【问题标题】:Multiple instances of btDefaultMotionState, all ignored, but onebtDefaultMotionState 的多个实例,全部被忽略,但只有一个
【发布时间】:2016-12-21 20:21:35
【问题描述】:

总结问题:

到目前为止,我的世界里有两个身体,一个是地面,另一个是一个名为“fallingStar”的坠落盒子。

1) 我不明白为什么我的子弹世界与我绘制的世界不对齐,除非我将 btVector3(2,2,2) 的偏移量设置为 (btDefault)MotionState。 代码中的任何地方都没有花哨的魔法来解释偏移量。或者至少我找不到任何原因,不是在着色器中,不是在任何地方。

2) 我希望能够使用btDefaultMotionState 的多个实例,确切地说,我想为坠落的实体使用一个实例并将其放置在地面上方的某个位置,然后为地面创建另一个实例只需与我的图形地面对齐,永远不动。

我对 2) 的体验是,无论出于何种原因,坠落实体的 btDefaultMotionState 实例总是也影响地面实例,没有任何参考。

现在是代码:

fallingBox的创建:

btCollisionShape *fallingBoxShape = new btBoxShape(btVector3(1,1,1));
btScalar fallingBoxMass = 1;
btVector3 fallingBoxInertia(0,0,0);
fallingBoxShape->calculateLocalInertia(fallingBoxMass, fallingBoxInertia);

// TODO this state somehow defines where exactly _ALL_ of the physicsWorld is...
btDefaultMotionState *fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(2,2,2)));
//btDefaultMotionState *fallMotionState = new btDefaultMotionState();
btRigidBody::btRigidBodyConstructionInfo fallingBoxBodyCI(fallingBoxMass, fallMotionState, fallingBoxShape, fallingBoxInertia);
/*btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));*/
this->fallingBoxBody = new btRigidBody(fallingBoxBodyCI);
/*fallMotionState->setWorldTransform(initialTransform);
this->fallingBoxBody->setWorldTransform(initialTransform);*/
this->physicsWorld->addBody(*fallingBoxBody);

现在对我来说有趣的部分是btVector3(2,2,2) 的必要偏移,以使其与我绘制的世界对齐,并且:

btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));
this->fallingStarBody = new btRigidBody(fallingStarBodyCI);
fallMotionState->setWorldTransform(initialTransform);

如果我重新启用这部分代码ALL,主体再次显示偏移量,但仅增加 5 个,如果出于某种原因,我可以以某种方式理解 worldTransform会影响每个实体,但大约 2,2,2 关...我根本无法掌握。

我猜这行没用:

fallMotionState->setWorldTransform(initialTransform); 因为无论它是否存在,它都不会改变任何东西。

现在是地面创建的代码:

btCompoundShape *shape = new btCompoundShape();

... just some logic, nothing to do with bullet

btTransform transform;
transform.setIdentity();

transform.setOrigin(btVector3(x + (this->x * Ground::width),
                          y + (this->y * Ground::height),
                          z + (this->z * Ground::depth)));

btBoxShape *boxShape = new btBoxShape(btVector3(1,0,1)); // flat surface, no box

shape->addChildShape(transform, boxShape);

(这部分只是为每个表面瓦片创建一个复合形状:)

btRigidBody::btRigidBodyConstructionInfo info(0, nullptr, shape);
return new btRigidBody(info); 

这里我特意将motionstate设置为nullptr,但这并没有改变任何东西。

现在我真的很好奇...我以为btDefaultMotionState的实现可能是一个单例,但看起来不是这样,所以...为什么要设置一个身体的运动状态影响整个世界?

【问题讨论】:

  • 会不会是你在创建fallingBoxBody刚体后删除了fallMotionState?这将导致刚体中的一个悬空指针可能会别名下一个相同大小的分配,可能导致您所看到的?要么,要么你有其他一些以前的悬空指针被fallMotionState
  • @Frank 好吧,这发生在构造函数中,稍后超出范围,但我没有在这里手动释放任何东西。 (是的,可能是泄漏的原因)
  • 切换一切使用智能指针,仍然没有运气

标签: c++ game-engine game-physics bulletphysics


【解决方案1】:

Bullet 是一个很好的库,但很少有人花时间编写好的文档。

要设置btRigidBody 的位置,试试这个:-

