|
|
发表于 2008-6-28 00:09:00
|
显示全部楼层
Re:(原创)仿CS第一人称行走演示
控制摄像头也是艺术。
如下是用OGRE写得一个第三人称控制摄像头代码,实现起来相当酷。
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------------------------
Filename: ParticleApplication.cpp
Description: Specialisation of OGRE's framework application to show the
environment mapping feature.
-----------------------------------------------------------------------------
*/
#include "ExampleApplication.h"
#include <OIS/OIS.h>
using namespace Ogre;
// 普通角色类
class Character
{
protected:
SceneNode *mMainNode; // 主角结点
SceneNode *mSightNode; // 可见结点,主角应当一直看着这里
SceneNode *mCameraNode; // 锁定摄象机结点,该结点围绕主角移动和旋转
Entity *mEntity; // 角色实体
SceneManager *mSceneMgr;
public:
// 更新主角状态(如移动等……)
virtual void update (Real elapsedTime, OIS::Keyboard *keyboard) = 0;
// 下面两个方法返回摄象机结点指针
SceneNode *getSightNode(){ return mSightNode ;}
SceneNode *getCameraNode(){ return mCameraNode; }
// 返回主角当前坐标(第一人称摄象机时需要)
Vector3 getWorldPosition(){ return mMainNode->getWorldPosition(); }
};
// 特殊的实例化角色类 ? 我们可爱的Ogre
class OgreCharacter : public Character
{
protected:
String mName;
public:
OgreCharacter(String name, SceneManager *sceneMgr)
{
// 保存类成员变量
mName = name;
mSceneMgr = sceneMgr;
// 创建节点用来存放绑定第三人称的摄象机
mMainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(mName);
mSightNode = mMainNode-> createChildSceneNode(mName + "_sight", Vector3(0, 0, 100));
mCameraNode = mMainNode-> createChildSceneNode(mName + "_camera", Vector3(0, 50, -100));
// 为角色绑定一个实体
mEntity = mSceneMgr->createEntity(mName, "OgreHead.mesh");
mMainNode->attachObject(mEntity);
}
void update(Real elapsedTime, OIS::Keyboard *keyboard)
{
using namespace OIS;
// 移动
if (keyboard->isKeyDown(KC_W))
{
mMainNode->translate(mMainNode->getOrientation() * Vector3(0, 0, 100 * elapsedTime));
}
if (keyboard->isKeyDown(KC_S))
{
mMainNode->translate(mMainNode->getOrientation() * Vector3(0, 0, -50 * elapsedTime));
}
if (keyboard->isKeyDown(KC_A))
{
mMainNode->yaw(Radian(2 * elapsedTime));;
}
if (keyboard->isKeyDown(KC_D))
{
mMainNode->yaw(Radian(-2 * elapsedTime));;
}
}
// 设置自身是否可见,这对于第一人称视角很有用。
void setVisible(bool visible)
{
mMainNode->setVisible(visible);
}
};
// 我们的扩展摄象机类
class ExtendedCamera
{
protected:
SceneNode *mTargetNode; // 摄象机目标结点
SceneNode *mCameraNode; // 摄象机自身结点
Camera *mCamera; // Ogre摄象机
SceneManager *mSceneMgr;
String mName;
bool mOwnCamera; // 判断是否是本类创建的摄象机,或是类外传入的摄象机
Real mTightness; // 摄象机捆绑紧密度。1.0表示摄象机与目标的移动保持完全一致。0.0表示摄象机不移动,完全不受目标移动的影响。
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);
// 因为需要自动跟踪,所以该项要设为true
mCameraNode->setFixedYawAxis(true);
// 假如没有从参数获得一个摄象机,我们则自己创建
if (camera == 0)
{
mCamera = mSceneMgr->createCamera(mName);
mOwnCamera = true;
}
else
{
mCamera = camera;
mOwnCamera = false;
}
// 为摄象机结点绑定一个Ogre摄象机
mCameraNode->attachObject(mCamera);
// 默认的摄象机捆绑紧密系数
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 getCameraPosition()
{
return mCameraNode->getPosition();
}
void instantUpdate(Vector3 cameraPosition, Vector3 targetPosition)
{
mCameraNode->setPosition(cameraPosition);
mTargetNode->setPosition(targetPosition);
}
void update(Real elapsedTime, Vector3 cameraPosition, Vector3 targetPositon)
{
// 管理移动
Vector3 displacement = (cameraPosition - mCameraNode->getPosition()) * mTightness;
mCameraNode->translate(displacement);
displacement = (targetPositon - mTargetNode->getPosition()) * mTightness;
mTargetNode->translate(displacement);
}
};
class SampleListener : public ExampleFrameListener
{
protected:
Character *mChar;
ExtendedCamera *mExCamera;
unsigned int mMode; // 摄象机模式,现在支持第一人称,绑定的第三人称摄象机和动态捕捉第三人称摄象机
public:
SampleListener(RenderWindow *win, Camera *cam) : ExampleFrameListener(win, cam)
{
mChar = 0;
mExCamera = 0;
mMode = 0;
}
void setCharacter(Character * character)
{
mChar = character;
}
void setExtendedCamera(ExtendedCamera *cam)
{
mExCamera = cam;
}
bool frameStarted( const FrameEvent& evt )
{
using namespace OIS;
mKeyboard->capture();
mMouse->capture();
if (mChar)
{
mChar->update(evt.timeSinceLastFrame, mKeyboard);
if (mExCamera)
{
switch(mMode)
{
// 动态捕捉型第三人称摄象机
case 0:
mExCamera->update(evt.timeSinceLastFrame, mChar->getCameraNode()->getWorldPosition(), mChar->getSightNode()->getWorldPosition());
break;
// 绑定的第三人称摄象机
case 1:
mExCamera->update(evt.timeSinceLastFrame, Vector3(0, 200, 0), mChar->getSightNode()->getWorldPosition());
break;
// 第一人称摄象机
case 2:
mExCamera->update(evt.timeSinceLastFrame, mChar->getWorldPosition(), mChar->getSightNode()->getWorldPosition());
break;
}
}
}
// F1键切换为动态捕捉型第三人称摄象机
if (mKeyboard->isKeyDown(KC_F1))
{
mMode = 0;
if (mChar)
static_cast<OgreCharacter* >(mChar)->setVisible(true);
if (mExCamera)
{
if (mChar)
{
mExCamera->instantUpdate(mChar->getCameraNode()->getWorldPosition(), mChar->getSightNode()->getWorldPosition());
}
mExCamera->setTightness(0.01f);
}
}
// F2切换为绑定的第三人称摄象机
if (mKeyboard->isKeyDown(KC_F2))
{
mMode = 1;
if (mChar)
static_cast<OgreCharacter*>(mChar)->setVisible(true);
if (mExCamera)
{
if (mChar)
mExCamera->instantUpdate(Vector3(0, 200, 0), mChar->getSightNode()->getWorldPosition());
mExCamera->setTightness(0.01f);
}
}
// F3键切换为第一人称摄象机
if (mKeyboard->isKeyDown(KC_F3))
{
mMode = 2;
if (mChar)
static_cast<OgreCharacter*>(mChar)->setVisible(false);
if(mExCamera)
{
if (mChar)
{
mExCamera->instantUpdate(mChar->getWorldPosition(), mChar->getSightNode()->getWorldPosition());
}
mExCamera->setTightness(1.0f);
}
}
// 若按下ESC就退出
if(mKeyboard->isKeyDown(KC_ESCAPE))
return false;
return true;
}
};
class SampleApplication : public ExampleApplication
{
public:
SampleApplication(){}
~SampleApplication(){}
protected:
// 创建场景
void createScene(void)
{
// 设置环境光
mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
// 创建一个点光源
Light* l = mSceneMgr->createLight("MainLight");
// 这个点光源使用默认设置
l->setType(Light: T_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);
}
// 主角
OgreCharacter *ogre = new OgreCharacter("Ogre 1", mSceneMgr);
ExtendedCamera *exCamera = new ExtendedCamera("Extended Camera", mSceneMgr, mCamera);
// 桢监听器用来管理主角和摄象机的更新和不同摄象机模式间的切换
mFrameListener = new SampleListener(mWindow, mCamera);
static_cast<SampleListener*>( mFrameListener)->setCharacter(ogre);
static_cast<SampleListener*>( mFrameListener)->setExtendedCamera(exCamera);
}
void destroyScene(void){}
void createFrameListener(void)
{
mRoot->addFrameListener(mFrameListener);
}
};
|
|