5

我正在编写一个使用 Bullet Physics 作为物理模拟引擎的角色动画渲染引擎。

一个序列将在屏幕上没有模型开始,然后将动画分配给该模型,模型将移动到动画的第 0 帧,引擎将开始使用动画渲染模型。

在第 0 帧初始化时,在角色模型上重新定位刚体的正确方法是什么?

目前我正在使用此代码,在将动画分配给模型并将骨骼移动到第 0 帧位置后立即调用该代码:

_world->removeRigidBody(_body);
bool k = (_type == Kinematics);
_body->setCollisionFlags(_body->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE);
btTransform tr = BulletPhysics::ConvertD3DXMatrix(&(_bone->getCombinedTrans()));
tr *= _trans;
_body->setCenterOfMassTransform(tr);
_body->clearForces();
_body->setLinearVelocity(btVector3(0,0,0));
_body->setAngularVelocity(btVector3(0,0,0));
_world->addRigidBody(_body, _groupID, _groupMask);

问题是有时这有效,有时则无效。以模特的裙子为例。有时它会出现在自然位置,有时会稍微错位并落入到位,有时它会完全穿过身体,好像碰撞已关闭,并且有一些力将它推向那个方向。这在大多数情况下确实有意义,因为在测试动画中,我使用模型的初始位置在屏幕中央,但动画从屏幕左侧开始。有谁知道如何解决这个问题?

我知道裙子上的骨骼不是问题,因为我关闭了物理并强制它在每一帧手动更新骨骼位置,并且在整个动画中一切都在正确的位置。

编辑:我也有限制,这可能是造成这种情况的原因吗?

4

3 回答 3

4

这是我的重新定位方法,正是这样做的。

void LimbBt::reposition(btVector3 position,btVector3 orientation) {
    btTransform initialTransform;

    initialTransform.setOrigin(position);
    initialTransform.setRotation(orientation);

    mBody->setWorldTransform(initialTransform);
    mMotionState->setWorldTransform(initialTransform);
}

运动状态 mMotionState 是您在开始时为 btRigidBody 创建的运动状态。只需将您的 clearForces() 和速度添加到它,以阻止身体从新位置继续移动,就好像它穿过一个门户一样。那应该这样做。它在这里很适合我。

编辑:如果您正确地重新定位所有刚体,约束将适应。为此,很容易计算相对位置并据此重新定位整个受约束的刚体结构。如果你做错了,你会得到严重的抽搐,因为约束会尝试以数字方式调整你的构造,如果约束间隙很大,则会产生很大的力。

编辑2:另一个问题是,如果您需要确定性行为(每次重置身体时,它们应该完全相同),那么您将不得不杀死旧的动态世界,重新创建它并再次添加所有身体。世界存储了一些暂时无法清除的有关尸体的信息。这可能会在未来发生变化,因为 bullet4 将支持确定性重置。但就目前而言,如果您使用确定性重置进行实验,您需要放弃世界并重新创建它。

资料来源:与 Bullet Physics 的开发者 Erwin Coumans 的讨论

于 2015-08-24T10:49:05.817 回答
0

我无法告诉您移动刚体时导致异常结果的原因,但我绝对可以同情!

为了解决这个问题,您需要做三件事:

  1. 将刚体转换为运动学刚体
  2. 调整身体运动状态而不是刚体的世界变换
  3. 将运动学体转换回刚体
于 2013-08-22T02:41:09.467 回答
0

一个经过测试的简短代码片段通过将刚体的运动状态更新到其新的位置和方向,并消除作用在其上的所有速度和力,有效地传送刚体。

    void teleport(btVector3 position, btQuaternion& orientation) const {

        btTransform transform;
        transform.setIdentity();

        transform.setOrigin(position);
        transform.setRotation(orientation); 

        m_rigidBodyVehicle->setWorldTransform(transform);
        m_rigidBodyVehicle->getMotionState()->setWorldTransform(transform);

        m_rigidBodyVehicle->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
        m_rigidBodyVehicle->setAngularVelocity(btVector3(0.0f, 0.0f, 0.0f));
        m_rigidBodyVehicle->clearForces();
}
于 2019-01-28T04:57:31.720 回答