ogre研究之第一个程序
版權申明:http://yarin.iteye.com/blog/453262
?
上一篇我們介紹了如何搭建開發(fā)環(huán)境,并創(chuàng)建了一個空白的窗口程序。
?
這里我們主要是實現(xiàn)在程序中裝載一個簡單的模型并顯示出來。
?
首先看一下效果吧,(模型就是ogre例子中的robot.mesh),如下:
?
例子很簡單,代碼頁不多,就4行。我們還是一步一步來分析吧。
?
首先我們上一個項目中的OgreDemo1類繼承自ExampleApplication類,我們之所以什么都沒有做就能創(chuàng)建一個窗口,就是因為ExampleApplication為我們實現(xiàn)了。
?
首先我們打開ExampleApplication類,可以看到包含了如下幾個成員變量(下乳了少許注釋)
?
//ogre的程序"根"任何ogre程序都會有改對象 Root *mRoot; //攝像機鏡頭 Camera* mCamera; //場景管理器 SceneManager* mSceneMgr; //對于每一幀進行處理的類 ExampleFrameListener* mFrameListener; //渲染窗口 RenderWindow* mWindow; //資源文件的路徑字符串 Ogre::String mResourcePath;這里的ExampleFrameListener類,如果你暫時還不清楚是做什么的,不要緊,后面我們慢慢介紹。
?
知道了這些成員變量,我們在返回OgreDemo1.c文件中看看入口函數(shù)WinMain中是如何書寫的呢?很簡單就一句話:
app.go();先將源代碼貼出來,加了詳細注意:
ExampleApplication.h
#ifndef __ExampleApplication_H__ #define __ExampleApplication_H__#include "Ogre.h" #include "OgreConfigFile.h" #include "ExampleFrameListener.h"#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE #include <CoreFoundation/CoreFoundation.h>std::string macBundlePath() {char path[1024];CFBundleRef mainBundle = CFBundleGetMainBundle();assert(mainBundle);CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);assert(mainBundleURL);CFStringRef cfStringRef = CFURLCopyFileSystemPath( mainBundleURL, kCFURLPOSIXPathStyle);assert(cfStringRef);CFStringGetCString(cfStringRef, path, 1024, kCFStringEncodingASCII);CFRelease(mainBundleURL);CFRelease(cfStringRef);return std::string(path); } #endifusing namespace Ogre;/** Base class which manages the standard startup of an Ogre application.Designed to be subclassed for specific examples if required. */ class ExampleApplication { public:ExampleApplication(){mFrameListener = 0;mRoot = 0; #if OGRE_PLATFORM == OGRE_PLATFORM_APPLEmResourcePath = macBundlePath() + "/Contents/Resources/"; #elsemResourcePath = ""; #endif}/// Standard destructorvirtual ~ExampleApplication(){if (mFrameListener)delete mFrameListener;if (mRoot)OGRE_DELETE mRoot;}/// 程序的入口virtual void go(void){//進行初始化工作if (!setup())return;//開始渲染mRoot->startRendering();// 清理屏幕destroyScene();}protected://ogre的程序"根"任何ogre程序都會有改對象Root *mRoot;//攝像機鏡頭Camera* mCamera;//場景管理器SceneManager* mSceneMgr;//對于每一幀進行處理的類ExampleFrameListener* mFrameListener;//渲染窗口RenderWindow* mWindow;//資源文件的路徑字符串Ogre::String mResourcePath;//初始化應用程序virtual bool setup(void){String pluginsPath; #ifndef OGRE_STATIC_LIBpluginsPath = mResourcePath + "plugins.cfg"; #endif//構建Root對象mRoot = OGRE_NEW Root(pluginsPath, mResourcePath + "ogre.cfg", mResourcePath + "Ogre.log");//配置資源文件相關setupResources();//配置,主要用于初始化渲染窗口bool carryOn = configure();if (!carryOn) return false;//創(chuàng)建場景管理器chooseSceneManager();//創(chuàng)建攝像機createCamera();//創(chuàng)建視口createViewports();TextureManager::getSingleton().setDefaultNumMipmaps(5);//創(chuàng)建資源監(jiān)聽createResourceListener();//床在資源loadResources();//創(chuàng)建屏幕,必須重寫,也就是我們OgreDemo1類中(我們現(xiàn)實模型需要實現(xiàn)的)createScene();//創(chuàng)建幀監(jiān)聽createFrameListener();return true;}/** 是否配置完成,完成則初始化系統(tǒng) */virtual bool configure(void){//判斷是否進入(即運行過了配置窗口,進入demo窗口)if(mRoot->showConfigDialog()){//初始化系統(tǒng),得到一個渲染窗口對象mWindow = mRoot->initialise(true);return true;}else{return false;}}virtual void chooseSceneManager(void){// 創(chuàng)建一個場景管理器(場景類型,窗口標題)mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "ExampleSMInstance");}virtual void createCamera(void){// 創(chuàng)建一個攝像機mCamera = mSceneMgr->createCamera("PlayerCam");// 設置攝像機的位置mCamera->setPosition(Vector3(0,0,500));// 設置觀察點mCamera->lookAt(Vector3(0,0,-300));// 設置最近裁剪距離,如果超出則不顯示mCamera->setNearClipDistance(5);//同樣還有設置最遠裁剪距離//mCamera->setFarClipDistance(1000);}//創(chuàng)建幀監(jiān)聽virtual void createFrameListener(void){//實例化幀監(jiān)聽,(渲染窗口,攝像機)mFrameListener= new ExampleFrameListener(mWindow, mCamera);//設置是否顯示調(diào)試信息(比如:fps...)mFrameListener->showDebugOverlay(true);//添加幀監(jiān)聽到root中mRoot->addFrameListener(mFrameListener);}//創(chuàng)建屏幕virtual void createScene(void) = 0; //清屏virtual void destroyScene(void){}/* 創(chuàng)建視口并初始化 */virtual void createViewports(void){// 創(chuàng)建一個“視口”Viewport* vp = mWindow->addViewport(mCamera);//設置背景顏色vp->setBackgroundColour(ColourValue(0,0,0));//設置屏幕的長寬比(視口的寬度和高度比,目前的寬屏電腦)mCamera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));}/// 初始化資源,比如:模型、貼圖等資源virtual void setupResources(void){ConfigFile cf;//讀取配置文件cf.load(mResourcePath + "resources.cfg");ConfigFile::SectionIterator seci = cf.getSectionIterator();String secName, typeName, archName;while (seci.hasMoreElements()){secName = seci.peekNextKey();ConfigFile::SettingsMultiMap *settings = seci.getNext();ConfigFile::SettingsMultiMap::iterator i;for (i = settings->begin(); i != settings->end(); ++i){//取得并添加資源文件typeName = i->first;archName = i->second; #if OGRE_PLATFORM == OGRE_PLATFORM_APPLEResourceGroupManager::getSingleton().addResourceLocation(String(macBundlePath() + "/" + archName), typeName, secName); #elseResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName); #endif}}}//創(chuàng)建資源監(jiān)聽,比如(正在裝載資源,請稍等界面)virtual void createResourceListener(void){}//裝載資源virtual void loadResources(void){ResourceGroupManager::getSingleton().initialiseAllResourceGroups();} };#endifExampleFrameListener.h?
#ifndef __ExampleFrameListener_H__ #define __ExampleFrameListener_H__#include "Ogre.h" #include "OgreStringConverter.h" #include "OgreException.h" #define OIS_DYNAMIC_LIB #include <OIS/OIS.h>using namespace Ogre;class ExampleFrameListener: public FrameListener, public WindowEventListener { protected:virtual void updateStats(void){static String currFps = "Current FPS: ";static String avgFps = "Average FPS: ";static String bestFps = "Best FPS: ";static String worstFps = "Worst FPS: ";static String tris = "Triangle Count: ";static String batches = "Batch Count: ";// 需要更新debug信息時更新try {OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");const RenderTarget::FrameStats& stats = mWindow->getStatistics();guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS));guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)+" "+StringConverter::toString(stats.bestFrameTime)+" ms");guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)+" "+StringConverter::toString(stats.worstFrameTime)+" ms");OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches");guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount));OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");guiDbg->setCaption(mDebugText);}catch(...) { /* ignore */ }}public:// 構造函數(shù),初始化成員變量ExampleFrameListener(RenderWindow* win, Camera* cam, bool bufferedKeys = false, bool bufferedMouse = false,bool bufferedJoy = false ) :mCamera(cam), mTranslateVector(Vector3::ZERO), mCurrentSpeed(0), mWindow(win), mStatsOn(true), mNumScreenShots(0),mMoveScale(0.0f), mRotScale(0.0f), mTimeUntilNextToggle(0), mFiltering(TFO_BILINEAR),mAniso(1), mSceneDetailIndex(0), mMoveSpeed(100), mRotateSpeed(36), mDebugOverlay(0),mInputManager(0), mMouse(0), mKeyboard(0), mJoy(0){//得到debug視圖mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");//日志管理器LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");OIS::ParamList pl;size_t windowHnd = 0;std::ostringstream windowHndStr;//取得自定義的屬性win->getCustomAttribute("WINDOW", &windowHnd);windowHndStr << windowHnd;pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));//創(chuàng)建輸入管理器mInputManager = OIS::InputManager::createInputSystem( pl );//創(chuàng)建輸入設備、鼠標、鍵盤、搖桿mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, bufferedKeys ));mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, bufferedMouse ));try {mJoy = static_cast<OIS::JoyStick*>(mInputManager->createInputObject( OIS::OISJoyStick, bufferedJoy ));}catch(...) {mJoy = 0;}//根據(jù)窗口的大小來設置鼠標的初始裁剪區(qū)域windowResized(mWindow);//顯示debug信息showDebugOverlay(true);//注冊一個windows窗口事件監(jiān)聽WindowEventUtilities::addWindowEventListener(mWindow, this);}//調(diào)整鼠標裁剪區(qū)域virtual void windowResized(RenderWindow* rw){unsigned int width, height, depth;int left, top;//取得窗口矩陣rw->getMetrics(width, height, depth, left, top);//得到鼠標const OIS::MouseState &ms = mMouse->getMouseState();ms.width = width;ms.height = height;}//關閉窗口之前進行的處理virtual void windowClosed(RenderWindow* rw){//檢測是否關閉了我們的渲染窗口if( rw == mWindow ){if( mInputManager ){//清除輸入設備mInputManager->destroyInputObject( mMouse );mInputManager->destroyInputObject( mKeyboard );mInputManager->destroyInputObject( mJoy );//銷毀輸入管理器OIS::InputManager::destroyInputSystem(mInputManager);mInputManager = 0;}}}virtual ~ExampleFrameListener(){//移除所有的窗口事件監(jiān)聽WindowEventUtilities::removeWindowEventListener(mWindow, this);//關閉窗口windowClosed(mWindow);}//按鍵事件處理virtual bool processUnbufferedKeyInput(const FrameEvent& evt){if(mKeyboard->isKeyDown(OIS::KC_A))mTranslateVector.x = -mMoveScale; // 向左移動攝像頭矩陣if(mKeyboard->isKeyDown(OIS::KC_D))mTranslateVector.x = mMoveScale; // Move camera RIGHTif(mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W) )mTranslateVector.z = -mMoveScale; // Move camera forwardif(mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S) )mTranslateVector.z = mMoveScale; // Move camera backwardif(mKeyboard->isKeyDown(OIS::KC_PGUP))mTranslateVector.y = mMoveScale; // Move camera upif(mKeyboard->isKeyDown(OIS::KC_PGDOWN))mTranslateVector.y = -mMoveScale; // Move camera downif(mKeyboard->isKeyDown(OIS::KC_RIGHT))mCamera->yaw(-mRotScale);if(mKeyboard->isKeyDown(OIS::KC_LEFT))mCamera->yaw(mRotScale);if( mKeyboard->isKeyDown(OIS::KC_ESCAPE) || mKeyboard->isKeyDown(OIS::KC_Q) )return false;if( mKeyboard->isKeyDown(OIS::KC_F) && mTimeUntilNextToggle <= 0 ){mStatsOn = !mStatsOn;showDebugOverlay(mStatsOn);mTimeUntilNextToggle = 1;}if( mKeyboard->isKeyDown(OIS::KC_T) && mTimeUntilNextToggle <= 0 ){switch(mFiltering){case TFO_BILINEAR:mFiltering = TFO_TRILINEAR;mAniso = 1;break;case TFO_TRILINEAR:mFiltering = TFO_ANISOTROPIC;mAniso = 8;break;case TFO_ANISOTROPIC:mFiltering = TFO_BILINEAR;mAniso = 1;break;default: break;}MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);showDebugOverlay(mStatsOn);mTimeUntilNextToggle = 1;}if(mKeyboard->isKeyDown(OIS::KC_SYSRQ) && mTimeUntilNextToggle <= 0){std::ostringstream ss;ss << "screenshot_" << ++mNumScreenShots << ".png";mWindow->writeContentsToFile(ss.str());mTimeUntilNextToggle = 0.5;mDebugText = "Saved: " + ss.str();}if(mKeyboard->isKeyDown(OIS::KC_R) && mTimeUntilNextToggle <=0){mSceneDetailIndex = (mSceneDetailIndex+1)%3 ;switch(mSceneDetailIndex) {case 0 : mCamera->setPolygonMode(PM_SOLID); break;//設置多邊形的模式case 1 : mCamera->setPolygonMode(PM_WIREFRAME); break;case 2 : mCamera->setPolygonMode(PM_POINTS); break;}mTimeUntilNextToggle = 0.5;}static bool displayCameraDetails = false;if(mKeyboard->isKeyDown(OIS::KC_P) && mTimeUntilNextToggle <= 0){displayCameraDetails = !displayCameraDetails;mTimeUntilNextToggle = 0.5;if (!displayCameraDetails)mDebugText = "";}if(displayCameraDetails)mDebugText = "P: " + StringConverter::toString(mCamera->getDerivedPosition()) +" " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation());return true;}//鼠標事件處理virtual bool processUnbufferedMouseInput(const FrameEvent& evt){// Rotation factors, may not be used if the second mouse button is pressed// 2nd mouse button - slide, otherwise rotateconst OIS::MouseState &ms = mMouse->getMouseState();if( ms.buttonDown( OIS::MB_Right ) ){mTranslateVector.x += ms.X.rel * 0.13;mTranslateVector.y -= ms.Y.rel * 0.13;}else{mRotX = Degree(-ms.X.rel * 0.13);mRotY = Degree(-ms.Y.rel * 0.13);}return true;}//移動攝像頭virtual void moveCamera(){//偏移mCamera->yaw(mRotX);//傾斜mCamera->pitch(mRotY);//移動攝像機到指定位置mCamera->moveRelative(mTranslateVector);}//顯示debug信息virtual void showDebugOverlay(bool show){if (mDebugOverlay){if (show)mDebugOverlay->show();elsemDebugOverlay->hide();}}// 渲染隊列bool frameRenderingQueued(const FrameEvent& evt){if(mWindow->isClosed()) return false;mSpeedLimit = mMoveScale * evt.timeSinceLastFrame;//捕獲、更新設備mKeyboard->capture();mMouse->capture();if( mJoy ) mJoy->capture();bool buffJ = (mJoy) ? mJoy->buffered() : true;Ogre::Vector3 lastMotion = mTranslateVector;if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ ){// one of the input modes is immediate, so setup what is needed for immediate movementif (mTimeUntilNextToggle >= 0)mTimeUntilNextToggle -= evt.timeSinceLastFrame;// Move about 100 units per secondmMoveScale = mMoveSpeed * evt.timeSinceLastFrame;// Take about 10 seconds for full rotationmRotScale = mRotateSpeed * evt.timeSinceLastFrame;mRotX = 0;mRotY = 0;mTranslateVector = Ogre::Vector3::ZERO;}//Check to see which device is not buffered, and handle itif( !mKeyboard->buffered() )if( processUnbufferedKeyInput(evt) == false )return false;if( !mMouse->buffered() )if( processUnbufferedMouseInput(evt) == false )return false;// ramp up / ramp down speedif (mTranslateVector == Ogre::Vector3::ZERO){// decay (one third speed)mCurrentSpeed -= evt.timeSinceLastFrame * 0.3;mTranslateVector = lastMotion;}else{// ramp upmCurrentSpeed += evt.timeSinceLastFrame;}// Limit motion speedif (mCurrentSpeed > 1.0)mCurrentSpeed = 1.0;if (mCurrentSpeed < 0.0)mCurrentSpeed = 0.0;mTranslateVector *= mCurrentSpeed;if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )moveCamera();return true;}//幀結束,更新狀態(tài)bool frameEnded(const FrameEvent& evt){updateStats();return true;}protected://指向攝像機的指針Camera* mCamera;//一個3維向量,用于攝像機的位置變換Vector3 mTranslateVector;Real mCurrentSpeed;//指向渲染窗口的指針RenderWindow* mWindow;//是否顯示調(diào)試信息bool mStatsOn;//debug信息std::string mDebugText;//主要用于截圖unsigned int mNumScreenShots;//該demo中,攝像機會旋轉(zhuǎn)float mMoveScale;//速度限制float mSpeedLimit;//同樣用于攝像機變換Degree mRotScale;//延時Real mTimeUntilNextToggle ;//鼠標旋轉(zhuǎn)的角度,用于攝像機的更新Radian mRotX, mRotY;//紋理差值的類型,枚舉類型TextureFilterOptions mFiltering;int mAniso;int mSceneDetailIndex ;//移動速度Real mMoveSpeed;//旋轉(zhuǎn)速度Degree mRotateSpeed;//debug視圖Overlay* mDebugOverlay;//一些輸入設備(輸入設備管理器)OIS::InputManager* mInputManager;//鼠標OIS::Mouse* mMouse;//鍵盤OIS::Keyboard* mKeyboard;//搖桿OIS::JoyStick* mJoy; };#endif首先,我們要分析的就是Root類,使用Ogre的程序所需要作的第一件事情就是實例化一個Root對象。如果沒有這個對象,你就無法調(diào)用(除了日志管理以外)的任何一個功能。Root類的構造函數(shù)接受一些符串對象的參數(shù),這些字符代表著不同作用的文件名稱。
Root * root = new Root(); Root * root = new Root("plugins.cfg"); Root * root = new Root("plugins.cfg", "ogre.cfg"); Root * root = new Root("plugins.cfg", "ogre.cfg", "ogre.log"); Root * root = new Root("", "");上面列出了一些不同的方法來創(chuàng)建Root實例,這里面任何的方法都能單獨的正確執(zhí)行。參數(shù)也是系統(tǒng)所默認的值(“plugins.cfg”, “ogre.cfg”, “ogre.log”——當你沒有填寫參數(shù)的時候,系統(tǒng)就認為采用了默認的這些值)。?
plugins.cfg:插件,Ogre中所謂的插件就是符合Ogre插件接口的代碼模塊,比如場景管理(SceneManager)插件和渲染系統(tǒng)(RenderSystem)插件等。在啟動的Ogre時候,他會載入plugins.cfg配置文件來查看有哪些插件可以被使用。下面是一個plugins.cfg文件例子
# Defines plugins to load# Define plugin folder PluginFolder=.# Define plugins Plugin=RenderSystem_Direct3D9_d Plugin=RenderSystem_GL_d Plugin=Plugin_ParticleFX_d Plugin=Plugin_BSPSceneManager_d Plugin=Plugin_CgProgramManager_d Plugin=Plugin_PCZSceneManager_d.dll Plugin=Plugin_OctreeZone_d.dll Plugin=Plugin_OctreeSceneManager_d其中PluginFolder用于定義這些插件存在的位置(路徑),??這里使用“.”,表示需要在“\”或者“/”(即根目錄)。在某些平臺上可以不使用“.”直接使用""(空白),ogre照樣會在“\”或者“/”中去找。
而Plugin則說明了有哪些插件可以使用,但是需要注意,這些插件都沒有后綴名。
這里需要注意:在“=”兩邊不能加入空格或者?Tab字符。
?
ogre.cfg則是一個屬性配置文件,主要保存用戶自定義的一些屬性,即下圖所示的界面的一些屬性。
文件如下:
相信這里就不用多解釋,大家都明白了。
?
Ogre.log?:日志文件,用于輸出一些調(diào)試信息等,比如下代碼:
LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***")就會在?Ogre.log文件中輸出"*** Initializing OIS ***"信息。
?
另外需要說明得就是FrameListener接口了,當Ogre渲染每一幀的開始和結束的時候會回調(diào)FrameListener接口的方法,其中主要包括如下兩個渲染方法。
class ExampleFrameListener : public FrameListener{ public:bool frameStarted (const FrameEvent &evt);bool frameEnded (const FrameEvent &evt ); };bool ExampleFrameListener::frameStarted (const FrameEvent &evt){//在每一幀畫面渲染前return true;} bool ExampleFrameListener::frameEnded (const FrameEvent &evt ){//在每一幀畫面渲染后return true; }所以我們就可以根據(jù)需要來實現(xiàn)這兩個方式,實現(xiàn)渲染。?
?
注意:在新的版本中frameRenderingQueued方法基本上取代了frameStarted,所以本例中我們就是用了frameRenderingQueued,一般在這個函數(shù)中都需要檢測各種輸入設備的情況,以進行相應的處理。
?
最后,當我們在程序中調(diào)用mRoot->startRendering();方法時,就告訴ogre,我們需要開始渲染了。ogre就會開始渲染。也正是ExampleApplication類中的go方法,所做的,初始化(setup)完成之后就開始渲染(mRoot->startRendering())。
?
之所以有了這兩個類,上一篇中我們才可以不寫任何代碼就可以構建一個窗口,那么本節(jié)內(nèi)容,我們要顯示模型當然就很簡單了。
直接在OgreDemo1類的createScene方法中來實現(xiàn),
1:設置環(huán)境光,首先需要為整個場景設置環(huán)境光,這樣才可以看到要顯示的內(nèi)容,通過調(diào)用setAmbientLight函數(shù)并指定環(huán)境光的顏色就可以做到這些。指定的顏色由紅、綠、藍三種顏色組成,且每種色數(shù)值范圍在 0 到 1 之間。
//設置環(huán)境光 mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) )?2:創(chuàng)建一個 Entity (物體),通過調(diào)用 SceneManager 的 createEntity 方法來創(chuàng)建
//創(chuàng)建一個物體 Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );變量 mSceneMgr 是當前場景管理器的一個對象,createEntity 方法的第一個參數(shù)是為所創(chuàng)建的實體指定一個唯一的標識,第二個參數(shù) "robot.mesh" 指明要使用的網(wǎng)格實體,"robot.mesh" 網(wǎng)格實體在 ExampleApplication 類中被裝載。這樣,就已經(jīng)創(chuàng)建了一個實體。
3:還需要創(chuàng)建一個場景節(jié)點來與它綁定在一起。既然每個場景管理器都有一個根節(jié)點,那我們就在根節(jié)點下創(chuàng)建一個場景節(jié)點。
//創(chuàng)建該物體對應的場景節(jié)點 SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );?首先調(diào)用場景管理器的 getRootSceneNode 方法來獲取根節(jié)點,再使用根節(jié)點的 createChildSceneNode 方法創(chuàng)建一個名為 "RobotNode" 的場景節(jié)點。與實體一樣,場景節(jié)點的名字也是唯一的。
4:最后,將實體與場景節(jié)點綁定在一起,這樣機器人(Robot)就會在指定的位置被渲染:
//將該物體和場景節(jié)點關聯(lián)起來 node1->attachObject( ent1 );ok,現(xiàn)在編譯運行你的程序,就可以看到我們偉大的機器人界面了。?
?
最后說一下,在創(chuàng)建Root對象時的文件一般會和程序最后的可執(zhí)行文件在同一目錄(因為有人說找不到這些文件)。祝你成功!
總結
以上是生活随笔為你收集整理的ogre研究之第一个程序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论文解读《STALLION:一个基于堆叠
- 下一篇: leflet使用kriging.js构建