preparation for bullet physics

This commit is contained in:
Erwin Coumans
2005-07-16 21:47:54 +00:00
parent 3166974a67
commit 2d73b31aff
15 changed files with 715 additions and 28 deletions

View File

@@ -63,6 +63,7 @@
// USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h
#ifdef USE_SUMO_SOLID
#include "SumoPhysicsEnvironment.h"
#include "KX_SumoPhysicsController.h"
@@ -577,6 +578,10 @@ void KX_ClearSumoSharedShapes()
map_gamemesh_to_instance.clear();
}
#endif //USE_SUMO_SOLID
@@ -651,3 +656,390 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
#endif // USE_ODE
#ifdef USE_BULLET
#include "CcdPhysicsEnvironment.h"
#include "CcdPhysicsController.h"
#include "KX_BulletPhysicsController.h"
#include "CollisionShapes/BoxShape.h"
#include "CollisionShapes/SphereShape.h"
#include "CollisionShapes/TriangleMeshInterface.h"
#include "CollisionShapes/ConeShape.h"
#include "CollisionShapes/ConvexShape.h"
#include "CollisionShapes/CylinderShape.h"
#include "CollisionShapes/MultiSphereShape.h"
#include "CollisionShapes/ConvexHullShape.h"
#include "CollisionShapes/TriangleMesh.h"
#include "CollisionShapes/TriangleMeshShape.h"
static GEN_Map<GEN_HashedPtr,CollisionShape*> map_gamemesh_to_bulletshape;
// forward declarations
static CollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
{
if (!meshobj)
return 0;
CollisionShape* collisionMeshShape = 0;
ConvexHullShape* convexHullShape = 0;
TriangleMeshShape* concaveShape = 0;
TriangleMesh* collisionMeshData = 0;
//see if there is any polygons, if not, bail out.
int numUsedPolygons = 0;
int numPoints = 0;
SimdVector3* points = 0;
CollisionShape** shapeptr = map_gamemesh_to_bulletshape[GEN_HashedPtr(meshobj)];
// Mesh has already been converted: reuse
if (shapeptr)
{
//return *shapeptr;
}
// Mesh has no polygons!
int numpolys = meshobj->NumPolygons();
if (!numpolys)
{
return NULL;
}
// Count the number of collision polygons and check they all come from the same
// vertex array
int numvalidpolys = 0;
int vtxarray = -1;
RAS_IPolyMaterial *poly_material = NULL;
bool reinstance = true;
for (int p=0; p<numpolys; p++)
{
RAS_Polygon* poly = meshobj->GetPolygon(p);
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
// check polygon is from the same vertex array
if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
{
if (vtxarray < 0)
vtxarray = poly->GetVertexIndexBase().m_vtxarray;
else
{
reinstance = false;
vtxarray = -1;
}
}
// check poly is from the same material
if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
{
if (poly_material)
{
reinstance = false;
poly_material = NULL;
}
else
poly_material = poly->GetMaterial()->GetPolyMaterial();
}
// count the number of collision polys
numvalidpolys++;
// We have one collision poly, and we can't reinstance, so we
// might as well break here.
if (!reinstance)
break;
}
}
// No collision polygons
if (numvalidpolys < 1)
return NULL;
if (polytope)
{
convexHullShape = new ConvexHullShape(points,numPoints);
collisionMeshShape = convexHullShape;
} else
{
collisionMeshData = new TriangleMesh();
concaveShape = new TriangleMeshShape(collisionMeshData);
collisionMeshShape = concaveShape;
}
numvalidpolys = 0;
for (int p2=0; p2<numpolys; p2++)
{
RAS_Polygon* poly = meshobj->GetPolygon(p2);
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
//Bullet can raycast any shape, so
if (polytope)
{
for (int i=0;i<poly->VertexCount();i++)
{
const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[i],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 point(vtx[0],vtx[1],vtx[2]);
convexHullShape->AddPoint(point);
}
if (poly->VertexCount())
numvalidpolys++;
} else
{
{
const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[2],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[1],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[0],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
collisionMeshData->AddTriangle(vertex0,vertex1,vertex2);
numvalidpolys++;
}
if (poly->VertexCount() == 4)
{
const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[3],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[2],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[0],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
SimdPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
collisionMeshData->AddTriangle(vertex0,vertex1,vertex2);
numvalidpolys++;
}
}
}
}
if (numvalidpolys > 0)
{
//map_gamemesh_to_bulletshape.insert(GEN_HashedPtr(meshobj),collisionMeshShape);
return collisionMeshShape;
}
delete collisionMeshShape;
return NULL;
}
void KX_ConvertBulletObject( class KX_GameObject* gameobj,
class RAS_MeshObject* meshobj,
class KX_Scene* kxscene,
struct PHY_ShapeProps* shapeprops,
struct PHY_MaterialProps* smmaterial,
struct KX_ObjectProperties* objprop)
{
CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
assert(env);
bool dyna = false;
CcdConstructionInfo ci;
class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
ci.m_MotionState = motionstate;
ci.m_gravity = SimdVector3(0,0,0);
ci.m_localInertiaTensor =SimdVector3(0,0,0);
ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
ci.m_localInertiaTensor = SimdVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
SimdTransform trans;
trans.setIdentity();
CollisionShape* bm = 0;
switch (objprop->m_boundclass)
{
case KX_BOUNDSPHERE:
{
float radius = objprop->m_radius;
SimdVector3 inertiaHalfExtents (
radius,
radius,
radius);
//blender doesn't support multisphere, but for testing:
//bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
bm = new SphereShape(objprop->m_radius);
bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
break;
};
case KX_BOUNDBOX:
{
MT_Vector3 halfExtents (
objprop->m_boundobject.box.m_extends[0],
objprop->m_boundobject.box.m_extends[1],
objprop->m_boundobject.box.m_extends[2]);
halfExtents /= 2.f;
SimdVector3 he (halfExtents[0]-CONVEX_DISTANCE_MARGIN ,halfExtents[1]-CONVEX_DISTANCE_MARGIN ,halfExtents[2]-CONVEX_DISTANCE_MARGIN );
he = he.absolute();
bm = new BoxShape(he);
bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
break;
};
case KX_BOUNDCYLINDER:
{
SimdVector3 halfExtents (
objprop->m_boundobject.c.m_radius,
objprop->m_boundobject.c.m_radius,
objprop->m_boundobject.c.m_height * 0.5f
);
bm = new CylinderShapeZ(halfExtents);
bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
break;
}
case KX_BOUNDCONE:
{
SimdVector3 halfExtents (objprop->m_boundobject.box.m_extends[0],
objprop->m_boundobject.box.m_extends[1],
objprop->m_boundobject.box.m_extends[2]);
halfExtents /= 2.f;
SimdVector3& he = halfExtents;
SimdTransform& tr = trans;
bm = new ConeShape(objprop->m_boundobject.c.m_radius,objprop->m_boundobject.c.m_height);
bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
break;
}
case KX_BOUNDPOLYTOPE:
{
bm = CreateBulletShapeFromMesh(meshobj,true);
if (bm)
{
bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
}
break;
}
case KX_BOUNDMESH:
{
if (!ci.m_mass)
{
bm = CreateBulletShapeFromMesh(meshobj,false);
ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
//no moving concave meshes, so don't bother calculating inertia
//bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
}
break;
}
default:
//interpret the shape as a concave triangle-mesh
{
if (meshobj)
{
// assert(0);
/*
meshobj->ScheduleCollisionPolygons();
KX_DeformableMesh* gfxmesh = new KX_DeformableMesh(meshobj);
gfxmesh->sendFixedMapping();
//trianglemesh
bm = new TriangleMeshInterface(gfxmesh,trans);
*/
}
}
}
// ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f);
if (!bm)
return;
ci.m_collisionShape = bm;
ci.m_broadphaseHandle = 0;
ci.m_friction = smmaterial->m_friction;
ci.m_restitution = smmaterial->m_restitution;
ci.m_linearDamping = shapeprops->m_lin_drag;
ci.m_angularDamping = shapeprops->m_ang_drag;
KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,dyna);
env->addCcdPhysicsController( physicscontroller);
gameobj->SetPhysicsController(physicscontroller);
physicscontroller->setNewClientInfo(gameobj);
gameobj->GetSGNode()->AddSGController(physicscontroller);
bool isActor = objprop->m_isactor;
STR_String materialname;
if (meshobj)
materialname = meshobj->GetMaterialName(0);
const char* matname = materialname.ReadPtr();
physicscontroller->SetObject(gameobj->GetSGNode());
}
void KX_ClearBulletSharedShapes()
{
int numshapes = map_gamemesh_to_bulletshape.size();
int i;
CollisionShape*shape=0;
for (i=0;i<numshapes ;i++)
{
shape = *map_gamemesh_to_bulletshape.at(i);
//delete shape;
}
map_gamemesh_to_bulletshape.clear();
}
#endif