【转】OGRE 模型绘制

OGRE简析(二)

                                                                             ------OGRE模型绘制

“伟大航路,我把世界上的一切都放在了那里,有种的话就去领取吧”

这是OGRE中文网的一则广告,我想,无论作为OGRE的学习者还是漫漫人生的一名旅人,这句话都是非常不错的激励语。放在这,是否能够让你隐约看到属于自己的新世界?

前沿

在上次完成框架解析之后,主要是参照OGRE_3D_1.7_Beginner's_Guide这本书,对OGRE的应用有了一个大简单而全面的了解,对其中场景、节点和相机等,以及模型、动画和粒子都有了一个概念的认知,这本书对于初学来说,还是值得一读的。还有就是Pro_OGRE_3D_Programming这本,网上推荐页不错,不过还没来得及看。

看完这本书,打算结合书中的应用场景来学习一下实现,毕竟会调用接口和了解内部处理机制上还是有不少差别的,而自然,第一个例子就是Sinbad水手模型了。

OGRE中显示一个模型很简单

Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.mesh");

mSceneMgr->getRootSceneNode()->attachObject(ent);

简单的两句话,一个模型就可以马上显示出来,下面进入本章的主题,模型绘制过程解析。OGRE中,这个过程主要分三个阶段

模型文件加载

纹理映射

模型渲染

备注:红色部分是可以讨论的技术,只做引用,想不全,只列出关键词

文件加载

       对于OGRE应用来说,添加一个含有模型的节点,即上面代码内容,主要就是为了在程序中加载模型,其后的显示均是在OGRE内部实现渲染,并不需要用户做其他工作。

       添加模型,就不得不提一下场景的概念:”场景组织就像一个舞台,需要摄影机、灯光、服饰、道具和演员”,对于场景中的Object,大致分为moveable和immobeable两类,而模型属于前者。在OGRE中MovableObjectCollectionMapmMovableObjectCollectionMap用来维护对象,其本身算是一个二维字典,先负责Entity、Cameras类型,然后再细化到每一类型下面的实体,以name作为索引。

对象的创建主要由MovableObject* MovableObjectFactory::createInstance(constString& name, SceneManager*manager, constNameValuePairList* params)函数来实现,工厂模式来处理

对于模型,最终由模型管理器Load实现。

一个完整的模型包括三大部分,模型文件,材质文件和纹理图片,其中,对于具有动画功能的,还包含骨骼文件,本章中不涉及骨骼文件的介绍,在动画专题中会做研究

1.      模型构建
模型管理器,通过资源管理器在内存中先构造出模型,此时模型为空壳,仅保存此模型的路径信息,只是在资源管理器中有此模型的唯一位置。其后,调用模型的load函数,实现模型文件的加载

2.      文件读取
Sinbad模型是一个zip文件,在load中,需要通过zip文件解析,获取解析后的文件流,存储在mFreshFromDisk成员中

3.      文件解析
准备好文件流后,则开始了文件解析的过程,OGRE中由MeshSerializer类型,负责模型二进制流的导入导出功能。最终形成一个完整的模型。

4.      模型的内存结构
Mesh最为一个整体,主要是由SubMesh组合而成的,每一个SubMesh包括材质、顶点数组、纹理数组、渲染类型和骨骼四项内容,依次读取Mesh文件中的信息,其中材质只是name标识,而在材质文件中根据name索引详细说明。在读取完子模型和骨骼后,下面存储的是模型的bounds和外接球半径,最后是EdgeData
如此,一个模型文件的读取告一段落。

引用计数的广泛应用

纹理映射

接下来,则进入了模型材质的准备阶段,其最关键的就是纹理的调度。

首先将每一个SubMesh(包含材质名称,并在材质对应文件中有描述)封装为SubEntity,通过材质管理器构建出材质,设置到所属的SubEntity,通过load函数来进行纹理映射的实现。

材质过程:T-》Pass-》TextureUnitStates-》TexturePtr

然后由纹理管理器创建出对应材质的纹理,如果共用则引用计数+1即可。

纹理创建Prepare(prepare::do_image_io,mLoadedImages)

纹理创建Load(GLTexture::createInternalResourcesImpl,HardwarePixelBuffer::blitFromMemory)

通过纹理管理器完成了纹理映射的构建,prepare阶段主要完成纹理图片的buffer内容,而在load中则完成了纹理的映射

 OGRE OpenGL纹理映射的关键点

glGenTextures获取纹理名字

glBindTexture设置纹理类型

glTexImage2D绑定纹理信息

glGetTexLevelParameteriv

glTexSubImage2D替换纹理信息

 MipMap方式

 纹理调度
全部加入内存,纹理管理器共用

 纹理配置文件

数据库方式

 GLHardwareVertexBuffer(vbo)

模型绘制

场景管理,(Plugin_OctreeSceneManager)各种过程后,我们从renderSingleObject开始说起,至于OGRE的场景管理,在以后讨论。

绘制过程如下:

1.     _setTexture绑定使用的纹理(在renderSingleObject函数之前准备好)

2.     getRenderOperation:顶点数组和纹理数字赋给RO

3.     lights场景光照开启

4.     render绘制

 

模型绘制关键点:

glEnable(GL_TEXTURE_2D); //开始使用纹理缓冲
glBindTexture(GL_TEXTURE_2D, texID); //选择当前使用的纹理缓冲

glBindBufferARB();    // OGRE中使用vbo方式绘图

glVertexPointer();          //设置顶点数组的指针为顶点缓存

glBindBufferARB();

glTexCoordPointer();     //设置顶点数组的指针为纹理坐标缓存

glDrawElements();     //绘制

glDisable()

 

  vbo高速绘图(截取网上,OGRE中在GLHardwareVertexBuffer类中封装初始化阶段,而在绘制的时候避免差异化方式)
初始化阶段:
1. glGenBuffersARB(1, &nVBOVertices); //生成一个句柄
2. glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVBOVertices); //声明该句柄为一个vbo句柄,并选择之
3. glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices),vertices,GL_STATIC_DRAW); //将顶点集上传至server端

使用阶段:
1. glEnableClientState(GL_VERTEX_ARRAY); //开始使用vbo
2. glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVBOVertices); //选择当前使用的vbo
3. glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));  //指定vbo顶点格式
4. glDrawArrays( GL_TRIANGLES, 0,g_pMesh->m_nVertexCount ); //画吧
5. glDisableClientState(GL_VERTEX_ARRAY); //停止使用vbo

收尾阶段:
1. glDeleteBuffersARB(1,&nVBOVertices); //删除句柄,同时删除server端顶点缓冲

对比

OGRE中充分考虑了硬件优化

内存全部加在

模型可复用性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值