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-04-08 02:14:06 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2009-04-08 02:14:06 +0400
commit51b4145841293d4a695b7bbe88e90ebd98443fc8 (patch)
tree61818fb3a50e0891b630680b203c3fe80fe149bb /source/gameengine
parent486985762aa71b75ec1d1d0e7bbf0f777065f3a3 (diff)
BGE Scenegraph and View frustrum culling improvement.
This commit contains a number of performance improvements for the BGE in the Scenegraph (parent relation between objects in the scene) and view frustrum culling. The scenegraph improvement consists in avoiding position update if the object has not moved since last update and the removal of redundant updates and synchronization with the physics engine. The view frustrum culling improvement consists in using the DBVT broadphase facility of Bullet to build a tree of graphical objects in the scene. The elements of the tree are Aabb boxes (Aligned Axis Bounding Boxes) enclosing the objects. This provides good precision in closed and opened scenes. This new culling system is enabled by default but just in case, it can be disabled with a button in the World settings. There is no do_version in this commit but it will be added before the 2.49 release. For now you must manually enable the DBVT culling option in World settings when you open an old file. The above improvements speed up scenegraph and culling up to 5x. However, this performance improvement is only visible when you have hundreds or thousands of objects. The main interest of the DBVT tree is to allow easy occlusion culling and automatic LOD system. This will be the object of further improvements.
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp67
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp7
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h12
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp58
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h25
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp48
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_MotionState.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_MotionState.h1
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.cpp17
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp7
-rw-r--r--source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h3
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.h9
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp103
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h17
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.cpp112
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.h74
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp16
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp107
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h15
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h35
-rw-r--r--source/gameengine/Physics/common/PHY_IController.cpp39
-rw-r--r--source/gameengine/Physics/common/PHY_IController.h53
-rw-r--r--source/gameengine/Physics/common/PHY_IGraphicController.cpp39
-rw-r--r--source/gameengine/Physics/common/PHY_IGraphicController.h56
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h8
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp8
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.h7
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.h1
-rw-r--r--source/gameengine/SceneGraph/SG_BBox.cpp7
-rw-r--r--source/gameengine/SceneGraph/SG_BBox.h2
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.cpp2
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.h30
-rw-r--r--source/gameengine/SceneGraph/SG_Node.cpp7
-rw-r--r--source/gameengine/SceneGraph/SG_Node.h3
-rw-r--r--source/gameengine/SceneGraph/SG_ParentRelation.h3
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.cpp19
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.h13
47 files changed, 953 insertions, 146 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index d74243b0eb0..3c77f122758 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -164,7 +164,11 @@ extern "C" {
// defines USE_ODE to choose physics engine
#include "KX_ConvertPhysicsObject.h"
-
+#ifdef USE_BULLET
+#include "CcdPhysicsEnvironment.h"
+#include "CcdGraphicController.h"
+#endif
+#include "KX_MotionState.h"
// This file defines relationships between parents and children
// in the game engine.
@@ -1265,8 +1269,37 @@ static void my_get_local_bounds(Object *ob, float *center, float *size)
//////////////////////////////////////////////////////
-
-
+void BL_CreateGraphicObjectNew(KX_GameObject* gameobj,
+ const MT_Point3& localAabbMin,
+ const MT_Point3& localAabbMax,
+ KX_Scene* kxscene,
+ bool isActive,
+ e_PhysicsEngine physics_engine)
+{
+ if (gameobj->GetMeshCount() > 0)
+ {
+ switch (physics_engine)
+ {
+#ifdef USE_BULLET
+ case UseBullet:
+ {
+ CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
+ assert(env);
+ PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+ CcdGraphicController* ctrl = new CcdGraphicController(env, motionstate);
+ gameobj->SetGraphicController(ctrl);
+ ctrl->setNewClientInfo(gameobj->getClientInfo());
+ ctrl->setLocalAabb(localAabbMin, localAabbMax);
+ if (isActive)
+ env->addCcdGraphicController(ctrl);
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+}
void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
struct Object* blenderobject,
@@ -1859,8 +1892,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
if (blenderscene->world) {
kxscene->SetActivityCulling( (blenderscene->world->mode & WO_ACTIVITY_CULLING) != 0);
kxscene->SetActivityCullingRadius(blenderscene->world->activityBoxRadius);
+ kxscene->SetDbvtCameraCulling((blenderscene->world->mode & WO_DBVT_CAMERA_CULLING) != 0);
} else {
kxscene->SetActivityCulling(false);
+ kxscene->SetDbvtCameraCulling(false);
}
int activeLayerBitInfo = blenderscene->lay;
@@ -1954,7 +1989,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeSetLocalPosition(pos);
gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
gameobj->NodeSetLocalScale(scale);
- gameobj->NodeUpdateGS(0,true);
+ gameobj->NodeUpdateGS(0);
BL_ConvertIpos(blenderobject,gameobj,converter);
BL_ConvertMaterialIpos(blenderobject, gameobj, converter);
@@ -2037,7 +2072,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
objectlist->Add(gameobj->AddRef());
//tf.Add(gameobj->GetSGNode());
- gameobj->NodeUpdateGS(0,true);
+ gameobj->NodeUpdateGS(0);
gameobj->AddMeshUser();
}
@@ -2148,7 +2183,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeSetLocalPosition(pos);
gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
gameobj->NodeSetLocalScale(scale);
- gameobj->NodeUpdateGS(0,true);
+ gameobj->NodeUpdateGS(0);
BL_ConvertIpos(blenderobject,gameobj,converter);
BL_ConvertMaterialIpos(blenderobject,gameobj, converter);
@@ -2226,7 +2261,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
objectlist->Add(gameobj->AddRef());
//tf.Add(gameobj->GetSGNode());
- gameobj->NodeUpdateGS(0,true);
+ gameobj->NodeUpdateGS(0);
gameobj->AddMeshUser();
}
else
@@ -2377,7 +2412,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
if (gameobj->GetSGNode()->GetSGParent() == 0)
{
parentlist->Add(gameobj->AddRef());
- gameobj->NodeUpdateGS(0,true);
+ gameobj->NodeUpdateGS(0);
}
}
@@ -2414,6 +2449,22 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren);
}
+ // create graphic controller for culling
+ if (kxscene->GetDbvtCameraCulling())
+ {
+ 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);
+ }
+ }
+ }
//set ini linearVel and int angularVel //rcruiz
if (converter->addInitFromFrame)
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 97a0819147c..b0c676a410d 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -267,9 +267,11 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
Scene *blenderscene = GetBlenderSceneForName(scenename);
e_PhysicsEngine physics_engine = UseBullet;
+ bool useDbvtCulling = false;
// hook for registration function during conversion.
m_currentScene = destinationscene;
destinationscene->SetSceneConverter(this);
+ SG_SetActiveStage(SG_STAGE_CONVERTER);
if (blenderscene)
{
@@ -281,6 +283,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
case WOPHY_BULLET:
{
physics_engine = UseBullet;
+ useDbvtCulling = (blenderscene->world->mode & WO_DBVT_CAMERA_CULLING) != 0;
break;
}
@@ -313,7 +316,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
#ifdef USE_BULLET
case UseBullet:
{
- CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment();
+ CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling);
ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
@@ -806,7 +809,7 @@ void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(){
gameobj->NodeSetLocalPosition(pos);
gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
gameobj->NodeSetLocalScale(scale);
- gameobj->NodeUpdateGS(0,true);
+ gameobj->NodeUpdateGS(0);
}
}
}
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index 062e9f7df50..435b2b5db19 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -417,13 +417,14 @@ void KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly)
{
if (!nondynaonly)
{
+ /*
btTransform worldTrans;
if (GetRigidBody())
{
GetRigidBody()->getMotionState()->getWorldTransform(worldTrans);
GetRigidBody()->setCenterOfMassTransform(worldTrans);
}
-
+ */
/*
scaling?
if (m_bDyna)
diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h
index 6ed21506372..4accd4bc2f1 100644
--- a/source/gameengine/Ketsji/KX_Camera.h
+++ b/source/gameengine/Ketsji/KX_Camera.h
@@ -45,6 +45,7 @@ class KX_Camera : public KX_GameObject
{
Py_Header;
protected:
+ friend class KX_Scene;
/** Camera parameters (clips distances, focal lenght). These
* params are closely tied to Blender. In the gameengine, only the
* projection and modelview matrices are relevant. There's a
@@ -67,6 +68,7 @@ protected:
* Storage for the projection matrix that is passed to the
* rasterizer. */
MT_Matrix4x4 m_projection_matrix;
+ //MT_Matrix4x4 m_projection_matrix1;
/**
* Storage for the modelview matrix that is passed to the
@@ -119,6 +121,16 @@ protected:
* Extracts the bound sphere of the view frustum.
*/
void ExtractFrustumSphere();
+ /**
+ * return the clip plane
+ */
+ MT_Vector4 *GetNormalizedClipPlanes()
+ {
+ ExtractClipPlanes();
+ NormalizeClipPlanes();
+ return m_planes;
+ }
+
public:
enum { INSIDE, INTERSECT, OUTSIDE } ;
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 7f99a565769..339a955702a 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -55,6 +55,7 @@ typedef unsigned long uint_ptr;
#include <stdio.h> // printf
#include "SG_Controller.h"
#include "KX_IPhysicsController.h"
+#include "PHY_IGraphicController.h"
#include "SG_Node.h"
#include "SG_Controller.h"
#include "KX_ClientObjectInfo.h"
@@ -91,6 +92,7 @@ KX_GameObject::KX_GameObject(
m_bVisible(true),
m_bCulled(true),
m_pPhysicsController1(NULL),
+ m_pGraphicController(NULL),
m_pPhysicsEnvironment(NULL),
m_xray(false),
m_pHitObject(NULL),
@@ -132,6 +134,10 @@ KX_GameObject::~KX_GameObject()
}
m_pSGNode->SetSGClientObject(NULL);
}
+ if (m_pGraphicController)
+ {
+ delete m_pGraphicController;
+ }
}
@@ -249,7 +255,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
NodeSetLocalScale(scale1);
NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
// object will now be a child, it must be removed from the parent list
CListValue* rootlist = scene->GetRootParentList();
if (rootlist->RemoveValue(this))
@@ -269,6 +275,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1);
}
}
+ // graphically, the object hasn't change place, no need to update m_pGraphicController
}
}
@@ -286,7 +293,7 @@ void KX_GameObject::RemoveParent(KX_Scene *scene)
// Remove us from our parent
GetSGNode()->DisconnectFromParent();
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
// the object is now a root object, add it to the parentlist
CListValue* rootlist = scene->GetRootParentList();
if (!rootlist->SearchValue(this))
@@ -303,12 +310,14 @@ void KX_GameObject::RemoveParent(KX_Scene *scene)
}
m_pPhysicsController1->RestoreDynamics();
}
+ // graphically, the object hasn't change place, no need to update m_pGraphicController
}
}
void KX_GameObject::ProcessReplica(KX_GameObject* replica)
{
replica->m_pPhysicsController1 = NULL;
+ replica->m_pGraphicController = NULL;
replica->m_pSGNode = NULL;
replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
replica->m_pClient_info->m_gameobject = replica;
@@ -437,22 +446,18 @@ void KX_GameObject::RemoveMeshes()
m_meshes.clear();
}
-
-
-void KX_GameObject::UpdateNonDynas()
+void KX_GameObject::UpdateTransform()
{
if (m_pPhysicsController1)
- {
+ // only update the transform of static object, dynamic object are handled differently
+ // note that for bullet, this does not even update the transform of static object
+ // but merely sets there collision flag to "kinematic" because the synchronization is
+ // done differently during physics simulation
m_pPhysicsController1->SetSumoTransform(true);
- }
-}
+ if (m_pGraphicController)
+ // update the culling tree
+ m_pGraphicController->SetGraphicTransform();
-
-
-void KX_GameObject::UpdateTransform()
-{
- if (m_pPhysicsController1)
- m_pPhysicsController1->SetSumoTransform(false);
}
void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
@@ -832,6 +837,7 @@ void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
}
GetSGNode()->SetLocalPosition(trans);
+
}
@@ -911,7 +917,7 @@ void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
}
-void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
+void KX_GameObject::NodeUpdateGS(double time)
{
if (GetSGNode())
GetSGNode()->UpdateWorldData(time);
@@ -1295,7 +1301,7 @@ int KX_GameObject::pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF *a
return 1;
self->NodeSetLocalPosition(pos);
- self->NodeUpdateGS(0.f,true);
+ self->NodeUpdateGS(0.f);
return 0;
}
@@ -1319,10 +1325,10 @@ int KX_GameObject::pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyMatTo(value, rot))
{
self->NodeSetLocalOrientation(rot);
- self->NodeUpdateGS(0.f,true);
+ self->NodeUpdateGS(0.f);
return 0;
}
- return 1;
+ PyErr_Clear();
if (PySequence_Size(value) == 4)
{
@@ -1331,7 +1337,7 @@ int KX_GameObject::pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF
{
rot.setRotation(qrot);
self->NodeSetLocalOrientation(rot);
- self->NodeUpdateGS(0.f,true);
+ self->NodeUpdateGS(0.f);
return 0;
}
return 1;
@@ -1344,7 +1350,7 @@ int KX_GameObject::pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF
{
rot.setEuler(erot);
self->NodeSetLocalOrientation(rot);
- self->NodeUpdateGS(0.f,true);
+ self->NodeUpdateGS(0.f);
return 0;
}
return 1;
@@ -1368,7 +1374,7 @@ int KX_GameObject::pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *at
return 1;
self->NodeSetLocalScale(scale);
- self->NodeUpdateGS(0.f,true);
+ self->NodeUpdateGS(0.f);
return 0;
}
@@ -1929,7 +1935,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
{
NodeSetLocalOrientation(matrix);
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
Py_RETURN_NONE;
}
@@ -1938,7 +1944,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
{
matrix.setRotation(quat);
NodeSetLocalOrientation(matrix);
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
Py_RETURN_NONE;
}
return NULL;
@@ -1959,7 +1965,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
if (fac> 1.0) fac= 1.0;
AlignAxisToVect(vect,axis,fac);
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
Py_RETURN_NONE;
}
}
@@ -1983,7 +1989,7 @@ PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
if (PyVecTo(value, pos))
{
NodeSetLocalPosition(pos);
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
Py_RETURN_NONE;
}
@@ -1996,7 +2002,7 @@ PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value)
if (PyVecTo(value, pos))
{
NodeSetWorldPosition(pos);
- NodeUpdateGS(0.f,true);
+ NodeUpdateGS(0.f);
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index bc6b60102d6..9c7dda5e394 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -57,6 +57,7 @@ struct KX_ClientObjectInfo;
class KX_RayCast;
class RAS_MeshObject;
class KX_IPhysicsController;
+class PHY_IGraphicController;
class PHY_IPhysicsEnvironment;
struct Object;
@@ -88,6 +89,7 @@ protected:
bool m_bCulled;
KX_IPhysicsController* m_pPhysicsController1;
+ PHY_IGraphicController* m_pGraphicController;
// used for ray casting
PHY_IPhysicsEnvironment* m_pPhysicsEnvironment;
STR_String m_testPropName;
@@ -351,6 +353,19 @@ public:
}
/**
+ * @return a pointer to the graphic controller owner by this class
+ */
+ PHY_IGraphicController* GetGraphicController()
+ {
+ return m_pGraphicController;
+ }
+
+ void SetGraphicController(PHY_IGraphicController* graphiccontroller)
+ {
+ m_pGraphicController = graphiccontroller;
+ }
+
+ /**
* @section Coordinate system manipulation functions
*/
@@ -367,8 +382,7 @@ public:
void
NodeUpdateGS(
- double time,
- bool bInitiator
+ double time
);
const
@@ -525,13 +539,6 @@ public:
static void UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene);
/**
- * Only update the transform if it's a non-dynamic object
- */
- void
- UpdateNonDynas(
- );
-
- /**
* Function to set IPO option at start of IPO
*/
void
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 97b4213b8bd..70ae0e4b937 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -412,7 +412,7 @@ else
// Compute the number of logic frames to do each update (fixed tic bricks)
- int frames =int(deltatime*m_ticrate);
+ int frames =int(deltatime*m_ticrate+1e-6);
// if (frames>1)
// printf("****************************************");
// printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
@@ -465,12 +465,15 @@ else
m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_NETWORK);
scene->GetNetworkScene()->proceed(m_frameTime);
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- scene->UpdateParents(m_frameTime);
+ //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE);
+ //scene->UpdateParents(m_frameTime);
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_PHYSICS1);
// set Python hooks for each scene
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
KX_SetActiveScene(scene);
@@ -479,31 +482,37 @@ else
// Update scenegraph after physics step. This maps physics calculations
// into node positions.
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- scene->UpdateParents(m_frameTime);
+ //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE);
+ //scene->UpdateParents(m_frameTime);
// Process sensors, and controllers
m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_CONTROLLER);
scene->LogicBeginFrame(m_frameTime);
// Scenegraph needs to be updated again, because Logic Controllers
// can affect the local matrices.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE);
scene->UpdateParents(m_frameTime);
// Process actuators
// Do some cleanup work for this logic frame
m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_ACTUATOR);
scene->LogicUpdateFrame(m_frameTime, true);
scene->LogicEndFrame();
// Actuators can affect the scenegraph
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
scene->UpdateParents(m_frameTime);
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->GetPhysicsEnvironment()->beginFrame();
// Perform physics calculations on the scene. This can involve
@@ -511,6 +520,7 @@ else
scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,1.0/m_ticrate);//m_deltatimerealDeltaTime);
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE);
scene->UpdateParents(m_frameTime);
@@ -574,6 +584,7 @@ else
KX_SetActiveScene(scene);
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_PHYSICS1);
scene->UpdateParents(m_clockTime);
// Perform physics calculations on the scene. This can involve
@@ -583,6 +594,7 @@ else
// Update scenegraph after physics step. This maps physics calculations
// into node positions.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->UpdateParents(m_clockTime);
// Do some cleanup work for this logic frame
@@ -591,6 +603,7 @@ else
// Actuators can affect the scenegraph
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_ACTUATOR);
scene->UpdateParents(m_clockTime);
scene->setSuspendedTime(0.0);
@@ -622,6 +635,7 @@ void KX_KetsjiEngine::Render()
const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_RENDER);
// hiding mouse cursor each frame
// (came back when going out of focus and then back in again)
@@ -1102,14 +1116,22 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
cam->GetCameraLocation(), cam->GetCameraOrientation());
cam->SetModelviewMatrix(viewmat);
- scene->UpdateMeshTransformations();
+ //redundant, already done in
+ //scene->UpdateMeshTransformations();
// The following actually reschedules all vertices to be
// redrawn. There is a cache between the actual rescheduling
// and this call though. Visibility is imparted when this call
// runs through the individual objects.
+
+ m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_CULLING);
+
scene->CalculateVisibleMeshes(m_rasterizer,cam);
+ m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_RENDER);
+
scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
if (scene->GetPhysicsEnvironment())
@@ -1166,15 +1188,17 @@ void KX_KetsjiEngine::AddScene(KX_Scene* scene)
void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
{
bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
-
- // if there is no activecamera, or the camera is being
- // overridden we need to construct a temporarily camera
+
+ SG_SetActiveStage(SG_STAGE_SCENE);
+
+ // if there is no activecamera, or the camera is being
+ // overridden we need to construct a temporarily camera
if (!scene->GetActiveCamera() || override_camera)
{
KX_Camera* activecam = NULL;
RAS_CameraData camdata = RAS_CameraData();
- activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata, false);
+ activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
activecam->SetName("__default__cam__");
// set transformation
@@ -1186,11 +1210,11 @@ void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
activecam->NodeSetLocalPosition(camtrans.getOrigin());
activecam->NodeSetLocalOrientation(camtrans.getBasis());
- activecam->NodeUpdateGS(0,true);
+ activecam->NodeUpdateGS(0);
} else {
activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
- activecam->NodeUpdateGS(0,true);
+ activecam->NodeUpdateGS(0);
}
scene->AddCamera(activecam);
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 7b5b77ccacf..f996f86d751 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -159,7 +159,7 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T
cam->NodeSetLocalPosition(camtrans.getOrigin());
cam->NodeSetLocalOrientation(camtrans.getBasis());
- cam->NodeUpdateGS(0,true);
+ cam->NodeUpdateGS(0);
/* setup rasterizer transformations */
ras->SetProjectionMatrix(projectionmat);
diff --git a/source/gameengine/Ketsji/KX_MotionState.cpp b/source/gameengine/Ketsji/KX_MotionState.cpp
index 15f100af915..00d9a32eb38 100644
--- a/source/gameengine/Ketsji/KX_MotionState.cpp
+++ b/source/gameengine/Ketsji/KX_MotionState.cpp
@@ -44,7 +44,7 @@ KX_MotionState::~KX_MotionState()
void KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ)
{
- MT_Point3 pos = m_node->GetWorldPosition();
+ const MT_Point3& pos = m_node->GetWorldPosition();
posX = pos[0];
posY = pos[1];
posZ = pos[2];
@@ -52,7 +52,7 @@ void KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ)
void KX_MotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
{
- MT_Vector3 scale = m_node->GetWorldScaling();
+ const MT_Vector3& scale = m_node->GetWorldScaling();
scaleX = scale[0];
scaleY = scale[1];
scaleZ = scale[2];
@@ -60,17 +60,23 @@ void KX_MotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
void KX_MotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)
{
- MT_Quaternion orn = m_node->GetWorldOrientation().getRotation();
+ MT_Quaternion& orn = m_node->GetWorldOrientation().getRotation();
quatIma0 = orn[0];
quatIma1 = orn[1];
quatIma2 = orn[2];
quatReal = orn[3];
}
+void KX_MotionState::getWorldOrientation(float* ori)
+{
+ const MT_Matrix3x3& mat = m_node->GetWorldOrientation();
+ mat.getValue(ori);
+}
+
void KX_MotionState::setWorldPosition(float posX,float posY,float posZ)
{
m_node->SetLocalPosition(MT_Point3(posX,posY,posZ));
- m_node->SetWorldPosition(MT_Point3(posX,posY,posZ));
+ //m_node->SetWorldPosition(MT_Point3(posX,posY,posZ));
}
void KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
@@ -82,13 +88,15 @@ void KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float qua
orn[3] = quatReal;
m_node->SetLocalOrientation(orn);
- m_node->SetWorldOrientation(orn);
+ //m_node->SetWorldOrientation(orn);
}
void KX_MotionState::calculateWorldTransformations()
{
- m_node->ComputeWorldTransforms(NULL);
+ //Not needed, will be done in KX_Scene::UpdateParents() after the physics simulation
+ //bool parentUpdated = false;
+ //m_node->ComputeWorldTransforms(NULL, parentUpdated);
}
diff --git a/source/gameengine/Ketsji/KX_MotionState.h b/source/gameengine/Ketsji/KX_MotionState.h
index c83af664817..7ba3ca2f85c 100644
--- a/source/gameengine/Ketsji/KX_MotionState.h
+++ b/source/gameengine/Ketsji/KX_MotionState.h
@@ -44,6 +44,7 @@ public:
virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal);
virtual void setWorldPosition(float posX,float posY,float posZ);
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
+ virtual void getWorldOrientation(float* ori);
virtual void calculateWorldTransformations();
};
diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp
index cd753210184..b9d1939e5db 100644
--- a/source/gameengine/Ketsji/KX_NearSensor.cpp
+++ b/source/gameengine/Ketsji/KX_NearSensor.cpp
@@ -127,13 +127,10 @@ CValue* KX_NearSensor::GetReplica()
}
}
- //static_cast<KX_TouchEventManager*>(m_eventmgr)->RegisterSensor(this);
- //todo: make sure replication works fine
- //>m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
- //replica->m_sumoObj->setMargin(m_Margin);
- //replica->m_sumoObj->setClientObject(replica->m_client_info);
-
- ((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
+ //Wrong: the parent object could be a child, this code works only if it is a root parent.
+ //Anyway, at this stage, the parent object is already synchronized, nothing to do.
+ //bool parentUpdated = false;
+ //((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL, parentUpdated);
replica->SynchronizeTransform();
return replica;
@@ -154,8 +151,10 @@ void KX_NearSensor::ReParent(SCA_IObject* parent)
client_info->m_sensors.push_back(this);
SCA_ISensor::ReParent(parent);
*/
- ((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
- SynchronizeTransform();
+ //Not needed, was done in GetReplica() already
+ //bool parentUpdated = false;
+ //((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL,parentUpdated);
+ //SynchronizeTransform();
SCA_ISensor::ReParent(parent);
}
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
index 355ac89a926..b9abe69633e 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.cpp
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -100,8 +100,9 @@ CValue* KX_RadarSensor::GetReplica()
//>m_sumoObj = new SM_Object(DT_NewCone(m_coneradius, m_coneheight),NULL,NULL,NULL);
//replica->m_sumoObj->setMargin(m_Margin);
//replica->m_sumoObj->setClientObject(replica->m_client_info);
-
- ((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
+ //Wrong: see KX_TouchSensor
+ //bool parentUpdated = false;
+ //((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL,parentUpdated);
replica->SynchronizeTransform();
return replica;
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
index 151270cbd68..0e7571031e8 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
@@ -57,7 +57,8 @@ New(Bone* bone
KX_BoneParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
){
MT_assert(child != NULL);
@@ -67,6 +68,8 @@ UpdateChildCoordinates(
const MT_Vector3 & child_scale = child->GetLocalScale();
const MT_Point3 & child_pos = child->GetLocalPosition();
const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
+ // we don't know if the armature has been updated or not, assume yes
+ parentUpdated = true;
// the childs world locations which we will update.
@@ -122,7 +125,7 @@ UpdateChildCoordinates(
else {
child->SetWorldFromLocalTransform();
}
-
+ child->SetModified(false);
return valid_parent_transform;
}
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
index 2a19d8a1784..c9baf228855 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
@@ -82,7 +82,8 @@ public :
bool
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
);
/**
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
index 0729ec8a902..87ff3b53911 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
@@ -51,13 +51,20 @@ New(
KX_NormalParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
){
MT_assert(child != NULL);
+ if (!parentUpdated && !child->IsModified())
+ return false;
+
+ parentUpdated = true;
+
if (parent==NULL) { /* Simple case */
child->SetWorldFromLocalTransform();
- return false;
+ child->SetModified(false);
+ return true; //false;
}
else {
// the childs world locations which we will update.
@@ -68,6 +75,7 @@ UpdateChildCoordinates(
child->SetWorldScale(p_world_scale * child->GetLocalScale());
child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation());
child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition()));
+ child->SetModified(false);
return true;
}
}
@@ -112,10 +120,15 @@ New(
KX_VertexParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
){
MT_assert(child != NULL);
+
+ if (!parentUpdated && !child->IsModified())
+ return false;
+
child->SetWorldScale(child->GetLocalScale());
if (parent)
@@ -124,7 +137,8 @@ UpdateChildCoordinates(
child->SetWorldPosition(child->GetLocalPosition());
child->SetWorldOrientation(child->GetLocalOrientation());
- return parent != NULL;
+ child->SetModified(false);
+ return true; //parent != NULL;
}
/**
@@ -172,10 +186,14 @@ New(
KX_SlowParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
){
MT_assert(child != NULL);
+ // the child will move even if the parent is not
+ parentUpdated = true;
+
const MT_Vector3 & child_scale = child->GetLocalScale();
const MT_Point3 & child_pos = child->GetLocalPosition();
const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
@@ -252,8 +270,9 @@ UpdateChildCoordinates(
child->SetWorldScale(child_w_scale);
child->SetWorldPosition(child_w_pos);
child->SetWorldOrientation(child_w_rotation);
+ child->SetModified(false);
- return parent != NULL;
+ return true; //parent != NULL;
}
/**
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
index faa650106c8..d8fb9211f21 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
@@ -71,7 +71,8 @@ public :
bool
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
);
/**
@@ -115,7 +116,8 @@ public :
bool
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
);
/**
@@ -166,7 +168,8 @@ public :
bool
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
);
/**
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 04d6bd75f92..7eed1cc387b 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -76,7 +76,9 @@
#include "NG_NetworkScene.h"
#include "PHY_IPhysicsEnvironment.h"
#include "KX_IPhysicsController.h"
+#include "PHY_IGraphicController.h"
#include "KX_BlenderSceneConverter.h"
+#include "KX_MotionState.h"
#include "BL_ShapeDeformer.h"
#include "BL_DeformableGameObject.h"
@@ -133,6 +135,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_suspendedtime = 0.0;
m_suspendeddelta = 0.0;
+ m_dbvt_culling = false;
m_activity_culling = false;
m_suspend = false;
m_isclearingZbuffer = true;
@@ -407,6 +410,13 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam
// will in any case be deleted. This ensures that the object will not try to use the node
// when it is finally deleted (see KX_GameObject destructor)
orgobj->SetSGNode(NULL);
+ PHY_IGraphicController* ctrl = orgobj->GetGraphicController();
+ if (ctrl)
+ {
+ // a graphic controller is set, we must delete it as the node will be deleted
+ delete ctrl;
+ orgobj->SetGraphicController(NULL);
+ }
}
if (node)
delete node;
@@ -485,7 +495,14 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
replicanode->AddSGController(replicacontroller);
}
}
-
+ // replicate graphic controller
+ if (orgobj->GetGraphicController())
+ {
+ PHY_IMotionState* motionstate = new KX_MotionState(newobj->GetSGNode());
+ PHY_IGraphicController* newctrl = orgobj->GetGraphicController()->GetReplica(motionstate);
+ newctrl->setNewClientInfo(newobj->getClientInfo());
+ newobj->SetGraphicController(newctrl);
+ }
return newobj;
}
@@ -792,6 +809,24 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
replica->GetSGNode()->AddChild(childreplicanode);
}
+ // At this stage all the objects in the hierarchy have been duplicated,
+ // we can update the scenegraph, we need it for the duplication of logic
+ MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
+ replica->NodeSetLocalPosition(newpos);
+
+ MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
+ replica->NodeSetLocalOrientation(newori);
+
+ // get the rootnode's scale
+ MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
+
+ // set the replica's relative scale with the rootnode's scale
+ replica->NodeSetRelativeScale(newscale);
+
+ replica->GetSGNode()->UpdateWorldData(0);
+ replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
+ replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
+
// now replicate logic
vector<KX_GameObject*>::iterator git;
for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
@@ -814,21 +849,6 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
ReplicateLogic((*git));
}
- MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
- replica->NodeSetLocalPosition(newpos);
-
- MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
- replica->NodeSetLocalOrientation(newori);
-
- // get the rootnode's scale
- MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
-
- // set the replica's relative scale with the rootnode's scale
- replica->NodeSetRelativeScale(newscale);
-
- replica->GetSGNode()->UpdateWorldData(0);
- replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
- replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
// check if there are objects with dupligroup in the hierarchy
vector<KX_GameObject*> duplilist;
for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
@@ -1163,7 +1183,6 @@ void KX_Scene::UpdateMeshTransformations()
{
KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
gameobj->GetOpenGLMatrix();
-// gameobj->UpdateNonDynas();
}
}
@@ -1298,21 +1317,46 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
}
}
+void KX_Scene::PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo)
+{
+ KX_GameObject* gameobj = objectInfo->m_gameobject;
+ if (!gameobj->GetVisible())
+ // ideally, invisible objects should be removed from the culling tree temporarily
+ return;
+ if(((CullingInfo*)cullingInfo)->m_layer && !(gameobj->GetLayer() & ((CullingInfo*)cullingInfo)->m_layer))
+ // used for shadow: object is not in shadow layer
+ return;
+
+ // make object visible
+ gameobj->SetCulled(false);
+ gameobj->UpdateBuckets(false);
+}
+
void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int layer)
{
-// FIXME: When tree is operational
-#if 1
- // do this incrementally in the future
- for (int i = 0; i < m_objectlist->GetCount(); i++)
+ bool dbvt_culling = false;
+ if (m_dbvt_culling)
{
- MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
+ // test culling through Bullet
+ PHY__Vector4 planes[5];
+ // 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());
+ CullingInfo info(layer);
+ dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5);
+ }
+ if (!dbvt_culling) {
+ // the physics engine couldn't help us, do it the hard way
+ for (int i = 0; i < m_objectlist->GetCount(); i++)
+ {
+ MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
+ }
}
-#else
- if (cam->GetFrustumCulling())
- MarkVisible(m_objecttree, rasty, cam, layer);
- else
- MarkSubTreeVisible(m_objecttree, rasty, true, cam, layer);
-#endif
}
// logic stuff
@@ -1393,7 +1437,7 @@ void KX_Scene::UpdateParents(double curtime)
for (int i=0; i<GetRootParentList()->GetCount(); i++)
{
KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
- parentobj->NodeUpdateGS(curtime,true);
+ parentobj->NodeUpdateGS(curtime);
}
}
@@ -1588,6 +1632,7 @@ PyAttributeDef KX_Scene::Attributes[] = {
KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend),
KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling),
KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),
+ KX_PYATTRIBUTE_BOOL_RO("dbvt_culling", KX_Scene, m_dbvt_culling),
KX_PYATTRIBUTE_RO_FUNCTION("__dict__", KX_Scene, pyattr_get_dir_dict),
{ NULL } //Sentinel
};
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index df51fcec8f7..9f05ddf70c2 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -85,6 +85,8 @@ class RAS_IRenderTools;
class SCA_JoystickManager;
class btCollisionShape;
class KX_BlenderSceneConverter;
+struct KX_ClientObjectInfo;
+
/**
* The KX_Scene holds all data for an independent scene. It relates
* KX_Objects to the specific objects in the modules.
@@ -92,6 +94,12 @@ class KX_BlenderSceneConverter;
class KX_Scene : public PyObjectPlus, public SCA_IScene
{
Py_Header;
+
+ struct CullingInfo {
+ int m_layer;
+ CullingInfo(int layer) : m_layer(layer) {}
+ };
+
protected:
RAS_BucketManager* m_bucketmanager;
CListValue* m_tempObjectList;
@@ -252,6 +260,11 @@ protected:
bool m_activity_culling;
/**
+ * Toggle to enable or disable culling via DBVT broadphase of Bullet.
+ */
+ bool m_dbvt_culling;
+
+ /**
* The framing settings used by this scene
*/
@@ -269,6 +282,7 @@ protected:
void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera*cam,int layer=0);
void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera*cam,int layer=0);
void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj, KX_Camera*cam, int layer=0);
+ static void PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo);
double m_suspendedtime;
double m_suspendeddelta;
@@ -530,6 +544,9 @@ public:
bool IsSuspended();
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 SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter);
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
index dcc87d614c0..e4aaef1803d 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
@@ -55,6 +55,7 @@ public:
virtual void removeConstraint(void * constraintid);
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes) { return false; }
//gamelogic callbacks
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
new file mode 100644
index 00000000000..caf18fd28ba
--- /dev/null
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
@@ -0,0 +1,112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "CcdPhysicsEnvironment.h"
+#include "CcdGraphicController.h"
+#include "btBulletDynamicsCommon.h"
+#include "MT_Point3.h"
+
+
+CcdGraphicController::CcdGraphicController (CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState) :
+ m_localAabbMin(0.f, 0.f, 0.f),
+ m_localAabbMax(0.f, 0.f, 0.f),
+ m_motionState(motionState),
+ m_phyEnv(phyEnv),
+ m_handle(NULL),
+ m_newClientInfo(NULL)
+{
+}
+
+CcdGraphicController::~CcdGraphicController()
+{
+ if (m_phyEnv)
+ m_phyEnv->removeCcdGraphicController(this);
+
+ if (m_motionState)
+ delete m_motionState;
+}
+
+void CcdGraphicController::setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ m_localAabbMin = aabbMin;
+ m_localAabbMax = aabbMax;
+ SetGraphicTransform();
+}
+
+void CcdGraphicController::setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax)
+{
+ m_localAabbMin = btVector3(aabbMin[0],aabbMin[1],aabbMin[2]);
+ m_localAabbMax = btVector3(aabbMax[0],aabbMax[1],aabbMax[2]);
+ SetGraphicTransform();
+}
+
+
+void CcdGraphicController::getAabb(btVector3& aabbMin, btVector3& aabbMax)
+{
+ btVector3 pos;
+ btVector3 scale;
+ float ori[12];
+ m_motionState->getWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]);
+ m_motionState->getWorldScaling(scale.m_floats[0],scale.m_floats[1],scale.m_floats[2]);
+ m_motionState->getWorldOrientation(ori);
+ btMatrix3x3 rot(ori[0], ori[4], ori[8],
+ ori[1], ori[5], ori[9],
+ ori[2], ori[6], ori[10]);
+
+ btVector3 localAabbMin = m_localAabbMin;
+ btVector3 localAabbMax = m_localAabbMax;
+ btVector3 tmpAabbMin = m_localAabbMin * scale;
+ btVector3 tmpAabbMax = m_localAabbMax * scale;
+
+ localAabbMin[0] = (scale.getX() >= 0.) ? tmpAabbMin[0] : tmpAabbMax[0];
+ localAabbMin[1] = (scale.getY() >= 0.) ? tmpAabbMin[1] : tmpAabbMax[1];
+ localAabbMin[2] = (scale.getZ() >= 0.) ? tmpAabbMin[2] : tmpAabbMax[2];
+ localAabbMax[0] = (scale.getX() <= 0.) ? tmpAabbMin[0] : tmpAabbMax[0];
+ localAabbMax[1] = (scale.getY() <= 0.) ? tmpAabbMin[1] : tmpAabbMax[1];
+ localAabbMax[2] = (scale.getZ() <= 0.) ? tmpAabbMin[2] : tmpAabbMax[2];
+
+ btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+ btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+
+ btMatrix3x3 abs_b = rot.absolute();
+ btVector3 center = rot*localCenter + pos;
+ btVector3 extent = abs_b*localHalfExtents;
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+}
+
+bool CcdGraphicController::SetGraphicTransform()
+{
+ if (!m_handle)
+ return false;
+ btVector3 aabbMin;
+ btVector3 aabbMax;
+ getAabb(aabbMin, aabbMax);
+ // update Aabb in broadphase
+ m_phyEnv->getCullingTree()->setAabb(m_handle,aabbMin,aabbMax,NULL);
+ return true;
+}
+
+PHY_IGraphicController* CcdGraphicController::GetReplica(class PHY_IMotionState* motionState)
+{
+ CcdGraphicController* replica = new CcdGraphicController(*this);
+ replica->m_motionState = motionState;
+ replica->m_newClientInfo = NULL;
+ replica->m_handle = NULL;
+ m_phyEnv->addCcdGraphicController(replica);
+ return replica;
+}
+
+
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h
new file mode 100644
index 00000000000..8faa0944313
--- /dev/null
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BULLET2_GRAPHICCONTROLLER_H
+#define BULLET2_GRAPHICCONTROLLER_H
+
+#include "PHY_IGraphicController.h"
+
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
+
+#include "PHY_IMotionState.h"
+#include "MT_Point3.h"
+
+class CcdPhysicsEnvironment;
+class btCollisionObject;
+
+///CcdGraphicController is a graphic object that supports view frustrum culling and occlusion
+class CcdGraphicController : public PHY_IGraphicController
+{
+public:
+ CcdGraphicController(CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState);
+
+ virtual ~CcdGraphicController();
+
+ void setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax);
+ void setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax);
+
+ PHY_IMotionState* GetMotionState() { return m_motionState; }
+ void getAabb(btVector3& aabbMin, btVector3& aabbMax);
+
+ virtual void setBroadphaseHandle(btBroadphaseProxy* handle) { m_handle = handle; }
+ virtual btBroadphaseProxy* getBroadphaseHandle() { return m_handle; }
+
+ ////////////////////////////////////
+ // PHY_IGraphicController interface
+ ////////////////////////////////////
+
+ /**
+ * Updates the Aabb based on the motion state
+ */
+ virtual bool SetGraphicTransform();
+
+ // client info for culling
+ virtual void* getNewClientInfo() { return m_newClientInfo; }
+ virtual void setNewClientInfo(void* clientinfo) { m_newClientInfo = clientinfo; }
+ virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate);
+
+private:
+ // unscaled aabb corner
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+
+ PHY_IMotionState* m_motionState;
+ CcdPhysicsEnvironment* m_phyEnv;
+ btBroadphaseProxy* m_handle;
+ void* m_newClientInfo;
+
+};
+
+#endif //BULLET2_PHYSICSCONTROLLER_H
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index bb2f53a1988..2283968801f 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -1245,6 +1245,22 @@ void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,flo
quatReal = m_worldTransform.getRotation()[3];
}
+void DefaultMotionState::getWorldOrientation(float* ori)
+{
+ *ori++ = m_worldTransform.getBasis()[0].x();
+ *ori++ = m_worldTransform.getBasis()[1].x();
+ *ori++ = m_worldTransform.getBasis()[1].x();
+ *ori++ = 0.f;
+ *ori++ = m_worldTransform.getBasis()[0].y();
+ *ori++ = m_worldTransform.getBasis()[1].y();
+ *ori++ = m_worldTransform.getBasis()[1].y();
+ *ori++ = 0.f;
+ *ori++ = m_worldTransform.getBasis()[0].z();
+ *ori++ = m_worldTransform.getBasis()[1].z();
+ *ori++ = m_worldTransform.getBasis()[1].z();
+ *ori++ = 0.f;
+}
+
void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ)
{
btVector3 pos(posX,posY,posZ);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 510454a7b63..245cde2baaa 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -544,6 +544,7 @@ class DefaultMotionState : public PHY_IMotionState
virtual void setWorldPosition(float posX,float posY,float posZ);
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
+ virtual void getWorldOrientation(float* ori);
virtual void calculateWorldTransformations();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index dd21e58bd68..cef2f2477b7 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -18,6 +18,7 @@ subject to the following restrictions:
#include "CcdPhysicsEnvironment.h"
#include "CcdPhysicsController.h"
+#include "CcdGraphicController.h"
#include <algorithm>
#include "btBulletDynamicsCommon.h"
@@ -316,8 +317,10 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec
-CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
-:m_numIterations(10),
+CcdPhysicsEnvironment::CcdPhysicsEnvironment(bool useDbvtCulling,btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
+:m_cullingCache(NULL),
+m_cullingTree(NULL),
+m_numIterations(10),
m_scalingPropagated(false),
m_numTimeSubSteps(1),
m_ccdMode(0),
@@ -350,6 +353,11 @@ m_ownDispatcher(NULL)
//m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
//m_broadphase = new btSimpleBroadphase();
m_broadphase = new btDbvtBroadphase();
+ // avoid any collision in the culling tree
+ if (useDbvtCulling) {
+ m_cullingCache = new btNullPairCache();
+ m_cullingTree = new btDbvtBroadphase(m_cullingCache);
+ }
m_filterCallback = new CcdOverlapFilterCallBack(this);
m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
@@ -364,7 +372,6 @@ m_ownDispatcher(NULL)
m_gravity = btVector3(0.f,-10.f,0.f);
m_dynamicsWorld->setGravity(m_gravity);
-
}
void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
@@ -558,6 +565,41 @@ void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ct
}
}
+void CcdPhysicsEnvironment::addCcdGraphicController(CcdGraphicController* ctrl)
+{
+ if (m_cullingTree)
+ {
+ btVector3 minAabb;
+ btVector3 maxAabb;
+ ctrl->getAabb(minAabb, maxAabb);
+
+ ctrl->setBroadphaseHandle(m_cullingTree->createProxy(
+ minAabb,
+ maxAabb,
+ INVALID_SHAPE_PROXYTYPE, // this parameter is not used
+ ctrl,
+ 0, // this object does not collision with anything
+ 0,
+ NULL, // dispatcher => this parameter is not used
+ 0));
+
+ assert(ctrl->getBroadphaseHandle());
+ }
+}
+
+void CcdPhysicsEnvironment::removeCcdGraphicController(CcdGraphicController* ctrl)
+{
+ if (m_cullingTree)
+ {
+ btBroadphaseProxy* bp = ctrl->getBroadphaseHandle();
+ if (bp)
+ {
+ m_cullingTree->destroyProxy(bp,NULL);
+ ctrl->setBroadphaseHandle(0);
+ }
+ }
+}
+
void CcdPhysicsEnvironment::beginFrame()
{
@@ -593,10 +635,10 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
(*it)->SynchronizeMotionStates(timeStep);
}
- for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
- {
- (*it)->SynchronizeMotionStates(timeStep);
- }
+ //for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
+ //{
+ // (*it)->SynchronizeMotionStates(timeStep);
+ //}
for (i=0;i<m_wrapperVehicles.size();i++)
{
@@ -1146,6 +1188,50 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
return result.m_controller;
}
+struct DbvtCullingCallback : btDbvt::ICollide
+{
+ PHY_CullingCallback m_clientCallback;
+ void* m_userData;
+
+ DbvtCullingCallback(PHY_CullingCallback clientCallback, void* userData)
+ {
+ m_clientCallback = clientCallback;
+ m_userData = userData;
+ }
+
+ void Process(const btDbvtNode* node,btScalar depth)
+ {
+ Process(node);
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
+ // the client object is a graphic controller
+ CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
+ KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)ctrl->getNewClientInfo();
+ if (info)
+ (*m_clientCallback)(info, m_userData);
+ }
+};
+
+bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes)
+{
+ if (!m_cullingTree)
+ return false;
+ DbvtCullingCallback dispatcher(callback, userData);
+ btVector3 planes_n[5];
+ btScalar planes_o[5];
+ if (nplanes > 5)
+ nplanes = 5;
+ for (int i=0; i<nplanes; i++)
+ {
+ planes_n[i].setValue(planes[i][0], planes[i][1], planes[i][2]);
+ planes_o[i] = planes[i][3];
+ }
+ btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
+ btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);
+ return true;
+}
int CcdPhysicsEnvironment::getNumContactPoints()
@@ -1211,6 +1297,13 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
if (NULL != m_broadphase)
delete m_broadphase;
+
+ if (NULL != m_cullingTree)
+ delete m_cullingTree;
+
+ if (NULL != m_cullingCache)
+ delete m_cullingCache;
+
}
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 2f1f0bb254b..ddbcbe6b4d6 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -20,6 +20,7 @@ subject to the following restrictions:
#include <vector>
#include <set>
class CcdPhysicsController;
+class CcdGraphicController;
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
@@ -40,6 +41,7 @@ class btDispatcher;
class WrapperVehicle;
class btPersistentManifold;
class btBroadphaseInterface;
+struct btDbvtBroadphase;
class btOverlappingPairCache;
class btIDebugDraw;
class PHY_IVehicle;
@@ -58,7 +60,10 @@ protected:
btIDebugDraw* m_debugDrawer;
class btDefaultCollisionConfiguration* m_collisionConfiguration;
- class btBroadphaseInterface* m_broadphase;
+ class btBroadphaseInterface* m_broadphase; // broadphase for dynamic world
+ // for culling only
+ btOverlappingPairCache* m_cullingCache;
+ struct btDbvtBroadphase* m_cullingTree; // broadphase for culling
//solver iterations
int m_numIterations;
@@ -77,7 +82,7 @@ protected:
void processFhSprings(double curTime,float timeStep);
public:
- CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
+ CcdPhysicsEnvironment(bool useDbvtCulling, btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
virtual ~CcdPhysicsEnvironment();
@@ -167,6 +172,7 @@ protected:
btTypedConstraint* getConstraintById(int constraintId);
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes);
//Methods for gamelogic collision/physics callbacks
@@ -200,7 +206,12 @@ protected:
void refreshCcdPhysicsController(CcdPhysicsController* ctrl);
+ void addCcdGraphicController(CcdGraphicController* ctrl);
+
+ void removeCcdGraphicController(CcdGraphicController* ctrl);
+
btBroadphaseInterface* getBroadphase();
+ btDbvtBroadphase* getCullingTree() { return m_cullingTree; }
btDispatcher* getDispatcher();
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index a92b1e7f4a6..fae1844d505 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -70,6 +70,7 @@ public:
}
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes) { return false; }
//gamelogic callbacks
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
index 65b07a7a0be..9942a367451 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
@@ -76,6 +76,7 @@ public:
}
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes) { return false; }
//gamelogic callbacks
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index c5cf92b553a..7ce40001af7 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -19,12 +19,42 @@ subject to the following restrictions:
-
+struct KX_ClientObjectInfo;
class PHY_Shape;
struct PHY__Vector3
{
float m_vec[4];
+
+ operator const float* () const
+ {
+ return &m_vec[0];
+ }
+ operator float* ()
+ {
+ return &m_vec[0];
+ }
+};
+
+struct PHY__Vector4
+{
+ float m_vec[4];
+ PHY__Vector4() {}
+ void setValue(const float *value)
+ {
+ m_vec[0] = *value++;
+ m_vec[1] = *value++;
+ m_vec[2] = *value++;
+ m_vec[3] = *value++;
+ }
+ void setValue(const double *value)
+ {
+ m_vec[0] = (float)(*value++);
+ m_vec[1] = (float)(*value++);
+ m_vec[2] = (float)(*value++);
+ m_vec[3] = (float)(*value++);
+ }
+
operator const float* () const
{
return &m_vec[0];
@@ -34,6 +64,7 @@ struct PHY__Vector3
return &m_vec[0];
}
};
+
//typedef float PHY__Vector3[4];
enum
@@ -59,7 +90,7 @@ enum
void *client_object1,
void *client_object2,
const PHY_CollData *coll_data);
-
+ typedef void (*PHY_CullingCallback)(KX_ClientObjectInfo* info, void* param);
/// PHY_PhysicsType enumerates all possible Physics Entities.
diff --git a/source/gameengine/Physics/common/PHY_IController.cpp b/source/gameengine/Physics/common/PHY_IController.cpp
new file mode 100644
index 00000000000..47fe9a9eea8
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "PHY_IController.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+PHY_IController::~PHY_IController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IController.h b/source/gameengine/Physics/common/PHY_IController.h
new file mode 100644
index 00000000000..45e93f9d24e
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IController.h
@@ -0,0 +1,53 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef PHY_ICONTROLLER_H
+#define PHY_ICONTROLLER_H
+
+#include "PHY_DynamicTypes.h"
+
+
+
+/**
+ PHY_IController is the abstract simplified Interface to objects
+ controlled by the physics engine. This includes the physics objects
+ and the graphics object for view frustrum and occlusion culling.
+*/
+class PHY_IController
+{
+ public:
+
+ virtual ~PHY_IController();
+ // clientinfo for raycasts for example
+ virtual void* getNewClientInfo()=0;
+ virtual void setNewClientInfo(void* clientinfo)=0;
+
+};
+
+#endif //PHY_ICONTROLLER_H
+
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.cpp b/source/gameengine/Physics/common/PHY_IGraphicController.cpp
new file mode 100644
index 00000000000..4dccecd3d29
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "PHY_IGraphicController.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+PHY_IGraphicController::~PHY_IGraphicController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.h b/source/gameengine/Physics/common/PHY_IGraphicController.h
new file mode 100644
index 00000000000..36b8a978e87
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.h
@@ -0,0 +1,56 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef PHY_IGRAPHICCONTROLLER_H
+#define PHY_IGRAPHICCONTROLLER_H
+
+#include "PHY_IController.h"
+
+
+
+/**
+ PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+ It contains the IMotionState and IDeformableMesh Interfaces.
+*/
+class PHY_IGraphicController : public PHY_IController
+{
+
+ public:
+
+ virtual ~PHY_IGraphicController();
+ /**
+ SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
+ virtual bool SetGraphicTransform()=0;
+
+ virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate) {return 0;}
+
+};
+
+#endif //PHY_IGRAPHICCONTROLLER_H
+
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
index d759b0aeff4..64bb810ee7c 100644
--- a/source/gameengine/Physics/common/PHY_IMotionState.h
+++ b/source/gameengine/Physics/common/PHY_IMotionState.h
@@ -43,6 +43,8 @@ class PHY_IMotionState
virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0;
+ // ori = array 12 floats, [0..3] = first column + 0, [4..7] = second colum, [8..11] = third column
+ virtual void getWorldOrientation(float* ori)=0;
virtual void setWorldPosition(float posX,float posY,float posZ)=0;
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0;
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index 884e14cfb5a..6cba6fa88af 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -29,7 +29,7 @@
#ifndef PHY_IPHYSICSCONTROLLER_H
#define PHY_IPHYSICSCONTROLLER_H
-#include "PHY_DynamicTypes.h"
+#include "PHY_IController.h"
@@ -37,7 +37,7 @@
PHY_IPhysicsController is the abstract simplified Interface to a physical object.
It contains the IMotionState and IDeformableMesh Interfaces.
*/
-class PHY_IPhysicsController
+class PHY_IPhysicsController : public PHY_IController
{
public:
@@ -82,9 +82,7 @@ class PHY_IPhysicsController
// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
virtual void setRigidBody(bool rigid)=0;
- // clientinfo for raycasts for example
- virtual void* getNewClientInfo()=0;
- virtual void setNewClientInfo(void* clientinfo)=0;
+
virtual PHY_IPhysicsController* GetReplica() {return 0;}
virtual void calcXform() =0;
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 226ba3a7e74..5edafe6b51e 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -142,6 +142,8 @@ class PHY_IPhysicsEnvironment
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0;
+ //culling based on physical broad phase
+ virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber) = 0;
//Methods for gamelogic collision/physics callbacks
//todo:
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
index f7938bb62e6..ec290f89d9e 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
@@ -148,6 +148,10 @@ void RAS_BucketManager::RenderAlphaBuckets(
while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools))
sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms));
+
+ // make this mesh slot culled automatically for next frame
+ // it will be culled out by frustrum culling
+ sit->m_ms->SetCulled(true);
}
rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
@@ -170,6 +174,10 @@ void RAS_BucketManager::RenderSolidBuckets(
while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools))
(*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit);
+
+ // make this mesh slot culled automatically for next frame
+ // it will be culled out by frustrum culling
+ mit->SetCulled(true);
}
}
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h
index 610bd13ff12..0a226ac30f9 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.h
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.h
@@ -163,6 +163,13 @@ struct RAS_FrameFrustum
float x2,y2;
};
+/* must match R_CULLING_... from DNA_scene_types.h */
+enum RAS_CullingMode
+{
+ RAS_CULLING_DBVT = 0,
+ RAS_CULLING_NORMAL,
+ RAS_CULLING_NONE
+};
/**
* @section RAS_FramingManager
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
index 475f01d549a..211770318ae 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
@@ -156,6 +156,7 @@ public:
bool Join(RAS_MeshSlot *target, MT_Scalar distance);
bool Equals(RAS_MeshSlot *target);
bool IsCulled();
+ void SetCulled(bool culled) { m_bCulled = culled; }
};
/* Used by RAS_MeshObject, to point to it's slots in a bucket */
diff --git a/source/gameengine/SceneGraph/SG_BBox.cpp b/source/gameengine/SceneGraph/SG_BBox.cpp
index a44262d04f7..66fcc5c7408 100644
--- a/source/gameengine/SceneGraph/SG_BBox.cpp
+++ b/source/gameengine/SceneGraph/SG_BBox.cpp
@@ -188,6 +188,13 @@ void SG_BBox::getaa(MT_Point3 *box, const MT_Transform &world) const
*box++ = max;
}
+void SG_BBox::getmm(MT_Point3 *box, const MT_Transform &world) const
+{
+ const MT_Point3 min(world(m_min)), max(world(m_max));
+ *box++ = min;
+ *box++ = max;
+}
+
void SG_BBox::split(SG_BBox &left, SG_BBox &right) const
{
MT_Scalar sizex = m_max[0] - m_min[0];
diff --git a/source/gameengine/SceneGraph/SG_BBox.h b/source/gameengine/SceneGraph/SG_BBox.h
index b7e8ff65865..c39ad268e25 100644
--- a/source/gameengine/SceneGraph/SG_BBox.h
+++ b/source/gameengine/SceneGraph/SG_BBox.h
@@ -122,6 +122,8 @@ public:
*/
void getaa(MT_Point3 *box, const MT_Transform &world) const;
+ void getmm(MT_Point3 *box, const MT_Transform &world) const;
+
void split(SG_BBox &left, SG_BBox &right) const;
friend class SG_Tree;
diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp
index d0bdac5c8f0..fbab4032a10 100644
--- a/source/gameengine/SceneGraph/SG_IObject.cpp
+++ b/source/gameengine/SceneGraph/SG_IObject.cpp
@@ -33,6 +33,8 @@
#include <config.h>
#endif
+SG_Stage gSG_Stage = SG_STAGE_UNKNOWN;
+
SG_IObject::
SG_IObject(
void* clientobj,
diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
index 7f6bdfbbb1c..9012b532059 100644
--- a/source/gameengine/SceneGraph/SG_IObject.h
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -31,6 +31,36 @@
#include <vector>
+// used for debugging: stage of the game engine main loop at which a Scenegraph modification is done
+enum SG_Stage
+{
+ SG_STAGE_UNKNOWN = 0,
+ SG_STAGE_NETWORK,
+ SG_STAGE_NETWORK_UPDATE,
+ SG_STAGE_PHYSICS1,
+ SG_STAGE_PHYSICS1_UPDATE,
+ SG_STAGE_CONTROLLER,
+ SG_STAGE_CONTROLLER_UPDATE,
+ SG_STAGE_ACTUATOR,
+ SG_STAGE_ACTUATOR_UPDATE,
+ SG_STAGE_PHYSICS2,
+ SG_STAGE_PHYSICS2_UPDATE,
+ SG_STAGE_SCENE,
+ SG_STAGE_RENDER,
+ SG_STAGE_CONVERTER,
+ SG_STAGE_CULLING,
+ SG_STAGE_MAX
+};
+
+extern SG_Stage gSG_Stage;
+
+inline void SG_SetActiveStage(SG_Stage stage)
+{
+ gSG_Stage = stage;
+}
+
+
+
class SG_Controller;
class SG_IObject;
diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp
index 8de7ac83477..64d9019c86a 100644
--- a/source/gameengine/SceneGraph/SG_Node.cpp
+++ b/source/gameengine/SceneGraph/SG_Node.cpp
@@ -219,18 +219,19 @@ void SG_Node::RemoveChild(SG_Node* child)
-void SG_Node::UpdateWorldData(double time)
+void SG_Node::UpdateWorldData(double time, bool parentUpdated)
{
//if (!GetSGParent())
// return;
- if (UpdateSpatialData(GetSGParent(),time))
+ if (UpdateSpatialData(GetSGParent(),time,parentUpdated))
+ // to update the
ActivateUpdateTransformCallback();
// update children's worlddata
for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
{
- (*it)->UpdateWorldData(time);
+ (*it)->UpdateWorldData(time, parentUpdated);
}
}
diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h
index ffaaad861e2..29943653a81 100644
--- a/source/gameengine/SceneGraph/SG_Node.h
+++ b/source/gameengine/SceneGraph/SG_Node.h
@@ -175,7 +175,8 @@ public:
void
UpdateWorldData(
- double time
+ double time,
+ bool parentUpdated=false
);
/**
diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h
index 6507cb98519..8f45df09b27 100644
--- a/source/gameengine/SceneGraph/SG_ParentRelation.h
+++ b/source/gameengine/SceneGraph/SG_ParentRelation.h
@@ -69,7 +69,8 @@ public :
bool
UpdateChildCoordinates(
SG_Spatial * child,
- const SG_Spatial * parent
+ const SG_Spatial * parent,
+ bool& parentUpdated
) = 0;
virtual
diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp
index 99aeb3e72ee..2f3176816c6 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.cpp
+++ b/source/gameengine/SceneGraph/SG_Spatial.cpp
@@ -55,7 +55,8 @@ SG_Spatial(
m_parent_relation (NULL),
m_bbox(MT_Point3(-1.0, -1.0, -1.0), MT_Point3(1.0, 1.0, 1.0)),
- m_radius(1.0)
+ m_radius(1.0),
+ m_modified(true)
{
}
@@ -101,6 +102,7 @@ SetParentRelation(
){
delete (m_parent_relation);
m_parent_relation = relation;
+ m_modified = true;
}
@@ -114,7 +116,8 @@ SetParentRelation(
SG_Spatial::
UpdateSpatialData(
const SG_Spatial *parent,
- double time
+ double time,
+ bool& parentUpdated
){
bool bComputesWorldTransform = false;
@@ -135,14 +138,14 @@ UpdateSpatialData(
// our world coordinates.
if (!bComputesWorldTransform)
- bComputesWorldTransform = ComputeWorldTransforms(parent);
+ bComputesWorldTransform = ComputeWorldTransforms(parent, parentUpdated);
return bComputesWorldTransform;
}
-bool SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent)
+bool SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated)
{
- return m_parent_relation->UpdateChildCoordinates(this,parent);
+ return m_parent_relation->UpdateChildCoordinates(this,parent,parentUpdated);
}
/**
@@ -166,6 +169,7 @@ RelativeTranslate(
m_localPosition += trans;
}
}
+ m_modified = true;
}
void
@@ -174,6 +178,7 @@ SetLocalPosition(
const MT_Point3& trans
){
m_localPosition = trans;
+ m_modified = true;
}
void
@@ -194,6 +199,7 @@ RelativeScale(
const MT_Vector3& scale
){
m_localScaling = m_localScaling * scale;
+ m_modified = true;
}
void
@@ -202,6 +208,7 @@ SetLocalScale(
const MT_Vector3& scale
){
m_localScaling = scale;
+ m_modified = true;
}
@@ -229,6 +236,7 @@ RelativeRotate(
rot
:
(GetWorldOrientation().inverse() * rot * GetWorldOrientation()));
+ m_modified = true;
}
void
@@ -236,6 +244,7 @@ SG_Spatial::
SetLocalOrientation(const MT_Matrix3x3& rot)
{
m_localRotation = rot;
+ m_modified = true;
}
diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h
index 6ccec2aa9c1..c2ed80d21b2 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.h
+++ b/source/gameengine/SceneGraph/SG_Spatial.h
@@ -61,7 +61,7 @@ protected:
SG_BBox m_bbox;
MT_Scalar m_radius;
-
+ bool m_modified;
public:
@@ -180,7 +180,7 @@ public:
MT_Transform GetWorldTransform() const;
- bool ComputeWorldTransforms( const SG_Spatial *parent);
+ bool ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated);
/**
* Bounding box functions.
@@ -193,9 +193,14 @@ public:
MT_Scalar Radius() const { return m_radius; }
void SetRadius(MT_Scalar radius) { m_radius = radius; }
+ bool IsModified() { return m_modified; }
protected:
friend class SG_Controller;
+ friend class KX_BoneParentRelation;
+ friend class KX_VertexParentRelation;
+ friend class KX_SlowParentRelation;
+ friend class KX_NormalParentRelation;
/**
* Protected constructor this class is not
@@ -223,8 +228,10 @@ protected:
bool
UpdateSpatialData(
const SG_Spatial *parent,
- double time
+ double time,
+ bool& parentUpdated
);
+ void SetModified(bool modified) { m_modified = modified; }
};