Need some help in understanding scene graph matrix operations

Started by
14 comments, last by Basket 8 years, 1 month ago

Hello everyone, I am a newbie game developer smile.png

At the moment I am trying to understand matrix operations and how they can be applied for 3D drawing and for 3D gameplay tasks. Its tough so far as I am having trouble visualizing the kinds of things that are possible and with what sorts of matrix operations and in what order of matrix operations sad.png

Most of the tutorials I have found focus on drawing simple meshes to the screen and so describe the " model-view-projection " accumulation of matrices but not much beyond that. sad.png

The biggest problem area for me is figuring out in a intuitive and visual sense how to transform between coordinate spaces. sad.png

Some of the things I am trying to grasp and looking for answers are :

  • How do we transform a element expressed in a " local coordinate space " into " scene coordinate space " ?

Lets say we have a position or point " pointA " expressed in the " local coordinate space " of game object " A "

and we have assigned a position and rotation and scale expressed in " scene coordinate space " to this same game object " A ".

Basically this scenario is equivalent to transforming a arbitrary vertex of some mesh that has been assigned a position and rotation and scale expressed in " scene space " into " scene space. "

If I understand correctly, we need to translate the given position and rotation and scale expressed in " scene coordinate space " that we assigned to game object " A " into a transformation matrix and then we need to perform the following :

transformedPointAInSceneSpace = ( transformationMatrixOfGameObject"A" ) * ( Vector4( pointA , 1 ) )

We don't need to concern ourselves with the " view matrix " or the " projection matrix " ... just the " model matrix. "

Am I correct ?

  • How do we " combine " or accumulate the transformation matrices of objects in a parent - child relationship so that the position and rotation of the child object is expressed relative to the position and rotation of the parent object ?

Basically how do we accumulate or combine " coordinate spaces. "

Lets say we have a game object " A " with a transformation matrix and a game object " B " with a transformation matrix

and that game object " A " is the parent of game object " B "

If I understand correctly, we need to perform the following :

transformationMatrixOf"B"ExpressedRelativeTo"A" = ( transformationMatrixOfParent"A" ) * ( transformationMatrixOfChild"B" )

Is this correct ?

  • How do we maintain the current position and rotation of a game object expressed in " scene coordinate space " when assigning it as a child of another game object ?

Lets say that we have a game object " B " that is in a existing parent-child relationship with game object " A. "

such that game object " B " is a child of game object " A. "

Now lets say that we " re-parent " game object " B " to game object " C. "

But to complicate matters, lets say that we want to maintain or retain the current position and rotation and scale expressed in " scene coordinate space " of game object " B " with the previous parent game object " A " after we have " re-parented " game object " B " with its new parent, game object " C. "

How would we go about this ?

First I think that we need to accumulate the transformation matrix of child game object " B " with the transformation matrix parent game object " A " so as to compute a position and rotation expressed in " scene coordinate space " of game object " B "

transformationMatrixOf"B"ExpressedRelativeTo"A" = ( transformationMatrixOfParent"A" ) * ( transformationMatrixOfChild"B" )

Then we would need to transform this transformation matrix representing a position and rotation expressed in " scene coordinate space " into the " local coordinate space " of game object " C. "

Which leads to my next question biggrin.png

  • How do we transform a position or point expressed in " scene coordinate space " into a corresponding point or position expressed in the " local coordinate space " of a game object and vice versa ?

Lets say we have a position or point " pointA " expressed in the " scene coordinate space "

and that we have a game object " B " and that we have assigned a position and rotation and scale expressed in " scene coordinate space " to this same game object " B ".

If I understand correctly in order to transform a given position or point " pointA " expressed in " scene coordinate space " into a corresponding position or point expressed in the " local coordinate space " of game object " B " we need to first translate the position and rotation and scale expressed in " scene coordinate space " that we assigned to game object " B " into a transformation matrix then we need to " invert " this same transformation matrix and then multiply it with the position or point " pointA. "

transformedPointAInLocalSpaceOfGameObject"B" = ( Math.Invert( transformationMatrixOfGameObject"B" ) ) * ( Vector4( pointA , 1 ) )

Now how to do the opposite ? biggrin.png

Lets say we have our newly transformed point or position " pointA " expressed in the " local coordinate space " of game object " B. "

Now how to we transform this point or position " pointA " into " scene coordinate space " ?

I think we can simply do the standard :

transformedPointAInSceneSpace = ( transformationMatrixOfGameObject"B" ) * ( Vector4( pointA , 1 ) )

What about " inverting " the " inverse " of the transformation matrix of game object " B " and multiplying this with point or position " pointA " ?

