标签:
首先参照这里配置好工程。
添加一个类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