Jittering when rotating and then translating a matrix

I’m having a problem where I am storing the position/rotation/scale in a matrix for easier manipulation of these values with parenting. It all seems to be going well, except for when I rotate the matrix, which is when the object seems to jitter around and shake. Here is the relevant code:

    // This runs for every object that doesn't have a parent, as the parent will execute
    // Draw() for its children once it is done
    internal void Draw()
    {
        float RadRot = MathHelper.ToRadians(Rotation);

        // Sets world matrix for things that draw
        if (Parent != null) {
            WorldMatrix = Matrix.CreateScale(RelativeSize.X * Parent.Size.X, RelativeSize.Y * Parent.Size.Y, 1) * -Matrix.CreateTranslation(Pivot.X, Pivot.Y, 0) * Matrix.CreateRotationZ(RadRot);
            WorldMatrix.Translation = Vector3.Zero; // Rotating seems to create a strange positioning issue, this fixes it
            WorldMatrix *= Matrix.CreateTranslation(RelativePosition.X * (Size / StartSize).X, RelativePosition.Y * (Size / StartSize).Y, 0) * Matrix.CreateRotationZ(Parent.DecomposedRotation) * Matrix.CreateTranslation(Parent.DecomposedPosition.X, Parent.DecomposedPosition.Y, 0);
        } else
        {
            WorldMatrix = Matrix.CreateScale(RelativeSize.X, RelativeSize.Y, 1) * -Matrix.CreateTranslation(Pivot.X, Pivot.Y, 0) * Matrix.CreateRotationZ(RadRot);
            WorldMatrix.Translation = Vector3.Zero; // Adjusting the pivot seems to create a strange positioning issue, this fixes it
            WorldMatrix *= Matrix.CreateTranslation(RelativePosition.X, RelativePosition.Y, 0);
        }

        Vector3 TempPos = Vector3.Zero;
        Quaternion TempRot = Quaternion.Identity;
        Vector3 TempSize = Vector3.Zero;
        WorldMatrix.Decompose(out TempSize, out TempRot, out TempPos);

        DecomposedPosition = new Vector2(-TempPos.X, -TempPos.Y);
        DecomposedRotation = RadRot;
        DecomposedSize = new Vector2(MathF.Round(TempSize.X), MathF.Round(TempSize.Y));

        SetRefs();

        foreach (Component2D comp in Components)
        {
            comp.Draw();
        }

        foreach (Object2D child in Children)
        {
            // Now draws the children
            child.Draw();
        }
    }

This is what comp.Draw calls:

MyGame.SpriteDrawing.Draw(Image, new Rectangle(LinkedObject.DecomposedPosition.ToPoint(), LinkedObject.DecomposedSize.ToPoint()), RenderRegion, Color, LinkedObject.DecomposedRotation, LinkedObject.Pivot, SpriteEffects.None, LinkedObject.Layer + (SubLayer / 10000));

Here is what it looks like in action:

And here’s another example

EXTRA NOTE: This jittering occurs no matter the scale of the objects

Looks like precision problems caused by too complicated math. Especially the decomposition of the parent rotation seems dangerous. In the bottom video you can see 4 “quadrant lines”. Unless that’s something else, the cube is flipping between different angles, offset by 90 degrees.

Usually you build a child matrix by simply multiplying the parent matrix with the relative child matrix. In the case of the chain from the top video, the relative child matrix would be a simple translation matrix, because the child cubes are rotated and scaled the same way as the parents.

If you need more info just search for something like: 3d matrix math for parent child hierarchy.

Thank you for your response,
In the code the rotation is not being decomposed, rather the value is being copied from its parent plus the rotation for the child (as I couldn’t be bothered to write the code to convert from a Quaternion to Vector3). Another thing (though, this probably won’t make a difference) is that everything is being rendered as a 2D image using a spritebatch rather than a 3D cube, I’m just using matrices to make the math somewhat easier on myself.

I’ve been looking for the right solution to this using multiple different ways of a parent-child hierarchy, but everything seems to either end in this, or the objects getting sent into oblivion.

From a glance your code looks on the right lines of a scene graph to me. They can be a fiddle to get “right” though. A good place to start is probably to look at the order of your matrix operations.

This is all from memory so feel free to tell me im totally wrong, but I think the way I remember is TRS. So translate, rotate, scale. But due to the non noncommutative nature of matrix ops, I think its done backwards.

So it would be something like, localMatrix = S * R * T
Then, worldMatrix = parentMatrix * localMatrix

I’ve found this a good resource in the past, even though its in WebGL the technique is the same and you get some web demos to play around with.

This is their code for updating matrices -

   Node.prototype.updateWorldMatrix = function(parentWorldMatrix) {
 if (parentWorldMatrix) {
   // a matrix was passed in so do the math
   m4.multiply(parentWorldMatrix, this.localMatrix, this.worldMatrix);
 } else {
   // no matrix was passed in so just copy local to world
   m4.copy(this.localMatrix, this.worldMatrix);
 }

 // now process all the children
 var worldMatrix = this.worldMatrix;
 this.children.forEach(function(child) {
   child.updateWorldMatrix(worldMatrix);
 });

};

Oh ok, I flew over your code too quickly, didn’t realize the decomposed rotation isn’t being used. I also didn’t realize that it’s actually 2D, and you’re using SpriteBatch for drawing.

You are converting floating point to integer here:

LinkedObject.DecomposedPosition.ToPoint()

I guess that’s your problem, at least part of it. You loose precision by rounding to integer. Use one of the draw methods where you can pass a floating point position.

Oh my goodness, thank you!
I actually can’t believe that I missed that. I didn’t even think that spritebatch has a Vector2 option rather than a Rect… But that fixed it. Thank you for your guys’ help!