BGE Scenegraph and View frustrum culling improvement.
authorBenoit Bolsee <benoit.bolsee@online.be>
Tue, 7 Apr 2009 22:14:06 +0000 (22:14 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Tue, 7 Apr 2009 22:14:06 +0000 (22:14 +0000)
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.

54 files changed:
extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj
projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj
projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj
source/blender/blenkernel/intern/world.c
source/blender/makesdna/DNA_world_types.h
source/blender/src/buttons_shading.c
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
source/gameengine/Ketsji/KX_Camera.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_Light.cpp
source/gameengine/Ketsji/KX_MotionState.cpp
source/gameengine/Ketsji/KX_MotionState.h
source/gameengine/Ketsji/KX_NearSensor.cpp
source/gameengine/Ketsji/KX_RadarSensor.cpp
source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
source/gameengine/Ketsji/KX_SG_NodeRelationships.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
source/gameengine/Physics/Bullet/CcdGraphicController.cpp [new file with mode: 0644]
source/gameengine/Physics/Bullet/CcdGraphicController.h [new file with mode: 0644]
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
source/gameengine/Physics/common/PHY_DynamicTypes.h
source/gameengine/Physics/common/PHY_IController.cpp [new file with mode: 0644]
source/gameengine/Physics/common/PHY_IController.h [new file with mode: 0644]
source/gameengine/Physics/common/PHY_IGraphicController.cpp [new file with mode: 0644]
source/gameengine/Physics/common/PHY_IGraphicController.h [new file with mode: 0644]
source/gameengine/Physics/common/PHY_IMotionState.h
source/gameengine/Physics/common/PHY_IPhysicsController.h
source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
source/gameengine/Rasterizer/RAS_BucketManager.cpp
source/gameengine/Rasterizer/RAS_FramingManager.h
source/gameengine/Rasterizer/RAS_MaterialBucket.h
source/gameengine/SceneGraph/SG_BBox.cpp
source/gameengine/SceneGraph/SG_BBox.h
source/gameengine/SceneGraph/SG_IObject.cpp
source/gameengine/SceneGraph/SG_IObject.h
source/gameengine/SceneGraph/SG_Node.cpp
source/gameengine/SceneGraph/SG_Node.h
source/gameengine/SceneGraph/SG_ParentRelation.h
source/gameengine/SceneGraph/SG_Spatial.cpp
source/gameengine/SceneGraph/SG_Spatial.h

index 457e26b1dc08fc3b9e15cf84558a21882b205f0d..b6231a8fda6ec3580264253c3a57fd457345f663 100644 (file)
@@ -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();
 
index 9fa3751c43612afa43c30a661f15167e7b6b3f13..336c40ef0e89bcc543eacd2e7619dbe454737aef 100644 (file)
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386"\r
-                               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"\r
+                               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"\r
                                OutputFile="..\..\..\..\bin\blenderplayer.exe"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
index 8c22733b4e94a4f2ff176bcab0ac3cb92925710f..c941704ce230301f4fe409e21b1acab499d77ffb 100644 (file)
                        Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
                        UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
                        >\r
+                       <File\r
+                               RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdGraphicController.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdPhysicsController.cpp"\r
                                >\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
                        >\r
+                       <File\r
+                               RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdGraphicController.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdPhysicsController.h"\r
                                >\r
index 582aed500acedcf56daa236698130ec887b8ba13..5441c5bd4f1147518c49510eec163baaeee1af8a 100644 (file)
@@ -4,6 +4,7 @@
        Version="9,00"\r
        Name="PHY_Physics"\r
        ProjectGUID="{E109F1A5-FDD3-4F56-A1C4-96867EEA4C5B}"\r
+       RootNamespace="PHY_Physics"\r
        TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                        Name="Source Files"\r
                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
                        >\r
+                       <File\r
+                               RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IController.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IGraphicController.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.cpp"\r
                                >\r
                                RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_DynamicTypes.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IController.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IGraphicController.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.h"\r
                                >\r
index 2e89ce3f80536010e2bdea24b317391ef151ec4e..594d18f1ca7c30ebc9e6323390cb7a5ca0e9e1b3 100644 (file)
@@ -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;
index ab7e25190adcd0c93de9a329a10a7b864289fde3..a51e9704be2c2d5a3db6ff1c9ed6cf2dd1e26cba 100644 (file)
@@ -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
index fe4649f31f431e23e9babde753bdad908fd23f0d..e68c86349ce485de845c596e58525af484bf04af 100644 (file)
@@ -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);
index d74243b0eb09cbb9cf9a08dfefe36421463d1c0e..3c77f122758284adfdbf8b5c022f404ee4710971 100644 (file)
@@ -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)
index 97a0819147c8cf060e3e404936c7fa7df2cb7cad..b0c676a410de6954e4318ffb8ffb0e28cc02ae9d 100644 (file)
@@ -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);
                                }
                        }
                }
