From e9ca43521f99c6b9baf6d9278f85323086fcade2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Jul 2009 22:57:29 +0000 Subject: BGE Physics 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 --- .../Converter/BL_BlenderDataConversion.cpp | 5 +- source/gameengine/Converter/BL_MeshDeformer.h | 2 + source/gameengine/Ketsji/KX_ConvertPhysicsObject.h | 2 +- .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 41 ++- source/gameengine/Ketsji/KX_GameObject.cpp | 24 ++ source/gameengine/Ketsji/KX_GameObject.h | 1 + source/gameengine/Ketsji/KX_MeshProxy.cpp | 12 - source/gameengine/Ketsji/KX_MeshProxy.h | 1 - .../Physics/Bullet/CcdPhysicsController.cpp | 401 ++++++++++++++++++++- .../Physics/Bullet/CcdPhysicsController.h | 7 + source/gameengine/PyDoc/GameTypes.py | 32 +- source/gameengine/Rasterizer/RAS_Deformer.h | 7 + source/gameengine/Rasterizer/RAS_MeshObject.cpp | 7 + source/gameengine/Rasterizer/RAS_MeshObject.h | 8 + 14 files changed, 503 insertions(+), 47 deletions(-) (limited to 'source/gameengine') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 385301b1105..caa76263b25 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -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::iterator mit = meshobj->GetFirstMaterial(); diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 99ae5f9dea0..289826e45e7 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -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: diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 74042366bae..cf50e0ccd06 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -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 diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 51c41c0686d..cc8a00e8454 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -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((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 diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index b266095c715..36a9efe5b91 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -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() { diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index ff5c8a01e6e..d2450d342c1 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -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); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index ee5813ad854..c6989a81c6d 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -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(self_v); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index bfdd4be4118..cbdce3c2745 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -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); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 3c41a856660..20e830c9dc3 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -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 + +/* 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 vert_tag_array(numverts, false); + vector 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; jv1 + 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 vert_tag_array(numverts, false); + vector vert_remap_array(numverts, 0); + + for(int p=0; pGetPolygon(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; pGetPolygon(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 */ + printf("# vert count %d\n", m_vertexArray.size()); + for(int i=0; i~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) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index d73759bac76..8eb2e616ecf 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -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 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() diff --git a/source/gameengine/PyDoc/GameTypes.py b/source/gameengine/PyDoc/GameTypes.py index 35d8cd63c44..6a554a7c42e 100644 --- a/source/gameengine/PyDoc/GameTypes.py +++ b/source/gameengine/PyDoc/GameTypes.py @@ -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): """ diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index fe9b1540af8..75c0dcd1eeb 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -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; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 1dfcb0c512d..0ae6ad9d7ea 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -382,6 +382,13 @@ RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, return NULL; } +const float* RAS_MeshObject::GetVertexLocation(unsigned int orig_index) +{ + vector& sharedmap = m_sharedvertex_map[orig_index]; + vector::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::iterator it; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index e763d6e7c7f..bf9c0f7b682 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -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 > shared_null(0); + shared_null.swap( m_sharedvertex_map ); /* really free the memory */ +#endif + } /* colors */ void DebugColor(unsigned int abgr); -- cgit v1.2.3