2012-06-11 14 views
9

Soy nuevo en XNA y estoy creando un juego simple. Perdón por que esto sea muy simple, pero no puedo encontrar ayuda. Hay un barco en el juego que hice con Blender, y quiero poder controlar la nave al poder rotar los ejes X, Y y Z del barco. Aquí está el código que tengo:Girar modelo 3D en XNA

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(); 
     } 
    } 

Esto rotará la nave, pero no a lo largo del eje de la nave. Si giro el eje Y (cambiando el valor de rotación Y), la nave rotará a lo largo de su eje Y. Pero si giro el eje X o Z, la nave gira de acuerdo con los ejes X y Z del mundo, no los suyos. ¿Cómo lo hago para que la nave gire sobre sus propios ejes? ¿Debo hacer algo diferente con las matrices? Gracias

Respuesta

6

Usando CreateRotationX, CreateRotationY, & CreateRotationZ toda aplican rotaciones alrededor del mundo o ejes globales. Lo que significa que hace que su objeto gire solo alrededor de los ejes mundiales/globales, no de los ejes locales de su objeto.

Usar CreateFromAxisAngle le permite ingresar cualquier eje de rotación que desee, incluidos los ejes locales propios del barco.

Sin embargo, se necesitará un cambio en su paradigma de rotación general, ya que una rotación alrededor de un eje arbitrario como el Up del barco, por ejemplo, puede causar un cambio a cualquiera de los 3 valores de ángulo a la vez. Hacer un seguimiento de todo eso es innecesariamente difícil. Hay una manera más fácil:

Simplemente almacene una rotación en forma de matriz (o cuaternión) en lugar de los 3 ángulos.

+0

Gracias. ¿Cómo puedo definir el eje de rotación de mi nave en CreateFromAxisAngle? Lo intenté, y todo lo que hizo fue transformar mi nave. ¿Cómo almaceno una rotación en una matriz? Eso es lo que he estado tratando de hacer. – davidsbro

+0

Da la casualidad de que escribí una publicación en el blog al respecto. http://stevehazen.wordpress.com/2010/02/15/matrix-basics-how-to-step-away-from-storing-an-orientation-as-3-angles/ –

+0

Gracias. Encontré el enlace que colocaste justo antes de subirlo. lol. Lo leí y pude solucionar el problema. ¡Gracias! Fue muy claro y realmente útil – davidsbro

2

EDIT: Dando algo de crédito aquí a Steve a continuación (gran respuesta compañero, hace tiempo que hice un montón de matemáticas en 3D).

Este tutorial aquí le mostrará cómo configurar lo que sugirió Steve.

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

Post original:

Creo que usted tiene que crear una effect.Rotation en su bucle BasicEffect.

Todo esto está cubierto en los tutoriales básicos en MSDN, creo. Tu código incluso parece que proviene de allí.

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

Si no es así, echa un vistazo a este enlace, Reimer cubre todo en 3D vale la pena conocer para empezar:

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

+0

Gracias. Traté de crear un efecto. Rotación en mi bucle de Básico, pero no había propiedad de Rotación para el efecto. Mi problema no es rotar el modelo, puedo hacer eso, es tener los modelos axises girando con el modelo. Cuando hago 'RotationMatrix = Matrix.CreateRotationY (MathHelper.PiOver2) * Matrix.CreateRotationY (rotationY) * Matrix.CreateRotationX (rotationX) * Matrix.CreateRotationZ (rotationZ);', cualquiera que sea el eje que creo una rotación para el primero gira con el barco , pero los dos después no. ¿Hay un orden certero para multiplicar las matrices para que giren con el modelo? – davidsbro

+0

El orden en realidad no importa (por lo que he notado). Pero veo su problema allí. Haga lo siguiente: RotationMatrix = Matrix.CreateRotationY (rotationY) * Matrix.CreateRotationX (rotationX) * Matrix.CreateRotationZ (rotationZ); –

+0

Supongo que MathHelper.PiOver2 prealinearía su nave en cierto ángulo. En su lugar, preestablezca su rotaciónY, X, Z a los valores que desea inicialmente cuando comience. Eso debería crear la rotación que estás buscando. Con él girando sobre su eje central. –

1

Esto es lo que terminé haciendo simplemente en cualquier caso lo demás se queda atascado como lo hice:

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(); 
    } 
}