天天看點

Ogre1.73學習執行個體

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檔案路徑配置進環境變量:

Ogre1.73學習執行個體

一:9個實體,随機出現一個,隐藏另一個,滑鼠移到轉動相機,按鍵盤移動相機.

(程式為遊戲類程式設計/Ogre/Ogre1.73/FirstOGRE)

 1:建立一個空的 win32控制台應用程式,命名為:FirstOGRE

 2:添加一個 FirstOGRE.cpp檔案

 3:配置包含目錄(包含Ogre的頭檔案的目錄)和庫目錄(包含Ogre的lib檔案的目錄):

Ogre1.73學習執行個體

 4:配置附加依賴項:

            OgreRTShaderSystem_d.lib

OgreMain_d.lib

OIS_d.lib

Ogre1.73學習執行個體

 5:将OgreSDK_vc10_v1-7-3安裝目錄下的 media目錄拷貝到目前工程目錄下,将OgreSDK_vc10_v1-7-3安裝目錄

下的 bin目錄下的 debug目錄下和 release目錄的下字尾為 .cfg的檔案拷貝到目前目錄下, 并修改.cfg檔案

内的配置内容(修改配置路徑的内容):

Ogre1.73學習執行個體

 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