BGE Physics
authorCampbell Barton <ideasman42@gmail.com>
Sat, 25 Jul 2009 22:57:29 +0000 (22:57 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 25 Jul 2009 22:57:29 +0000 (22:57 +0000)
Add support back for reinstancePhysics mesh, a frequently requested feature in the BGE forums.
from what I can tell Sumo supported this but bullet never did.
Currently only accessible via python at the moment.

- rigid body, dynamic, static types work.
- instanced physics meshes are modified too.
- compound shapes are not supported.

Physics mesh can be re-instanced from...
* shape keys & armature deformations
* subsurf (any other modifiers too)
* RAS_TexVert's (can be modified from python)

Moved the reinstancePhysicsMesh functions from RAS_MeshObject into KX_GameObject since the physics data is stored here.

video and blend file demo.
http://www.graphicall.org/ftp/ideasman42/reinstance.ogv
http://www.graphicall.org/ftp/ideasman42/reinstance_demo.blend

14 files changed:
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_MeshDeformer.h
source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_MeshProxy.cpp
source/gameengine/Ketsji/KX_MeshProxy.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/PyDoc/GameTypes.py
source/gameengine/Rasterizer/RAS_Deformer.h
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h

index 385301b110587c06f65cdc739de1757f959a3fbc..caa76263b2501076e275fefdcea8c11d8a610313 100644 (file)
@@ -1040,7 +1040,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
                        layer.face++;
                }
        }
-       meshobj->m_sharedvertex_map.clear();
+       // keep meshobj->m_sharedvertex_map for reinstance phys mesh.
+       // 2.49a and before it did: meshobj->m_sharedvertex_map.clear();
+       // but this didnt save much ram. - Campbell
+       meshobj->EndConversion();
 
        // pre calculate texture generation
        for(list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
index 99ae5f9dea0aaba2ea89b4779edbce38d1378c33..289826e45e70796afa7377b3bdea162e6214eb2b 100644 (file)
@@ -68,6 +68,8 @@ public:
        virtual RAS_Deformer*   GetReplica(){return NULL;};
        virtual void ProcessReplica();
        struct Mesh* GetMesh() { return m_bmesh; };
+       virtual class RAS_MeshObject* GetRasMesh() { return (RAS_MeshObject*)m_pMeshObject; };
+       virtual float (* GetTransVerts(int *tot))[3]    {       *tot= m_tvtot; return m_transverts; }
        //      virtual void InitDeform(double time){};
 
 protected:
index 74042366baec9865b81fbf4c4def93d7941cbdad..cf50e0ccd06551b85b1cffb0272116973471361b 100644 (file)
@@ -194,7 +194,7 @@ void        KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        struct  KX_ObjectProperties*    objprop);
        
 void   KX_ClearBulletSharedShapes();
-//bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj);
+bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj);
 
 #endif
 #endif //KX_CONVERTPHYSICSOBJECTS
index 51c41c0686def1b86a2bab3892e1dc7de4d3d3b6..cc8a00e84545597e3d7c5386f240984cb09d498d 100644 (file)
@@ -1220,5 +1220,44 @@ void     KX_ClearBulletSharedShapes()
 {
 }
 
-#endif
+/* Refresh the physics object from either an object or a mesh.
+ * gameobj must be valid
+ * from_gameobj and from_meshobj can be NULL
+ * 
+ * when setting the mesh, the following vars get priority
+ * 1) from_meshobj - creates the phys mesh from RAS_MeshObject
+ * 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject
+ * 3) gameobj - update the phys mesh from DerivedMesh or RAS_MeshObject
+ * 
+ * Most of the logic behind this is in shapeInfo->UpdateMesh(...)
+ */
+bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj)
+{
+       KX_BulletPhysicsController      *spc= static_cast<KX_BulletPhysicsController*>((gameobj->GetPhysicsController()));
+       CcdShapeConstructionInfo        *shapeInfo;
+
+       /* if this is the child of a compound shape this can happen
+        * dont support compound shapes for now */
+       if(spc==NULL)
+               return false;
+       
+       shapeInfo = spc->GetShapeInfo();
+       
+       if(shapeInfo->m_shapeType != PHY_SHAPE_MESH || spc->GetSoftBody())
+               return false;
+       
+       spc->DeleteControllerShape();
+       
+       if(from_gameobj==NULL && from_meshobj==NULL)
+               from_gameobj= gameobj;
+       
+       /* updates the arrays used for making the new bullet mesh */
+       shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
 
+       /* create the new bullet mesh */
+       btCollisionShape* bm= shapeInfo->CreateBulletShape(spc->getConstructionInfo().m_margin);
+
+       spc->ReplaceControllerShape(bm);
+       return true;
+}
+#endif
index b266095c71588a3fddb976e8ce973f8ec6ffdefa..36a9efe5b9158b4bd0ba853ad29d416231582368 100644 (file)
@@ -66,6 +66,7 @@ typedef unsigned long uint_ptr;
 #include "KX_PythonInit.h"
 #include "KX_PyMath.h"
 #include "KX_PythonSeq.h"
+#include "KX_ConvertPhysicsObject.h"
 #include "SCA_IActuator.h"
 #include "SCA_ISensor.h"
 #include "SCA_IController.h"
@@ -1183,6 +1184,7 @@ PyMethodDef KX_GameObject::Methods[] = {
        {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
        {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
        {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
+       {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS},
        
        KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
        KX_PYMETHODTABLE(KX_GameObject, rayCast),
@@ -1280,6 +1282,28 @@ PyObject* KX_GameObject::PyEndObject()
 
 }
 
+PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
+{
+       KX_GameObject *gameobj= NULL;
+       RAS_MeshObject *mesh= NULL;
+       
+       PyObject *gameobj_py= NULL;
+       PyObject *mesh_py= NULL;
+
+       if (    !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) ||
+                       (gameobj_py && !ConvertPythonToGameObject(gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || 
+                       (mesh_py && !ConvertPythonToMesh(mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject"))
+               ) {
+               return NULL;
+       }
+       
+       /* gameobj and mesh can be NULL */
+       if(KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh))
+               Py_RETURN_TRUE;
+
+       Py_RETURN_FALSE;
+}
+
 
 PyObject* KX_GameObject::PyGetPosition()
 {
index ff5c8a01e6e0739d4c731738d66001065a37dd3d..d2450d342c1672af1968171fe45aaaebb3436cf9 100644 (file)
@@ -872,6 +872,7 @@ public:
        KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo);
        KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo);
        KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage);
+       KX_PYMETHOD_VARARGS(KX_GameObject, ReinstancePhysicsMesh);
        
        /* Dict access */
        KX_PYMETHOD_VARARGS(KX_GameObject,get);
index ee5813ad85496f42eb962f585b98419bd6921a36..c6989a81c6d7c4f41894c7bd736533f6aa7f3cdf 100644 (file)
@@ -87,7 +87,6 @@ PyMethodDef KX_MeshProxy::Methods[] = {
 {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
 {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
 {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
-KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh),
 //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
 
   {NULL,NULL} //Sentinel
@@ -262,17 +261,6 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds)
        return polyob;
 }
 
-KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
-"Reinstance the physics mesh.")
-{
-#if 0
-       //this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ?
-       if(KX_ReInstanceShapeFromMesh(m_meshobj))
-               Py_RETURN_TRUE;
-#endif
-       Py_RETURN_FALSE;
-}
-
 PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_MeshProxy* self= static_cast<KX_MeshProxy*>(self_v);
index bfdd4be41187899f6ceb234a1aca89714e6ed445..cbdce3c27458370a3686a2a6cc77631c3aefc59e 100644 (file)
@@ -69,7 +69,6 @@ public:
        KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength);
        KX_PYMETHOD(KX_MeshProxy,GetVertex);
        KX_PYMETHOD(KX_MeshProxy,GetPolygon);
-       KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh);
        
        static PyObject*        pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject * pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
index 3c41a8566607bb00c9ab53e7ac64a06f0540b147..20e830c9dc39b4c5154272a6244f8a39da056d0c 100644 (file)
@@ -22,6 +22,8 @@ subject to the following restrictions:
 #include "PHY_IMotionState.h"
 #include "CcdPhysicsEnvironment.h"
 #include "RAS_MeshObject.h"
+#include "KX_GameObject.h"
+
 #include "BulletSoftBody/btSoftBody.h"
 #include "BulletSoftBody//btSoftBodyInternals.h"
 #include "BulletSoftBody/btSoftBodyHelpers.h"
@@ -529,7 +531,7 @@ void CcdPhysicsController::CreateRigidbody()
                
 }
 
