Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1] 2
  Print  
Author Topic: Rotation Problem (Quaternion's)  (Read 16574 times)
SalatalikTursusu
Community Member
*
Posts: 20


« on: August 04, 2004, 03:06:12 PM »

i asked this question(s) also in gamedev but i couldn't resolve my problem ... here

from my question in gamedev;
Quote
currently i am working on simple 3d flight simulation.
i assume that <- and -> arrows will be for rotating the ship on its local z axis. rotation's at z axis not effects the direction vector until up|down movement.
i assume that up and down arrows will be for rotating the ship on its local x axis. rotation's at x axis effects the direction vector.
i assume that ship has an initial speed.

i have a vector which keeps the direction of movement.
i am (trying!) using Quaternion's for rotations.
i am using directx and c#.

but i have some problems with rotations and usage of Quaternion's ... after continuous rotations, values of the direction vector becomes non-understandable Smiley also rotations of the ship are not matched with the rotations of direction vector. thats why i decided to work with camera at first ... but no luck Sad i couldn't control neither camera nor ship in the expected style Sad


more details on my question and user replies can be found on that topic, i decided to ask here because i think i cant create expected values for tv system ...

i am using GetRotationMatrix and SetRotationMatrix from tv , Quaternion functions from dx ...

thanks
Logged
Roulette
Community Member
*
Posts: 30


« Reply #1 on: August 04, 2004, 03:42:32 PM »

see the "A17 - Space sim" tutorial

Code:
     
  ' We move the ship forward

        Ship(i).MoveRelative ShipSpeed * 100, 0, 0
       
        ' We update the ship angles with the smooth pitch/yaw/roll movement
        Ship(i).RotateX ShipPitchSM
        Ship(i).RotateY ShipYawSM
        Ship(i).RotateZ ShipRollSM
Logged

truth is out there...
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #2 on: August 04, 2004, 03:53:24 PM »

omg great!
tnx, i missed those tuts!  :oops:
Logged
War
Community Member
*
Posts: 147


« Reply #3 on: August 05, 2004, 09:44:13 AM »

I'm not sure if what Roulette offered solved your problem or not but if you would like to see a sample of using Quaternion based rotation with TrueVision3D you can check out my sample listed here

-War
Logged
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #4 on: August 05, 2004, 03:46:44 PM »

i saw your sample war, thanks ...
i also tried to use Quaternion's ! But i couldn't solve my problem with them also i couldn't find how you implemented in your sample ... your sample is errrm complex  :oops:
Logged
War
Community Member
*
Posts: 147


« Reply #5 on: August 05, 2004, 08:33:22 PM »

Fair enough.  :wink:

The quaternion implementation is located within the Starship base class, which can be found in the \Objects folder of the Game.Engine project.

Rotation begins once a move order is issued to a selected mesh (click to select [bounding box appears] and then press M to enter move orders mode).  The actual call is made from the Move method, which is located on line 104 of Starship.cs.  You'll also notice that within the Move method the direction is stored in a private member variable called _Direction, which doesn't change as a result of rotating the starship.

Code:

public virtual void Move(Vector3 destination)
{
_Origin      = new Vector3(this._Mesh.GetPosition());
_Destination = destination;
_Direction   = _Destination - _Origin;
_Direction.Normalize();

Rotate(destination);
using(Event.PositionChangedEventArgs args = new Event.PositionChangedEventArgs())
{
args.Destination = _Destination;
args.Origin      = _Origin;

OnMove(null, args);
}
}


The Rotate method (line 128) gets the current rotation matrix (D3D) and converts it to a Quaternion storing it in the member variable _RotationOrigin.  It also populates the _RotationDestination variable using the ships current position and selected destination – finally it toggles the orientation flag to false so rotation can start.

Code:

public virtual void Rotate(Vector3 destination)
{
D3DMATRIX currentRotation = new D3DMATRIX();

this._Mesh.GetRotationMatrix(ref currentRotation);
Matrix4 convertedRotation = Matrix4.Convert(currentRotation);

_RotationOrigin.FromRotationMatrix(convertedRotation.GetMatrix3());
_RotationDestination = Quaternion.FromDestination(this.Position, destination);
this._IsOriented = false;
}


The rotation itself is performed within the Instance_FrameStart event handler (line 298).  Here a check is made to see if the mesh is oriented, and if not, a check is then made against the _RotationIncrement value to ensure it’s < 1.  Assuming all is well (not oriented and increment is < 1) the _RotationIncrement value is incremented (using _Rotation).  A new quaternion is populated using the Quaternion Slerp method and the values of _RotationIncrement, _RotationOrigin, and _RotationDestination.  The Quaternion is then converted into a matrix (D3D) and applied to the model.

This process is then repeated every frame until the model has rotated completely towards the destination.

Code:

private void Instance_FrameStart(FrameEventArgs e)
{
#region Rotation
if(this._IsOriented == false)
{
if(_RotationIncrement < 1f)
{
_RotationIncrement += _Rotation;
if(_RotationIncrement > 1f)
{
_RotationIncrement  = 1f;
this._IsOriented = true;
}
Quaternion currentOrientation = Quaternion.Slerp(_RotationIncrement, _RotationOrigin, _RotationDestination);

Matrix3 currentMatrix = currentOrientation.ToRotationMatrix();
D3DMATRIX tvMatrix = Matrix4.Convert(Matrix4.FromMatrix3(currentMatrix));
this._Mesh.SetRotationMatrix(ref tvMatrix);

if(this._IsOriented)
{
_RotationIncrement = 0f;
}
}
}
#endregion

#region Movement check
if(this.State == StarshipState.Moving)
{
Vector3 currentPosition = new Vector3(this._Mesh.GetPosition());

#region Check Destination
if(currentPosition.Equals(_Destination, 2f))
{
this.SetPosition(_Destination);
this.State = StarshipState.Idle;
_Destination = Vector3.Negate(_Destination);
}
#endregion

#region Move

_Direction = _Destination - currentPosition;
_Direction.Normalize();

Vector3 scaledPosition = (_Direction * (e.LastFrameTimeLapsed * _Speed/10f));
Vector3 newPosition    = currentPosition + scaledPosition;
this.SetPosition(newPosition);

#endregion
}
#endregion
}

Hopefully that’ll shed some light on things for you.  Let me know if I can help further.

-War
Logged
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #6 on: August 06, 2004, 03:43:39 AM »

thank you War , for explanations! Smiley

i decided to start with quaternion's for preventing "gimbal locks" , errors in rotations ... but i couldn't implemented ... :oops:

ermm, from what i see in the tutorial a-17, there is no need to use quaternion's ? and gimbal lock, i know that quaternion's is also for resolving gimbal lock, what about a-17 ?  i need local axis vector's , direction, left and up , can i extract them from my model's getrotationmatrix method ?

tnx!
Logged
War
Community Member
*
Posts: 147


« Reply #7 on: August 06, 2004, 08:22:45 AM »

Correct, you can accomplish roation without the use of Quaternions (obviously).  As for A-17 it is also prone to gimbal lock because it users Euler angles to rotate the model.

To answer your question, yes you can extract the Euler angles from the model's matrix -- here's the how to from The Matrix and Quaternions FAQ listed below:

Quote

Q37. How do I convert a rotation matrix to Euler angles?
--------------------------------------------------------

  This operation is the exact opposite to the one answered in the question
  above. Given that the rotation matrix is:

         |  CE      -CF      -D   0 |
    M  = | -BDE+AF   BDF+AE  -BC  0 |
         |  ADE+BF  -ADF+BE   AC  0 |
         |  0        0        0   1 |

  where A,B are the cosine and sine of the X-axis rotation axis,
        C,D are the cosine and sine of the Y-axis rotation axis,
        E,F are the cosine and sine of the Z-axis rotation axis.

  Using the C data structure for a 4x4 matrix, the index values are
  as follows:

         |  0  1  2  3 |
    M =  |  4  5  6  7 |
         |  8  9 10 11 |
         | 12 13 14 15 |
     
  From looking at these two tables, it can be see that array element
  [2] has the value of -D or -sin(Y). Then the rotation angle in the
  Y-axis can be calculated from a call to to the inverse-sine function.
  Passing this value to the cosine function then gives the value of
  C.

  If C is not zero, then the rotation angles in each of the X and Z
  axii, can be derived from the terms on the third column and first row
  respectively. These are as follows:

    X-axis:  M[6]  = -BC        
             M[10] =  AC  
 
    Z-axis:  M[0]  =  CE
             M[1]  = -CF

  The actual rotation angles can be derived by taking each pair of values
  dividing by C and passing the results to the inverse tangent function.

  If C is zero, then these calculations are not possible. In this case
  the rotation angle in the Y-axis will be either -90 or +90. Thus D
  will either have the value of 1 or -1.

  In this case, Gimbal Lock will have occurred. Rotations in both the
  X and Z axii will appear to be in the same axis. This can be seen
  through the evaluation of the rotation axis.

         |  0.E       -0.F        1    0 |
    M  = | -B.1.E+AF   B.1.F+AE  -B.0  0 |
         |  A.1.E+BF  -A.1.F+BE   A.0  0 |
         |  0          0          0    1 |

  Multiplying out each term gives:

         |  0          0          1    0 |
    M  = | -BE+AF      BF+AE      0    0 |
         |  AE+BF     -AF+BE      0    0 |
         |  0          0          0    1 |

  Rearranging these terms gives:

         |  0          0          1    0 |
    M  = | -BE+AF      AE+BF      0    0 |
         |  AE+BF      BE-AF      0    0 |
         |  0          0          0    1 |

  Then it can be seen that the matrix is really of the form:

         |  0   0  -1   0 |
    M  = | -V   W   0   0 |
         |  W   V   0   0 |
         |  0   0   0   1 |

  Where V has the value of BE-AF and
        W has the value of AE+BF

  These two values can be considered to be the sin and cosine of a
  single rotation axis.

  The final algorithm is then as follows:

    -----------------------------------

    angle_y = D = -asin( mat[2]);        /* Calculate Y-axis angle */
    C           =  cos( angle_y );
    angle_y    *= RADIANS;

    if ( fabs( C ) > 0.005 )             /* Gimball lock? */
      {
      trx      =  mat[10] / C;           /* No, so get X-axis angle */
      try      = -mat[6]  / C;

      angle_x  = atan2( try, trx ) * RADIANS;

      trx      =  mat[0] / C;            /* Get Z-axis angle */
      try      = -mat[1] / C;

      angle_z  = atan2( try, trx ) * RADIANS;
      }
    else                                 /* Gimball lock has occurred */
      {
      angle_x  = 0;                      /* Set X-axis angle to zero */

      trx      = mat[5];                 /* And calculate Z-axis angle */
      try      = mat[4];

      angle_z  = atan2( try, trx ) * RADIANS;
      }

    angle_x = clamp( angle_x, 0, 360 );  /* Clamp all angles to range */
    angle_y = clamp( angle_y, 0, 360 );
    angle_z = clamp( angle_z, 0, 360 );

    -----------------------------------


Hope that helps.

-War

Reference:

Eulars & Quats
The Matrix and Quaternions FAQ
Getting Direction Vectors From a Quaternion
Logged
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #8 on: August 07, 2004, 03:22:46 PM »

as you mentioned that there can be a gimbal lock in a-17 i decided to work with Quaternion's ...

currently i defined a direction vector and left vector. let me show what i am doing;

-> increase/decrease pitch with up/down keys,
-> increase/decrease roll with <-/->  keys,

when the input key is <- or ->;
-> ModelRotationMatrix.RotateAxis(new Microsoft.DirectX.Vector3(direction.x,direction.y,direction.z),(float)(roll)); // for rotating on direction axis ...
-> Model.SetRotationMatrix(ref ModelRotationMatrix); // applying the rotation to model ...
->    qua1 = new Microsoft.DirectX.Quaternion((float)direction.x,(float)direction.y,(float)direction.z,(float)(roll*Math.PI / 180));         
   qua1.Normalize();

   qua2 = new Microsoft.DirectX.Quaternion((float)left.x,(float)left.y,(float)left.z,0);               
   qua2.Normalize();

   qua3 = new Microsoft.DirectX.Quaternion();
   qua3 = qua1;
   qua1.Multiply(qua2);
   qua3.Invert();
   qua1.Multiply(qua3);
   qua1.Normalize();

   left.x = qua1.X;
   left.y = qua1.Y;
   left.z = qua1.Z;
// rotating left vector ... because we need local axis's Smiley

my vector rotates more than my model Smiley i have this problem also in up/down inputs ... i need correct direction and left vector values for both rotations and movement ...

where is my the problem ?  :roll:
Logged
War
Community Member
*
Posts: 147


« Reply #9 on: August 07, 2004, 03:35:19 PM »

Hhmmm, I think I'll need to see your class before I can offer any insight.  I'm responding to your PM -- we can take this offline.

-War
Logged
newborn
Customers
Community Member
*****
Posts: 2451


WWW
« Reply #10 on: August 07, 2004, 04:36:31 PM »

no no! dont take this offline, lots of interesting stuff in there!!
believe it or not, lots of us learned bu this very interesting conversation!
Logged

War
Community Member
*
Posts: 147


« Reply #11 on: August 07, 2004, 05:05:23 PM »

<chuckles/>

I'll be happy to continue in forum -- however that's up to SalatalikTursusu.

-War
Logged
War
Community Member
*
Posts: 147


« Reply #12 on: August 07, 2004, 05:43:52 PM »

In the interim for those that are following along, there is a sample that I'd like to make you aware of.  It is the sample that I used to become familiar with Quaternions.

The sample is C++/OpenGL base and I found it quite helpful.  The author is someone called DigiBen, you can locate it here: http://www.gametutorials.com/download/OpenGL/Quaternions_OGL.zip

-War
Logged
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #13 on: August 08, 2004, 02:40:58 AM »

allright, so let me restart from the beginning ... my goal is to provide movement freedom at local axis's in 3d space ... this is for my basic flight simulation.

for solving the problem let's use "divide and conquer" method;

-> i have a simple SpaceShip model, which isn't moving.
-> i have a camera which also isn't moving but looking to my model for inspecting model rotations ...
-> i assume that i have 3 vector which defines my model local axis's ... direction, up and left.
-> i assume that <- and -> arrows will be for rotating the ship on its local z axis. rotation's at z axis not effects the direction vector until up|down movement.
-> i assume that up and down arrows will be for rotating the ship on its local x axis. rotation's at x axis effects the direction vector.

initial values of the vectors;
Code:
direction.x = 0;
direction.y = 0;
direction.z = -1;

left.x = -1;
left.y = 0;
left.z = 0;


when the input is <- or -> we should rotate our ship on ship's local z axis, which is direction vector (assume that type conversions possible);
Code:
Ship.GetRotationMatrix(ref ShipModelMatrix);

Microsoft.DirectX.Matrix dummy = new Matrix();

// create rotation axis on local z axis, on direction vector
//key_z positive if input is <- else negative , 1 / -1
dummy.RotateAxis(new Microsoft.DirectX.Vector3(direction.x,direction.y,direction.z),(float)(key_z));

// apply rotation to current rotation matrix
ShipModelMatrix.Multiply(dummy);

// set rotation matrix of ship
Ship.SetRotationMatrix(ref ShipModelMatrix);


with this rotation ship will have new left vector;
Code:
left.x = ShipModelMatrix.M11;
left.y = ShipModelMatrix.M21;
left.z = ShipModelMatrix.M31;


when the input is up or down we should rotate our ship on ship's local x axis, which is left vector (assume that type conversions possible);
Code:
Microsoft.DirectX.Vector3 vect = new Microsoft.DirectX.Vector3(left.x,left.y,left.z);
vect.Normalize();

Microsoft.DirectX.Matrix dummy = new Matrix();

// create rotation axis on local x axis, on left vector
//key_x positive if input is up else negative , 1 / -1
dummy.RotateAxis(vect,(float)(key_x));

// apply rotation to current rotation matrix
ShipModelMatrix.Multiply(dummy);

// set rotation matrix of ship
Ship.SetRotationMatrix(ref ShipModelMatrix);


with this rotation ship will have new direction vector;
Code:
direction.x = ShipModelMatrix.M12;
direction.y = ShipModelMatrix.M22;
direction.z = ShipModelMatrix.M32;


with this implementation ship is rotating on its local axis's perfectly ... but i can't use mixed axis rotations, for example rotation on x axis after z axis ...

as you can see i decided to use matrix's because of getrotation , setrotation methods but i can't resolve my problem ... i think there won't be gimbal lock problem with this code because i defined my local axis's as vector and i am rotating these vectors with ship rotations ...

as you can see implementation is really simple but there are problems ... i also tried Quaternion's for rotations but i couldnt ...
Logged
JeffWeber
Community Member
*
Posts: 1023


« Reply #14 on: August 08, 2004, 08:36:29 AM »

Hmmm, I'm late coming to this post and have really only browsed thru it, but I think I've had a similar problem before.

Your problem might be that the order in which you apply rotations to your ship matters.  

Rotationg 90 deg on X axis then Rotating 90 degrees on the Z axis is different then Rotationg 90 deg on Z axis then Rotating 90 degress on the X axis.  

You need to take this into consideration when ever you process your input and turn it into ship rotation.

To do this, you need to find a way to always do you rotations in the same order.  I think you might be able to do this by always starting from original orientation when you apply your rotations. This would mean keeping track of you rotations as you go, then when they say want to rotate the ship 5 degrees more on the X, add the 5 degrees to your current X rotation, then mathematically put the ship back to it's original orientation and rotate X  then Z using your cummaltive rotations...  This way you are always doing your rotations in the same order.

Not sure it'll work, but maybe it will give you some ideas.
Logged

""Space is deep, Man is small and Time is his relentless enemy" --Orson Scott Card
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #15 on: August 08, 2004, 08:50:58 AM »

thank you jeff for the information ...

you pointed out the order of rotations, but i defined my own axis's for Ship model ... also i defined the rotations on these local axis's so there shouldn't be a problem with the rotation order. because i am rotating the axis's and model according the input on related axis ... after rotations i am calculating the new axis's ... i am applying rotation matrix's to current rotation matrix of my model ...

i think we should solve this problem Tongue Quaternion's are really good for both calculations , solving the rotation problems and multiplayer games but ... :oops:  

i think problem can be on angle values (radian/degree) , order of applying rotation , usage of getrotation/setrotation ...

tnx!
Logged
War
Community Member
*
Posts: 147


« Reply #16 on: August 08, 2004, 01:30:33 PM »

OK SalatalikTursusu, I have a better understanding of what you are trying to accomplish and how you are currently going about it.  I'm quite certain a Quaternion based solution won't be a problem.  I've got a full schedule today but I'll try to post a follow-up ASAP.

-War
Logged
SalatalikTursusu
Community Member
*
Posts: 20


« Reply #17 on: August 08, 2004, 03:13:29 PM »

Quote from: "War"
OK SalatalikTursusu, I have a better understanding of what you are trying to accomplish and how you are currently going about it.  I'm quite certain a Quaternion based solution won't be a problem.  I've got a full schedule today but I'll try to post a follow-up ASAP.

-War


thank you war, i can give more information on my controls during flight if you want or you can look at my first post in this topic ... problem may be in the implementation of my assumptions at controls ...  :wink:
Logged
BYTE-Smasher
Community Member
*
Posts: 956

vaporware makes baby jesus cry


WWW
« Reply #18 on: August 09, 2004, 08:37:50 AM »

Quote from: "newborn"
no no! dont take this offline, lots of interesting stuff in there!!
believe it or not, lots of us learned bu this very interesting conversation!


YES!! please continue!!! I've had problems with rotation before too!! I'd like to know how to resolve them....
Logged

SalatalikTursusu
Community Member
*
Posts: 20


« Reply #19 on: August 10, 2004, 01:19:36 AM »

Quote from: "BYTE-Smasher"
Quote from: "newborn"
no no! dont take this offline, lots of interesting stuff in there!!
believe it or not, lots of us learned bu this very interesting conversation!


YES!! please continue!!! I've had problems with rotation before too!! I'd like to know how to resolve them....


we are waiting replies  Tongue
i think war found a solution for my problem and he will explain it as soon as possible  :wink:
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks