OGRE使用指南:

在這裏我們將學習OGRE的方方面面:SceneManager,SceneNode,Entity.我們會重點介紹一些在OGRE中使用的概念.
    隨着我們瞭解得越來越多,我們將能夠編寫自己得遊戲,代碼量會越來越大!
    讓我們開始吧:
    首先讓我們來寫一些代碼,這些是我們遊戲得基本框架,隨着我們框架得逐步完善,你將慢慢明白

OGRE的流程:
    #include "ExampleApplication.h"

    class TutorialApplication : public ExampleApplication
    {
    protected:
    public:
         TutorialApplication()
         {
         }

         ~TutorialApplication()
         {
         }
     protected:
         void createScene(void)
        {
        }
    };

    #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    #define WIN32_LEAN_AND_MEAN
    #include "windows.h"

    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
    #else
    int main(int argc, char **argv)
    #endif
    {
       // Create application object
       TutorialApplication app;

      try {
          app.go();
        } catch( Exception& e ) {
      #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!",

MB_OK | MB_ICONERROR | MB_TASKMODAL);
     #else
         fprintf(stderr, "An exception has occured: %s/n",
                e.getFullDescription().c_str());
     #endif
        }

     return 0;
   }
    如果你是在windows平臺下開發,並且已經安裝了 OGRE  SDK,確定把"[OgreSDK_DIRECTORY]/samples/include"添加到工程的引用庫裏面.請先正確編譯和運行上面的代碼再接着看以下內容,這將使你更加有信心.儘管它運行時只有的界面和一個盒子,這將使OGRE世界中的"Hello World".
   請確定再可執行文件的目錄下有以下兩個文件:plugins.cfg,resources.cfg.plugins.cfg告訴OGRE將使用哪個運行庫(Direct3D9 or OpenGL).Resources.cfg被ExampleApplication所使用並且指定紋理,網格腳本的路徑.以上兩個文件都使文本文件,必要時編輯它們,以確保路徑時正確的。否則將出現錯誤。
 OGRE是如何工作的?
 這是一個相當寬泛的問題,只研究一點顯然不能夠得到答案。我們將相繼介紹

SceneManagers,Entities,SceneNodes.這三個類是OGRE的基石.
SceneManager 基礎:
    我們再屏幕上看到的一切都通過SceneManager來管理,當你把一個物體放到場景中去的時候,SceneManager就是我們來跟蹤它們位置的類.當你創建了一個相機來觀察場景的時候,SceneManager將用來跟蹤相機的位置,當你創建了飛機,燈光等等,SceneManager來跟蹤他們.
    正如我們以後將要看到的一樣,有很多中SceneManager,有用來渲染terrain的SceneManager,有用來渲染BSP圖的SceneManager等等.
Octree Scene Manager
Terrain Scene Manager
Nature Scene Manager
Paging Scene Manager
BSP Scene Manager
DotSceneOctree SceneManager
我們將再以後詳細介紹每個 SceneManager
Entity  基礎:
    一個Entity就是我們將要渲染到屏幕上的一個對象,我們可以把Entity想象成任何3D網格模型.一個系統任務可以是一個Entity,一條魚是一個Entity,遊戲中的地形也是Entity.但是,燈光,例子,相機等等都不是 Entity.
     這裏有一點我們需要注意,那就是OGRE將所要渲染的物體與它們的位置分開了,這就意味着我們不能只創建一個Entity,然後把它放置到現場中,只能通過將它與一個SceneNode綁定才能夠放置它到場景中,SceneNode中包括了位置的信息.
SceneNode 基礎:
     在前面我們已經提到,SceneNode中維護着與它綁定的對象的位置,當你創建了一個Entity對象時,只有你將它與一個SceneNode對象綁定時才能在場景中渲染它.它們之間的這種關心時對應的,我們也不能直接將一個SceneNode對象直接在場景中渲染,直到有Entity綁定在它身上.
    一個SceneNode可以由很多對象綁定到它身上,比如說有一個人在走動情景,我們想在他周圍加上燈光.我們可以這樣來實現:讓我們首先來創建一個SceneNode對象,然後創建人物Entity,並且把它綁定在先創建的那個SceneNode上,然後我們再創建燈光對象,並且將燈光與SceneNode綁定.不僅如此,SceneNode還可以跟其它的SceneNode綁定,這樣就可以形成一個有層次的結構.我們應該記住很重要

的一點,那就是一個SceneNode的位置是跟它父節點的位置是相關的,並且每個SceneManager都包含一個

SceneNode層次結構的根節點.
    現在回到我們剛纔的"hello world",找到函數:TutorialApplication::createScene,現在我們只關

心這個函數.我們要做的第一件事情就是打開環境光.這通過調用函數setAmbientLight來實現,它接受一

個顏色參數以用來指定光的顏色.這裏需要注意的是顏色值RGB的分量都是在0和1之間的.
   mSceneMgr->setAmbientLight(ColourValue(1,1,1));
   接下來我們就要創建一個Entity,看下面的代碼:
   Entity *ent1=mSceneMgr->createEntity("Robot","robot.mesh");
   Ok,現在你的頭腦中肯定產生了很多問題:mSceneMgr是什麼?在上個函數中的各個參數的含義是什麼?
現在讓我來告訴你:mSceneMgr包含了當前的SceneManger對象(ExampleApplication爲我們做了這些).再

