Ogre渲染简单的几何物体的方法
转载请注明出处!http://www.cnblogs.com/pulas/
在Ogre里有两种方法来创建自定义网格。第一种是继承SimpleRenderable,并直接提供给它顶点和索引缓存。这是最直接的创建方式,但也是最不直观的。为了使事情更简单,Ogre提供了一个更棒的接口叫做ManualObject,它能让你用一些简单的函数来定义一个网格,而不用往缓存里写原始数据。仅仅调用"position"和"colour"等函数即可,而不用往缓存里丢位置、颜色等数据。
使用ManualObject或者其派生类渲染简单的几何物体的步骤如下:
1. 新建一个ManualObject对象
mManualObj = mSceneManager->createManualObject ("SimpleStuff");
2. 设置该ManualObject的参数(可以不设置以使用默认参数)
- 设置其渲染队列所在的组
mManualObj->setRenderQueueGroup(RENDER_QUEUE_OVERLAY);
- 使用单元投影矩阵和单元视图矩阵, 这两个默认为false, 即使用相机的视图矩阵和投影矩阵
mManualObj->setUseIdentityProjection(true);
mManualObj->setUseIdentityView(true);
使用这两个函数之后, 所绘制的物体坐标范围位于(-1, -1, -1)至(1, 1, 1)之间
- 设置查询参数
mManualObj->setQueryFlags(0);
3. 调用绘制函数
mManualObj->clear();
mManualObj->begin("", RenderOperation::OT_LINE_STRIP);
for (int i = 0; i < 5; i++)
{
mManualObj->position(pos[i]);
}
mManualObj->end();
4. 创建场景节点挂接该对象
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mManualObj);
注意:
- 若在绘制前能确定顶点或索引的个数,则应先调用estimateVertexCount(size_t vcount)和estimateIndexCount(size_t icount)方法。虽然这不是必需的,但是这可以避免在定义顶点时重新分配内存以提高效率。
- 对于每个顶点,可以调用position(), normal(), textureCoord(), colour()等方法定义顶点数据,注意,每次调用position()即开始了一个新的顶点,第一个顶点的数据结构决定了所有顶点的数据结构,不能再在后续顶点定义中添加新类型分量。
- 通过调用index(uint32 idx)使用索引,或者调用triangle(uint32 i1, uint32 i2, uint32 i3)对三角形使用索引,或者调用quad (uint32 i1, uint32 i2, uint32 i3, uint32 i4) 对四边形使用索引。顶点的顺序:逆时针为正面。
- 如果想使用不同的渲染操作类型或材质构造更多的几何体,可使用多个begin-end块。这个类在内部通过一个Renderable列表来组织维护数据,一个begin-end块对应一个Renderable。
- 可以使用beginUpdate()方法动态改变几何体,要想这样做,必须在第一次调用begin()前调用setDynamic(true)方法,并且考虑使用estimateVertexCount(size_t vcount)和estimateIndexCount(size_t icount )方法,使之在顶点数增长时以增量式分配内存,而不是再重新构造一个新的内存块。
Ogre场景的组成
总体上来看,场景中的Objects可分为可动实体和不可动实体。其中,Entities、Cameras和Lights属于Movable Objects,World Geometry属于Immovable Objects。Materials依附于别的Objects之上,无所谓动与不动。
OGRE把离散的,相对较小的,可移动的物体定义为Ogre::MovableObject。其派生出来的类如下图所示。
Camera属于Frustum的子类:
从另一个角度看,物体有可渲染和不可渲染之分。OGRE中能被渲染的Objects都继承于Ogre::Renderable类:
比较MovableObject和Renderable可以发现, Entity属于MovableObject但却不属于Renderable:
Renderable有一个SubEntity的子类,而Entity是由SubEntity组成的:
typedef std::vector<SubEntity*> SubEntityList;
SubEntityList mSubEntityList;
由此可以断定,Entity是被分解为SubEntity完成渲染的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构