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

@ -767,7 +767,17 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
{
if (!ci.m_mass)
{
shapeInfo->SetMesh(meshobj, false);
// 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);
}
bm = shapeInfo->CreateBulletShape();
//no moving concave meshes, so don't bother calculating inertia
//bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);

@ -902,9 +902,25 @@ void DefaultMotionState::calculateWorldTransformations()
}
// 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)
{
// assume no shape information
// no support for dynamic change of shape yet
assert(m_meshObject == NULL);
m_shapeType = PHY_SHAPE_NONE;
m_vertexArray.clear();
m_polygonIndexArray.clear();
@ -1006,6 +1022,11 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope)
return false;
}
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;
}
@ -1066,16 +1087,18 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
break;
case PHY_SHAPE_COMPOUND:
if (m_nextShape)
if (m_shapeArray.size() > 0)
{
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)
{
collisionShape->setLocalScaling(nextShapeInfo->m_childScale);
compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape);
collisionShape->setLocalScaling((*sit)->m_childScale);
compoundShape->addChildShape((*sit)->m_childTrans, collisionShape);
}
}
collisionShape = compoundShape;
@ -1086,28 +1109,31 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo)
{
CcdShapeConstructionInfo* nextShape = this;
while (nextShape->m_nextShape != NULL)
nextShape = nextShape->m_nextShape;
nextShape->m_nextShape = shapeInfo;
m_shapeArray.push_back(shapeInfo);
}
CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
{
CcdShapeConstructionInfo* childShape = m_nextShape;
while (childShape)
for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin();
sit != m_shapeArray.end();
sit++)
{
CcdShapeConstructionInfo* nextShape = childShape->m_nextShape;
childShape->m_nextShape = NULL;
childShape->Release();
childShape = nextShape;
(*sit)->Release();
}
m_shapeArray.clear();
if (m_unscaledShape)
{
DeleteBulletShape(m_unscaledShape);
}
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
#include <vector>
#include <map>
#include "PHY_IPhysicsController.h"
@ -42,15 +43,17 @@ class btCollisionShape;
class CcdShapeConstructionInfo
{
public:
static CcdShapeConstructionInfo* FindMesh(RAS_MeshObject* mesh, bool polytope);
CcdShapeConstructionInfo() :
m_shapeType(PHY_SHAPE_NONE),
m_radius(1.0),
m_height(1.0),
m_halfExtend(0.f,0.f,0.f),
m_childScale(1.0f,1.0f,1.0f),
m_nextShape(NULL),
m_unscaledShape(NULL),
m_refCount(1)
m_refCount(1),
m_meshObject(NULL),
m_unscaledShape(NULL)
{
m_childTrans.setIdentity();
}
@ -77,22 +80,19 @@ public:
{
return m_unscaledShape;
}
CcdShapeConstructionInfo* GetNextShape()
{
return m_nextShape;
}
CcdShapeConstructionInfo* GetChildShape(int i)
{
CcdShapeConstructionInfo* shape = m_nextShape;
while (i > 0 && shape != NULL)
{
shape = shape->m_nextShape;
i--;
}
return shape;
if (i < 0 || i >= m_shapeArray.size())
return NULL;
return m_shapeArray.at(i);
}
bool SetMesh(RAS_MeshObject* mesh, bool polytope);
RAS_MeshObject* GetMesh(void)
{
return m_meshObject;
}
btCollisionShape* CreateBulletShape();
@ -109,14 +109,15 @@ public:
std::vector<int> m_polygonIndexArray; // Contains the array of polygon index in the
// original mesh that correspond to shape triangles.
// only set for concave mesh shape.
const RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh
protected:
CcdShapeConstructionInfo* m_nextShape; // for compound shape
btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
// the actual shape is of type btScaledBvhTriangleMeshShape
static std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> m_meshShapeMap;
int m_refCount; // this class is shared between replicas
// 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

@ -865,7 +865,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
if (shape == rayCallback.m_hitTriangleShape &&
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);
// Bullet returns the normal from "outside".