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:
authorBenoit Bolsee <benoit.bolsee@online.be>2009-05-14 17:47:08 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2009-05-14 17:47:08 +0400
commitd95a10999052ad308599cb0fbbe7ed4f59870c9c (patch)
treec8ab32463f7e774319e35ab23855743dd0dea341 /source/gameengine/Converter
parent003534513645576215092b79f1aa46e85c89e3bd (diff)
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.
Diffstat (limited to 'source/gameengine/Converter')
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp102
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.cpp9
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.h2
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp73
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.h5
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.cpp9
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.h1
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp45
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.h2
9 files changed, 158 insertions, 90 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 09604e5c2e3..9ea623f17e4 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1249,18 +1249,34 @@ static void my_tex_space_mesh(Mesh *me)
}
-static void my_get_local_bounds(Object *ob, float *center, float *size)
+static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, float *size)
{
BoundBox *bb= NULL;
/* uses boundbox, function used by Ketsji */
switch (ob->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<parentChildLink> 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;i<childrenlist->GetCount();i++)
{
KX_GameObject* obj = static_cast<KX_GameObject*>(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;i<templist->GetCount();++i)
+ for (i=0;i<sumolist->GetCount();++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; i<sumolist->GetCount();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;i<sumolist->GetCount();++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; i<sumolist->GetCount();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;i<sumolist->GetCount();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<class GEN_HashedPtr, void*>*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; imat<nmat; imat++) {
RAS_MeshMaterial *mmat = m_pMeshObject->GetMeshMaterial(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; imat<nmat; imat++) {
- mmat = m_pMeshObject->GetMeshMaterial(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; i<it.endvertex; i++) {
- RAS_TexVert& v = it.vertex[i];
- v.SetXYZ(m_transverts[v.getOrigIndex()]);
+ if (m_transverts) {
+ // 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; imat<nmat; imat++) {
+ mmat = m_pMeshObject->GetMeshMaterial(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; i<it.endvertex; i++) {
+ RAS_TexVert& v = it.vertex[i];
+ v.SetXYZ(m_transverts[v.getOrigIndex()]);
+ }
}
}
}
@@ -161,6 +163,13 @@ RAS_Deformer *BL_SkinDeformer::GetReplica()
return result;
}
+void BL_SkinDeformer::ProcessReplica()
+{
+ BL_MeshDeformer::ProcessReplica();
+ m_lastArmaUpdate = -1;
+ m_releaseobject = false;
+}
+
//void where_is_pose (Object *ob);
//void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag);
bool BL_SkinDeformer::Update(void)
diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h
index 0a7b60788f9..8d3167746be 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.h
+++ b/source/gameengine/Converter/BL_SkinDeformer.h
@@ -68,6 +68,8 @@ public:
BL_ArmatureObject* arma = NULL);
virtual RAS_Deformer *GetReplica();
+ virtual void ProcessReplica();
+
virtual ~BL_SkinDeformer();
bool Update (void);
bool Apply (class RAS_IPolyMaterial *polymat);