ogre研究之第一个程序(一)

第一次发送超过字数了,被迫剪成两篇!

上一篇我们介绍了如何搭建开发环境,并创建了一个空白的窗口程序。
这里我们主要是实现在程序中装载一个简单的模型并显示出来。
首先看一下效果吧,(模型就是ogre例子中的robot.mesh),如下:


例子很简单,代码页不多,就4行。我们还是一步一步来分析吧。
首先我们上一个项目中的OgreDemo1类继承自ExampleApplication类,我们之所以什么都没

有做就能创建一个窗口,就是因为ExampleApplication为我们实现了。
首先我们打开ExampleApplication类,可以看到包含了如下几个成员变量(加入了少许注释)

//ogre的程序"根"任何ogre程序都会有改对象     
Root *mRoot;     
//摄像机镜头     
Camera* mCamera;     
//场景管理器     
SceneManager* mSceneMgr;     
//对于每一帧进行处理的类     
ExampleFrameListener* mFrameListener;     
//渲染窗口     
RenderWindow* mWindow;     
//资源文件的路径字符串     
Ogre::String mResourcePath;
这里的ExampleFrameListener类,如果你暂时还不清楚是做什么的,不要紧,后面我们慢慢介绍。
知道了这些成员变量,我们在返回OgreDemo1.c文件中看看入口函数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);     
}     
#endif     
    
using 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_APPLE     
        mResourcePath = macBundlePath() + "/Contents/Resources/";     
#else     
        mResourcePath = "";     
#endif     
    }     
    /// Standard destructor     
    virtual ~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_LIB     
        pluginsPath = mResourcePath + "plugins.cfg";     
#endif     
        //构建Root对象     
        mRoot = OGRE_NEW Root(pluginsPath,      
            mResourcePath + "ogre.cfg", mResourcePath + "Ogre.log");     
        //配置资源文件相关     
        setupResources();     
        //配置,主要用于初始化渲染窗口     
        bool carryOn = configure();     
        if (!carryOn) return false;     
        //创建场景管理器     
        chooseSceneManager();     
        //创建摄像机     
        createCamera();     
        //创建视口     
        createViewports();     
             
        TextureManager::getSingleton().setDefaultNumMipmaps(5);     
        //创建资源监听     
        createResourceListener();     
        //床在资源     
        loadResources();     
        //创建屏幕,必须重写,也就是我们OgreDemo1类中(我们现实模型需要实现的)     
        createScene();     
        //创建帧监听     
        createFrameListener();     
        return true;     
    }     
    /** 是否配置完成,完成则初始化系统 */    
    virtual bool configure(void)     
    {     
        //判断是否进入(即运行过了配置窗口,进入demo窗口)     
        if(mRoot->showConfigDialog())     
        {     
            //初始化系统,得到一个渲染窗口对象     
            mWindow = mRoot->initialise(true);     
            return true;     
        }     
        else    
        {     
            return false;     
        }     
    }     
    
    virtual void chooseSceneManager(void)     
    {     
        // 创建一个场景管理器(场景类型,窗口标题)     
        mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "ExampleSMInstance");     
    }     
    virtual void createCamera(void)     
    {     
        // 创建一个摄像机     
        mCamera = mSceneMgr->createCamera("PlayerCam");     
    
        // 设置摄像机的位置     
        mCamera->setPosition(Vector3(0,0,500));     
        // 设置观察点     
        mCamera->lookAt(Vector3(0,0,-300));     
        // 设置最近裁剪距离,如果超出则不显示     
        mCamera->setNearClipDistance(5);     
        //同样还有设置最远裁剪距离     
        //mCamera->setFarClipDistance(1000);     
    }     
    //创建帧监听     
    virtual void createFrameListener(void)     
    {     
        //实例化帧监听,(渲染窗口,摄像机)     
        mFrameListener= new ExampleFrameListener(mWindow, mCamera);     
        //设置是否显示调试信息(比如:fps...)     
        mFrameListener->showDebugOverlay(true);     
        //添加帧监听到root中     
        mRoot->addFrameListener(mFrameListener);     
    }     
    //创建屏幕     
    virtual void createScene(void) = 0;      
    //清屏     
    virtual void destroyScene(void){}     
    /* 创建视口并初始化 */    
    virtual void createViewports(void)     
    {     
        // 创建一个“视口”     
        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_APPLE     
                ResourceGroupManager::getSingleton().addResourceLocation(     
                    String(macBundlePath() + "/" + archName), typeName, secName);     
#else     
                ResourceGroupManager::getSingleton().addResourceLocation(     
                    archName, typeName, secName);     
#endif     
            }     
        }     
    }     
    
    //创建资源监听,比如(正在装载资源,请稍等界面)     
    virtual void createResourceListener(void)     
    {     
    }     
    
    //装载资源     
    virtual void loadResources(void)     
    {     
        ResourceGroupManager::getSingleton().initialiseAllResourceGroups();     
    }     
};     
    
    
#endif 