index 062e9f7df503ac14a7e8da81dd9db1d3262f9469..435b2b5db19f0641a398ce91f470ba92697bb12e 100644 (file)
@@ -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)
index 6ed2150637206d5ee9f096f339ee40e5dfad0972..4accd4bc2f1035a4367d2023b5ded5c23cdf70aa 100644 (file)
@@ -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 } ;
index 7f99a565769dbc65b6b36b786f621aa304c292a6..339a955702aa4440c530a25c212ceb7475ab3392 100644 (file)
@@ -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;
        }
 
index bc6b60102d6b50a64870a3d91a1d0c46eeace2a7..9c7dda5e3947b7434c7e4a10ffc954463bb01f5e 100644 (file)
@@ -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;
@@ -350,6 +352,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 
@@ -524,13 +538,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
         */ 
index 97b4213b8bd4e9a5dcc93c893c424333b6fa819a..70ae0e4b937d96c8573fb558d2e3ebdff5fa8333 100644 (file)
@@ -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);
index 7b5b77ccacfce2ff689aa032c7bb7d08714f328c..f996f86d751239d1d966093c4a8972d51cfb085a 100644 (file)
@@ -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);
index 15f100af915745f2122a3c3650daed5fa6314746..00d9a32eb38149189f727ad810cea64f7f4750a6 100644 (file)
@@ -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);
 }
 
  
index c83af66481738b421f7103b71308432bc0c1c046..7ba3ca2f85c222c85a09c0ff880975cc57abc7a7 100644 (file)
@@ -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();
 };
index cd7532101845625f434145e64c1a67cfbbed87db..b9d1939e5db0868fa96cded948934e46bbb2146e 100644 (file)
@@ -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);
 }
 
index 355ac89a926a4f1d579f30ea1a3f6d5272d65e6f..b9abe69633e6483e90af8179df680e768a8c098f 100644 (file)
@@ -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;
index 151270cbd68fd2e662f9a6564b34a2fafd4f4191..0e7571031e818dcfe57aade39d969d7001f6f0f9 100644 (file)
@@ -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;
 }
 
