Hello,
This question is probably for Mike Lischke only but if anyone has any idea let me know. Ta

I would like to combine a rotation matrix to do one rotation in one direction then another rotation in another direction. The problem im having is that in Mike's "opener" code, it rotates an object (to translate from .3ds) to a certain position. If I want to rotate it again in a diferent direction is combines the previous rotation and gives me strange results. So I need to do one rotation at the very start (say on the X) then all rotations after that on the Y. Is that impossible?

I found a function called QuaternionMultiply in geomtry.pas which sounds like it should do the trick but I haven't a clue how to use it.

well, usually the results aren't that what one would expect when using Euler angles (that is, to describe a free rotation by applying three "base" rotations about X, Y and Z). Quaternions are not bad but their main advantage lie in the animation field where you may need to smoothly rotate an object about an arbitrary axis and spin it possibly at the same time.

For your problem I would recommend another approach. Look into Geometry.pas. There are 6 functions to roll, turn and pitch a coordinate system around an arbitrary axis.

Ciao, Mike

0

WoodyJ3Author Commented:

I have spit the code to treat ever object contaioned in the 3ds file as sperate objects so I can spin individual objects independantly. When I apply a rotation matrix around the X to an object that has already been rotated on the Y I get the combination of both rotations, which is not what I want. After the whole scene has been imported to the viewer, I just want all object to rotate in one direction and forget about all rotations that were applied during the import process. I now store an objects current matrix but I seem to lose the pivot point, so I've reverted back to calculating the objects position from the original matrix.

Will the functions you have mentioned work in this way?

No, the functions I mentioned add another rotation to what was before. This is how rotation actually works mostly. But I'm thinking now about another way for you. Since you are interested to take back all rotations which have been made while importing the objects you can probably decompose the resulting object matrix (see MatrixDecompose in Geometry.pas) and create a rotation matrix from the returned values. Invert this matrix then and apply it to the object matrix. So you should get the unrotated object.

For quaternion operations I recommend that you look for the comp.graphics.algotithms FAQs (news groups or www.faq.org) to learn how to work with them. MakeQuaternion is a simple function to fill a TQuaternion record with the values you provide (or build a quaternion on the fly).

Ciao, Mike

0

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Woody,
If the result of your rotation is not what you want, it's probably because you don't make the rotation in the right order.

a rotation can be represented by a quaternion rotation and the function
QuaternionMultiply gives the rotation obtained by the composition of the two quaternions given in param...it that's helpfull...

to do a rotation in X then rotations by Y, you create the rotation matrix in X, push it on the stack, multiplie by the rotation matrix in Y, get the matrix pushed on the stack and multiplie it by the new rotation matrix in Y...

jeurk, of course, there are a lot of things I don't know :-)

Woody, I'm still confused. Let's assume another situation. Say, the image is opend to the right hand side when loaded but want it to be opened to the left hand side (or rotate it down or whatever). Describes this your situation? If yes then my previous recommendations still are valid. You need to take back the rotations already made somehow and then apply your own rotations. What's so difficult with this approach?

