36实现模型跟随地形的效果.docx
- 文档编号:27870559
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:19
- 大小:32.76KB
36实现模型跟随地形的效果.docx
《36实现模型跟随地形的效果.docx》由会员分享,可在线阅读,更多相关《36实现模型跟随地形的效果.docx(19页珍藏版)》请在冰豆网上搜索。
36实现模型跟随地形的效果
36.实现模型跟随地形的效果
这个教程是对引擎中的示例Sample03的一点解释,这个示例实现了一个坦克模型跟随地形移动的效果。
因为我要控制坦克的炮塔、炮管、轮子的ModelMesh,所以需要从ModelSceneNode类继承实现一个tankModel类,因为事先不可能知道所使用的模型的结构,所以这个类没有放在引擎中,在实际制作游戏时需要从引擎的ModelSceneNode基类派生出你所使用的模型的类,代码如下:
namespaceSample03
{
///
///坦克模型,从ModelSceneNode继承,添加了层次模型的支持
///
publicclasstankModel:
ModelSceneNode
{
#region成员变量、属性和构造函数
//需要跟随的地形
SimpleTerrainSceneNodeterrain;
//坦克各部件的Bone。
ModelBoneturretBone;
ModelBonecannonBone;
ModelBonelSteerEngineBone;
ModelBonerSteerEngineBone;
ModelBoneleftBackWheelBone;
ModelBonerightBackWheelBone;
ModelBoneleftFrontWheelBone;
ModelBonerightFrontWheelBone;
//坦克各部件Bone的转换矩阵
MatrixturretTransform;
MatrixcannonTransform;
MatrixlSteerEngineTransform;
MatrixrSteerEngineTransform;
MatrixleftBackWheelTransform;
MatrixrightBackWheelTransform;
MatrixleftFrontWheelTransform;
MatrixrightFrontWheelTransform;
//车轮自转的旋转矩阵
MatrixwheelRollMatrix;
//各部件的旋转量
floatturretRotationValue;
floatcannonRotationValue;
floatsteerRotationValue;
floatwheelRotationValue;
///
///炮管、炮塔旋转的最大角速度
///
publicconstfloatMaxCannonSpeed=1f;
///
///炮塔的旋转范围
///
privateconstfloatMaxTurretAngle=1.0f;
privateconstfloatMinTurretAngle=-1.0f;
///
///炮管的旋转范围
///
privateconstfloatMaxCannonAngle=0.0f;
privateconstfloatMinCannonAngle=-0.9f;
///
///获取或设置车轮的旋转量
///
publicfloatWheelRotationValue
{
get{returnwheelRotationValue;}
set{wheelRotationValue=value;}
}
///
///获取或设置前轮轴的旋转量
///
publicfloatSteerRotationValue
{
get{returnsteerRotationValue;}
set{steerRotationValue=value;}
}
///
///获取或设置炮塔旋转量
///
publicfloatTurretRotation
{
get{returnturretRotationValue;}
set
{
if(value>MaxTurretAngle)
turretRotationValue=MaxTurretAngle;
elseif(value turretRotationValue=MinTurretAngle; else turretRotationValue=value; } } /// ///获取或设置炮管旋转量 /// publicfloatCannonRotation { get{returncannonRotationValue;} set { if(value>MaxCannonAngle) cannonRotationValue=MaxCannonAngle; elseif(value cannonRotationValue=MinCannonAngle; else cannonRotationValue=value; } } /// ///创建一个ModelSceneNode对象。 /// /// /// publictankModel(StunXnaGEengine,ScenesetScene,stringmodelAssetName,SimpleTerrainSceneNodeterrain) : base(engine,setScene,modelAssetName) { this.terrain=terrain; } #endregion /// ///初始化节点。 /// publicoverridevoidInitialize() { base.Initialize(); //获取坦克各部件的Bone。 turretBone=model.Bones["turret_geo"]; cannonBone=model.Bones["canon_geo"]; lSteerEngineBone=model.Bones["l_steer_geo"]; rSteerEngineBone=model.Bones["r_steer_geo"]; leftBackWheelBone=model.Bones["l_back_wheel_geo"]; rightBackWheelBone=model.Bones["r_back_wheel_geo"]; leftFrontWheelBone=model.Bones["l_front_wheel_geo"]; rightFrontWheelBone=model.Bones["r_front_wheel_geo"]; //获取坦克各部件的转换矩阵 turretTransform=turretBone.Transform; cannonTransform=cannonBone.Transform; lSteerEngineTransform=lSteerEngineBone.Transform; rSteerEngineTransform=rSteerEngineBone.Transform; leftBackWheelTransform=leftBackWheelBone.Transform; rightBackWheelTransform=rightBackWheelBone.Transform; leftFrontWheelTransform=leftFrontWheelBone.Transform; rightFrontWheelTransform=rightFrontWheelBone.Transform; } publicoverridevoidUpdate(GameTimegameTime) { base.Update(gameTime); //根据旋转量重新计算变换矩阵 turretBone.Transform=Matrix.CreateRotationY(turretRotationValue)*turretTransform; cannonBone.Transform=Matrix.CreateRotationX(cannonRotationValue)*cannonTransform; lSteerEngineBone.Transform=Matrix.CreateRotationY(steerRotationValue)*lSteerEngineTransform; rSteerEngineBone.Transform=Matrix.CreateRotationY(steerRotationValue)*rSteerEngineTransform; wheelRollMatrix*=Matrix.CreateRotationX(wheelRotationValue); leftBackWheelBone.Transform=Matrix.CreateRotationX(wheelRotationValue)*leftBackWheelTransform; rightBackWheelBone.Transform=Matrix.CreateRotationX(wheelRotationValue)*rightBackWheelTransform; leftFrontWheelBone.Transform=Matrix.CreateRotationX(wheelRotationValue)*leftFrontWheelTransform; rightFrontWheelBone.Transform=Matrix.CreateRotationX(wheelRotationValue)*rightFrontWheelTransform; } /// ///绘制坦克。 /// /// publicoverrideintDraw(GameTimegameTime,booluseReflect) { model.CopyAbsoluteBoneTransformsTo(modelTransforms); returnbase.Draw(gameTime,useReflect); } } } 这个类主要添加了要控制的ModelMesh的信息,因为要实现地形跟随,还需要添加地形的引用。 具体解释首先可参见简单动画-坦克1,然后是较难的4.8可视化模型骨骼结构和4.9使Bone独立运动: 模型动画。 接着还要从相机类CameraSceneNode.cs中派生出跟随相机类ChaseCameraSceneNode.cs,代码如下: usingSystem; usingMicrosoft.Xna.Framework; usingMicrosoft.Xna.Framework.Input; usingStunEngine.Controllers; usingStunEngine.SceneManagement; namespaceStunEngine.SceneNodes { /// ///照相机类型 /// publicenumCameraType { ThirdPersonFar, ThirdPersonClose, HighView } publicclassChaseCameraSceneNode: CameraSceneNode { /// ///要跟踪的对象 /// SceneNodenode; /// ///跟踪相机类型枚举 /// publicCameraTypecurrentCameraType=CameraType.ThirdPersonFar; /// ///相机位置偏离模型的距离。 /// Vector3CameraPositionOffset; /// ///相机观察目标偏离的距离。 /// Vector3CameraTargetOffset; /// ///创建一个跟随相机 /// /// /// /// publicChaseCameraSceneNode(StunXnaGEengine,ScenesetScene,SceneNodenode) : base(engine,setScene,Vector3.Zero,Vector3.Forward) { this.node=node; } /// ///更新视矩阵 /// /// publicoverridevoidUpdateViewMatrix(boolupdateProjection) { if(Input.KeyboardKeyJustPressed(Keys.Tab)) { currentCameraType+=1; if(currentCameraType>CameraType.HighView) currentCameraType=CameraType.ThirdPersonFar; } Vector3cameraRotatedPosition; Vector3cameraFinalPosition; Vector3cameraFinalTargetPosition; switch(currentCameraType) { caseCameraType.ThirdPersonFar: CameraPositionOffset=newVector3(0,15,-25); CameraTargetOffset=newVector3(0,10,0); break; caseCameraType.ThirdPersonClose: CameraPositionOffset=newVector3(0,6,-9); CameraTargetOffset=newVector3(0,6,0); break; caseCameraType.HighView: CameraPositionOffset=newVector3(0,40,-1); CameraTargetOffset=newVector3(0,0,0); break; default: thrownewInvalidOperationException("照相机类型不存在"); } cameraFinalTargetPosition=node.pose.Position+CameraTargetOffset; cameraRotatedPosition=Vector3.Transform(CameraPositionOffset,Quaternion.CreateFromAxisAngle(Vector3.Up,MathHelper.ToRadians(-node.AngleRotation.Y))); cameraFinalPosition=node.pose.Position+cameraRotatedPosition; viewMatrix=Matrix.CreateLookAt(cameraFinalPosition,cameraFinalTargetPosition,Vector3.Up); //updateProjection为true则重新设置真实投影矩阵和逻辑投影矩阵 if(updateProjection) { //真实视锥体,基于很大的真实远裁平面 projectionMatrix=Matrix.CreatePerspectiveFieldOfView(cameraFov,AspectRatio,nearPlane,internalFarPlane); internalFarPlaneBoundingFrustum.Matrix=viewMatrix*projectionMatrix; //基于逻辑远裁平面的逻辑视锥体。 farPM=Matrix.CreatePerspectiveFieldOfView(cameraFov,AspectRatio,nearPlane,FarPlane); farPlaneBoundingFrustum.Matrix=viewMatrix*farPM; } hasChanged=true; } } } 这个类的作用是根据引用的模型的位置改变相机的属性,具体实现原理可参见XNA的帮助文件中的HowTo: MakeaThird-PersonCamera。 地形跟随是指让模型根据其下的地形调整高度,更难的是调整模型的倾斜程度,详细解释请参见4.17根据地形正确倾斜模型,代码放在了从ModelController继承的tankModelController类中,代码如下: namespaceSample03 { /// ///坦克模型控制器,从ModelController类继承,实现了坦克跟随地形的效果 /// publicclasstankModelController: ModelController { #region构造函数和成员变量 privatetankModeltankModel; SimpleTerrainSceneNodeterrain; privateconstintWALK_HEIGHT=5; /// ///创建一个新ModelController对象。 /// /// publictankModelController(StunXnaGEengine,SimpleTerrainSceneNodeterrain): base(engine) { this.terrain=terrain; } #endregion /// ///主控制逻辑 /// /// publicoverridevoidControllerAction(GameTimegameTime) { if(tankModel==null) { tankModel=(tankModel)controlledNode; } //每帧流逝的时间,秒为单位 floattimeDifference=(float)gameTime.ElapsedGameTime.TotalMilliseconds/1000.0f; ProcessInput(timeDifference); } privatevoidProcessInput(floatelapsedTime) { floatmovement=0; floatrotation=0; //坦克相机每帧旋转和移动距离 floatrotationPerFrame=elapsedTime*tankModel.RotationSpeed; floatmovementPerFrame=elapsedTime*tankModel.MovementSpeed; if(Input.KeyboardUpPressed||Input.Keyboard.IsKeyDown(Keys.W)) { movement+=movementPerFrame; //轮子的转动角度 floattheta=movementPerFrame/1.8f; tankModel.WheelRotationValue+=theta; } if(Input.KeyboardDownPressed||Input.Keyboard.IsKeyDown(Keys.S)) { movement-=movementPerFrame; //轮子的转动角度 floattheta=movementPerFrame/1.8f; tankModel.WheelRotationValue-=theta; } if(Input.KeyboardRightPressed||Input.Keyboard.IsKeyDown(Keys.D)) { rotation+=rotationPerFrame; //前轮轴的转动角度 tankModel.SteerRotationValue=-
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 36 实现 模型 跟随 地形 效果
![提示](https://static.bdocx.com/images/bang_tan.gif)