How to convert pitch and yaw to x, y, z rotations?
- 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.... :(
So my quesiton is: how do you calculate the X, Y, and Z rotations for an object in terms of pitch and yaw?
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();
    }
}