Code & Comments For Basic Tutorial 4 in Ogre3d Wiki
Copyright © MikeFeng QQ: 76848502
本文的代码来自于Ogre官方网站wiki的基础教程4, 这个代码使用Ogre自带的Example框架, 主要实现了以下功能:
-
读入一个ninja模型
-
使用了一个点光源将该模型照亮
-
鼠标左键的点击控制灯光的开关
-
鼠标右键点住拖动实现相机方向的改变
-
方向键控制相机的位置
-
非缓冲输入的处理
-
两个相机的按1,2键进行切换
由于Ogre Wiki没有给出完整连贯的代码和效果图, 故在此画蛇添足一下. 另外我在代码里补充了一些自己的注释,希望对大家有帮助. 下面是效果图
灯开着的效果
关灯后的效果
下面是代码
/**
/file
Demo.h
/brief
Specialisation of OGRE's framework application to show the
multi-camera and unbuffered input feature.
*/
#include
"ExampleApplication.h"
class
DemoFrameListener : public ExampleFrameListener
{
public
:
bool mMouseDown; // Whether or not the left mouse button was down last frame
Real mToggle; // The time left until next toggle
Real mRotate; // The rotate constant
Real mMove; // The movement constant
SceneManager *mSceneMgr; // The current SceneManager
SceneNode *mCamNode; // The SceneNode the camera is currently attached to
// unbuffered keyboard and mouse input
DemoFrameListener(RenderWindow* win, Camera* cam, SceneManager* sceneMgr)
: ExampleFrameListener(win, cam, false, false)
{
// Key and mouse state tracking
mMouseDown = false;
mToggle = 0.0;
// Populate the camera and scene manager containers
// the first parent will be the PitchNode,
// and the CamNode which we are looking for is the parent of that node.
mCamNode = cam->getParentSceneNode()->getParentSceneNode();
mSceneMgr = sceneMgr;
// Set the rotation and move speed
mRotate = 0.13;
mMove = 250;
}
bool frameStarted(const FrameEvent& evt)
{
using namespace OIS;
// 1. capture the current state of the keyboard and mouse
mMouse->capture();
mKeyboard->capture();
// if the frameStarted method return false,
// ogre will exit from the main render loop
if( mKeyboard->isKeyDown( KC_ESCAPE ) )
return false;
// Get the current left mouse button state
bool currMouse = mMouse->getMouseState().buttonDown( MB_Left );
// if the left mouse button is pressed, and in last frame
// this button is up, we do the light toggle..
if ( currMouse && ! mMouseDown )
{
Light *light = mSceneMgr->getLight( "Light1" );
light->setVisible( ! light->isVisible() );
}
// mMouseDown is set for the next frame.
mMouseDown = currMouse;
// mToggle is the time counter for changing the camera action
if ( mToggle >= 0.0f )
mToggle -= evt.timeSinceLastFrame;
// if mToggle is less than 0, and key '1' is pressed
if ( ( mToggle < 0.0f ) && mKeyboard->isKeyDown( KC_1 ) )
{
// set the toggle back to 1
// this means only after 1 second, the toggle action will be excuted
mToggle = 1.0f;
// detach the camera form CamNode2, and attach to CamNode1
mCamera->getParentSceneNode()->detachObject( mCamera );
mCamNode = mSceneMgr->getSceneNode( "CamNode1" );
mSceneMgr->getSceneNode( "PitchNode1" )->attachObject( mCamera );
}
// if mToggle is less than 0, and key '1' is pressed
else if ( ( mToggle < 0.0f ) && mKeyboard->isKeyDown( KC_2 ) )
{
mToggle = 0.1f;
// detach the camera form CamNode1, and attach to CamNode2
mCamera->getParentSceneNode()->detachObject( mCamera );
mCamNode = mSceneMgr->getSceneNode( "CamNode2" );
mSceneMgr->getSceneNode( "PitchNode2" )->attachObject( mCamera );
}
// direction keys, used for moving the camera
Vector3 transVector = Vector3::ZERO;
if ( mKeyboard->isKeyDown( KC_UP ) || mKeyboard->isKeyDown( KC_W ) )
transVector.z -= mMove;
if ( mKeyboard->isKeyDown( KC_DOWN ) || mKeyboard->isKeyDown( KC_S ) )
transVector.z += mMove;
if ( mKeyboard->isKeyDown( KC_LEFT ) || mKeyboard->isKeyDown( KC_A ) )
transVector.x -= mMove;
if ( mKeyboard->isKeyDown( KC_RIGHT ) || mKeyboard->isKeyDown( KC_D ) )
transVector.x += mMove;
if ( mKeyboard->isKeyDown( KC_PGUP ) || mKeyboard->isKeyDown( KC_Q ) )
transVector.y += mMove;
if ( mKeyboard->isKeyDown( KC_PGDOWN ) || mKeyboard->isKeyDown( KC_E ) )
transVector.y -= mMove;
//mCamNode->translate( mCamNode->getOrientation() *
// transVector * evt.timeSinceLastFrame );
// move the camera
mCamNode->translate( mCamNode->getOrientation() *
mCamNode->getChild( 0 )->getOrientation() *
transVector * evt.timeSinceLastFrame );
// change the camare direction according to the right mouse button
if ( mMouse->getMouseState().buttonDown( MB_Right ) )
{
mCamNode->yaw( Degree(-mRotate * mMouse->getMouseState().X.rel) );
mCamNode->getChild( 0 )->pitch( Degree(-mRotate * mMouse->getMouseState().Y.rel) );
}
return true;
}
};
class
DemoApplication : public ExampleApplication
{
public
:
DemoApplication() {}
protected
:
// Just override the mandatory create scene method
void chooseSceneManager()
{
mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE);
}
// create the frame listener we defined above
void createFrameListener()
{
mFrameListener = new DemoFrameListener(mWindow, mCamera, mSceneMgr);
mRoot->addFrameListener(mFrameListener);
}
void createScene(void)
{
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.25, 0.25, 0.25));
// Create a light
Light *light = mSceneMgr->createLight( "Light1" );
light->setType( Light::LT_POINT );
light->setPosition( Vector3(250, 150, 250) );
light->setDiffuseColour( ColourValue::White );
light->setSpecularColour( ColourValue::White );
// Loading ninja mesh
Entity *ent = mSceneMgr->createEntity( "Ninja", "ninja.mesh" );
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "NinjaNode" );
node->attachObject( ent );
// Create the scene node
node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "CamNode1", Vector3( -400, 200, 400 ) );
// Make it look towards the ninja
node->yaw( Degree(-45) );
// Create the pitch node
node = node->createChildSceneNode( "PitchNode1" );
node->attachObject( mCamera );
// create the second camera node/pitch node
node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "CamNode2", Vector3( 0, 200, 400 ) );
node = node->createChildSceneNode( "PitchNode2" );
}
};