Parenting of SpaceComponent
Suggested by @juztme87.
Make SpaceComponents have references to any parent / child components, like a Node. This would be useful for collision detection.
One question I have about implementation is how would it work in practice? Is the position relative to the parent, i.e if I have a parent positioned at (100, 100) and position the child at (100, 100) would the child appear on the screen at (200, 200)? Also, is there inheritance? Does the child by default have the same properties as the parent or does it default to zero?
This issue is related to #556
Some example use cases:
-
A Tank has a Turret. This Turret needs to be able to rotate independently but the position and rotation should be relative to the parent.
-
A Unit has a health bar. The health bar is located 10px above the Unit. The position should be relative to the parent but the rotation should be fixed. (The position of the child shouldn't be affected by the Rotation of the parent)
Maybe there are some other use cases that require inheritance.
@Noofbiz this is a fairly common paradigm in game engines and pretty much every major game engine has this concept. The way it works rather universally, is that child enities are transformed in relation to their parent entity. So as an example, if EntityA was at position 100, 100 and Entity B was a child of EntityB and had position 100, 100, it would actually be rendered at global position 200, 200. Generally, most systems expose two types of T/R/S, a local one (100, 100 in this example) and a global one (200, 200 in this example). This is important because sometimes, it's necessary to know the relative or local position, while other times it's important to know the global or world position, depending on what you are trying to do.
I agree, I'm only stuck on the implementation. We could either make space components themselves do this by unexporting Point and using Get/Set methods for position. This would allow us to do it all internally, but will change the API for space components quite a bit. Another solution would be to have a SpaceParentSystem or something that does it separately as its own system. This has the advantage of not needing to change the current API, but seems clunkier to me.
I'd prefer the former approach personally, but as you said it does break backwards compatibility.
That said, there are a couple other backwards incompatible changes id like to make too, so maybe after 1.1 is out, we can get together and start thinking about 2.0
I'm implementing the latter. I can share the code as a gist or a PR.
as you said it does break backwards compatibility
I personally don't think this is a gigantic issue for a clean implementation of a core feature.
A PR would be pretty great, and the changes shouldn't be too bad now with go modules. We can just make sure to release a version before so anyone who needs to can check out that one. And it'll definitely need be updated for version 2.0 anyway, and it is a pretty useful feature.
I've put up a PR here with my latest draft. The math is wrong and I am not seeing expected behavior for heirarchical transformations yet. Would love a second set of eyes on this, perhaps you can see what I'm missing?
https://github.com/EngoEngine/engo/pull/705
This gist shows how entities might be added to this TreeNodeSystem: https://gist.github.com/diwant/11b05a3908028ed60377ec6a3ae2c025
In this example, if I run code to increase the LocRot value of the starHandle, it doesn't orbit the moon. It orbits a much larger circle than that, which is not the expected behavior (I'd like the star to orbit the moon.
ecs.BasicEntity has a parent/child tree node now, and I've added a demo called parenting that shows how to do this for any component, not just space ^_^!
https://github.com/EngoEngine/engo/tree/c76f7316599b705e8a3655640db2c0cb4b71c1b2/demos/parenting
You know, I'm not certain that really solves the original problem - a tree node layout is only about the relationship during entity creation. At every other time it's about the derived values.
For @diwant's case, he'd still need to implement the derivation calculations for moving, rotating, and scaling SpaceComponents himself.
Yeah, I agree, I’ll reopen this. I think we should expand the demo to include working with space components. Do you think that covers it, or should something be added to common?
Perhaps reopen @diwant's PR? I didn't realise it remained closed.
Interestingly, I just stumbled upon a talk Mike Acton gave about ECS in Unity (which appears to be the direction in which they're moving), and he talks about this exact problem, giving a brief walkthrough the implementation:
https://youtu.be/p65Yt20pw0g?t=3087
Yeah, that's why I think updating the example is the best way to do it. It'll show users how to do it themselves, but like how every game is going to have a different control system for obvious reasons, every game is going to have different rules regarding what happens based on parent/child relationships. One may want it to orbit a parent instead of simply follow. Idk if there is a general purpose kinda system for that.
I think I need to watch like 30 hours of 3blue1brown videos 'cause I'm sure matrix operations are the general purpose magical answer to everything, and I'm twice as sure that I don't understand them at all.
In the case of an orbiting example, parenting doesn't make sense. Each step of the simulation, the GravitySystem would step through each celestial body and apply a force to them, then the PhysicsSystem would step through each celestial body and calculate the new position and momentum based on the force (off the top of my head and probably entirely incorrectly).
From what I understand, the way all scene graphs work is a transform to a parent happens to all its children. If I scale the tank body up by 2x, the turret is also scaled by 2x. If I rotate the turret by 90°, the barrel is also rotated by 90° (about the parent's point of rotation). If someone wanted to reimplement, let's say, Robotnik's egg forcefield things, the EggForcefieldThingSystem would step over each of them, and modify their position based on perhaps dt modulo something. Separately, the RobotnikAISystem would modify Robotnik's position based on whatever it needs to, and the ParentingSystem would somehow have to know about this, subsequently updating all children.
Difficulty probably comes in when scaling things, as if I scale something by 2x, and its child moves by a local 1, I'd expect it to move globally by 2. I think. It's been a while since I fired Unity up.
Just came back to this after following a few trips through other frameworks to see how it's done elsewhere.
As you mentioned above, I'm hoping for the parent child relationship to imply transformation from parent to child. A general purpose system might be something like this: https://webglfundamentals.org/webgl/lessons/webgl-scene-graph.html
I found something implemented on another game engine in Go, g3n (https://github.com/g3n/engine). They have a heirarchical scene graph implemented, which works like the scene graph described above.
(Now I'm moving from there to Magnum as I realized I need to communicate a lot with FFMPEG's libav which is in C++ and I'm not able to do all I need with it via goav, a go wrapper library on libav. So I'm off to C++ land.)
hth