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/