# Spaceship Movement

This topic is 2358 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi fellow programmers,
i'm currently working on a prototype of a space fighting game and having a hard time figuring out how the movement of the spaceships can be realised. My first approach was using several rotation and translation matrices but while i succeed in placing and moving the ship i failed miserably in changeing the direction of the objects =(. Like if the ship is upsidedown and it should rotate left it is rotating right which doesn't surprise me but i could not find a way to solve the problem. My researches brought up these "Quarternions", which certenly are a cool thing but i don't know how to work properly with them. Is there anyone here how coud give me a hint (or a code snipet) where such "six degree of freedom" movement is actually implemented? I found a code written in python but i'm using C++ and so this doesn't help that much =(

Without this technique i'd have to convert the rotation of the worldspace into the "private" space of the ship ( http://vblab.de/files/problem.png like shown here) but failed again.

Any help would be appreciated!

##### Share on other sites
Typically you will do the "player controlled" navigation of the ship in local space, and then transform that into world space for moving the ship itself. Understanding that transformation is probably the most important part of working in 6DOF environments.

##### Share on other sites
And unfortunately this is exact what i'm unable to do =/ Currently the ship movement is based on a vector giving the yaw, pitch and roll of the spaceship in worldspace and a position vector giving the x,y and z coordinates in worldspace. Moving the ship there is not that hard, the velocity vector transformed with the rotationmatrix via D3DMatrixRotationYawPitchRoll and D3DXVectorTransformCoord added to the position vector of the spaceship and it's moving like it should.
 D3DXVECTOR3 position, velocity; float yaw, pitch, roll; D3DXMATRIX rotationMatrix; //Position contains .x, .y, .z of the ship; //Velocity contains x = 0.0, y = 0.0, Z = 1.0 so the vessel will move forward //Yaw, Pitch, Roll hold the ypw values in worldspace // Create the rotation matrix from the yaw, pitch, and roll values. D3DXMatrixRotationYawPitchRoll(&rotationMatrix, yaw, pitch, roll); // Transform the velocity vector by the rotation matrix so it is correctly rotated at the origin D3DXVec3TransformCoord(&velocity, &velocity, &rotationMatrix); //Translate the rotated ship position to its location in worldspace position = position + velocity; //Store the new position of the ship 

As mentioned this works fine with any values but how do i manage to change the rotation? Creating another rotationmatrix due to the user input and multiplying it to the old rotationmatrix gives odd results as much as changing the roll/pitch/yaw values since they are measured in worldspace and not localspace and google isn't much of a help here =(

##### Share on other sites
I think you should change your representation for the rotations. Yaw-Pitch-Roll may be more intuitive (well, not for me actually but people seem to find it intuitive), but it's a quite bad representation when you have to compose several rotations and work with large rotations (and spaceships do rotate quite freely in the space). I suggest to either use rotation matrices or quaternions. Quaternions are probably more stable and easier to normalize, but you probably know a lot more about matrices and you may have to convert the quaternions to matrices anyway.

##### Share on other sites
You simply modify the pitch, yaw, or roll values - that will change your rotation.

The tricky part is obtaining the correct Euler angles in world space. D3DX should have a function for going from an axis-angle rotation representation to Euler angles; you could use the ship's local axis-angle change during steering, transform that to world space, recover the Euler angles, and then construct your world-space transform for the new ship orientation.

Of course, it may be a hell of a lot simpler to just ditch Euler angles entirely and work in axis-angle representations always :-)

##### Share on other sites
Hm, I thought about giving these quaternions a shot, but since DirectX eventually needs matrices to render the model I'll try to use matrices to deal with this problem. Thanks so far, I'll reply after some tests

