BGE patch: allow Bullet mesh shape sharing for objects copied with ALT-D.
authorBenoit Bolsee <benoit.bolsee@online.be>
Sat, 20 Sep 2008 21:33:54 +0000 (21:33 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Sat, 20 Sep 2008 21:33:54 +0000 (21:33 +0000)
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp

index b3f24d972818040e925d4e85e799089246bc4093..6f5f9e22506978d61eac3ca085f6882a634ca1e2 100644 (file)
@@ -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);
index b1b97b5370f3cde08d5df726717f0813d6cb4b13..1ec555f653d68747c7514c274ac216853b041bc1 100644 (file)
@@ -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);
+               }
+       }
 }
 
 
index 355c1d608b1a9faa790ac7457c843cff3f429777..af146413c918a8a98f6f6c7958261f745aec1c12 100644 (file)
@@ -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
index 96caf885e7c350dfc1500b38e4c61625ab4aa9fe..68b3df1695c13e3c530c392f37641959a01d1725 100644 (file)
@@ -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".