Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Rottbott

Turn in global space

This topic is 5283 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I''ve been struggling with this problem for a few days now. I''ve read just about every post on these boards to try and find the answer myself, and it''s just given me an even bigger headache. I have set up an Entity class, from which classes like Camera, Light, Mesh, etc. can inherit. The Entity class arranges entities in a tree - with a Global entity being the root. Each entity has 6 floats (position and scale), and a Microsoft.DirectX.Quaternion for rotation. They also have a Microsoft.DirectX.Matrix which holds the complete global transformation for that entity (the floats and Quaternion are for the local position/rotation/scale). Now my Entity.Position(), Entity.Rotate(), and Entity.Scale() methods all work perfectly, which is nice. The problem occurs when I come to do Entity.Turn() and Entity.Move(). Entity.Turn() looks like this: public void Turn(float pitch, float yaw, float roll, bool Global) When Global is false, it works fine. However, I can''t work out hhow to do a turn (delta rotation) in global space. I *think* I need to calculate the current global pitch/yaw/roll, and add it to the delta pitch/yaw/roll, to get my final overall rotation (which can then be given to the working Entity.Rotate() method). However, I can''t seem to find out a way to get the global pitch/yaw/roll back from the transformation matrix. Is there another way to do this? Ideas?

Share this post


Link to post
Share on other sites
Advertisement
quote:
Original post by Rottbott
However, I can''t seem to find out a way to get the global pitch/yaw/roll back from the transformation matrix. Is there another way to do this?


Why not just store it as its own information when you plug it into the matrix, instead of trying to retrieve it back out again?



Red Sodium

Share this post


Link to post
Share on other sites
That was quick!

I can't quite work out what you mean. The values I put into the matrix are local - the global matrix is worked out by multiplying with the parent's matrix.

To illustrate, here's my Entity.RebuildMatrix() and Entity.Position() methods:


// RebuildMatrix - turns the position, rotation and scale into a new matrix

void RebuildMatrix()
{
// Parent matrix (just identity if parent is Global)

this.Transform = this.Parent.Transform;
// Scale

this.Transform = this.Transform * Matrix.Scaling(this.LocalScaleX, this.LocalScaleY, this.LocalScaleZ);
// Translate

this.Transform = this.Transform * Matrix.Translation(this.LocalX, this.LocalY, this.LocalZ);
// Rotate

this.Transform = this.Transform * Matrix.RotationQuaternion(this.LocalRotation);
}


// Position - sets to an absolute position in local or global space

public void Position(float x, float y, float z, bool Global)
{
this.LocalX = x;
this.LocalY = y;
this.LocalZ = z;
if (Global == true)
{
this.LocalX = this.LocalX - this.Parent.LocalX;
this.LocalY = this.LocalY - this.Parent.LocalY;
this.LocalZ = this.LocalZ - this.Parent.LocalZ;
}
this.RebuildMatrix();
}


EDIT: Formatting.

[edited by - Rottbott on May 29, 2004 4:57:41 AM]

Share this post


Link to post
Share on other sites
Sorry, I assumed that you wanted to extract data from the matrix, when in actual fact it would just be easier storing the data seperate from the matrix.

What I meant, in the context of your problem, is that you should just set up a Get...() function to retrieve the global position from the parent, which is stored as a variable. Not sure if i''ve understood your problem though :/

Red Sodium

Share this post


Link to post
Share on other sites
I suppose what I really need is:

1. A way to extract the rotation (in Euler angles) and position from any entity''s matrix, and

2. A way to transform a point between an entity''s local space, to global space, and back again.


Or a whole new set of transformation methods

Share this post


Link to post
Share on other sites
quote:

I suppose what I really need is:

1. A way to extract the rotation (in Euler angles) and position from any entity''s matrix,
and

2. A way to transform a point between an entity''s local space, to global space, and back
again.


Or a whole new set of transformation methods



Lets take the general case. If a have a tree of nodes
with transformation at each level, then the following is
true:

if at each Level i, the transformation is represented by
the matrix Li, then the total transformation is:

T = L0*L1*L2*...Ln

where n is the number of levels in the tree. If at any point
in the tree you wish to apply a transform, you simply take
that Li and multiply it by the transformation matrix. This
goes for ALL "delta" transformations. This type of idea
basically represents a heirarchy of objects attached to each
other and effected by the transformation of the node higher
up in the tree.

Now, instead of matrices, you could probably use your quaternions
(as long as proper care is taken to deal with translations/scaling).

one more thing that might be useful (and this is probably mostly
opinion), it is probably a good idea to implement rotations as
an angle around a user''s chosen axis rather than 3 angles around 3 fixed axis. It deals with some of the problems that are caused by Euler angles (gimble lock).

As for extracting rotation angles, unless you have a need to know
these rotations, you probably should not do this (it will slow things down). It is absolutely unnecessary for purposes of transformation. Hope I was helpful.

SporadicFire

Share this post


Link to post
Share on other sites
SporadicFire,

That all makes sense, thanks. It''s starting to come together in my mind. I probably will use an axis-angle for rotation, rather than Euler angles, or perhaps even use the quaternions directly.

However, I still have to work out the transformation. I think my RebuildMatrices() method is applying transformations in the wrong order. At the moment, it does this:

Parent
Scale
Translate
Rotate

I think it should probably be doing this:

Parent
Scale
Rotate
Translate

But that gives me another problem. If I rotate my entity, and rebuild the matrix, the position will also change due to the new rotation, I think.


Here''s a question:

If I have a rotation matrix which turns my entity 90 degrees right, and I multiply it by a translation matrix which moves my entity 5 units forwards on the Z-axis, which will happen?

A) The entity is rotated 90 degrees right, and moves 5 units along the global X-axis (which the local Z-axis is now aligned with due to the rotation).

B) The entity is rotated 90 degrees right, and moves 5 units along the global Z-axis.

Share this post


Link to post
Share on other sites
Ok, ideally, you want to think of a matrix at one level as a coordinate system. So, it consists of a position, orientation and scaling... Let S be scaling, T be translation and R be rotation. IMHO, you rotate first, then translate and
then scale. (This is to make sure that translation does not
screw up rotation and that scaling does not screw up translation).

So, in matrix notation, total transform M = S*T*R
(when concatenating transforms, always multiply to the left).

if you write out the matrices in 2D it will answer your question.
But, it is clear that the above rotates first, and then translates according to the global coordinate system.

As for M = T*R*S, which is what i think what you are proposing
to do, it is not possible to get a proper nonuniform scaling if
scaling is done first and rotation second. Hope it helps.

if you want to check in the future, use following homogenous
2D matrices

R = cos(theta) -sin(theta) 0
sin(theta) cos(theta) 0
0 0 1
T = 1 0 tx
0 1 ty
0 0 1

and S =Sx 0 0
0 Sy 0
0 0 1

just matrix multiply them by hand and see what happens.

SporadicFire.

[edited by - SporadicFire on May 28, 2004 1:28:01 PM]

Share this post


Link to post
Share on other sites
I suggest using

M=P*T*R*S or M=P*T*S*R, they are the same.

P is the parent''s transformation.

I think this is the best way if you use the scaling for making an object bigger and not for increasing distances between objects (I guess this is nonuniform scaling).

Share this post


Link to post
Share on other sites
Sorry, my mistake, szinkopa right,
except, i''d use M=P*T*S*R. because T*R*S wont give
proper non uniform scaling when you use a rotation matrix.

SporadicFire

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!