drb2k2 122 Report post Posted February 8, 2005 Hi all, Yes i've had a look through previous posts. The problem is most of them seem to be dealing with quaternion cameras. OK now thats out the way let me explain the problem Basically I have a global axis XYZ which is tied in to the camera rotation, so for the moment lets pretend that it never changes and Y is always up, X off to the right I want to rotate objects around this axis. I have some numeric spinners to set the rotation value, so to rotate 90 degrees around the y axis just pop 90 into the y box. So far all is good. BUT, if you rotate 90 degress around the X axis, then try and rotate around the Z axis, it turns on the Y axis instead. Now I realize that this probably has something to do with an axis shifting with the model, That would be fine if all the axis did that. The y rotation spinner however will always spin around the correct axis. This means that if you rotate an object 90 degrees on the X axis, the Z rotation is now exactly the same as the Y rotation. I hope i've explained whats happening ok. Basically each object has a rotation vector. To rotate around the Y axis just add 1 to the Y value etc. The rendering part is as follows. Dim qRot As Microsoft.DirectX.Quaternion Dim RadianRot As Microsoft.DirectX.Quaternion RadianRot.X = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.x / 180 RadianRot.Y = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Y / 180 RadianRot.Z = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Z / 180 qRot = Microsoft.DirectX.Quaternion.RotationYawPitchRoll(RadianRot.Y, RadianRot.X, RadianRot.Z) Dim RotMatrix As Microsoft.DirectX.Matrix = Matrix.Identity 'might use this later for object positional Dim Cent As Microsoft.DirectX.Vector3 Cent = New Microsoft.DirectX.Vector3(0, 0, 0) RotMatrix.AffineTransformation(1, Cent, qRot, New Microsoft.DirectX.Vector3(0, 0, 0)) // tried this and it is exactly the same //'RotMatrix.Multiply(Matrix.RotationX(Geometry.DegreeToRadian(Me.ObjectDetailsList(Me.WhichObj).Rotation.X))) //'RotMatrix.Multiply(Matrix.RotationY(Geometry.DegreeToRadian(Me.ObjectDetailsList(Me.WhichObj).Rotation.Y))) //'RotMatrix.Multiply(Matrix.RotationZ(Geometry.DegreeToRadian(Me.ObjectDetailsList(Me.WhichObj).Rotation.Z))) Me.device.Transform.World = Matrix.Multiply(RotMatrix, Me.device.Transform.World) Me.device.RenderState.Lighting = True device.SetStreamSource(0, Me.ModelVertexBuffer, 0) device.VertexFormat = CustomVertex.PositionNormal.Format device.DrawPrimitives(PrimitiveType.TriangleList, 0, Me.FacetCount) If anyone can help or point me in the right direction I would be very grateful. Cheers DRB2K2 0 Share this post Link to post Share on other sites
Eelco 301 Report post Posted February 8, 2005 im not sure if it makes a difference, but try constructing the quaternions seperatly from the rotationvalues, then combine them by multiplication into one. 0 Share this post Link to post Share on other sites
Eelco 301 Report post Posted February 8, 2005 oh wait i think i got it.you should accumulate the rotation in the quaternion. it seems like right now youre accumulating in euler angles, then convert those to quats. that way you might aswell not use a quat. 0 Share this post Link to post Share on other sites
drb2k2 122 Report post Posted February 9, 2005 hmmmmmmmm not too sure I see what you're getting at there. The vector3 structure is only used as a holding place for the rotation angle.Do you mean to simply change this into a quaternion structure instead?If thats the case then I don't think there'll be a difference. Thanks for the suggestion though, keep em coming.CheersDRB2k2 0 Share this post Link to post Share on other sites
drb2k2 122 Report post Posted February 9, 2005 Ok have cracked itThe rendering part was fine, what was wrong was the bit where I was calculating the rotation. Before if I wanted a 90 rotation on the Z axis I would just put Rot.Z = 90Now though I've done this. Dim temp As Microsoft.DirectX.Vector3 = New Microsoft.DirectX.Vector3(Me.NumericUpDown_RotX.Value, Me.NumericUpDown_RotY.Value, Me.NumericUpDown_RotZ.Value) Dim test As Microsoft.DirectX.Vector3 = New Microsoft.DirectX.Vector3(0, 0, 1) test.TransformCoordinate(Me.GlobalMatrix) Dim mat As Matrix = Matrix.Identity mat.RotationAxis(test, Me.NumericUpDown_RotZ.Value) temp.TransformCoordinate(mat) Me.ObjectDetailsList(Me.WhichObj).Rotation = tempBasically we know that we want to rotate on the axis 0,0,1 for a z rotation.This is dependent on the world transform so me.GlobalMatrix is simply device.transform.worldwe then rotate around the transformed Z axis by the amount held in the rotation spinners e.g. 90 degreesThen transform the entire rotation amount by these et voila it all works for the momentCheersDRB2k2 0 Share this post Link to post Share on other sites
drb2k2 122 Report post Posted February 9, 2005 damn,well it nearly works, just now the X axis always changes with the model RadianRot.X = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.x / 180 RadianRot.Y = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Y / 180 RadianRot.Z = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Z / 180 'qRot = Microsoft.DirectX.Quaternion.RotationYawPitchRoll(RadianRot.Y, RadianRot.X, RadianRot.Z) Dim qX, qY, qZ As Quaternion qX = Quaternion.RotationAxis(New Microsoft.DirectX.Vector3(1, 0, 0), RadianRot.X) qY = Quaternion.RotationAxis(New Microsoft.DirectX.Vector3(0, 1, 0), RadianRot.Y) qZ = Quaternion.RotationAxis(New Microsoft.DirectX.Vector3(0, 0, 1), RadianRot.Z) 'multiplication not communative causing rotation problems here qRot = Quaternion.Multiply(qX, qY) qRot.Multiply(qZ)If I change around the multiplication order whichever one is done first changes its axis and ends up being the same axis as the last. hmmmmmmmm is there a better way to generate a rotation matrix I wonder.CheersDRB2k2 0 Share this post Link to post Share on other sites
Eelco 301 Report post Posted February 9, 2005 Quote:Original post by drb2k2If I change around the multiplication order whichever one is done first changes its axis and ends up being the same axis as the last. i think the difference might be in post-or premulitplication.try both of these, and see if there is a difference: qRot = Quaternion.Multiply(qX, qY) qRot = Quaternion.Multiply(qRot, qZ)//or qRot = Quaternion.Multiply(qX, qY) qRot = Quaternion.Multiply(qZ, qRot)if i recall correctly the difference between post and premultiplication is that either you do rotation a in coordinate system b, or rotation b along coordinate system a. then again im not sure. i should brush up on these things myself a bit... 0 Share this post Link to post Share on other sites
Dmytry 1151 Report post Posted February 9, 2005 as about pre-multiply and post multiply.if to transform points you useQ*Point*~Q - based formula, thenA*B will do rotation same as if you rotate first by B then by A. That is, if i want to rotate camera around camera's x axis, i should rotate after i get point into camera space. That is, i should useQuaternionThatRotatesAroundXAxis*CameraQuaternion;(then, result is supposed to be used for transform like Q*Point*~Q)If i want to rotate around world's x axis i must useCameraQuaternion*QuaternionThatRotatesAroundXAxis;- i first rotate around world, then rotate by camera.Some people store inverse of camera's quaternion instead of camera's quaternion itself. I myself do that, i have unified coordinate system class (instead of camera class) with method GetTransformTo and GetTransformFrom (returning 4x4 matrix ready for OGL). I use GetTransformTo for camera and GetTransformFrom for skeletons/etc. Very handy, in fact. 0 Share this post Link to post Share on other sites
drb2k2 122 Report post Posted February 9, 2005 ahha,I see what you meanHave decided to settle for RadianRot.X = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.x / 180 RadianRot.Y = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Y / 180 RadianRot.Z = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Z / 180 Dim matX, matY, matZ As Matrix matX = Matrix.RotationX(RadianRot.X) matY = Matrix.RotationY(RadianRot.Y) matZ = Matrix.RotationZ(RadianRot.Z) RotMatrix = Matrix.Multiply(matX, matY) RotMatrix = Matrix.Multiply(RotMatrix, matZ) RotMatrix = Matrix.Multiply(RotMatrix, Me.device.Transform.World)Still not 100% on it though, thanks guys for your help especially EelcoMuch obligedCheersDRB2k2 0 Share this post Link to post Share on other sites
Guest Anonymous Poster Report post Posted February 9, 2005 Could it be that the product of tow quaternion is different than the product of two matrices.q0 * q1 != r0 * r1I believe this can be and was proof on another thread 0 Share this post Link to post Share on other sites
drb2k2 122 Report post Posted February 10, 2005 ok will give it a go,i.e convert quaternions to matrices and then multiply them together.CheersDRB2k2 0 Share this post Link to post Share on other sites
Dmytry 1151 Report post Posted February 10, 2005 Quote:Original post by Anonymous PosterCould it be that the product of tow quaternion is different than the product of two matrices.q0 * q1 != r0 * r1I believe this can be and was proof on another threadDon't sure what you mean.I tested my quaternion lib by checking thatquaternion_to_matrix(q1)*quaternion_to_matrix(q2)is nearly equal(except for roundoff errors) toquaternion_to_matrix(q1*q1)Though, if you use different convention that is IMHO confusing, it might be equal toquaternion_to_matrix(q2*q1) 0 Share this post Link to post Share on other sites
Guest Anonymous Poster Report post Posted February 10, 2005 You are right I was wrong 0 Share this post Link to post Share on other sites