diff options
54 files changed, 990 insertions, 151 deletions
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 457e26b1dc0..b6231a8fda6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -350,12 +350,13 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, for (int i=0;i<clampedSimulationSteps;i++) { internalSingleStepSimulation(fixedTimeStep); - synchronizeMotionStates(); + //for Blender, no need to synchronize here, it is done in blender anyway + //synchronizeMotionStates(); } } - - synchronizeMotionStates(); + //else + // synchronizeMotionStates(); clearForces(); diff --git a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj index 9fa3751c436..336c40ef0e8 100644 --- a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj +++ b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj @@ -166,7 +166,7 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
- AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib"
+ AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib"
OutputFile="..\..\..\..\bin\blenderplayer.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
diff --git a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj index 8c22733b4e9..c941704ce23 100644 --- a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj +++ b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj @@ -431,6 +431,10 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
+ RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdGraphicController.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdPhysicsController.cpp"
>
</File>
@@ -445,6 +449,10 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
+ RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdGraphicController.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdPhysicsController.h"
>
</File>
diff --git a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj index 582aed500ac..5441c5bd4f1 100644 --- a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj +++ b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj @@ -4,6 +4,7 @@ Version="9,00"
Name="PHY_Physics"
ProjectGUID="{E109F1A5-FDD3-4F56-A1C4-96867EEA4C5B}"
+ RootNamespace="PHY_Physics"
TargetFrameworkVersion="131072"
>
<Platforms>
@@ -470,6 +471,14 @@ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
+ RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IGraphicController.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.cpp"
>
</File>
@@ -495,6 +504,14 @@ >
</File>
<File
+ RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IController.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IGraphicController.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.h"
>
</File>
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 2e89ce3f805..594d18f1ca7 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -106,6 +106,7 @@ World *add_world(char *name) wrld->ao_approx_error= 0.25f; wrld->physicsEngine= WOPHY_BULLET;//WOPHY_SUMO; Bullet by default + wrld->mode = WO_DBVT_CAMERA_CULLING; // DBVT culling by default wrld->preview = NULL; return wrld; diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index ab7e25190ad..a51e9704be2 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -84,6 +84,8 @@ typedef struct World { * bit 1: Do stars * bit 2: (reserved) depth of field * bit 3: (gameengine): Activity culling is enabled. + * bit 4: ambient occlusion + * bit 5: (gameengine) : enable Bullet DBVT tree for view frustrum culling */ short mode; int physicsEngine; /* here it's aligned */ @@ -133,6 +135,7 @@ typedef struct World { #define WO_DOF 4 #define WO_ACTIVITY_CULLING 8 #define WO_AMB_OCC 16 +#define WO_DBVT_CAMERA_CULLING 32 /* aomix */ #define WO_AOADD 0 diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index fe4649f31f4..e68c86349ce 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2181,7 +2181,7 @@ static void world_panel_mistaph(World *wrld) uiSetButLock(wrld->id.lib!=0, ERROR_LIBDATA_MESSAGE); #if GAMEBLENDER == 1 - uiDefButI(block, MENU, 1, + uiDefButI(block, MENU, B_REDR, #ifdef USE_ODE "Physics %t|None %x0|Sumo %x2|Ode %x4 |Bullet %x5", #else @@ -2198,6 +2198,8 @@ static void world_panel_mistaph(World *wrld) /* Gravitation for the game worlds */ uiDefButF(block, NUMSLI,0, "Grav ", 150,180,150,19, &(wrld->gravity), 0.0, 25.0, 0, 0, "Sets the gravitation constant of the game world"); + if (wrld->physicsEngine == WOPHY_BULLET) + uiDefButBitS(block, TOG, WO_DBVT_CAMERA_CULLING, 0, "DBVT culling", 10,160,140,19, &wrld->mode, 0, 0, 0, 0, "Toggles use of optimized Bullet DBVT tree for camera culling"); #endif uiBlockSetCol(block, TH_BUT_SETTING1); 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; } }; |