-static void DeleteBulletShape(btCollisionShape* shape)
+static void DeleteBulletShape(btCollisionShape* shape, bool free)
 {
        if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
        {
@@ -539,21 +541,13 @@ static void DeleteBulletShape(btCollisionShape* shape)
                if (meshInterface)
                        delete meshInterface;
        }
-       delete shape;
+       if(free) {
+               delete shape;
+       }
 }
 
-CcdPhysicsController::~CcdPhysicsController()
+bool CcdPhysicsController::DeleteControllerShape( )
 {
-       //will be reference counted, due to sharing
-       if (m_cci.m_physicsEnv)
-               m_cci.m_physicsEnv->removeCcdPhysicsController(this);
-
-       if (m_MotionState)
-               delete m_MotionState;
-       if (m_bulletMotionState)
-               delete m_bulletMotionState;
-       delete m_object;
-
        if (m_collisionShape)
        {
                // collision shape is always unique to the controller, can delete it here
@@ -565,11 +559,64 @@ CcdPhysicsController::~CcdPhysicsController()
                        for (int i=numChild-1 ; i >= 0; i--)
                        {
                                btCollisionShape* childShape = compoundShape->getChildShape(i);
-                               DeleteBulletShape(childShape);
+                               DeleteBulletShape(childShape, true);
                        }
                }
-               DeleteBulletShape(m_collisionShape);
+               DeleteBulletShape(m_collisionShape, true);
+
+               return true;
        }
