我正在尝试以编程方式在XNA中为我的角色模型制作动画。我从这里查看代码示例开始: http://create.msdn.com/en-US/education/catalog/sample/skinned_model 通过编辑此示例中的代码,我能够让角色按照我喜欢的方式移动。然后我尝试使用基本代码创建一个单独的程序来执行此操作。 (我从例子中借用了“dude”模型)。
这是我的代码:
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);
}
}
}
我无法弄清楚为什么这不起作用。如果我将boneId(在UpdateBoneTransforms中)设置为0,整个模型会按预期移动,但如果我将boneId更改为其他任何东西,他只会站在原始位置。即使我没有更新孩子,我也会期待一个关节可以移动,但我甚至无法实现这一点。我忘记了重要的事情吗?
答案 0 :(得分:1)
您的代码似乎正确,但我敢打赌您没有通过SkinnedModelProcessor加载模型。如果不是,则使用BasicEffect着色器绘制模型,该着色器不支持模型上的蒙皮信息。
所以:
1)验证dude.fbx使用SkinnedModelProcessor作为内容处理器。为此,您必须在内容项目中包含对SkinnedModelPipeline的引用。使用此处理器将使您的模型使用正确的着色器(SkinnedModel.fx)。
2)您必须使用AnimationPlayer来获取模型姿势(而不是使用CopyAbsoluteBoneTransformsTo)。如果您不需要动画,请不要更新()动画播放器。
3)对结果姿势(矩阵[])做任何你想要的变换。
4)使用pose(骨骼)和视图和投影矩阵配置SkinnedModelEffect:
effect.Parameters["Bones"].SetValue(bones);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
5)画画。
所有这些东西都在皮肤模型示例代码中,您需要它来使用皮肤数据。