transformedPointAInSceneSpace = ( Math.Invert( Math.Invert( transformationMatrixOfGameObject"B" ) ) ) * ( Vector4( pointA , 1 ) )

Is this possible to ? Which is the better approach ?

  • How do we transform a position or point expressed in one " local coordinate space " into another " local coordinate space " ?

This sort of a weird question but it follows from talking about " local coordinate spaces " and " scene coordinate spaces " and translating between them biggrin.png

I think since we have two " local coordinate spaces " we effectively have a single " local coordinate space " and so any points or positions are in and operations are performed in effectively same single " local coordinate space " implicitly.

So no " transformation " step is required. biggrin.png

Looking at the above questions, they are pretty basic ... but I am really new at 3D transformation stuff sad.png

But I think that they pretty much cover the basic matrix math stuff that I am having difficulty with.

For more complex stuff could anyone please point me to a real good matrix math tutorial that moves beyond the simple math operations and describes actual and " common " gameplay and drawing usage scenarios ... and does so in basic and newbie friendly way for people that have difficulties with math ?

Or instead could someone please walk-through some common examples in simple language and simple maths how I can I do those " common " gameplay and drawing related things, like those described above, with a " standard " math library like JOML ( for Java ) or GML.

Thank-you biggrin.png

Advertisement

it might be more apparent to think of these in terms of just positioning (replacing matrices with 3D translation vectors for the sake of making a point)

How do we transform a element expressed in a " local coordinate space " into " scene coordinate space " ?

if you have an object offset (.3, .4, .2) from the camera's origin, its translation vector will be (.3, .4, .2). This is its position in "screen coordinate space".

How do we " combine " or accumulate the transformation matrices of objects in a parent - child relationship so that the position and rotation of the child object is expressed relative to the position and rotation of the parent object ?

If you want to express the child's offset from the parent, you don't need to combine or accumulate the translation vector. If a child is offset (.3, .4, .2) from its parent's origin, you would set its translation vector to (.3, .4, .2). This is its position in "parent coordinate space".

How do we maintain the current position and rotation of a game object expressed in " scene coordinate space " when assigning it as a child of another game object ?

You wouldn't "maintain" the child's position in scene coordinate space, but you can calculate the child's position in scene coordinate space by combining the child's translation vector with the parent's translation vector, IE scs_vector = parent.vector + child.vector
This allows you to form an hierarchy of offsets, IE: scs_vector = parent.get_scs_vector() + child.vector
In the case of matrices, it allows you to form an hierarchy of offsets AND rotations.

How do we transform a position or point expressed in " scene coordinate space " into a corresponding point or position expressed in the " local coordinate space " of a game object and vice versa ?

To get a point in scene space into object space, you would reverse the object transformation
ocs_point = point - object.vector;
ocs_point = point * inv(object.matrix);

How do we transform a position or point expressed in one " local coordinate space " into another " local coordinate space "

The simplest way is to translate it into scene space, and then translate it into the other local coordinate space. But if they're in the same coordinate space hierarchy (IE have a common "ancestor" object), you can save a few matrix multiplications by only translating back down to the ancestor's coordinate space, then to the other object's coordinate space.


I think since we have two " local coordinate spaces " we effectively have a single " local coordinate space " and so any points or positions are in and operations are performed in effectively same single " local coordinate space " implicitly.

So no " transformation " step is required. biggrin.png


Is wrong thinking. One object's coordinate space is not another object's coordinate space.


How do we transform a element expressed in a " local coordinate space " into " scene coordinate space " ?

apply the world transform matrix


We don't need to concern ourselves with the " view matrix " or the " projection matrix " ... just the " model matrix. " Am I correct ?

yes


How do we " combine " or accumulate the transformation matrices of objects in a parent - child relationship so that the position and rotation of the child object is expressed relative to the position and rotation of the parent object ?

start with the object in model space, location 0,0,0, rotation 0,0,0. apply the object's scale and rotation, and any translation with respect to the attachment point on the parent object. then for each parent, grandparent, etc, apply their transforms to the object. the result is the final position and orientation of the object in world space.


How do we maintain the current position and rotation of a game object expressed in " scene coordinate space " when assigning it as a child of another game object ?

subtract the parent's attachment point location from the child's location to get the translation of the chiid object with respect to the parent's attachment point. subtract the parent's rotation from the child's rotation to get the rotation of the child relative to the parent.


How do we transform a position or point expressed in " scene coordinate space " into a corresponding point or position expressed in the " local coordinate space " of a game object and vice versa ?

un-rotate in reverse order, then un-translate. if your rotation order is xr,yr,zr, un-rotate by -zr, then -yr, then -xr..