來看createEntity的參數,第一個參數是我們所要創建的Entity的名字,每個Entity都必須有一個唯一的

名字.如果創建一個同名的Entity就會有錯誤發生."robot.mesh"是我們所創建的Entity所用到的網格.

我們所要用到的網格被ExampleApplication預先導入了.
   好,我們現在創建了Entity,按照我們前面所說,現在該爲它創建一個SceneNode.因爲每個

SceneManager都有個根節點,現在我們就來創建它的子節點:
   SceneNode * node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode");
   上面的語句首先是調用了getRootSceneNode來得到當前的SceneManager,然後就來創建它的子節點.
參數就是我們所創建的SceneNode的名字,同Entity一樣,不能有重名的.
   最後我們要把Entity綁定在SceneNode上,以使得Entity有一個位置用來渲染.
   node1->attachObject(ent1);
   好的,現在就來了編譯我們的程序,就將看到一個人物站在場景中.
   注意:robot.mesh沒有在ogreCore.zip中,修改resources.cfg:
   FileSystem=../../media/materials/programs
   FileSystem=../../media/materials/scripts
   FileSystem=../../media/materials/textures
   FileSystem=../../media/models
   以使得我們的程序能正常工作.

 座標與向量:
   在我們繼續之前,先來看一下OGRE中的座標系跟向量對象. OGRE跟其它的圖形引擎一樣使用x,z來表

示水平平面,  用y來表示垂直方向.面對你的顯示器,x軸是從左到右,右邊是正方向;y軸是從下到上,上

方是正方向;z軸是從裏向外,外面是正方向. 
   OGRE是用向量類來表示位置跟方向的,Vector2,Vector3,Vector4是OGRE中定義的三種向量,然而我們

最常使用的是Vector3.在繼續前進之前請確定你右足夠的向量方面的數學知識,這對以後的學習是非常

重要的.
   添加更多對象:
   現在你明白了座標系統如何工作的,現在讓我們繼續看我們的代碼.我們如何來指定對象的位置呢?大

多數的函數都是右默認值的,比如說,SceneNode::createChildSceneNode成員函數右三個參

數:SceneNode的名字,位置,朝向.它的位置,正如我們先前看到的一樣默認是在(0,0,0)處,現在讓我們來

重新創建一個節點,這次我們讓它處在不同的位置:
       Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
       SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode(            

                                     "RobotNode2", Vector3( 50, 0, 0 ) );
       node2->attachObject( ent2 );
       這裏的代碼大多數跟以前是一樣的,有兩處小區別:一個是名稱,再一個就是對象的初始位置,這

次我們是把對象放在了(50,0,0)處.
    下面我們來列舉一些Entity的常用函數:
     setVisible()
     isVisible()
     getName()
     getParentSceneNode()
     至於Entity類是如何實現的,大家現在先不要急於瞭解這些,以後的學習中慢慢體會,一開始就過度

瞭解細節有可能打擊我們的積極性.
    SceneNode的一些常用函數:
    //位置相關
    getPositiion()
    setPosition()
    translate()
    //旋轉
    scale()
    yaw()
    roll()
    pitch()
    resetOrientation()
    setOrientation()
    getOrientation()
    rotate()
    //其它
    attachObject()
    numAttachedObject()
    getAttachedObject()
    detachObject()
    detachAllObjects()
  
    讓我們來看一下下面這段代碼:
    Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );
    SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode(               

                               "RobotNode" );
    node1->attachObject( ent1 );
    Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
    SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode(               

                               "RobotNode2", Vector3( 50, 0, 0 ) );
    node2->attachObject( ent2 );
    如果我們把第五行:
    SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode(               

                       "RobotNode2", Vector3( 50, 0, 0 ) );
    改爲:
    SceneNode *node2 = node1->createChildSceneNode( "RobotNode2", Vector3( 50, 0, 0 ) );
    現在,RobotNode2是RobotNode的一個子節點,這就意味着node1移動,node2就會跟着移動,但是移動

node2不會影響到node1.下面這行代碼就只移動了node2:
    node2->translate( Vector3( 10, 0, 10 ) );
   下面的這段代碼是移動的node1,因爲node2是node1的子節點,所以niode2也就跟着移動了.
    node1->translate( Vector3( 25, 0, 0 ) );
   
練習一下這些代碼:
    縮放:
    Entity *ent = mSceneMgr->createEntity( "Robot", "robot.mesh" );
    SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
    node->attachObject( ent );
    node->scale( .5, 1, 2 );
    ent = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
    node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode2", Vector3( 50,

                                                              0, 0 ) );
    node->attachObject( ent );
    node->scale( 1, 2, 1 );
    旋轉:
    Entity *ent = mSceneMgr->createEntity( "Robot", "robot.mesh" );
    SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode(                

            "RobotNode", Vector3( -100, 0, 0 )  );
    node->attachObject( ent );
    node->yaw( Degree( -90 ) );
    ent = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
    node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode2");
    node->attachObject( ent );
    node->pitch( Degree( -90 ) );
    ent = mSceneMgr->createEntity( "Robot3", "robot.mesh" );
    node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode3", Vector3(    

                         100, 0, 0 ) );
    node->attachObject( ent );

    node->roll( Degree( -90 ) );

發佈了18 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章