+
+       return false;
+}
+
+bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape)
+{
+       
+       /* Note, deleting the previous collision shape must be done alredy */
+       /* if (m_collisionShape) DeleteControllerShape(); */
+
+       m_object->setCollisionShape(newShape);
+       m_collisionShape= newShape;
+       m_cci.m_collisionShape= newShape;
+       
+       
+       /* Copied from CcdPhysicsEnvironment::addCcdPhysicsController() */
+       
+       /* without this, an object can rest on the old physics mesh
+        * and not move to account for the physics mesh, even with 'nosleep' */ 
+       btSoftRigidDynamicsWorld* dw= GetPhysicsEnvironment()->getDynamicsWorld();
+       btCollisionObjectArray &obarr= dw->getCollisionObjectArray();
+       btCollisionObject *ob;
+       btBroadphaseProxy* proxy;
+
+       for(int i= 0; i < obarr.size(); i++) {
+               ob= obarr[i];
+               if (ob->getCollisionShape() == newShape); {
+                       proxy = obarr[i]->getBroadphaseHandle();
+                       
+                       if(proxy)
+                               dw->getPairCache()->cleanProxyFromPairs(proxy,dw->getDispatcher());
+               }
+       }
+       
+       return true;
+}
+
+CcdPhysicsController::~CcdPhysicsController()
+{
+       //will be reference counted, due to sharing
+       if (m_cci.m_physicsEnv)
+               m_cci.m_physicsEnv->removeCcdPhysicsController(this);
+
+       if (m_MotionState)
+               delete m_MotionState;
+       if (m_bulletMotionState)
+               delete m_bulletMotionState;
+       delete m_object;
+
+       DeleteControllerShape();
+
        if (m_shapeInfo)
        {
                m_shapeInfo->Release();
@@ -1264,7 +1311,7 @@ PHY_IPhysicsController*   CcdPhysicsController::GetReplica()
        if (m_shapeInfo)
        {
                // This situation does not normally happen
-               cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(0.01);
+               cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin);
        } 
        else if (m_collisionShape)
        {
@@ -1621,6 +1668,311 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
        return true;
 }
 
+#include <cstdio>
+
+/* Updates the arrays used by CreateBulletShape(),
+ * take care that recalcLocalAabb() runs after CreateBulletShape is called.
+ * */
+bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* meshobj)
+{
+       int numpolys;
+       int numverts;
+
+       unsigned int tot_bt_tris= 0;
+       unsigned int tot_bt_verts= 0;
+
+       int i, j;
+       int v_orig;
+
+       /* Use for looping over verts in a face as a try or 2 tris */
+       const int quad_verts[7]=        {0,1,2,          0,2,3,         -1};
+       const int tri_verts[4]= {0,1,2,         -1};
+       const int *fv_pt;
+
+       if(gameobj==NULL && meshobj==NULL)
+               return false;
+       
+       if(m_shapeType != PHY_SHAPE_MESH)
+               return false;
+
+       RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL;
+       
+       /* get the mesh from the object if not defined */
+       if(meshobj==NULL) {
+               
+               /* modifier mesh */
+               if(deformer && deformer->GetFinalMesh())
+                       meshobj= deformer->GetRasMesh();
+               
+               /* game object first mesh */
+               if(meshobj==NULL) {
+                       if(gameobj->GetMeshCount() > 0) {
+                               meshobj= gameobj->GetMesh(0);
+                       }
+               }
+       }
+       
+       if(deformer && deformer->GetFinalMesh() && deformer->GetRasMesh() == meshobj)
+       {       /*
+                * Derived Mesh Update
+                *
+                * */
+
+               DerivedMesh* dm= gameobj->GetDeformer()->GetFinalMesh();
+
+               MVert *mvert = dm->getVertArray(dm);
+               MFace *mface = dm->getFaceArray(dm);
+               numpolys = dm->getNumFaces(dm);
+               numverts = dm->getNumVerts(dm);
+               int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX);
+
+               MFace *mf;
+               MVert *mv;
+
+               int flen;
+
+               if(CustomData_has_layer(&dm->faceData, CD_MTFACE))
+               {
+                       MTFace *tface = (MTFace *)dm->getFaceDataArray(dm, CD_MTFACE);
+                       MTFace *tf;
+
+                       vector<bool> vert_tag_array(numverts, false);
+                       vector<int> vert_remap_array(numverts, 0);
+
+                       for(mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) {
+                               if(tf->mode & TF_DYNAMIC)
+                               {
+                                       if(mf->v4) {
+                                               tot_bt_tris+= 2;
+                                               flen= 4;
+                                       } else {
+                                               tot_bt_tris++;
+                                               flen= 3;
+                                       }
+
+                                       for(j=0; j<flen; j++)
+                                       {
+                                               v_orig = (*(&mf->v1 + j));
+
+                                               if(vert_tag_array[v_orig]==false)
+                                               {
+                                                       vert_tag_array[v_orig]= true;
+                                                       vert_remap_array[v_orig]= tot_bt_verts;
+                                                       tot_bt_verts++;
+                                               }
+                                       }
+                               }
+                       }
+
+                       m_vertexArray.resize(tot_bt_verts*3);
+                       btScalar *bt= &m_vertexArray[0];
+
+                       m_triFaceArray.resize(tot_bt_tris*3);
+                       int *tri_pt= &m_triFaceArray[0];
+
+                       m_polygonIndexArray.resize(tot_bt_tris);
+                       int *poly_index_pt= &m_polygonIndexArray[0];
+
+
+                       for(mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++)
+                       {
+                               if(tf->mode & TF_DYNAMIC)
+                               {
+                                       if(mf->v4) {
+                                               fv_pt= quad_verts;
+                                               *poly_index_pt++ = *poly_index_pt++ = index[i];
+                                               flen= 4;
+                                       } else {
+                                               fv_pt= tri_verts;
+                                               *poly_index_pt++ = index[i];
+                                               flen= 3;
+                                       }
+
+                                       for(; *fv_pt > -1; fv_pt++)
+                                       {
+                                               v_orig = (*(&mf->v1 + (*fv_pt)));
+
+                                               if(vert_tag_array[v_orig])
+                                               {
+                                                       mv= mvert + v_orig;
+                                                       *bt++ = mv->co[0];
+                                                       *bt++ = mv->co[1];
+                                                       *bt++ = mv->co[2];
+
+                                                       vert_tag_array[v_orig]= false;
+                                               }
+                                               *tri_pt++ = vert_remap_array[v_orig];
+                                       }
+                               }
+                       }
+               }
+               else {
+                       /* no need for a vertex mapping. simple/fast */
+
+                       tot_bt_verts= numverts;
+
+                       for(mf= mface, i=0; i < numpolys; mf++, i++) {
+                               tot_bt_tris += (mf->v4 ? 2:1);
+                       }
+
+                       m_vertexArray.resize(tot_bt_verts*3);
+                       btScalar *bt= &m_vertexArray[0];
+
+                       m_triFaceArray.resize(tot_bt_tris*3);
+                       int *tri_pt= &m_triFaceArray[0];
+
+                       m_polygonIndexArray.resize(tot_bt_tris);
+                       int *poly_index_pt= &m_polygonIndexArray[0];
+
+                       for(mv= mvert, i=0; i < numverts; mv++, i++) {
+                               *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2];
+                       }
+
+                       for(mf= mface, i=0; i < numpolys; mf++, i++) {
+                               unsigned int *fv = &mf->v1;
+
+                               if(mf->v4) {
+                                       fv_pt= quad_verts;
+                                       *poly_index_pt++ = *poly_index_pt++ = index[i];
+                               }
+                               else {
+                                       fv_pt= tri_verts;
+                                       *poly_index_pt++ = index[i];
+                               }
+
+                               for(; *fv_pt > -1; fv_pt++)
+                                       *tri_pt++ = (*(&mf->v1 + (*fv_pt)));
+                       }
+               }
+       }
+       else {  /*
+                        * RAS Mesh Update
+                        *
+                        * */
+               
+               /* Note!, gameobj can be NULL here */
+
+               /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data
+                * is too hard to get at, see below for details */
+               float (*transverts)[3]= NULL;
+               int transverts_tot= 0; /* with deformed meshes - should always be greater then the max orginal index, or we get crashes */
+
+               if(deformer) {
+                       /* map locations from the deformed array
+                        *
+                        * Could call deformer->Update(); but rely on redraw updating.
+                        * */
+                       transverts= deformer->GetTransVerts(&transverts_tot);
+               }
+
+               // Tag verts we're using
+               numpolys= meshobj->NumPolygons();
+               numverts= meshobj->m_sharedvertex_map.size();
+               const float *xyz;
+
+
+               vector<bool> vert_tag_array(numverts, false);
+               vector<int> vert_remap_array(numverts, 0);
+
+               for(int p=0; p<numpolys; p++)
+               {
+                       RAS_Polygon* poly= meshobj->GetPolygon(p);
+                       if (poly->IsCollider())
+                       {
+                               for(i=0; i < poly->VertexCount(); i++)
+                               {
+                                       v_orig= poly->GetVertex(i)->getOrigIndex();
+                                       if(vert_tag_array[v_orig]==false)
+                                       {
+                                               vert_tag_array[v_orig]= true;
+                                               vert_remap_array[v_orig]= tot_bt_verts;
+                                               tot_bt_verts++;
+                                       }
+                               }
+                               tot_bt_tris += (poly->VertexCount()==4 ? 2:1);
+                       }
+               }
+
+               m_vertexArray.resize(tot_bt_verts*3);
+               btScalar *bt= &m_vertexArray[0];
+
+               m_triFaceArray.resize(tot_bt_tris*3);
+               int *tri_pt= &m_triFaceArray[0];
+
+               /* cant be used for anything useful in this case, since we dont rely on the original mesh
+                * will just be an array like pythons range(tot_bt_tris) */
+               m_polygonIndexArray.resize(tot_bt_tris);
+
+
+               for(int p=0; p<numpolys; p++)
+               {
+                       RAS_Polygon* poly= meshobj->GetPolygon(p);
+
+                       if (poly->IsCollider())
+                       {
+                               /* quad or tri loop */
+                               fv_pt= (poly->VertexCount()==3 ? tri_verts:quad_verts);
+
+                               for(; *fv_pt > -1; fv_pt++)
+                               {
+                                       v_orig= poly->GetVertex(*fv_pt)->getOrigIndex();
+
+                                       if(vert_tag_array[v_orig])
+                                       {
+                                               if(transverts) {
+                                                       /* deformed mesh, using RAS_TexVert locations would be too troublesome
+                                                        * because they are use the gameob as a hash in the material slot */
+                                                       *bt++ = transverts[v_orig][0];
+                                                       *bt++ = transverts[v_orig][1];
+                                                       *bt++ = transverts[v_orig][2];
+                                               }
+                                               else {
+                                                       /* static mesh python may have modified */
+                                                       xyz= meshobj->GetVertexLocation( v_orig );
+                                                       *bt++ = xyz[0];
+                                                       *bt++ = xyz[1];
+                                                       *bt++ = xyz[2];
+                                               }
+
+                                               vert_tag_array[v_orig]= false;
+                                       }
+
+                                       *tri_pt++ = vert_remap_array[v_orig];
+                               }
+                       }
+
+                       m_polygonIndexArray[p]= p; /* dumb counting */
+               }
+       }
+       
+#if 0
+       /* needs #include <cstdio> */
+       printf("# vert count %d\n", m_vertexArray.size());
+       for(int i=0; i<m_vertexArray.size(); i+=3) {
+               printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i+1], m_vertexArray[i+2]);
+       }
+
+       printf("# face count %d\n", m_triFaceArray.size());
+       for(int i=0; i<m_triFaceArray.size(); i+=3) {
+               printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
+       }
+#endif
+
+       /* force recreation of the m_unscaledShape.
+        * If this has multiple users we cant delete */
+       if(m_unscaledShape) {
+               // dont free now so it can re-allocate under the same location and not break pointers.
+               // DeleteBulletShape(m_unscaledShape); 
+               m_forceReInstance= true;
+       }
+
+       m_meshObject= meshobj;
+       
+       return true;
+}
+
+
+
 bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo)
 {
        if (shapeInfo == NULL)
@@ -1696,7 +2048,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
 
                } else
                {
-                       if (!m_unscaledShape)
+                       if (!m_unscaledShape || m_forceReInstance)
                        {
                        
                                btTriangleIndexVertexArray* indexVertexArrays = 0;
@@ -1731,7 +2083,18 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
                                }
                                
                                // this shape will be shared and not deleted until shapeInfo is deleted
-                               m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true );
+                               
+                               // for UpdateMesh, reuse the last memory location so instancing wont crash.
+                               if(m_unscaledShape) {
+                                       DeleteBulletShape(m_unscaledShape, false);
+                                       m_unscaledShape->~btBvhTriangleMeshShape();
+       
+                                       m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true );
+                               } else {
+                                       m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true );
+                               }
+                               
+                               m_forceReInstance= false;
                                m_unscaledShape->recalcLocalAabb();
                        }
                        collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
