您的位置:首页 > 移动开发 > Objective-C

OGRE基础教程一:OGRE最基本的组成结构:SceneManager,SceneNode和Entity objects

2013-11-07 17:23 471 查看
文献来源网址:http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Basic+Tutorial+1&structure=Tutorials

    导言:

    在本节教程中,我们将会向您介绍OGRE最基本的组成结构:场景管理器(SceneManager),场景节点(SceneNode)和实体对象(Entity objects),我们不会涉及大量的源代码,相反地,由于开始学习OGRE,我们会着重给你介绍几本概念。

    当您浏览本教程的时候,你可以慢慢地将代码加入到你自己的项目,然后查看编译结果。没有比实际编程更好的方法去熟悉这些概念,如果你仅仅是阅读,我劝你还是打住你的念头吧。(个人注:实践是学习编程最好的方法)

    预备知识:

    1,本教程假设你已经拥有C++知识和能够建立和编译OGRE运用程序

     2,本教程假设你已经用 Ogre Wiki Tutorial Framework创建了一个工程,或者,手动地,用CMake或者Ogre运用程序向导--请查看Setting
Up An Application 使用说明  

开始:

    从这里开始在这篇教程里,我们将使用已经写好的代码作为模版。除了我们将要在createScene函数里面添加的代码之外,您可以暂时忽略其他的东西。在后面的教程里我会深入讲解OGRE程序是如何工作的,现在我们只需要从最简单的地方学起就行了。在您的IDE创建一个名叫Tutorial工程,然后把教程运用程序框架(tutorial
application framework)下面的代码添加进去:

BaseApplication.h
BaseApplication.cpp
TutorialApplication.h
TutorialApplication.cpp

    从这里获取以上文件: Ogre Wiki Tutorial Framework 
    或者,使用Ogre AppWizard

.

    TutorialApplication.cpp是本教程中我们唯一使用的文件,并且我们只在成员函数createScene()进行工作。

    TutorialApplication.cpp应当包含以下代码 

   

#include "TutorialApplication.h"

TutorialApplication::TutorialApplication(void)
{
}

TutorialApplication::~TutorialApplication(void)
{
}

//-------------------------------------------------------------------------------------
void TutorialApplication::createScene(void)
{
// Set the scene's ambient light
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));

// Create an Entity
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");

// Create a SceneNode and attach the Entity to it
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");
headNode->attachObject(ogreHead);

// Create a Light and set its position
Ogre::Light* light = mSceneMgr->createLight("MainLight");
light->setPosition(20.0f, 80.0f, 50.0f);
}

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

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
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( Ogre::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
std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl;
#endif
}

return 0;
}

#ifdef __cplusplus
}
#endif


    继续编译和运行这个程序,当然你要保证你的环境配置正确的,一旦你的程序是正常运行起来,使用WASD键移动,鼠标键用来环顾四周,ESC键退出程序。

   


    个人注:在IDE中创建工程时,可以选择控制台,也可以选择win32。

    小细节:上面可以看出,average  fps 有个fps重叠的字符串fps,这应该是个bug,修改文件SdkTray.h,将2768行与2774行中的 values.push_back(s); 改为values.push_back(str);修改后运行的截图:多出来的fps字符串没有了,感觉清爽多了,


   


解决问题:

    如果你有问题,请检查下运用程序的设置使你的编译器配置正确,或者查看Ogre.log文件获取更多的详细信息。如果你需要帮助。可以去搜索论坛(http://www.ogre3d.org/forums/search.php),可能你的问题,别人已经遇到了很多次。如果这是一个新的问题,阅读论坛规则,然后再问。确保从您的Ogre.log提供相关细节,异常,错误消息,和/或调试后的痕迹。

    需要注意的是以后的教程中,将不包含此类问题解决的信息,所以请如果您有问题,要特别注意以下几个部分。

    1,MessageBox的问题

    如果你使用支持UNICODE字符集的VS,你可能会遇到如下问题:

error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char *' to 'LPCWSTR'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or  function-style cast

    这个问题是MessageBox函数(在这种情况下)是期待的是Unicode类型的字符串(个人注:此时的形参的类型必须是宽字符类型的),而我们给的是你ANSI字符串,修正这个错误,我们只需要修改下面的代码

MessageBox( NULL, e.what(), "An exception has occurred!", MB_OK |   MB_IConerror  | MB_TASKMODAL);


为:

MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK |   MB_IConerror  | MB_TASKMODAL);


     或者,你也可以将编译器的字符集从Unicode改为ANSI,然后,你这样做,会失去国际语言的支持。

    这样做的原因是,"MessageBox "将被自动解析为,要么是MessageBoxA(ANSI),要么是MessageBoxW(宽/ Unicode),根据项目配置,我们明确它使用ANSI修复该错误。

   2,缺失配置文件或者dll

    如果你试图启动你刚生成的应用程序,但该程序报错,缺少DLL或配置文件(*.cfg),,那么你可能没有将它们从OgreSDK的文件夹中复制过来,在VS中,当你在release模式下编译你的运用程序,它将release版的可执行文件放在[ProjectFolder]\ BIN \ release文件夹中,debug版的可执行文件放在[ProjectFolder] \ BIN \ debug文件夹中。你必须从OgreSDK中复制所有的".dll",".cfg" 的文件到相应的文件夹中。也就是说,将这些文件从[OgreSDK]\
