层次模型动画—坦克2

XNA使用ModelBone类对象表示一个部件,如前所述,一个部件是一个刚性物体,部件中的所有顶点同时只能做一种运动,即部件中的顶点都具有相同的世界变换矩阵,部件具有相同的材质和纹理。一个部件必须有一个ModelMesh对象,ModelMesh对象用于在计算机显示器屏幕显示该部件的外观。ModelBone类的常用属性如下:

.x文件中定义的部件,必须在3D程序中转变为ModelBone类的对象,才能最终在显示器屏幕显示。使用ContentManager类方法Load来装载包含层次关系的.x文件:

Model tankModel=Content.Load<Model>(“tank”);

该方法将创建在.x文件中定义的每一个部件的ModelBone类对象,部件也称为骨骼(bone)。Model类对象记录一个3D模型的所有ModelBone类对象、ModelBone类对象所使用的ModelMesh类对象以及ModelBone类对象的阶层关系。Model类的一些常用属性和方法如下:

用如下代码得到这个矩阵数组:

Matrix[] boneTransforms;
boneTransforms=new Matrix[tankModel.Bones.Count]; 
tankModel.CopyAbsoluteTransformsTo[boneTransforms];

XNA代码

1. 在Game1类中添加变量:

Model tankModel; Matrix[] boneTransforms;

//分别引用坦克Body、Turret和Gun部件 
ModelBone BodyBone, TurretBone, GunBone; 

//坦克Body、Turret和Gun部件的变换矩阵 
Matrix BodyTransform, TurretTransform, GunTransform; 

//分别为坦克Body部件的移动距离,炮塔旋转弧度,火炮上下转动弧度 
float BodyMove = 0, GunUpDown = 0, TurreRound = 0; 2;

修改Game1类的LoadContent方法:

tankModel = Content.Load<Model>("Tank"); 
		
//得到坦克Body部件的ModelBone对象 
BodyBone = tankModel.Bones["Body"]; 
TurretBone = tankModel.Bones["Turret"]; 
GunBone = tankModel.Bones["Gun"]; 

//得到部件的初始世界矩阵 
BodyTransform = BodyBone.Transform; 
TurretTransform = TurretBone.Transform; 
GunTransform = GunBone.Transform; 

boneTransforms = new Matrix[tankModel.Bones.Count]; 

3. 修改Update方法:

CheckInput(); 
GunBone.Transform = Matrix.CreateRotationX(GunUpDown) * GunTransform; 
TurretBone.Transform = Matrix.CreateRotationY(TurreRound) * TurretTransform; 
BodyBone.Transform = Matrix.CreateTranslation(0, BodyMove,0) * BodyTransform; 

tankModel.CopyAbsoluteBoneTransformsTo(boneTransforms); 

base.Update(gameTime); 

并添加CheckInput方法:

KeyboardState newState = Keyboard.GetState(); 

//键盘上下控制坦克的移动 
if (newState.IsKeyDown(Keys.Down)) 
    BodyMove += 0.5f; 
if (newState.IsKeyDown(Keys.Up)) 
    BodyMove -= 0.5f; 
    
//键盘PageUp,PageDown控制炮管上下
if (newState.IsKeyDown(Keys.PageUp)) 
{
    GunUpDown -= 0.05f; 
    if (GunUpDown < -0.6) 
        GunUpDown = -0.6f; 
}
if (newState.IsKeyDown(Keys.PageDown)) 
{
    GunUpDown += 0.05f; 
    if (GunUpDown > 0) 
        GunUpDown = 0.01f; 
}

//键盘左右控制炮塔旋转
if (newState.IsKeyDown(Keys.Left)) 
{
    TurreRound -= 0.05f; 
    if (TurreRound < -1f) 
        TurreRound = -1f; 
}
if (newState.IsKeyDown(Keys.Right)) 
{
    TurreRound += 0.05f; 
    if (TurreRound > 1f) 
        TurreRound = 1f; 
} 

4. Draw方法中的代码如下:

GraphicsDevice.Clear(Color.CornflowerBlue); 

foreach (ModelMesh mesh in tankModel.Meshes) 
{
    foreach (BasicEffect effect in mesh.Effects) 
    { 
        effect.EnableDefaultLighting(); 
        effect.World = boneTransforms[mesh.ParentBone.Index]; 
        effect.View = Matrix.CreateLookAt(new Vector3(0, 100.0f, 200.0f), Vector3.Zero ,Vector3 .Up ); 
        effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 
        (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height, 1.0f, 400.0f); 
    }
    mesh.Draw(); 
}
base.Draw(gameTime); 

运行程序后,可使用键盘上下控制坦克前进后退,键盘PageUp,PageDown控制炮管上下,/键盘左右控制炮塔旋转,截图如下:

程序截图


发布时间:2009/6/8 10:19:42  阅读次数:7028

2006 - 2024,推荐分辨率1024*768以上,推荐浏览器Chrome、Edge等现代浏览器,截止2021年12月5日的访问次数:1872万9823 站长邮箱

沪ICP备18037240号-1

沪公网安备 31011002002865号