@@ -1776,7 +2139,7 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
        m_shapeArray.clear();
        if (m_unscaledShape)
        {
-               DeleteBulletShape(m_unscaledShape);
+               DeleteBulletShape(m_unscaledShape, true);
        }
        m_vertexArray.clear();
        if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL) 
index d73759bac76847b57e5a6fefb621117edb088ec7..8eb2e616ecf232232671c827c87dbf03e3c320ce 100644 (file)
@@ -146,6 +146,9 @@ public:
                return m_meshObject;
        }
 
+       bool UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* mesh);
+
+
        bool SetProxy(CcdShapeConstructionInfo* shapeInfo);
        CcdShapeConstructionInfo* GetProxy(void)
        {
@@ -185,6 +188,7 @@ protected:
                                                                                        // the actual shape is of type btScaledBvhTriangleMeshShape
        std::vector<CcdShapeConstructionInfo*> m_shapeArray;    // for compound shapes
        bool    m_useGimpact; //use gimpact for concave dynamic/moving collision detection
+       bool    m_forceReInstance; //use gimpact for concave dynamic/moving collision detection
        float   m_weldingThreshold1;    //welding closeby vertices together can improve softbody stability etc.
        CcdShapeConstructionInfo* m_shapeProxy; // only used for PHY_SHAPE_PROXY, pointer to actual shape info
 };
