物理引擎如何计算刚体运动?为什么不同的引擎给我不同的结果

时间:2017-11-10 03:22:32

标签: game-physics physics-engine bulletphysics

我想参考世界框架来模拟由扭矩T = {1,1,1}施加的物体。物体的质量为1Kg,其惯性张量的对角元素为{2,1,1}。但是bullet2.7和bullet2.8给了我完全不同的结果

#include <btBulletDynamicsCommon.h>  
#include <stdio.h>
#include <iostream>
#include <fstream> 
using namespace std;

/// This is a Hello World program for running a basic Bullet physics simulation

int main(int argc, char** argv)
{

btBroadphaseInterface* broadphase = new btDbvtBroadphase();

///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();

///use the default collision dispatcher. For parallel processing you can use a differnt dispatcher
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

///the default constraint solver. For parallel processing you can use a different solver
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

///instantiate the dynamics world
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);

///sets the gravity
dynamicsWorld->setGravity(btVector3(0, 0, 0));


btCollisionShape* Shape = new btSphereShape(1);


//The btTransform class supports rigid transforms with only translation and rotation 
btDefaultMotionState* MotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 50, 0)));

btScalar mass = 1;
btVector3 Inertia(2, 1, 1);
btVector3 torque(1, 1, 1);
btVector3 angularVelocity(0, 0, 0);

///when bodies are constructed, they are passed certain parameters. This is done through a special structure Bullet provides for this.
///rigid body is dynamic if and only if mass is non zero, otherwise static  
btRigidBody::btRigidBodyConstructionInfo RigidBodyCI(mass, MotionState, Shape, Inertia);
btRigidBody* RigidBody = new btRigidBody(RigidBodyCI);
dynamicsWorld->addRigidBody(RigidBody);

ofstream outfile("data.csv", ios::out);
for (int i = 0; i < 300; i++) {

    RigidBody->applyTorque(torque);

    dynamicsWorld->stepSimulation(1 / 60.f, 10);

    angularVelocity = RigidBody->getAngularVelocity();

    outfile << angularVelocity.getX() << "," << angularVelocity.getY() << "," << angularVelocity.getZ() << endl;
}

outfile.close();

delete Shape;


delete dynamicsWorld;
delete solver;
delete dispatcher;
delete collisionConfiguration;
delete broadphase;

printf("Press a key to exit\n");
getchar();
}

子弹2.78: result of bullet 2.78

子弹2.83: result of bullet 2.83

1 个答案:

答案 0 :(得分:0)

物理引擎当然会给出不同的结果 他们计算它们的方式是不同的。这就是你注意到的。

物理引擎,它们是互动的,或者是实时的&#34; (如Box2D和Bullet),通常并不意味着给出100%准确的结果。他们意味着提供足够好的结果&#34;。这通常意味着足以在视频游戏环境中提供物理感。这是因为他们可以使用快捷方式来更快地计算结果。

来自Box2D FAQ:

  

Box2D使用近似方法有几个原因。

     
      
  • 性能
  •   
  • 一些微分方程没有已知的解决方案
  •   
  • 无法确定某些约束
  •   

这些近似值和在现实主义方面的权衡取舍,不同的引擎制造,可能和确实在引擎之间有所不同。如果引擎使用迭代求解器,那么任何差异都可以放大差异。发动机也会对诸如碰撞余量之类的事情做出不同的选择,使发动机的苹果对比比较困难。

由于这些近似,即使物理引擎如何计算因重力等力而计算速度也会有所不同。为了深入了解Box2D和轨迹的牛顿物理学之间的差异,请看看iforce2d在Projected trajectories tutorial中解释了什么。

有些事情可以做,可以提高这类引擎的准确性。然而,这些都是以牺牲性能为代价的。比如使用更小的时间步长,更高的迭代次数或更高精度的数字类型(例如从使用float切换到使用double)。

我发现的资源比较ODE 0.11,PhysX和Newton 3.11可能会让您更深入了解:A comparison between 3 physics engines。然而,我并没有讨论差异的原因,但我已经解释了这些差异。在How can I increase the physical realism of my simulation?

还有关于增加“物理学”中现实主义的讨论

希望这有帮助!