第三人称 摄像机系统 (基于 Ogre )

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.

源码如下:

Code:
  1.   
  2. #include "ExampleApplication.h"   
  3.   
  4. class Charater   
  5. {   
  6.     // Attributes   
  7. public:   
  8. protected:   
  9.     SceneNode *mMainNode;   // 主要角色结点   
  10.     SceneNode *mSightNode;  // 视线结点,角色的目标结点   
  11.     SceneNode *mCameraNode; // 摄像机,跟踪结点   
  12.     Entity *mEntity;        // 角色实体   
  13.     SceneManager *mSceneMgr;   
  14. private:   
  15.     //  Methods   
  16. public:   
  17.     //  更新角色的运动   
  18.     virtual void update(Real elapsedTime,OIS::Keyboard *input) = 0;   
  19.     // 接下来的三种方法返回 与摄像机相关的 结点,以及当前角色的位置   
  20.     SceneNode *getSightNode()   
  21.     {   
  22.         return mSightNode;   
  23.     }   
  24.     SceneNode *getCameraNode()   
  25.     {   
  26.         return mCameraNode;   
  27.     }   
  28.     // _getDerivedPosition()()   
  29.     Vector3 _getDerivedPosition()   
  30.     {   
  31.         return mMainNode->_getDerivedPosition();   
  32.     }   
  33. protected:   
  34. private:   
  35. };   
  36.   
  37. // 对于Ogre来说我们特地为他建立一个Character类   
  38. class OgreCharater:public Charater   
  39. {   
  40.     //  Attributes   
  41. public:   
  42. protected:   
  43.     String mName;   
  44. private:   
  45.     //  Methods   
  46. public:   
  47.     OgreCharater(String name,SceneManager *sceneMgr)   
  48.     {   
  49.         //  初始化成员引用   
  50.         mName = name;   
  51.         mSceneMgr = sceneMgr;   
  52.         //  初始化基本结点结构体,以处理3rd 人称摄像机   
  53.         mMainNode = mSceneMgr->   
  54.             getRootSceneNode()->createChildSceneNode(mName);   
  55.         mSightNode = mMainNode->createChildSceneNode(mName+   
  56.             "_sight",Vector3(0,0,100));   
  57.         mCameraNode = mMainNode->createChildSceneNode(mName+   
  58.             "_camera",Vector3(0,50,-100));   
  59.         //  我们假定角色为 一个 OgreHead   
  60.         mEntity = mSceneMgr->createEntity(   
  61.             mName,"OgreHead.mesh");   
  62.         mMainNode->attachObject(mEntity);   
  63.     }   
  64.     ~OgreCharater()   
  65.     {   
  66.         mMainNode->detachAllObjects();   
  67.         delete mEntity;   
  68.         mMainNode->removeAndDestroyAllChildren();   
  69.         mSceneMgr->destroySceneNode(mName);   
  70.     }   
  71.        
  72.     //  处理移动   
  73.     void update(Real elapsedTime,OIS::Keyboard *input)   
  74.     {   
  75.         if (input ->  isKeyDown(OIS::KC_W))   
  76.         {   
  77.             mMainNode->translate(mMainNode->getOrientation()*   
  78.                 Vector3(0,0,100*elapsedTime));   
  79.         }   
  80.   
  81.         if (input -> isKeyDown(OIS::KC_S))   
  82.         {   
  83.             mMainNode->translate(mMainNode->getOrientation()*   
  84.                 Vector3(0,0,0-100*elapsedTime));   
  85.         }   
  86.   
  87.         if (input -> isKeyDown(OIS::KC_A))   
  88.         {   
  89.             mMainNode -> yaw(Radian(2*elapsedTime));   
  90.         }   
  91.   
  92.         if (input -> isKeyDown(OIS::KC_D))   
  93.         {   
  94.             mMainNode -> yaw(Radian(-2*elapsedTime));   
  95.         }   
  96.   
  97.     }   
  98.     // 改变可见性,很适合 第一人称视角   
  99.     void setVisible(bool visible)   
  100.     {   
  101.         mMainNode -> setVisible(visible);   
  102.     }   
  103. };   
  104.   
  105. //  Our extended Camera class   
  106. class ExtendedCamera   
  107. {   
  108.     // Attributes   
  109. public:   
  110. protected:   
  111.     SceneNode *mTargetNode; // 摄像机的目标结点   
  112.     SceneNode *mCameraNode; // 摄像机自己所在结点   
  113.     Camera *mCamera;     // Ogre 的摄像机   
  114.   
  115.     SceneManager *mSceneMgr;   
  116.     String mName;   
  117.     bool mOwnCamera;   // 测试ogre 的摄像机是在该类 里面还是 外面被绑定   
  118.   
  119.     Real mTightness;    //决定摄像机的运动幅度 1:代表tightmovement,0:代表不移动   
  120. private:   
  121.     // Methods   
  122. public:   
  123.     ExtendedCamera(String name,SceneManager *scenemgr,   
  124.         Camera *camera = 0)   
  125.     {   
  126.         mName = name;   
  127.         mSceneMgr = scenemgr;   
  128.         // 创建摄像机的结点结构   
  129.         mCameraNode = mSceneMgr->getRootSceneNode()   
  130.             ->createChildSceneNode(mName);   
  131.         mTargetNode = mSceneMgr->getRootSceneNode()   
  132.             ->createChildSceneNode(mName+"_target");   
  133.         // 摄像机将永远面向摄像机的目标节点   
  134.         mCameraNode->setAutoTracking(true,mTargetNode);   
  135.         //  自动跟踪   
  136.         mCameraNode->setFixedYawAxis(true);   
  137.         //  如果没有传 camera ,那么自己创建 一个摄像机   
  138.         if (camera == 0)   
  139.         {   
  140.             mCamera = mSceneMgr->createCamera(mName);   
  141.             mOwnCamera = true// 设定camera在该类里创建   
  142.         }   
  143.         else  
  144.         {   
  145.             mCamera = camera;   
  146.             //  设置camera 的原始位置,和面Camera的位置一样   
  147.             mCamera->setPosition(0.0,0.0,0.0);   
  148.             mOwnCamera = false;   
  149.         }   
  150.         //  把摄像机添加到摄像机结点处   
  151.         mCameraNode -> attachObject(mCamera);   
  152.         // 设置默认 tight 为0.01f;   
  153.         mTightness = 0.01f;   
  154.     }   
  155.     ~ExtendedCamera()   
  156.     {   
  157.         mCameraNode->detachAllObjects();   
  158.         if (mOwnCamera)   
  159.         {   
  160.             delete mCamera;   
  161.         }   
  162.         mSceneMgr->destroySceneNode(mName);   
  163.         mSceneMgr->destroySceneNode(mName + "_target");   
  164.     }   
  165.   
  166.     void setTightness (Real tightness)   
  167.     {   
  168.         mTightness = tightness;   
  169.     }   
  170.   
  171.     Real getTightness()   
  172.     {   
  173.         return mTightness;   
  174.     }   
  175.   
  176.     Vector3 getCameraPostion()   
  177.     {   
  178.         return mCameraNode->getPosition();   
  179.     }   
  180.   
  181.     void instantUpdate(Vector3 cameraPostion,Vector3 targetPostion)   
  182.     {   
  183.         mCameraNode->setPosition(cameraPostion);   
  184.         mTargetNode->setPosition(targetPostion);   
  185.     }   
  186.     // 处理运动跟新   
  187.     void update(Real elapsedTime,Vector3 cameraPosition,Vector3 targetPosition)   
  188.     {   
  189.         Vector3 displacement;   
  190.   
  191.         displacement = (cameraPosition-mCameraNode->getPosition())*mTightness;   
  192.         mCameraNode->translate(displacement);   
  193.   
  194.         displacement = (targetPosition-mTargetNode->getPosition())*mTightness;   
  195.         mTargetNode->translate(displacement);   
  196.     }   
  197. };   
  198.   
  199. class SampleListener:public ExampleFrameListener   
  200. {   
  201.   
  202. protected:   
  203.     // 定义 Character 和ExtendedCamera指针对象   
  204.     Charater*mChar;   
  205.     ExtendedCamera *mExCamera;   
  206.     // 摄像机的 状态模式 1st,3rd person(chasing) ,3rd person (fixed)   
  207.     unsigned int mMode;   
  208. public:   
  209.     SampleListener(RenderWindow* win,Camera* cam):ExampleFrameListener(win,cam)   
  210.     {   
  211.         mChar = 0;   
  212.         mExCamera = 0;   
  213.         mMode = 0;   
  214.     }   
  215.     void setCharater(Charater * character)   
  216.     {   
  217.         mChar = character;   
  218.     }   
  219.     void setExtendedCamera(ExtendedCamera *cam)   
  220.     {   
  221.         mExCamera = cam;   
  222.     }   
  223.        
  224.     bool frameStarted(const FrameEvent& evt)   
  225.     {   
  226.         mKeyboard ->capture();   
  227.         if (mChar)   
  228.         {   
  229.             mChar->update(evt.timeSinceLastFrame,mKeyboard);   
  230.             if (mExCamera)   
  231.             {   
  232.                 switch (mMode)   
  233.                 {   
  234.                 case 0:   3rd person chase   
  235.   
  236.                     mExCamera->update(evt.timeSinceLastFrame,   
  237.                         mChar->getCameraNode()->_getDerivedPosition(),   
  238.                         mChar->getSightNode()->_getDerivedPosition());   
  239.                 break;   
  240.   
  241.                 case 1:    // 3rd person fixed   
  242.   
  243.                     mExCamera->update(evt.timeSinceLastFrame,   
  244.                         Vector3(0,200,0),   
  245.                         mChar->getSightNode()->_getDerivedPosition());   
  246.                 break;   
  247.                 case 2:     // 1st person   
  248.   
  249.                     mExCamera->update(evt.timeSinceLastFrame,   
  250.                         mChar->_getDerivedPosition(),   
  251.                         mChar->getSightNode()->_getDerivedPosition());   
  252.                 break;   
  253.                 }   
  254.             }//if   
  255.         }//if   
  256.         // 3rd Person --chase Camera   
  257.         if (mKeyboard -> isKeyDown((OIS::KC_F1)))   
  258.         {   
  259.             mMode = 0;   
  260.             if (mChar)   
  261.             {   
  262.                 static_cast<OgreCharater *> (mChar)->setVisible(true);   
  263.             }   
  264.             if(mExCamera)   
  265.             {   
  266.                 if (mChar)   
  267.                 {   
  268.                     mExCamera->instantUpdate(mChar->getCameraNode()->_getDerivedPosition(),   
  269.                         mChar->getSightNode()->_getDerivedPosition());   
  270.                 }   
  271.                 mExCamera ->setTightness(0.01f);   
  272.             }   
  273.         }   
  274.   
  275.         // 3rd Person --Fixed Camera   
  276.         if (mKeyboard->isKeyDown(OIS::KC_F2))   
  277.         {   
  278.             mMode = 1;   
  279.             if (mChar)   
  280.             {   
  281.                 static_cast<OgreCharater *>(mChar)->setVisible(true);   
  282.                 if (mExCamera)   
  283.                 {   
  284.                     if (mChar)   
  285.                     {   
  286.                         mExCamera->instantUpdate(Vector3(0,200,0),   
  287.                             mChar->getSightNode()->_getDerivedPosition());   
  288.                     }   
  289.                     mExCamera->setTightness(0.01f);   
  290.                 }   
  291.             }   
  292.         }   
  293.         //  1st Person    
  294.         if (mKeyboard->isKeyDown(OIS::KC_F3))   
  295.         {   
  296.             mMode = 2;   
  297.             if (mChar)   
  298.             {   
  299.                 static_cast<OgreCharater *>(mChar)->setVisible(false);   
  300.                 if (mExCamera)   
  301.                 {   
  302.                     if (mChar)   
  303.                     {   
  304.                         mExCamera->instantUpdate(mChar->_getDerivedPosition(),mChar->getSightNode()->_getDerivedPosition());   
  305.   
  306.                     }   
  307.                     mExCamera->setTightness(1.0f);   
  308.                 }   
  309.             }   
  310.         }   
  311.         if (mKeyboard->isKeyDown(OIS::KC_ESCAPE))   
  312.         {   
  313.             return false;   
  314.         }   
  315.         return true;   
  316.     }   
  317. private:   
  318. };   
  319.   
  320. class SampleApplication:public ExampleApplication   
  321. {   
  322. public:   
  323.     SampleApplication()   
  324.     {   
  325.   
  326.     }   
  327.     ~SampleApplication()   
  328.     {   
  329.   
  330.     }   
  331. protected:   
  332.     // 仅仅 重写createS方法   
  333.     void createScene(void)   
  334.     {   
  335.         //  设置环境光线   
  336.         mSceneMgr->setAmbientLight(ColourValue(0.2f,0.2f,0.2f));   
  337.         //  设置灯光   
  338.         Light *l = mSceneMgr->createLight("MainLight");   
  339.         l->setType(Light::LT_DIRECTIONAL);   
  340.         l->setDirection(-0.5,-0.5,0);   
  341.         //  设置摄像机的位置   
  342.         mCamera->setPosition(0,0,0);   
  343.   
  344.         SceneNode *razorNode;   
  345.         Entity*razorEntity;   
  346.         //  填充一些飞船到 场景里   
  347.         for (unsigned int i = 0; i<30; ++i)   
  348.         {   
  349.             razorNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(StringConverter::toString(i),   
  350.                 Vector3(Math::RangeRandom(-1000,1000),0,   
  351.                 Math::RangeRandom(-1000,1000)));   
  352.             razorEntity = mSceneMgr->createEntity(StringConverter::toString(i),"razor.mesh");   
  353.             razorNode ->attachObject(razorEntity);   
  354.         }   
  355.         //   主要角色   
  356.         OgreCharater *ogre = new OgreCharater("Ogre 1",mSceneMgr);   
  357.         ExtendedCamera * exCamera = new ExtendedCamera("Extended Camera",mSceneMgr, mCamera);   
  358.         //   创建 帧监听器,以更新角色和摄像机   
  359.         mFrameListener = new SampleListener(mWindow,mCamera);   
  360.         static_cast<SampleListener *> (mFrameListener)->setCharater(ogre);   
  361.         static_cast<SampleListener *> (mFrameListener)->setExtendedCamera(exCamera);   
  362.     }   
  363.   
  364.     void destroyScene(void )   
  365.     {   
  366.   
  367.     }   
  368.     void createFrameListener(void)   
  369.     {   
  370.         //  初始化我们的帧监听器   
  371.         mRoot->addFrameListener(mFrameListener);   
  372.     }   
  373. private:   
  374. };   
  375. #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32   
  376. #define WIN32_LEAN_AND_MEAN   
  377. #include "windows.h"   
  378.   
  379. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCELPSTR strCmdLine, INT )   
  380. #else   
  381. int main(int argc, char **argv)   
  382. #endif   
  383. {   
  384.     // Create application object   
  385.     SampleApplication app;   
  386.   
  387.     try {   
  388.         app.go();   
  389.     } catch( Exception& e ) {   
  390. #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32    
  391.         MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK |      MB_ICONERROR | MB_TASKMODAL);   
  392. #else   
  393.         fprintf(stderr, "An exception has occured: %s/n",   
  394.             e.getFullDescription().c_str());   
  395. #endif   
  396.     }   
  397.   
  398.     return 0;   
  399. }  

http://www.ogre3d.org/tikiwiki/3rd+person+camera+system+tutorial

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值