`
onejavaer
  • 浏览: 5127 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

【转】Ogre 场景管理

阅读更多
每个3D引擎都会用scene graph 来组织它的可渲染对象。scene graph总是会为了更快地搜索与查询做
优化,提供给用户查找目标对象附近特定对象的功能,允许查找,排序,剔除多边形,以实现更高效的渲染。偶尔,scene graph也用于碰撞检测。有时,一个单独的scene graph可被用于程序中的所有子系统,包括音效与物理。
Ogre使用插件机制来实现场景管理功能。ScenceManager只是接口,他可以有很多具体的实现。Ogre允许在同一时刻同一场景中使用多个Scene Manager,这样在不同的场景类型切换时带来好处。

场景管理器的责任
1,创建,放置场景中的可移动对象,light,camera,并可以在图形遍历中有效地访问它们。
2,加载,装配world geometry(它通常很大,向四处延伸,不可移动)
3,完成场景查询,例如可以回答这样的问题:在世界空间的特定点画一个球体,它会包含哪些对象?
4,剔除不可见对象,把可见对象放入渲染队列进行渲染
5,从当前可渲染的透视图中组织,拣选各方向光照
6,设置,渲染场景中的所有阴影
7 设置,渲染场景中的其他对象(如背景,天空盒)
8 传递组织良好的内容到渲染系统进行渲染
场景管理器类型
以分析源码的方式讨论一下插件的加载机制与特定场景管理器是如何进行运用的。
上一章提到了以手工的方式初始化ogre,包括手工加载场景管理器:
root->loadPlugin("Plugin_OctreeSceneManager");
其实所谓的自动方式下,Root:Root()中也会间接调用到loadPlugin()方法,这已在前面的笔记
(配置文件Plugins.cfg )中提到过。既然特定管理器以插件的形式(dll文件)给出,下面先看如何
加载dll. 进入源码:标号表明执行顺序。
void Root::loadPlugin(const String& pluginName)
{
// Load plugin library
    DynLib* lib = DynLibManager::getSingleton().load( pluginName ); //(1)
  // Store for later unload
mPluginLibs.push_back(lib); //(4)
// Call startup function
    DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin"); //(5)
// This must call installPlugin
pFunc(); //(6)
}
DynLib* DynLibManager::load( const String& filename)  //(2)
{
        DynLib* pLib = new DynLib(filename);
pLib->load();       
        mLibList[filename] = pLib;
return pLib;
}
void DynLib::load() //(3)
{
m_hInst = (DYNLIB_HANDLE)DYNLIB_LOAD( name.c_str() );
}
第(3)中的宏定义如下:
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#    define DYNLIB_HANDLE hInstance
#    define DYNLIB_LOAD( a ) LoadLibrary( a )
到此,DLL被加载到内存,第(4)步,mPluginLibs是个STL容器,它存放动态库指针。
第(5)步,进入源码可以看到
void* DynLib::getSymbol( const String& strName ) const throw()
    {
        return (void*)DYNLIB_GETSYM( m_hInst, strName.c_str() );
    }
其中宏定义:define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b ),很显然,它取得一个名为
dllStartPlugin的函数指针:不防再看看宏定义: typedef void (*DLL_START_PLUGIN)(void);
说明DLL_START_PLUGIN为参数为空,返回值为空的函数指针。
每个注册到ogre的dll都实现了这个约定函数。对于我们当前讨论的场景管理器Plugin_OctreeSceneManager
来讲,我们可以找到其相应的定义:它在第(6)步中执行
OctreePlugin* octreePlugin;
extern "C" void _OgreOctreePluginExport dllStartPlugin( void )
{
    // Create new scene manager
    octreePlugin = new OctreePlugin(); //(6-1)
    // Register
    Root::getSingleton().installPlugin(octreePlugin); //(6-2)
}
程序执行到(6-1)步,new 来一个OctreePlugin,我们看一下它的定义:
class OctreePlugin : public Plugin
{
public:
  OctreePlugin();
  const String& getName() const;
  void install();
   void initialise();
   void shutdown();
   void uninstall();
protected:
  OctreeSceneManagerFactory* mOctreeSMFactory;
  TerrainSceneManagerFactory* mTerrainSMFactory;
  TerrainPageSourceListenerManager* mTerrainPSListenerManager;
};
我们会注意到它包含两个工厂类指针:OctreeSceneManagerFactory,TerrainSceneManagerFactory
他们就是用来生产特定ScenManager的,稍后讨论。先看(6-2)步:
void Root::installPlugin(Plugin* plugin)
{
mPlugins.push_back(plugin);  //(6-2-1)
plugin->install();             //(6-2-2)
// if rendersystem is already initialised, call rendersystem init too
if (mIsInitialised)
{
plugin->initialise();         //(6-2-3)
}
}
//(6-2-1)步把插件放到容器中。看看(6-2-2)做了什么:
void OctreePlugin::install()
{
  // Create objects
  mOctreeSMFactory = new OctreeSceneManagerFactory();
  mTerrainSMFactory = new TerrainSceneManagerFactory();
  mTerrainPSListenerManager = new TerrainPageSourceListenerManager();
}
呵,刚才还说两个工厂类指针,现在把两个工厂建起来,以后可以用来生产东西了。
继续看看(6-2-3):
void OctreePlugin::initialise()
{
  // Register
  Root::getSingleton().addSceneManagerFactory(mOctreeSMFactory);
  Root::getSingleton().addSceneManagerFactory(mTerrainSMFactory);
}
哦,把这两个工厂注册到Root中,让Root可以使用它们。啊这句话有点问题,Root只是间接的用到,
直接雇主是 SceneManagerEnumerator* mSceneManagerEnum;它被包含在Root中。于是我们可以看到
void Root::addSceneManagerFactory(SceneManagerFactory* fact) //(6-2-3-1)
{
  mSceneManagerEnum->addFactory(fact);
}
工厂已经有了,我们如何利用这个工厂生产出我们想到的东西(SceneManager)呢?
回忆上一章的手工初始化过程中,我们一般用以下语句来创建SceneManager:
  SceneManager *sceneMgr = root->createSceneManager(ST_GENERIC); //(A)
也可以这样用
  sceneMgr = ogre->createSceneManager("OctreeSceneManager"); //(B)
每个工厂类都用一个字符串表示其类型。上面说的两个工厂分别使用的字符串为:“TerrainSceneManager”,"OctreeSceneManager"
(A)语句肯定会调用工厂类的方法来产生实际的SceneManager,下面看源码验证一下:
SceneManager* Root::createSceneManager(const String& typeName,
  const String& instanceName)
{
  return mSceneManagerEnum->createSceneManager(typeName, instanceName);
}
继续挖:
SceneManager* SceneManagerEnumerator::createSceneManager(
  const String& typeName, const String& instanceName)
{
  SceneManager* inst = 0;
  for(Factories::iterator i = mFactories.begin(); i != mFactories.end(); ++i)
  {
   if ((*i)->getMetaData().typeName == typeName)
   {
    if (instanceName.empty())
    {
     // generate a name
     StringUtil::StrStreamType s;
     s << "SceneManagerInstance" << ++mInstanceCreateCount;
     inst = (*i)->createInstance(s.str());
    }
    else
    {
     inst = (*i)->createInstance(instanceName);
    }
    break;
   }
  }
}
上述代码很简单:因为执行(6-2-3-1)已经过实际工厂类实例进行了注册。于是遍历每个工厂实例,
找到类型相符的。找到之后,如果没有传场景管理器实例的名字,就起个名字。然后用这个名字
生产出一个实例来。CreateInstance没干什么,new 呗。
SceneManager* OctreeSceneManagerFactory::createInstance(
const String& instanceName)
{
return new OctreeSceneManager(instanceName);
}
就是这样。OctreeSceneManager and TerrainSceneManager 的功能都是由一个DLL提供的。它们的关系是:class _OgreOctreePluginExport TerrainSceneManager : public OctreeSceneManager,按照一般的类关系逻辑,
我们知道派生类一般功能都比父类强大,父类应用于一般场景,子类针对特定场景。这个逻辑在这里是对的。本来是写读书笔记,跑题了,打住。

场景对象创建
场景中的所有对象,包括可移动与不可移动的:lights, cameras, entities,particle system,
billboards, skyboxes, static geometry , world geometry.都由场景管理器来创建。场景中的
任何东西都由场景管理器来管理。任何通过场景管理器得到的东西,都必须由场景管理器来销毁。
用户不能delete通过由场景管理器得到的指针。
场景结点只有一个父结点,可能有多个子结点。可以随意的attach 和 detach 这些场景中的结点。
在明确告诉场景管理器销毁这些结点前,它们总是存在。如果不想渲染场景中的某些结点上的内容,
我们可以很方便地对她们进行detach.场景中总是存在一个Root结点。可以把多个内容对象attach到
同一个结点上。不能同时把一个实例对象挂到两个场景结点上,一个场景结点也不能有两个父结点。
总是场景结点在执行空间操作(平移,旋转,缩放)而不是实体对象。
场景查询
场景管理器的第二个最常用的功能是进行场景查询。包括射线查询,球查询,绑定盒查询,绑定平面
查询,相交查询。Terrain clamping:在崎岖不平的路上,勇敢地向下发射一束光,不管你告诉我你有
多高,我永远把你踩在脚下..(是不是不太像笔记?^_^)。所有这些查询都是 maskble的,这表明可
以在查询时过滤掉不关心的对象类型。如球查询时,只想看看它包含了多少lights,其他的对象即使包含在球里也不必返回,实际上根本不用计算。
空间关系与3D变换
world , parent , local世界空间中的变换是相对于全局坐标系的源点(0,0,0),这也是root scene node的位置。因此可以认为世界空间中的变换是相对于Root scene node的。父空间中的变换是相对于场点结点的父结点的,本地空间的变换是相对于物体所挂接的结点的。大多数情况下,我们会在父空间中做平移,在本地空间中做旋转,ogre中的这些操作,都是在上述的这种方式下。
object space
从模型导出的顶点数据与它的源点之间的关系是不变的,当它被挂到场景结点上,这个结点就是认为是
它的源点。建模时与导出时不假设测量单位,以世界单位导出(也就是无单位)。
ogre平移与设置位置不同:平移可以有多个参照点(world,local,parent space),而用setPosition()
时,总是相对于parent-space 坐标系的。
可移动的场景对象
基于资源的对象:最普通的是mesh(陪伴着skeleton),这种类型的对象被资源管理系统管理。
场景管理器不负责实际的装载,它调用Ogreuq资源管理器来完成。
基于四边形的对象:粒子系统,公告板,ribbon trail,overlay,天空盒。它们通常是面向相机的,
使用动态材质。它们的主要资源是脚本,这些脚本定义了如何映射材质,以及它们的生命期(对于粒子系统与ribbon trail来说)。天空盒直接用场景管理器来定义。
skyplane,skydome,skybox
主要的相似点是它们与相机保持一个常量的距离。它们可以在场景中其它对象
之前或是之后渲染。它们使用普通的ogre material,因此纹理动画与其他纹理没有什么不同。它们可以
被场景管理器打开或关闭,与相机的距离也可以设置。
skyplane 是一个平面。用距离和法线定义它与相机的位置关系。可以弯曲,可以分多个段,可对纹理进行多次平铺。skydome由五个平面组成,底部空。使用改变纹理坐标的方式来达到外观上的曲率变化。有一个值用来调节,值越低,曲率越柔和,值越高,越陡峭。skybox 像skydome,但他不能“弯曲”材质坐标。它可以使用立方材质。可使用硬件加速功能达到很好渲染效率。

使用光的限制:单个通道通常最大支持8个灯。使用更多的灯,通过多通道。
光与物体之间的距离,决定光对物体实际的影响。Ogre支持点光源,平等光,聚光灯。
世界几何
当创建基于mesh的景物或关卡,应该分成较小的部分,以便于裁减。Paging Scene Manager提供了这样的工具。
空间分割方案
Ogre是基于硬件加速渲染引擎,因此以最大化几何体batching的方式会比基于实际多边形进行空间分割
效果要好的多。Modern GPUs prefer to render a few large batches of geometry instead of
many small batches.
The more visible geometry you can render in a single batch, the better your application’s
performance is likely to be (within reason, of course; other classic issues such as fillrate and
overdraw can still take over if you just blindly blast polygons at the GPU, batched or not).
静态几何使用注意:
静态几何在使用之间必须被建立。
使用相同材质的几何体将被放到同一渲染操作中(batch):different materials still require a separate batch.
努力的方向是,最大化一个调用的三角形数,最小化调用的次数。
不能移动被包含在static geometry中的对象。只有一个世界转换应用到完整的static geometry对象上.
比同样规模的movable geometry占用更多的内存。
假如组中的任何东西在视锥之内,那么组中的所有对象都将被渲染。
分享到:
评论

相关推荐

    OGRE场景管理分析

    场景组织是整个 Engine的灵魂, 而且到目前为止没有适用于任何场景的场景组织方式,所以都...对于不同的场景需要不同的组织方式,才能有效的进行管理。但是对于不同的场景都有其基本特性。本文从这些基本特性进行分析。

    ogre场景编辑器

    Ogre场景编辑器是专为Ogre 3D渲染引擎设计的一款强大的工具,它允许开发者和设计师直观地创建、编辑和管理复杂的3D场景。Ogre,全称为Object-Oriented Graphics Rendering Engine(面向对象的图形渲染引擎),是一款...

    c# 实现的OGRE场景编辑器 OgreStudio

    1. **场景管理**:用户可以通过Ogre Studio创建、导入、删除和组织3D场景对象,包括模型、光照、摄像机等。 2. **直观的界面**:C#实现的用户界面通常更加直观易用,提供拖放功能,使得场景构建更为便捷。 3. **...

    3 ogre场景管理.ppt

    3 ogre场景管理.ppt

    Ogre场景管理器SceneManager类

    Ogre的场景管理器SceneManager是Ogre 3D渲染引擎中的核心组件,它负责组织和管理游戏或应用中的三维场景。场景管理器包含了对场景中各个元素如相机、灯光、实体(Entity)以及场景节点(SceneNode)的创建、获取、...

    BSP.rar_BSP_Ogre_ Ogre_场景管理

    **BSP.rar_BSP_Ogre_ Ogre_场景管理** 在计算机图形学中,BSP(Binary Space Partitioning,二进制空间分割)是一种强大的场景管理技术,尤其适用于室内环境的渲染。Ogre是一个流行的开源3D图形引擎,它提供了多种...

    Ogre3D场景编辑器

    1. **场景管理**:编辑器允许用户创建、导入和导出3D场景,通过直观的界面进行物体摆放、删除、复制和粘贴。用户可以调整对象的位置、旋转和缩放,实现精确的场景布局。 2. **模型导入与编辑**:支持多种3D模型格式...

    基于Ogre的场景编辑器OgreSE源代码+示例

    2. **多层次场景管理**:支持场景图,允许组织和管理复杂的3D对象和层次结构。 3. **丰富的材质系统**:支持自定义纹理、光照、着色器,允许创建复杂的视觉效果。 4. **多通道渲染**:支持多个视口和渲染目标,如...

    ogre场景组织分析

    ### Ogre场景组织分析 在游戏开发与三维图形领域,Ogre是一个广受赞誉的开源图形渲染引擎,以其高效、灵活的特性,为开发者提供了构建复杂3D环境的强大工具。其中,场景组织是Ogre的核心机制之一,它不仅关乎场景的...

    ogre 场景中文字显示

    本文将深入探讨如何在Ogre场景中实现文字的显示,以及如何实现文字面向相机、不随场景移动以及居中等操作。我们将主要关注`MovableText.cpp`和`MovableText.h`这两个文件,它们是Ogre中处理动态文本的核心组件。 ...

    Ogre初级和中级教程

    基础教程一 场景管理器,场景节点和实体 基础教程二 摄影机,阴影和光照处理 基础教程三 天空,地面和雾化处理 基础教程四 帧监听器和非缓冲输入 基础教程五 缓冲输入 基础教程六 CEGUI和OGRE 基础教程七 ...

    OGRE分析之场景管理

    ### OGRE分析之场景管理深度解析 #### 一、场景的构成与角色 在深入探讨OGRE(Object-Oriented Graphics Rendering Engine)的场景管理之前,我们先理解场景的基本构成。场景,作为游戏或虚拟环境中视觉表现的核心...

    ogre基础教程一(场景管理器、场景节点和实体)

    ### Ogre基础教程一:场景管理器、场景节点和实体 #### 一、引言 Ogre是一款开源的3D图形渲染引擎,适用于游戏开发、模拟系统以及任何需要高性能3D图形渲染的应用。对于初学者来说,掌握Ogre的基础概念至关重要。...

    ogre 资源管理

    在众多特性中,资源管理和场景内容设计尤为突出,它们不仅体现了Ogre的强大能力,也为开发者提供了极大的便利。本文将深入探讨Ogre中的资源管理模块及其设计理念。 #### 二、资源管理的重要性 资源管理是3D引擎的...

    3D MESH格式 OGRE大场景模型

    在OGRE中,大场景模型的加载和管理是一个挑战,因为它们可能包含数以万计的多边形,需要高效的优化策略来确保流畅的性能。 在使用3D MESH格式的模型与OGRE结合时,有以下几个关键知识点: 1. **模型导入与转换**:...

    ogre开发的简单场景查看器源码 xgEditor

    - Ogre引擎的核心组件包括渲染系统、资源管理系统、场景管理系统等。渲染系统负责将3D模型转化为2D图像显示在屏幕上;资源管理系统管理纹理、模型、材质等资源的加载和释放;场景管理系统则负责组织和管理3D场景中...

    ogre3D引擎教程

    ogre场景组织分析.pdf OGRE的消息机制.pdf Ogre的渲染系统(Rendering System).pdf OGRE分析之场景管理.pdf OGRE分析之场景渲染.pdf OGRE分析之设计模式(1234).pdf OGRE分析之文件系统(1234).pdf ogre数据文件...

    ogre材质编辑器OgreMaterialEditor

    它提供了丰富的图形API支持,如Direct3D和OpenGL,以及强大的场景管理、光照模型、纹理处理等功能。而OgreMaterialEditor则是Ogre 3D引擎生态系统的一部分,专门用于处理材质(Material)——定义表面如何被光照、...

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

    本教程旨在介绍OGRE的基础构架,包括场景管理器、场景节点和实体,帮助初学者理解其核心概念。 ### 1. 场景管理器基础 场景管理器是OGRE中负责组织和渲染3D场景的核心组件。它负责管理场景中的所有对象,如实体、...

    Ogre 引擎 源码分析

    下面我们将从消息处理、文件系统、数据管理以及场景渲染等关键方面来探讨Ogre引擎的核心知识点。 1. **消息处理**:在Ogre引擎中,消息系统是组件之间通信的重要桥梁。引擎内部通过事件驱动模式实现,各个组件可以...

Global site tag (gtag.js) - Google Analytics