Turn in global space

Started by
13 comments, last by Rottbott 19 years, 10 months ago
OK, thanks to the help from you two I've managed to simplify it a lot.

I've scrapped the local quaternion and 6 floats, and I'm now using only the matrix. I don't really need to know the global Euler angles, and I can easily get the global position of any entity from its matrix (M41, M42, M43).

I think I've got the following working:

Rotate()
Position()
Translate()
Move()

I also have Turn() working, but only with global angles. Turning in local space is trickier. It should work the same as Translate(), but that uses something I can't do with angles.

Also I've left scale alone for now to keep things simple I've also not done the code to update the children when a parent is altered but that shouldn't be too hard.

Here's the source for the local co-ordinates Translate() method (x/y/z describe the translation vector):

// Turn global position into local spacethis.Parent.PointToLocal(this.Transform.M41, this.Transform.M42, this.Transform.M43);// Add translation to itx = this.Parent.PointX - x;y = this.Parent.PointY - y;z = this.Parent.PointZ - z;// Set new positionMatrix M = this.Parent.Transform;M = Matrix.Translation(x, y, z) * M;this.Position(M.M41, M.M42, M.M43, true);


PointToLocal() simply runs a point through the matrix like this:

public void PointToLocal(float x, float y, float z){	Matrix M = this.Transform;	M.Invert();	PointX = (M.M11 * x) + (M.M21 * y) + (M.M31 * z) + M.M41;	PointY = (M.M12 * x) + (M.M22 * y) + (M.M32 * z) + M.M42;	PointZ = (M.M13 * x) + (M.M23 * y) + (M.M33 * z) + M.M43;}


So - can anyone tell me if it's possible to write a QuaternionToLocal() method to run a rotation through the matrix in the same way as a point? That would enable me to finish my Turn() method.

Thanks for all the help so far!

EDIT: Tidied code.

EDIT AGAIN: I got Turn() working in local space by simply reversing the order of the matrix multiplication! However, my global Turn() doesn't seem to work quite right still.

[edited by - Rottbott on May 28, 2004 5:28:48 PM]
Advertisement
Let's see:

M is your entity's matrix now.
GlobalRot is your global rotation matrix
So after rotating you would get the following matrix:

GlobalRot * M

This should be equal to another expression, in which you apply an unknown local rotation matrix:

M*LocalRot

So

GlobalRot * M == M * LocalRot is true, from this

LocalRot = M^(-1) * GlobalRot * M

This will be the local rotation matrix, I think.

Try it, hope it's a good idea.


[edited by - szinkopa on May 28, 2004 5:48:19 PM]

Lets say,
M = TR, where R is the linear component (that means rotations/
scaling and sheering. T is translational component. When you
look at matrix elements of M you see that:

M = M11 M12 M13 Tx
M21 M22 M23 Ty
M31 M32 M33 Tz
0 0 0 1

If you need to do an absolute transform at any level, just
separate the two components of the matrix and rewrite it.
So, if you want it to translate to someplace else, just
change Tx,Ty,Tz...if you want to rotate in a different
way, just replace the top 3x3 with a new rotation matrix.
If you have to do a "turn" or "move" instead, then just
left multiply the change in transformation to existing matrix.


Now, inverse matrices will allow you to untransfrom things from global
down to local without worrying about what an angle was. Just
multiply the inverse matrices of the higher levels on the left
and they will bring it back down to a lower level.

Well, one more things, you probably want to store your coordinates in their untransformed states. This means
that Local takes them to the locally transformed coordinate
system and global * local takes them to the global coordinate
system. This removes the need to always have to transform
things back from global before doing local transformations.

Also, only transform coordinates on demand. Meaning, store
the matrices, modify them as much as you want, and then compute
for a concatenated transformation of points or a set of points
when you need it. This will take more advantage of the matrices than if you transformed each time your matrix changed.

As for transforming quaternion through a matrix, its done by converting the quaternion to a matrix and then multiply
it through. There's a formula for that somewhere. It would
help in writing a turn method that uses a quaternion. But, be
sure to multiply it to the left.

hope this helps,

SporadicFire.

EDIT: typo


[edited by - SporadicFire on May 28, 2004 9:42:06 PM]
szinkopa,
That makes sense. How do I do M^(-1)? Is it just M.Invert()?

SporadicFire,
I've taken your advice and included the local transformation components again.

However I'm still having trouble with Turn(). I want to turn on the global axes... but how do I work out the new *local* quaternion which will result in a given global rotation? To do that with translation is easy - I use my PointToLocal() method - but I can't seem to get a working RotationToLocal() method, even with szinkopa's equation above.


EDIT: A global Turn() now semi-works. However, if I turn an entity slowly to the right, it works up until about 270', and then goes crazy. Weird.

[edited by - Rottbott on May 29, 2004 1:26:54 PM]
yes, M^(-1) is its invert.

Ah, i think i see what you mean now...
but correct me if i am wrong

T = G * L is the total transformation G is global, L is local.
Now, to achieve a rotation in the total transform:

RT = R*G*L

but, you want this represented locally,

RT = G*S*L

R*G*L = G*S*L
inverse(G)*R*G*L*inverse(L) = S
S = inverse(G)*R*G

and S is the transformation that you have to apply at local level
to get RT = R*G*L to be the new total transformation.

Ofcourse, this will work for any general transform, not just
rotations.

SporadicFire.

This topic is closed to new replies.

Advertisement