Oops, there's something wrong with E-E. My last comment was sent AFTER your last comment Woody (with the pseudo code). Will E-E never get it right? So many changes in the past month and there's always something unfuctional afterwards... :-(

Ciao, Mike

0

WoodyJ3Author Commented:

I've put together some fake code does this look like what you mean ....

Imagine a house. The house has a door which is sitting above the door frame. To place the door in the door frame it needs to be rotated down. This is it's final position. I then need to open the door which involves rotating it out. For each rotation on the door being opened I need to calculate from the point when it was sitting above the door frame.

To rotate on the horizontal axis and then the Vertical axis.

Cheers
Woody.

0

WoodyJ3Author Commented:

Err.. very confusing. Comments all over the place.

I already know the unrotated position so I just need to combine two rotations. One to get the door to the door frame (vertical). And another to open the door (horizontal). I'll post but rotation function shortly.

0

WoodyJ3Author Commented:

Ok. Here is my function. I'm not even sure which values to pass into the RotX, RotY and RotZ variables!!!

Thanks
John.

//------------------------------------------------------------------------------
// Method: ManipulateObject
//
// Purpose: Simple method that recompiles the display list based on new object positions.
//------------------------------------------------------------------------------
Procedure ManipulateObject(Var GLReader : TGLReader; MeshMotion : TKFMesh3DS; ListIndex : Integer;
RecalcPivots, RedrawScene : Boolean; RotX, RotY, RotZ : Single);
Var
Matrix, Matrix2, OrigMatrix : TMatrix;
CurrentMeshIndex : Integer;
NewList : Cardinal;
i : Integer;
MeshIndex : Integer;
Mesh : PMeshObject;
ParentMeshMotion : TKFMesh3DS;
ParentMotionIndex : Integer;
Begin
glDeleteLists(StrToInt(GLReader.GlLists[ListIndex]), 1);

NewList := glGenLists(1);

glNewList(NewList, GL_COMPILE);

GLReader.GlLists[ListIndex] := IntToStr(NewList);

// *******************************************************
// The below section would move the door to the doorframe
// *******************************************************

// scaling
If (MeshMotion.NSKeys > 0) And (MeshMotion.SKeys[0].Time = 0) Then
Begin
Matrix2 := CreateScaleMatrix(TAffineVector(MeshMotion.Scale[0]));
Matrix := MatrixMultiply(Matrix, Matrix2);
End;

// rotation to normal position
If (MeshMotion.NRKeys > 0) And (MeshMotion.RKeys[0].Time = 0) Then
Begin
Matrix2 := CreateRotationMatrix(MakeAffineVector([MeshMotion.Rot[0].X, MeshMotion.Rot[0].Y, MeshMotion.Rot[0].Z]), MeshMotion.Rot[0].Angle);
Matrix := MatrixMultiply(Matrix, Matrix2);
End;

// translation
If (MeshMotion.NPKeys > 0) And (MeshMotion.PKeys[0].Time = 0) Then
Begin
Matrix[3, 0] := Matrix[3, 0] + MeshMotion.Pos[0].X;
Matrix[3, 1] := Matrix[3, 1] + MeshMotion.Pos[0].Y;
Matrix[3, 2] := Matrix[3, 2] + MeshMotion.Pos[0].Z;
End;

// *******************************************************
// This is the bit I'm confussed on.
// I need to apply another rotation in another direction (Open the door)
//
// I've provided three variables RotX, RotY, RotZ : Single
//
// I dont want to lose the pivot point either
// *******************************************************

Mmh, I think we come closer now. You get wrong results because of the wrong order, I believe. But it is not as Jeurk said but you need to apply the rotation before it is translated! So place the code between

// scaling
If (MeshMotion.NSKeys > 0) And (MeshMotion.SKeys[0].Time = 0) Then
Begin
...
End;

and

// rotation to normal position
If (MeshMotion.NRKeys > 0) And (MeshMotion.RKeys[0].Time = 0) Then
Begin
...
End;

You could also try just to add your angles to the three values of the rotation keys in MeshMotion which are used to create the other rotation matrix. This would save one step.

// scaling
If (MeshMotion.NSKeys > 0) And (MeshMotion.SKeys[0].Time = 0) Then
Begin
Matrix2 := CreateScaleMatrix(TAffineVector(MeshMotion.Scale[0]));
Matrix := MatrixMultiply(Matrix, Matrix2);
End;

// open the door
Matrix2 := CreateRotationMatrix(MakeAffineVector([RotX, RotY, RotZ]), 1);
Matrix := MatrixMultiply(Matrix, Matrix2);

// move door to doorframe
If (MeshMotion.NRKeys > 0) And (MeshMotion.RKeys[0].Time = 0) Then
Begin
Matrix2 := CreateRotationMatrix(MakeAffineVector([MeshMotion.Rot[0].X, MeshMotion.Rot[0].Y, MeshMotion.Rot[0].Z]), MeshMotion.Rot[0].Angle);
Matrix := MatrixMultiply(Matrix, Matrix2);
End;

// translation
If (MeshMotion.NPKeys > 0) And (MeshMotion.PKeys[0].Time = 0) Then
Begin
Matrix[3, 0] := Matrix[3, 0] + MeshMotion.Pos[0].X;
Matrix[3, 1] := Matrix[3, 1] + MeshMotion.Pos[0].Y;
Matrix[3, 2] := Matrix[3, 2] + MeshMotion.Pos[0].Z;
End;

Note that this is the kind of Euler angles rotation I talked above which may sometimes not give the requested result. To avoid this you need to use the overloaded variant of these functions and provide a vector (which is usually one of the world axes: [1, 0, 0], [0, 1, 0] and [0, 0, 1]). This is a difference because after the Pitch call the objects up vector no longer is aligned to [0, 1, 0] and turning around this axis is totally different than around the world's "up" vector.

Ciao, Mike

0

WoodyJ3Author Commented:

err... I think I understand that. I'll let you know how I get on.

well, usually the results aren't that what one would expect when using Euler angles (that is, to describe a free rotation by applying three "base" rotations about X, Y and Z). Quaternions are not bad but their main advantage lie in the animation field where you may need to smoothly rotate an object about an arbitrary axis and spin it possibly at the same time.

For your problem I would recommend another approach. Look into Geometry.pas. There are 6 functions to roll, turn and pitch a coordinate system around an arbitrary axis.

Ciao, Mike