Qt Quick + OpenGL + Bullet初次測試
Qt Quick + OpenGL + Bullet初次測試
眼下Qt的Quick模塊已經表現得很出色,並且可以預留接口來渲染OpenGL場景。一般來說,已經可以滿足大部分編程須要了。這次呢。嘗試使用結合一些技術,來做一些有趣兒的事情——將Bullet整合進來,並且進行測試。
蔣彩陽原創文章。首發地址:http://blog.csdn.net/gamesdev/article/details/44284317。歡迎同行前來探討。
有關Bullet的選擇,事實上也是有一番講究的。眼下Bullet的2.82版本號,臨時沒有更新了,而Bullet 3.x。則是還少有應用。假設我們去看Bullet的新的代碼庫——github。就會發現,在“Requirementsfor Bullet 2”,作者表示差點兒不論什麽編譯器都可以編譯它的代碼,而在“Requirements for Bullet 3”的介紹中,僅僅是說能在高端的顯卡中執行,低端顯卡或者是移動設備可能和Bullet 3無緣了。
所以在這樣的情況下,我就選擇Bullet 2.82來制作這個樣例。
為了完畢這個樣例,我參考了前輩們的一些樣例,比方說Qt在諾基亞時期,就寫了一個非常棒的Bullet + Qt的樣例。叫做BulletDice。
它的github地址在這裏。這邊兒比較簡單,easy上手。再加上Bullet有一份Manual,兩者結合起來看。方便了很多。
花了一周的時間。最終模仿而且制作出來了這種效果:
一開始立方體在平面的上面位置,隨後依據重力,呈自由落體速度,慢慢地往下落。
終於落在了地面上。下圖表示落下來時候的樣子:
怎麽樣?非常easy吧。
這裏也是我對Bullet的初步認識。在編寫這個樣例的過程中,遇到了非常多困難,也有非常多地方值得推敲。
所以我在這裏先作一個筆記。給以後作參考。
首先為了驗證物理引擎可用,我在類中寫了一個函數叫debugShow()。每次仿真採樣的時候。輸出立方體的位置。在驗證這樣是沒有問題的基礎上。開始研究如何讓數據與渲染相結合。以下的代碼片描寫敘述了與Bullet相關的一些知識:
void DynamicsWorldPrivate::initializePhysics( void ) { // 初始化物理引擎 m_broadPhase = new btDbvtBroadphase; m_conf = new btDefaultCollisionConfiguration; m_dispatcher = new btCollisionDispatcher( m_conf ); m_solver = new btSequentialImpulseConstraintSolver; // 應用重力 m_world = new btDiscreteDynamicsWorld( m_dispatcher, m_broadPhase, m_solver, m_conf ); m_world->setGravity( btVector3( 0, -9.81, 0 ) ); // 創建一個平面剛體 createPlane( ); // 創建一個立方體剛體 createCube( ); } void DynamicsWorldPrivate::releasePhysics( void ) { delete m_world; m_world = Q_NULLPTR; delete m_solver; m_solver = Q_NULLPTR; delete m_conf; m_conf = Q_NULLPTR; delete m_dispatcher; m_dispatcher = Q_NULLPTR; delete m_broadPhase; m_broadPhase = Q_NULLPTR; qDeleteAll( m_shapes ); qDeleteAll( m_bodies ); m_shapes.clear( ); m_bodies.clear( ); } void DynamicsWorldPrivate::createPlane( void ) { btStaticPlaneShape* planeShape = new btStaticPlaneShape( btVector3( 0, 1, 0 ), // 平面法線 0.0 ); // 平面的相對原點的距離 btTransform originTransform; originTransform.setFromOpenGLMatrix( m_planeModelMatrix->data( ) ); btDefaultMotionState* motionState = new btDefaultMotionState( originTransform, // 開始的變換 btTransform::getIdentity( ) ); // 中心平移量 btRigidBody::btRigidBodyConstructionInfo planeInfo( 0, // 質量 motionState, // 運動狀態 planeShape, // 碰撞的形狀 btVector3( 0, 0, 0 ) ); // 本地的慣性 m_planeBody = new btRigidBody( planeInfo ); m_world->addRigidBody( m_planeBody ); m_shapes.append( planeShape ); m_bodies.append( m_planeBody ); } void DynamicsWorldPrivate::createCube( void ) { qreal semi = m_cubeLength / 2.0; btBoxShape* cubeShape = new btBoxShape( btVector3( semi, semi, semi ) );// 半個立方體的大小 btTransform originTransform; originTransform.setFromOpenGLMatrix( m_cubeModelMatrix->data( ) ); btDefaultMotionState* motionState = new btDefaultMotionState( originTransform, // 開始的變換 btTransform::getIdentity( ) ); // 中心平移量 btRigidBody::btRigidBodyConstructionInfo cubeInfo( 0.8f, // 質量 motionState, // 運動狀態 cubeShape, // 碰撞的形狀 btVector3( 0, 0, 0 ) ); // 本地的慣性 cubeInfo.m_friction = 0.3; // 摩擦力 cubeInfo.m_restitution = 0.1; // 反彈力(恢復力) m_cubeBody = new btRigidBody( cubeInfo ); m_world->addRigidBody( m_cubeBody ); m_shapes.append( cubeShape ); m_bodies.append( m_cubeBody ); } void DynamicsWorldPrivate::simulate( void ) { QTime curTime = QTime::currentTime( ); int stepTime = m_lastTime.msecsTo( curTime ); m_lastTime = curTime; m_world->stepSimulation( btScalar( stepTime ) * 0.001 ); } void DynamicsWorldPrivate::debugShow( void ) { btTransform worldTransform; m_cubeBody->getMotionState( )->getWorldTransform( worldTransform ); btVector3 position = worldTransform * btVector3( 0, 0, 0 ); qDebug( "position is: ( %.2f, %.2f, %.2f )", position.x( ), position.y( ), position.z( ) ); }
隨後,可能要考慮,在這個模型中,僅僅有一個施力物體。也就是“地球”,它對立方體施以重力。讓立方體做自由落體運動,運動過程中採樣的軌跡通過body中motionState中的worldTransform來表述。假設和渲染引擎相結合的話,我這邊的做法是物理引擎終於僅僅改動物體的modelMatrix,模型自己的形態則控制著本原位置,攝像機的參數控制著viewMatrix和projectionMatrix。
僅僅有這樣。一切看起來概念才清晰。
這裏可能有一個比較棘手的問題,有時候,須要對modelMatrix進行手動控制,來改變模型的變換信息。可是呢。modelMatrix又是受物理引擎控制的。所以對於modelMatrix受手動控制和物理引擎控制的切換,是比較難以處理的,下次我再看看隨著學習的深入,能不能厘清他們之前的關系。
最後。我也在我的Android平板電腦上測試成功。
說明Bullet是全然能夠做到結合Qt來跨平臺的。
Qt Quick + OpenGL + Bullet初次測試