ExampleFrameListener.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:     
    // 构造函数,初始化成员变量     
    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()));     
        //创建输入管理器     
        mInputManager = OIS::InputManager::createInputSystem( pl );     
    
        //创建输入设备、鼠标、键盘、摇杆     
        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;     
        }     
    
        //根据窗口的大小来设置鼠标的初始裁剪区域     
        windowResized(mWindow);     
        //显示debug信息     
        showDebugOverlay(true);     
    
        //注册一个windows窗口事件监听     
        WindowEventUtilities::addWindowEventListener(mWindow, this);     
    }     
    
    //调整鼠标裁剪区域     
    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()     
    {     
        //移除所有的窗口事件监听     
        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 RIGHT     
    
        if(mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W) )     
            mTranslateVector.z = -mMoveScale;   // Move camera forward     
    
        if(mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S) )     
            mTranslateVector.z = mMoveScale;    // Move camera backward     
    
        if(mKeyboard->isKeyDown(OIS::KC_PGUP))     
            mTranslateVector.y = mMoveScale;    // Move camera up     
    
        if(mKeyboard->isKeyDown(OIS::KC_PGDOWN))     
            mTranslateVector.y = -mMoveScale;   // Move camera down     
    
        if(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 rotate     
        const 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();     
            else    
                mDebugOverlay->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 movement     
            if (mTimeUntilNextToggle >= 0)     
                mTimeUntilNextToggle -= evt.timeSinceLastFrame;     
    
            // Move about 100 units per second     
            mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;     
            // Take about 10 seconds for full rotation     
            mRotScale = mRotateSpeed * evt.timeSinceLastFrame;     
    
            mRotX = 0;     
            mRotY = 0;     
            mTranslateVector = Ogre::Vector3::ZERO;     
    
        }     
    
        //Check to see which device is not buffered, and handle it     
        if( !mKeyboard->buffered() )     
            if( processUnbufferedKeyInput(evt) == false )     
                return false;     
        if( !mMouse->buffered() )     
            if( processUnbufferedMouseInput(evt) == false )     
                return false;     
    
        // ramp up / ramp down speed     
        if (mTranslateVector == Ogre::Vector3::ZERO)     
        {     
            // decay (one third speed)     
            mCurrentSpeed -= evt.timeSinceLastFrame * 0.3;     
            mTranslateVector = lastMotion;     
        }     
        else    
        {     
            // ramp up     
            mCurrentSpeed += evt.timeSinceLastFrame;     
    
        }     
        // Limit motion speed     
        if (mCurrentSpeed > 1.0)     
            mCurrentSpeed = 1.0;     
        if (mCurrentSpeed < 0.0)     
            mCurrentSpeed = 0.0;     
    
        mTranslateVector *= mCurrentSpeed;     
    
    
        if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )     
            moveCamera();     
    
        return true;     
    }     
    
    //帧结束,更新状态     
    bool frameEnded(const FrameEvent& evt)     
    {     
        updateStats();     
        return true;     
    }     
    
protected:     
    //指向摄像机的指针     
    Camera* mCamera;     
    //一个3维向量,用于摄像机的位置变换     
    Vector3 mTranslateVector;     
    Real mCurrentSpeed;     
    //指向渲染窗口的指针     
    RenderWindow* mWindow;     
    //是否显示调试信息     
    bool mStatsOn;     
    //debug信息     
    std::string mDebugText;     
    //主要用于截图     
    unsigned int mNumScreenShots;     
    //该demo中,摄像机会旋转     
    float mMoveScale;     
    //速度限制     
    float mSpeedLimit;     
    //同样用于摄像机变换     
    Degree mRotScale;     
    //延时     
    Real mTimeUntilNextToggle ;     
    //鼠标旋转的角度,用于摄像机的更新     
    Radian mRotX, mRotY;     
    //纹理差值的类型,枚举类型     
    TextureFilterOptions mFiltering;     
    int mAniso;     
    int mSceneDetailIndex ;     
    //移动速度     
    Real mMoveSpeed;     
    //旋转速度     
    Degree mRotateSpeed;     
    //debug视图     
    Overlay* mDebugOverlay;     
    
    //一些输入设备(输入设备管理器)     
    OIS::InputManager* mInputManager;     
    //鼠标     
    OIS::Mouse*    mMouse;     
    //键盘     
    OIS::Keyboard* mKeyboard;     
    //摇杆     
    OIS::JoyStick* mJoy;     
};     
    
#endif 
接续(二)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章