Norris's picture

Get entity absolute transformation in nested hierarchy

I have scene graph system with nodes that have "position" and "rotation" vectors. Each node can have one or more linked entities that have also "position" and "rotation" vectors.
All those vectors are RELATIVE position and rotation to the parent node. When drawing my hierarchy, I simply use the OpenGL matrix stack and add transformations to the current ModelView matrix.
But I want to improve my system so that a camera can be a linked entity. So, it can be nested deeply in the nodes hierarchy.

The problem is I need the ABSOLUTE transformation of my camera to be able to "move" my world before drawing the scene ... and I only store RELATIVE transformation.
I know that to get the absolute transformation, I must start from my nested entity, add transformations and go back to the root. Then I must invert the result matrix. But I'm not really sure of how to implement it.
This is my first attempt:

In my Entity class:

Public Function GetAbsoluteTransformation() As Matrix4
    'Create an matrix to accumulate transformations
    Dim accuMat As Matrix4 = New Matrix4
    accuMat = Matrix4.Identity
    'normal order (drawing) is translate and rotate X,Y and Z. Do I need to do the the inverse ?
    Dim rotMatX As Matrix4 = Matrix4.CreateRotationX(-DegreesToRadians(_RotX))
    Dim rotMatY As Matrix4 = Matrix4.CreateRotationY(-DegreesToRadians(_RotY))
    Dim rotMatZ As Matrix4 = Matrix4.CreateRotationZ(-DegreesToRadians(_RotZ))
    Dim transMat As Matrix4 = Matrix4.CreateTranslation(Position)
    Dim tmpMat As Matrix4 = rotMatZ * rotMatY * rotMatX * transMat
    Matrix4.Mult(accuMat, tmpMat, accuMat)
    GetAbsTransRecurs(ParentLinkedNode, accuMat)
    Return accuMat
End Function
Public Sub GetAbsTransRecurs(ByVal parentNode As SceneNode, ByRef accuMat As Matrix4)
    If parentNode IsNot Nothing Then
        Dim rotMatZ_p As Matrix4 = Matrix4.CreateRotationZ(-DegreesToRadians(parentNode.Rotation.Z))
        Dim rotMatY_p As Matrix4 = Matrix4.CreateRotationY(-DegreesToRadians(parentNode.Rotation.Y))
        Dim rotMatX_p As Matrix4 = Matrix4.CreateRotationX(-DegreesToRadians(parentNode.Rotation.X))
        Dim transMat_p As Matrix4 = Matrix4.CreateTranslation(parentNode.Position)
        Dim tmpMat_p As Matrix4 = rotMatZ_p * rotMatY_p * rotMatX_p * transMat_p
        Matrix4.Mult(accuMat, tmpMat_p, accuMat)
        If parentNode.ParentNode IsNot Nothing Then
            GetAbsTransRecurs(parentNode.ParentNode, accuMat)
        End If
    End If
End Sub

Are my maths good (I'm really bad at maths) ?
I just start to test this, and it seems that I must invert rotations angles. strange results but I think I'm on the right way.