简体   繁体   中英

Rotate 3D Model in XNA

I am new to XNA, and I am creating a simple game. Sorry that this is probably really simple, but I can't find any help on it. There is a ship in the game that I made with Blender, and I want to be able to control the ship by being able to rotate the ship's X, Y and Z axises. Here is the code I have:

protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
  RotationMatrix = Matrix.CreateRotationY(MathHelper.PiOver2) * Matrix.CreateRotationY    (rotationY) * Matrix.CreateRotationX(rotationX) * Matrix.CreateRotationZ(rotationZ);

        Matrix shipTransformMatrix = RotationMatrix * Matrix.CreateTranslation(ship.Position);

                        DrawModel(ship.Model, shipTransformMatrix, ship.Transforms);
        // TODO: Add your drawing code here


        base.Draw(gameTime);
    }

    public  void DrawModel(Model model, Matrix modelTransform, Matrix[] absoluteBoneTransforms)
    {
        //Draw the model, a model can have multiple meshes, so loop
        foreach (ModelMesh mesh in model.Meshes)
        {
            //This is where the mesh orientation is set
            foreach (BasicEffect effect in mesh.Effects)
            {

                effect.World = absoluteBoneTransforms[mesh.ParentBone.Index] * modelTransform;
                effect.Projection = projectionMatrix;
                effect.View = viewMatrix;

            }

            //Draw the mesh, will use the effects set above.
            mesh.Draw();
        }
    }

This will rotate the ship, but not along the ship's axis's. If I rotate the Y axis (by changing the value of rotationY), the ship will rotate along its Y axis. But if I rotate the X or Z axis, the ship rotates according according to the world's X and Z axises, not its own. How do I make it so the ship rotates on its own axises? Do I need to do something different with the matrices? Thanks

Using CreateRotationX, CreateRotationY, & CreateRotationZ all apply rotations around the world or global axes. Meaning it causes your object to rotate only around the world/global axes, not your object's local axes.

Using CreateFromAxisAngle allows you to input whatever rotation axis you want, including the ship's own local axes.

A shift in your overall rotation paradigm will be needed, however, since a rotation around an arbitrary axis like the ship's Up, for instance, can cause a change to any of the 3 angle values at once. Keeping track of all that is unnecessarily difficult. There is an easier way:

Simply store a rotation in matrix (or quaternion) form instead of the 3 angles.

EDIT: Giving some credit here to Steve below (great answer mate, been a while since I did alot of 3D math).

This tutorial here will show you how to setup what Steve suggested!

http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Rotation_-_translation.php

Original Post:

I believe you have to create an effect.Rotation in your BasicEffect loop.

All of this is covered in the basic tutorials over at MSDN I believe. Your code even looks like it came from there.

http://msdn.microsoft.com/en-us/library/bb203897(v=xnagamestudio.31)

If not, check out this link, Reimer covers everything in 3D worth knowing to start:

http://www.riemers.net/eng/Tutorials/XNA/Csharp/series1.php

Here is what I ended up doing just in case anyone else gets stuck like I did:

Matrix RotationMatrix;
//every time I wanted to rotate around an axis, I would do something like this:
protected void rotateY()
    {
        RotationMatrix *= Matrix.CreateFromAxisAngle(RotationMatrix.Up, MathHelper.ToRadians(1.0f));
        //For the X axis I used RotationMatrix.Right, and for the Z RotationMatrix.Forward
    }
protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);


    Matrix shipTransformMatrix = RotationMatrix * Matrix.CreateTranslation(ship.Position);

                    DrawModel(ship.Model, shipTransformMatrix, ship.Transforms);
    // TODO: Add your drawing code here


    base.Draw(gameTime);
}

public  void DrawModel(Model model, Matrix modelTransform, Matrix[] absoluteBoneTransforms)
{
    //Draw the model, a model can have multiple meshes, so loop
    foreach (ModelMesh mesh in model.Meshes)
    {
        //This is where the mesh orientation is set
        foreach (BasicEffect effect in mesh.Effects)
        {

            effect.World = absoluteBoneTransforms[mesh.ParentBone.Index] * modelTransform;
            effect.Projection = projectionMatrix;
            effect.View = viewMatrix;

        }

        //Draw the mesh, will use the effects set above.
        mesh.Draw();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM