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
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("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
{
}
}
//Update the Animation State.
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.更换模型。
&spm=1001.2101.3001.5002&articleId=83264158&d=1&t=3&u=0af5a8e396344d788f8eec9c35551415)
1662

被折叠的 条评论
为什么被折叠?



