Mogre学习笔记(七)

来源:互联网 发布:淘宝第一次自动回复 编辑:程序博客网 时间:2024/06/08 15:11
 Section 7: Skeleton animation

今天试图添加多个模型的骨骼动画,出了一些问题,郁闷了一上午之后终于找到了问题所在,下面我们就首先给出Tutorial上的一段代码,看看如何使用骨骼动画,再说说我遇到的问题吧n_n

using System;using System.Drawing;using Math3D;using OgreDotNet;using System.Collections.Generic;namespace OgreDotNetTutorial{   public class MoveDemoApplication : ExampleApplication   {       protected Entity mEntity = null;    // The entity of the object we are animating       protected SceneNode mNode = null;   // The SceneNode of the object we are moving       protected AnimationState mAnimationState = null; //The AnimationState the moving object       protected float mDistance = 0.0f;              //The distance the object has left to travel       protected Vector3 mDirection = Vector3.Zero;   // The direction the object is moving       protected Vector3 mDestination = Vector3.Zero; // The destination the object is moving towards       protected LinkedList<Vector3> mWalkList = null; // A doubly linked containing the waypoints       protected float mWalkSpeed = 35.0f;  // The speed at which the object is moving       protected bool mWalking = false;     // Whether or not the object is moving       protected override void CreateScene()       {           //temporary entity and SceneNode           Entity ent;           SceneNode node;           // Set the default lighting and background color           mSceneManager.SetAmbientLight(Color.White);           mViewport.SetBackgroundColour(Color.Black);           // Create the Robot entity           mEntity = mSceneManager.CreateEntity("Robot", "robot.mesh");           // Create the Robot's SceneNode           mNode = mSceneManager.GetRootSceneNode().CreateChildSceneNode("RobotNode",               new Vector3(0.0f, 0.0f, 25.0f));           mNode.AttachObject(mEntity);           // Create the walking list           mWalkList = new LinkedList<Vector3>();           mWalkList.AddLast(new Vector3(550.0f, 0.0f, 50.0f));           mWalkList.AddLast(new Vector3(-100.0f, 0.0f, -200.0f));           mWalkList.AddLast(new Vector3(0.0f, 0.0f, 25.0f));           // Create knot objects so we can see movement           ent = mSceneManager.CreateEntity("Knot1", "knot.mesh");           node = mSceneManager.GetRootSceneNode().CreateChildSceneNode("Knot1Node",               new Vector3(0.0f, -10.0f, 25.0f));           node.AttachObject(ent);           node.SetScale(0.1f, 0.1f, 0.1f);           //           ent = mSceneManager.CreateEntity("Knot2", "knot.mesh");           node = mSceneManager.GetRootSceneNode().CreateChildSceneNode("Knot2Node",               new Vector3(550.0f, -10.0f, 50.0f));           node.AttachObject(ent);           node.SetScale(0.1f, 0.1f, 0.1f);           //           ent = mSceneManager.CreateEntity("Knot3", "knot.mesh");           node = mSceneManager.GetRootSceneNode().CreateChildSceneNode("Knot3Node",               new Vector3(-100.0f, -10.0f, -200.0f));           node.AttachObject(ent);           node.SetScale(0.1f, 0.1f, 0.1f);           // Set the camera to look at our handywork           mCamera.SetPosition(90.0f, 280.0f, 535.0f);           mCamera.Pitch(new Radian(new Degree(210.0f)));           mCamera.Yaw(new Radian(new Degree(-15.0f)));           mCamera.Roll(new Radian(new Degree(180.0f)));           // Set idle animation           mAnimationState = mEntity.GetAnimationState("Idle");           mAnimationState.SetLoop(true);           mAnimationState.SetEnabled(true);       }       protected bool nextLocation()       {           if (mWalkList.Count == 0)               return false;           return true;       }       protected override bool FrameStarted(FrameEvent e)       {           if (mRenderWindow.Closed || mDone) return false;           mDeltaTime = e.TimeSinceLastFrame;           UpdateDebugOverlay();           if (!mWalking)           //either we've not started walking or reached a way point           {               //check if there are places to go               if (nextLocation())               {                   //Start the walk animation                   mAnimationState = mEntity.GetAnimationState("Walk");                   mAnimationState.SetLoop(true);                   mAnimationState.SetEnabled(true);                   mWalking = true;                   //Update the destination using the walklist.                   LinkedListNode<Vector3> tmp;  //temporary listNode                   mDestination = mWalkList.First.Value; //get the next destination.                   tmp = mWalkList.First; //save the node that held it                   mWalkList.RemoveFirst(); //remove that node from the front of the list                   mWalkList.AddLast(tmp);  //add it to the back of the list.                   //update the direction and the distance                   mDirection = mDestination - mNode.GetPosition();                   mDistance = mDirection.Normalize();               }//if(nextLocation())               else //nowhere to go. set the idle animation. (or Die)               {                   mAnimationState = mEntity.GetAnimationState("Idle");                   //mAnimationState = mEntity.GetAnimationState("Die");                   //mAnimationState.SetLoop(false);               }           }           else //we're in motion           {               //determine how far to move this frame               float move = mWalkSpeed * mDeltaTime;               mDistance -= move;               if (mDistance <= 0.0f)               {                   mNode.SetPosition(mDestination);                   mDirection = Vector3.Zero;                   //Check to see if we've arrived at a waypoint                   if (mDistance <= 0.0f)                   {                       //set our node to the destination we've just reached & reset direction to 0                       mNode.SetPosition(mDestination);                       mDirection = Vector3.Zero;                       mWalking = false;                   }//if(mDistance <= 0.0f)               }               else               {                   //movement code goes here                   mNode.Translate(mDirection * move);                   //Rotation code goes here                   Vector3 src = mNode.GetOrientation() * Vector3.UnitX;                   if ((1.0f + src.Dot(mDirection)) < 0.0001f)                   {                       mNode.Yaw(180.0f);                   }                   else                   {                       Quaternion quat = src.GetRotationTo(mDirection);                       mNode.Rotate(quat);                   }               }           }           //Update the Animation State.           mAnimationState.AddTime(mDeltaTime);           return true;       }       [MTAThread]       static void Main(string[] args)       {           using (MoveDemoApplication app = new MoveDemoApplication())           {               app.Start();           }       }   }}

首先,注意红色代码部分,每个Entity对象都有一个GetAnimationState方法,用于取得其Animation State,robot.skeleton有Walk和Idle两种属性,设置loop true和enabled true,调用AddTime方法以设置动画速度。AddTime方法必须在FrameStarted或者FrameEnded中被调用,以使其在render时被刷新。

需要注意的是,骨骼动画是已经设置好的,代码只能让其按照脚本动作。

蓝色代码部分是设置位置和转向的。

这样,我们的robot就可以走动了。但是,今天,我试图使用ninja.mesh来做骨骼动画,却发现VS崩溃,无法调试,看代码,断点……整整一上午都没有找到问题所在,直到自己很巧合的在Windows下运行给出了错误提示:其实每个.skeleton文件中,定义的Animation State不一定一样,ninja.skeleton中就没有Idle这种状态,get当然会出错。

找到问题所在就容易解决了,两种方法:1.try catch 2.更换模型。