标签:
杂谈 |
分类: 物理引擎 |
编译及环境设置就不说了,我想用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 |

加载中…