@@ -381,6 +385,9 @@ protected:
 
                CcdPhysicsController (const CcdConstructionInfo& ci);
 
+               bool DeleteControllerShape();
+               bool ReplaceControllerShape(btCollisionShape *newShape);
+
                virtual ~CcdPhysicsController();
 
                CcdConstructionInfo& getConstructionInfo()
index 35d8cd63c4490d5e1a8884a6dc0efc42acccea67..6a554a7c42ed07d79834e9d4d24bf7cb0be0fc4d 100644 (file)
@@ -2078,6 +2078,26 @@ class KX_GameObject(SCA_IObject):
                @param to: The name of the object to send the message to (optional)
                @type to: string
                """
+       def reinstancePhysicsMesh(gameObject, meshObject):
+               """
+               Updates the physics system with the changed mesh.
+               
+               If no arguments are given the physics mesh will be re-created from the first mesh assigned to the game object.
+
+               @param gameObject: optional argument, set the physics shape from this gameObjets mesh.
+               @type gameObject: string, L{KX_GameObject} or None
+               @param meshObject: optional argument, set the physics shape from this mesh.
+               @type meshObject: string, L{KX_MeshProxy} or None
+
+               @note: if this object has instances the other instances will be updated too.
+               @note: the gameObject argument has an advantage that it can convert from a mesh with modifiers applied (such as subsurf).
+               @warning: only triangle mesh type objects are supported currently (not convex hull)
+               @warning: if the object is a part of a combound object it will fail (parent or child)
+               @warning: rebuilding the physics mesh can be slow, running many times per second will give a performance hit.
+               @rtype: boolean
+               @return: True if reinstance succeeded, False if it failed.
+               """
+               
        def get(key, default=None):
                """
                Return the value matching key, or the default value if its not found.
