Bullet Physics - 在身体的局部空间中应用扭矩脉冲
Posted
技术标签:
【中文标题】Bullet Physics - 在身体的局部空间中应用扭矩脉冲【英文标题】:Bullet Physics - Apply Torque Impulse in Body's Local Space 【发布时间】:2010-12-13 05:16:49 【问题描述】:我目前正在为使用 C++ 和 Ogre3D 编写的 3D 太空游戏评估 Bullet Physics Library。通过从 btMotionState 派生并插入我的 SceneNodes,我已经很好地集成了 Ogre3D 和 Bullet,但是现在我在计算应该传递给 btRigidBody::applyCentralImpulse 和 btRigidBody::applyTorqueImpulse 方法以实现的值时遇到了很多麻烦我正在寻找的结果。
当我按下键盘上的 LEFT 或 RIGHT 键时,我希望飞船在本地 Z 轴上滚动。当我按下 UP 或 DOWN 时,我希望它在本地 X 轴上倾斜。当我按下 A 或 Z 时,我希望它在局部 Z 轴的方向上加速/减速。我可以使用一些四元数数学在 Ogre 中完美地实现这一点,并直接在 SceneNode 上应用平移/旋转,但我真的想使用力/扭矩方法在子弹引擎中应用这些值,以便它继续移动/俯仰/滚动即使在用户停止按键之后,摩擦力也会作用在对象上,使其在必要时减慢速度。
那么,我如何计算提供给这两种脉冲方法的必要值,以确保脉冲根据身体当前的方向而不是使用世界坐标轴起作用?
谢谢, 马克
更新:
我能够计算出向前和向后运动所需的脉冲,但我仍在努力调整偏航/俯仰/滚动值的方向,以便将它们与扭矩脉冲法一起使用。以下是我进行向前/向后移动的方式:
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);
【问题讨论】:
您能否将四元数传递给脉冲 API 或以某种方式将四元数转换为您可以传递的东西? 从我在 API 中可以看到,似乎线性脉冲方法只接受世界坐标方向的 x,y,z 向量,而角度脉冲方法只接受 y,p ,r 世界坐标中偏航、俯仰和滚动的向量。虽然数学可能有点超出我的想象(我很难想象像点积和叉积之类的东西),但实际的 Bullet API 本身就超出了我的想象,对我来说是全新的……这两者的结合使我此刻的生活是不可能的。 【参考方案1】:所以看看 btRigidBody.h
我注意到以下代码:
void applyTorqueImpulse(const btVector3& torque)
m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
现在据我了解,您希望您的扭矩等于某个常数乘以围绕与您的飞船相关的 x(或 z)轴的旋转矢量。
众所周知,广义旋转矩阵可以如下确定:
-
旋转以对齐轴预制件
围绕标准轴旋转
步骤 1 的逆操作
这意味着,如果您可以识别轴对齐扭矩(我不知道在我的头顶上),您可以使用您的:
mBody->getWorldTransform()*axisAlignedXTorque
根据http://www.bulletphysics.com/Bullet/BulletFull/classbtTransform.html 此处的 * 运算符被覆盖以对 Torque 向量进行世界变换。
【讨论】:
【参考方案2】:body->getInvInertiaTensorWorld().inverse()*(body->getWorldTransform().getBasis()*torque)
经过长时间的挫折,我终于得到了身体局部扭矩,使用上述作为 applyTorqueImpulse(或 applyTorque)的输入。我不假装理解它为什么在这一点上起作用,但确实如此。
来自子弹:
void applyTorqueImpulse(const btVector3& torque)
m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
也许这就是 tzenes 提到的关于产生轴对齐扭矩的内容。但我很困惑,我找不到其他人这样做的例子。肯定有人想要在身体的局部空间中施加扭矩吗?但我在网上发现的任何东西都不起作用,尽管看起来应该如此。
如果您只应用 transform*torque,它一开始会看起来像它一样有效,直到您开始远离世界的起源。因此,如果您离原点越远感觉旋转越困难,或者如果根据身体所在的位置开始反向旋转,这可能是您的问题。
编辑: 哦,我的翻译是这样的:
btVector3 m = body->getWorldTransform().getBasis()*btVector3(strafe,move,rise);
【讨论】:
以上是关于Bullet Physics - 在身体的局部空间中应用扭矩脉冲的主要内容,如果未能解决你的问题,请参考以下文章
有没有人有关于如何使用 Bullet Physics/jBullet 进行 voronoi 粉碎的示例/教程?
[原][osg][osgEarth]关于在OE中使用物理引擎的调研