DirectX使用的是左手坐标系x正向右,y正向上,z正向前,即向螢幕裡
Ogre/OpGL 使用的是右手坐标系 x正向右,y正向上,z正向自己,即向螢幕外
以下開發工具為 Visual Studio 2010, DirectX版本為:Microsoft DirectX SDK (June 2010)
Ogre版本為:OgreSDK_vc10_v1-7-3
注意:要想Ogre程式能運作,必須将Ogre庫的dll檔案路徑配置進環境變量:

一:9個實體,随機出現一個,隐藏另一個,滑鼠移到轉動相機,按鍵盤移動相機.
(程式為遊戲類程式設計/Ogre/Ogre1.73/FirstOGRE)
1:建立一個空的 win32控制台應用程式,命名為:FirstOGRE
2:添加一個 FirstOGRE.cpp檔案
3:配置包含目錄(包含Ogre的頭檔案的目錄)和庫目錄(包含Ogre的lib檔案的目錄):
4:配置附加依賴項:
OgreRTShaderSystem_d.lib
OgreMain_d.lib
OIS_d.lib
5:将OgreSDK_vc10_v1-7-3安裝目錄下的 media目錄拷貝到目前工程目錄下,将OgreSDK_vc10_v1-7-3安裝目錄
下的 bin目錄下的 debug目錄下和 release目錄的下字尾為 .cfg的檔案拷貝到目前目錄下, 并修改.cfg檔案
内的配置内容(修改配置路徑的内容):
6:添加一個 MyEntity
MyEntity.h:
#ifndef MyEntity_H_
#define MyEntity_H_
#include <OGRE/ExampleApplication.h>
class MyEntity
{
public:
MyEntity(Ogre::SceneManager*mSceneMgr, int i, int j);//建立實體,節點,并為節點建立動畫.
~MyEntity(void);
public:
voidupdate(floatinterval);//動畫
voidenable(); //随機顯示實體
voiddisable();//讓顯示的實體隐藏
boolisEnable();//判斷顯示隐藏狀态
private:
Ogre::Entity *m_pEnt; //建立的實體
Ogre::SceneNode *m_pSceneNode;//儲存實體的節點
Ogre::AnimationState *m_pAnimState;//負責實體的動畫
};
#endif
MyEntity.cpp:
#include "MyEntity.h"
MyEntity::MyEntity(Ogre::SceneManager*mSceneMgr,int i, int j)
{
using namespace Ogre;
m_pEnt = mSceneMgr->createEntity("myEntiy"+Ogre::StringConverter::toString(i*3+j),"Sinbad.mesh");//建立實體,并給實體命名
m_pEnt->setVisible(false);//預設情況下實體隐藏
m_pSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(50*i, 0, 50*j));//建立一個節點時,給節點一個位置
//pSceneNode->setScale(Ogre::Vector3(6.0f, 6.0f, 6.0f));//節點放大6倍
m_pSceneNode->attachObject(m_pEnt);//節點與實體關聯
//建立實體的動畫
Ogre::Animation *pAnimation =mSceneMgr->createAnimation("myEntiy"+Ogre::StringConverter::toString(i*3+j), 3.0f);//第一個為動畫的名稱,後一個為動畫的時長
pAnimation->setInterpolationMode(Ogre::Animation::IM_SPLINE);//設定動畫內插補點為樣條插值
Ogre::NodeAnimationTrack*pTrack =pAnimation->createNodeTrack(0,m_pSceneNode);//建立一個軌迹動畫,第一個值為索引,第二個為關聯的節點
//在第秒,物體放大為整個物體的倍
Ogre::TransformKeyFrame*pKey =pTrack->createNodeKeyFrame(0.0f);
pKey->setScale(Ogre::Vector3(3.0f,3.0f, 3.0f));//物體放大3倍
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));//轉換點
//在第秒後,物體放大為整個物體的倍
pKey = pTrack->createNodeKeyFrame(1.0f);
pKey->setScale(Ogre::Vector3(6.0f,6.0f, 6.0f));
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));
//在第秒後,物體放大為整個物體的倍
pKey = pTrack->createNodeKeyFrame(2.0f);
pKey->setScale(Ogre::Vector3(6.0f,6.0f, 6.0f));
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));
//在第秒後,物體放大為整個物體的倍
pKey = pTrack->createNodeKeyFrame(3.0f);
pKey->setScale(Ogre::Vector3(3.0f,3.0f, 3.0f));
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));
//通過上面的動畫建立動畫狀态
m_pAnimState = mSceneMgr->createAnimationState("myEntiy"+Ogre::StringConverter::toString(i*3+j));
m_pAnimState->setEnabled(false);//初期動畫為關閉
m_pAnimState->setLoop(true); //設定動畫為循環播放
}
MyEntity::~MyEntity(void)
{
}
void MyEntity::update(floatinterval)
{
m_pAnimState->setTimePosition(interval);//設定動畫的起點
}
void MyEntity::enable()
{
if(!m_pEnt->getVisible()){
m_pAnimState->setEnabled(true);//設定動畫為開啟
m_pAnimState->setTimePosition(0.0f);//設定動畫的起點
m_pEnt->setVisible(true);
}
}
void MyEntity::disable()
{
if(m_pEnt->getVisible())m_pEnt->setVisible(false);//隐藏
}
bool MyEntity::isEnable()
{
return m_pEnt->getVisible();//判斷是否是顯示
}
7:添加一個 MyEntityManager
MyEntityManager.h:
#ifndef MyEntityManager_H_
#define MyEntityManager_H_
#include "MyEntity.h"
class MyEntityManager//MyEntity的管理類
{
public:
MyEntityManager(Ogre::SceneManager*mSceneMgr);
~MyEntityManager(void);
public:
voidupdate(constFrameEvent&evt);//幀事件
private:
MyEntity*m_pMyEnt[9];//9個實體
MyEntity*m_pCurrentMyEnt;//記錄目前可見實體
floatm_time;//用于時間累加,當大于等于1時,還原為0
};
#endif
MyEntityManager.cpp:
#include "MyEntityManager.h"
MyEntityManager::MyEntityManager(Ogre::SceneManager*mSceneMgr) : m_time(0.0f),m_pCurrentMyEnt(NULL)
{
for(inti=0; i<3; i++){ //建立9個實體
for(intj=0; j<3; j++){
m_pMyEnt[i*3+j] =new MyEntity(mSceneMgr,i, j);
}
}
}
MyEntityManager::~MyEntityManager(void)
{
for(inti=0; i<9; i++){
deletem_pMyEnt[i];
m_pMyEnt[i] =NULL;
}
m_pCurrentMyEnt= NULL;
}
void MyEntityManager::update(constFrameEvent& evt)
{
m_time+= evt.timeSinceLastFrame;
if(m_time >= 1.0f){//當每過1秒,随機顯示一個實體
if(NULL !=m_pCurrentMyEnt)m_pCurrentMyEnt->disable();
m_pCurrentMyEnt= m_pMyEnt[rand()%9];
m_pCurrentMyEnt->enable();
m_time= 0.0f; //還原為0.0f
}
if(NULL !=m_pCurrentMyEnt)m_pCurrentMyEnt->update(m_time);//更新顯示的實體狀态
}
8:添加一個監聽類:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
class MyEntityManager;
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
//bufferedKeys,bufferedMouse,bufferedJoy:是否啟用鍵盤,滑鼠,搖桿的緩沖,預設不啟用,會導緻不停地檢查輸入裝置資訊來确定按鍵是否按下或釋放,滑鼠是否移動等等,如果檢測
// 不夠快速,某一動作可能不會被發現,是以調用時,要啟用緩沖,在緩沖模式下,OIS會記錄所有輸入裝置的變化,并把它們通過消息告知應
// 用程式。在緩沖模式下不需要檢查輸入裝置的狀态,隻需要處理OIS發送的消息。
MyEntityFrameListener(MyEntityManager *pMyEntMgr,RenderWindow*win,Camera*cam,bool bufferedKeys= false, bool bufferedMouse = false,bool bufferedJoy=false);
~MyEntityFrameListener(void);
public:
//virtualbool processUnbufferedKeyInput(const FrameEvent& evt); //鍵盤輸入
//virtual bool processUnbufferedMouseInput(constFrameEvent& evt);//滑鼠輸入
virtualboolkeyPressed(constOIS::KeyEvent &arg);//啟用bufferedKeys緩存,并繼承了KeyListener,則使用此替代processUnbufferedKeyInput
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(const OIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
void moveCamera(); //移動相機
virtualboolframeEnded(constFrameEvent&evt); //循環重新整理界面
private:
MyEntityManager*m_pMyEntMgr;//實體管理類,也是實體集合類
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
#include "MyEntityManager.h"
MyEntityFrameListener::MyEntityFrameListener(MyEntityManager *pMyEntMgr,RenderWindow*win,Camera* cam, bool bufferedKeys,bool bufferedMouse,bool bufferedJoy)
:ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy),m_pMyEntMgr(pMyEntMgr)
{
//啟用了鍵鼠柄的緩沖,就能使用它們的回調函數
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
if(NULL !=m_pMyEntMgr){
deletem_pMyEntMgr;
m_pMyEntMgr= NULL;
}
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//鍵盤的鍵按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent &arg)//釋放按下的鍵
{
mTranslateVector= Vector3::ZERO;//防止按鍵釋放後還繼續移動相機
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent &arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)) {
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.X.rel * 0.13);//轉為弧度,如:Degree(180)
mRotY= Degree(-ms.Y.rel * 0.13);//轉為弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera()//移動相機
{
mCamera->yaw(mRotX); //繞y軸轉動
mCamera->pitch(mRotY);//繞x軸轉動
mCamera->moveRelative(mTranslateVector);//移動相機
mRotX= mRotY = 0; //防止滑鼠不轉動後繼續轉動相機
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
//ExampleFrameListener::frameEnded(evt);//可以不用
moveCamera();//移動相機
if(NULL !=m_pMyEntMgr)m_pMyEntMgr->update(evt);//每個一秒随機顯示一個實體,隐藏另一個實體等
returntrue;
}
9:添加一個 應用程式類:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include <OGRE/ExampleApplication.h>
#include "MyEntityManager.h"
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//建立螢幕(設定燈光,材質,相機,建立實體節點等)
voidcreateFrameListener(void);//建立幀監聽
private:
MyEntityManager *m_pMyEntMgr;
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pMyEntMgr= NULL;
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if(NULL !=m_pMyEntMgr){
deletem_pMyEntMgr;
m_pMyEntMgr= NULL;
}
if(NULL ==m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除監聽
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//設定環境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(94.0f, 194.043f, 375.0f);//設定錄影機位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//設定錄影機角度
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2",50);//設定天空盒
m_pMyEntMgr= new MyEntityManager(mSceneMgr);//建立9個實體
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(m_pMyEntMgr,mWindow,mCamera, true, true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
10:FirstOGRE.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationm;
m.go();
return0;
}
二:旋轉節點,縮放節點,坐标空間移動旋轉節點等,綁定相機旋轉節點等
(程式為遊戲類程式設計/Ogre/Ogre1.73/SecondOGRE)
1:建立一個 空的win32控制台應用程式,命名為:SecondOGRE.
2:添加一個 SecondOGRE.cpp檔案.
3:配置跟 FirstOGRE的3,4,5項一樣.
4:添加一個類:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include <OGRE/ExampleApplication.h>
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//建立螢幕(設定燈光,材質,相機,建立實體節點等)
voidcreateFrameListener(void);//建立幀監聽
private:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst = NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除監聽
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//設定環境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//設定錄影機位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//設定錄影機方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//設定天空盒
//建立地面
Planeplane(Vector3::UNIT_Y, -15);//通過法向量與恒定數建立一個Plane
MeshManager::getSingleton().createPlane("GrassPlane",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500, 1500,//寬度,高度
200, 200, // x方向段值,y方向段值,即面闆分成多少個三角形
true, //建立一個垂直的法向量到面闆
1, 5, 5, Vector3::UNIT_Z);// 2D紋理坐标設定的數量,在u,v方向重複的瓦片的數量,紋理方向
Entity*pEnt =mCamera->getSceneManager()->createEntity("GrassPlane","GrassPlane");
mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode("GrassPlane")->attachObject(pEnt);
pEnt->setMaterialName("Examples/BeachStones");//設定材質 Examples/GrassFloor
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera,true, true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
5:添加一個類:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
using namespaceOgre;
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移動相機
virtualboolframeEnded(constFrameEvent&evt);//循環重新整理界面
protected:
voidcreateEntity1();//建立實體,繞各自自身軸旋轉節點等
voidcreateEntity2();//建立實體,縮放節點等
// root節點沒有父節點,其它節點都有父節點
voidcreateEntity3();//坐标空間,TS_PARENT(父節點空間),TS_WORLD(世界坐标空間),TS_LOCAL(自己的空間)
voidcreateEntity4();//在各個空間的移動
voidcreateEntity5();//在各個空間的轉動
protected:
SceneManager*mSceneMgr;
SceneNode*m_pNode7;
SceneNode*m_pNode8;
SceneNode*m_pNode9;
SceneNode*m_pNode10;
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy)
{
//啟用了鍵鼠柄的緩沖,就能使用它們的回調函數
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
mSceneMgr= cam->getSceneManager();
createEntity1();//建立實體,繞各自自身軸旋轉節點等
createEntity2();//建立實體,縮放節點
createEntity3();//坐标空間,TS_PARENT(父節點空間),TS_WORLD(世界坐标空間),TS_LOCAL(自己的空間)
createEntity4();//在各個空間的移動
createEntity5();//在各個空間的轉動
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//鍵盤的鍵按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//釋放按下的鍵
{
mTranslateVector= Vector3::ZERO;//防止按鍵釋放後還繼續移動相機
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.Y.rel * 0.13);//轉為弧度,如:Degree(180)
mRotY= Degree(-ms.X.rel * 0.13);//轉為弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera() //移動相機
{
// mCamera->yaw(mRotX); //繞y軸轉動
//mCamera->pitch(mRotY);//繞x軸轉動
mCamera->moveRelative(mTranslateVector);//移動相機
// pNode7->translate(tran3, Node::TS_PARENT);//TS_PARENT時,點的位置:pos7+tran3
//Quaternionq;q.FromAngleAxis(angle,axis);q.normalise();mOrientation = q*mOrientation;
//pNode8->translate(tran8,Node::TS_LOCAL);//TS_LOCAL時,點的位置:pos8+mOrientation*tran8
//Quaternionq;q.FromAngleAxis(angle,axis);q.normalise();mOrientation = q*mOrientation;
//pNode9->translate(tran9,Node::TS_WORLD);//TS_WORLD時,點的位置:pos9+(mParent->_getDerivedOrientation().Inverse()*tran9)/mParent->_getDerivedScale())
//Quaternionq;q.FromAngleAxis(angle,axis);q.normalise();
//mOrientation =mOrientation*_getDerivedOrientation().Inverse()*q*_getDerivedOrientation();
m_pNode7->yaw(mRotY);//m_pNode7節點必須轉,下面的3個節點才會繞着m_pNode7節點轉
//m_pNode7節點轉,會導緻其子節點跟着轉, 實際上不需要 m_pNode8->yaw +m_pNode8->lookAt
/
createLinghtAndMesh();//建立Plane,燈光,和Mesh
createNewCamera(); //建立相機,添加視口
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(m_pSinbadNode,mWindow,mCamera,true,true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::createLinghtAndMesh()//建立Plane,燈光,和Mesh
{
//建立Plane
Ogre::Planeplane(Vector3::UNIT_Y,-10);//通過法向量與恒定數建立一個Plane
Ogre::MeshManager::getSingleton().createPlane("plane",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500, 1500,//寬度,高度
200, 200,//x方向段值,y方向段值,即面闆分成多少個三角形
true, //建立一個垂直的法向量到面闆
1, 5, 5, Vector3::UNIT_Z);//2D紋理坐标設定的數量,在u,v方向重複的瓦片的數量,紋理方向
Ogre::Entity*pEnt = mSceneMgr->createEntity("plane1","plane");
mSceneMgr->getRootSceneNode()->createChildSceneNode("plane1")->attachObject(pEnt);
pEnt->setMaterialName("Examples/BeachStones");
//建立燈光1,點光源,點光源有位置,無方向,參與陰影計算
Ogre::Light *pLight1=mSceneMgr->createLight("Light1");
pLight1->setType(Ogre::Light::LT_POINT);//點光源
pLight1->setPosition(100, 20, 0);
pLight1->setDiffuseColour(1.0f, 1.0f, 1.0f);//漫反射顔色
Ogre::Entity *pLightEnt1=mSceneMgr->createEntity("sphere1","sphere.mesh");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
Ogre::SceneNode *pLightNode1=pNode->createChildSceneNode("LightNode1");
pLightNode1->attachObject(pLightEnt1);
pLightNode1->setPosition(100, 20, 0);
pLightNode1->setScale(0.1f, 0.1f, 0.1f);
//建立燈光2,聚光燈,聚光燈有位置,有方向,參與陰影計算
Ogre::Light *pLight2=mSceneMgr->createLight("Light2");
pLight2->setType(Ogre::Light::LT_SPOTLIGHT);//聚光燈
pLight2->setPosition(0, 100, 0);//聚光燈的位置
pLight2->setDirection(Ogre::Vector3(1, -1, 0));//方向
pLight2->setSpotlightInnerAngle(Ogre::Degree(5.0f));//内角
pLight2->setSpotlightOuterAngle(Ogre::Degree(15.0f));//外角
pLight2->setSpotlightFalloff(0.0f);//衰減
pLight2->setDiffuseColour(Ogre::ColourValue(0.0f, 1.0f, 0.0f));//漫反射
Ogre::Entity *pLightEnt2=mSceneMgr->createEntity("sphere2","sphere.mesh");
Ogre::SceneNode *pLightNode2=pNode->createChildSceneNode("LightNode2");
pLightNode2->attachObject(pLightEnt2);//将實體關聯到節點
//pLightNode2->attachObject(pLight2)将聚光燈關聯到節點
pLightNode2->setPosition(0, 100, 0);//指定節點,也就是聚光燈的位置
pLightNode2->setScale(0.1f, 0.1f, 0.1f);
//建立燈光3,方向光,方向光沒有位置,有方向,參與陰影計算
Ogre::Light *pLight3=mSceneMgr->createLight("Light3");
pLight3->setType(Ogre::Light::LT_DIRECTIONAL);//方向光
pLight3->setDiffuseColour(Ogre::ColourValue(1.0f, 0.0f, 0.0f));//漫反射
pLight3->setDirection(Ogre::Vector3(1, -1, 0));
//建立模型實體
Ogre::Entity *pSinbadEnt=mSceneMgr->createEntity("Sinbad1","Sinbad.mesh");
m_pSinbadNode= pNode->createChildSceneNode("Sinbad1");
m_pSinbadNode->attachObject(pSinbadEnt);
m_pSinbadNode->setPosition(Ogre::Vector3(61.0f, 4.0f, 0.0f));
m_pSinbadNode->setScale(3.0, 3.0, 3.0);
//添加陰影
mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
}
void MyExampleApplication::createNewCamera()//建立相機,添加視口
{
Camera*mpNewCamera =mSceneMgr->createCamera("MyCamera1");
mpNewCamera->setPosition(0, 100, 200);
mpNewCamera->lookAt(0, 0, 0);
mpNewCamera->setNearClipDistance(5);//近距離...從圓台到近面闆...
//mpNewCamera->setPolygonMode(Ogre::PM_WIREFRAME);//多線段模式,PM_WIREFRAME(線框模式)
//mpNewCamera->setPolygonMode(Ogre::PM_POINTS); //點模式
//mpNewCamera->setPolygonMode(Ogre::PM_SOLID); //實線模式,也是預設模式
//建立視口(viewport),要想添加視口不崩,必須給視口設定一個ZOrder,且ZOrder全局唯一,
//當視口多餘1個時,需要為每個視口指定left,top,width,height,否則ZOrder值大的會覆寫ZOrder值小的視口
Ogre::Viewport *pvp =mWindow->addViewport(mpNewCamera, 1, 0, 0, 0.2, 1);
pvp->setBackgroundColour(ColourValue(0.0f,0.0f, 1.0f));
mpNewCamera->setAspectRatio(Real(pvp->getActualWidth())/Real(pvp->getActualHeight()));
}
5:添加一個類:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(SceneNode *pSinbadNode,RenderWindow*win,Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移動相機
virtualboolframeEnded(constFrameEvent&evt);//循環重新整理界面
protected:
SceneNode*m_pSinbadNode;//模型實體節點
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(SceneNode*pSinbadNode,RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy),m_pSinbadNode(pSinbadNode)
{
//啟用了鍵鼠柄的緩沖,就能使用它們的回調函數
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//鍵盤的鍵按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//釋放按下的鍵
{
mTranslateVector= Vector3::ZERO;//防止按鍵釋放後還繼續移動相機
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.X.rel * 0.13);//轉為弧度,如:Degree(180)
mRotY= Degree(-ms.Y.rel * 0.13);//轉為弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera() //移動相機
{
mCamera->yaw(mRotX); //繞Y軸轉動
mCamera->pitch(mRotY);//繞X軸轉動
mCamera->moveRelative(mTranslateVector);//移動相機
mRotX= mRotY = 0; //防止滑鼠不轉動後繼續轉動相機
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
//ExampleFrameListener::frameEnded(evt);//可以不用
m_pSinbadNode->translate(mTranslateVector);//模型移動
moveCamera();//移動相機
returntrue;
}
6:LightCameraShadow.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationapp;
app.go();
return0;
}
四:模型動畫,走動,跳動,切換武器,攻擊動畫等和 相機跟蹤,相機跟蹤模型實體與跟蹤旋轉等,外帶相機節點
綁定另一個模型實體,模型實體繞的是相機節點所在點轉動, 而相機卻是繞相機lookAt的點轉動.
(程式為 遊戲類程式設計/Ogre/Ogre1.73/ Animating)
1:建立一個空的 win32控制台應用程式, 命名為:Animating
2:添加一個 Animating.cpp檔案.
3:配置跟 FirstOGRE的3,4,5項一樣.
4:添加一個類:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include <OGRE/ExampleApplication.h>
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//建立螢幕(設定燈光,材質,相機,建立實體節點等)
voidcreateFrameListener(void);//建立幀監聽
protected:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除監聽
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//設定環境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//設定錄影機位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//設定錄影機方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//設定天空盒
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera, true, true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
5:添加一個類:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
using namespaceOgre;
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移動相機
virtualboolframeEnded(constFrameEvent&evt);//循環重新整理界面
voidcreateEntity();//建立實體
protected:
Entity *m_pSinbadEnt;//模型實體
SceneNode*m_pSinbadNode;//模型節點
AnimationState*m_pAniState;//動畫
Entity*m_pSword1;//武器劍1
Entity*m_pSword2;//武器劍2
RibbonTrail*m_pSwordTrail;//絲帶
boolm_bUseSword;//預設情況下為true,即劍在手上
Realm_fUseSwordTime;//使用武器動畫時長
boolm_bAttack; //攻擊動畫是否啟用
Realm_fAttackTime;//攻擊時長
boolm_bJump; //跳
Realm_fJumpTime;//跳動時長
SceneNode*m_pCameraNode;//關聯相機節點
Vector3m_moveVector;//移動向量
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy)
{
//啟用了鍵鼠柄的緩沖,就能使用它們的回調函數
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
createEntity(); //建立實體
m_bAttack= false; //攻擊動畫不啟用
m_fAttackTime= 0.0f;
m_bUseSword= true;//預設使用武器
m_fUseSwordTime= -1.0f; //防止動畫重複,使用武器動畫時長
m_bJump= false; //預設不跳
m_fJumpTime= 0.0f;
m_moveVector= Vector3::ZERO;
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//鍵盤的鍵按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x =moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x = -moveScale;//Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z =moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z = -moveScale;//Move camera backward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
case OIS::KC_E: //使用武器
{
m_fUseSwordTime= 0.0f;
if(m_bUseSword){//将武器放到背上
m_bUseSword= false;
} else{ //将武器放到手上
m_bUseSword= true;
}
}
break;
caseOIS::KC_SPACE://跳動
m_bJump= true;
break;
}
if(0 != mTranslateVector.x || 0 != mTranslateVector.z){ //走動
m_pAniState= m_pSinbadEnt->getAnimationState("RunBase");
m_pAniState->setEnabled(true);
m_pAniState= m_pSinbadEnt->getAnimationState("RunTop");
m_pAniState->setEnabled(true);
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//釋放按下的鍵
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x = 0.0f;
break;
caseOIS::KC_W:
caseOIS::KC_UP:
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z = 0.0f;
break;
caseOIS::KC_PGUP:
caseOIS::KC_PGDOWN:
mTranslateVector.y = 0.0f;
break;
caseOIS::KC_SPACE://停止跳動
m_bJump= false;
break;
}
if(0 == mTranslateVector.x && 0 == mTranslateVector.z){ //停止走動
m_pAniState= m_pSinbadEnt->getAnimationState("RunBase");
m_pAniState->setEnabled(false);
m_pAniState= m_pSinbadEnt->getAnimationState("RunTop");
m_pAniState->setEnabled(false);
}
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.Y.rel * 0.13);//轉為度數,如:Degree(180)
mRotY= Degree(-ms.X.rel * 0.13);//轉為度數,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
m_bAttack= true;//開始攻擊
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
m_bAttack= false;//停止攻擊
returntrue;
}
void MyEntityFrameListener::moveCamera() //移動相機
{
m_pSinbadNode->yaw(mRotY);//模型實體節點繞自身Y軸轉動
m_pCameraNode->yaw(mRotY,Node::TS_WORLD);//m_pCameraNode節點綁定的相機會繞着m_pSinbadNode節點所在點轉,但是
//m_pCameraNode節點是繞着自己所在的點轉,而不是m_pSinbadNode節點所在的點
m_pCameraNode->pitch(mRotX);
mRotX= mRotY = Radian(0);//防止滑鼠不轉動後繼續轉動相機
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
// *******************************換武器動畫
m_pAniState= m_pSinbadEnt->getAnimationState("DrawSwords");
if(0.0f== m_fUseSwordTime){ //隻要m_fUseSwordTime時間為0,就表示要切換武器
m_pAniState->setEnabled(true);
}
if(0.0f<= m_fUseSwordTime && m_fUseSwordTime <= m_pAniState->getLength()){ //值在0.0f與動畫時長之間,就運作動畫,一個完整的動畫
m_pAniState->addTime(evt.timeSinceLastFrame);
m_fUseSwordTime+= evt.timeSinceLastFrame;
}
if (m_fUseSwordTime >=m_pAniState->getLength()){//動畫結束
m_pAniState->setEnabled(false);
m_fUseSwordTime= -1.0f; //防止動畫重複
m_pSinbadEnt->detachAllObjectsFromBone();
if(m_bUseSword){//使用武器
m_pSinbadEnt->attachObjectToBone("Handle.L",m_pSword1);
m_pSinbadEnt->attachObjectToBone("Handle.R",m_pSword2);
} else{ //解除安裝武器
m_pSinbadEnt->attachObjectToBone("Sheath.L",m_pSword1);
m_pSinbadEnt->attachObjectToBone("Sheath.R",m_pSword2);
}
}
/
//紋理坐标小于1塊紋理,用于滾動紋理
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(0,0.2);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(0.2,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(0.2,0.2);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
//通過點索引構造兩個三角形
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");//将手工對象轉為Mesh
//通過Mesh建立實體
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::createManual1()//旋轉紋理
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial6",RenderOperation::OT_TRIANGLE_LIST);
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(0,1);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(1,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
//pEnt->setMaterialName("myMaterial7");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::createShader1() //紋理着色
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial9",RenderOperation::OT_TRIANGLE_LIST);
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(0,1);//紋理坐标
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(1,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::createShader2()//顔色着色
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial10",RenderOperation::OT_TRIANGLE_LIST);
pManual->position(5.0, 0.0, 0.0);
pManual->colour(0, 0, 1);
pManual->position(-5.0, 10.0, 0.0);
pManual->colour(0, 1, 0);
pManual->position(-5.0, 0.0, 0.0);
pManual->colour(0, 1, 0);
pManual->position(5.0, 10.0, 0.0);
pManual->colour(0, 0, 1);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::setEntMaterial()//給實體設定自定義的材質
{
Ogre::Entity *pEnt =mSceneMgr->createEntity("Entity1","Sinbad.mesh");
pEnt->setMaterialName("myMaterial11");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
pNode->scale(6.0, 6.0, 6.0);
}
//myMaterial.material, Ogre3DBeginnersGuideShaders.cg
6:myMaterial.material的内容:
//材質
//給材質命名
material myMaterial
{
//技術
technique
{
//通道
pass
{
//關閉燈光
lighting off
//場景混合,alpha混合
scene_blend alpha_blend
depth_write off
//漫反射頂點顔色
diffuse vertexcolor
texture_unit
{
texture terr_rock6.jpg//leaf.png
tex_address_mode clamp
}
}
}
}
//在大于1塊紋理時,多餘的紋理部分,重複模式紋理(重複繪制紋理)
material myMaterial1
{
technique
{
pass
{
texture_unit
{
texture leaf.png
}
}
}
}
//在大于1塊紋理時,多餘的紋理部分,材質不拉伸,材質邊緣延伸填充
material myMaterial2
{
technique
{
pass
{
texture_unit
{
texture terr_rock6.jpg
//材質不拉伸,材質邊緣延伸填充
tex_address_mode clamp
}
}
}
}
//在大于1塊紋理時,多餘的紋理部分由紋理邊框産生
material myMaterial3
{
technique
{
pass
{
texture_unit
{
texture leaf.png
//邊框模式,多餘的紋理部分由邊框産生
tex_address_modeborder
tex_border_colour 1.00.0 0.0
}
}
}
}
//在大于1塊紋理時,多餘的紋理部分,鏡像産生
material myMaterial4
{
technique
{
pass
{
texture_unit
{
texture leaf.png
//鏡像模式
tex_address_modemirror
}
}
}
}
//滾動紋理
material myMaterial5
{
technique
{
pass
{
texture_unit
{
texture leaf.png
scroll 0.8 0.8
scroll_anim 0.1 0.1
}
}
}
}
//旋轉紋理
material myMaterial6
{
technique
{
pass
{
texture_unit
{
texture leaf.png
rotate_anim 0.1
}
}
}
}
//材質可以繼承,繼承上一期紋理的滾動屬性
material myMaterial7 : myMaterial6
{
set_texture_alias texture1Water02.jpg
}
//
//片段着色
fragment_program MyFragmentShader1 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_pointMyFragmentShader1A
profiles ps_2_0 arbfp1
}
//頂點着色
vertex_program MyVertexShader1 cg
{
//嵌入一段cg程式
source Ogre3DBeginnersGuideShaders.cg
//指出該cg程式的入口函數,按cg标準,預設入口為main
entry_point MyVertexShader1A
//D3D vs_1_1 标準,或openglarbvp1标準,Ogre自動檢查是硬體是否支援
profiles vs_2_0 arbvp1
default_params
{
param_named_auto worldViewMatrixworldviewproj_matrix
}
}
material myMaterial8
{
technique
{
pass
{
vertex_program_refMyVertexShader1
{
}
fragment_program_refMyFragmentShader1
{
}
//貼圖
texture_unit
{
texturegrass_1024.jpg
}
}
}
//如果顯示卡不支援頂點程式,系統會選擇使用下面的技術通道(普通貼圖)
technique
{
pass
{
alpha_rejection greater150
scene_blend alpha_blend
cull_hardware none
cull_software none
texture_unit
{
texture gras_02.png
}
}
}
}
//
vertex_program MyVertexShader2 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_point MyVertexShader2A
profiles vs_2_0 arbvp1
default_params
{
param_named_autoworldViewMatrix worldviewproj_matrix
}
}
material myMaterial9
{
technique
{
pass
{
vertex_program_refMyVertexShader2
{
}
fragment_program_refMyFragmentShader1
{
}
texture_unit
{
textureterr_rock6.jpg
}
}
}
}
//
fragment_program MyFragmentShader3 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_pointMyFragmentShader3A
profiles ps_2_0 arbfp1
}
vertex_program MyVertexShader3 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_point MyVertexShader3A
profiles vs_2_0 arbvp1
default_params
{
param_named_auto worldViewMatrixworldviewproj_matrix
}
}
material myMaterial10
{
technique
{
pass
{
vertex_program_refMyVertexShader3
{
}
fragment_program_refMyFragmentShader3
{
}
}
}
}
//
fragment_program MyFragmentShader4 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_pointMyFragmentShader4A
profiles ps_2_0 arbfp1
}
vertex_program MyVertexShader4 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_point MyVertexShader4A
profiles vs_2_0 arbvp1
default_params
{
param_named_autoworldViewMatrix worldviewproj_matrix
//添加脈沖,系統内部變量使用param_named_auto
param_named_auto pulseTimetime
//自定義變量offset,前面隻能用param_named
param_named offset float40.3 0.85 0.7 1
}
}
material myMaterial11
{
technique
{
pass
{
vertex_program_refMyVertexShader4
{
}
fragment_program_refMyFragmentShader4
{
}
texture_unit
{
texture leaf.png
}
}
}
}
7:Ogre3DBeginnersGuideShaders.cg的内容:
//
//
void MyVertexShader2A(float4 position:POSITION, out float4oPosition:POSITION,
float2uv:TEXCOORD0, out float2 oUv:TEXCOORD0, uniform float4x4 worldViewMatrix)
{
oPosition = mul(worldViewMatrix,position);
oPosition.z += oPosition.x;
oPosition.y += oPosition.x;
oUv = uv+0.1;
}
//
void MyFragmentShader3A(float4 color : COLOR, out float4 oColor :COLOR)
{
oColor = color;
oColor.b = 0.5;
}
void MyVertexShader3A(float4 position:POSITION, out float4oPosition:POSITION,
float4color:COLOR, out float4 ocolor:COLOR, uniform float4x4 worldViewMatrix)
{
oPosition =mul(worldViewMatrix, position);
ocolor = color;
ocolor.b = 0.2;
}
//
void MyFragmentShader4A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
color =float4(temp_color.r+0.7, temp_color.g+0.5, temp_color.b+0.2, 0);
}
void MyVertexShader4A(uniform float pulseTime, float4position:POSITION, out float4 oPosition:POSITION,
float2uv:TEXCOORD0, out float2 oUv:TEXCOORD0, uniform float4x4 worldViewMatrix
,uniformfloat4 offset)
{
oPosition =mul(worldViewMatrix, position);
oPosition.x *=(2+sin(pulseTime));
oPosition *= offset;
oUv = uv;
}
//
//對每個頂點計算搖擺位置及顔色
七:組合材質以及視口的實作,組合材質設定參數,組合監聽等
(程式為遊戲類程式設計/Ogre/Ogre1.73/CompositorFramework)
1:建立一個空的 win32控制台應用程式,命名為:CompositorFramework
2:添加一個 CompositorFramework.cpp檔案.
3:配置跟 FirstOGRE的3,4,5項一樣.
4:添加一個類:MyEntityFrameListener,内容與 五 中的MyEntityFrameListener一緻
5:添加一個 材質組合類,用于設定材質參數等:MyCompositorListener
MyCompositorListener.h:
//材質組合監聽類,組合材質僅僅針對視口使用
#ifndef _MyCompositorListener_H_
#define _MyCompositorListener_H_
#include <ogre/OgreCompositorInstance.h>
using namespaceOgre;
class MyCompositorListener: public CompositorInstance::Listener
{
public:
MyCompositorListener(void);
~MyCompositorListener(void);
voidnotifyMaterialSetup(uint32pass_id,MaterialPtr&mat);
//virtualvoid notifyMaterialRender(uint32 pass_id, MaterialPtr &mat);
protected:
int m_index;
};
#endif
MyCompositorListener.cpp:
#include <ogre/OgreTechnique.h>
#include "MyCompositorListener.h"
MyCompositorListener::MyCompositorListener(void)
{
m_index= 0;
}
MyCompositorListener::~MyCompositorListener(void)
{
}
void MyCompositorListener::notifyMaterialSetup(uint32pass_id,MaterialPtr&mat)
{
if(1 == m_index){//第二個pass裡面才有下面兩個參數,兩個pass的pass_id都是0???
mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters()->setNamedConstant("numpixels",1250.0f);
mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters()->setNamedConstant("factors",Vector3(1.0f, 0.0f, 0.0f));
}
m_index++;
}
6:添加一個類:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include <OGRE/ExampleApplication.h>
#include "MyEntityFrameListener.h"
#include "MyCompositorListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//建立螢幕(設定燈光,材質,相機,建立實體節點等)
voidcreateFrameListener(void);//建立幀監聽
voidcompositor();//組合,組合材質僅僅針對視口使用
voidcreateCamera(); //添加分屏,添加2個相機
voidcreateViewports();//添加分屏,添加3個視口
private:
MyEntityFrameListener*m_pFrameLst;
MyCompositorListener *m_pCompositorLst;
Ogre::Camera *mCamera2;
Ogre::Viewport *pVp1;
Ogre::Viewport *pVp2;
Ogre::Viewport *pVp3;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
m_pCompositorLst= NULL;
pVp1= NULL;
pVp2= NULL;
pVp3= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除監聽
deletem_pFrameLst;
m_pFrameLst= NULL;
}
if (NULL !=m_pCompositorLst){
deletem_pCompositorLst;
m_pCompositorLst= NULL;
}
//視口不在本類中釋放空間
if (NULL !=pVp1){
pVp1= NULL;
}
if (NULL !=pVp2){
pVp2= NULL;
}
if (NULL !=pVp3){
pVp3= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//設定環境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort= mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//設定錄影機位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//設定錄影機方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//設定天空盒
compositor();//組合,組合材質僅僅針對視口使用
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera,true, true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::compositor() //組合,組合材質僅僅針對視口使用,myMaterial.material, myCg.cg
{
Ogre::Entity *pEnt =mSceneMgr->createEntity("Entity1","Sinbad.mesh");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
pNode->scale(3.0f, 3.0f, 3.0f);
CompositorManager::getSingleton().addCompositor(pVp1,"Compositor4");
CompositorManager::getSingleton().setCompositorEnabled(pVp1,"Compositor4",true);
//為視口的材質組合添加監聽
m_pCompositorLst= new MyCompositorListener();
CompositorInstance*pComp =CompositorManager::getSingleton().getCompositorChain(pVp1)->getCompositor("Compositor4");
pComp->addListener(m_pCompositorLst);
}
void MyExampleApplication::createCamera()//添加分屏,添加2個相機
{
mCamera= mSceneMgr->createCamera("MyCamera1");
mCamera->setPosition(0,10,20);
mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(5);
mCamera2= mSceneMgr->createCamera("MyCamera2");
mCamera2->setPosition(20,10,0);
mCamera2->lookAt(0,0,0);
mCamera2->setNearClipDistance(5);
}
void MyExampleApplication::createViewports()//添加分屏,添加3個視口
{
//一個相機mCamera可以建立多個視口,并且添加的各個視口的ZOrder必須唯一
pVp1= mWindow->addViewport(mCamera, 0, 0.0, 0.0, 0.5, 0.5);
pVp1->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
pVp2= mWindow->addViewport(mCamera, 1, 0.0, 0.5, 0.5, 1.0);
pVp2->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
pVp3= mWindow->addViewport(mCamera2, 3, 0.5, 0.0, 0.5, 1.0);
pVp3->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
//設定相機長寬比
mCamera->setAspectRatio(Real(pVp1->getActualWidth())/Real(pVp1->getActualHeight()));
mCamera2->setAspectRatio(Real(pVp3->getActualWidth())/Real(pVp3->getActualHeight()));
}
//myMaterial.material, myCg.cg
7:myMaterial.material的内容:
//
fragment_program MyFragmentShader4 cg
{
source myCg.cg
entry_pointMyFragmentShader4A
profiles ps_2_0 arbfp1
//傳遞給MyFragmentShader4A的參數,數字越大越清晰
default_params
{
param_named numpixelsfloat 50
param_named factors float4 0.2 0.6 0.3 0
}
}
material Ogre3DBeginnersGuide/Comp4
{
technique
{
pass
{
fragment_program_refMyFragmentShader4
{
}
texture_unit
{
}
}
}
}
compositor Compositor4
{
technique
{
texture scene target_widthtarget_height PF_R8G8B8
target scene
{
input previous
}
target scene
{
input none
pass render_quad
{
materialOgre3DBeginnersGuide/Comp2
input 0 scene
}
}
target_output
{
input none
pass render_quad
{
materialOgre3DBeginnersGuide/Comp4
input 0 scene
}
}
}
}
8:myCg.cg的内容:
//以下為片段着色程式,片斷着色程式對每個片斷進行獨立的顔色計算,最後輸出顔色值的就是該片段最終顯示的顔色。
//可以這樣說,頂點着色程式主要進行幾何方面的運算,而片段着色程式主要針對最終的顔色值進行計算。
void MyFragmentShader1A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
color =float4(1.0-temp_color.r, 1.0-temp_color.g, 1.0-temp_color.b, 0);
}
void MyFragmentShader2A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
float greyvalue =temp_color.r*0.3 + temp_color.g*0.59 + temp_color.b*0.11;
color =float4(greyvalue,greyvalue,greyvalue,0);
}
void MyFragmentShader3A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color = tex2D(texture,uv);
color =float4(temp_color.r+0.5, temp_color.g+0.2, temp_color.b+0.3, 0);
}
//在材質中添加像素數量numpixels和一個顔色通道(修改顔色值)
void MyFragmentShader4A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture, uniform float numpixels, uniform float4 factors)
{
//float num = 50;
float num = numpixels;
float stepsize = 1.0/ num;
//floor樓面處理,numpixels越大越清晰,越小越不清晰
float2 fragment =float2(stepsize*floor(uv.x*num), stepsize*floor(uv.y*num));
color = tex2D(texture,fragment);
color *= factors;
}
八:實作類似于 Ogre的 ExampleApplication 與 ExampleFrameListener 的類
(程式為 遊戲類程式設計/Ogre/Ogre1.73/Startup)
1:建立一個空的 win32控制台應用程式,命名為:Startup
2:添加一個 Startup.cpp檔案.
3:配置跟 FirstOGRE的3,4,5項一樣.
4:添加一個類:MyFrameListener
MyFrameListener.h:
#ifndef _MyFrameListener_H_
#define _MyFrameListener_H_
#include <ogre/Ogre.h>
using namespaceOgre;
#define OIS_DYNAMIC_LIB
#include <OIS/OIS.h>
class MyFrameListener:public FrameListener,publicOIS::KeyListener,public OIS::MouseListener,public WindowEventListener
{
public:
MyFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false,bool bufferedMouse= false, bool bufferedJoy = false);
~MyFrameListener(void);
public:
//鍵盤事件
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
//滑鼠事件
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
//幀事件
virtualboolframeStarted(constOgre::FrameEvent&evt);
virtualboolframeRenderingQueued(constOgre::FrameEvent&evt);
virtualboolframeEnded(constOgre::FrameEvent&evt);
//移動相機
virtualvoidmoveCamera();
//渲染視窗事件
virtualvoidwindowResized(RenderWindow*rw);
virtualvoidwindowClosed(RenderWindow*rw);
protected:
// OIS輸入控制對象
OIS::InputManager *m_pInputMgr;
OIS::Keyboard *m_pKeyboard;
OIS::Mouse *m_pMouse;
OIS::JoyStick *m_pJoy;
//渲染視窗和相機
Ogre::RenderWindow *m_pWindow;
Ogre::Camera *m_pCamera;
//相機移動轉動事件
Ogre::Vector3m_TranslateVector;
Ogre::Radianm_RotX;
Ogre::Radianm_RotY;
bool m_bSysMouseShowFlag;//是否顯示滑鼠
};
#endif
MyFrameListener.cpp:
#include "MyFrameListener.h"
MyFrameListener::MyFrameListener(RenderWindow*win, Camera*cam, bool bufferedKeys, boolbufferedMouse,boolbufferedJoy)
: m_pWindow(win),m_pCamera(cam),m_TranslateVector(0.0f,0.0f, 0.0f), m_RotY(0), m_RotX(0)
{
m_bSysMouseShowFlag = false;//用于解決滑鼠獨占
ShowCursor(0); //用于解決滑鼠獨占
//建立OIS鍵盤,滑鼠,搖桿等對象
unsignedintwindowHandle= 0;
std::ostringstreamwindowHandleString;
win->getCustomAttribute("WINDOW",&windowHandle);
windowHandleString<< windowHandle;
OIS::ParamListparameters;
parameters.insert(std::make_pair(std::string("WINDOW"),windowHandleString.str()));
parameters.insert(std::make_pair(std::string("w32_mouse"),
std::string("DISCL_FOREGROUND"))); //用于解決滑鼠獨占
parameters.insert(std::make_pair(std::string("w32_mouse"),
std::string("DISCL_NONEXCLUSIVE")));//用于解決滑鼠獨占
m_pInputMgr= OIS::InputManager::createInputSystem(parameters);
m_pKeyboard= static_cast<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard,bufferedKeys));
m_pMouse= static_cast<OIS::Mouse*>(m_pInputMgr->createInputObject(OIS::OISMouse,bufferedMouse));
try{
m_pJoy= static_cast<OIS::JoyStick*>(m_pInputMgr->createInputObject(OIS::OISJoyStick,bufferedJoy));
} catch(...){
m_pJoy= 0;
}
//以下鍵盤,滑鼠回調函數需要在子類中被調用到,才會有keyPressed,mouseMoved等事件
m_pKeyboard->setEventCallback(this);
m_pMouse->setEventCallback(this);
//監聽渲染視窗
WindowEventUtilities::addWindowEventListener(m_pWindow,this);
}
MyFrameListener::~MyFrameListener(void)
{
WindowEventUtilities::removeWindowEventListener(m_pWindow,this);//虛構時删除視窗的監聽,渲染視窗關閉後,m_pWindow對應的值已經不存在
windowClosed(m_pWindow);
}
bool MyFrameListener::keyPressed(constOIS::KeyEvent&arg)
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
m_TranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
m_TranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
m_TranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
m_TranslateVector.z =moveScale;//Move camera backward
break;
caseOIS::KC_PGUP:
m_TranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
m_TranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyFrameListener::keyReleased(constOIS::KeyEvent&arg)
{
m_TranslateVector= Vector3::ZERO;//防止鍵釋放後,相機還在移動
returntrue;
}
bool MyFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
//用于解決滑鼠獨占
if(arg.state.X.abs <m_pWindow->getViewport(0)->getActualLeft()+1
||(arg.state.Y.abs <m_pWindow->getViewport(0)->getActualTop()+1)
||(arg.state.X.abs >m_pWindow->getViewport(0)->getActualLeft()+m_pWindow->getViewport(0)->getActualWidth())
||(arg.state.Y.abs >m_pWindow->getViewport(0)->getActualTop()+m_pWindow->getViewport(0)->getActualHeight())){
if(!m_bSysMouseShowFlag){//滑鼠移出界面
ShowCursor(1);
m_bSysMouseShowFlag=true;
}
} else{ //滑鼠進入界面
if(m_bSysMouseShowFlag){
ShowCursor(0);
m_bSysMouseShowFlag= false;
}
}
if(!m_bSysMouseShowFlag){
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
m_RotX= Degree(-ms.Y.rel * 0.13);//轉為弧度,如:Degree(180)
m_RotY= Degree(-ms.X.rel * 0.13);//轉為弧度,如:Degree(180)
}
}
returntrue;
}
bool MyFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyFrameListener::frameStarted(constOgre::FrameEvent&evt)
{
if(NULL ==m_pWindow)returnfalse; //當視窗為NULL時,傳回false,退出循環(Root->startRendering())
returntrue;
}
bool MyFrameListener::frameRenderingQueued(constOgre::FrameEvent&evt)
{
if(NULL !=m_pInputMgr){//捕捉鍵,鼠,搖桿事件
m_pKeyboard->capture();
m_pMouse->capture();
if(m_pJoy)m_pJoy->capture();
}
returntrue;
}
bool MyFrameListener::frameEnded(constOgre::FrameEvent&evt)
{
moveCamera();//移動相機
returntrue;
}
void MyFrameListener::moveCamera()//移動相機
{
m_pCamera->pitch(m_RotX);
m_pCamera->yaw(m_RotY);
m_pCamera->moveRelative(m_TranslateVector);
m_RotX= m_RotY = 0.0f;
}
void MyFrameListener::windowResized(RenderWindow*rw)
{
}
void MyFrameListener::windowClosed(RenderWindow*rw)
{
if(rw ==m_pWindow)
{
if(m_pInputMgr)//釋放鍵,鼠,搖桿等對象
{
m_pInputMgr->destroyInputObject(m_pMouse);
m_pInputMgr->destroyInputObject(m_pKeyboard);
m_pInputMgr->destroyInputObject(m_pJoy);
OIS::InputManager::destroyInputSystem(m_pInputMgr);
m_pInputMgr= NULL;
}
m_pWindow= NULL;//視窗關閉時,此值置為NULL,用于退出循環(Root->startRendering())
}
}
5:添加一個類:MyApplication
MyApplication.h:
#ifndef _MyApplication_H_
#define _MyApplication_H_
#include "MyFrameListener.h"
#include <ogre/Ogre.h>
using namespaceOgre;
class MyApplication
{
public:
MyApplication(void);
~MyApplication(void);
public:
voidgo();
virtualvoidcreateScene(); //建立場景
virtualvoidcreateListener();//建立監聽
protected:
Ogre::Root *m_pRoot;
Ogre::RenderWindow *m_pWindow;
Ogre::SceneManager *m_pSceneManager;
Ogre::Camera *m_pCamera;
Ogre::Viewport *m_pViewport;
Entity*m_pEnt;
MyFrameListener*m_pFrameLst;
};
#endif
MyApplication.cpp:
#include "MyApplication.h"
MyApplication::MyApplication(void)
{
m_pRoot= NULL;
m_pWindow= NULL;
m_pSceneManager= NULL;
m_pCamera= NULL;
m_pViewport= NULL;
m_pEnt= NULL;
m_pFrameLst= NULL;
}
MyApplication::~MyApplication(void)
{
m_pSceneManager->destroyAllEntities();
m_pEnt= NULL;
m_pSceneManager->getRootSceneNode()->removeAndDestroyAllChildren();
if(NULL !=m_pRoot){//釋放root資源
m_pRoot->removeFrameListener(m_pFrameLst);
deletem_pRoot;
m_pRoot= NULL;
m_pFrameLst= NULL;
}
}
void MyApplication::go()
{
//建立Root,視窗,場景管理
m_pRoot= new Ogre::Root("plugins_d.cfg","ogre.cfg","ogre.log");
if(!m_pRoot->restoreConfig()){//啟動時不顯示Ogre的配置視窗,要求必須有ogre.cfg
if(!m_pRoot->showConfigDialog()){//啟動時顯示Ogre的配置視窗,如果沒有ogre.cfg
return;
} else{
m_pRoot->saveConfig();//儲存一個 ogre.cfg
}
}
m_pWindow= m_pRoot->initialise(true,"渲染視窗");
m_pSceneManager= m_pRoot->createSceneManager(Ogre::ST_GENERIC,"ExampleSMInstance");
//建立相機與視口
m_pCamera= m_pSceneManager->createCamera("Camera");
m_pCamera->setPosition(Vector3(0.0f,0.0f, 50.0f));
m_pCamera->lookAt(Vector3(0.0f,0.0f, 0.0f));
m_pCamera->setNearClipDistance(5);
m_pViewport= m_pWindow->addViewport(m_pCamera);
m_pViewport->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
m_pCamera->setAutoAspectRatio(Real(m_pViewport->getActualWidth())/Real(m_pViewport->getActualHeight()));
//載入單個資源
//ResourceGroupManager::getSingleton().addResourceLocation("media/packs/Sinbad.zip","Zip", "Popular");
//ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
//從檔案載入資源
ConfigFilecf;
cf.load("resources_d.cfg");
ConfigFile::SectionIteratorsectionIter= cf.getSectionIterator();
StringsectionName,typeName,dataName;
while(sectionIter.hasMoreElements()){
sectionName= sectionIter.peekNextKey();
ConfigFile::SettingsMultiMap *settings=sectionIter.getNext();
ConfigFile::SettingsMultiMap::iteratormultiMapIter;
for(multiMapIter =settings->begin();multiMapIter!= settings->end();multiMapIter++){
typeName= multiMapIter->first;
dataName= multiMapIter->second;
ResourceGroupManager::getSingleton().addResourceLocation(dataName,typeName,sectionName);
}
}
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
createScene(); //建立場景
createListener();//建立監聽
m_pRoot->startRendering();//開始渲染,需要FrameListener類的frameStarted或frameRenderingQueued或frameEnded函數傳回false才會退出循環
}
void MyApplication::createScene()//建立場景
{
m_pEnt= m_pSceneManager->createEntity("Sinbad.mesh");//建立實體
m_pSceneManager->getRootSceneNode()->attachObject(m_pEnt);
}
void MyApplication::createListener()//建立監聽,Root類必須有幀監聽類,否則startRendering無法退出,其它看上面的startRendering後的解釋
{
m_pFrameLst= new MyFrameListener(m_pWindow,m_pCamera,true,true, true);
m_pRoot->addFrameListener(m_pFrameLst);
}
6:Startup.cpp的内容:
#include "MyApplication.h"
int main(){
MyApplicationapp;
app.go();
return0;
}
九:粒子系統和擴充Ogre3D (程式為 遊戲類程式設計/Ogre/Ogre1.73/ParticleSystems)
1:建立一個空的 win32控制台應用程式,命名為:ParticleSystems
2:添加一個 ParticleSystems.cpp檔案.
3:配置跟 FirstOGRE的3,4,5項一樣.
4:添加一個類:MyEntityFrameListener,内容與 五 中的MyEntityFrameListener一緻
5:添加一個類:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include <OGRE/ExampleApplication.h>
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//建立螢幕(設定燈光,材質,相機,建立實體節點等)
voidcreateFrameListener(void);//建立幀監聽
voidcreateParticle();//建立粒子系統
private:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除監聽
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//設定環境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 500.0f);//設定錄影機位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//設定錄影機方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//設定天空盒
createParticle();//建立粒子系統
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera, true,true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::createParticle()//建立粒子系統
{
//通過模闆建立粒子系統,粒子系統需要一個發射器,粒子,顔色修改器
Ogre::ParticleSystem*partSystem= mSceneMgr->createParticleSystem("Smoke","MySwarm");//MySmokePoint Examples/Smoke Examples/Fireworks
SceneNode*pNode =mSceneMgr->getRootSceneNode()->createChildSceneNode();
pNode->attachObject(partSystem);
pNode->setPosition(1, 10, 0);
}
//myParticle.particle,myMaterial.material
6:myMaterial.material的内容:
//材質
//給材質命名
material myMaterial
{
//技術
technique
{
//通道
pass
{
//關閉燈光
lighting off
//場景混合,alpha混合
scene_blend alpha_blend
depth_write off
//漫反射頂點顔色
diffuse vertexcolor
texture_unit
{
texture smoke.png
//tex_address_modeclamp,//材質不拉伸,材質邊緣延伸填充,具體看材質方面的執行個體
}
}
}
}
7:myParticle.particle的内容:
//粒子系統:需要一個發射器,粒子,顔色修改器等
//billboard_type point: 粒子的頭尾與XZ面是垂直的
//billboard_type oriented_self: 粒子的頭尾連線是指向原點的,即與XZ平面有夾角,(雷射射線,焰火,隨着粒子改變方向,公告闆也重定向它自己面向這個方向)
//billboard_type oriented_common:粒子的頭尾連線都是平行于XY面(粒子面向一個共同的固定的方向向量),(暴風雨,流星,較oriented_self略快)
//perpendicular_common:粒子垂直于一個共同的固定的方向向量
//perpendicular_self: 粒子垂直于它們自己的方向向量
//billboard_type oriented_common與common_direction 0 -1 0改變粒子在Y軸的方向,common_direction好像無法與billboard_type point結合
//
particle_system MySmoke_Point_oriented_self
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_type oriented_self
emitter Point
{
emission_rate 100
direction 0 1 0
angle 30
velocity 20
time_to_live 10
colour_range_start 1 0 0 1
colour_range_end 0.5 0.5 0.5 0.1
}
}
particle_system MySmoke_Point_point
{
//粒子材質名稱,粒子寬度,粒子高度myMaterial
material Examples/Flare2
particle_width 5
particle_height 5
//粒子配額(數量)和 類型 point 與 oriented_self的差別是,point粒子的頭尾與XZ面是垂直的,
//而oriented_self的頭尾連線是指向原點的,即與XZ平面有夾角
quota 500
billboard_type point
//點發射器
emitter Point
{
//每秒發出10個
emission_rate 100
//發射方向
direction 0 1 0
//速度
velocity 20
//最小速度和最大速度
//velocity_min 50
//velocity_max80
//角度,粒子存活時長10秒,頂點顔色
angle 30
//time_to_live10//粒子存活時長10秒
//粒子存活最短時長和最大時長
time_to_live_min1
time_to_live_max6
//colour 1 0 0 1//頂點顔色
//頂點起始顔色和結束顔色
//colour_range_start 1 0 0 1
//colour_range_end 0.5 0.5 0.5 0.1
//連續發射時長,和等待發射時長,發1秒,隔1秒
//duration 1
//repeat_delay 1
}
//在粒子存活時段,放大5倍大小
affector Scaler
{
rate 5
}
//導流面闆,粒子碰到此面闆,會向面闆的法向量方向運動
affector DeflectorPlane
{
//面闆點,面闆法向量
plane_point 00 80 0
plane_normal -1 -1 0
bounce 1.0
}
//顔色圖檔,給材質加顔色,相當于colour等
affector ColourImage
{
imagesmokecolors.png
}
//添加随機???
//affectorDirectionRandomiser
//{
// randomness 100
//1代表100%,0代表0%, 保持速度,即速度不改變
// scope 1
// keep_velocity true
//}
//不同時段,粒子顔色不同
}
particle_system MySmoke_Point_oriented_common
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_typeoriented_common
emitter Point
{
emission_rate 100
direction 0 1 0
angle 30
velocity 20
time_to_live 10
colour_range_start 1 0 0 1
colour_range_end 0.5 0.5 0.5 0.1
}
}
//
particle_system MySmoke_Box_oriented_self
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_type oriented_self
emitter Box
{
height 10
width 10
depth 10
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
particle_system MySmoke_Box_point
{
//粒子材質名稱,粒子寬度,粒子高度
material Examples/Flare2
particle_width 5
particle_height 5
//粒子配額(數量)和點類型
quota 5000
billboard_type point
//盒子發射器
emitter Box
{
//定義盒子,高寬深
height 10
width 10
depth 10
//每秒發出100個,發射方向,速度
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
particle_system MySmoke_Box_oriented_common
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_typeoriented_common
emitter Box
{
height 10
width 10
depth 10
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
//
particle_system MySmoke_Ring_oriented_self
{
material myMaterial
particle_width 5
particle_height 5
quota 5000
billboard_type oriented_self
emitter Ring
{
height 50
width 50
inner_height 0.9
inner_width 0.9
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
particle_system MySmoke_Ring_point
{
//粒子材質名稱,粒子寬度,粒子高度
material myMaterial
particle_width 5
particle_height 5
sorted true
//粒子配額(數量)和點類型
quota 500
billboard_type point
emitter Ring
{
//高寬
height 10
width 10
//内部90%部分不發射粒子(百分比)
inner_height 0.9
inner_width 0.9
//每秒發出10個,發射方向,速度
emission_rate 50
direction 0 1 0
velocity 20
time_to_live 10
//angle 30
}
//不同時間段,顔色不同
affector ColourInterpolator
{
time0 0.00
colour0 1 0 0
time1 0.50
colour1 0 1 0
time2 0.70
colour2 0 0 1
}
}
particle_system MySmoke_Ring_oriented_common
{
material myMaterial
particle_width 5
particle_height 5
quota 5000
billboard_typeoriented_common
emitter Ring
{
height 50
width 50
inner_height 0.9
inner_width 0.9
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
//
//一煙沖天
particle_system MySmoke
{
material myMaterial
particle_width 5
particle_height 5
sorted true
quota 500
billboard_type point
emitter Point
{
emission_rate 25
direction 0 1 0
velocity 20
time_to_live 10
}
affector ColourInterpolator
{
time0 0.00
colour0 1 0 0
time1 0.50
colour1 0 1 0
time2 0.70
colour2 0 0 1
}
affector Scaler
{
rate 3
}
affector ColourFader2
{
red1 -0.25
green1 -0.25
blue1 -0.25
state_change 2
red2 +0.25
green2 +0.25
blue2 +0.25
}
}
//煙花爆竹粒子系統(使用了多點發射器)
particle_system myFirework
{
material myMaterial
particle_width 5
particle_height 5
quota 1000
billboard_type point
point_rendering false
cull_each false
//每次發射的數量
emit_emitter_quota 10
//發射器(emitterBox)使用多點發射:explosion
emitter Box
{
height 50
width 50
depth 50
name mainEmitter
emit_emitter explosion
time_to_live 3
direction 0 100 0
velocity 200
}
//explosion:通過Box發射器,爆炸之後得emitterPoint....
emitter Point
{
name explosion
duration 0.1
repeat_delay_min 2
repeat_delay_max 3
emission_rate 1000
direction 0 100 0
velocity 80
angle 90
colour_range_start 0.50.6 0.7
colour_range_end 1 0.7 0.8
}
//下墜向量
affector LinearForce
{
force_vector 0 -100 0
force_application add
}
//不同時間段,顔色不同
affector ColourInterpolator
{
time0 0.00
colour0 1 0 0
time1 0.25
colour1 0 1 0
time2 0.50
colour2 0 0 1
}
}
//下雨粒子系統
particle_system myRain
{
//粒子材質名稱,粒子寬度,粒子高度
material Examples/Droplet
particle_width 50
particle_height 100
//粒子配額(數量)和點類型
quota 500
//直線下墜,直線方向沿Y軸方向(common_direction0 -1 0向Y軸方向)
billboard_type oriented_common
common_direction 0 -1 0
//盒子發射器,
emitter Box
{
angle 0
//定義盒子,高寬深
height 500
width 500
depth 500
//每秒發出10個,發射方向,速度
emission_rate 100
direction 0 -10 0
velocity 200
}
//下落或上升,取決于force_vector的值
affector LinearForce
{
force_vector 0 -100 0
force_application add
}
}
//billboard_type oriented_self + angle 360 + affector DeflectorPlane實作
//在粒子在Box裡面随機方向運動加碰撞轉向運動
particle_system MySwarm
{
material Examples/Flare2
particle_width 12
particle_height 24
quota 500
billboard_type oriented_self
emitter Box
{
angle 360
height 100
width 100
depth 100
emission_rate 50
direction 0 1 0
velocity 20
}
affector DeflectorPlane
{
plane_point 0 -50 0
plane_normal 0 1 0
bounce 1
}
affector DeflectorPlane
{
plane_point 0 50 0
plane_normal 0 -1 0
bounce 1
}
affector DeflectorPlane
{
plane_point 50 0 0
plane_normal -1 0 0
bounce 1
}
affector DeflectorPlane
{
plane_point -50 0 0
plane_normal 1 0 0
bounce 1
}
affector DeflectorPlane
{
plane_point 0 0 50
plane_normal 0 0 -1
bounce 1
}
affector DeflectorPlane
{
plane_point 0 0 -50
plane_normal 0 0 1
bounce 1
}
}
十:主角實體運動與 障礙物判斷,怪物實體向 主角 實體 方向 運動等
(程式為 遊戲類程式設計/Ogre/Ogre1.73/AITest(簡單的測試))
1:建立一個空的 win32控制台應用程式,命名為:AITest
2:添加一個 AITest.cpp檔案.
3:配置跟 FirstOGRE的3,4,5項一樣.
4:代碼 看:AITest(簡單的測試)
十一:地形程式設計(讀取地形配置檔案的地形程式設計)。(程式為遊戲類程式設計/Ogre/Ogre1.73/TerrainCfgFile)
1:建立一個空的 win32控制台應用程式, 命名為:TerrainCfgFile
2:添加一個 TerrainCfgFile.cpp檔案,内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationapp;
app.go();
return 0;
}
3:配置跟 FirstOGRE的3,4,5項一樣.
4:在3的基礎上,需要添加Ogre目錄:
5:需要多引入一個地形庫:OgreTerrain_d.lib
6:添加一個類:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include <OGRE/ExampleApplication.h>
#include <ogre/Terrain/OgreTerrain.h>
#include <ogre/Terrain/OgreTerrainGroup.h>
#include "MyEntityFrameListener.h"
using namespaceOgre;
class MyExampleApplication :public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
virtual void chooseSceneManager(void);//建立螢幕管理
virtual void createCamera(void); //建立相機
void createScene(void); //建立螢幕(設定燈光,材質,相機,建立實體節點等)
void createFrameListener(void);//建立幀監聽
protected:
MyEntityFrameListener *m_pFrameLst;
RaySceneQuery *m_pRaySceneQuery;//射線碰撞查詢器
TerrainGlobalOptions *m_pTerrainGlobals;//地形全局配置
TerrainGroup *m_pTerrainGroup; //地形分組對象
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst = NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除監聽
delete m_pFrameLst;
m_pFrameLst = NULL;
}
}
void MyExampleApplication::chooseSceneManager(void)//建立螢幕管理
{
mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE,"ExampleSMInstance2");//室外封閉場景
}
void MyExampleApplication::createCamera(void)
{
mSceneMgr = mRoot->getSceneManager("ExampleSMInstance2");//根據管理器名稱擷取螢幕管理器
mCamera = mSceneMgr->createCamera("plyerCam2");//建立錄影機
mCamera->setPosition(Vector3(707.0f, 150.0f, 528.0f));//錄影機位置
mCamera->lookAt(Vector3(0.0f, 0.0f, -300.0f));//錄影機的目标點
mCamera->setNearClipDistance(1); //錄影機近距
mCamera->setFarClipDistance(1000);//錄影機遠距
}
void MyExampleApplication::createScene(void)
{
//地形相關
mSceneMgr = mRoot->getSceneManager("ExampleSMInstance2");
mSceneMgr->setAmbientLight(ColourValue(0.5f, 0.5f, 0.5f));//設定場景的環境光
Light *l =mSceneMgr->createLight("MainLight");//建立燈光
l->setPosition(20.0f,80.0f, 50.0f); //設定燈光位置
mSceneMgr->setFog(FogMode::FOG_LINEAR,ColourValue(0.93f, 0.16f, 0.76f), 0.001,500, 1000);//設定霧
mWindow->getViewport(0)->setBackgroundColour(ColourValue(0.93f,0.86f, 0.76f));//設定視口背景
//***************地形塊的全局配置
m_pTerrainGlobals = newOgre::TerrainGlobalOptions();
m_pTerrainGlobals->setLayerBlendMapSize(64);//設定地形層混合圖大小為64x64
m_pTerrainGlobals->setMaxPixelError(8);
m_pTerrainGlobals->setCompositeMapDistance(3000);
m_pTerrainGlobals->setLightMapDirection(l->getDerivedDirection());//設定光線方向,所有地形均采用同一個方向的光
m_pTerrainGlobals->setCompositeMapAmbient(mSceneMgr->getAmbientLight());//設定環境光
m_pTerrainGlobals->setCompositeMapDiffuse(l->getDiffuseColour());//設定漫反射光
m_pTerrainGlobals->setLightMapSize(1500);//設定光線圖的大小,這個數字越小,地圖的陰影将越粗糙
//***************建立地形分組對象,該對象用于建立以及管理地形塊
m_pTerrainGroup = newTerrainGroup(mSceneMgr,Terrain::ALIGN_X_Z,1500, 1500);
m_pTerrainGroup->setOrigin(Vector3(750, 0, 750));
//***************通過地形分組建立地形塊
//設定地形預設屬性
Terrain::ImportData&defalutImp =m_pTerrainGroup->getDefaultImportSettings();
defalutImp.terrainSize= 1500;
defalutImp.worldSize = 1500;
defalutImp.inputScale = 1;
defalutImp.minBatchSize=33;
defalutImp.maxBatchSize=65;
//設定紋理
defalutImp.layerList.resize(1);
defalutImp.layerList[0].worldSize = 8;//每層貼圖wordsize取8為佳
defalutImp.layerList[0].textureNames.push_back("terrain_texture.jpg");
//defalutImp.layerList[0].textureNames.push_back(750);
//設定地形預設屬性
Terrain::ImportData&defaultimp =m_pTerrainGroup->getDefaultImportSettings();
defalutImp.terrainSize= 1500;
defalutImp.worldSize = 1500;
defalutImp.inputScale = 1;
defalutImp.minBatchSize=33;
defalutImp.maxBatchSize=65;
m_pTerrainGroup->defineTerrain(100,100, 10.0f);
//mSceneMgr->setWorldGeometry("myTerrain.cfg"); //設定世界幾何體
//是否支援無限遠的面投影
mCamera = mSceneMgr->getCamera("plyerCam2");//擷取相機
if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE)){
mCamera->setFarClipDistance(0);
}
//建立射線碰撞查詢器,由錄影機位置向Y軸負向發射線進行查詢
m_pRaySceneQuery = mSceneMgr->createRayQuery(Ray(mCamera->getPosition(),Vector3::NEGATIVE_UNIT_Y));
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst = new MyEntityFrameListener(m_pRaySceneQuery,mWindow,mCamera,true, true, true);//啟用各輸入裝置的緩沖
mRoot->addFrameListener(m_pFrameLst);
}
7:添加一個類:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
using namespaceOgre;
class MyEntityFrameListener :public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RaySceneQuery*pRaySceneQuery,RenderWindow*win,Camera* cam, bool bufferedKeys = false,bool bufferedMouse=false, bool bufferedJoy = false);
~MyEntityFrameListener(void);
public:
virtual bool keyPressed(constOIS::KeyEvent &arg);
virtual bool keyReleased(constOIS::KeyEvent &arg);
virtual bool mouseMoved(constOIS::MouseEvent &arg);
virtual bool mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid);
virtual bool mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid);
void moveCamera();//移動相機
virtual bool frameEnded(constFrameEvent& evt);//循環重新整理界面
protected:
SceneManager *mSceneMgr;
RaySceneQuery *m_pRaySceneQuery;//射線碰撞查詢器
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RaySceneQuery *pRaySceneQuery,RenderWindow*win,Camera*cam,bool bufferedKeys,bool bufferedMouse,bool bufferedJoy)
: ExampleFrameListener(win,cam,bufferedKeys,bufferedMouse,bufferedJoy)
{
//啟用了鍵鼠柄的緩沖,就能使用它們的回調函數
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
m_pRaySceneQuery = pRaySceneQuery;//射線碰撞查詢器
mSceneMgr = cam->getSceneManager();
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//鍵盤的鍵按下
{
Real moveScale= 0.2f;
switch(arg.key){
case OIS::KC_A:
case OIS::KC_LEFT:
mTranslateVector.x= -moveScale;//Movecamera left
break;
case OIS::KC_D:
case OIS::KC_RIGHT:
mTranslateVector.x=moveScale; //Move camera RIGHT
break;
case OIS::KC_W:
case OIS::KC_UP:
mTranslateVector.z= -moveScale;//Movecamera forward
break;
case OIS::KC_S:
case OIS::KC_DOWN:
mTranslateVector.z=moveScale; //Move camera backward
break;
case OIS::KC_PGUP:
mTranslateVector.y=moveScale; //Move camera up
break;
case OIS::KC_PGDOWN:
mTranslateVector.y= -moveScale;//Movecamera down
break;
}
return true;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//釋放按下的鍵
{
mTranslateVector = Vector3::ZERO;//防止按鍵釋放後還繼續移動相機
return true;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
const OIS::MouseState &ms=arg.state;
if(ms.buttonDown(OIS::MB_Left)) {
} else if(ms.buttonDown(OIS::MB_Right)){
} else {
mRotX = Degree(-ms.Y.rel * 0.13);//轉為弧度,如:Degree(180)
mRotY = Degree(-ms.X.rel * 0.13);//轉為弧度,如:Degree(180)
}
return true;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
return true;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
return true;
}
void MyEntityFrameListener::moveCamera() //移動相機
{
mCamera->yaw(mRotY); //繞Y軸轉動
mCamera->pitch(mRotX);//繞X軸轉動
mCamera->moveRelative(mTranslateVector);//移動相機
mRotX = mRotY =Radian(0); //防止滑鼠不轉動後繼續轉動相機
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
moveCamera(); //移動相機
static Ray updateRay;//定義一個射線變量
updateRay.setOrigin(mCamera->getPosition());//設定原點為錄影機的位置
updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);//設定方向為Y軸方向
m_pRaySceneQuery->setRay(updateRay);//碰撞查詢器設定射線
RaySceneQueryResult &qryResult=m_pRaySceneQuery->execute();//執行碰撞查詢
//周遊查詢結果
RaySceneQueryResult::iteratoritrRaySQRst =qryResult.begin();
if(itrRaySQRst !=qryResult.end()&&itrRaySQRst->worldFragment){
mCamera->setPosition(mCamera->getPosition().x,itrRaySQRst->worldFragment->singleIntersection.y
+100, mCamera->getPosition().z);//将錄影機設定成地表的位置偏移10
}
return true;
}
8:添加一個地形配置檔案:myTerrain.cfg,放在Media目錄下,内容為:
#WorldTexture,DetailTexture僅用作紋理
#主世界紋理,通過紋理管理器建立一個材質
WorldTexture=terrain_texture.jpg
#詳細紋理,通過紋理管理器建立一個材質 waves2.dds
DetailTexture=terrain_detail.jpg
#平鋪的瓦片數
DetailTile=3
#高位圖資源(相當于模型),指定的高位圖,圖檔為png格式
PageSource=Heightmap
Heightmap.image=terrain.png
#圖檔大小,圖檔頂點數,尺寸必須是方形,必須是(2^n)+1
PageSize=513
#每一個瓦塊大小,必須是(2^n)+1
TileSize=65
#Heightmap.image=waveNM1.raw
#如果使用的是RAW格式的圖檔,指定RAW格式圖檔大小,必須是(2^n)+1
#Heightmap.raw.size=513
#指定使用的像素bit度(1 = 8bit, 2=16bit)
#Heightmap.raw.bpp=1
#如果設定為true,則翻轉高度圖
#Heightmap.flip=true
#當LOD時允許最大的誤差,過高會導緻地形撕裂,過低則會影響性能
MaxPixelError=3
#在世界單元中一個地形頁的大小
PageWorldX=1500
PageWorldZ=1500
#地形的最大高度,用于相乘
MaxHeight=200
#渲染地形使用的細節層次的數目。地形的遠處和平坦處會以低細節渲染
MaxMipMapLevel=5
#VertexNormals=yes
#VertexColors=yes
#UseTriStrips=yes
#使用頂點端變形LODs
VertexProgramMorph=yes
#The proportional distance range at which the LODmorph starts to take effect
#This is as a proportion of the distance betweenthe current LODs effective range,
#and the effective range of the next lower LOD
#LOD融合開始點:高低LOD之間距離之比
LODMorphStart=0.2
#This following section is for if you want toprovide your own terrain shading routine
#Note that since you define your textures withinthe material this makes the
#WorldTexture and DetailTexture settingsredundant
#The name of the vertex program parameter youwish to bind the morph LOD factor to
#this is 0 when there is no adjustment (highest)to 1 when the morph takes it completely
#to the same position as the next lower LOD
#USE THIS IF YOU USE HIGH-LEVEL VERTEX PROGRAMSWITH LOD MORPHING
#MorphLODFactorParamName=morphFactor
#The index of the vertex program parameter youwish to bind the morph LOD factor to
#this is 0 when there is no adjustment (highest)to 1 when the morph takes it completely
#to the same position as the next lower LOD
#USE THIS IF YOU USE ASSEMBLER VERTEX PROGRAMSWITH LOD MORPHING
#MorphLODFactorParamIndex=4
#The name of the material you will define toshade the terrain
#CustomMaterialName=Ogre/Skin