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 ... herefrom my question in gamedev; 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  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  i couldn't control neither camera nor ship in the expected style  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 ' 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. 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. 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. 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!  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: 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 & QuatsThe Matrix and Quaternions FAQGetting 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  my vector rotates more than my model  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
|
 |
« 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; 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); 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; 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); 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; 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  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 » |
|
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
|
 |
« Reply #18 on: August 09, 2004, 08:37:50 AM » |
|
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 » |
|
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 i think war found a solution for my problem and he will explain it as soon as possible :wink:
|
|
|
|
|
Logged
|
|
|
|
|