What about " inverting " the " inverse " of the transformation matrix of game object " B " and multiplying this with point or position " pointA " ?

i heard somewhere that inverting a matrix can have rounding error issues. so i use other ways to do things.


How do we transform a position or point expressed in one " local coordinate space " into another " local coordinate space " ?

using the methods described by nfries88. you convert from current local space to world space, then from world space to new local space. or you convert from current local space to some other common frame of reference, and then to the new local space.


For more complex stuff could anyone please point me to a real good matrix math tutorial that moves beyond the simple math operations and describes actual and " common " gameplay and drawing usage scenarios ... and does so in basic and newbie friendly way for people that have difficulties with math ?

once you have those basics down, about all else you'll need is D3DXvect3Transform (transform point by matrix). if you get into flight sims, you'll need local rotations using the axis-angle formula, forward, up, and right vectors, and re-ortho-normalization of the forward, up and right vectors after applying a discrete rotation.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Thank-you so much nfries88 for helping me biggrin.png

if you have an object offset (.3, .4, .2) from the camera's origin, its translation vector will be (.3, .4, .2). This is its position in "screen coordinate space".

Hmm this is a bit confusing to me sad.png ... I think what your saying is that if I have an object with a position and rotation expressed in the same coordinate space as the position and rotation of the camera then we effectively have expressed the position and rotation of the object in " scene space. " Is this right ?

In my case, I am trying to understand how to transform a point or position from local space into scene or global space so that I can do things like " pre-transform " vertices in editor tools and such.

So in these special cases, there is no actual " camera " but the idea is that we have a parent coordinate space ... which would implicitly be the coordinate space in which the position and rotation of the camera is expressed in.

If you want to express the child's offset from the parent, you don't need to combine or accumulate the translation vector. If a child is offset (.3, .4, .2) from its parent's origin, you would set its translation vector to (.3, .4, .2). This is its position in "parent coordinate space".

Ahh I understand what your saying biggrin.png

What I was considering was how to transform a game object with a position and rotation expressed in the coordinate space of a parent game object into a " scene space. " I I understand correctly for that you would need to accumulate the transformation matrices ?

But as you said if you want to express a position and rotation relative to a parent coordinate space you just need to specify it within the parent coordinate space. smile.png

You wouldn't "maintain" the child's position in scene coordinate space, but you can calculate the child's position in scene coordinate space by combining the child's translation vector with the parent's translation vector, IE scs_vector = parent.vector + child.vector
This allows you to form an hierarchy of offsets, IE: scs_vector = parent.get_scs_vector() + child.vector
In the case of matrices, it allows you to form an hierarchy of offsets AND rotations.

This is exactly what I wanted to know about that whole " how do I accumulate transformation matrices in a parent-child relationship." Thank-you biggrin.png

I think I may have poorly worded the question though sad.png

What I was considering was in special cases where I have a child object of some parent object that is nicely positioned and rotated relative to its current parent.

When we transform the position and rotation of this child object specified relative to its current parent object we get a final position and rotation expressed in scene space that is pretty nice for some purpose. All is well biggrin.png

But then lets say we re-parent this same child object to some other parent object.

Suddenly the position and rotation of this child object is expressed relative to the parent coordinate space of a different parent object.

So suddenly the final position and rotation of this child object expressed in scene space is very different from the " previous " or " original " position and rotation of this child object expressed in scene space.

In many cases we actually want to change parent objects but retain the same scene space position and rotation of the child object.

So effectively we need to position and rotate the child object relative to a arbitrary parent object in such a way as to be at the same scene space position and rotation even if we switch parent objects.

To get a point in scene space into object space, you would reverse the object transformation
ocs_point = point - object.vector;
ocs_point = point * inv(object.matrix);

Very clear biggrin.png

The simplest way is to translate it into scene space, and then translate it into the other local coordinate space. But if they're in the same coordinate space hierarchy (IE have a common "ancestor" object), you can save a few matrix multiplications by only translating back down to the ancestor's coordinate space, then to the other object's coordinate space.

Very cool that is a great trick biggrin.png

Is wrong thinking. One object's coordinate space is not another object's coordinate space.

I understand what your saying. I was implicitly assuming that we have two objects without a position or rotation relative to a parent coordinate space.

For example , two meshes. Provided that both meshes have vertices expressed relative to the same local origin, then for purposes of combining these vertices into a single mesh, we can consider that both meshes are effectively expressed in the same coordinate space and so we can simply " merge " the meshes.

Now this simplification does not work if we assign a transformation matrix to either mesh. But if we have, for example , a scene editor tool and describe geometry in two meshes that share the same common local origin then effectively they are the same " composite " mesh just described in two different sub-meshes.

