BGE patch: allow Bullet mesh shape sharing for objects copied with ALT-D.

This commit is contained in:
Benoit Bolsee 2008-09-20 21:33:54 +00:00
parent 768e12a064
commit 22a50402ef
4 changed files with 73 additions and 36 deletions

@ -766,8 +766,18 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
case KX_BOUNDMESH: case KX_BOUNDMESH:
{ {
if (!ci.m_mass) if (!ci.m_mass)
{
// mesh shapes can be shared, check first if we already have a shape on that mesh
class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, false);
if (sharedShapeInfo != NULL)
{
delete shapeInfo;
shapeInfo = sharedShapeInfo;
shapeInfo->AddRef();
} else
{ {
shapeInfo->SetMesh(meshobj, false); shapeInfo->SetMesh(meshobj, false);
}
bm = shapeInfo->CreateBulletShape(); bm = shapeInfo->CreateBulletShape();
//no moving concave meshes, so don't bother calculating inertia //no moving concave meshes, so don't bother calculating inertia
//bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);

@ -902,9 +902,25 @@ void DefaultMotionState::calculateWorldTransformations()
} }
// Shape constructor // Shape constructor
std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> CcdShapeConstructionInfo::m_meshShapeMap;
CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, bool polytope)
{
if (polytope)
// not yet supported
return NULL;
std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::const_iterator mit = m_meshShapeMap.find(mesh);
if (mit != m_meshShapeMap.end())
return mit->second;
return NULL;
}
bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope)
{ {
// assume no shape information // assume no shape information
// no support for dynamic change of shape yet
assert(m_meshObject == NULL);
m_shapeType = PHY_SHAPE_NONE; m_shapeType = PHY_SHAPE_NONE;
m_vertexArray.clear(); m_vertexArray.clear();
m_polygonIndexArray.clear(); m_polygonIndexArray.clear();
@ -1006,6 +1022,11 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope)
return false; return false;
} }
m_meshObject = meshobj; m_meshObject = meshobj;
if (!polytope)
{
// triangle shape can be shared, store the mesh object in the map
m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this));
}
return true; return true;
} }
@ -1066,16 +1087,18 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
break; break;
case PHY_SHAPE_COMPOUND: case PHY_SHAPE_COMPOUND:
if (m_nextShape) if (m_shapeArray.size() > 0)
{ {
compoundShape = new btCompoundShape(); compoundShape = new btCompoundShape();
for (nextShapeInfo=m_nextShape; nextShapeInfo; nextShapeInfo = nextShapeInfo->m_nextShape) for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin();
sit != m_shapeArray.end();
sit++)
{ {
collisionShape = nextShapeInfo->CreateBulletShape(); collisionShape = (*sit)->CreateBulletShape();
if (collisionShape) if (collisionShape)
{ {
collisionShape->setLocalScaling(nextShapeInfo->m_childScale); collisionShape->setLocalScaling((*sit)->m_childScale);
compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape); compoundShape->addChildShape((*sit)->m_childTrans, collisionShape);
} }
} }
collisionShape = compoundShape; collisionShape = compoundShape;
@ -1086,28 +1109,31 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo) void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo)
{ {
CcdShapeConstructionInfo* nextShape = this; m_shapeArray.push_back(shapeInfo);
while (nextShape->m_nextShape != NULL)
nextShape = nextShape->m_nextShape;
nextShape->m_nextShape = shapeInfo;
} }
CcdShapeConstructionInfo::~CcdShapeConstructionInfo() CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
{ {
CcdShapeConstructionInfo* childShape = m_nextShape; for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin();
sit != m_shapeArray.end();
while (childShape) sit++)
{ {
CcdShapeConstructionInfo* nextShape = childShape->m_nextShape; (*sit)->Release();
childShape->m_nextShape = NULL;
childShape->Release();
childShape = nextShape;
} }
m_shapeArray.clear();
if (m_unscaledShape) if (m_unscaledShape)
{ {
DeleteBulletShape(m_unscaledShape); DeleteBulletShape(m_unscaledShape);
} }
m_vertexArray.clear(); m_vertexArray.clear();
if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL)
{
std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject);
if (mit != m_meshShapeMap.end() && mit->second == this)
{
m_meshShapeMap.erase(mit);
}
}
} }

