好久沒有動Ogre相關的東西了
這次是另一個物理引擎Bullet與Ogre的結合:OgreBullet
之所以想試Bullet是因為它有SoftBody這個有趣的東西
可以模擬軟的東西,如草與繩子的擺動(線)、布(面)、皮球與輪胎(體)等
可是實際下載使用後,就像當初看到Ogre的Water範例程式碼一樣
果然沒這麼簡單,一大塊不知道寫什麼鬼的程式碼
然後OgreBullet只支援RigidBody[1],並無法直接使用SoftBody
這也是意料中事,所以只能一步一步來啦
[1]Rigid Body就是國中物理所提的剛體,不會形變的物體。
拜討論區上Building OgreBullet with OgreSDK 1.8.1 on Windows這篇文章所賜
從原始碼一步步建立相關的函式庫檔案時輕鬆不少
Ogre使用舊版的1.7.4,編譯器也是從上次就沒更新的MinGW
仍然建立的很順
不過要自己寫一個範例來跑跑時,則遇到了一點點問題
我這「肉腳」看不懂OgreBullet本身附檔範例怎麼寫
所幸官網上OgreBullet Tutorial 2寫的很簡潔明白
很快的也搞定了第一個範例「丟東西」
因為有使用過另一個OgreNewt的函式庫,兩者不免拿來比較一下
整體來說OgreBullet與之前使用的OgreNewt大體上都差不多
都有DynamicWolrd(World),RigidBody(Body),Shap(Collision), Constraint(Joint)等
以Wrapper函式庫[2]來說,OgreBullet一開始實在用不習慣,太散亂了
本身就分為Dynamic與Collision兩個部分,而OgreNewt就比較單一,只產生一個檔案。
同時OgreNewt只要include一個標頭檔則可使用全部功能,感覺方便很多
OgreBullet使用不同的功能要個別include標頭檔,就覺得比較麻煩。
不過Bullet分為兩個部分也是有好處,它可以允許Collision單獨存在
對於只想偵測碰撞有無,而不需要物理模擬時,這是個不錯的方案。
[2]Wrapper(包裝)函式庫是指提供兩個不同的函式庫的一個介面。
因為它會把另一個輔助的函式庫包起來看不到原始函數,所以叫Wrapper。
舉例來說,我想讓一個物體旋轉時,
前者可以直接由OgreNewt函式設定轉速
而後者卻要先取出bullet本體的RigidBody才能處理,
等於完全跳過Wrapper,從底層去處理
我個人認為,這麼單純的功能應該是身為「介面」就可以處理掉的,
既然要直接叫原始函式出來的話,那介面存在就不太必要了嘛
或許也因為如此,才會有另一個輕量化的工具btOgre出現
這個下次再提。
雖然OgreBullet有著不少不盡我意的地方,
上面都是些抱怨連連的描述。
但是畢竟是個連結Ogre與Bullet方便的工具
從這邊開始學Bullet就跟從ExampleApplication與ExampleFramelistener學Ogre一樣
簡單方便但有些限制
而且,除了跟OgreNewt一樣有載入Entity就可以產出ConvexHull的Shape外
它還有一個可以產出更複雜,更貼近3D模型本身的物件GImpactConcaveShape可用
跟OgreNewt的TreeCollision很類似,但OgreBullet的是可以移動的
而TreeCollision只能是靜態物件,這就差很多
只是要使用這函數沒那麼簡單,以下是範例
//這是重點,要註冊GImpactCollision讓碰撞運算有效 //不然就會看到它穿過去 btCollisionDispatcher * dispatcher = static_cast然後你就可以得到一個非常貼近模型形狀的碰撞偵測區(mWorld->getBulletCollisionWorld()->getDispatcher()); btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); //產生Ogre的Entity與SceneNode ent = mSceneMgr->createEntity("HitBody","athene.mesh"); ent->setCastShadows(true); node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); node->attachObject(ent); /* 使用OgreBullet的AnimatedMeshToShapeConverter 這個物件的作用是輸入Entity取得Mesh的詳細資料, 便於算出ConvexHull或更複雜的GImpactCollision 其實用另一個StaticMeshToShapeConverter也行,並不影響結果 */ OgreBulletCollisions::AnimatedMeshToShapeConverter *animeMesh = new OgreBulletCollisions::AnimatedMeshToShapeConverter( ent, //很單純就載入Entity,裡面會去取得所需要的Mesh資訊 node->_getFullTransform()); /*載入此Entity的Matrix4, 也就是取得大小與位置, 這邊直接用_getFullTransform()從node取得最方便*/ //使用createConcave產生我們所要的GImpactConcaveShape OgreBulletCollisions::GImpactConcaveShape *concaveMeshShape = animeMesh->createConcave(); //最後就是產生一個Rigid Body OgreBulletDynamics::RigidBody *specialBody = new OgreBulletDynamics::RigidBody( "specialBody", mWorld); //然後把這碰撞偵測的外型載入 specailBody->setShape(node,//與Ogre的node連結 concaveMeshShape, // 0.6f, // 物體的恢復係數(碰撞動能損失) 0.8f, // 物體磨擦力 1.0f, // 物體質量 position, // 物體啟始位置 node->getOrientation());// 物體的方向 /* ===完成=== */
嘖嘖,真是好用啊
不過我還是想玩SoftBody特效,希望花一週都搞定Bullet基本
下次再發表就是SoftBody的Demo影片(自己的)
沒有留言:
張貼留言