index 2a19d8a1784282743f8db849f4211fcf0f2a4195..c9baf2288557a0d057d6e162f6123208ca59e0b3 100644 (file)
@@ -82,7 +82,8 @@ public :
                bool
        UpdateChildCoordinates(
                SG_Spatial * child,
-               const SG_Spatial * parent
+               const SG_Spatial * parent,
+               bool& parentUpdated
        );
 
        /**
index 0729ec8a9025badf3d9f6a3202533ce41ad70865..87ff3b539118b1874fbb66c05569fe06d89cc48e 100644 (file)
@@ -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;
 }
 
 /** 
index faa650106c800284de1e3d492ed4906de8182435..d8fb9211f214ff4d74c97d7deeffafe6f757a92b 100644 (file)
@@ -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     
        );
 
        /** 
index 04d6bd75f92b3b428511988806e4f454101bc537..7eed1cc387b14bbbbc68e73f3a1c6713a112c5a6 100644 (file)
@@ -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
 };
index df51fcec8f7ca19f52bd33ffb576e5ed920f7292..9f05ddf70c27c5a3f37c9649a29ca444cf0a3ac1 100644 (file)
@@ -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;
@@ -251,6 +259,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);
 
index dcc87d614c0f1e503fbba9aa411f2edb20c56bb7..e4aaef1803d06a9c0818c8ac1b1d084ed3681c9d 100644 (file)
@@ -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 (file)
index 0000000..caf18fd
--- /dev/null
@@ -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 (file)
index 0000000..8faa094
--- /dev/null
@@ -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
index bb2f53a19883c90d069a160facc2133f1ae397fa..2283968801f7c686a52bbb84f015f1013dd14873 100644 (file)
@@ -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);
index 510454a7b630b61c41e0913dd3210fbbb74430fc..245cde2baaa67e2932affb9588fc016f8e3070d6 100644 (file)
@@ -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();
                
index dd21e58bd68a6f24c86ccc512afee65796e8b4d6..cef2f2477b73fbd19d636281f1425d91d2d0d9e4 100644 (file)
@@ -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;
+
 }
 
 
index 2f1f0bb254b7f8e8c16242871a271b09b581ed57..ddbcbe6b4d649bac4b006f7b1c6b0463edb3b62e 100644 (file)
@@ -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();
                
index a92b1e7f4a6d5734d14c40cabb13cab3f534d089..fae1844d50548c458133718630e9736a19e7d5fd 100644 (file)
@@ -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
index 65b07a7a0bee5a68f437590f27cb6e184c795c41..9942a367451665fb50d9b459226ba3c871cea64c 100644 (file)
@@ -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
index c5cf92b553ae171c78058349ccb70f77563179f6..7ce40001af75dca5c756982e375581cafecb1d89 100644 (file)
@@ -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 (file)
index 0000000..47fe9a9
--- /dev/null
@@ -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 (file)
index 0000000..45e93f9
--- /dev/null
@@ -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 (file)
index 0000000..4dccecd
--- /dev/null
@@ -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 (file)
index 0000000..36b8a97
--- /dev/null
@@ -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
+
index d759b0aeff4a1e775698da2c1639289142537ba5..64bb810ee7c6420f678047f29c3dded94de62d61 100644 (file)
@@ -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;
index 884e14cfb5af124482a068ca0fae4311cb87f547..6cba6fa88afb47d497d7cb9c5bc217734c113846 100644 (file)
@@ -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;
index 226ba3a7e744e2c3f9d1eb0c14d0e62347d202fc..5edafe6b51e69a1d235a7be5c4c44a99cebca1e6 100644 (file)
@@ -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:
index f7938bb62e67e28b1ad5800f13487e67730b25dc..ec290f89d9ec8a5f67f687bb27ab150bb96de74b 100644 (file)
@@ -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);
                }
        }
        
index 610bd13ff122a19f80da379689987e736a3069de..0a226ac30f9e1d4d0c66ada6c9f5c5b8d646aa52 100644 (file)
@@ -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
index 475f01d549a6234772766cade873ec31acbe73c0..211770318aeb275c2c386cb04ec28baf82d99e0d 100644 (file)
@@ -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 */
index a44262d04f756efbda6ff5e348e4c9a26becb1e2..66fcc5c740897c61db8301613ce6de5af424f4fd 100644 (file)
@@ -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];
index b7e8ff6586521dab81583cba3e14812b2f2ae359..c39ad268e25bcd45fc9b37f5261ddc98553149fb 100644 (file)
@@ -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;
index d0bdac5c8f0215b1a09e28c5ef0713bc8617cad3..fbab4032a10a88c5d02c1c3828df55f7713da68e 100644 (file)
@@ -33,6 +33,8 @@
 #include <config.h>
 #endif
 
+SG_Stage gSG_Stage = SG_STAGE_UNKNOWN;
+
 SG_IObject::
 SG_IObject(
        void* clientobj,
index 7f6bdfbbb1cb29b22d12700b51990eeb1bfe4dac..9012b532059b492e09d76f2a46bd08de8abfe69a 100644 (file)
 
 #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;
 
index 8de7ac834779605b5b7a13fa34d10ff9233a6aeb..64d9019c86a0c5c54090cf8172b51baa6e2ff964 100644 (file)
@@ -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);
        }
 }
 
index ffaaad861e2db097ceb0cde59e178631a2f19da5..29943653a81b71bbf70cb4a98f60455e54aac891 100644 (file)
@@ -175,7 +175,8 @@ public:
 
                void            
        UpdateWorldData(
-               double time
+               double time,
+               bool parentUpdated=false
        );
 
        /**
index 6507cb98519d245210555a2794edb8065f08b189..8f45df09b27b72fb40520e8a110d228f89b8a236 100644 (file)
@@ -69,7 +69,8 @@ public :
                bool
        UpdateChildCoordinates(
                SG_Spatial * child,
-               const SG_Spatial * parent
+               const SG_Spatial * parent,
+               bool& parentUpdated
        ) = 0;
 
        virtual 
index 99aeb3e72eeb6ff7585d92926ee945f3a1b0f915..2f3176816c63761430745f081165f54224484d1a 100644 (file)
@@ -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;
 }
 
 
index 6ccec2aa9c107a50004b951e3d608ded7b0cb5f8..c2ed80d21b2e267c88ffc7ef4d0c9c055e0b1dcb 100644 (file)
@@ -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; }
 
 };