From d95a10999052ad308599cb0fbbe7ed4f59870c9c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 14 May 2009 13:47:08 +0000 Subject: BGE modifier: generate correct physic shape, share static derived mesh, share display list. This commit completes the support for modifiers in the BGE. - The physic shape is generated according to the derived mesh. This is true for all types of shapes and all types of objects except soft body. - Optimization for static derived mesh (mesh with modifiers but no armature and no shape keys). Replicas will share the derived mesh and the display list: less memory and faster rendering. With this optimization, the static derived mesh will render as fast as if the modifiers were applied. Known Limits: - Sharing of mesh and display list is only possible between in-game replicas or dupligroup. If you want to instantiate multiple objects with modifiers, use dupligroup to ensure best memory and GPU utilization. - rayCast() will interact with the derived mesh as follow: Hit position and hit normal are the real values according to the derived mesh but the KX_PolyProxy object refers to the original mesh. You should use it only to retrieve the material. - Dynamic derived mesh have very poor performance: They use direct openGL calls for rendering (no support for display list and vertex array) and they dont't share the derived mesh memory. Always apply modifiers on dynamic mesh for best performance. - Time dependent modifiers are not supported. - Modifiers are not supported for Bullet soft body. --- .../PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj | 12 +- .../Converter/BL_BlenderDataConversion.cpp | 102 ++++++----- source/gameengine/Converter/BL_MeshDeformer.cpp | 9 + source/gameengine/Converter/BL_MeshDeformer.h | 2 +- .../gameengine/Converter/BL_ModifierDeformer.cpp | 73 +++++--- source/gameengine/Converter/BL_ModifierDeformer.h | 5 + source/gameengine/Converter/BL_ShapeDeformer.cpp | 9 +- source/gameengine/Converter/BL_ShapeDeformer.h | 1 + source/gameengine/Converter/BL_SkinDeformer.cpp | 45 +++-- source/gameengine/Converter/BL_SkinDeformer.h | 2 + source/gameengine/Ketsji/KX_ConvertPhysicsObject.h | 2 + .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 51 +++--- source/gameengine/Physics/Bullet/CMakeLists.txt | 3 + .../Physics/Bullet/CcdPhysicsController.cpp | 200 ++++++++++++--------- .../Physics/Bullet/CcdPhysicsController.h | 5 +- source/gameengine/Physics/Bullet/Makefile | 2 + source/gameengine/Physics/Bullet/SConscript | 3 + source/gameengine/Rasterizer/RAS_Deformer.h | 10 +- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp | 46 +++-- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 6 +- 20 files changed, 359 insertions(+), 229 deletions(-) diff --git a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj index e6991592d40..9f16283e1cd 100644 --- a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj +++ b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj @@ -42,7 +42,7 @@ type) { case OB_MESH: - bb= ( (Mesh *)ob->data )->bb; - if(bb==0) + if (dm) + { + float min_r[3], max_r[3]; + INIT_MINMAX(min_r, max_r); + dm->getMinMax(dm, min_r, max_r); + size[0]= 0.5*fabs(max_r[0] - min_r[0]); + size[1]= 0.5*fabs(max_r[1] - min_r[1]); + size[2]= 0.5*fabs(max_r[2] - min_r[2]); + + center[0]= 0.5*(max_r[0] + min_r[0]); + center[1]= 0.5*(max_r[1] + min_r[1]); + center[2]= 0.5*(max_r[2] + min_r[2]); + return; + } else { - my_tex_space_mesh((struct Mesh *)ob->data); bb= ( (Mesh *)ob->data )->bb; + if(bb==0) + { + my_tex_space_mesh((struct Mesh *)ob->data); + bb= ( (Mesh *)ob->data )->bb; + } } break; case OB_CURVE: @@ -1498,7 +1514,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, } KX_BoxBounds bb; - my_get_local_bounds(blenderobject,objprop.m_boundobject.box.m_center,bb.m_extends); + DerivedMesh* dm = NULL; + if (gameobj->GetDeformer()) + dm = gameobj->GetDeformer()->GetFinalMesh(); + my_get_local_bounds(blenderobject,dm,objprop.m_boundobject.box.m_center,bb.m_extends); if (blenderobject->gameflag & OB_BOUNDS) { switch (blenderobject->boundtype) @@ -1567,7 +1586,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, { #ifdef USE_BULLET case UseBullet: - KX_ConvertBulletObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop); + KX_ConvertBulletObject(gameobj, meshobj, dm, kxscene, shapeprops, smmaterial, &objprop); break; #endif @@ -1947,8 +1966,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int activeLayerBitInfo = blenderscene->lay; - // templist to find Root Parents (object with no parents) - CListValue* templist = new CListValue(); + // list of all object converted, active and inactive CListValue* sumolist = new CListValue(); vector vec_parent_child; @@ -2048,9 +2066,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->SetName(blenderobject->id.name); - // templist to find Root Parents (object with no parents) - templist->Add(gameobj->AddRef()); - // update children/parent hierarchy if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame)) { @@ -2243,9 +2258,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->SetName(blenderobject->id.name); - // templist to find Root Parents (object with no parents) - templist->Add(gameobj->AddRef()); - // update children/parent hierarchy if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame)) { @@ -2398,8 +2410,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for ( i=0;iGetCount();i++) { KX_GameObject* obj = static_cast(childrenlist->GetValue(i)); - if (templist->RemoveValue(obj)) - obj->Release(); if (sumolist->RemoveValue(obj)) obj->Release(); if (logicbrick_conversionlist->RemoveValue(obj)) @@ -2455,16 +2465,47 @@ void BL_ConvertBlenderObjects(struct Main* maggie, vec_parent_child.clear(); // find 'root' parents (object that has not parents in SceneGraph) - for (i=0;iGetCount();++i) + for (i=0;iGetCount();++i) { - KX_GameObject* gameobj = (KX_GameObject*) templist->GetValue(i); + KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); if (gameobj->GetSGNode()->GetSGParent() == 0) { parentlist->Add(gameobj->AddRef()); gameobj->NodeUpdateGS(0); } } - + + // create graphic controller for culling + if (kxscene->GetDbvtCulling()) + { + bool occlusion = false; + for (i=0; iGetCount();i++) + { + KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); + if (gameobj->GetMeshCount() > 0) + { + MT_Point3 box[2]; + gameobj->GetSGNode()->BBox().getmm(box, MT_Transform::Identity()); + // box[0] is the min, box[1] is the max + bool isactive = objectlist->SearchValue(gameobj); + BL_CreateGraphicObjectNew(gameobj,box[0],box[1],kxscene,isactive,physics_engine); + if (gameobj->GetOccluder()) + occlusion = true; + } + } + if (occlusion) + kxscene->SetDbvtOcclusionRes(blenderscene->world->occlusionRes); + } + + // now that the scenegraph is complete, let's instantiate the deformers. + // We need that to create reusable derived mesh and physic shapes + for (i=0;iGetCount();++i) + { + KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); + if (gameobj->GetDeformer()) + gameobj->GetDeformer()->UpdateBuckets(); + } + bool processCompoundChildren = false; // create physics information @@ -2498,28 +2539,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } - // create graphic controller for culling - if (kxscene->GetDbvtCulling()) - { - bool occlusion = false; - for (i=0; iGetCount();i++) - { - KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); - if (gameobj->GetMeshCount() > 0) - { - MT_Point3 box[2]; - gameobj->GetSGNode()->BBox().getmm(box, MT_Transform::Identity()); - // box[0] is the min, box[1] is the max - bool isactive = objectlist->SearchValue(gameobj); - BL_CreateGraphicObjectNew(gameobj,box[0],box[1],kxscene,isactive,physics_engine); - if (gameobj->GetOccluder()) - occlusion = true; - } - } - if (occlusion) - kxscene->SetDbvtOcclusionRes(blenderscene->world->occlusionRes); - } - //set ini linearVel and int angularVel //rcruiz if (converter->addInitFromFrame) for (i=0;iGetCount();i++) @@ -2605,7 +2624,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } - templist->Release(); sumolist->Release(); // convert global sound stuff diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index b6a59774636..b49544050d1 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -91,6 +91,15 @@ BL_MeshDeformer::~BL_MeshDeformer() delete [] m_transnors; } +void BL_MeshDeformer::ProcessReplica() +{ + m_transverts = NULL; + m_transnors = NULL; + m_tvtot = 0; + m_bDynamic=false; + m_lastDeformUpdate = -1; +} + void BL_MeshDeformer::Relink(GEN_Map*map) { void **h_obj = (*map)[m_gameobj]; diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 11ca3b00a1d..99ae5f9dea0 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -66,7 +66,7 @@ public: virtual bool Update(void){ return false; }; virtual bool UpdateBuckets(void){ return false; }; virtual RAS_Deformer* GetReplica(){return NULL;}; - virtual void ProcessReplica() {m_bDynamic=false;}; + virtual void ProcessReplica(); struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp index 3c4c0c5caad..fe539f9a6c5 100644 --- a/source/gameengine/Converter/BL_ModifierDeformer.cpp +++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp @@ -72,8 +72,11 @@ extern "C"{ BL_ModifierDeformer::~BL_ModifierDeformer() { if (m_dm) { - m_dm->needsFree = 1; - m_dm->release(m_dm); + // deformedOnly is used as a user counter + if (--m_dm->deformedOnly == 0) { + m_dm->needsFree = 1; + m_dm->release(m_dm); + } } }; @@ -90,7 +93,10 @@ void BL_ModifierDeformer::ProcessReplica() { /* Note! - This is not inherited from PyObjectPlus */ BL_ShapeDeformer::ProcessReplica(); - m_dm = NULL; + if (m_dm) + // by default try to reuse mesh, deformedOnly is used as a user count + m_dm->deformedOnly++; + // this will force an update and if the mesh cannot be reused, a new one will be created m_lastModifierUpdate = -1; } @@ -117,29 +123,40 @@ bool BL_ModifierDeformer::Update(void) bool bShapeUpdate = BL_ShapeDeformer::Update(); if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) { - /* execute the modifiers */ - Object* blendobj = m_gameobj->GetBlendObject(); - /* hack: the modifiers require that the mesh is attached to the object - It may not be the case here because of replace mesh actuator */ - Mesh *oldmesh = (Mesh*)blendobj->data; - blendobj->data = m_bmesh; - /* execute the modifiers */ - DerivedMesh *dm = mesh_create_derived_no_virtual(blendobj, m_transverts, CD_MASK_MESH); - /* restore object data */ - blendobj->data = oldmesh; - /* free the current derived mesh and replace, (dm should never be NULL) */ - if (m_dm != NULL) { - m_dm->needsFree = 1; + // static derived mesh are not updated + if (m_dm == NULL || m_bDynamic) { + /* execute the modifiers */ + Object* blendobj = m_gameobj->GetBlendObject(); + /* hack: the modifiers require that the mesh is attached to the object + It may not be the case here because of replace mesh actuator */ + Mesh *oldmesh = (Mesh*)blendobj->data; + blendobj->data = m_bmesh; + /* execute the modifiers */ + DerivedMesh *dm = mesh_create_derived_no_virtual(blendobj, m_transverts, CD_MASK_MESH); + /* restore object data */ + blendobj->data = oldmesh; + /* free the current derived mesh and replace, (dm should never be NULL) */ + if (m_dm != NULL) { + // HACK! use deformedOnly as a user counter + if (--m_dm->deformedOnly == 0) { + m_dm->needsFree = 1; + m_dm->release(m_dm); + } + } + m_dm = dm; + // get rid of temporary data + m_dm->needsFree = 0; m_dm->release(m_dm); - } - m_dm = dm; - /* update the graphic controller */ - PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController(); - if (ctrl) { - float min_r[3], max_r[3]; - INIT_MINMAX(min_r, max_r); - m_dm->getMinMax(m_dm, min_r, max_r); - ctrl->setLocalAabb(min_r, max_r); + // HACK! use deformedOnly as a user counter + m_dm->deformedOnly = 1; + /* update the graphic controller */ + PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController(); + if (ctrl) { + float min_r[3], max_r[3]; + INIT_MINMAX(min_r, max_r); + m_dm->getMinMax(m_dm, min_r, max_r); + ctrl->setLocalAabb(min_r, max_r); + } } m_lastModifierUpdate=m_gameobj->GetLastFrame(); bShapeUpdate = true; @@ -156,10 +173,10 @@ bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat) int nmat = m_pMeshObject->NumMaterials(); for (int imat=0; imatGetMeshMaterial(imat); - RAS_MeshSlot *slot = *mmat->m_slots[(void*)m_gameobj]; - if(!slot) + RAS_MeshSlot **slot = mmat->m_slots[(void*)m_gameobj]; + if(!slot || !*slot) continue; - slot->m_pDerivedMesh = m_dm; + (*slot)->m_pDerivedMesh = m_dm; } return true; } diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h index 465c287a88b..d5a1caeb91f 100644 --- a/source/gameengine/Converter/BL_ModifierDeformer.h +++ b/source/gameengine/Converter/BL_ModifierDeformer.h @@ -86,6 +86,11 @@ public: { m_lastModifierUpdate = -1.0; }; + virtual struct DerivedMesh* GetFinalMesh() + { + return m_dm; + } + protected: double m_lastModifierUpdate; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index e04d4dad015..12ef3ff84f1 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -77,6 +77,12 @@ RAS_Deformer *BL_ShapeDeformer::GetReplica() return result; } +void BL_ShapeDeformer::ProcessReplica() +{ + BL_SkinDeformer::ProcessReplica(); + m_lastShapeUpdate = -1; +} + bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma) { IpoCurve *icu; @@ -163,7 +169,8 @@ bool BL_ShapeDeformer::Update(void) // check for armature deform bSkinUpdate = BL_SkinDeformer::Update(); - if (!bSkinUpdate && bShapeUpdate) { + // non dynamic deformer = Modifer without armature and shape keys, no need to create storage + if (!bSkinUpdate && bShapeUpdate && m_bDynamic) { // this means that there is no armature, we still need to copy the vertex to m_transverts // and update the normal (was not done after shape key calculation) diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 1ec7bfdf74a..949e5e1e3ad 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -67,6 +67,7 @@ public: }; virtual RAS_Deformer *GetReplica(); + virtual void ProcessReplica(); virtual ~BL_ShapeDeformer(); bool Update (void); diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index e92c3b29543..a13f78e1b27 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -127,24 +127,26 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) if (!Update()) return false; - // the vertex cache is unique to this deformer, no need to update it - // if it wasn't updated! We must update all the materials at once - // because we will not get here again for the other material - nmat = m_pMeshObject->NumMaterials(); - for (imat=0; imatGetMeshMaterial(imat); - if(!mmat->m_slots[(void*)m_gameobj]) - continue; - - slot = *mmat->m_slots[(void*)m_gameobj]; - - // for each array - for(slot->begin(it); !slot->end(it); slot->next(it)) { - // for each vertex - // copy the untransformed data from the original mvert - for(i=it.startvertex; iNumMaterials(); + for (imat=0; imatGetMeshMaterial(imat); + if(!mmat->m_slots[(void*)m_gameobj]) + continue; + + slot = *mmat->m_slots[(void*)m_gameobj]; + + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { + // for each vertex + // copy the untransformed data from the original mvert + for(i=it.startvertex; iSetMesh(meshobj, true,false); + shapeInfo->SetMesh(meshobj, dm,true,false); bm = shapeInfo->CreateBulletShape(); break; } case KX_BOUNDMESH: { - - if (!ci.m_mass ||objprop->m_softbody) - { - // 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,false); - } + bool useGimpact = (ci.m_mass && !objprop->m_softbody); - // Soft bodies require welding. Only avoid remove doubles for non-soft bodies! - if (objprop->m_softbody) - { - shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI - } - - bm = shapeInfo->CreateBulletShape(); - //no moving concave meshes, so don't bother calculating inertia - //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); + // mesh shapes can be shared, check first if we already have a shape on that mesh + class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, dm, false,useGimpact); + if (sharedShapeInfo != NULL) + { + delete shapeInfo; + shapeInfo = sharedShapeInfo; + shapeInfo->AddRef(); } else { - shapeInfo->SetMesh(meshobj, false,true); - bm = shapeInfo->CreateBulletShape(); + shapeInfo->SetMesh(meshobj, dm, false,useGimpact); } + // Soft bodies require welding. Only avoid remove doubles for non-soft bodies! + if (objprop->m_softbody) + { + shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI + } + + bm = shapeInfo->CreateBulletShape(); + //should we compute inertia for dynamic shape? + //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); + break; } } diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index ec2cdede683..02f2aa635af 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -32,6 +32,7 @@ SET(INC ../../../../extern/bullet2/src ../../../../extern/glew/include ../../../../intern/moto/include + ../../../../intern/guardedalloc ../../../kernel/gen_system ../../../../intern/string ../../../../intern/SoundSystem @@ -41,6 +42,8 @@ SET(INC ../../GameLogic ../../SceneGraph ../../../../source/blender/makesdna + ../../../../source/blender/blenlib + ../../../../source/blender/blenkernel ${PYTHON_INC} ) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 961e9096442..01e8aa2560f 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -35,6 +35,10 @@ subject to the following restrictions: #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +extern "C"{ +#include "BKE_cdderivedmesh.h" +} + class BP_Proxy; ///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class @@ -1312,9 +1316,9 @@ void DefaultMotionState::calculateWorldTransformations() // Shape constructor std::map CcdShapeConstructionInfo::m_meshShapeMap; -CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, bool polytope) +CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope, bool gimpact) { - if (polytope) + if (polytope || dm || gimpact) // not yet supported return NULL; @@ -1324,9 +1328,9 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope,bool useGimpact) { - int numpolys; + int numpolys, numverts; m_useGimpact = useGimpact; @@ -1335,6 +1339,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo assert(IsUnused()); m_shapeType = PHY_SHAPE_NONE; m_meshObject = NULL; + bool free_dm = false; // No mesh object or mesh has no polys if (!meshobj || meshobj->HasColliderPolygon()==false) { @@ -1344,12 +1349,21 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo return false; } - numpolys = meshobj->NumPolygons(); + if (!dm) { + free_dm = true; + dm = CDDM_from_mesh(meshobj->GetMesh(), NULL); + } + + 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); m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; /* Convert blender geometry into bullet mesh, need these vars for mapping */ - vector vert_tag_array(meshobj->GetMesh()->totvert, false); + vector vert_tag_array(numverts, false); unsigned int tot_bt_verts= 0; unsigned int orig_index; int i; @@ -1359,19 +1373,16 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo // Tag verts we're using for (int p2=0; p2GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly = meshobj->GetPolygon(index[p2]); // only add polygons that have the collision flag set if (poly->IsCollider()) { - for(i=0; iVertexCount(); i++) { - orig_index= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[orig_index]==false) - { - vert_tag_array[orig_index]= true; - tot_bt_verts++; - } - } + if (vert_tag_array[mf->v1]==false) {vert_tag_array[mf->v1]= true;tot_bt_verts++;} + if (vert_tag_array[mf->v2]==false) {vert_tag_array[mf->v2]= true;tot_bt_verts++;} + if (vert_tag_array[mf->v3]==false) {vert_tag_array[mf->v3]= true;tot_bt_verts++;} + if (mf->v4 && vert_tag_array[mf->v4]==false) {vert_tag_array[mf->v4]= true;tot_bt_verts++;} } } @@ -1381,51 +1392,69 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo for (int p2=0; p2GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly= meshobj->GetPolygon(index[p2]); // only add polygons that have the collisionflag set if (poly->IsCollider()) { - for(i=0; iVertexCount(); i++) { - RAS_TexVert *v= poly->GetVertex(i); - orig_index= v->getOrigIndex(); - - if (vert_tag_array[orig_index]==true) - { - const float* vtx = v->getXYZ(); - vert_tag_array[orig_index]= false; - - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; - } + if (vert_tag_array[mf->v1]==true) + { + const float* vtx = mvert[mf->v1].co; + vert_tag_array[mf->v1]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; + } + if (vert_tag_array[mf->v2]==true) + { + const float* vtx = mvert[mf->v2].co; + vert_tag_array[mf->v2]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; + } + if (vert_tag_array[mf->v3]==true) + { + const float* vtx = mvert[mf->v3].co; + vert_tag_array[mf->v3]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; + } + if (mf->v4 && vert_tag_array[mf->v4]==true) + { + const float* vtx = mvert[mf->v4].co; + vert_tag_array[mf->v4]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; } } } } else { unsigned int tot_bt_tris= 0; - vector vert_remap_array(meshobj->GetMesh()->totvert, 0); + vector vert_remap_array(numverts, 0); // Tag verts we're using for (int p2=0; p2GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly= meshobj->GetPolygon(index[p2]); // only add polygons that have the collision flag set if (poly->IsCollider()) { - for(i=0; iVertexCount(); i++) { - orig_index= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[orig_index]==false) - { - vert_tag_array[orig_index]= true; - vert_remap_array[orig_index]= tot_bt_verts; - tot_bt_verts++; - } - } - - tot_bt_tris += (i==4 ? 2:1); /* a quad or a tri */ + if (vert_tag_array[mf->v1]==false) + {vert_tag_array[mf->v1]= true;vert_remap_array[mf->v1]= tot_bt_verts;tot_bt_verts++;} + if (vert_tag_array[mf->v2]==false) + {vert_tag_array[mf->v2]= true;vert_remap_array[mf->v2]= tot_bt_verts;tot_bt_verts++;} + if (vert_tag_array[mf->v3]==false) + {vert_tag_array[mf->v3]= true;vert_remap_array[mf->v3]= tot_bt_verts;tot_bt_verts++;} + if (mf->v4 && vert_tag_array[mf->v4]==false) + {vert_tag_array[mf->v4]= true;vert_remap_array[mf->v4]= tot_bt_verts;tot_bt_verts++;} + tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */ } } @@ -1437,76 +1466,67 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo int *poly_index_pt= &m_polygonIndexArray[0]; int *tri_pt= &m_triFaceArray[0]; - for (int p2=0; p2GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly= meshobj->GetPolygon(index[p2]); // only add polygons that have the collisionflag set if (poly->IsCollider()) { - RAS_TexVert *v1= poly->GetVertex(0); - RAS_TexVert *v2= poly->GetVertex(1); - RAS_TexVert *v3= poly->GetVertex(2); - int i1= v1->getOrigIndex(); - int i2= v2->getOrigIndex(); - int i3= v3->getOrigIndex(); - const float* vtx; + MVert *v1= &mvert[mf->v1]; + MVert *v2= &mvert[mf->v2]; + MVert *v3= &mvert[mf->v3]; // the face indicies - tri_pt[0]= vert_remap_array[i1]; - tri_pt[1]= vert_remap_array[i2]; - tri_pt[2]= vert_remap_array[i3]; + tri_pt[0]= vert_remap_array[mf->v1]; + tri_pt[1]= vert_remap_array[mf->v2]; + tri_pt[2]= vert_remap_array[mf->v3]; tri_pt= tri_pt+3; // m_polygonIndexArray - *poly_index_pt= p2; + *poly_index_pt= index[p2]; poly_index_pt++; // the vertex location - if (vert_tag_array[i1]==true) { /* *** v1 *** */ - vert_tag_array[i1]= false; - vtx = v1->getXYZ(); - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; + if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */ + vert_tag_array[mf->v1]= false; + *bt++ = v1->co[0]; + *bt++ = v1->co[1]; + *bt++ = v1->co[2]; } - if (vert_tag_array[i2]==true) { /* *** v2 *** */ - vert_tag_array[i2]= false; - vtx = v2->getXYZ(); - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; + if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */ + vert_tag_array[mf->v2]= false; + *bt++ = v2->co[0]; + *bt++ = v2->co[1]; + *bt++ = v2->co[2]; } - if (vert_tag_array[i3]==true) { /* *** v3 *** */ - vert_tag_array[i3]= false; - vtx = v3->getXYZ(); - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; + if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */ + vert_tag_array[mf->v3]= false; + *bt++ = v3->co[0]; + *bt++ = v3->co[1]; + *bt++ = v3->co[2]; } - if (poly->VertexCount()==4) + if (mf->v4) { - RAS_TexVert *v4= poly->GetVertex(3); - int i4= v4->getOrigIndex(); + MVert *v4= &mvert[mf->v4]; - tri_pt[0]= vert_remap_array[i1]; - tri_pt[1]= vert_remap_array[i3]; - tri_pt[2]= vert_remap_array[i4]; + tri_pt[0]= vert_remap_array[mf->v1]; + tri_pt[1]= vert_remap_array[mf->v3]; + tri_pt[2]= vert_remap_array[mf->v4]; tri_pt= tri_pt+3; // m_polygonIndexArray - *poly_index_pt= p2; + *poly_index_pt= index[p2]; poly_index_pt++; // the vertex location - if (vert_tag_array[i4]==true) { /* *** v4 *** */ - vert_tag_array[i4]= false; - vtx = v4->getXYZ(); - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; + if (vert_tag_array[mf->v4]==true) { /* *** v4 *** */ + vert_tag_array[mf->v4]= false; + *bt++ = v4->co[0]; + *bt++ = v4->co[1]; + *bt++ = v4->co[2]; } } } @@ -1538,7 +1558,13 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo #endif m_meshObject = meshobj; - if (!polytope) + if (free_dm) { + dm->release(dm); + dm = NULL; + } + + // sharing only on static mesh at present, if you change that, you must also change in FindMesh + if (!polytope && !dm && !useGimpact) { // triangle shape can be shared, store the mesh object in the map m_meshShapeMap.insert(std::pair(meshobj,this)); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 4ab478b2106..315e2bdf429 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -36,6 +36,7 @@ extern bool gDisableDeactivation; class CcdPhysicsEnvironment; class btMotionState; class RAS_MeshObject; +struct DerivedMesh; class btCollisionShape; @@ -59,7 +60,7 @@ class CcdShapeConstructionInfo public: - static CcdShapeConstructionInfo* FindMesh(RAS_MeshObject* mesh, bool polytope); + static CcdShapeConstructionInfo* FindMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope, bool gimpact); CcdShapeConstructionInfo() : m_shapeType(PHY_SHAPE_NONE), @@ -139,7 +140,7 @@ public: return true; } - bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact); + bool SetMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope,bool useGimpact); RAS_MeshObject* GetMesh(void) { return m_meshObject; diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile index 48e537bb6a3..19b17de275a 100644 --- a/source/gameengine/Physics/Bullet/Makefile +++ b/source/gameengine/Physics/Bullet/Makefile @@ -51,4 +51,6 @@ CPPFLAGS += -I../../Expressions CPPFLAGS += -I../../GameLogic CPPFLAGS += -I../../SceneGraph CPPFLAGS += -I../../../../source/blender/makesdna +CPPFLAGS += -I../../../../source/blender/blenkernel +CPPFLAGS += -I../../../../source/blender/blenlib diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript index 115ab8bf730..c517d8b5d9d 100644 --- a/source/gameengine/Physics/Bullet/SConscript +++ b/source/gameengine/Physics/Bullet/SConscript @@ -14,7 +14,10 @@ incs += ' #source/gameengine/Expressions' incs += ' #source/gameengine/GameLogic' incs += ' #source/gameengine/SceneGraph' incs += ' #source/blender/makesdna' +incs += ' #source/blender/blenkernel' +incs += ' #source/blender/blenlib' incs += ' #intern/SoundSystem' +incs += ' #intern/guardedalloc' incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index bb8e3750485..9dc656ba56a 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -34,12 +34,15 @@ #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 +#include #include "GEN_Map.h" +struct DerivedMesh; + class RAS_Deformer { public: - RAS_Deformer() : m_pMesh(0), m_bDynamic(false) {}; + RAS_Deformer() : m_pMesh(NULL), m_bDynamic(false) {}; virtual ~RAS_Deformer(){}; virtual void Relink(GEN_Map*map)=0; virtual bool Apply(class RAS_IPolyMaterial *polymat)=0; @@ -60,6 +63,11 @@ public: { return m_bDynamic; } + virtual struct DerivedMesh* GetFinalMesh() + { + return NULL; + } + protected: class RAS_MeshObject *m_pMesh; bool m_bDynamic; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index f5324c6fbc9..014169f8838 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -118,16 +118,24 @@ RAS_ListRasterizer::~RAS_ListRasterizer() void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) { - if (list->m_flag & LIST_STANDALONE) - return ; - - RAS_ArrayLists::iterator it = mArrayLists.begin(); - while(it != mArrayLists.end()) { - if (it->second == list) { - mArrayLists.erase(it); - break; + if (list->m_flag & LIST_DERIVEDMESH) { + RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin(); + while(it != mDerivedMeshLists.end()) { + if (it->second == list) { + mDerivedMeshLists.erase(it); + break; + } + it++; + } + } else { + RAS_ArrayLists::iterator it = mArrayLists.begin(); + while(it != mArrayLists.end()) { + if (it->second == list) { + mArrayLists.erase(it); + break; + } + it++; } - it++; } } @@ -143,9 +151,15 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) if(!localSlot) { if (ms.m_pDerivedMesh) { // that means that we draw based on derived mesh, a display list is possible - // but it's unique to this mesh slot - localSlot = new RAS_ListSlot(this); - localSlot->m_flag |= LIST_STANDALONE; + // Note that we come here only for static derived mesh + RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.find(ms.m_pDerivedMesh); + if(it == mDerivedMeshLists.end()) { + localSlot = new RAS_ListSlot(this); + localSlot->m_flag |= LIST_DERIVEDMESH; + mDerivedMeshLists.insert(std::pair(ms.m_pDerivedMesh, localSlot)); + } else { + localSlot = static_cast(it->second->AddRef()); + } } else { RAS_ArrayLists::iterator it = mArrayLists.find(ms.m_displayArrays); if(it == mArrayLists.end()) { @@ -162,12 +176,12 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) void RAS_ListRasterizer::ReleaseAlloc() { - RAS_ArrayLists::iterator it = mArrayLists.begin(); - while(it != mArrayLists.end()) { + for(RAS_ArrayLists::iterator it = mArrayLists.begin();it != mArrayLists.end();++it) delete it->second; - it++; - } mArrayLists.clear(); + for (RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin();it != mDerivedMeshLists.end();++it) + delete it->second; + mDerivedMeshLists.clear(); } void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index 912f28af6aa..fe358808e4a 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -34,16 +34,20 @@ enum RAS_ListSlotFlags { LIST_BEGIN =16, LIST_END =32, LIST_REGEN =64, - LIST_STANDALONE =128, + LIST_DERIVEDMESH=128, }; +struct DerivedMesh; + typedef std::map RAS_ArrayLists; +typedef std::map RAS_DerivedMeshLists; class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer { bool mUseVertexArrays; bool mATI; RAS_ArrayLists mArrayLists; + RAS_DerivedMeshLists mDerivedMeshLists; RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms); void ReleaseAlloc(); -- cgit v1.2.3