Here is what I have: a custom DrawableGameComponent
, containing children in which I call some DrawUserPrimitve
. Each of the child can contain children etc.
I store in each component a list of the vertices describing its shape, and a Matrix
to store its relative position (and eventually transformation).
So before I "DrawUserPrimitive
", I need to "apply" a matrix. This matrix must be the multiplication of the component's transformations and of its parent and its parent's parents etc.
This system allow me to keep the component's variable independant and if I understood correctly, that's the way to go.
To do so I saw the BasicEffect
object in XNA, with which I can apply some matrices. So I am trying to multiply the basicEffect.World
with my component.Transformation
(Matrix
)
So I should continue to inquire but for now it does not give me the results I was waiting for. I wonder if I chose the good way to do this. I see 2 systems for the same results:
Some code for illustration's sake:
public void override Draw(GameTime gameTime){
Game.basicEffect.World *= Transformation;
foreach(var child in this.Children){
child.Draw(gameTime);
}
Game.basicEffect.World *= Matrix.Invert(Transformation);
}
Thanks to @nico-schertler 's comment I was able to make it.
Having a Matrix stack storing the current state of your "pencil" is the solution. But there was something I was missing:
Each time you go deeper in the object hierarchy (ex: the arm of a robot) you multiply the new Matrix by the current one and put the resulting one on the stack. Therefore the stack always have (on top of itself) the Matrix which must be used to draw. When you are done with this object and go back to its parent, just pop once and you retrieve the Matrix to use for it. (I was stacking each Matrix and then everytime recalculating the resulting Matrix to use.)
Remark: be careful to the order you multiplications. Matrices' multiplication are not commutative! Always multiply your child matrix by the current one.
internal void HandleDraw(GameTime gameTime)
{
Draw(gameTime);
if (Children.Count > 0)
{
// draw children
foreach (Control child in Children.Values.OfType<Control>())
{
if (child.Visible)
{
Engine.CurrentTransformation.Push(Matrix.Multiply(
child.Transformation,
Engine.CurrentTransformation.Peek()
));
child.HandleDraw(gameTime);
Engine.CurrentTransformation.Pop();
}
}
}
}