[XNA] Animaciones básicas en 3D

Las animaciones en 3D implican muchas operaciones de matrices… pero por suerte XNA nos facilita el trabajo hasta tal punto que prácticamente el más negado en matemáticas puede trabajar con ellas… pero aunque sea fácil cualquier programador de XNA que se precie debe hacer un esfuerzo por comprenderlas si quiere saber lo que hace xD. En fin, el de las animaciones es un tema muy ámplio, e iré explicando algunas partes en pequeños episodios. En esta introducción veremos las operaciones más básicas.

Animar objetos en su forma más básica consistirá en multiplicar matrices, y algo muy importante es el orden en el que realicemos estas multiplicaciones. Si no realicamos las multiplicaciones en el orden correcto, nuestro modelo 3D sin duda se moverá de forma cuanto menos “rara” o inesperada. Este problema se soluciona recordando el orden que hay que aplicar, que siempre va a ser el mismo, partiendo de la matriz identidad:

  1. Escalar el modelo
  2. Rotar el modelo sobre su propio eje
  3. Rotar el modelo sobre un punto externo
  4. Trasladar el modelo

Y como he comentado, XNA nos ayuda enormemente en estas posibles operaciones básicas de matrices.

Esto se podría traducir en los siguientes ejemplos:

   1: // Matriz identidad

   2: Matrix.Identity;

   3:  

   4: // Crear escalas

   5: Matrix.CreateScale(1.0f);

   6: Matrix.CreateScale(Vector3.Zero);

   7:  

   8: // Rotar ejes

   9: Matrix.CreateRotationX(0.5f);

  10: Matrix.CreateRotationY(0.5f);

  11: Matrix.CreateRotationZ(0.5f);

  12:  

  13: // Trasladar

  14: Matrix.CreateTranslation(Vector3.Zero);

Ahora vamos a ver un par de ejemplos prácticos muuuy sencillos.

Ejemplo 1: Animando un ventilador

Para animar este ventilador, lo primero que he hecho es descargar el modelo 3D de Internet. En la web hay cientos de páginas que permiten descargar modelos 3D libres de derecho… con una simple búsqueda en Bing encontraremos 41 millones de resultados 🙂 Eso sí, a continuación he tenido que realizar algunas pequeñas modificaciones en 3DSMAX.

Si ampliáis la imágen veréis que he “fusionado” las aspas, con el eje central y los soportes que unen las aspas con los ejes, para animarlos todos juntos, y les he puesto un nombre: “aspas”, al que después accederé desde XNA para animar sólo esa parte del modelo 3D.

captura_3dmax

Ese acostumbra a ser un problema para más de un programador… que no acostumbramos a conocer 3D Max, por suerte siempre hay buenos amigos en los foros que nos ayudaran en estos detalles… en el caso de 3D MAX hay que convertir cada pala a malla editable (con el botón derecho sobre el aspa: Convert To->Editable Mesh), y posteriormente, en las propiedades de la malla, usaremos la función “Attach” para ir fusionando las palas. Finalmente ponemos un nombre que usaremos desde XNA al conjunto de aspas y el eje.

El código no es que tenga mucha dificultad… tampoco entraré mucho en detalle porque os dejo el link para descargarlo.

   1: public void Draw(GameTime gameTime, Matrix vista, Matrix proyeccion) 

   2: {

   3:     modelo.CopyAbsoluteBoneTransformsTo(transformaciones);

   4:  

   5:     foreach(ModelMesh mesh in modelo.Meshes)

   6:     {

   7:         Vector3 rotacionTmp = Vector3.Zero;

   8:  

   9:         if (mesh.Name == "aspas")

  10:         {

  11:             rotacion.Y += 0.01f;

  12:  

  13:             if (rotacion.Y > 360)

  14:                 rotacion.Y = 0;

  15:  

  16:             rotacionTmp = rotacion;

  17:         }

  18:  

  19:         Matrix.CreateTranslation(Vector3.Zero);

  20:         Matrix.CreateRotationX(0.5f);

  21:         Matrix.CreateRotationY(0.5f);

  22:         Matrix.CreateRotationZ(0.5f);

  23:  

  24:         foreach (BasicEffect efecto in mesh.Effects) 

  25:         {

  26:             efecto.EnableDefaultLighting();

  27:  

  28:             efecto.World = transformaciones[mesh.ParentBone.Index] * 

  29:                 Matrix.CreateFromYawPitchRoll(

  30:                 rotacionTmp.Y,

  31:                 rotacionTmp.X,

  32:                 rotacionTmp.Z) *

  33:                 Matrix.CreateScale(escala) *

  34:                 Matrix.CreateTranslation(posicion);

  35:  

  36:             efecto.View = vista;

  37:             efecto.Projection = proyeccion;

  38:         }

  39:         mesh.Draw();

  40:     }

  41: }

 La parte interesante es la que compobamos si el nombre de la malla es “aspas”, en cuyo caso lo rotamos en su eje Y.

Ejemplo 2: Animando la tierra y la luna

Este vamos a complicarlo un poco, pero tampoco mucho eh 🙂  Lo que haremos va a ser poner en evidencia el orden de la multiplicación de las matrices.

En este caso he creado una simple esfera con el 3D Max, y le he asignado primero la textura de la Tierra, y he exportado a FBX, y después lo mismo con la Luna. Estas texturas también pueden encontrarse rápidamente en Internet.

A la clase que he llamado “ModeloExtendido”, que es la que se encarga de almacenar la información del modelo y pintarlo, le he añadido las siguientes matrices (la matriz World pasa a ser privada):

   1: public Matrix rotacion;

   2: public Matrix traslacion;

   3: public Matrix orbitacion;

   4: public Matrix escala;

 

Ahora, desde fuera de la clase podemos modificar cualquiera de estas matrices en el orden que queramos, sólo en el Draw tendremos que tener en cuenta el orden de multiplicación de las mismas:

   1: public void Draw(GameTime gameTime, Matrix vista, Matrix proyeccion) 

   2: {

   3:     modelo.CopyAbsoluteBoneTransformsTo(transformaciones);

   4:  

   5:     foreach(ModelMesh mesh in modelo.Meshes)

   6:     {

   7:         foreach (BasicEffect efecto in mesh.Effects) 

   8:         {

   9:             efecto.EnableDefaultLighting();

  10:  

  11:             efecto.World = transformaciones[mesh.ParentBone.Index] * ObtenerWorld();

  12:             efecto.View = vista;

  13:             efecto.Projection = proyeccion;

  14:         }

  15:  

  16:         mesh.Draw();

  17:     }

  18: }

  19:  

  20: private Matrix ObtenerWorld() 

  21: {

  22:     return world * escala * rotacion * orbitacion * traslacion;

  23: }

 

Con su salsa y demás, el resultado es el vídeo que habéis visto. El código está disponible para descargar.

2 comentarios en “[XNA] Animaciones básicas en 3D”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *