   Turn in global space
  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? 
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;  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 matrixvoid RebuildMatrix(){// Parent matrix (just identity if parent is Global)this.Transform = this.Parent.Transform;// Scalethis.Transform = this.Transform * Matrix.Scaling(this.LocalScaleX, this.LocalScaleY, this.LocalScaleZ);// Translatethis.Transform = this.Transform * Matrix.Translation(this.LocalX, this.LocalY, this.LocalZ);// Rotatethis.Transform = this.Transform * Matrix.RotationQuaternion(this.LocalRotation);}// Position - sets to an absolute position in local or global spacepublic 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];  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;  I suppose what I really need is:1. A way to extract the rotation (in Euler angles) and position from any entity''s matrix, and2. 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 ;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,and2. A way to transform a point between an entity''s local space, to global space, and backagain.Or a whole new set of transformation methods  Lets take the general case.  If a have a tree of nodeswith transformation at each level, then the following istrue:if at each Level i, the transformation is represented bythe matrix Li, then the total transformation is:T = L0*L1*L2*...Lnwhere n is the number of levels in the tree.  If at any pointin the tree you wish to apply a transform, you simply takethat Li and multiply it by the transformation matrix.  Thisgoes for ALL "delta" transformations.  This type of ideabasically represents a heirarchy of objects attached to eachother and effected by the transformation of the node higherup 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 mostlyopinion), it is probably a good idea to implement rotations asan 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 knowthese 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 ;  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:ParentScaleTranslateRotateI think it should probably be doing this:ParentScaleRotateTranslateBut 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. ;  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 andthen scale.  (This is to make sure that translation does notscrew 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 proposingto do, it is not possible to get a proper nonuniform scaling ifscaling is done first and rotation second.   Hope it helps.if you want to check in the future, use following homogenous2D matricesR = cos(theta) -sin(theta) 0    sin(theta)  cos(theta) 0001T =   10    tx 01    ty 00    1and S =Sx   0    0 0Sy   0 00    1just matrix multiply them by hand and see what happens.SporadicFire.   [edited by - SporadicFire on May 28, 2004 1:28:01 PM];  I suggest usingM=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).;  Sorry, my mistake, szinkopa right,except, i''d use M=P*T*S*R. because T*R*S wont giveproper non uniform scaling when you use a rotation matrix.SporadicFire 