diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2009-04-14 00:08:33 +0400 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2009-04-14 00:08:33 +0400 |
commit | 0b8661ab4da1a7cfbc756640649a2d07bb36cc64 (patch) | |
tree | 6d171db30ddcba3d379dea04b2da9449203419a6 /source/gameengine/Ketsji | |
parent | 6f12e584a97f664c654ddfbe5f721d2a7be3d491 (diff) |
BGE: Occlusion culling and other performance improvements.
Added occlusion culling capability in the BGE.
More info: http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.49/Game_Engine#BGE_Scenegraph_improvement
MSVC, scons, cmake, Makefile updated.
Other minor performance improvements:
- The rasterizer was computing the openGL model matrix of the objects too many times
- DBVT view frustrum culling was not properly culling behind the near plane:
Large objects behind the camera were sent to the GPU
- Remove all references to mesh split/join feature as it is not yet functional
Diffstat (limited to 'source/gameengine/Ketsji')
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 51 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 35 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 15 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.cpp | 16 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.h | 11 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_VisibilityActuator.cpp | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_VisibilityActuator.h | 2 |
7 files changed, 103 insertions, 31 deletions
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 817afedd205..16cf3d9ae32 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -92,6 +92,7 @@ KX_GameObject::KX_GameObject( m_bIsNegativeScaling(false), m_bVisible(true), m_bCulled(true), + m_bOccluder(false), m_pPhysicsController1(NULL), m_pGraphicController(NULL), m_pPhysicsEnvironment(NULL), @@ -146,7 +147,12 @@ KX_GameObject::~KX_GameObject() } } - +KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info) +{ + if (!info) + return NULL; + return info->m_gameobject; +} CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) { @@ -435,7 +441,7 @@ static void UpdateBuckets_recursive(SG_Node* node) void KX_GameObject::UpdateBuckets( bool recursive ) { - double* fl = GetOpenGLMatrix(); + double* fl = GetOpenGLMatrixPtr()->getPointer(); for (size_t i=0;i<m_meshes.size();i++) m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); @@ -597,23 +603,34 @@ KX_GameObject::SetVisible( setVisible_recursive(m_pSGNode, v); } -bool -KX_GameObject::GetCulled( - void - ) +static void setOccluder_recursive(SG_Node* node, bool v) { - return m_bCulled; + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->SetOccluder(v, false); + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + setOccluder_recursive(childnode, v); + } } void -KX_GameObject::SetCulled( - bool c +KX_GameObject::SetOccluder( + bool v, + bool recursive ) { - m_bCulled = c; + m_bOccluder = v; + if (recursive) + setOccluder_recursive(m_pSGNode, v); } - void KX_GameObject::SetLayer( int l @@ -1036,6 +1053,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O}, {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O}, {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, + {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS}, {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS}, {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS}, {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS}, @@ -1069,6 +1087,7 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), + KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_position, pyattr_set_position), KX_PYATTRIBUTE_RO_FUNCTION("localInertia", KX_GameObject, pyattr_get_localInertia), KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_orientation,pyattr_set_orientation), @@ -1746,6 +1765,16 @@ PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) } +PyObject* KX_GameObject::PySetOcclusion(PyObject* self, PyObject* args) +{ + int occlusion, recursive = 0; + if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive)) + return NULL; + + SetOccluder(occlusion ? true:false, recursive ? true:false); + Py_RETURN_NONE; +} + PyObject* KX_GameObject::PyGetVisible(PyObject* self) { ShowDeprecationWarning("getVisible()", "the visible property"); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 172272150c0..c389d6cc776 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -87,6 +87,7 @@ protected: // culled = while rendering, depending on camera bool m_bVisible; bool m_bCulled; + bool m_bOccluder; KX_IPhysicsController* m_pPhysicsController1; PHY_IGraphicController* m_pGraphicController; @@ -103,6 +104,11 @@ protected: public: bool m_isDeformable; + /** + * Helper function for modules that can't include KX_ClientObjectInfo.h + */ + static KX_GameObject* GetClientObject(KX_ClientObjectInfo* info); + // Python attributes that wont convert into CValue // // there are 2 places attributes can be stored, in the CValue, @@ -118,11 +124,8 @@ public: // * if CValue conversion fails, use a PyObject in "m_attrlist" // * when assigning a value, first see if it can be a CValue, if it can remove the "m_attrlist" and set the CValue // - PyObject* m_attrlist; - - virtual void /* This function should be virtual - derived classed override it */ Relink( GEN_Map<GEN_HashedPtr, void*> *map @@ -698,20 +701,37 @@ public: /** * Was this object culled? */ - bool + inline bool GetCulled( void - ); + ) { return m_bCulled; } /** * Set culled flag of this object */ - void + inline void SetCulled( bool c - ); + ) { m_bCulled = c; } + + /** + * Is this object an occluder? + */ + inline bool + GetOccluder( + void + ) { return m_bOccluder; } /** + * Set occluder flag of this object + */ + void + SetOccluder( + bool v, + bool recursive + ); + + /** * Change the layer of the object (when it is added in another layer * than the original layer) */ @@ -908,6 +928,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetOrientation); KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible); KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible); + KX_PYMETHOD_VARARGS(KX_GameObject,SetOcclusion); KX_PYMETHOD_NOARGS(KX_GameObject,GetState); KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index aeb80806f6c..83a2fa8a448 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -294,8 +294,14 @@ void KX_KetsjiEngine::RenderDome() if (!BeginFrame()) return; - int n_renders=m_dome->GetNumberRenders();// usually 4 or 6 KX_SceneList::iterator sceneit; + for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) + { + // do this only once per scene + (*sceneit)->UpdateMeshTransformations(); + } + + int n_renders=m_dome->GetNumberRenders();// usually 4 or 6 for (int i=0;i<n_renders;i++){ m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) @@ -311,7 +317,6 @@ void KX_KetsjiEngine::RenderDome() // shadow buffers if (i == 0){ RenderShadowBuffers(scene); - scene->UpdateMeshTransformations();//I need to run it somewherelse, otherwise Im overrunning it } // Avoid drawing the scene with the active camera twice when it's viewport is enabled if(cam && !cam->GetViewport()) @@ -812,6 +817,9 @@ void KX_KetsjiEngine::Render() // pass the scene's worldsettings to the rasterizer SetWorldSettings(scene->GetWorldInfo()); + // do this only once per scene + scene->UpdateMeshTransformations(); + // shadow buffers RenderShadowBuffers(scene); @@ -1140,7 +1148,6 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) light->BindShadowBuffer(m_rasterizer, cam, camtrans); /* update scene */ - scene->UpdateMeshTransformations(); scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer()); /* render */ @@ -1245,7 +1252,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) cam->GetCameraLocation(), cam->GetCameraOrientation()); cam->SetModelviewMatrix(viewmat); - //redundant, already done in + //redundant, already done in Render() //scene->UpdateMeshTransformations(); // The following actually reschedules all vertices to be diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 2f7c1b77794..98c129ebca5 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -138,6 +138,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_suspendeddelta = 0.0; m_dbvt_culling = false; + m_dbvt_occlusion_res = 0; m_activity_culling = false; m_suspend = false; m_isclearingZbuffer = true; @@ -1352,17 +1353,18 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int if (m_dbvt_culling) { // test culling through Bullet - PHY__Vector4 planes[5]; + PHY__Vector4 planes[6]; // get the clip planes MT_Vector4* cplanes = cam->GetNormalizedClipPlanes(); // and convert - planes[0].setValue(cplanes[0].getValue()); - planes[1].setValue(cplanes[1].getValue()); - planes[2].setValue(cplanes[2].getValue()); - planes[3].setValue(cplanes[3].getValue()); - planes[4].setValue(cplanes[5].getValue()); + planes[0].setValue(cplanes[4].getValue()); // near + planes[1].setValue(cplanes[5].getValue()); // far + planes[2].setValue(cplanes[0].getValue()); // left + planes[3].setValue(cplanes[1].getValue()); // right + planes[4].setValue(cplanes[2].getValue()); // top + planes[5].setValue(cplanes[3].getValue()); // bottom CullingInfo info(layer); - dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5); + dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res); } if (!dbvt_culling) { // the physics engine couldn't help us, do it the hard way diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 55e7afa4957..e1e89e253ed 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -265,6 +265,11 @@ protected: bool m_dbvt_culling; /** + * Occlusion culling resolution + */ + int m_dbvt_occlusion_res; + + /** * The framing settings used by this scene */ @@ -545,8 +550,10 @@ public: bool IsClearingZBuffer(); void EnableZBufferClearing(bool isclearingZbuffer); // use of DBVT tree for camera culling - void SetDbvtCameraCulling(bool b) { m_dbvt_culling = b; }; - bool GetDbvtCameraCulling() { return m_dbvt_culling; }; + void SetDbvtCulling(bool b) { m_dbvt_culling = b; }; + bool GetDbvtCulling() { return m_dbvt_culling; }; + void SetDbvtOcclusionRes(int i) { m_dbvt_occlusion_res = i; }; + int GetDbvtOcclusionRes() { return m_dbvt_occlusion_res; }; void SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index 1ee2169adc4..fceb0b5922c 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -38,11 +38,13 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool occlusion, bool recursive, PyTypeObject* T ) : SCA_IActuator(gameobj,T), m_visible(visible), + m_occlusion(occlusion), m_recursive(recursive) { // intentionally empty @@ -78,6 +80,7 @@ KX_VisibilityActuator::Update() KX_GameObject *obj = (KX_GameObject*) GetParent(); obj->SetVisible(m_visible, m_recursive); + obj->SetOccluder(m_occlusion, m_recursive); obj->UpdateBuckets(m_recursive); return false; @@ -130,6 +133,7 @@ KX_VisibilityActuator::Methods[] = { PyAttributeDef KX_VisibilityActuator::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("visibility", KX_VisibilityActuator, m_visible), + KX_PYATTRIBUTE_BOOL_RW("occlusion", KX_VisibilityActuator, m_occlusion), KX_PYATTRIBUTE_BOOL_RW("recursion", KX_VisibilityActuator, m_recursive), { NULL } //Sentinel }; diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index fca37500915..4269258f862 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -39,6 +39,7 @@ class KX_VisibilityActuator : public SCA_IActuator /** Make visible? */ bool m_visible; + bool m_occlusion; bool m_recursive; public: @@ -46,6 +47,7 @@ class KX_VisibilityActuator : public SCA_IActuator KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool occlusion, bool recursive, PyTypeObject* T=&Type ); |