##### Share on other sites
Quaternions are best for flight motion since they allow you to travel upside down without having to keep track of your angles as much

 void IMovable::accelerateForward( float scaleFactor ) { float Matrix[16]; Quaternion q; calculateQuats(); // calculates Quaternions from our heading and pitch into _qHeading and _qPitch q = _qPitch * _qHeading; // Combine the 2 vectors and rotations - Order specific multiplication! q.CreateMatrix(Matrix); // Store our new vector and its rotation glMultMatrixf(Matrix); // This is the same as glRotatef _qPitch.CreateMatrix(Matrix); // Load this new Matrix into _qPitch _localVelocity.y += Matrix[9] * _acceleration * scaleFactor; // Location [9] will always contain our Y movemet q = _qHeading * _qPitch; // Combine the Quarts again to get our X and Z vectors q.CreateMatrix(Matrix); // Store our new vector and its rotation _localVelocity.x += Matrix[8] * _acceleration * scaleFactor; // Location [8] will always contain our X movemet _localVelocity.z += -Matrix[10] * _acceleration * scaleFactor; // Location [10] will always contain our Z movemet (negate Z in OpenGL) } void IMovable::calculateQuats() { _qPitch.CreateFromAxisAngle(1.0f, 0.0f, 0.0f, _pitch); _qHeading.CreateFromAxisAngle(0.0f, 1.0f, 0.0f, _heading); } 

 void Quaternion::CreateFromAxisAngle(float x, float y, float z, float degrees) { // First we want to convert the degrees to radians // since the angle is assumed to be in radians float angle = degreesToRadians(degrees); // Here we calculate the sin( theta / 2) once for optimization float result = (float)sin( angle / 2.0f ); // Calcualte the w value by cos( theta / 2 ) _w = (float)cos( angle / 2.0f ); // Calculate the x, y and z of the quaternion _x = float(x * result); _y = float(y * result); _z = float(z * result); } void Quaternion::CreateMatrix(float *pMatrix) { // Make sure the matrix has allocated memory to store the rotation data if(!pMatrix) return; // First row pMatrix[ 0] = 1.0f - 2.0f * ( _y * _y + _z * _z ); pMatrix[ 1] = 2.0f * (_x * _y + _z * _w); pMatrix[ 2] = 2.0f * (_x * _z - _y * _w); pMatrix[ 3] = 0.0f; // Second row pMatrix[ 4] = 2.0f * ( _x * _y - _z * _w ); pMatrix[ 5] = 1.0f - 2.0f * ( _x * _x + _z * _z ); pMatrix[ 6] = 2.0f * (_z * _y + _x * _w ); pMatrix[ 7] = 0.0f; // Third row pMatrix[ 8] = 2.0f * ( _x * _z + _y * _w ); pMatrix[ 9] = 2.0f * ( _y * _z - _x * _w ); pMatrix[10] = 1.0f - 2.0f * ( _x * _x + _y * _y ); pMatrix[11] = 0.0f; // Fourth row pMatrix[12] = 0; pMatrix[13] = 0; pMatrix[14] = 0; pMatrix[15] = 1.0f; // Now pMatrix[] is a 4x4 homogeneous matrix that can be applied to an OpenGL Matrix } 

as you receive input to change the direction you adjust q_pitch and q_heading accordingly and it will get calculated. I recommend creating a movable interface/class and deriving all your objects that need to move from it.

##### Share on other sites
Will try it right away with this code. Thank you so much!

##### Share on other sites
VBLab, quaternions solve a number of problems, and if you have a working implementation you can actually treat them as a black box object that just does what you need it to do. It's not hard to construct a rotation matrix on the fly form a quaternion, even by hand.

The problem that quaternions solve is http://en.wikipedia.org/wiki/Gimbal_lock which can cause your movements to end up not working correctly.

1. 1
Rutin
42
2. 2
3. 3
4. 4
5. 5

• 9
• 27
• 20
• 14
• 14
• ### Forum Statistics

• Total Topics
633388
• Total Posts
3011622
• ### Who's Online (See full list)

There are no registered users currently online

×