Ogre中grass渲染动态草体
关键词:
StaticGeometry、静态几何体
“看起来似乎静态几何体是活动物体(Moveable Object)的反义词,但事实上也不全是:通常来说静态几何体会由很多不再活动的活动物体来构成。”(Pro OGRE 3D Programming
中文翻译版本0.2.0)
静态物体的几个缺点(Pro OGRE 3D Programming中文翻译版本0.2.0):
•巨大的静态物体需要在使用前被构建,通常这是一个缓慢的过程,所以不能在每一帧都执行。
• 静态几何体将按着放入物体的材质来进行分类,并且把材质相同的集合体放置到同一个渲染设置当中(换句话说,也就是放到同一个簇中)。但这并不表示只要把一组几何体打包成一个静态物体就能神奇的把它们捆绑到一个渲染设置中。
•在静态几何体中“静态”的含义是:一旦物体被放入静态几何体中,你就不能在单独移动它了。任何对静态几何体的世界变换都会应用到所有里面包含的物体上。
•静态几何体会比同样大小的活动物体占用更多的内存。静态几何体会为每一个实体创建一个网格模型数据的拷贝。
•就算在你的视野里(视截体)中看到了整个静态几何体的一小部分,甚至包括在你身后的整个数据都会传到图形硬件中渲染。
ogre_src_v1-7-2\Samples\Grass\include\Grass.h
这个注释很机械,够参考用了:http://xmchang.bokee.com/4277630.html
StaticGeometry的数据分析见后面的“底层数据结构分析”。
StaticGeometry对象作为动态草坪,然后在上面附加手绘的grass mesh
步骤:
1. 创建手绘mesh,命名为“grass”,并加载到Etity中。这是一个创建用户自定义mesh的方法,稍后再说。
2. 构造静态几何体,并设置它的参数。
StaticGeometry* mField = mSceneMgr->createStaticGeometry("Field");
3. 将草体Entity加到StaticGeometry静态几何体中,也就是往field中种草
mField->addEntity(grass, pos, ori, scale);
4. 执行创建。烘焙草体?
mField->build(); // build our static geometry (bake the grass into it)
5. 草体随风摇摆。帧循环中
waveGrass(evt.timeSinceLastFrame); // wave the grass around slowly to simulate wind
手动创建mesh(需补充。。。)
草体摇动的代码不是很懂。不是很熟悉静态几何体的结构。(需补充。。。)
PagedGeometry中的草体
奥米格得,那不是2句话就能说清楚的,还用了cg。静止的树如下渲染:
1. 创建PagedGeometry对象
PagedGeometry* trees = new PagedGeometry();
2. 创建TreeLoader3D对象,用于加载树,并加载到PG中。
TreeLoader3D *treeLoader = new TreeLoader3D(trees, TBounds(0, 0, 1500, 1500));
trees->setPageLoader(treeLoader); //Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance
3. 准备好地形高度表,方便种树嘛
//Setup the height function (so the Y values of trees can be calculated when they are placed on the terrain)
HeightFunction::initialize(sceneMgr);
4. 种树了。随机在一个区域种树,世界里没有一颗相同的树。
for (int i = 0; i < 20000; i++){
yaw = Degree(Math::RangeRandom(0, 360));
position.x = Math::RangeRandom(0, 1500);
position.z = Math::RangeRandom(0, 1500);
position.y = HeightFunction::getTerrainHeight(position.x, position.z);
scale = Math::RangeRandom(0.5f, 0.6f);
treeLoader->addTree(myEntity, position, yaw, scale);
}
5. 帧循环中更新LOD
//[NOTE] PagedGeometry::update() is called every frame to keep LODs, etc. up-to-date
trees->update();
类关系
class BatchedGeometry: public Ogre::MovableObject
class WindBatchedGeometry: public BatchedGeometry
总结:
很迷惑,似乎是用的MovableObject,为什么不用StaticGeometry?PG实现了一套完整的树木森林渲染方式,得单独理解。暂且放下,看看ogitor如何实现的。
Ogitor中的草体
Ogitor 0.4中也是是用的pagedgeometry 1.1.0,和上面分析时使用的一个版本。
#define PAGEDGEOMETRY_VERSION "1.1.0"
Ogitor中还用到了moc,暂记之。
CPGInstanceManager
用于管理pagedgeometry
class CBaseEditor: public Ogre::GeneralAllocatedObject
class CPGInstanceManager : public CBaseEditor, public MouseListener
class CPGInstanceEditor : public CBaseEditor
加载树的代码和上面的介绍一样,这里找
bool CPGInstanceManager::load(bool async)
update在这里
bool CPGInstanceManager::update(float timePassed)
总之还是可以借鉴的。
底层数据结构分析
---------------------------------------------------------------------------------------------------------------
内存种类
enum MemoryCategory
{
/// General purpose
MEMCATEGORY_GENERAL = 0,
/// Geometry held in main memory
MEMCATEGORY_GEOMETRY = 1,
/// Animation data like tracks, bone matrices
MEMCATEGORY_ANIMATION = 2,
/// Nodes, control data
MEMCATEGORY_SCENE_CONTROL = 3,
/// Scene object instances
MEMCATEGORY_SCENE_OBJECTS = 4,
/// Other resources
MEMCATEGORY_RESOURCE = 5,
/// Scripting
MEMCATEGORY_SCRIPTING = 6,
/// Rendersystem structures
MEMCATEGORY_RENDERSYS = 7,
// sentinel value, do not use
MEMCATEGORY_COUNT = 8
};
This allocation policy uses nedmalloc
(http://nedprod.com/programs/portable/nedmalloc/index.html).
class NedPoolingPolicy
template <MemoryCategory Cat> class CategorisedAllocPolicy : public NedPoolingPolicy{};
typedef CategorisedAllocPolicy<Ogre::MEMCATEGORY_GEOMETRY> GeometryAllocPolicy;
|
typedef AllocatedObject<GeometryAllocPolicy> GeometryAllocatedObject;
|
typedef GeometryAllocatedObject BatchedGeometryAlloc;
值得注意的是,nedprod宣称: there is no faster portable memory allocator out there!
Ned似乎是作者的名字。
Policy模式
PagedGeometry插件分析
http://sxoo0305.blog.163.com/blog/static/10132887201061154455372/