btTransform transform = body -> getCenterOfMassTransform();
transform.setOrigin(aNewPosition); //<- set orientation / position that you like
body -> setCenterOfMassTransform(transform);  

如果您的代码在设置转换部分有错误(这是我从略读您的代码中猜到的),它应该被解决。

注意这个sn-p只对动态体有效,对静态体无效。

关于 CompoundBody:-

如果是复合体,例如形状B 包含形状C
设置B 的转换将起作用(设置B 的主体),但不适用于C
(因为C只是一个shape,transformation只支持body。)

如果我想将C 的相对变换更改为B,我将创建一个全新的复合形状和一个新的刚体。不要忘记去除旧的身体和形状。

这是一个库限制。

附言

我无法回答您的一些疑问/问题,这些信息是我在子弹论坛上跟踪一段时间后收集的,并经过自己测试。

(我也在从零开始编写游戏+游戏库,使用 Bullet 和其他开源代码。)

编辑:(关于新问题)

它只是慢慢下落(连同地面本身,应该 不要移动,因为我给它的质量是 0)

我会尝试按这个顺序解决它。

想法A

  • 改为设置复合质量 = 0,因为设置子形状的质量没有任何意义。

想法 B

  • 首先检查-&gt; getCenterOfMassTransform()每个时间步,它真的下降了吗?
  • 如果它确实在下降,请尝试dynamicsWorld-&gt;setGravity(btVector3(0,0,0));
  • 如果还是不行,试试非常简单的世界(1 个简单的对象,没有复合)然后看看。

Idea C(现在我开始绝望了)

  • 确保您的摄像头位置保持不变。
  • 如果问题仍然存在,我认为您现在可以创建一个简单的测试用例并将其发布到 Bullet 论坛,而无需花费太多精力。
  • 更少的代码行数 = 更好的反馈

【讨论】:

  • 你的位置输入给我带来了新的问题,但我有东西要看。有趣的是:如果我确实在那里设置了一个硬编码的位置,我会假设身体会简单地呆在那里,对吧?嗯,它没有......它只是慢慢地掉下来(连同地面本身,它不应该移动,因为我给它的质量是 0)没有想法
  • @Sorona 我的第一个赏金,谢谢!我在答案末尾添加了一些关于新问题的想法。 :)
  • 我当然是在身体上设置质量,而不是在任何形状上。如果我不设置重力,它当然不会掉下来。它也只有在里面有另一个身体的情况下才会下落。如果它只是它停留的地面(但完全偏移)......也许它与相机有关,去检查。
  • @Sorona 我从来没有成功控制世界重力,所以我总是将世界重力设置为 0 并使用每个对象的直接脉冲(手动)。 ......“只有在有其他物体的情况下才会下落” 它表明下落的力量可能来自碰撞冲动(来自某一对物体)。我遇到了一个错误,即这种未知速度来自第一个时间步的碰撞(因此很难找到该错误)。尝试将另一个对象在 0 时间步的位置更改为非常远/添加一些碰撞回调进行检查。
  • @Sorona 另一个猜测:我希望你在添加到世界之后没有设置/修改(复合)物体的质量。
【解决方案2】:

您所描述的不是正常的子弹行为。您对库的理解是正确的。

您最有可能处理的是缓冲区溢出或悬空指针。您发布的代码没有明显的任何一个,因此它将来自您代码库中的其他地方。您也许可以使用放置良好的内存断点来跟踪它。

您“可能”正在处理标头/二进制版本不一致问题,但这不太可能,因为您可能会看到其他主要问题。

【讨论】:

    【解决方案3】:

    只是与悬挂在世界顶部的 DebugDrawer 具有完全相同的行为类型。通过将投影视图矩阵单独传递给 Bullet Physics 解决了这个问题,而没有他已经拥有并与之相乘的模型矩阵:

    glUseProgram(shaderID);
    
    m_MVP = m_camera->getProjectionViewMatrix();
    glUniformMatrix4fv(shaderIDMVP, 1, GL_FALSE, &m_MVP[0][0]);
    if (m_dynamicWorld) m_dynamicWorld->debugDrawWorld();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 2022-12-05
      • 2016-12-24
      • 2020-04-20
      • 2015-12-31
      • 1970-01-01
      相关资源
      最近更新 更多