@@ -2387,18 +2407,6 @@ class KX_MeshProxy(SCA_IObject):
                @rtype: L{KX_PolyProxy}
                @return: a polygon object.
                """
-       def reinstancePhysicsMesh():
-               """
-               Updates the physics system with the changed mesh.
-               
-               A mesh must have only one material with collision flags, 
-               and have all collision primitives in one vertex array (ie. < 65535 verts) and
-               be either a polytope or polyheder mesh.  If you don't get a warning in the
-               console when the collision type is polytope, the mesh is suitable for reinstance.
-               @bug: This currently does not work.
-               @rtype: boolean
-               @return: True if reinstance succeeded, False if it failed.
-               """
 
 class SCA_MouseSensor(SCA_ISensor):
        """
index fe9b1540af88c4ceea0ef0d7b31c652a359c513d..75c0dcd1eeb55b864e5cdc00f9803233fb1e4865 100644 (file)
@@ -38,6 +38,7 @@
 #include "GEN_Map.h"
 
 struct DerivedMesh;
+class RAS_MeshObject;
 
 class RAS_Deformer
 {
@@ -71,6 +72,12 @@ public:
        {
                return NULL;
        }
+       virtual class RAS_MeshObject* GetRasMesh()
+       {
+               /* m_pMesh does not seem to be being used?? */
+               return NULL;
+       }
+       virtual float (* GetTransVerts(int *tot))[3]    {       *tot= 0; return NULL; }
 
 protected:
        class RAS_MeshObject    *m_pMesh;
index 1dfcb0c512df0de7363f08bbd5cc23bfdc8f2bf7..0ae6ad9d7eae292052445afd8de8ecdffa4f8e4f 100644 (file)
@@ -382,6 +382,13 @@ RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid,
        return NULL;
 }
 
+const float* RAS_MeshObject::GetVertexLocation(unsigned int orig_index)
+{
+       vector<SharedVertex>& sharedmap = m_sharedvertex_map[orig_index];
+       vector<SharedVertex>::iterator it= sharedmap.begin();
+       return it->m_darray->m_vertex[it->m_offset].getXYZ();
+}
+
 void RAS_MeshObject::AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer)
 {
        list<RAS_MeshMaterial>::iterator it;
index e763d6e7c7fe51a07b997b8ad02ebd0848e7ddbb..bf9c0f7b682d7b652153a1f61292dd58f2422e3c 100644 (file)
@@ -126,6 +126,7 @@ public:
        /* vertex and polygon acces */
        int                                     NumVertices(RAS_IPolyMaterial* mat);
        RAS_TexVert*            GetVertex(unsigned int matid, unsigned int index);
+       const float*            GetVertexLocation(unsigned int orig_index);
 
        int                                     NumPolygons();
        RAS_Polygon*            GetPolygon(int num) const;
@@ -141,6 +142,13 @@ public:
                                                        bool culled);
 
        void                            RemoveFromBuckets(void *clientobj);
+       void                            EndConversion() {
+#if 0
+               m_sharedvertex_map.clear(); // SharedVertex
+               vector<vector<SharedVertex> >   shared_null(0);
+               shared_null.swap( m_sharedvertex_map ); /* really free the memory */
+#endif
+       }
 
        /* colors */
        void                            DebugColor(unsigned int abgr);