标签:
首先参照这里配置好工程。
添加一个类CharacterApplication,还有main.cpp.
直接贴代码了。
characterapplication.h
#pragma once
#include <OgreCamera.h>
#include <OgreEntity.h>
#include <OgreLogManager.h>
#include <OgreRoot.h>
#include <Ogre.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>
#include <OgreConfigFile.h>
#include <OgreTextureManager.h>
#include <OgreMaterialManager.h>
#include <OgreWindowEventUtilities.h>
#include <conio.h>
class CharactorApplication
{
public:
CharactorApplication();
~CharactorApplication();
void go();
private:
bool startup();
void loadResouces();
void createScene();
void createCamera();
Ogre::SceneManager* mSceneManager;
Ogre::Root* mRoot;
Ogre::RenderWindow* mWindow;
};
characterapplication.cpp
#include "charactorapplication.h"
CharactorApplication::CharactorApplication()
{
mSceneManager = NULL;
mRoot = NULL;
}
CharactorApplication::~CharactorApplication()
{
delete mRoot;
}
bool CharactorApplication::startup()
{
mRoot = new Ogre::Root("plugins_d.cfg");
if (!mRoot->showConfigDialog())
{
return false;
}
mWindow = mRoot->initialise(true, "Character Control");
mSceneManager = mRoot->createSceneManager(Ogre::ST_GENERIC);
return true;
}
void CharactorApplication::createCamera()
{
Ogre::Camera* camera = mSceneManager->createCamera("Camera");
camera->setPosition(Ogre::Vector3(0, 0, 30));
camera->lookAt(Ogre::Vector3(0, 0, 0));
camera->setNearClipDistance(5);
Ogre::Viewport* viewport = mWindow->addViewport(camera);
viewport->setBackgroundColour(Ogre::ColourValue(1.0f, 1.0f, 0.0f));
camera->setAspectRatio(Ogre::Real(viewport->getActualWidth()) / Ogre::Real(viewport->getActualHeight()));
}
void CharactorApplication::loadResouces()
{
//Load resources
Ogre::ConfigFile cf;
cf.load("resources_d.cfg");
// Go through all sections & settings in the file
Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
Ogre::String secName, typeName, archName;
while (seci.hasMoreElements())
{
secName = seci.peekNextKey();
Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
Ogre::ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
archName, typeName, secName);
}
}
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}
void CharactorApplication::createScene()
{
mSceneManager->setAmbientLight(Ogre::ColourValue(1, 1, 1));
Ogre::Entity* sinbadEnt = mSceneManager->createEntity("Sinbad.mesh");
mSceneManager->getRootSceneNode()->attachObject(sinbadEnt);
}
void CharactorApplication::go()
{
if (startup())
{
loadResouces();
createCamera();
createScene();
mRoot->startRendering();
_cprintf("Done");
}
}工程目录下面别忘了把resources_d.cfg和plugins_d.cfg拷贝过来。
运行一下,结果如下:
最终场景如下
地面和天空盒
Ogre::Plane plane(Ogre::Vector3::UNIT_Y, -25);
Ogre::MeshManager::getSingleton().createPlane("plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane, 1500, 1500, 20, 20, true, 1, 5, 5, Ogre::Vector3::UNIT_Z);
Ogre::Entity* plantEnt = mSceneManager->createEntity("LightPlaneEntity", "plane");
plantEnt->setMaterialName("Examples/BeachStones");
mSceneManager->getRootSceneNode()->createChildSceneNode()->attachObject(plantEnt);
mSceneManager->setSkyBox(true, "Examples/SpaceSkyBox", 5000, true);void CharactorApplication::createGrass()
{
//Create grass
Ogre::ManualObject* manual = mSceneManager->createManualObject("grass");
manual->begin("Examples/GrassBlades", Ogre::RenderOperation::OT_TRIANGLE_LIST);
manual->position(5.0, 0.0, 0.0);
manual->textureCoord(1, 1);
manual->position(-5.0, 10.0, 0.0);
manual->textureCoord(0, 0);
manual->position(-5.0, 0.0, 0.0);
manual->textureCoord(0, 1);
manual->position(5.0, 10.0, 0.0);
manual->textureCoord(1, 0);
manual->position(2.5, 0.0, 4.3);
manual->textureCoord(1, 1);
manual->position(-2.5, 10.0, -4.3);
manual->textureCoord(0, 0);
manual->position(-2.0, 0.0, -4.3);
manual->textureCoord(0, 1);
manual->position(2.5, 10.0, 4.3);
manual->textureCoord(1, 0);
manual->position(2.5, 0.0, -4.3);
manual->textureCoord(1, 1);
manual->position(-2.5, 10.0, 4.3);
manual->textureCoord(0, 0);
manual->position(-2.0, 0.0, 4.3);
manual->textureCoord(0, 1);
manual->position(2.5, 10.0, -4.3);
manual->textureCoord(1, 0);
manual->index(0);
manual->index(1);
manual->index(2);
manual->index(0);
manual->index(3);
manual->index(1);
manual->index(4);
manual->index(5);
manual->index(6);
manual->index(4);
manual->index(7);
manual->index(5);
manual->index(8);
manual->index(9);
manual->index(10);
manual->index(8);
manual->index(11);
manual->index(9);
manual->end();
manual->convertToMesh("BladesOfGrass");
Ogre::StaticGeometry* field = mSceneManager->createStaticGeometry("FieldOfGrass");
for (int i = -25; i < 25; i++)
{
for (int j = -25; j < 25; j++)
{
Ogre::Entity * ent = mSceneManager->createEntity("BladesOfGrass");
field->addEntity(ent, Ogre::Vector3(i * 3, -25, j * 3));
}
}
field->build();
} Ogre::ParticleSystem::setDefaultNonVisibleUpdateTimeout(5); // set nonvisible timeout
Ogre::ParticleSystem* ps;
ps = mSceneManager->createParticleSystem("Nimbus", "Examples/GreenyNimbus");
mSceneManager->getRootSceneNode()->attachObject(ps); mSceneManager->setAmbientLight(Ogre::ColourValue(0, 0, 0));
mSceneManager->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
Ogre::Light* directionalLight = mSceneManager->createLight("directionalLight");
directionalLight->setType(Ogre::Light::LT_DIRECTIONAL);
directionalLight->setDiffuseColour(Ogre::ColourValue(0.8f, 0.8f, 0.8f));
directionalLight->setSpecularColour(Ogre::ColourValue(.25, .25, 0));
directionalLight->setDirection(Ogre::Vector3(-1, -1, -1));
这个类主要处理角色的运动,动画的播放,摄像机的控制。
charactorcontroller.h
#pragma once
#include "Ogre.h"
#include "OIS.h"
#include <algorithm>
#define NUM_ANIMS 13 // number of animations the character has
#define CHAR_HEIGHT 0 // height of character‘s center of mass above ground
#define CAM_HEIGHT 2 // height of camera above character‘s center of mass
#define RUN_SPEED 85 // character running speed in units per second
#define TURN_SPEED 500.0f // character turning in degrees per second
#define ANIM_FADE_SPEED 7.5f // animation crossfade speed in % of full weight per second
#define JUMP_ACCEL 60.0f // character jump acceleration in upward units per squared second
#define GRAVITY 180.0f // gravity in downward units per squared second
class CharactorController
{
public:
CharactorController(Ogre::Camera* cam);
~CharactorController();
void addTime(Ogre::Real deltaTime);
void injectKeyDown(const OIS::KeyEvent& evt);
void injectKeyUp(const OIS::KeyEvent& evt);
void injectPointerMove(const OIS::MouseEvent& evt);
void injectPointerDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
private:
enum AnimID
{
ANIM_IDLE_BASE,
ANIM_IDLE_TOP,
ANIM_RUN_BASE,
ANIM_RUN_TOP,
ANIM_HANDS_CLOSED,
ANIM_HANDS_RELAXED,
ANIM_DRAW_SWORDS,
ANIM_SLICE_VERTICAL,
ANIM_SLICE_HORIZONTAL,
ANIM_DANCE,
ANIM_JUMP_START,
ANIM_JUMP_LOOP,
ANIM_JUMP_END,
ANIM_NONE
};
void setupBody(Ogre::SceneManager* sceneManager);
void setupAnimations();
void setupCamera(Ogre::Camera* cam);
void updateBody(Ogre::Real deltaTime);
void updateAnimations(Ogre::Real deltaTime);
void fadeAnimations(Ogre::Real deltaTime);
void updateCamera(Ogre::Real deltaTime);
void updateCameraGoal(Ogre::Real deltaYaw, Ogre::Real deltaPitch, Ogre::Real deltaZoom);
void setBaseAnimation(AnimID id, bool reset = false);
void setTopAnimation(AnimID id, bool reset = false);
Ogre::SceneNode* mBodyNode;
Ogre::SceneNode* mCameraPivot;
Ogre::SceneNode* mCameraGoal;
Ogre::SceneNode* mCameraNode;
Ogre::Real mPivotPitch;
Ogre::Entity* mBodyEnt;
Ogre::Entity* mSword1;
Ogre::Entity* mSword2;
Ogre::RibbonTrail* mSwordTrail;
Ogre::AnimationState* mAnims[NUM_ANIMS]; // master animation list
AnimID mBaseAnimID; // current base (full- or lower-body) animation
AnimID mTopAnimID; // current top (upper-body) animation
bool mFadingIn[NUM_ANIMS]; // which animations are fading in
bool mFadingOut[NUM_ANIMS]; // which animations are fading out
bool mSwordsDrawn;
Ogre::Vector3 mKeyDirection; // player‘s local intended direction based on WASD keys
Ogre::Vector3 mGoalDirection; // actual intended direction in world-space
Ogre::Real mVerticalVelocity; // for jumping
Ogre::Real mTimer; // general timer to see how long animations have been playing
};
#include "charactorcontroller.h"
CharactorController::CharactorController(Ogre::Camera* cam)
{
setupBody(cam->getSceneManager());
setupCamera(cam);
setupAnimations();
}
CharactorController::~CharactorController()
{
}
void CharactorController::addTime(Ogre::Real deltaTime)
{
updateBody(deltaTime);
updateAnimations(deltaTime);
updateCamera(deltaTime);
}
void CharactorController::injectKeyDown(const OIS::KeyEvent& evt)
{
if (evt.key == OIS::KC_Q && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// take swords out (or put them back, since it‘s the same animation but reversed)
setTopAnimation(ANIM_DRAW_SWORDS, true);
mTimer = 0;
}
else if (evt.key == OIS::KC_E && !mSwordsDrawn)
{
if (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP)
{
// start dancing
setBaseAnimation(ANIM_DANCE, true);
setTopAnimation(ANIM_NONE);
// disable hand animation because the dance controls hands
mAnims[ANIM_HANDS_RELAXED]->setEnabled(false);
}
else if (mBaseAnimID == ANIM_DANCE)
{
// stop dancing
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
// re-enable hand animation
mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
}
}
// keep track of the player‘s intended direction
else if (evt.key == OIS::KC_W) mKeyDirection.z = -1;
else if (evt.key == OIS::KC_A) mKeyDirection.x = -1;
else if (evt.key == OIS::KC_S) mKeyDirection.z = 1;
else if (evt.key == OIS::KC_D) mKeyDirection.x = 1;
else if (evt.key == OIS::KC_SPACE && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// jump if on ground
setBaseAnimation(ANIM_JUMP_START, true);
setTopAnimation(ANIM_NONE);
mTimer = 0;
}
if (!mKeyDirection.isZeroLength() && mBaseAnimID == ANIM_IDLE_BASE)
{
// start running if not already moving and the player wants to move
setBaseAnimation(ANIM_RUN_BASE, true);
if (mTopAnimID == ANIM_IDLE_TOP) setTopAnimation(ANIM_RUN_TOP, true);
}
}
void CharactorController::injectKeyUp(const OIS::KeyEvent& evt)
{
// keep track of the player‘s intended direction
if (evt.key == OIS::KC_W && mKeyDirection.z == -1) mKeyDirection.z = 0;
else if (evt.key == OIS::KC_A && mKeyDirection.x == -1) mKeyDirection.x = 0;
else if (evt.key == OIS::KC_S && mKeyDirection.z == 1) mKeyDirection.z = 0;
else if (evt.key == OIS::KC_D && mKeyDirection.x == 1) mKeyDirection.x = 0;
if (mKeyDirection.isZeroLength() && mBaseAnimID == ANIM_RUN_BASE)
{
// stop running if already moving and the player doesn‘t want to move
setBaseAnimation(ANIM_IDLE_BASE);
if (mTopAnimID == ANIM_RUN_TOP) setTopAnimation(ANIM_IDLE_TOP);
}
}
void CharactorController::injectPointerMove(const OIS::MouseEvent& evt)
{
updateCameraGoal(-0.05f * evt.state.X.rel, -0.05f * evt.state.Y.rel, -0.0005f * evt.state.Z.rel);
}
void CharactorController::injectPointerDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
if (mSwordsDrawn && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// if swords are out, and character‘s not doing something weird, then SLICE!
if (id == OIS::MB_Left) setTopAnimation(ANIM_SLICE_VERTICAL, true);
else if (id == OIS::MB_Right) setTopAnimation(ANIM_SLICE_HORIZONTAL, true);
mTimer = 0;
}
}
void CharactorController::setupBody(Ogre::SceneManager* sceneManager)
{
// create main model
mBodyNode = sceneManager->getRootSceneNode()->createChildSceneNode(Ogre::Vector3::UNIT_Y * CHAR_HEIGHT);
mBodyEnt = sceneManager->createEntity("SinbadBody", "Sinbad.mesh");
mBodyNode->attachObject(mBodyEnt);
// create swords and attach to sheath
Ogre::LogManager::getSingleton().logMessage("Creating swords");
mSword1 = sceneManager->createEntity("SinbadSword1", "Sword.mesh");
mSword2 = sceneManager->createEntity("SinbadSword2", "Sword.mesh");
mBodyEnt->attachObjectToBone("Sheath.L", mSword1);
mBodyEnt->attachObjectToBone("Sheath.R", mSword2);
Ogre::LogManager::getSingleton().logMessage("Creating the chains");
// create a couple of ribbon trails for the swords, just for fun
Ogre::NameValuePairList params;
params["numberOfChains"] = "2";
params["maxElements"] = "80";
mSwordTrail = (Ogre::RibbonTrail*)sceneManager->createMovableObject("RibbonTrail", ?ms);
mSwordTrail->setMaterialName("Examples/LightRibbonTrail");
mSwordTrail->setTrailLength(50);
mSwordTrail->setInitialWidth(0, 100);
mSwordTrail->setVisible(false);
sceneManager->getRootSceneNode()->attachObject(mSwordTrail);
for (int i = 0; i < 2; i++)
{
mSwordTrail->setInitialColour(i, 1, 0.8, 0);
mSwordTrail->setColourChange(i, 0.75, 1.25, 1.25, 1.25);
mSwordTrail->setWidthChange(i, 1);
mSwordTrail->setInitialWidth(i, 0.5);
}
mKeyDirection = Ogre::Vector3::ZERO;
mVerticalVelocity = 0;
mBodyNode->setScale(5.0f, 5.0f, 5.0f);
}
void CharactorController::setupAnimations()
{
// this is very important due to the nature of the exported animations
mBodyEnt->getSkeleton()->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE);
Ogre::String animNames[] =
{ "IdleBase", "IdleTop", "RunBase", "RunTop", "HandsClosed", "HandsRelaxed", "DrawSwords",
"SliceVertical", "SliceHorizontal", "Dance", "JumpStart", "JumpLoop", "JumpEnd" };
for (int i = 0; i < NUM_ANIMS; i++)
{
mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
mAnims[i]->setLoop(true);
mFadingIn[i] = false;
mFadingOut[i] = false;
}
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
mSwordsDrawn = false;
}
void CharactorController::setupCamera(Ogre::Camera* cam)
{
mCameraPivot = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
mCameraGoal = mCameraPivot->createChildSceneNode(Ogre::Vector3(0, 0, 15));
mCameraNode = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
mCameraNode->setPosition(mCameraPivot->getPosition() + mCameraGoal->getPosition());
mCameraPivot->setFixedYawAxis(true);
mCameraGoal->setFixedYawAxis(true);
mCameraNode->setFixedYawAxis(true);
cam->setNearClipDistance(0.1);
cam->setFarClipDistance(100);
mCameraNode->attachObject(cam);
mPivotPitch = 0;
}
void CharactorController::updateBody(Ogre::Real deltaTime)
{
mGoalDirection = Ogre::Vector3::ZERO; // we will calculate this
if (mKeyDirection != Ogre::Vector3::ZERO && mBaseAnimID != ANIM_DANCE)
{
// calculate actually goal direction in world based on player‘s key directions
mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
mGoalDirection += mKeyDirection.x * mCameraNode->getOrientation().xAxis();
mGoalDirection.y = 0;
mGoalDirection.normalise();
Ogre::Quaternion toGoal = mBodyNode->getOrientation().zAxis().getRotationTo(mGoalDirection);
// calculate how much the character has to turn to face goal direction
Ogre::Real yawToGoal = toGoal.getYaw().valueDegrees();
// this is how much the character CAN turn this frame
Ogre::Real yawAtSpeed = yawToGoal / Ogre::Math::Abs(yawToGoal) * deltaTime * TURN_SPEED;
// reduce "turnability" if we‘re in midair
if (mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *= 0.2f;
// turn as much as we can, but not more than we need to
if (yawToGoal < 0) yawToGoal = std::min<Ogre::Real>(0, std::max<Ogre::Real>(yawToGoal, yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
else if (yawToGoal > 0) yawToGoal = std::max<Ogre::Real>(0, std::min<Ogre::Real>(yawToGoal, yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
mBodyNode->yaw(Ogre::Degree(yawToGoal));
// move in current body direction (not the goal direction)
mBodyNode->translate(0, 0, deltaTime * RUN_SPEED * mAnims[mBaseAnimID]->getWeight(),
Ogre::Node::TS_LOCAL);
}
if (mBaseAnimID == ANIM_JUMP_LOOP)
{
// if we‘re jumping, add a vertical offset too, and apply gravity
mBodyNode->translate(0, mVerticalVelocity * deltaTime, 0, Ogre::Node::TS_LOCAL);
mVerticalVelocity -= GRAVITY * deltaTime;
Ogre::Vector3 pos = mBodyNode->getPosition();
if (pos.y <= CHAR_HEIGHT)
{
// if we‘ve hit the ground, change to landing state
pos.y = CHAR_HEIGHT;
mBodyNode->setPosition(pos);
setBaseAnimation(ANIM_JUMP_END, true);
mTimer = 0;
}
}
}
void CharactorController::updateAnimations(Ogre::Real deltaTime)
{
Ogre::Real baseAnimSpeed = 1;
Ogre::Real topAnimSpeed = 1;
mTimer += deltaTime;
if (mTopAnimID == ANIM_DRAW_SWORDS)
{
// flip the draw swords animation if we need to put it back
topAnimSpeed = mSwordsDrawn ? -1 : 1;
// half-way through the animation is when the hand grasps the handles...
if (mTimer >= mAnims[mTopAnimID]->getLength() / 2 &&
mTimer - deltaTime < mAnims[mTopAnimID]->getLength() / 2)
{
// so transfer the swords from the sheaths to the hands
mBodyEnt->detachAllObjectsFromBone();
mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.L" : "Handle.L", mSword1);
mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.R" : "Handle.R", mSword2);
// change the hand state to grab or let go
mAnims[ANIM_HANDS_CLOSED]->setEnabled(!mSwordsDrawn);
mAnims[ANIM_HANDS_RELAXED]->setEnabled(mSwordsDrawn);
// toggle sword trails
if (mSwordsDrawn)
{
mSwordTrail->setVisible(false);
mSwordTrail->removeNode(mSword1->getParentNode());
mSwordTrail->removeNode(mSword2->getParentNode());
}
else
{
mSwordTrail->setVisible(true);
mSwordTrail->addNode(mSword1->getParentNode());
mSwordTrail->addNode(mSword2->getParentNode());
}
}
if (mTimer >= mAnims[mTopAnimID]->getLength())
{
// animation is finished, so return to what we were doing before
if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
else
{
setTopAnimation(ANIM_RUN_TOP);
mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
}
mSwordsDrawn = !mSwordsDrawn;
}
}
else if (mTopAnimID == ANIM_SLICE_VERTICAL || mTopAnimID == ANIM_SLICE_HORIZONTAL)
{
if (mTimer >= mAnims[mTopAnimID]->getLength())
{
// animation is finished, so return to what we were doing before
if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
else
{
setTopAnimation(ANIM_RUN_TOP);
mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
}
}
// don‘t sway hips from side to side when slicing. that‘s just embarrassing.
if (mBaseAnimID == ANIM_IDLE_BASE) baseAnimSpeed = 0;
}
else if (mBaseAnimID == ANIM_JUMP_START)
{
if (mTimer >= mAnims[mBaseAnimID]->getLength())
{
// takeoff animation finished, so time to leave the ground!
setBaseAnimation(ANIM_JUMP_LOOP, true);
// apply a jump acceleration to the character
mVerticalVelocity = JUMP_ACCEL;
}
}
else if (mBaseAnimID == ANIM_JUMP_END)
{
if (mTimer >= mAnims[mBaseAnimID]->getLength())
{
// safely landed, so go back to running or idling
if (mKeyDirection == Ogre::Vector3::ZERO)
{
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
}
else
{
setBaseAnimation(ANIM_RUN_BASE, true);
setTopAnimation(ANIM_RUN_TOP, true);
}
}
}
// increment the current base and top animation times
if (mBaseAnimID != ANIM_NONE) mAnims[mBaseAnimID]->addTime(deltaTime * baseAnimSpeed);
if (mTopAnimID != ANIM_NONE) mAnims[mTopAnimID]->addTime(deltaTime * topAnimSpeed);
// apply smooth transitioning between our animations
fadeAnimations(deltaTime);
}
void CharactorController::fadeAnimations(Ogre::Real deltaTime)
{
for (int i = 0; i < NUM_ANIMS; i++)
{
if (mFadingIn[i])
{
// slowly fade this animation in until it has full weight
Ogre::Real newWeight = mAnims[i]->getWeight() + deltaTime * ANIM_FADE_SPEED;
mAnims[i]->setWeight(Ogre::Math::Clamp<Ogre::Real>(newWeight, 0, 1));
if (newWeight >= 1) mFadingIn[i] = false;
}
else if (mFadingOut[i])
{
// slowly fade this animation out until it has no weight, and then disable it
Ogre::Real newWeight = mAnims[i]->getWeight() - deltaTime * ANIM_FADE_SPEED;
mAnims[i]->setWeight(Ogre::Math::Clamp<Ogre::Real>(newWeight, 0, 1));
if (newWeight <= 0)
{
mAnims[i]->setEnabled(false);
mFadingOut[i] = false;
}
}
}
}
void CharactorController::updateCamera(Ogre::Real deltaTime)
{
// place the camera pivot roughly at the character‘s shoulder
mCameraPivot->setPosition(mBodyNode->getPosition() + Ogre::Vector3::UNIT_Y * CAM_HEIGHT);
// move the camera smoothly to the goal
Ogre::Vector3 goalOffset = mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition();
mCameraNode->translate(goalOffset * deltaTime * 9.0f);
// always look at the pivot
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(), Ogre::Node::TS_WORLD);
}
void CharactorController::updateCameraGoal(Ogre::Real deltaYaw, Ogre::Real deltaPitch, Ogre::Real deltaZoom)
{
mCameraPivot->yaw(Ogre::Degree(deltaYaw), Ogre::Node::TS_WORLD);
// bound the pitch
if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0))
{
mCameraPivot->pitch(Ogre::Degree(deltaPitch), Ogre::Node::TS_LOCAL);
mPivotPitch += deltaPitch;
}
Ogre::Real dist = mCameraGoal->_getDerivedPosition().distance(mCameraPivot->_getDerivedPosition());
Ogre::Real distChange = deltaZoom * dist;
// bound the zoom
if (!(dist + distChange < 8 && distChange < 0) &&
!(dist + distChange > 25 && distChange > 0))
{
mCameraGoal->translate(0, 0, distChange, Ogre::Node::TS_LOCAL);
}
}
void CharactorController::setBaseAnimation(AnimID id, bool reset)
{
if (mBaseAnimID >= 0 && mBaseAnimID < NUM_ANIMS)
{
// if we have an old animation, fade it out
mFadingIn[mBaseAnimID] = false;
mFadingOut[mBaseAnimID] = true;
}
mBaseAnimID = id;
if (id != ANIM_NONE)
{
// if we have a new animation, enable it and fade it in
mAnims[id]->setEnabled(true);
mAnims[id]->setWeight(0);
mFadingOut[id] = false;
mFadingIn[id] = true;
if (reset) mAnims[id]->setTimePosition(0);
}
}
void CharactorController::setTopAnimation(AnimID id, bool reset)
{
if (mTopAnimID >= 0 && mTopAnimID < NUM_ANIMS)
{
// if we have an old animation, fade it out
mFadingIn[mTopAnimID] = false;
mFadingOut[mTopAnimID] = true;
}
mTopAnimID = id;
if (id != ANIM_NONE)
{
// if we have a new animation, enable it and fade it in
mAnims[id]->setEnabled(true);
mAnims[id]->setWeight(0);
mFadingOut[id] = false;
mFadingIn[id] = true;
if (reset) mAnims[id]->setTimePosition(0);
}
}
标签:
原文地址:http://blog.csdn.net/silangquan/article/details/43835395