Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-07-26 02:57:29 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-07-26 02:57:29 +0400
commite9ca43521f99c6b9baf6d9278f85323086fcade2 (patch)
tree58ab9f5afe70d77fa04f920fa2c55adb34cd2990
parent1c00eacca2b084d7189de33cb75e8612cb542030 (diff)
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
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp5
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.h2
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h2
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp41
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp24
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.h1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp401
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h7
-rw-r--r--source/gameengine/PyDoc/GameTypes.py32
-rw-r--r--source/gameengine/Rasterizer/RAS_Deformer.h7
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp7
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h8
14 files changed, 503 insertions, 47 deletions
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<RAS_MeshMaterial>::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<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
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<KX_MeshProxy*>(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 <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)
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<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()
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<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;
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<vector<SharedVertex> > shared_null(0);
+ shared_null.swap( m_sharedvertex_map ); /* really free the memory */
+#endif
+ }
/* colors */
void DebugColor(unsigned int abgr);