Bullet有關六自由度彈性約束研究,bullet自由度

來源:互聯網
上載者:User

Bullet有關六自由度彈性約束研究,bullet自由度
Bullet有關六自由度彈性約束研究

       這段時間打算將物理引擎整合進來,於是對Bullet這款開源的物理引擎進行了一些研究。Bullet的研究也有了一段時間了,Bullet這個引擎其實很久之前就接觸了,只是一直以來,只是跑跑它的例子,也沒有研究例子以及原始碼,想要整合進入渲染引擎中也就井中月水中花了。今年3月,我曾經製作了一個整合Bullet最簡單的一個例子。即類比物體墜落的,並且寫了部落格《QtQuick + OpenGL + Bullet初次測試》。這個例子開了一個好頭。這段時間開始研究Bullet的一些其它有趣兒的特性了。

       Bullet的約束(也稱關節),是一個非常有意思的部分,因為它表示了兩個碰撞物體之間的物理關係。比如說如果兩個珠子是由一根繩子串起來的,那麼繩子就代表了兩個珠子之間的約束,當然你可以將繩子換成一根橡皮筋或者一根彈簧,它們都代表了不同的約束。這些約束,都有它們的名稱,我最近在研究的就是六自由度彈性約束。

       研究一個引擎最好的方法就是研究它的例子。對於Bullet也是如此。在Bullet內建的ConstraintDemo中,我看到了由一些非常有意思的約束組織而成的情境。因此從這個地方入手還不錯。例子的如下:

       你可以使用滑鼠右鍵發射方塊,來測試一下約束對於這些物體有什麼作用。

       這個情境包含了多種約束,每一種約束的處理方法都包含了相應的力學公式以及它的加成。我這回只對六自由度彈性約束進行研究,因此將其單獨拉了出來。

       六自由度彈性約束是一種約束,顧名思義,它可以作六個維度旋轉,並且在平移方面可以保持一定的彈性。中的右上方中黃色和藍色方塊形成的就是一個六自由度彈性約束。這個情境將Bullet的約束都顯示出來了,讓大家都可以瞭解,約束究竟能夠怎樣地影響物體。

       六自由度彈性約束它具有一下的屬性,它們分別如下:

英文名

中文名

RigidBodyA

此約束作用的剛體A

RigidBodyB

此約束作用的剛體B

frameInA

從剛體A到此約束的變換

frameInB

從剛體B到此約束的變換

LinearUpperLimit

平移(線性)最高的限制

LinearLowerLimit

平移(線性)最低的限制

AngularUpperLimit

旋轉(角)最高的限制

AngularLowerLimit

旋轉(角)最低的限制

Spring

彈簧效果

Stiffness

彈簧的剛性(勁度)

Damping