@ -18,6 +18,7 @@ subject to the following restrictions:
#define BULLET2_PHYSICSCONTROLLER_H #define BULLET2_PHYSICSCONTROLLER_H
#include <vector> #include <vector>
#include <map>
#include "PHY_IPhysicsController.h" #include "PHY_IPhysicsController.h"
@ -42,15 +43,17 @@ class btCollisionShape;
class CcdShapeConstructionInfo class CcdShapeConstructionInfo
{ {
public: public:
static CcdShapeConstructionInfo* FindMesh(RAS_MeshObject* mesh, bool polytope);
CcdShapeConstructionInfo() : CcdShapeConstructionInfo() :
m_shapeType(PHY_SHAPE_NONE), m_shapeType(PHY_SHAPE_NONE),
m_radius(1.0), m_radius(1.0),
m_height(1.0), m_height(1.0),
m_halfExtend(0.f,0.f,0.f), m_halfExtend(0.f,0.f,0.f),
m_childScale(1.0f,1.0f,1.0f), m_childScale(1.0f,1.0f,1.0f),
m_nextShape(NULL), m_refCount(1),
m_unscaledShape(NULL), m_meshObject(NULL),
m_refCount(1) m_unscaledShape(NULL)
{ {
m_childTrans.setIdentity(); m_childTrans.setIdentity();
} }
@ -77,22 +80,19 @@ public:
{ {
return m_unscaledShape; return m_unscaledShape;
} }
CcdShapeConstructionInfo* GetNextShape()
{
return m_nextShape;
}
CcdShapeConstructionInfo* GetChildShape(int i) CcdShapeConstructionInfo* GetChildShape(int i)
{ {
CcdShapeConstructionInfo* shape = m_nextShape; if (i < 0 || i >= m_shapeArray.size())
while (i > 0 && shape != NULL) return NULL;
{
shape = shape->m_nextShape; return m_shapeArray.at(i);
i--;
}
return shape;
} }
bool SetMesh(RAS_MeshObject* mesh, bool polytope); bool SetMesh(RAS_MeshObject* mesh, bool polytope);
RAS_MeshObject* GetMesh(void)
{
return m_meshObject;
}
btCollisionShape* CreateBulletShape(); btCollisionShape* CreateBulletShape();
@ -109,14 +109,15 @@ public:
std::vector<int> m_polygonIndexArray; // Contains the array of polygon index in the std::vector<int> m_polygonIndexArray; // Contains the array of polygon index in the
// original mesh that correspond to shape triangles. // original mesh that correspond to shape triangles.
// only set for concave mesh shape. // only set for concave mesh shape.
const RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh
protected: protected:
CcdShapeConstructionInfo* m_nextShape; // for compound shape static std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> m_meshShapeMap;
btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
// the actual shape is of type btScaledBvhTriangleMeshShape
int m_refCount; // this class is shared between replicas int m_refCount; // this class is shared between replicas
// keep track of users so that we can release it // keep track of users so that we can release it
RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh
btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
// the actual shape is of type btScaledBvhTriangleMeshShape
std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes
}; };
struct CcdConstructionInfo struct CcdConstructionInfo

@ -865,7 +865,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
if (shape == rayCallback.m_hitTriangleShape && if (shape == rayCallback.m_hitTriangleShape &&
rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size()) rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size())
{ {
result.m_meshObject = shapeInfo->m_meshObject; result.m_meshObject = shapeInfo->GetMesh();
result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex); result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex);
// Bullet returns the normal from "outside". // Bullet returns the normal from "outside".