`
yarin
  • 浏览: 174312 次
  • 性别: 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引擎中构建并显示一个简单的3D模型。Ogre是一个开源的3D图形渲染引擎,广泛用于游戏开发和其他需要高质量3D图形的应用。在这个过程中,我们将了解到几个关键的...

    OGRE 3D程序设计

    1. **OGRE 3D基础知识**:包括OGRE的安装与配置,理解其基本架构,以及如何设置第一个3D场景。 2. **资源管理**:学习如何加载模型、纹理、材质和动画,理解OGRE的资源管理系统,以高效地管理项目中的各种资源。 3...

    OGRE开发的一个程序zombieisland_bug_camera

    "ZombieIsland_bug_camera"程序专注于相机系统的调试,可能包含了各种相机运动模式的实现,如自由视角、第一人称视角、第三人称视角等。开发者可能通过这个程序来检查相机在不同场景、运动状态下的表现,找出并修复...

    ogre_source file

    "ogre_source file" 是一个与 Ogre 3D 渲染引擎相关的压缩包,它包含了用于学习和开发基于 Ogre 的应用程序的源代码示例。Ogre 是一款强大的开源图形渲染引擎,广泛应用于游戏开发、虚拟现实和可视化应用等领域。这...

    OGRE初学者引导.pdf

    - 创建第一个项目:编写简单的“Hello World”程序,展示3D立方体。 - 进阶学习:研究光照、材质、动画和脚本,尝试创建更复杂的场景。 7. **社区与资源** - OGRE官方论坛:遇到问题时,可以在官方论坛提问,...

    Havok动画渲染Demo(使用Ogre) 测试程序和源代码

    总之,“Havok动画渲染Demo(使用Ogre) 测试程序和源代码”为我们提供了一个学习和实践Havok物理引擎与Ogre渲染引擎结合应用的宝贵机会。掌握这两个工具的结合使用,对于提升3D游戏或实时仿真应用的品质具有重要意义...

    CEGUI-0.5.0-RC2.zip_CEGUI_CEGUI5.0_Ogre_ Ogre_界面库

    这个"CEGUI-0.5.0-RC2.zip"压缩包包含了CEGUI 0.5.0的第二个候选发布版本,用于与Ogre 3D渲染引擎集成,提供强大的界面创建能力。 CEGUI库的核心特点在于其可扩展性和灵活性,允许开发者根据需求定制各种控件和布局...

    Ogre 3d 1.7 beginner's Guide - 2010

    - **第一个项目**:通过创建简单的“Hello World”项目来熟悉Ogre 3D的工作流程。 ##### 3.3 基础教程 - **基本概念**:介绍了Ogre 3D中的关键概念,如节点(Node)、实体(Entity)、场景(Scene)等。 - **场景构建**...

    Ogre初级和中级教程的代码

    1. **Ogre入门**:介绍如何安装Ogre SDK,设置项目环境,并编写基本的“Hello World”程序,展示如何创建一个窗口并加载Ogre渲染场景。 2. **场景管理**:讲解Ogre的Scene Manager,它是如何组织和管理3D场景的,...

    ogre基础教程 我会向您介绍OGRE最基础的构架:场景管理器,场景节点和实体。由于我需要在这篇教程里把OGRE的基本概念介绍给你,所以我们不会接触太多的代码。在您阅读这篇教程的同时,您应该自己一点一点的添加代码来体会代码的作用,只有这样才可以真正理解这些概念。

    在你的第一个OGRE程序中,你会看到一个简单的`TutorialApplication`类,它是`ExampleApplication`的子类。`createScene`函数是添加和设置场景内容的地方。虽然初始代码可能只包含框架,但随着教程的深入,你将逐步...

    OGREBooks(中文文档)

    它涵盖了从安装到创建第一个项目的整个过程,并且包含了一些常见问题的解答,帮助用户迅速上手。 "OGRE使用指南v0[1].01a.doc"可能是OGRE早期版本的一个用户指南,尽管版本较旧,但对于理解OGRE的基本工作原理仍然...

    Ogrebook

    - 快速入门:搭建开发环境,创建第一个3D应用。 - GUI系统:使用Ogre的Overlay系统创建用户界面。 - 动画系统:角色动画、骨骼动画以及动画状态机。 - 摄像机控制:视角切换、视锥体剪裁等。 - AI与行为树:在...

    OgreBullet

    在实际应用中,OgreBullet可用于创建各种类型的游戏,例如赛车游戏中的车辆碰撞、第一人称射击游戏中的弹道模拟,或者建筑模拟器中的结构稳定性测试。此外,它也适用于非游戏领域的3D应用,如模拟仿真、可视化工具等...

    在游戏中使用CEGUI —— 第一章(底层).pdf

    ### 在游戏中使用CEGUI——第一章(底层) #### 一、引言 随着游戏行业的不断发展,游戏界面设计变得越来越重要。良好的用户界面不仅能够提升玩家的游戏体验,还能提高游戏的市场竞争力。CEGUI(Crazy Eddie's GUI...

    三维渲染引擎编辑器的研究

    总之,基于OGRE的三维渲染引擎编辑器是一个强大的工具,它为三维开发人员提供了一个功能丰富、使用便捷的环境。通过这样的编辑器,可以更高效地制作出高质量的三维应用程序,无论是游戏开发、虚拟现实还是可视化模拟...

    CEGUI 源码最新版(0.7.1)

    CEGUI,全称为“Crazy Eddie's GUI System”,是一个开源的、跨平台的图形用户界面(GUI)库,专门设计用于游戏开发和其他实时应用程序。它提供了丰富的组件和自定义功能,使得开发者能够创建出复杂的、高性能的用户...

    TelaMitto-开源

    TelaMitto是一款开源的第一人称射击(FPS)游戏,采用角色扮演的元素,为玩家提供丰富的游戏体验。它不仅是一个娱乐项目,更是技术爱好者和开发者研究、学习和改进游戏开发技术的宝贵资源。这款游戏的核心特性包括...

Global site tag (gtag.js) - Google Analytics