`
yarin
  • 浏览: 171999 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

ogre研究之第一个程序

    博客分类:
  • ogre
阅读更多

版权申明:http://yarin.iteye.com/blog/453262

 

上一篇我们介绍了如何搭建开发环境,并创建了一个空白的窗口程序。

 

这里我们主要是实现在程序中装载一个简单的模型并显示出来。

 

首先看一下效果吧,(模型就是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

首先,我们要分析的就是Root类,使用Ogre的程序所需要作的第一件事情就是实例化一个Root对象。如果没有这个对象,你就无法调用(除了日志管理以外)的任何一个功能。Root类的构造函数接受一些符串对象的参数,这些字符代表着不同作用的文件名称。

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("", "");

上面列出了一些不同的方法来创建Root实例,这里面任何的方法都能单独的正确执行。参数也是系统所默认的值(“plugins.cfg”, “ogre.cfg”, “ogre.log”——当你没有填写参数的时候,系统就认为采用了默认的这些值)。 

plugins.cfg:插件,Ogre中所谓的插件就是符合Ogre插件接口的代码模块,比如场景管理(SceneManager)插件和渲染系统(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则是一个属性配置文件,主要保存用户自定义的一些属性,即下图所示的界面的一些属性。



文件如下:

Render System=Direct3D9 Rendering Subsystem

[Direct3D9 Rendering Subsystem]
Allow NVPerfHUD=No
Anti aliasing=None
Floating-point mode=Fastest
Full Screen=No
Rendering Device=Mobile Intel(R) 945 Express Chipset Family
VSync=No
Video Mode=800 x 600 @ 32-bit colour
sRGB Gamma Conversion=No

[OpenGL Rendering Subsystem]
Colour Depth=32
Display Frequency=N/A
FSAA=0
Full Screen=No
RTT Preferred Mode=FBO
VSync=No
Video Mode=1024 x 768
sRGB Gamma Conversion=No

相信这里就不用多解释,大家都明白了。

 

Ogre.log :日志文件,用于输出一些调试信息等,比如下代码:

LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***")

就会在 Ogre.log文件中输出"*** Initializing OIS ***"信息。

 

另外需要说明得就是FrameListener接口了,当Ogre渲染每一帧的开始和结束的时候会回调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;
}

所以我们就可以根据需要来实现这两个方式,实现渲染。 

 

注意:在新的版本中frameRenderingQueued方法基本上取代了frameStarted,所以本例中我们就是用了frameRenderingQueued,一般在这个函数中都需要检测各种输入设备的情况,以进行相应的处理。

 

最后,当我们在程序中调用mRoot->startRendering();方法时,就告诉ogre,我们需要开始渲染了。ogre就会开始渲染。也正是ExampleApplication类中的go方法,所做的,初始化(setup)完成之后就开始渲染(mRoot->startRendering())。

 

之所以有了这两个类,上一篇中我们才可以不写任何代码就可以构建一个窗口,那么本节内容,我们要显示模型当然就很简单了。

直接在OgreDemo1类的createScene方法中来实现,

1:设置环境光,首先需要为整个场景设置环境光,这样才可以看到要显示的内容,通过调用setAmbientLight函数并指定环境光的颜色就可以做到这些。指定的颜色由红、绿、蓝三种颜色组成,且每种色数值范围在 0 到 1 之间。

//设置环境光  
mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) ) 

2:创建一个 Entity (物体),通过调用 SceneManager 的 createEntity 方法来创建

//创建一个物体
Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );

变量 mSceneMgr 是当前场景管理器的一个对象,createEntity 方法的第一个参数是为所创建的实体指定一个唯一的标识,第二个参数 "robot.mesh" 指明要使用的网格实体,"robot.mesh" 网格实体在 ExampleApplication 类中被装载。这样,就已经创建了一个实体。

3:还需要创建一个场景节点来与它绑定在一起。既然每个场景管理器都有一个根节点,那我们就在根节点下创建一个场景节点。

//创建该物体对应的场景节点
SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );

 首先调用场景管理器的 getRootSceneNode 方法来获取根节点,再使用根节点的 createChildSceneNode 方法创建一个名为 "RobotNode" 的场景节点。与实体一样,场景节点的名字也是唯一的。

4:最后,将实体与场景节点绑定在一起,这样机器人(Robot)就会在指定的位置被渲染:

//将该物体和场景节点关联起来
node1->attachObject( ent1 );

ok,现在编译运行你的程序,就可以看到我们伟大的机器人界面了。 

 

最后说一下,在创建Root对象时的文件一般会和程序最后的可执行文件在同一目录(因为有人说找不到这些文件)。祝你成功!

  • 大小: 83.5 KB
  • 大小: 63 KB
分享到:
评论
1 楼 yarin 2010-01-03  
实在抱歉,忘记了一个问题,这里补充一下:
需要将sdk下的media文件夹拷贝到该项目目录下,因为里面存放了一些资源文件,本文中的机器人模型也在其中。

相关推荐

    ogre第一个程序研究

    学习ogre非常好的资料,本人从网上搜集下来,特贡献出来供大家分享,此文章对我的学习帮助很大,希望对大家有所帮助.

    【Ogre开发】之二:第一个Ogre程序源码

    【Ogre开发】之二:第一个Ogre程序源码 要将工程环境重新配置一下 否则编译会通不过 具体方法参见我的博客 http://blog.csdn.net/cowboylym/article/details/9745823

    ogre研究第一个程序

    学习ogre非常好的文章,带全部源码,有详细的解说,内容丰富,供大家参考学习.

    OGRE 3D程序设计

    OGRE 3D程序设计

    OGRE程序基本流程

    用来做OGRE开发的基本框架,是Tutorial的精简版

    OGRE建立应用程序的框架

    用VS2010建立OGRE简单应用程序的框架,适合于OGRE1.9版本,

    ogre+mfc框架程序

    ogre+mfc ogre+mfc框架程序

    《OGRE+3D+程序设计》.

    OGRE+3D+程序设计》 OGRE+3D+程序设计》

    Ogre - 程序框架

    1. 类似于Ogre-wiki上的set up your first application with CMake(没成功过下载和编译过) 2. Ogre是binary的形式, 不用下载ogre源代码和依赖库 3. 可以在此基础上,学习ogre及编写新的程序 4. 基于《Ogre 3d 1.7...

    Ogre游戏程序 源码

    Ogre游戏程序 源码......................

    ogre3D引擎教程

    基于HLA的OGRE引擎的实现及应用研究.kdh 基于OGRE和MPI的虚拟场景多机并行渲染.caj 基于OGRE和ODE的驾驶模拟系统的设计与实现.caj 基于多核平台优化的OGRE 3D渲染引擎.pdf Apress.Pro.OGRE.3D.Programming.pdf

    ogre程序设计结构

    ogre结构,很好的讲述了ogre的结构设计

    Ogre 示例程序框架分析

    本文对Ogre的示例程序框架的源代码进行了分析,展示如何由main开始进入每个示例。

    Ogre常用的一些框架程序

    Ogre常用的一些框架程序,从完善版本到精简版本,值得初学者使用。

    Ogre中文版教程

    如果你曾想用Ogre 3D开发3D应用程序,这本引例驱动的书能够使你梦想成真。你需要掌握C++来学习本书中的例题。本书是一本引例驱动的Ogre3D简介。每个例题都会显示一些新的特征,你将一步步地学习用Ogre 3D制造出有着...

    OGRE开发的一个程序zombieisland_bug_camera

    OGRE开发的一个程序zombieisland_bug_camera

    ogre和havok第三部分

    一个简单的ogre和havok的整合 利用开源图形库OGRE,物理库havok,界面库cegui,以及他们用到的依赖库ois、boost等,在vs2010编译平台上开发出一个易于拓展的三维游戏框架。 应为我的相关库比较多,所以这个项目的...

    OGRE 3D 游戏开发框架指南+光盘源码

    《OGRE 3D游戏开发框架指南(含CD光盘1张)》主要用来帮助读者从一个引擎研究者成为一个游戏开发人员,《OGRE 3D游戏开发框架指南(含CD光盘1张)》的最大特点是依靠代码来推进进度,以三周21天的时间顺序来编排主体内容...

    易语言OGRE类库1.1.zip易语言程序源码资源下载

    易语言OGRE类库1.1.zip易语言程序源码资源下载易语言OGRE类库1.1.zip易语言程序源码资源下载 1.适合学生做毕业设计用 2.适合程序员学习研究用 3.适合新手自学研究使用

Global site tag (gtag.js) - Google Analytics