Mogre学习笔记(七)

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.更换模型。

你可能感兴趣的:(windows,脚本,Go)