3rd person camera - Chasing
We have a main character, who has a main node (the actor), a sight node (the point the character is supposed to be looking at), and a chase camera node (where we think the best chasing camera should be placed). There are other ways to achieve the same effect, but I will use this for simplicity.
What we will do is to use the sight node as the desired position of the camera target, and the chase camera node as the desired position of the camera itself.
Further sight nodes will mean the character will me more offseted from the center of the screen (for instance, if the character is in "investigation" mode in a 3rd person camera game, in the opposite of a "walk around" mode). This helps to keep a broad view of the scene, while keeping track of the character.
3rd person camera - Fixed
This kind of camera can be seen in many adventure games like Resident Evil, Silent Hill, Alone in the dark... The idea is that the target will follow the character sight, but it will remain fixed in a single position.
The way this camera works is similar to the chasing camera.
Variants of this are crane cameras, rail cameras... used in movie sets.
1st person camera
Instead of using the desired chase camera position, we use the character position as the desired position for the camera. For this mode, cameras with a tightness value of 1 work better (and hiding the character model too).
That's the only difference with the 3rd person cameras described above.
源码如下:
- #include "ExampleApplication.h"
- class Charater
- {
- // Attributes
- public:
- protected:
- SceneNode *mMainNode; // 主要角色结点
- SceneNode *mSightNode; // 视线结点,角色的目标结点
- SceneNode *mCameraNode; // 摄像机,跟踪结点
- Entity *mEntity; // 角色实体
- SceneManager *mSceneMgr;
- private:
- // Methods
- public:
- // 更新角色的运动
- virtual void update(Real elapsedTime,OIS::Keyboard *input) = 0;
- // 接下来的三种方法返回 与摄像机相关的 结点,以及当前角色的位置
- SceneNode *getSightNode()
- {
- return mSightNode;
- }
- SceneNode *getCameraNode()
- {
- return mCameraNode;
- }
- // _getDerivedPosition()()
- Vector3 _getDerivedPosition()
- {
- return mMainNode->_getDerivedPosition();
- }
- protected:
- private:
- };
- // 对于Ogre来说我们特地为他建立一个Character类
- class OgreCharater:public Charater
- {
- // Attributes
- public:
- protected:
- String mName;
- private:
- // Methods
- public:
- OgreCharater(String name,SceneManager *sceneMgr)
- {
- // 初始化成员引用
- mName = name;
- mSceneMgr = sceneMgr;
- // 初始化基本结点结构体,以处理3rd 人称摄像机
- mMainNode = mSceneMgr->
- getRootSceneNode()->createChildSceneNode(mName);
- mSightNode = mMainNode->createChildSceneNode(mName+
- "_sight",Vector3(0,0,100));
- mCameraNode = mMainNode->createChildSceneNode(mName+
- "_camera",Vector3(0,50,-100));
- // 我们假定角色为 一个 OgreHead
- mEntity = mSceneMgr->createEntity(
- mName,"OgreHead.mesh");
- mMainNode->attachObject(mEntity);
- }
- ~OgreCharater()
- {
- mMainNode->detachAllObjects();
- delete mEntity;
- mMainNode->removeAndDestroyAllChildren();
- mSceneMgr->destroySceneNode(mName);
- }
- // 处理移动
- void update(Real elapsedTime,OIS::Keyboard *input)
- {
- if (input -> isKeyDown(OIS::KC_W))
- {
- mMainNode->translate(mMainNode->getOrientation()*
- Vector3(0,0,100*elapsedTime));
- }
- if (input -> isKeyDown(OIS::KC_S))
- {
- mMainNode->translate(mMainNode->getOrientation()*
- Vector3(0,0,0-100*elapsedTime));
- }
- if (input -> isKeyDown(OIS::KC_A))
- {
- mMainNode -> yaw(Radian(2*elapsedTime));
- }
- if (input -> isKeyDown(OIS::KC_D))
- {
- mMainNode -> yaw(Radian(-2*elapsedTime));
- }
- }
- // 改变可见性,很适合 第一人称视角
- void setVisible(bool visible)
- {
- mMainNode -> setVisible(visible);
- }
- };
- // Our extended Camera class
- class ExtendedCamera
- {
- // Attributes
- public:
- protected:
- SceneNode *mTargetNode; // 摄像机的目标结点
- SceneNode *mCameraNode; // 摄像机自己所在结点
- Camera *mCamera; // Ogre 的摄像机
- SceneManager *mSceneMgr;
- String mName;
- bool mOwnCamera; // 测试ogre 的摄像机是在该类 里面还是 外面被绑定
- Real mTightness; //决定摄像机的运动幅度 1:代表tightmovement,0:代表不移动
- private:
- // Methods
- public:
- ExtendedCamera(String name,SceneManager *scenemgr,
- Camera *camera = 0)
- {
- mName = name;
- mSceneMgr = scenemgr;
- // 创建摄像机的结点结构
- mCameraNode = mSceneMgr->getRootSceneNode()
- ->createChildSceneNode(mName);
- mTargetNode = mSceneMgr->getRootSceneNode()
- ->createChildSceneNode(mName+"_target");
- // 摄像机将永远面向摄像机的目标节点
- mCameraNode->setAutoTracking(true,mTargetNode);
- // 自动跟踪
- mCameraNode->setFixedYawAxis(true);
- // 如果没有传 camera ,那么自己创建 一个摄像机
- if (camera == 0)
- {
- mCamera = mSceneMgr->createCamera(mName);
- mOwnCamera = true; // 设定camera在该类里创建
- }
- else
- {
- mCamera = camera;
- // 设置camera 的原始位置,和面Camera的位置一样
- mCamera->setPosition(0.0,0.0,0.0);
- mOwnCamera = false;
- }
- // 把摄像机添加到摄像机结点处
- mCameraNode -> attachObject(mCamera);
- // 设置默认 tight 为0.01f;
- mTightness = 0.01f;
- }
- ~ExtendedCamera()
- {
- mCameraNode->detachAllObjects();
- if (mOwnCamera)
- {
- delete mCamera;
- }
- mSceneMgr->destroySceneNode(mName);
- mSceneMgr->destroySceneNode(mName + "_target");
- }
- void setTightness (Real tightness)
- {
- mTightness = tightness;
- }
- Real getTightness()
- {
- return mTightness;
- }
- Vector3 getCameraPostion()
- {
- return mCameraNode->getPosition();
- }
- void instantUpdate(Vector3 cameraPostion,Vector3 targetPostion)
- {
- mCameraNode->setPosition(cameraPostion);
- mTargetNode->setPosition(targetPostion);
- }
- // 处理运动跟新
- void update(Real elapsedTime,Vector3 cameraPosition,Vector3 targetPosition)
- {
- Vector3 displacement;
- displacement = (cameraPosition-mCameraNode->getPosition())*mTightness;
- mCameraNode->translate(displacement);
- displacement = (targetPosition-mTargetNode->getPosition())*mTightness;
- mTargetNode->translate(displacement);
- }
- };
- class SampleListener:public ExampleFrameListener
- {
- protected:
- // 定义 Character 和ExtendedCamera指针对象
- Charater*mChar;
- ExtendedCamera *mExCamera;
- // 摄像机的 状态模式 1st,3rd person(chasing) ,3rd person (fixed)
- unsigned int mMode;
- public:
- SampleListener(RenderWindow* win,Camera* cam):ExampleFrameListener(win,cam)
- {
- mChar = 0;
- mExCamera = 0;
- mMode = 0;
- }
- void setCharater(Charater * character)
- {
- mChar = character;
- }
- void setExtendedCamera(ExtendedCamera *cam)
- {
- mExCamera = cam;
- }
- bool frameStarted(const FrameEvent& evt)
- {
- mKeyboard ->capture();
- if (mChar)
- {
- mChar->update(evt.timeSinceLastFrame,mKeyboard);
- if (mExCamera)
- {
- switch (mMode)
- {
- case 0: 3rd person chase
- mExCamera->update(evt.timeSinceLastFrame,
- mChar->getCameraNode()->_getDerivedPosition(),
- mChar->getSightNode()->_getDerivedPosition());
- break;
- case 1: // 3rd person fixed
- mExCamera->update(evt.timeSinceLastFrame,
- Vector3(0,200,0),
- mChar->getSightNode()->_getDerivedPosition());
- break;
- case 2: // 1st person
- mExCamera->update(evt.timeSinceLastFrame,
- mChar->_getDerivedPosition(),
- mChar->getSightNode()->_getDerivedPosition());
- break;
- }
- }//if
- }//if
- // 3rd Person --chase Camera
- if (mKeyboard -> isKeyDown((OIS::KC_F1)))
- {
- mMode = 0;
- if (mChar)
- {
- static_cast<OgreCharater *> (mChar)->setVisible(true);
- }
- if(mExCamera)
- {
- if (mChar)
- {
- mExCamera->instantUpdate(mChar->getCameraNode()->_getDerivedPosition(),
- mChar->getSightNode()->_getDerivedPosition());
- }
- mExCamera ->setTightness(0.01f);
- }
- }
- // 3rd Person --Fixed Camera
- if (mKeyboard->isKeyDown(OIS::KC_F2))
- {
- mMode = 1;
- if (mChar)
- {
- static_cast<OgreCharater *>(mChar)->setVisible(true);
- if (mExCamera)
- {
- if (mChar)
- {
- mExCamera->instantUpdate(Vector3(0,200,0),
- mChar->getSightNode()->_getDerivedPosition());
- }
- mExCamera->setTightness(0.01f);
- }
- }
- }
- // 1st Person
- if (mKeyboard->isKeyDown(OIS::KC_F3))
- {
- mMode = 2;
- if (mChar)
- {
- static_cast<OgreCharater *>(mChar)->setVisible(false);
- if (mExCamera)
- {
- if (mChar)
- {
- mExCamera->instantUpdate(mChar->_getDerivedPosition(),mChar->getSightNode()->_getDerivedPosition());
- }
- mExCamera->setTightness(1.0f);
- }
- }
- }
- if (mKeyboard->isKeyDown(OIS::KC_ESCAPE))
- {
- return false;
- }
- return true;
- }
- private:
- };
- class SampleApplication:public ExampleApplication
- {
- public:
- SampleApplication()
- {
- }
- ~SampleApplication()
- {
- }
- protected:
- // 仅仅 重写createS方法
- void createScene(void)
- {
- // 设置环境光线
- mSceneMgr->setAmbientLight(ColourValue(0.2f,0.2f,0.2f));
- // 设置灯光
- Light *l = mSceneMgr->createLight("MainLight");
- l->setType(Light::LT_DIRECTIONAL);
- l->setDirection(-0.5,-0.5,0);
- // 设置摄像机的位置
- mCamera->setPosition(0,0,0);
- SceneNode *razorNode;
- Entity*razorEntity;
- // 填充一些飞船到 场景里
- for (unsigned int i = 0; i<30; ++i)
- {
- razorNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(StringConverter::toString(i),
- Vector3(Math::RangeRandom(-1000,1000),0,
- Math::RangeRandom(-1000,1000)));
- razorEntity = mSceneMgr->createEntity(StringConverter::toString(i),"razor.mesh");
- razorNode ->attachObject(razorEntity);
- }
- // 主要角色
- OgreCharater *ogre = new OgreCharater("Ogre 1",mSceneMgr);
- ExtendedCamera * exCamera = new ExtendedCamera("Extended Camera",mSceneMgr, mCamera);
- // 创建 帧监听器,以更新角色和摄像机
- mFrameListener = new SampleListener(mWindow,mCamera);
- static_cast<SampleListener *> (mFrameListener)->setCharater(ogre);
- static_cast<SampleListener *> (mFrameListener)->setExtendedCamera(exCamera);
- }
- void destroyScene(void )
- {
- }
- void createFrameListener(void)
- {
- // 初始化我们的帧监听器
- mRoot->addFrameListener(mFrameListener);
- }
- private:
- };
- #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
- #define WIN32_LEAN_AND_MEAN
- #include "windows.h"
- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
- #else
- int main(int argc, char **argv)
- #endif
- {
- // Create application object
- SampleApplication app;
- try {
- app.go();
- } catch( Exception& e ) {
- #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
- MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
- #else
- fprintf(stderr, "An exception has occured: %s/n",
- e.getFullDescription().c_str());
- #endif
- }
- return 0;
- }
http://www.ogre3d.org/tikiwiki/3rd+person+camera+system+tutorial