2011-07-26 3 views
2

J'essaie d'animer par programmation mon modèle de caractères dans XNA. J'ai commencé par regarder l'exemple de code ici: http://create.msdn.com/en-US/education/catalog/sample/skinned_model En éditant le code dans cet exemple, j'ai réussi à faire bouger le personnage comme je l'aimais. Ensuite, j'ai essayé de faire un programme séparé avec juste le code essentiel pour le faire. (J'ai emprunté le modèle "mec" de l'exemple).Je ne parviens pas à animer des modèles d'image de manière indépendante dans XNA

Voici mon code:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 

namespace WindowsGame1 
{ 
public class Game1 : Microsoft.Xna.Framework.Game 
{ 
    GraphicsDevice device; 
    GraphicsDeviceManager graphics; 
    Model myModel; 
    float aspectRatio; 

    public Matrix[] boneTransforms; 
    public Matrix[] originalBoneTransforms; 
    Matrix[] worldTransforms; 

    float pos = 0; 

    public Game1() 
    { 
     graphics = new GraphicsDeviceManager(this); 
     Content.RootDirectory = "Content"; 
    } 

    protected override void Initialize() 
    { 
     base.Initialize(); 
    } 

    protected override void LoadContent() 
    { 
     device = graphics.GraphicsDevice; 
     myModel = Content.Load<Model>("dude"); 

     worldTransforms = new Matrix[myModel.Bones.Count]; 
     boneTransforms = new Matrix[myModel.Bones.Count]; 
     originalBoneTransforms = new Matrix[myModel.Bones.Count]; 
     myModel.CopyAbsoluteBoneTransformsTo(boneTransforms); 
     myModel.CopyAbsoluteBoneTransformsTo(originalBoneTransforms); 


     aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio; 
    } 

    protected override void Update(GameTime gameTime) 
    { 
     UpdateBoneTransforms(); 
     UpdateWorldTransforms(); 

     base.Update(gameTime); 
    } 

    public void UpdateBoneTransforms() 
    { 
     pos += .1f; 
     int boneId = 32; //Right Arm 
     boneTransforms[boneId] = Matrix.CreateTranslation(new Vector3(0, pos, 0)) * originalBoneTransforms[boneId]; 
    } 

    public void UpdateWorldTransforms() 
    { 
     // Root bone. 
     worldTransforms[0] = boneTransforms[0]; 

     // Child bones. 
     for (int bone = 1; bone < worldTransforms.Length; bone++) 
     { 
      int parentBone = myModel.Bones[bone].Parent.Index; 

      worldTransforms[bone] = boneTransforms[bone] * 
             worldTransforms[parentBone]; 
     } 
    } 

    protected override void Draw(GameTime gameTime) 
    { 
     GraphicsDevice.Clear(Color.CornflowerBlue); 

     Matrix view = Matrix.CreateLookAt(new Vector3(0, 150, 125), 
        Vector3.Zero, Vector3.Up); 
     Matrix projection = Matrix.CreatePerspectiveFieldOfView(
        MathHelper.ToRadians(45.0f), aspectRatio, 
        1.0f, 10000.0f); 

     foreach (ModelMesh mesh in myModel.Meshes) 
     { 
      foreach (BasicEffect meshEffect in mesh.Effects) 
      { 
       meshEffect.EnableDefaultLighting(); 
       meshEffect.World = worldTransforms[mesh.ParentBone.Index]; 
       meshEffect.View = view; 
       meshEffect.Projection = projection; 

       meshEffect.SpecularColor = new Vector3(0.25f); 
       meshEffect.SpecularPower = 16; 
      } 
      mesh.Draw(); 
     } 

     base.Draw(gameTime); 
    } 
} 
} 

Je ne peux pas comprendre pourquoi cela ne fonctionne pas. Si je mets boneId (dans UpdateBoneTransforms) à 0, le modèle entier se déplace comme prévu, mais si je change boneId en quoi que ce soit d'autre, il reste immobile dans la position d'origine. Je m'attendais à ce qu'une seule articulation bouge même si je n'ai pas mis à jour les enfants, mais je n'arrive même pas à le faire. Suis-je en train d'oublier quelque chose d'important?

Répondre

1

Votre code semble correct mais je parie que vous ne chargez pas le modèle via le SkinnedModelProcessor. Si ce n'est pas le cas, votre modèle est dessiné avec un shader BasicEffect qui ne prend pas en charge les informations de skinning sur votre modèle.

So:

1) Vérifier que dude.fbx utilise SkinnedModelProcessor comme processeur de contenu. Pour cela, vous devrez inclure une référence à SkinnedModelPipeline sur votre projet de contenu. L'utilisation de ce processeur permettra à votre modèle d'utiliser le shader approprié (SkinnedModel.fx).

2) Vous devrez utiliser un AnimationPlayer pour obtenir la pose du modèle (au lieu d'utiliser CopyAbsoluteBoneTransformsTo). Ne mettez pas à jour() le AnimationPlayer si vous n'avez pas besoin d'animation.

3) À la pose résultante (une matrice []) faites la transformation que vous voulez.

4) Configurez le SkinnedModelEffect avec la pose (os) et vue et projection des matrices:

effect.Parameters["Bones"].SetValue(bones); 
effect.Parameters["View"].SetValue(view); 
effect.Parameters["Projection"].SetValue(projection); 

5) Draw.

Tout cela se trouve dans l'exemple de code du Skinned Model et vous en avez besoin pour utiliser les données de skinning.

+0

Merci, cela m'a beaucoup aidé. – user788497

+0

De rien. Cela a fonctionné finalement? –

Questions connexes