标签:
杂谈 |
分类: 物理引擎 |
编译及环境设置就不说了,我想用bullet的人,肯定都有c++基础以及Vsiualstudio开发的经历。
这篇文章主要在bullet中实现一下helloworld程序,bullet官网上也有该教程。
首先在vs2008中建一个win32控制台程序,并增加头文件<btBulletDynamicsCommon.h>及bullet中相应库文件
1 | #include "stdafx.h" |
2 | #include <iostream> |
3 | #include <btBulletDynamicsCommon.h> |
4 | |
5 | #pragma comment (lib,"BulletCollision.lib") //碰撞检测库文件 |
6 | #pragma comment (lib,"BulletDynamics.lib") //动力学库文件 |
7 | #pragma comment (lib,"LinearMath.lib") //线性代数库文件 |
8 | |
9 | int _tmain(int argc, _TCHAR* argv[]) |
10 | { |
11 | std::cout << "Hello World!" << std::endl; |
12 | return 0; |
13 | } |
14 |
下面先了解一下bullet中刚体物理模拟的Pipeline(管线)
http://s15/middle/61feffe1499b9a1d1214e&690
可以看到,管线一开始会先对物理模拟世界中的物体施加重力,结束时会计算物体的最终位置,并实位移操作。
所有的这些管线操作,在bullet中都抽象的称为动力学世界(dynamics world),当我们执行dynamicsWorld->stepSimulation函数时,管线的每个阶段都会执行。缺省的动力学世界是btDiscreteDynamicsWorld,在helloworld程序中,我们也会使用该对象类创建动力学世界。
现在开始helloworld的代码:
首先需要指定broadphase阶段的算法。假设动力学世界中有n个物体,极端情况下,每两个物体之间都有相互作用关系,问题的复杂度是N^2,broadphase阶段的的作用就是尽量剔除没有相互作用的物体对(pairs)。代码如下:
btBroadphaseInterface* broadphase = new btDbvtBroadphase(); |
接下来创建碰撞配置对象和调度器对象,通过配置对象(CollisionConfiguration),我们可以在管线各个阶段尝试不同的算法组合。
btDefaultCollisionConfig |
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); |
|
下面创建解算器(solver),解算器就是求解约束方程,得到物体在一些外力约束情况下(比如重力)最终的位置,速度等。
btSequentialImpulseConst |
下面实例化一个动态世界对象(dynamics objects),需要用前面创建的几个参数作为输入参数,同时设置动力学世界的重力为y轴向下方向:
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); |
dynamicsWorld->setGravity(btVector3(0,-10,0)) |
接下来的代码就是在动力学世界中创建物体,我们创建一个平面和一个球体。
//第一个参数是平面的法向,第二个参数是在法线方向的偏移
btCollisionShape* groundShape = newtaticPlaneShape(btVector3(0,1,0),1); |
//1为球体的半径
btCollisionShape* fallShape = new btSphereShape(1); |
下面代码把球体和平面加到dynamicsWorld中,这要用到btDefaultMotionState对象,该对象包括一个表示旋转的四元数以及一个位移向量。
btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0))); |
|
btRigidBody::btRigidBodyConstructionI |
|
groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));//地面是静态的,所以惯性为0向量,静态物体质量也为0,第一个参数为物体质量,最后一个参数为物体惯性 |
|
btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);//绑定操作 |
|
dynamicsWorld->addRigidBody(groundRigidBody); |
|
btDefaultMotionState* fallMotionState = |
|
new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0))); |
|
btScalar mass = 1; //质量 |
|
btVector3 fallInertia(0,0,0);//惯性 |
|
fallShape->calculateLocalInertia(mass,fallInertia); //通过质量,这个函数计算出运动物体的惯性 |
|
btRigidBody::btRigidBodyConstructionI |
|
btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI); |
|
dynamicsWorld->addRigidBody(fallRigidBody); |
|
|
接下来启动物体模拟操作,并打印出球体在各个时刻位置,可以从dos窗口看到物体从高度50米的地方不断下落,最后停留在(0,1,0)的位置。
while(1) { |
dynamicsWorld->stepSimulation(1/60.f,10); |
btTransform trans; |
fallRigidBody->getMotionState()->getWorldTransform(trans); |
std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl; |
} |
在程序的尾部不要忘记删除创建的对象:
dynamicsWorld->removeRigidBody(fallRigidBody); |
delete fallRigidBody->getMotionState(); |
delete fallRigidBody; |
dynamicsWorld->removeRigidBody(groundRigidBody); |
delete groundRigidBody->getMotionState(); |
delete groundRigidBody; |
delete fallShape; |
delete groundShape; |
delete dynamicsWorld; |
delete solver; |
delete collisionConfiguration; |
delete dispatcher; |
delete broadphase; |
最终的代码:
1 | #include "stdafx.h" |
2 | #include <iostream> |
3 | #include <btBulletDynamicsCommon.h> |
4 | |
5 | #pragma comment (lib,"BulletCollision.lib") //碰撞检测库文件 |
6 | #pragma comment (lib,"BulletDynamics.lib") //动力学库文件 |
7 | #pragma comment (lib,"LinearMath.lib") //线性代数库文件 |
8 | |
9 | int _tmain(int argc, _TCHAR* argv[]) |
10 | { |
11 | //创建broadphase阶段算法 |
12 | btBroadphaseInterface* broadphase = new btDbvtBroadphase(); |
13 | |
14 | //创建碰撞碰撞配置对象以及碰撞调度器对象 |
15 |
btDefaultCollisionConfig |
16 | btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); |
17 | |
18 | //创建解算器 |
19 |
btSequentialImpulseConst |
20 | |
21 | btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); |
22 | |
23 | dynamicsWorld->setGravity(btVector3(0,-10,0)); |
24 | |
25 | |
26 | //第一个参数是平面的法向,第二个参数是在法线方向的偏移 |
27 | btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1); |
28 | |
29 | //1为球体的半径 |
30 | btCollisionShape* fallShape = new btSphereShape(1); |
31 | |
32 | |
33 | btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0))); |
34 |
btRigidBody::btRigidBodyConstructionI |
35 | groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0)); |
36 | btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);//绑定操作 |
37 | dynamicsWorld->addRigidBody(groundRigidBody); |
38 | |
39 | |
40 | btDefaultMotionState* fallMotionState = |
41 | new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0))); |
42 | btScalar mass = 1; //质量 |
43 | btVector3 fallInertia(0,0,0);//惯性 |
44 | fallShape->calculateLocalInertia(mass,fallInertia); |
45 |
btRigidBody::btRigidBodyConstructionI |
46 | btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI); |
47 | dynamicsWorld->addRigidBody(fallRigidBody); |
48 | |
49 | |
50 | //启动物理模拟 |
51 | while(1) { |
52 | dynamicsWorld->stepSimulation(1/60.f,10); |
53 | |
54 | btTransform trans; |
55 | fallRigidBody->getMotionState()->getWorldTransform(trans); |
56 | |
57 | std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl; |
58 | } |
59 | |
60 | //删除创建的对象 |
61 | dynamicsWorld->removeRigidBody(fallRigidBody); |
62 | delete fallRigidBody->getMotionState(); |
63 | delete fallRigidBody; |
64 | |
65 | dynamicsWorld->removeRigidBody(groundRigidBody); |
66 | delete groundRigidBody->getMotionState(); |
67 | delete groundRigidBody; |
68 | |
69 | |
70 | delete fallShape; |
71 | |
72 | delete groundShape; |
73 | |
74 | |
75 | delete dynamicsWorld; |
76 | delete solver; |
77 | delete collisionConfiguration; |
78 | delete dispatcher; |
79 | delete broadphase; |
80 | return 0; |
81 | } |
82 |