彈簧的衰減

       我們將預設的例子效果修改一下,設計成我們想要的帶有彈簧的效果:

        frameInA.setOrigin(btVector3(btScalar(10), btScalar(0), btScalar(0.)));        frameInB.setOrigin(btVector3(btScalar(0), btScalar(0), btScalar(0.)));        btGeneric6DofSpringConstraint* pGen6DOFSpring = new btGeneric6DofSpringConstraint(*pBodyA, *pBodyB, frameInA, frameInB, true);        pGen6DOFSpring->setLinearUpperLimit(btVector3(0, 0, 0));        pGen6DOFSpring->setLinearLowerLimit(btVector3(0, 0, 0));        pGen6DOFSpring->setAngularLowerLimit(btVector3(-0.17f, -0.17f, -0.17f) );        pGen6DOFSpring->setAngularUpperLimit(btVector3(0.17f, 0.17f, 0.17f) );        pGen6DOFSpring->enableSpring(3, true);        pGen6DOFSpring->setStiffness(3, 100.0f);        pGen6DOFSpring->setDamping(3, 0.25f);        pGen6DOFSpring->enableSpring(4, true);        pGen6DOFSpring->setStiffness(4, 100.0f);        pGen6DOFSpring->setDamping(4, 0.25f);        pGen6DOFSpring->enableSpring(5, true);        pGen6DOFSpring->setStiffness(5, 100.0f);        pGen6DOFSpring->setDamping(5, 0.25f);        pBodyA->addConstraintRef( pGen6DOFSpring );        pBodyB->addConstraintRef( pGen6DOFSpring );

       將這些代碼替換掉ConstraintDemo.cpp的559到576行,然後重新查看效果。發現約束改變了,如:

       黃色的方塊變成一個在六個自由度中都只有-10°到10°的約束。嘗試用方塊碰撞它,發現會繞著約束進行旋轉。

       接下來就是模仿的過程了,話說我要親自嘗試一下在Qt Quick + OpenGL下跑Bullet中約束的例子,因此在前期做了很多的工作,初始化相關的類就花費了很多的精力,由於代碼篇幅較長,這裡只貼出重要的部分:


    void initialize( void )    {        qDebug( "--- initialize compoundCube physics ---" );        btTransform centerOfMassTransform( btTransform::getIdentity( ) );        centerOfMassTransform.setOrigin( btVector3( 0.2, 0.0, 0.2 ) );        btTransform tr;        tr.setIdentity();        tr.setOrigin(btVector3(btScalar(-20.), btScalar(16.), btScalar(0.)));        tr.getBasis().setEulerZYX(0,0,0);        btRigidBody* pBodyA = createRigidBody( Cube, btVector3( 1.0, 1.0, 1.0 ), 0.0, tr );        pBodyA->setActivationState(DISABLE_DEACTIVATION);        tr.setIdentity();        tr.setOrigin(btVector3(btScalar(-10.), btScalar(16.), btScalar(0.)));        tr.getBasis().setEulerZYX(0,0,0);        btRigidBody* pBodyB = createRigidBody( Cube, btVector3( 1.0, 1.0, 1.0 ), 1.0, tr, centerOfMassTransform );        pBodyB->setActivationState(DISABLE_DEACTIVATION);        btTransform frameInA, frameInB;        frameInA = btTransform::getIdentity();        frameInB = btTransform::getIdentity();        frameInA.setOrigin(btVector3(btScalar(10), btScalar(0), btScalar(0.)));        frameInB.setOrigin(btVector3(btScalar(0), btScalar(0), btScalar(0.)));        btGeneric6DofSpringConstraint* pGen6DOFSpring =                new btGeneric6DofSpringConstraint(                    *pBodyA, *pBodyB, frameInA, frameInB, false );        pGen6DOFSpring->setLinearUpperLimit(btVector3(0, 0, 0));        pGen6DOFSpring->setLinearLowerLimit(btVector3(0, 0, 0));        pGen6DOFSpring->setAngularLowerLimit(btVector3(-0.17f, -0.17f, -0.17f) );        pGen6DOFSpring->setAngularUpperLimit(btVector3(0.17f, 0.17f, 0.17f) );        pGen6DOFSpring->enableSpring(3, true);        pGen6DOFSpring->setStiffness(3, 100.0f);        pGen6DOFSpring->setDamping(3, 0.25f);        pGen6DOFSpring->enableSpring(4, true);        pGen6DOFSpring->setStiffness(4, 100.0f);        pGen6DOFSpring->setDamping(4, 0.25f);        pGen6DOFSpring->enableSpring(5, true);        pGen6DOFSpring->setStiffness(5, 100.0f);        pGen6DOFSpring->setDamping(5, 0.25f);        pBodyA->addConstraintRef( pGen6DOFSpring );        pBodyB->addConstraintRef( pGen6DOFSpring );        // End 我們新添加的        m_scene->physics( )->world( ).addConstraint(pGen6DOFSpring, true);        pGen6DOFSpring->setDbgDrawSize(btScalar(5.f));        m_constraint = pGen6DOFSpring;        // 新添加一個自由落體的        btTransform newTrans;        newTrans.setIdentity( );        newTrans.setOrigin( btVector3( -12.0, 60, 0.9 ) );//        btQuaternion q;//        q.setEuler( 0.7, 0.6, 0.7 );//        newTrans.setRotation( q );        btRigidBody* newBody = createRigidBody( Cube, btVector3( 2.0, 6.0, 3.0 ),                                                300.0, newTrans );        newBody->setActivationState( DISABLE_DEACTIVATION );    }    void simulate( void )    {        //m_constraint->setEquilibriumPoint( );        //qDebug( "--- simulate compoundCube physics ---" );    }    btRigidBody* createRigidBody(            ShapeType shapeType,            const btVector3& half,            btScalar mass,            const btTransform& startTransform,            const btTransform& centerOfMassTransform = btTransform::getIdentity( ) )    {        btCollisionShape* shape = Q_NULLPTR;        // 建立形狀        switch ( shapeType )        {        case Sphere:// 球狀            shape = new btSphereShape( half.x( ) );            break;        case Cube:// 立方體            shape = new btBoxShape( half );            break;        case Capsule:// 膠囊            shape = new btCapsuleShape( half.x( ), half.y( ) );            break;        default:            qDebug( "This piece is code will never be reached unless bug." );            break;        }        btMotionState* motionState = new btDefaultMotionState( startTransform,                                                               centerOfMassTransform );        btVector3 inertia( 0, 0, 0 );        shape->calculateLocalInertia( mass, inertia );        btRigidBody* body = new btRigidBody( mass,                                             motionState,                                             shape,                                             inertia );        m_scene->physics( )->world( ).addRigidBody( body );        return body;    }

       這裡建立的是一個簡單的情境:只有一個六自由度彈性約束,兩個剛體,還有一個品質非常大的物體,通過點擊按鈕來啟用物理引擎,這樣物體會通過做自由落體運動來將重力勢能轉化為動能,衝擊這個剛體。由於設定了旋轉彈性因子,因此處於約束另一方的剛體很自然地通過旋轉避開了品質大的物體,最終該物體被彈出……



       翻開源碼,究竟彈性是怎麼實現的呢?原來這用到了一個經典的公式:胡克定律。胡克定律的公式是F= k·x,其中k是物體的勁度係數,這裡對應的也就是stiffness。看來要瞭解Bullet這個庫的原理,還要我們複習很多物理知識呢。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.