【物理引擎系列(3)】剛體運(yùn)動(dòng)學(xué) - 轉(zhuǎn)動(dòng)

本文不會(huì)詳述剛體運(yùn)動(dòng)學(xué)的公式推導(dǎo)。主要對(duì)旋轉(zhuǎn)相關(guān)的幾個(gè)關(guān)鍵物理量,以及相互之間的聯(lián)系做一個(gè)簡(jiǎn)單的記錄。

(1)使用轉(zhuǎn)動(dòng)慣量、力矩,計(jì)算角加速度

在系列文章1中已經(jīng)簡(jiǎn)單介紹了轉(zhuǎn)動(dòng)慣量。這里貼上 games104 的圖方便對(duì)照記憶。


games104.png

unity 的 rigidbody. inertiaTensor 對(duì)應(yīng) physx actor 的 getMassSpaceInertiaTensor 返回值。 rigidbody. inertiaTensorRotation 對(duì)應(yīng) actor.getCMassLocalPose().q 。返回質(zhì)心的旋轉(zhuǎn)四元數(shù)。
參考physx api - rigidbody

對(duì)于施加力矩,unity 中有兩個(gè)函數(shù):AddTorque( Vector3 torque ),AddRelativeTorque( Vector3 torque )。前者輸入的是 world space 的力矩,后者輸入的是 local space 的力矩。

Vector3 torque_local = transform.InverseTransformDirection ( torque_world )

簡(jiǎn)單插入一下關(guān)于 InverseTransformPoint, InverseTransformVector,
InverseTransformDirection 的區(qū)別。
InverseTransformPoint 的實(shí)現(xiàn):

Vector3 pos_world;
var mat_ltw = Matrix4x4.TRS(transform.localPosition, transform.localRotation, transform.localScale);
Vector4 pos_local = mat_ltw * new Vector4(pos_world.x, pos_world.y, pos_world.z, 1)   
//注意這里一定要把 pos_world 轉(zhuǎn)成 Vector4 齊次坐標(biāo),否則就會(huì)丟失 translation

InverseTransformVector 不包含 translation,只包含 rotation, scale。
InverseTransformDirection 只包含 rotation。

那么,如何使用轉(zhuǎn)動(dòng)慣量,直接計(jì)算出角加速度,來(lái)實(shí)現(xiàn) AddTorque 同樣的效果呢。從公式我們知道,角加速度 \alpha = I^{-1} \tau。實(shí)際實(shí)現(xiàn)時(shí),需要注意 unity 的 inertiaTensor 是 local space 的,所以在套用公式前后都需要進(jìn)行坐標(biāo)系轉(zhuǎn)換。

        Vector3 I = rgd.inertiaTensor;
        Quaternion Ir = rgd.inertiaTensorRotation;
        Vector3 cent_w = rgd.worldCenterOfMass;

        Vector3 torque = Vector3.Cross(pos - cent_w, force);
        Vector3 torque_local = transform.InverseTransformDirection(torque);

        float[][] mat = new float[][] {
            new float[]{I.x, 0, 0},
            new float[]{ 0, I.y, 0},
            new float[]{0, 0, I.z}};

        Matrix Im = new Matrix(mat);  // Matrix 是通用矩陣類
        Matrix Irm = new Matrix(Ir);

        Matrix It = Irm * Im * Irm.Transpose();

        Vector3 wa_local = (It.Inverse() * torque_local).ToVec3();
        Vector3 wa = transform.TransformDirection(wa_local);

        rgd.angularVelocity = rgd.angularVelocity + wa * Time.deltaTime;
       // * deltaTime 后等價(jià)于 AddTorque 使用 ForceMode.Force
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容