Or at least that's what I think tongue.png


I understand what your saying. I was implicitly assuming that we have two objects without a position or rotation relative to a parent coordinate space.

For example , two meshes. Provided that both meshes have vertices expressed relative to the same local origin, then for purposes of combining these vertices into a single mesh, we can consider that both meshes are effectively expressed in the same coordinate space and so we can simply " merge " the meshes.



Then you could optimize for this rare case by not applying translation. But if these meshes are not even offset differently in parent space, then this must mean they overlap, which is messy.

Thank-you Norman for helping me as well, your explanations helped to clear up some of the things that nfries88 described biggrin.png

start with the object in model space, location 0,0,0, rotation 0,0,0. apply the object's scale and rotation, and any translation with respect to the attachment point on the parent object. then for each parent, grandparent, etc, apply their transforms to the object. the result is the final position and orientation of the object in world space.

Perfectly clear biggrin.png

subtract the parent's attachment point location from the child's location to get the translation of the child object with respect to the parent's attachment point. subtract the parent's rotation from the child's rotation to get the rotation of the child relative to the parent.

I don't understand this sad.png

If I have a scene graph comprised of a child object and a parent object, then the child object is positioned and rotated relative to its parent object and thus in the coordinate space of its parent object. Soooo why would we need to " subtract the parent's attachment point location [ ... do you mean local origin ? ... ] from the child's location " to get the child object's position and rotation relative to it's parent object... since we implicitly have it ?

Could you please walk me though a simple math example, lets say assuming only translations so to simplify things ?

un-rotate in reverse order, then un-translate. if your rotation order is xr,yr,zr, un-rotate by -zr, then -yr, then -xr..

Ok I think what your doing is computing the " transpose " of the rotation matrix as it is equivalent to the inverse of the rotation matrix ... or is this some of those other tricks that you mentioned tongue.png ?

i heard somewhere that inverting a matrix can have rounding error issues. so i use other ways to do things.

I think that as long as I have a relatively " shallow " hierarchy and keep points or positions within sensible range limits then it should be alright smile.png

using the methods described by nfries88. you convert from current local space to world space, then from world space to new local space. or you convert from current local space to some other common frame of reference, and then to the new local space.

When you say " some other common frame of reference " do you mean some parent coordinate space that is shared , common to the two or more child objects ?

once you have those basics down, about all else you'll need is D3DXvect3Transform (transform point by matrix). if you get into flight sims, you'll need local rotations using the axis-angle formula, forward, up, and right vectors, and re-ortho-normalization of the forward, up and right vectors after applying a discrete rotation.

I take it that ' D3DXVect3Transform " is basically a means to apply a transformation matrix ( i.e. " model matrix " or " world matrix " ) to an arbitrary point or position ? So whats the difference between manually computing a transformation matrix and multiplying it against a point or position ?

I am not working on a flight sim, but I think I will have to learn abit of those local orientation operations. Joy wacko.png


How do we maintain the current position and rotation of a game object expressed in " scene coordinate space " when assigning it as a child of another game object ?

subtract the parent's attachment point location from the child's location to get the translation of the chiid object with respect to the parent's attachment point. subtract the parent's rotation from the child's rotation to get the rotation of the child relative to the parent.

this is the answer to "how to change parent without changing final world position"

there will be an "attachment point" on a parent, this is where the child's appears with no translation or rotation with respect to the parent. it may be the origin of the parent, or some other point with respect to the parents origin, such as the end of a bone, the bow of a ship for a turret, etc.

when the child is transformed into its final position in world space, you then subrtact its location form the new parent's location to get the offset to the new parent's attachment point. you then subtract its orientation from the new parent's orientation to get the orientation relative to the new parent. you can then switch to the new parent, using the new off set and orientation to draw and the object will be in the same place and orientation in world space as it was with the old parent. a football being handed off comes to mind. the football is the child. when the handoff occurs, and the parent of the football changes from the first to the second player's hand bone, the football will not move.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


Ok I think what your doing is computing the " transpose " of the rotation matrix as it is equivalent to the inverse of the rotation matrix ... or is this some of those other tricks that you mentioned ?

to un-transform from world to object space, you apply the transforms in reverse order. so if your normal order is scale, rotx, roty, rotz, translate, to un-transform, you -rotz, then

-roty, then -rotx, then un-translate, then un-scale.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


I think that as long as I have a relatively " shallow " hierarchy and keep points or positions within sensible range limits then it should be alright

to each his own. there are other lossless methods available though.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


When you say " some other common frame of reference " do you mean some parent coordinate space that is shared , common to the two or more child objects ?

yes

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement