初学Ogre 貌似看到一些套路(ajohn)

1 Ogre的编译
  获得最新的Ogre 1.71 和之前的Ogre比起来,除了sampler集成之外,最大的改变就是编译过程加入了Cmake,这个东西其实就是检测你电脑上装了些什么?
  比如说是否安装DX_SDK 如果没有装,就不会有RenderSystem_DXXXX的工程,如果有装,检测DXSDK是什么版本的,相应产生
  RenderSystem_DX9 RenderSystem_DX10 RenderSystem_DX11工程到你的解决方案中
  还有就是boost,如果你安装了一定版本的boost(太低了不行)便会加入多线程
  网上看到一个评估程序员能力的文章:
  说对于工程的编译的最高境界,就是写相关的编译脚本,让我想起了linux的工程的编译,不禁感叹生在Windows是多么得幸福,
  俺的工程编译的境界还停留在初期阶段,顶多就是把VS玩来玩去,而且VS的工程设置的每个选项还不一定都知道。- -!

1 内存管理
  之前分析过U3的内存管理以及其GC机制,所以一上来就看内存,Ogre没有GC,有的是比
  System new和delete效率更高,速度更快的nedmalloc的封装。
  nedmalloc是一个免费的第三方支持多线程并且速度在同类产品中很快的内存管理库。
  Ogre对nedmalloc的封装可以说是一波三折,并且提供内存泄露检测工具类,
  先从底层看OgreMemoryNedPooling.h
  NedPoolingImpl 接口类,适配模式,提供allocBytes,deallocBytes,具体实现便是对nedmalloc的调用
  NedPoolingPolicy Alloc的分配策略,也是简单提供allocateBytes和deallcateBytes,具体通过NedPoolingImpl来操作
  接下来在OgreMemoryAllocatorConfig.h中提供一个模板类
  template <MemoryCategory Cat> class CategorisedAllocPolicy : public NedPoolingPolicy{};
  似乎没做什么,其实意义很大,目的是可以通过模板实例化来定义不同的AllocPolicy。
    typedef CategorisedAllocPolicy<Ogre::MEMCATEGORY_GENERAL> GeneralAllocPolicy;        通用分配器
 typedef CategorisedAllocPolicy<Ogre::MEMCATEGORY_GEOMETRY> GeometryAllocPolicy;      几何图元分配器
 typedef CategorisedAllocPolicy<Ogre::MEMCATEGORY_RESOURCE> ResourceAllocPolicy;
 .
 .
  这些其实都是一样的东西,但是类名不一样
  转到OgreMemoryAllcatedObject.h 的 templete<class Alloc> class AllocatedObject 模板类
  提供operator new, operator delete, operator new[], operator delete[]。
  里面的操作就是通过模板类型Alloc的 allocateBytes 和 deallocateBytes来分配内存.
  再回头看OgreMemoryAllocatorConfig.h
    typedef AllocatedObject<GeneralAllocPolicy> GeneralAllocatedObject;                  通用分对象            
 typedef AllocatedObject<GeometryAllocPolicy> GeometryAllocatedObject;                集合图元分配对象
 typedef AllocatedObject<ResourceAllocPolicy> ResourceAllocatedObject;
 .
 .
  还没完。。。。Ogre似乎为大部分常用的类(或者说sizeof(该类)很大)都定义了一个具体的名字:
    typedef ResourceAllocatedObject  ResourceAlloc;
    typedef SceneObjAllocatedObject  SubEntityAlloc;
    typedef ResourceAllocatedObject  SubMeshAlloc;
    typedef RenderSysAllocatedObject BufferAlloc;
  看Resource类的申明:
  class Resource : public StringInterface, public ResourceAlloc
  所以,当你new Resource或者Resource的派生类的时候,内存的分配通过ResourceAlloc -> ResourceAllocatedObject
     -> operator new -> ResourceAllocPolicy::allocateBytes -> NedPoolingPolicy::allocateBytes
     -> NedPoolingImpl::allocaBytes -> nedmalloc的C函数开辟内存(->不是指的函数调用)
  当某些类或者资源没有派生自这些Alloc的时候,怎样用nedmalloc来处理?
  Ogre提供很多宏来用nedmalloc操作内存:
  OGRE_MALLOC (等同于malloc) OGRE_ALLOC_T(等同于malloc) OGRE_FREE(等同于free)
  OGRE_NEW_T (等同于new)OGRE_NEW_ARRAY_T(等同于new[]) 
  OGRE_DELETE_T (等同于delete) OGRE_DELETE_ARRAY_T(等同于delete[])。
  最后提下内存跟踪和泄露:
  参看OgreMemoryNedPooling.cpp
  在NedPoolingImpl的allocBytes和deAllocBytes中,如果定义了OGRE_MEMORY_TRACKER宏,便会把当前的
  内存分配信息交给MemoryTracker处理,MemoryTracker是单件,里面用哈希表
  typedef HashMap<void*, Alloc> AllocationMap;   AllocationMap mAllocations;   
  来存储这些内存分配和释放信息,计算是使用HashMap,速度还是慢,测试了一下,
  没有内存跟踪和有内存跟踪的性能比为 38::5

2 SharedPtr
  纯粹模仿boost::shared_ptr。
  基类实现几个重要的操作接口:
  SharedPtr() 对象指针和计数指针都为NULL。
  explicit SharedPtr(Y* rep)对象指针->rep 计数指针->+1
  SharedPtr(const SharedPtr& r)对象指针->r的对象指针 计数指针->r的计数指针并+1
  SharedPtr& operator=(const SharedPtr& r)有点复杂,自己跟代码
  而每个资源型的类,貌似都附带一个该类的Ptr,
  1 直接定义 有的直接def SharedPtr<SomeClass> SomeClassPtr;
  2 继承 有的是class SomeClassPtr : public SharedPtr<SomeClass>。
  分析一下TexturePtr说明为什么有继承的存在:
  TexturePtr 新加入了2个函数:
        TexturePtr(const ResourcePtr& r) 把资源指针看成纹理
        TexturePtr& operator=(const ResourcePtr& r) 同上
  索迪斯内

3 Manager
  凡有很多对象需要管理,比如说Resource , SceneNode, 等 都会配套实现一个该类的Manager
  如ResourceManager SceneManager
  虽然所有的Manager都是单件,但是并不是真正意义上的单件!一般说来,单件是不允许new出来的,即
  sigleton基类的构造函数是protected的,
  而Ogre的sigleton的构造函数是public,这样就允许new SomeManager出来。
  这样做的目的是为了实现Plugin机制(抽象工厂模式)。
  比如说有个TextureManager(抽象类) createImpl创建的产品是 TexturePtr
  而D3D9TextureManager(具体实现类) createImpl创建的产品是 D3D9TexturePtr
    GLTextureManager(具体实现类) createImpl创建的产品是 GLTexturePtr
  OgreMain中给用户的只有TextureManager接口,那么它到底是哪个具体实现类?
  所以必须new出来,so,就有了这个不标准的sigleton  
  
  例举Resource。关键步骤如下
    class D3D9Resource
    {
        //不做任何事情,相应派生自改类的做事情
        virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) {}
       //当创建一个需要管理的对象的时候,通知合适的Manager做处理 一般说来就是加入到manager的自身列表
        D3D9Resource::D3D9Resource()
        {    
            D3D9RenderSystem::getResourceManager()->_notifyResourceCreated(static_cast<D3D9Resource*>(this));  
        }
        //当销毁一个需要管理的对象的时候,通知合适的Manager做处理,一般说来就是从manager的自身列表中删除
        D3D9Resource::~D3D9Resource()
        {  
            D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
        }
    };
  
    
    class D3D9RespirceManager
    {
        //加入列表
        void _notifyOnDeviceCreate (IDirect3DDevice9* d3d9Device)
        {
            mResources.push_back(pResource);
        }
        //从列表中找到该对象,并且删除
        void _notifyResourceDestroyed(D3D9Resource* pResource)
        {  
            OGRE_LOCK_MUTEX(mResourcesMutex)

ResourceContainerIterator it = mResources.begin();

while (it != mResources.end())
            {
                if ((*it) == pResource)
                {
                    mResources.erase(it);
                    break;
                }   
                ++it;
            } 
        }
        //注意,保存的是指针。
        //这里用的vector,因为删除,查找操作不常见,否则会用map,比如说SceneManager
        typedef vector<D3D9Resource*>::type  ResourceContainer;
    }
    
    
4, Plugin
    就RenderSystem_DX9来详细说明一下
    基本流程如下:
    1,OgreMain 定义基本接口 RenderSystem  Texture HardwareVertexBuffer HardwareIndexBuffer
        其中RenderSystem代表抽象出的渲染接口  其他类代表是渲染资源
    2,Plugins 写各种基于改基本接口的扩展类的dll 提供 D3D9RenderSystem D3D9Texture D3D9HardwareVertexBuffer HardwareIndexBuffer
    3,配置文件制定那种dll,就动态链接动态链接库,来找到扩展类的实现
    
    逆向分析RenderSystem_DX9的实现,先了解Plugin的思路。
    Ogre运行,
    new Root(); 
    跟入代码发现root() -> loadPlugins() -> loadPlugin() -> pFunc().
    仔细跟一下代码发现pFunc()是Dll的extern "C"的导出函数,如果你当前的Plugin是RenderSystemn_DX9的话
    会进入到OgreD3D9EngineDll.cpp -> dllstartPlugin中 改dllstartPlugin做的事情是:构建D3D9Plugin对象
    然后通知Root维护该对象,并且调用plugin->install().进入到OgreD3DPlugin::install,构建D3D9RenderSystem
    然后通知Root维护改RenderSystem。 
         over
    Plugin的机制就是以dll的方式来隐藏具体的实现,比如说D3D9Device,D3D9IB D3D9VB D3D9Textuer
    Ogremain提供基本的抽象,比如说3D引擎都有渲染器,便抽象出RenderSystem以及里面的接口,如针对DX9的Device提供的函数的
    各种具体操作:如_useLights _setDepthBias _setfog _setTexture _setWorldMatrix等等
    用户(使用Ogre的民工)只需要面对Ogreman的接口,无须关心DX的具体实现,
    对于资源型接口,如HardwareVertexBuffer HardwareIndexBuffer Texture来说,也是同理,
    分析一下Texture的创建过程,根据套路2,Manager的思路,在root初始化之后写下如下代码调试跟进。
    Ogre::TexturePtr pt = Ogre::TextureManager::getSingleton().create("danteng.jpg","danteng");
    会发现,最终由D3D9TextureManager负责创建一个D3D9Texture,然后返回其基类TexturePtr的智能指针
    D3D9TextureManager是继承自TextureManager,并且是单件,根据抽象工厂设计模式的概念来理解
    一般单件都不是new出来的,而是getsingleton出来的,但是Ogre为了保证抽象工厂,必须注册一个具体的Manager。
    这个初始化过程在root->initialize() -> mActiveRenderer->_initialise() -> mTextureManager = new D3D9TextureManager();
    注意这个mTextureManager是RenderSystem接口的成员。
    于是乎,,D3D9Texture透明化了,用户能看到的只有Texture

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/shenghanzhouyou/archive/2010/05/05/5559730.aspx

转:Ogre源码剖析1的更多相关文章

  1. 转:Ogre源码剖析 - 场景管理之Octree

    由于本人的引擎ProjectGaia服务于08年创新杯的游戏项目 – 3D太空游戏,所以理所应当加入Octree(八叉树 – 已经周宁学长发帖介绍过)场景管理器.参考了无数Octree的代码,发现还是 ...

  2. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

  3. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  4. Apache Spark源码剖析

    Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著   ISBN 978-7-121-25420- ...

  5. 基于mybatis-generator-core 1.3.5项目的修订版以及源码剖析

    项目简单说明 mybatis-generator,是根据数据库表.字段反向生成实体类等代码文件.我在国庆时候,没事剖析了mybatis-generator-core源码,写了相当详细的中文注释,可以去 ...

  6. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

  7. SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现

    SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...

  8. 自己实现多线程的socket,socketserver源码剖析

    1,IO多路复用 三种多路复用的机制:select.poll.epoll 用的多的两个:select和epoll 简单的说就是:1,select和poll所有平台都支持,epoll只有linux支持2 ...

  9. Java多线程9:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

随机推荐

  1. 自适应尺寸变化的meanshift跟踪

    近期在看meanshift方面的文章,看了一篇博文对这篇文章<Robust scale-adaptive meanshift for tracking>寄予非常高的评价,所以把这篇文章简要 ...

  2. Deformable Convolutional Networks-v1-v2(可变形卷积网络)

    如何评价 MSRA 视觉组最新提出的 Deformable ConvNets V2? <Deformable Convolutional Networks>是一篇2017年Microsof ...

  3. 关掉Windows Firewall的PowerShell

    在Windows 8或Windows 2012 R2上, 使用下面的命令: Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled ...

  4. 根据ip地址获取用户所在地

    java代码: package com.henu.controller; import java.io.BufferedReader; import java.io.IOException; impo ...

  5. ES8新特性——ES8 was Released and here are its Main New Features

    原文: https://hackernoon.com/es8-was-released-and-here-are-its-main-new-features-ee9c394adf66 -------- ...

  6. Flask莫名其妙特别慢

    其他上网都正常,代理服务器.防火墙反复检查都没问题,最后,严重怀疑腾讯的mysql服务器,监控是这样的: 突然下降那段就很不正常. 后面忽然就崩溃了,死活都连不上.把可疑连接都关闭了,把防火墙都关闭了 ...

  7. 如何用Docker建立一个Node.js的开发环境

      建立一个文件夹 用管理员身份打开powershell. 在文件夹下面运行npm init, 根据提示填入信息,以便产生一个package.json文件. 在文件中加入需要的dependencies ...

  8. clearfix 兼容IE6/IE7,解决ie6/ie7下多出一行的问题,bootstrap的clearfix的bug

    .clearfix:before, .clearfix:after { content: "."; display: block; height: ; overflow: hidd ...

  9. 从 bootup.js 学习加载脚本等资源

    本文内容 如何使用 示例 参考资料 本文的目的在于,通过 bootup.js 的源代码,认识如何从客户端加载服务器的文件,特别是 JavaScript 文件,注入到页面,并存储在本地缓存,以扩展对 J ...

  10. Nginx 用log_format设置日志格式

    1.配置文件#vim /usr/local/nginx/conf/nginx.conflog_format access ‘$remote_addr – $remote_user [$time_loc ...