Help with calculation to steer ship in 3d space
- by Aaron Anodide
I'm a beginner using XNA to try and make a 3D Asteroids game.
I'm really close to having my space ship drive around as if it had thrusters for pitch and yaw.
The problem is I can't quite figure out how to translate the rotations, for instance, when I pitch forward 45 degrees and then start to turn - in this case there should be rotation being applied to all three directions to get the "diagonal yaw" - right? I thought I had it right with the calculations below, but they cause a partly pitched forward ship to wobble instead of turn.... :(
Here's current (almost working) calculations for the Rotation acceleration:
float accel = .75f;
// Thrust +Y / Forward
if (currentKeyboardState.IsKeyDown(Keys.I))
{
this.ship.AccelerationY += (float)Math.Cos(this.ship.RotationZ) * accel;
this.ship.AccelerationX += (float)Math.Sin(this.ship.RotationZ) * -accel;
this.ship.AccelerationZ += (float)Math.Sin(this.ship.RotationX) * accel;
}
// Rotation +Z / Yaw
if (currentKeyboardState.IsKeyDown(Keys.J))
{
this.ship.RotationAccelerationZ += (float)Math.Cos(this.ship.RotationX) * accel;
this.ship.RotationAccelerationY += (float)Math.Sin(this.ship.RotationX) * accel;
this.ship.RotationAccelerationX += (float)Math.Sin(this.ship.RotationY) * accel;
}
// Rotation -Z / Yaw
if (currentKeyboardState.IsKeyDown(Keys.K))
{
this.ship.RotationAccelerationZ += (float)Math.Cos(this.ship.RotationX) * -accel;
this.ship.RotationAccelerationY += (float)Math.Sin(this.ship.RotationX) * -accel;
this.ship.RotationAccelerationX += (float)Math.Sin(this.ship.RotationY) * -accel;
}
// Rotation +X / Pitch
if (currentKeyboardState.IsKeyDown(Keys.F))
{
this.ship.RotationAccelerationX += accel;
}
// Rotation -X / Pitch
if (currentKeyboardState.IsKeyDown(Keys.D))
{
this.ship.RotationAccelerationX -= accel;
}
I'm combining that with drawing code that does a rotation to the model:
public void Draw(Matrix world, Matrix view, Matrix projection, TimeSpan elsapsedTime)
{
float seconds = (float)elsapsedTime.TotalSeconds;
// update velocity based on acceleration
this.VelocityX += this.AccelerationX * seconds;
this.VelocityY += this.AccelerationY * seconds;
this.VelocityZ += this.AccelerationZ * seconds;
// update position based on velocity
this.PositionX += this.VelocityX * seconds;
this.PositionY += this.VelocityY * seconds;
this.PositionZ += this.VelocityZ * seconds;
// update rotational velocity based on rotational acceleration
this.RotationVelocityX += this.RotationAccelerationX * seconds;
this.RotationVelocityY += this.RotationAccelerationY * seconds;
this.RotationVelocityZ += this.RotationAccelerationZ * seconds;
// update rotation based on rotational velocity
this.RotationX += this.RotationVelocityX * seconds;
this.RotationY += this.RotationVelocityY * seconds;
this.RotationZ += this.RotationVelocityZ * seconds;
Matrix translation = Matrix.CreateTranslation(PositionX, PositionY, PositionZ);
Matrix rotation = Matrix.CreateRotationX(RotationX) * Matrix.CreateRotationY(RotationY) * Matrix.CreateRotationZ(RotationZ);
model.Root.Transform = rotation * translation * world;
model.CopyAbsoluteBoneTransformsTo(boneTransforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = boneTransforms[mesh.ParentBone.Index];
effect.View = view;
effect.Projection = projection;
effect.EnableDefaultLighting();
}
mesh.Draw();
}
}