BIN \release 文件夹复制到[ProjectFolder]\ BIN\release文件夹,从[OgreSDK] \ BIN \debug文件夹复制到[ProjectFolder] \ BIN \debug文件夹。您还需要编辑的resources.cfg文件以便指向正确的路径。想获取更多信息,请参阅下一节。

    3,资源或插件问题

    确保你有一个plugins.cfg和resources.cfg文件在与可执行文件相同的目录中。Plugins.cfg告诉OGRE哪个渲染库是可用的(Direct3D9,OpenGL等)。resources.cfg被ExampleApplication使用,用于指定纹理,网格模型和脚本的路径。它们两个都是文本文件,所以可以编辑它们以保证这些路径是正确的。否则,您的OGRE设置对话框可能没有任何渲染库,或者您可能会收到一个错误,在你的屏幕上或在Ogre.log文件中,看起来像这样:

Description: ../../Media/packs/OgreCore.zip - error whilst opening archive: Unable to read zip file

    如果是这种情况,打开你的resources.cfg文件,修改它包含的路径,使它指向Media文件夹(附带有食人魔(Ogre))的位置。注意:您不能使用环境变量在这些路径上,例如$(SomeVariable)。

ogre是怎么工作的?

    OGRE是怎样工作的这是一个很广的话题,我们将从场景管理器开始然后进一步了解场景节点和实体。这三个类是所有OGRE程序的基石。

     1,场景管理器基础:
     在屏幕上显示的所有东西都是由场景管理器来管理。当您在场景中添加物体时,场景管理器会记录这些物体的位置。当您添加摄像机来观看某个场景时,场景管理器会记录摄像机的位置。当您添加平面、广告牌、灯光时,场景管理器同样会管理他们。 OGRE里有很多种场景管理器。有的场景管理器渲染地面,有的场景管理器渲染BSP表等等。在后面,我们将进一步了解场景管理器。
     2,实体基础:
    一个实体是可以在场景中渲染的物体之一。您可以把实体理解为任何一个3D模型。一个机器人可以是一个实体,一条鱼可以是一个实体,大地草原可以是一个非常大的实体。灯光,摄像机,粒子,广告牌等不能成为实体。
    关于OGRE需要注意的一点是,它从对象的位置和方向分离出渲染对象,这就意味着,在 Ogre中你不能够直接将一个实体放入到场景中,而是将实体与场景节点绑在一起,这个场景节点则包括了实体的方位信息。
     3,场景节点基础:
    场景节点将持续跟踪与它绑在一起的实体的方位。当你创建了一个实体时,它直到与一个场景节点绑定后才会被渲染。同样,一个场景节点也不能单独的在屏幕上显示出来,只有与一个实体绑定后才能在屏幕上显示。
    场景节点可以绑定多个实体。例如在屏幕上有在行走的一个人物对象,并且希望这个对象产生发光效果,要实现这些,首先你需要创建一个场景节点,然后再创建一个人物对象的实体并与场景节点绑定在一起,之后你还需要创建一个光照模型也与这个场景节点绑定在一起。场景节点同样可以与其它场景节点绑定以描述更完整的对象。我们在后续的章节中介绍场景节点更多的用法。
    在场景中,场景节点的位置总是与它的父节点相关。每一个场景管理器都包含一个根节点。
你的第一个OGRE程序
    返回到我们刚才创建的代码,找到 TutorialApplication::createScene成员函数。首先需要为整个场景设置环境光,这样才可以看到要显示的内容,通过调用setAmbientLight函数并指定环境光的颜色就可以做到这些。指定的颜色由红、绿、蓝三种颜色组成,且每种色数值范围在0到1之间。将下一句添加到
createScene 中:

mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));


    下一步创建一个 Entity,通过调用 SceneManager的
createEntity 方法来创建:

Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");


    好的,一些问题需要提出来,首先,mSceneMgr来自哪里?我们调用函数的参数是什么?mSceneMgr变量是当前场景管理器对象(这个是BaseApplication类为我们做的)。createEntity函数的第一个参数是我们创建实体对象的名字,所有的实体必须有唯一的名字,如果你创建两个名字相同的实体对象,你会得到一个错误,第二个参数 "ogrehead.mesh" 指明我们用于实体的网格模型,"ogrehead.mesh"是一个来自Ogre SDK的资源。资源加载和网格模型将会在后面的教程中涉及,现在,我们直接使用具有资源加载能力的BaseApplication类。我们已经创建了一个实体,但还需要创建一个场景节点来与它绑定在一起。既然每个场景管理器都有一个根节点,那我们就在根节点下创建一个场景节点。

Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");


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

    然后,将实体绑定到场景节点,指定了Ogre Head渲染位置

headNode->attachObject(ogreHead);


    尽管灯光知道下一个章节才会涉及,但是,我们在这里添加一个灯光,这样我们看到模型带有适当的阴影,而不是来自自然光的平坦阴影,当我们创建灯光时,我们也要给一个唯一的名字。

Ogre::Light* light = mSceneMgr->createLight( "MainLight" );


    一旦灯光被创建,可以用setPosition函数设置它的位置,。给定的这三个参数是要设置的新的位置的X,Y和Z坐标。坐标将在下面详细讨论。

light->setPosition(20, 80, 50);


    编译运行你的程序,你将会在屏幕中看到食人魔的头像。
   


坐标与向量
    待续.....
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OGRE 基础教程 C++