NxOgre缓冲摄像机(及摄像机抖动解决办法)

来源:互联网 发布:centos下安装图形界面 编辑:程序博客网 时间:2024/05/18 09:48

重新对摄像机进行了封装,增加了缓冲功能,使赛车的操作真实感提升了不少,关于缓冲摄像机可以参考Ogre wiki上的第三人称摄像机那篇文章

其原理是:

      使用两个SceneNode, 一个绑定摄像机,另一个用来绑定代表赛车的节点, 赛车移动的时候摄像机的位置始终以一定速度向赛车节点靠近,这个速度跟摄像机与赛车子节点的全局坐标距离成正比.并不断跟新两节点位置.

 

关于摄像机更新抖动的问题,NxOgre和Ogre使用两个不同的FrameListener来更新场景,可能会使帧更新一致,我的解决办法是在创建NxOgre::Scene的时候将mProcessingPriority = xOgre::Enums::Priority_Low
设置成最低优先级,即不对场景进行处理(默认情况下为Priority_Medium),之后再手动更新场景
mScene->advance(timeSinceLastFrame * 0.015, NxOgre::Enums::Priority_Low);

 

//创建场景,并设置场景基本属性
NxOgre::SceneDescription desc;
//设置重力
desc.mGravity = NxOgre::Vec3(0.0f, -9.8f, 0.0f);
desc.mName = "Racing World";
/**
注:
(mProcessingPriority参数默认为中等)
设置不更新场景,保持与Ogre渲染同步,避免摄像机抖动现象
并在update调用mScene->advance(timeSinceLastFrame * 0.075, NxOgre::Enums::Priority_Low);
*/
desc.mProcessingPriority = NxOgre::Enums::Priority_Low;
mScene = mWorld->createScene(desc);

 

摄像机的封装

 

#ifndef __VEHICLECAMERA_H__
#define __VEHICLECAMERA_H__

#include <Ogre.h>
#include <string>
#include "Util.h"

/**
赛车缓冲摄像机原理:
使用两个SceneNode, 一个绑定摄像机,另一个用来绑定代表赛车的节点, 赛车移动的时候
摄像机的位置始终以一定速度向赛车节点靠近,这个速度跟摄像机与赛车子节点的全局坐标距离成正比.
并不断跟新两节点位置.

例如: 在这里每20帧跟新一次两节点坐标(与赛车同步),并更新节点相对位置.

// 根据当前赛车速度和帧数来设定缓冲大小
if (isBoundingCamera())
{
      float speed = getSpeed() / 30;

      // 提供刹车时的缓冲
      if (speed < 1.0f)
         speed = 1.0f;

      // 时时跟新摄像机,
      mVehicleCamer->update(timeSinceLastFrame * speed) ;
}
*/
class VehicleCamera
{
public:
      VehicleCamera(const std::string &playerName);

      ~VehicleCamera();

      // 设置摄像机缓冲程度值越大越硬,越小越柔和
      void setTightness ( Real tightness );

      float getTightness ( ) const;

 // 设定绑定节点, cameraNode为赛车上摄像机位置的节点, lookAtNode为赛车上车体的节点
      void setTarget ( Ogre::SceneNode*cameraNode,                                            Ogre::SceneNode* lookAtNode );

 // 手动更新节点位置, 与赛车同步
      void instantUpdate ( );

      void update ( float timeSinceLastFrame );

private:

      Ogre::SceneNode  *mBaseCamerNode;
      Ogre::SceneNode  *mBaseLookedAtNode;

      Ogre::SceneNode  *mCameraLookAtNode;
      Ogre::SceneNode  *mCameraNode;

      Ogre::Camera   *mCamera;
      // 设置摄像机缓冲程度值越大越硬,越小越柔和
      float           mTightness;
};

#endif

 

实现:

 

#include "VehicleCamera.h"

VehicleCamera::VehicleCamera(const std::string &playerName) :
   mTightness(2.0),   mCameraNode(0),
   mCameraLookAtNode(0),
   mBaseLookedAtNode(0),
   mBaseCamerNode(0)
{
      Ogre::SceneManager* sceneMgr = Util::getSceneManager();

      mCamera = Util::getSceneManager()->createCamera(                         playerName + "VehicleCamera");
      mCamera->setNearClipDistance ( 0.1f );

      Util::removeAllViewports();
      Ogre::Viewport*viewport = Util::addViewport(mCamera);

      mCamera->setAspectRatio(Real(viewport->getActualWidth()) / Real(viewport->getActualHeight()));

      // 构造绑定摄像机的节点
       mCameraNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
      mCameraLookAtNode = sceneMgr->getRootSceneNode()->createChildSceneNode();

      // 使绑定摄像机的节点自动追踪赛车节点
       mCameraNode->setAutoTracking ( true, mCameraLookAtNode );
      // [重要]设置只能延Y轴旋转,
      mCameraNode->setFixedYawAxis ( true );  

      mCameraNode->attachObject ( mCamera );

      // 开启N02加速模糊
       Util::addCompositor(viewport, "Bloom");
      Util::setCompositorEnabled(viewport,"Bloom",true);
}

VehicleCamera::~VehicleCamera()
{
      mCameraNode->detachAllObjects ();

      Util::removeAllViewports();
      Util::getSceneManager()->destroyCamera(mCamera);

      Util::getSceneManager()->destroySceneNode ( mCameraNode );
      Util::getSceneManager()->destroySceneNode ( mCameraLookAtNode );

      mCamera = 0;
}

void VehicleCamera::setTightness ( Real tightness )
{
      mTightness = tightness;
}

float VehicleCamera::getTightness ( ) const
{
      return mTightness;
}

// 设定绑定节点, cameraNode为赛车上摄像机位置的节点, lookAtNode为赛车上车体的节点
void VehicleCamera::setTarget ( Ogre::SceneNode* cameraNode,  Ogre::SceneNode* lookAtNode )
{
       mBaseCamerNode = cameraNode;
       mBaseLookedAtNode = lookAtNode;

       instantUpdate ( );
}

// 手动更新节点位置, 与赛车同步
void VehicleCamera::instantUpdate ( )
{
       mCameraNode->setPosition ( mBaseCamerNode->_getDerivedPosition() );
       mCameraLookAtNode->setPosition (                           mBaseLookedAtNode->_getDerivedPosition() );
}

void VehicleCamera::update ( float timeSinceLastFrame )
{
       if (mCameraNode)
       {
   Ogre::Vector3 displacement;
   float rate = mTightness * timeSinceLastFrame;

   displacement = ( mBaseCamerNode->_getDerivedPosition()- mCameraNode->_getDerivedPosition() );
           mCameraNode->translate ( displacement  * rate);

   displacement = ( mBaseLookedAtNode->_getDerivedPosition()- mCameraLookAtNode->_getDerivedPosition() );
   mCameraLookAtNode->translate ( displacement  * rate);
        }
}

原创粉丝点击