Bullet(Cocos2dx)之封装PhysicsWorld3D
Bullet3之封装PhysicsWorld3D根据bullet3HelloWorld程序去封装一个PhysicsWorld3D, 首先应该去创建一个物理世界,而对于一个物理世界,默认都有重力,提供一个创建 世界的静态方法(重力默认为(0,-10,0)) static PhysicsWorld3D* create(const btVector3& gravity = btVector3(0,0)); 负责创建世界,同时对世界初始化 这里创建一个btDiscreteDynamicsWorld 直接复制bullet3HelloWorld对世界的初始化,并修改 _collisionConfiguration,_dispatcher,_solver,_overlappingPairCache,_drawer均为成员变量, 具体使用参照Bullet的文档 PhysicsWorld3D* PhysicsWorld3D::create(const btVector3& gravity) { auto world = new PhysicsWorld3D; if (world && world->initWorld(gravity)) { return world; } delete world; return nullptr; } bool PhysicsWorld3D::initWorld(const btVector3& gravity) { _collisionConfiguration = new btDefaultCollisionConfiguration(); _dispatcher = new btCollisionDispatcher(_collisionConfiguration); _overlappingPairCache = new btDbvtBroadphase(); _solver = new btSequentialImpulseConstraintSolver; _world = new btDiscreteDynamicsWorld(_dispatcher,_collisionConfiguration); if (_world == nullptr) { return false; } _world->setGravity(gravity); return true; } 销毁一个物理世界 void PhysicsWorld3D::destroy() { this->clear(); delete _collisionConfiguration; delete _dispatcher; delete _solver; delete _overlappingPairCache; delete _world; delete this; } void PhysicsWorld3D::clear() { int i; //remove the rigidbodies from the dynamics world and delete them for (i = _world->getNumCollisionObjects() - 1; i >= 0; i--) { btCollisionObject* obj = _world->getCollisionObjectArray()[i]; btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getMotionState()) { delete body->getMotionState(); delete body->getCollisionShape(); } _world->removeCollisionObject(body); delete obj; } } 创建一些简单的body 由于每种body都有自己的材质信息 btRigidBodyConstructionInfo是构造一个刚体信息的结构体, 我们只需关心几个参数, friction; //摩擦系数 rollingFriction;//滚动摩擦系数 restitution;//恢复系数(弹性系数) mass;//质量 自己去实现一个简单的材质结构体 struct PhysicsMaterial3D { btScalar friction; btScalar rollingFriction; btScalar restitution; btScalar mass; PhysicsMaterial3D() : friction(0.0f),rollingFriction(0.f),restitution(0.f),mass(0.f) {} PhysicsMaterial3D(btScalar aMass,btScalar aFriction,btScalar aRestitution,btScalar aRollingFriction) : friction(aFriction),rollingFriction(aRollingFriction),restitution(aRestitution),mass(aMass) {} }; 并提供一个默认的材质信息 const PhysicsMaterial3D PHYSICS_MATERIAL3D_DEFAULT(1.f,0.5f,0.0f); 实现构造3个基本物体,如下声明 btRigidBody* addPlane(const btVector3& normal,const btVector3& position,const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_DEFAULT); btRigidBody* addSphere(btScalar radius,const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_DEFAULT); btRigidBody* addBox(const btVector3& halfSize,const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_DEFAULT); 对于一个无限的平面,需要一个法向量决定Plane的朝向,同时position决定plane的位置,当然还有材质,但是mass必须为0 对于一个球体(Sphere)半径,位置,材质 对于一个盒子(Box)尺寸,位置,材质 btRigidBody* PhysicsWorld3D::addPlane(const btVector3& normal,const PhysicsMaterial3D& material) { CCAssert(material.mass == 0.f,"plane's mass must be 0."); // 特殊处理,保证mass为0 btCollisionShape* groundShape = new btStaticPlaneShape(normal,0.f); auto body = getBody(groundShape,position,material); _world->addRigidBody(body); return body; } btRigidBody* PhysicsWorld3D::addSphere(btScalar radius,const PhysicsMaterial3D& material) { btCollisionShape* colShape = new btSphereShape(radius); auto body = getBody(colShape,material); _world->addRigidBody(body); return body; } btRigidBody* PhysicsWorld3D::addBox(const btVector3& size,const PhysicsMaterial3D& material) { btCollisionShape* colShape = new btBoxShape(size * 0.5f); // halfSize auto body = getBody(colShape,material); _world->addRigidBody(body); return body; } 构造一个刚体包含一些共同的步骤collisionShape,material 由于Plane,Sphere,BoxcollisionShape类型不同,所以单独实现, 其他的公共步骤可以抽离出来 btRigidBody* getBody(btCollisionShape* colShape,const PhysicsMaterial3D& material); 仿照HelloWorld构造body的方法 btRigidBody* PhysicsWorld3D::getBody(btCollisionShape* colShape,const PhysicsMaterial3D& material) { /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); //rigidbody is dynamic if and only if mass is non zero,otherwise static bool isDynamic = (material.mass != 0.f); btVector3 localInertia(0,0); if (isDynamic) colShape->calculateLocalInertia(material.mass,localInertia); // 计算物体惯性 startTransform.setOrigin(position); // 设置物体位置 //using motionstate is recommended,it provides interpolation capabilities,and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(material.mass,myMotionState,colShape,localInertia); // 使用自定义的材质 rbInfo.m_restitution = material.restitution; rbInfo.m_friction = material.friction; rbInfo.m_rollingFriction = material.rollingFriction; // 创建body btRigidBody* body = new btRigidBody(rbInfo); return body; } 不要忘了物理世界的更新 void PhysicsWorld3D::update(float dt) { _world->stepSimulation(dt); } 完整源码 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |