天天看點

Bullet(Cocos2dx)之分析剛體建立與銷毀(Primitives)

相關連結:http://bulletphysics.org/mediawiki-1.5.8/index.php/Collision_Shapes

Bullet基本圖形簡介

Bullet提供的基本圖形包括球體、長方體、圓柱體、膠囊體、圓錐體、多球體

當然還有一個Plane,一個無限的平面

1.球體是個很簡單的形狀:

btSphereShape (btScalar radius) 提供一個球體的半徑

2.長方體(盒子)

btBoxShape (const btVector3 &boxHalfExtents) 提供盒子的半尺寸(長寬高的一半)

3.圓柱體(類似box shape)

btCylinderShape (const btVector3 &halfExtents) 提供半尺寸 (半徑, 高度, 不知)

預設軸為y軸,btCylinderShapeX (x軸), btCylinderShapeZ(z軸)

4.膠囊體

btCapsuleShape (btScalar radius, btScalar height) 提供半球形半徑, 圓柱體高度, 實際高度為2*radius + height

預設軸為y軸,btCapsuleShapeX (x軸), btCapsuleShapeZ(z軸)

5.圓錐體

btConeShape (btScalar radius, btScalar height) 提供底面半徑, 高度

預設軸為y軸,btConeShapeX (x軸), btConeShapeZ(z軸)

6.多球體(多個球體組合)

btMultiSphereShape (const btVector3 *positions, const btScalar *radi, int numSpheres) 

positions每個球體的位置,radi每個球體的半徑, 球體個數

Bullet(Cocos2dx)之分析剛體建立與銷毀(Primitives)

建立剛體

1.首先擷取要建立的剛體形狀,以box為例

btCollisionShape* colShape = new btBoxShape(size * 0.5f); // halfSize

因為btBoxShape繼承自btCollisionShape

2.設定剛體的其他基本資訊

(1).剛體的變換矩陣

(2).剛體的慣性(動态物體才有)

(3).MotionState提供插值,同步活動的物體等

(4).剛體的材質資訊

(5).建立剛體

btTransform startTransform;    // 1
startTransform.setIdentity();
startTransform.setOrigin(position);
 
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (material.mass != 0.f);
 
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(material.mass, localInertia); // 2
 
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); // 3
btRigidBody::btRigidBodyConstructionInfo rbInfo(material.mass, myMotionState,colShape,localInertia); // 4
rbInfo.m_restitution = material.restitution;
rbInfo.m_friction = material.friction;
rbInfo.m_rollingFriction = material.rollingFriction;
btRigidBody* body = new btRigidBody(rbInfo); // 5
           

3.将剛體添加到world

_world->addRigidBody(body);

銷毀剛體

1.因為剛體繼承自btCollisionObject是以從world擷取_world->getCollisionObjectArray()

2.如果obj為剛體則要轉換為剛體btRigidBody* body = btRigidBody::upcast(obj);

因為剛體有可能包含MoitonState,

3.删除剛體的MotionState,和CollisionShape,(CollisionShape不就是obj嗎?檢視兩者的值是不一樣的)

4.從世界移除obj,不是應該移除剛體嗎?看源碼注釋可知

///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject 

virtual void removeCollisionObject(btCollisionObject* collisionObject);

5.釋放obj,因為是用new 生成的,new實際是Bullet的記憶體配置設定方式,重載new

6.釋放完畢

//remove the bodies 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(obj);  
delete obj;
}
           

繼續閱讀