0
votes

This is probably more of a Math subject area, but I'm hoping it's simple enough that some other dev out there might know.

Situation: I have an airplane game. I need to Pitch, Yaw, and Roll (Rotate about x,y,z) the plane with respect to the plane's orientation.

Problem: I can make the plane model rotate, however the rotations are global to the model. For example, when the plane is facing forward, applying a CreateRotationZ() works fine, but if the model is pointing upward (90 degree pitch), apply the CreateRotationZ() doesn't cause the plane to roll (with respect to the planes orientation), it causes it to yaw.

2
You know there is CreateRotationX and CreateRotationY as well? However, there will be a bit more complicated mathematics when the plane is at different angles. But it'll be a combination of the 3 methods. - anothershrubery
Yes, CreateRotationZ(Yaw), CreateRotationX(Pitch), and CreateRotationY(Roll). These dont work though as they rotate without regard to the orientation on the plane as explained. I have however come very close using: Quaternion rot = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), Roll) * Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), Pitch) * Quaternion.CreateFromAxisAngle(new Vector3(0,1,0), Yaw); Airframe.Orientation = Matrix.CreateFromQuaternion(rot); If you roll the plane to the right, applying pitch correctly works, but yaw does not. Very Frustrating - Neovivacity
Yes you'll need to axes local to your ship, not world axes. The rotation matrix of your ship will have accessors to get (Forward, Backward, Left, Right, Up, and Down), you can rotate around those vectors instead. - Nic Foster

2 Answers

1
votes

Have a position (Vector3) and rotation (Matrix) on your Object/Entity/Ship, and then you can use the following code sample to move or rotate it in any of its local axes.

For example, you want to roll an airplane 45 degrees (this is the rotation about the forward vector you were asking about):

Entity plane = new Entity();
plane.Roll(MathHelper.PiOver4);

Or pitch roll the airplane 90 degrees:

plane.Pitch(MathHelper.PiOver2);    

And here's the code sample

public class Entity
{
    Vector3 position = Vector3.Zero;
    Matrix rotation = Matrix.Identity;

    public void Yaw(float amount)
    {
        this.rotation *= Matrix.CreateFromAxisAngle(this.rotation.Up, amount);
    }

    public void YawAroundWorldUp(float amount)
    {
        this.rotation *= Matrix.CreateRotationY(amount);
    }

    public void Pitch(float amount)
    {
        this.rotation *= Matrix.CreateFromAxisAngle(this.rotation.Right, amount);
    }

    // This is the specific method you were asking for in the question title
    public void Roll(float amount)
    {
        this.rotation *= Matrix.CreateFromAxisAngle(this.rotation.Forward, amount);
    }

    public void Strafe(float amount)
    {
        this.position += this.rotation.Right * amount;
    }

    public void GoForward(float amount)
    {
        this.position += this.rotation.Forward * amount;
    }

    public void Jump(float amount)
    {
        this.position += this.rotation.Up * amount;
    }

    public void Rise(float amount)
    {
        this.position += Vector3.Up * amount;
    }
}

If you want a smooth movement you'll want to use these in very small increments, and use elapsed time in your calculations for the amount that you use.

0
votes

Use Matrix.CreateWorld(), is better for what you want, the parameters are the position, the forward vector and the up vector.

http://msdn.microsoft.com/en-us/library/bb975261.aspx