Bullet3之封装PhysicsWorld3D

Bullet3之封装PhysicsWorld3D

根据bullet3 HelloWorld程序去封装一个PhysicsWorld3D

首先应该去创建一个物理世界,而对于一个物理世界,默认都有重力,提供一个创建

世界的静态方法(重力默认为(0, -10, 0)

  1. static PhysicsWorld3D* create(const btVector3& gravity = btVector3(0, -10, 0));  

负责创建世界,同时对世界初始化

这里创建一个btDiscreteDynamicsWorld

直接复制bullet3 HelloWorld对世界的初始化,并修改

_collisionConfiguration,_dispatcher, _solver, _overlappingPairCache, _drawer均为成员变量,

具体使用参照Bullet的文档

  1. PhysicsWorld3D* PhysicsWorld3D::create(const btVector3& gravity)  
  2. {  
  3.     auto world = new PhysicsWorld3D;  
  4.     if (world && world->initWorld(gravity))  
  5.     {  
  6.         return world;  
  7.     }  
  8.   
  9.     delete world;  
  10.     return nullptr;  
  11. }  
  12.   
  13.   
  14. bool PhysicsWorld3D::initWorld(const btVector3& gravity)  
  15. {  
  16.     _collisionConfiguration = new btDefaultCollisionConfiguration();  
  17.   
  18.     _dispatcher = new   btCollisionDispatcher(_collisionConfiguration);  
  19.   
  20.     _overlappingPairCache = new btDbvtBroadphase();  
  21.   
  22.     _solver = new btSequentialImpulseConstraintSolver;  
  23.     _world = new btDiscreteDynamicsWorld(_dispatcher, _overlappingPairCache, _solver, _collisionConfiguration);  
  24.     if (_world == nullptr)  
  25.     {  
  26.         return false;  
  27.     }  
  28.       
  29.     _world->setGravity(gravity);  
  30.   
  31.     return true;  
  32. }  

销毁一个物理世界

  1. void PhysicsWorld3D::destroy()  
  2. {  
  3.     this->clear();  
  4.     delete _collisionConfiguration;  
  5.     delete _dispatcher;  
  6.     delete _solver;  
  7.     delete _overlappingPairCache;  
  8.     delete _world;  
  9.     delete this;  
  10. }  
  11.   
  12. void PhysicsWorld3D::clear()  
  13. {  
  14.     int i;  
  15.     //remove the rigidbodies from the dynamics world and delete them  
  16.     for (i = _world->getNumCollisionObjects() - 1; i >= 0; i--)  
  17.     {  
  18.         btCollisionObject* obj = _world->getCollisionObjectArray()[i];  
  19.         btRigidBody* body = btRigidBody::upcast(obj);  
  20.       
  21.         if (body && body->getMotionState())  
  22.         {  
  23.             delete body->getMotionState();  
  24.             delete body->getCollisionShape();  
  25.         }  
  26.         _world->removeCollisionObject(body);  
  27.         delete obj;  
  28.     }  
  29.   
  30. }  

创建一些简单的body

由于每种body都有自己的材质信息

btRigidBodyConstructionInfo是构造一个刚体信息的结构体,

 

我们只需关心几个参数,

friction; // 摩擦系数

rollingFriction; // 滚动摩擦系数

restitution; // 恢复系数(弹性系数)

mass;   // 质量

自己去实现一个简单的材质结构体

  1. struct PhysicsMaterial3D  
  2. {  
  3.     btScalar friction;  
  4.     btScalar rollingFriction;  
  5.     btScalar restitution;  
  6.     btScalar mass;  
  7.           
  8.     PhysicsMaterial3D() :  
  9.         friction(0.0f),  
  10.         rollingFriction(0.f),  
  11.         restitution(0.f),  
  12.         mass(0.f)  
  13.     {}  
  14.   
  15.     PhysicsMaterial3D(btScalar aMass, btScalar aFriction, btScalar aRestitution, btScalar aRollingFriction) :  
  16.         friction(aFriction),  
  17.         rollingFriction(aRollingFriction),  
  18.         restitution(aRestitution),  
  19.         mass(aMass)  
  20.     {}  
  21. };  

并提供一个默认的材质信息

  1. const PhysicsMaterial3D PHYSICS_MATERIAL3D_DEFAULT(1.f, 0.5f, 0.5f, 0.0f);   

实现构造3个基本物体,如下声明

  1. btRigidBody* addPlane(const btVector3& normal, const btVector3& position, const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_DEFAULT);  
  2. btRigidBody* addSphere(btScalar radius, const btVector3& position, const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_DEFAULT);  
  3. btRigidBody* addBox(const btVector3& halfSize, const btVector3& position, const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_DEFAULT);  

对于一个无限的平面,需要一个法向量决定Plane的朝向,同时position决定plane的位置,当然还有材质,但是mass必须为0

对于一个球体(Sphere)半径,位置,材质

对于一个盒子(Box)尺寸, 位置,材质

  1. btRigidBody* PhysicsWorld3D::addPlane(const btVector3& normal, const btVector3& position, const PhysicsMaterial3D& material)  
  2. {  
  3. CCAssert(material.mass == 0.f, "plane's mass must be 0."); // 特殊处理,保证mass为0  
  4.     btCollisionShape* groundShape = new btStaticPlaneShape(normal, 0.f);  
  5.     auto body = getBody(groundShape, position, material);  
  6.   
  7.     _world->addRigidBody(body);  
  8.     return body;  
  9. }  
  10.   
  11. btRigidBody* PhysicsWorld3D::addSphere(btScalar radius, const btVector3& position, const PhysicsMaterial3D& material)  
  12. {  
  13.     btCollisionShape* colShape = new btSphereShape(radius);  
  14.     auto body = getBody(colShape, position, material);  
  15.   
  16.     _world->addRigidBody(body);  
  17.   
  18.     return body;  
  19. }  
  20.   
  21. btRigidBody* PhysicsWorld3D::addBox(const btVector3& size, const btVector3& position, const PhysicsMaterial3D& material)  
  22. {  
  23.     btCollisionShape* colShape = new btBoxShape(size * 0.5f); // halfSize  
  24.     auto body = getBody(colShape, position, material);  
  25.   
  26.     _world->addRigidBody(body);  
  27.   
  28.     return body;  
  29. }  

构造一个刚体包含一些共同的步骤collisionShape, position, material

由于Plane,Sphere,Box collisionShape类型不同,所以单独实现,

其他的公共步骤可以抽离出来

  1. btRigidBody* getBody(btCollisionShape* colShape, const btVector3& position, const PhysicsMaterial3D& material);  

仿照HelloWorld构造body的方法

  1. btRigidBody* PhysicsWorld3D::getBody(btCollisionShape* colShape, const btVector3& position, const PhysicsMaterial3D& material)  
  2. {  
  3.     /// Create Dynamic Objects  
  4.     btTransform startTransform;  
  5.     startTransform.setIdentity();  
  6.   
  7.     //rigidbody is dynamic if and only if mass is non zero, otherwise static  
  8.     bool isDynamic = (material.mass != 0.f);  
  9.   
  10.     btVector3 localInertia(0,0,0);  
  11.     if (isDynamic)  
  12.         colShape->calculateLocalInertia(material.mass, localInertia); // 计算物体惯性  
  13.   
  14.     startTransform.setOrigin(position); // 设置物体位置  
  15.   
  16.     //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects  
  17.     btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);  
  18.     btRigidBody::btRigidBodyConstructionInfo rbInfo(material.mass, myMotionState,colShape,localInertia);  
  19. // 使用自定义的材质  
  20.     rbInfo.m_restitution = material.restitution;  
  21.     rbInfo.m_friction = material.friction;  
  22.     rbInfo.m_rollingFriction = material.rollingFriction;  
  23. // 创建body  
  24.     btRigidBody* body = new btRigidBody(rbInfo);  
  25.   
  26.     return body;  
  27. }  

不要忘了物理世界的更新

  1. void PhysicsWorld3D::update(float dt)  
  2. {  
  3.     _world->stepSimulation(dt);  
  4. }  

完整源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值