diff options
author | Daniel Stokes <kupomail@gmail.com> | 2013-12-18 02:42:47 +0400 |
---|---|---|
committer | kupoman <kupomail@gmail.com> | 2013-12-18 05:03:27 +0400 |
commit | e9e08a1d12594eab0e341049fc252ff8578e9333 (patch) | |
tree | ac7c15959b03398babb68058f3824c2a4dbff5b7 /source/gameengine | |
parent | 173f7a3d30db8cba95656bf03dc842b9300c2436 (diff) |
Game Engine: Level of detail support and tools
Levels of detail can be added and modified in the object panel. The object
panel also contains new tools for generating levels of detail, setting up
levels of detail based on object names (useful for importing), and
clearing an object's level of detail settings. This is meant as a game
engine feature, though the level of details settings can be previewed in
the viewport.
Reviewed By: moguri, nexyon, brecht
Differential Revision: http://developer.blender.org/D109
Diffstat (limited to 'source/gameengine')
-rw-r--r-- | source/gameengine/Converter/BL_BlenderDataConversion.cpp | 30 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Dome.cpp | 3 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 39 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 18 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 3 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.cpp | 13 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.h | 3 |
7 files changed, 107 insertions, 2 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index eeaffd9005a..9998f10e417 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -93,6 +93,7 @@ #include "KX_SoftBodyDeformer.h" //#include "BL_ArmatureController.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" #include "BlenderWorldInfo.h" #include "KX_KetsjiEngine.h" @@ -938,8 +939,15 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, RAS_MeshObject *meshobj; int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object. - if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL) - return meshobj; + // Without checking names, we get some reuse we don't want that can cause + // problems with material LoDs. + if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL) { + STR_String bge_name = meshobj->GetName(); + STR_String blender_name = ((Mesh*)blenderobj->data)->id.name+2; + if (bge_name == blender_name) + return meshobj; + } + // Get DerivedMesh data DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj); DM_ensure_tessface(dm); @@ -1852,6 +1860,24 @@ static KX_GameObject *gameobject_from_blenderobject( // set transformation gameobj->AddMesh(meshobj); + + // gather levels of detail + if (BLI_countlist(&ob->lodlevels) > 1) { + LodLevel *lod = ((LodLevel*)ob->lodlevels.first)->next; + Mesh* lodmesh = mesh; + Object* lodmatob = ob; + gameobj->AddLodMesh(meshobj); + for (; lod; lod = lod->next) { + if (!lod->source || lod->source->type != OB_MESH) continue; + if (lod->flags & OB_LOD_USE_MESH) { + lodmesh = static_cast<Mesh*>(lod->source->data); + } + if (lod->flags & OB_LOD_USE_MAT) { + lodmatob = lod->source; + } + gameobj->AddLodMesh(BL_ConvertMesh(lodmesh, lodmatob, kxscene, converter, libloading)); + } + } // for all objects: check whether they want to // respond to updates diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index f87d4799abc..43d74487542 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -2045,5 +2045,8 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) scene->CalculateVisibleMeshes(m_rasterizer,cam); scene->RenderBuckets(camtrans, m_rasterizer); + + // update levels of detail + scene->UpdateObjectLods(); } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index d3b5a987138..8b7e6667fae 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -71,6 +71,8 @@ typedef unsigned long uint_ptr; #include "NG_NetworkScene.h" //Needed for sendMessage() #include "KX_ObstacleSimulation.h" +#include "BKE_object.h" + #include "BL_ActionManager.h" #include "BL_Action.h" @@ -732,6 +734,43 @@ void KX_GameObject::RemoveMeshes() m_meshes.clear(); } +void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) +{ + m_lodmeshes.push_back(mesh); +} + +void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) +{ + // Handle dupligroups + if (this->m_pInstanceObjects) { + KX_GameObject * instob; + int count = this->m_pInstanceObjects->GetCount(); + for (int i = 0; i < count; i++) { + instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i); + instob->UpdateLod(cam_pos); + } + } + + if (this->m_lodmeshes.empty()) return; + + MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos; + float distance2 = delta.length2(); + + int level = 0; + Object *bob = this->GetBlenderObject(); + LodLevel *lod = (LodLevel*) bob->lodlevels.first; + for (; lod; lod = lod->next, level++) { + if (!lod->source) level--; + if (!lod->next || lod->next->distance * lod->next->distance > distance2) break; + } + + RAS_MeshObject *mesh = this->m_lodmeshes[level]; + + if (mesh != this->m_meshes[0]) { + this->GetScene()->ReplaceMesh(this, mesh, true, false); + } +} + void KX_GameObject::UpdateTransform() { // HACK: saves function call for dynamic object, they are handled differently diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 12aac68365b..ac0afca91eb 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -87,6 +87,7 @@ protected: STR_String m_text; int m_layer; std::vector<RAS_MeshObject*> m_meshes; + std::vector<RAS_MeshObject*> m_lodmeshes; SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; @@ -772,6 +773,23 @@ public: } /** + * Add a level of detail mesh to the object. These should + * be added in order. + */ + void + AddLodMesh( + RAS_MeshObject* mesh + ); + + /** + * Updates the current lod level based on distance from camera. + */ + void + UpdateLod( + MT_Vector3 &cam_pos + ); + + /** * Pick out a mesh associated with the integer 'num'. */ RAS_MeshObject* diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 0e9e2cd8328..3aa5a9f4f0e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1315,6 +1315,9 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) scene->CalculateVisibleMeshes(m_rasterizer,cam); + // update levels of detail + scene->UpdateObjectLods(); + m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_RENDER); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 70924c65519..4a147b4eb60 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1726,6 +1726,19 @@ void KX_Scene::RenderFonts() } } +void KX_Scene::UpdateObjectLods(void) +{ + KX_GameObject* gameobj; + MT_Vector3 cam_pos = this->m_active_camera->NodeGetWorldPosition(); + + for (int i = 0; i < this->GetObjectList()->GetCount(); i++) { + gameobj = (KX_GameObject*) GetObjectList()->GetValue(i); + if (!gameobj->GetCulled()){ + gameobj->UpdateLod(cam_pos); + } + } +} + void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index ee2a994d53c..50fac923fe2 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -544,6 +544,9 @@ public: // Resume a suspended scene. void Resume(); + + // Update the mesh for objects based on level of detail settings + void UpdateObjectLods(void); // Update the activity box settings for objects in this scene, if needed. void UpdateObjectActivity(void); |