子弹物理 - 在身体的局部空间中施加扭矩冲击

时间:2009-11-04 22:17:01

标签: c++ physics ogre3d bullet

我正在评估Bullet Physics Library我正在使用C ++和Ogre3D编写的3D太空游戏。通过从btMotionState派生并插入我的SceneNodes,我已经很好地集成了Ogre3D和Bullet,但是现在我在计算我应该传递给btRigidBody :: applyCentralImpulse和btRigidBody :: applyTorqueImpulse方法的值时遇到很多麻烦才能实现我正在寻找的结果。

当我按下键盘上的左或右键时,我希望太空船在本地Z轴上滚动。当我按UP或DOWN时,我希望它在本地X轴上倾斜。当我按A或Z时,我希望它在局部Z轴的方向上加速/减速。我可以在Ogre中使用一些四元数学并直接在SceneNode上应用translate / rotation来实现这一点,但我真的想使用force / torque方法在Bullet引擎中应用这些值,这样它将继续移动/俯仰/滚动即使在用户停止按键之后,摩擦也会作用在物体上以根据需要减慢速度。

那么,我如何计算提供给这两种脉冲方法的必要值,以确保脉冲基于身体的当前方向而不是使用世界的轴来作用?

谢谢, 马克

更新

我能够计算出向前和向后运动所需的冲动,但我仍在努力解决如何重新定向偏航/俯仰/滚转值以便将它们与扭矩脉冲方法一起使用。这是我进行前进/后退运动的方式:

if (mKeyboard->isKeyDown(OIS::KC_A))
    mBody->applyCentralImpulse(mBody->getWorldTransform().getBasis().getColumn(2) * 20 * time);
if (mKeyboard->isKeyDown(OIS::KC_Z))
    mBody->applyCentralImpulse(mBody->getWorldTransform().getBasis().getColumn(2) * -20 * time);

2 个答案:

答案 0 :(得分:3)

所以看看btRigidBody.h

我注意到以下代码:

     void applyTorqueImpulse(const btVector3& torque)
     {
                     m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
     }

根据我的理解,你希望你的扭矩等于与你的宇宙飞船相关的x(或z)轴周围的旋转矢量的常数倍。

我们知道广义旋转矩阵可以确定如下:

  1. 旋转以对齐轴预制件
  2. 关于规范轴的旋转
  3. 第1步的反面
  4. 这意味着如果你能识别一个轴对齐的扭矩(我不知道我的头顶),你可以用你的方式改变它:

    mBody->getWorldTransform()*axisAlignedXTorque
    

    根据http://www.bulletphysics.com/Bullet/BulletFull/classbtTransform.html 这里的*运算符被覆盖,以便在扭矩矢量上进行世界变换。

答案 1 :(得分:1)

body->getInvInertiaTensorWorld().inverse()*(body->getWorldTransform().getBasis()*torque)

经过长时间的挫折之后,我终于使用以上作为applyTorqueImpulse(或applyTorque)的输入来获得身体局部扭矩。我并没有假装理解为什么它在这一点上起作用,但确实如此。

来自子弹:

    void applyTorqueImpulse(const btVector3& torque)
{
        m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
}

也许这就是tzenes提到的关于产生轴对齐扭矩的问题。但我感到困惑的是,我找不到任何其他人这样做的例子。当然还有其他人想要在身体的局部空间施加扭矩吗?但我在网上找不到任何东西,尽管看起来应该如此。

如果你只使用变换*扭矩,它看起来就像它起作用,直到你开始远离你的世界的起源。因此,如果感觉越难旋转,你就越远离原点,或者如果事物开始反向旋转,这取决于身体的位置,这可能是你的问题。

修改 哦,这就是我的翻译方式:

  

btVector3 m = body-> getWorldTransform()。getBasis()* btVector3(strafe,move,rise);