Speed up the physics engine: hook the SOLID broad phase, so we can either reject...
authorKester Maddock <Christopher.Maddock.1@uni.massey.ac.nz>
Sat, 6 Nov 2004 04:58:10 +0000 (04:58 +0000)
committerKester Maddock <Christopher.Maddock.1@uni.massey.ac.nz>
Sat, 6 Nov 2004 04:58:10 +0000 (04:58 +0000)
20 files changed:
source/gameengine/Ketsji/KX_ClientObjectInfo.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
source/gameengine/Ketsji/KX_NearSensor.cpp
source/gameengine/Ketsji/KX_RadarSensor.cpp
source/gameengine/Ketsji/KX_RaySensor.cpp
source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
source/gameengine/Ketsji/KX_TouchEventManager.cpp
source/gameengine/Ketsji/KX_TouchEventManager.h
source/gameengine/Ketsji/KX_TouchSensor.cpp
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h

index 0ef1a1b86fe849c372ecf715edca2c268912aac6..237ec137a1c54a90395c294f85a3bc91774acb89 100644 (file)
 #ifndef __KX_CLIENTOBJECT_INFO_H
 #define __KX_CLIENTOBJECT_INFO_H
 
+#include <SM_Object.h>
+
+#include <list>
+
+class SCA_ISensor;
+class KX_GameObject;
 /**
  * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks
  */
-struct KX_ClientObjectInfo
+struct KX_ClientObjectInfo : public SM_ClientObject
 {
        enum clienttype {
                STATIC,
@@ -44,15 +50,32 @@ struct KX_ClientObjectInfo
                RADAR,
                NEAR
        }               m_type;
-       void*           m_clientobject;
+       KX_GameObject*  m_gameobject;
        void*           m_auxilary_info;
+       std::list<SCA_ISensor*> m_sensors;
 public:
-       KX_ClientObjectInfo(void *clientobject, clienttype type = STATIC, void *auxilary_info = NULL) :
+       KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) :
+               SM_ClientObject(),
                m_type(type),
-               m_clientobject(clientobject),
+               m_gameobject(gameobject),
                m_auxilary_info(auxilary_info)
        {}
        
+       KX_ClientObjectInfo(const KX_ClientObjectInfo &copy)
+               : SM_ClientObject(copy),
+                 m_type(copy.m_type),
+                 m_gameobject(copy.m_gameobject),
+                 m_auxilary_info(copy.m_auxilary_info)
+       {
+       }
+       
+       virtual ~KX_ClientObjectInfo() {}
+       
+       virtual bool hasCollisionCallback() 
+       {
+               return m_sensors.size() != 0;
+       }
+       
        bool isActor() { return m_type <= ACTOR; }
 };
 
index 67148114de85a6d30507743792d749af4deafa8d..896da63ea040ebed1744773edfe7d908df7a5796 100644 (file)
@@ -188,7 +188,7 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica)
        replica->m_pPhysicsController1 = NULL;
        replica->m_pSGNode = NULL;
        replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
-       replica->m_pClient_info->m_clientobject = replica;
+       replica->m_pClient_info->m_gameobject = replica;
 }
 
 
index fbe2fd9c6cd0087b14f2dc2d0c6bdd095ed01af9..04777bf4a36a64833723b2876f63bd77abe804fb 100644 (file)
@@ -315,17 +315,13 @@ void KX_KetsjiEngine::NextFrame()
        m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
 
        double curtime;
+       double localtime = m_previoustime;
        if (m_bFixedTime)
-       {
-               m_deltatime = 1.0/m_ticrate;
                curtime = m_previoustime + m_deltatime;
-       }
        else
-       {
                curtime = m_kxsystem->GetTimeInSeconds();
-               m_deltatime += curtime - m_previoustime;
-               m_previoustime = curtime;
-       }
+       m_deltatime += curtime - m_previoustime;
+       m_previoustime = curtime;
 
        // Compute the number of logic frames to do each update (fixed tic bricks)
        int frames = (int) (m_deltatime*m_ticrate);
@@ -337,13 +333,17 @@ void KX_KetsjiEngine::NextFrame()
        
        if (!frames)
        {
-               for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+               for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
                // for each scene, call the proceed functions
                {
                        KX_Scene* scene = *sceneit;
        
                        if (!scene->IsSuspended())
                        {
+                               // set Python hooks for each scene
+                               PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
+                               PHY_SetActiveScene(scene);
+                               
                                // Do some cleanup work for this logic frame
                                m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
                                scene->LogicUpdateFrame(curtime, false);
@@ -356,7 +356,6 @@ void KX_KetsjiEngine::NextFrame()
                                // many iterations of the physics solver.
                                m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
                                scene->GetPhysicsEnvironment()->proceed(curtime);
-               
                                // Update scenegraph after physics step. This maps physics calculations
                                // into node positions.         
                                m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
@@ -371,7 +370,8 @@ void KX_KetsjiEngine::NextFrame()
        
        while (frames--)
        {
-               for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+               localtime += 1.0/m_ticrate;
+               for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
                // for each scene, call the proceed functions
                {
                        KX_Scene* scene = *sceneit;
@@ -385,6 +385,10 @@ void KX_KetsjiEngine::NextFrame()
        
                        if (!scene->IsSuspended())
                        {
+                               m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
+                               scene->GetPhysicsEnvironment()->endFrame();
+                               scene->GetPhysicsEnvironment()->beginFrame();
+                       
                                m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
                                scene->GetNetworkScene()->proceed(curtime);
        
@@ -416,7 +420,6 @@ void KX_KetsjiEngine::NextFrame()
                                // many iterations of the physics solver.
                                m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
                                scene->GetPhysicsEnvironment()->proceed(curtime);
-               
                                // Update scenegraph after physics step. This maps physics calculations
                                // into node positions.         
                                m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
index 84b08058ecc5448801bce37af3cefb162bd6a37c..9380ef6f2fae78a39ce36c3257bf977c7f4d6b0d 100644 (file)
@@ -42,7 +42,6 @@
 #endif
 
 #include "MT_Point3.h"
-#include "KX_ClientObjectInfo.h"
 #include "RAS_FramingManager.h"
 #include "RAS_ICanvas.h"
 #include "RAS_IRasterizer.h"
 #include "KX_Camera.h"
 #include "KX_MouseFocusSensor.h"
 
-#include "KX_ClientObjectInfo.h"
 #include "SM_Object.h"
 #include "SM_Scene.h"
 #include "SumoPhysicsEnvironment.h"
 #include "KX_SumoPhysicsController.h"
+#include "KX_ClientObjectInfo.h"
 
 /* ------------------------------------------------------------------------- */
 /* Native functions                                                          */
@@ -259,7 +258,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
                /* all this casting makes me nervous... */
                KX_ClientObjectInfo* client_info 
                        = ( hitSMObj ?
-                               (KX_ClientObjectInfo*) hitSMObj->getClientObject() :
+                               static_cast<KX_ClientObjectInfo*>( hitSMObj->getClientObject() ):
                                NULL);
                
                if (!client_info)
@@ -268,7 +267,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
                        return false;
                } 
        
-               KX_GameObject* hitKXObj = (KX_GameObject*)client_info->m_clientobject;
+               KX_GameObject* hitKXObj = client_info->m_gameobject;
                
                if (client_info->m_type > KX_ClientObjectInfo::ACTOR)
                {
index 3bb6bad502999a0e6cd0d764958ada7147c865f4..bfcf9794d1b3c2d31c12bfe2226f8cd83d19594a 100644 (file)
@@ -62,7 +62,9 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
                         m_ResetMargin(resetmargin)
 
 {
+       gameobj->getClientInfo()->m_sensors.remove(this);
        m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
+       m_client_info->m_sensors.push_back(this);
        
        DT_ShapeHandle shape = (DT_ShapeHandle) vshape;
        m_sumoObj = new SM_Object(shape,NULL,NULL,NULL);
@@ -90,7 +92,9 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
                         m_ResetMargin(resetmargin)
 
 {
+       gameobj->getClientInfo()->m_sensors.remove(this);
        m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
+       m_client_info->m_sensors.push_back(this);
        
        m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
        m_sumoObj->setMargin(m_Margin);
@@ -115,7 +119,7 @@ CValue* KX_NearSensor::GetReplica()
        // this will copy properties and so on...
        CValue::AddDataToReplica(replica);
        
-       replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_clientobject, KX_ClientObjectInfo::NEAR);
+       replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR);
        
        replica->m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
        replica->m_sumoObj->setMargin(m_Margin);
@@ -132,7 +136,8 @@ void KX_NearSensor::ReParent(SCA_IObject* parent)
 {
        SCA_ISensor::ReParent(parent);
        
-       m_client_info->m_clientobject = static_cast<KX_GameObject*>(parent); 
+       m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 
+       m_client_info->m_sensors.push_back(this);
        
        SynchronizeTransform();
 }
@@ -197,7 +202,7 @@ DT_Bool KX_NearSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData *
                                        ((SM_Object*)obj1)->getClientObject());
 
        KX_GameObject* gameobj = ( client_info ? 
-                       static_cast<KX_GameObject*>(client_info->m_clientobject) : 
+                       client_info->m_gameobject :
                        NULL);
        
        if (gameobj && (gameobj != parent))
index 798ebdfc944ab41ededa3edcc4db8f88d87091a8..1ad3750422460e9fc76e8ba1b6075549cabfea39 100644 (file)
@@ -88,7 +88,7 @@ CValue* KX_RadarSensor::GetReplica()
        // this will copy properties and so on...
        CValue::AddDataToReplica(replica);
        
-       replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_clientobject, KX_ClientObjectInfo::RADAR);
+       replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::RADAR);
        
        replica->m_sumoObj = new SM_Object(DT_NewCone(m_coneradius, m_coneheight),NULL,NULL,NULL);
        replica->m_sumoObj->setMargin(m_Margin);
index 04f57bb754b4f39f1098e4aa196b0802f9f9d100..c60b2171cab3650543dc847a41452b7b1196107e 100644 (file)
@@ -195,7 +195,7 @@ bool KX_RaySensor::Evaluate(CValue* event)
                if (hitObj)
                {
        
-                       KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)hitObj->getClientObject();
+                       KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(hitObj->getClientObject());
                        bool bFound = false;
                        
                        if (!info)
@@ -205,7 +205,7 @@ bool KX_RaySensor::Evaluate(CValue* event)
                                break;
                        } 
                        
-                       SCA_IObject *hitgameobj = (SCA_IObject*)info->m_clientobject;
+                       SCA_IObject *hitgameobj = info->m_gameobject;
                        
                        if (hitgameobj == obj || info->m_type > KX_ClientObjectInfo::ACTOR)
                        {
index a5284b4016581987d4ab0032565d81cf64f76e37..8f284809a1719c9bd69da4e82ffcada1047605b2 100644 (file)
@@ -8,6 +8,7 @@
 #include "SM_Scene.h"
 #include "KX_GameObject.h"
 #include "KX_MotionState.h"
+#include "KX_ClientObjectInfo.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
index 704d949b0e7232a2a65754258c8a676cee2116dc..4f074ce9b12ec312918ada05c8c62cd8dd93fb8c 100644 (file)
 
 #include "SM_Object.h"
 
+KX_TouchEventManager::Collision::Collision(SCA_ISensor *sensor, SM_Object *obj1, SM_Object *obj2)
+       : m_id(next_id++),
+         m_sensor(sensor),
+         m_object1(obj1),
+         m_object2(obj2)
+{
+}
+
+bool KX_TouchEventManager::Collision::operator<(const Collision &other) const
+{
+       if (*this == other)
+               return true;
+               
+       return m_id < other.m_id;
+}
+               
+bool KX_TouchEventManager::Collision::operator==(const Collision &other) const
+{
+       return m_sensor == other.m_sensor && 
+               ((m_object1 == other.m_object1 && m_object2 == other.m_object2) ||
+                (m_object1 == other.m_object2 && m_object2 == other.m_object1));
+}
+
+int KX_TouchEventManager::Collision::next_id = 0;
+
 KX_TouchEventManager::KX_TouchEventManager(class SCA_LogicManager* logicmgr,
        SM_Scene *scene)
        : SCA_EventManager(TOUCH_EVENTMGR),
@@ -51,6 +76,24 @@ KX_TouchEventManager::KX_TouchEventManager(class SCA_LogicManager* logicmgr,
        m_scene->addTouchCallback(SENSOR_RESPONSE, KX_TouchEventManager::collisionResponse, this);
 }
 
+DT_Bool KX_TouchEventManager::HandleCollision(void* object1, void* object2, const DT_CollData *coll_data)
+{
+       SM_Object * obj1 = static_cast<SM_Object*>(object1);
+       SM_Object * obj2 = static_cast<SM_Object*>(object2);
+       KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>(obj1->getClientObject());
+       
+       list<SCA_ISensor*>::iterator it;
+       for ( it = client_info->m_sensors.begin(); it != client_info->m_sensors.end(); ++it)
+               m_collisions.insert(Collision(*it, obj1, obj2));
+
+       client_info = static_cast<KX_ClientObjectInfo *>(obj2->getClientObject());
+       for ( it = client_info->m_sensors.begin(); it != client_info->m_sensors.end(); ++it)
+               m_collisions.insert(Collision(*it, obj2, obj1));
+               
+       return DT_CONTINUE;
+}
+
+/*
 DT_Bool KX_TouchEventManager::HandleCollision(void* object1,void* object2,
                                                 const DT_CollData * coll_data)
 {
@@ -76,6 +119,8 @@ DT_Bool KX_TouchEventManager::HandleCollision(void* object1,void* object2,
        return DT_CONTINUE;
 }
 
+*/
+
 DT_Bool KX_TouchEventManager::collisionResponse(void *client_data, 
                                                        void *object1,
                                                        void *object2,
@@ -115,10 +160,15 @@ void KX_TouchEventManager::NextFrame()
        {
                vector<SCA_ISensor*>::iterator it;
                
-               for (it = m_sensors.begin();!(it==m_sensors.end());it++)
+               for (it = m_sensors.begin();!(it==m_sensors.end());++it)
                        static_cast<KX_TouchSensor*>(*it)->SynchronizeTransform();
                
-               for (it = m_sensors.begin();!(it==m_sensors.end());it++)
+               for (std::set<Collision>::iterator cit = m_collisions.begin(); cit != m_collisions.end(); ++cit)
+                       static_cast<KX_TouchSensor*>((*cit).m_sensor)->HandleCollision((*cit).m_object1, (*cit).m_object2, NULL);
+                       
+               m_collisions.clear();
+                       
+               for (it = m_sensors.begin();!(it==m_sensors.end());++it)
                        (*it)->Activate(m_logicmgr,NULL);
        }
 }
index 923ecd108848f7bbf2a820520f92bc14e84746ae..eb2c26a64f32db9e13171de5208e57ae9a958596 100644 (file)
 #include "KX_GameObject.h"
 
 #include <vector>
+#include <set>
+
+class SCA_ISensor;
+class SM_Object;
 
 class KX_TouchEventManager : public SCA_EventManager
 {
+       struct Collision
+       {
+               static int next_id;
+               int          m_id;
+               SCA_ISensor *m_sensor;
+               SM_Object   *m_object1;
+               SM_Object   *m_object2;
+               
+               Collision(SCA_ISensor *sensor, SM_Object *obj1, SM_Object *obj2);
+               
+               bool operator<(const Collision &other) const;
+               bool operator==(const Collision &other) const;
+       };
+
        class SCA_LogicManager* m_logicmgr;
        SM_Scene *m_scene;
+       
+       std::set<Collision> m_collisions;
+       
 
        static DT_Bool collisionResponse(void *client_data, 
                                                        void *object1,
index 9091a41d0549cbd7e25bcdf304a0577d86e285f2..4a7e9d8646dda195731e0e2546b5b4b1d26930e8 100644 (file)
@@ -103,8 +103,9 @@ m_bLastTriggered(false)
        m_colliders = new CListValue();
        
        KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
-       client_info->m_clientobject = gameobj;
+       client_info->m_gameobject = gameobj;
        client_info->m_auxilary_info = NULL;
+       client_info->m_sensors.push_back(this);
        
        KX_SumoPhysicsController *sphy = dynamic_cast<KX_SumoPhysicsController *>(gameobj->GetPhysicsController());
        if (sphy)
@@ -141,8 +142,9 @@ void        KX_TouchSensor::ReParent(SCA_IObject* parent)
 
 //     m_solidHandle = m_sumoObj->getObjectHandle();
        KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
-       client_info->m_clientobject = parent;
+       client_info->m_gameobject = gameobj;
        client_info->m_auxilary_info = NULL;
+       client_info->m_sensors.push_back(this);
        SCA_ISensor::ReParent(parent);
 }
 
@@ -164,12 +166,12 @@ DT_Bool    KX_TouchSensor::HandleCollision(void* obj1,void* obj2,const DT_CollDa
 
        // need the mapping from SM_Objects to gameobjects now
        
-       KX_ClientObjectInfo* client_info =(KX_ClientObjectInfo*) (obj1 == m_sumoObj? 
+       KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*> (obj1 == m_sumoObj? 
                                        ((SM_Object*)obj2)->getClientObject() : 
                                        ((SM_Object*)obj1)->getClientObject());
 
        KX_GameObject* gameobj = ( client_info ? 
-                       (KX_GameObject*)client_info->m_clientobject : 
+                       client_info->m_gameobject : 
                        NULL);
        
        if (gameobj && (gameobj != parent) && client_info->isActor())
@@ -338,7 +340,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self,
                                SM_Object* smob = spc?spc->GetSumoObject():NULL;
                                
                                if (smob) {
-                                       KX_ClientObjectInfo* cl_inf = (KX_ClientObjectInfo*) smob->getClientObject();
+                                       KX_ClientObjectInfo* cl_inf = static_cast<KX_ClientObjectInfo*>(smob->getClientObject());
                                        
                                        if (m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) {
                                                newList->Add(m_colliders->GetValue(i)->AddRef());
index bfb24f5fec1bfea2aeb9d01840431555252c490a..6c69e14c8865dee19c16dcafd1d91a8b6d59643c 100644 (file)
@@ -48,14 +48,24 @@ DummyPhysicsEnvironment::~DummyPhysicsEnvironment()
        //destroy physicsengine data
 }
 
-void DummyPhysicsEnvironment::proceed(double timeStep)
+void DummyPhysicsEnvironment::beginFrame()
+{
+       // beginning of logic frame: apply forces
+}
+
+void DummyPhysicsEnvironment::endFrame()
+{
+       // end of logic frame: clear forces
+}
+
+bool DummyPhysicsEnvironment::proceed(double timeStep)
 {
        //step physics simulation, typically perform
        
        //collision detection 
        //solve constraints
        //integrate solution
-
+       // return true if an update was done.
 }
 
 void DummyPhysicsEnvironment::setGravity(float x,float y,float z)
index 96f1ff82f9e9097906245903d2aa29ad2b31de6f..65f421410458d9c6c4bd5088daa1fd04b21f8277 100644 (file)
@@ -48,8 +48,10 @@ class DummyPhysicsEnvironment  : public PHY_IPhysicsEnvironment
 public:
        DummyPhysicsEnvironment ();
        virtual         ~DummyPhysicsEnvironment ();
+       virtual void            beginFrame();
+       virtual void            endFrame();
 // Perform an integration step of duration 'timeStep'.
-       virtual void            proceed (double timeStep);
+       virtual bool            proceed (double timeStep);
        virtual void            setGravity(float x,float y,float z);
 
        virtual int                     createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
index 54574f9fc55622e817e2d52d2bc7bbe6841eb349..4a69f7e2990fd51fc41cb482b64520a0e305f95b 100644 (file)
@@ -66,6 +66,14 @@ struct SM_MaterialProps {
        bool      m_fh_normal;             ///< Should the object slide off slopes?
 };
 
+class SM_ClientObject
+{
+public:
+       SM_ClientObject() {}
+       virtual ~SM_ClientObject() {}
+       
+       virtual bool hasCollisionCallback() = 0;
+};
 
 /**
  * SM_Object is an internal part of the Sumo physics engine.
@@ -227,7 +235,6 @@ public:
 
        SM_Object *getDynamicParent() ;
 
-       void beginFrame();
        void integrateForces(MT_Scalar timeStep);
        void integrateMomentum(MT_Scalar timeSteo);
 
@@ -255,8 +262,8 @@ public:
        );
        
        
-       void *getClientObject() { return m_client_object; }
-       void setClientObject(void *client_object) { m_client_object = client_object; }
+       SM_ClientObject *getClientObject() { return m_client_object; }
+       void setClientObject(SM_ClientObject *client_object) { m_client_object = client_object; }
        
        void relax();
        
@@ -301,7 +308,7 @@ private:
     // as the collision callback now has only information
        // on an SM_Object, there must be a way that the SM_Object client
        // can identify it's clientdata after a collision
-       void                   *m_client_object;
+       SM_ClientObject        *m_client_object;
 
        DT_ShapeHandle          m_shape;                 // Shape for collision detection
 
index 1c11df66c3866b8c0ee2dfe10b6ebad027bf9fbb..0b429a3c1a43fc99a057d38935cb6f7cada3843b 100644 (file)
@@ -101,13 +101,15 @@ public:
        
        void requestCollisionCallback(SM_Object &object);
 
+       void beginFrame();
+       void endFrame();
 
        // Perform an integration step of duration 'timeStep'.
        // 'subSampling' is the maximum duration of a substep, i.e.,
        // The maximum time interval between two collision checks.
        // 'subSampling' can be used to control aliasing effects
        // (fast moving objects traversing through walls and such). 
-       void proceed(MT_Scalar curtime, MT_Scalar ticrate);
+       bool proceed(MT_Scalar curtime, MT_Scalar ticrate);
 
        /**
         * Test whether any objects lie on the line defined by from and
index 940f0d221a0d5e14477312114172db59eefe6b5c..42adfcd4d9e89a946419c28eda3159152d72c66e 100644 (file)
@@ -101,16 +101,6 @@ SM_Object::SM_Object(
        m_suspended = false;
 }
 
-       void
-SM_Object::
-beginFrame(
-){
-       if (!m_suspended) {
-               m_prev_state = *this;
-               m_prev_state.setLinearVelocity(actualLinVelocity());
-               m_prev_state.setAngularVelocity(actualAngVelocity());
-       }
-}
 
        void 
 SM_Object::
@@ -118,6 +108,9 @@ integrateForces(
        MT_Scalar timeStep
 ){
        if (!m_suspended) {
+               m_prev_state = *this;
+               m_prev_state.setLinearVelocity(actualLinVelocity());
+               m_prev_state.setAngularVelocity(actualAngVelocity());
                if (isDynamic()) {
                        // Integrate momentum (forward Euler)
                        m_lin_mom += m_force * timeStep;
@@ -348,49 +341,68 @@ void SM_Object::dynamicCollision(const MT_Point3 &local2,
        }
 }
 
+static void AddCallback(SM_Scene *scene, SM_Object *obj1, SM_Object *obj2)
+{
+       // If we have callbacks on either of the client objects, do a collision test
+       // and add a callback if they intersect.
+       DT_Vector3 v;
+       if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) || 
+           (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()) &&
+            DT_GetIntersect(obj1->getObjectHandle(), obj2->getObjectHandle(), v))
+               scene->addPair(obj1, obj2);
+}
+
 DT_Bool SM_Object::boing(
        void *client_data,  
        void *object1,
        void *object2,
        const DT_CollData *coll_data
 ){
-       //if (!coll_data)
-       //      return DT_CONTINUE;
-
        SM_Scene  *scene = (SM_Scene *)client_data; 
        SM_Object *obj1  = (SM_Object *)object1;  
        SM_Object *obj2  = (SM_Object *)object2;  
        
-       scene->addPair(obj1, obj2); // Record this collision for client callbacks
+       // at this point it is unknown whether we are really intersecting (broad phase)
+       
+       DT_Vector3 p1, p2;
+       if (!obj2->isDynamic()) {
+               std::swap(obj1, obj2);
+       }
        
        // If one of the objects is a ghost then ignore it for the dynamics
        if (obj1->isGhost() || obj2->isGhost()) {
+               AddCallback(scene, obj1, obj2);
                return DT_CONTINUE;
        }
 
        // Objects do not collide with parent objects
        if (obj1->getDynamicParent() == obj2 || obj2->getDynamicParent() == obj1) {
+               AddCallback(scene, obj1, obj2);
                return DT_CONTINUE;
        }
        
        if (!obj2->isDynamic()) {
-               std::swap(obj1, obj2);
-       }
-
-       if (!obj2->isDynamic()) {
+               AddCallback(scene, obj1, obj2);
                return DT_CONTINUE;
        }
 
        // Get collision data from SOLID
-       DT_Vector3 p1, p2;
        if (!DT_GetPenDepth(obj1->getObjectHandle(), obj2->getObjectHandle(), p1, p2))
                return DT_CONTINUE;
+       
        MT_Point3 local1(p1), local2(p2);
        MT_Vector3 normal(local2 - local1);
        MT_Scalar dist = normal.length();
        
        if (dist < MT_EPSILON)
                return DT_CONTINUE;
+               
+       // Now we are definately intersecting.
+
+       // Set callbacks for game engine.
+       if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) || 
+           (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()))
+               scene->addPair(obj1, obj2);
        
        local1 -= obj1->m_pos;
        local2 -= obj2->m_pos;
index 0af1c22edbd006e6322193351b8fab8f618dcd48..1ea19c56336769c8b990f39f07f708f5bcb52d81 100644 (file)
@@ -65,38 +65,38 @@ SM_Scene::SM_Scene() :
        
        /* Sensor */
        DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
        DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
        
        /* Static */
-       DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
        DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[STATIC_RESPONSE], 0, DT_NO_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this);
        
        /* Object */
-       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::boing, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this);
        
        /* Fh Object */
        DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this);
        DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
        
        /* Object (Fix Pass) */
        DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
-       DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::fix, DT_SIMPLE_RESPONSE, this);
-       DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::fix, DT_SIMPLE_RESPONSE, this);
+       DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::fix, DT_BROAD_RESPONSE, this);
+       DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::fix, DT_BROAD_RESPONSE, this);
        DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
 }
 
 void SM_Scene::addTouchCallback(int response_class, DT_ResponseCallback callback, void *user)
 {
-       DT_AddClassResponse(m_secondaryRespTable, m_secondaryResponseClass[response_class], callback, DT_SIMPLE_RESPONSE, user);
+       DT_AddClassResponse(m_secondaryRespTable, m_secondaryResponseClass[response_class], callback, DT_BROAD_RESPONSE, user);
 }
 
 void SM_Scene::addSensor(SM_Object& object) 
@@ -161,11 +161,27 @@ void SM_Scene::remove(SM_Object& object) {
        }
 }
 
-void SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
+void SM_Scene::beginFrame()
+{
+       T_ObjectList::iterator i;
+       // Apply a forcefield (such as gravity)
+       for (i = m_objectList.begin(); i != m_objectList.end(); ++i)
+               (*i)->applyForceField(m_forceField);
+
+}
+
+void SM_Scene::endFrame()
+{
+       T_ObjectList::iterator i;
+       for (i = m_objectList.begin(); i != m_objectList.end(); ++i)
+               (*i)->clearForce();
+}
+
+bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
        if (m_lastTime < 0.0)
        {
                m_lastTime = curtime;
-               return;
+               return false;
        }
                
        // Divide the timeStep into a number of subsamples of size roughly 
@@ -177,7 +193,7 @@ void SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
        T_ObjectList::iterator i;
        
        // No timestep! (should do a mini update)
-       if (!num_samples)
+       if (num_samples <= 0)
        {
                // Apply a forcefield (such as gravity)
 #if 0
@@ -191,7 +207,7 @@ void SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
                        //(*i)->clearForce();
                }
 #endif
-               return; 
+               return false;   
        }
 
        m_lastTime += MT_Scalar(num_samples)*subStep;
@@ -201,9 +217,8 @@ void SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
        for (step = 0; step != num_samples; ++step) {
 
                for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
-                       (*i)->beginFrame();
                        // Apply a forcefield (such as gravity)
-                       (*i)->applyForceField(m_forceField);
+                       //(*i)->applyForceField(m_forceField);
                        //(*i)->setTimeStep(timeStep);
                        (*i)->integrateForces(subStep);
                        // And second we update the object positions by performing
@@ -235,7 +250,7 @@ void SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
                        (*i)->relax();
                        (*i)->proceedKinematic(subStep);
                        (*i)->saveReactionForce(subStep);
-                       (*i)->clearForce();
+                       //(*i)->clearForce();
                }
        }
        // For each pair of object that collided, call the corresponding callback.
@@ -252,6 +267,8 @@ void SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
        }
        
        clearPairs();
+       
+       return true;
 }
 
 SM_Object *SM_Scene::rayTest(void *ignore_client, 
index 151c55d75de8fd74c1347d581c1e41bd4262ddea..f035bfb4cf2c188d3f05ac99bcdb958498937c58 100644 (file)
@@ -62,9 +62,19 @@ MT_Scalar SumoPhysicsEnvironment::getTicRate()
        return PhysicsTicRate;
 }
 
-void SumoPhysicsEnvironment::proceed(double curtime)
+void SumoPhysicsEnvironment::beginFrame()
 {
-       m_sumoScene->proceed(curtime, PhysicsTicRate);
+       m_sumoScene->beginFrame();
+}
+
+void SumoPhysicsEnvironment::endFrame()
+{
+       m_sumoScene->endFrame();
+}
+
+bool SumoPhysicsEnvironment::proceed(double curtime)
+{
+       return m_sumoScene->proceed(curtime, PhysicsTicRate);
 }
 
 void SumoPhysicsEnvironment::setGravity(float x,float y,float z)
index 09ffe6ce112b7004b349cd183ea8dfd6be8067eb..aba341360f994e7d909254f39bd3f965ed697e96 100644 (file)
@@ -48,8 +48,10 @@ class SumoPhysicsEnvironment : public PHY_IPhysicsEnvironment
 public:
        SumoPhysicsEnvironment();
        virtual         ~SumoPhysicsEnvironment();
+       virtual void            beginFrame();
+       virtual void            endFrame();
 // Perform an integration step of duration 'timeStep'.
-       virtual void            proceed(double curtime);
+       virtual bool            proceed(double curtime);
        virtual void            setGravity(float x,float y,float z);
        virtual int             createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
                        float pivotX,float pivotY,float pivotZ,
index 1eabc4bfd64a8549324909e12b6c048435ec8f60..0fdac35f514c729fe61118255ad478d1a4321b40 100644 (file)
@@ -43,8 +43,10 @@ class PHY_IPhysicsEnvironment
 {
        public:
                virtual         ~PHY_IPhysicsEnvironment();
+               virtual void            beginFrame() = 0;
+               virtual void            endFrame() = 0;
                /// Perform an integration step of duration 'timeStep'.
-               virtual void            proceed(double  timeStep)=0;
+               virtual bool            proceed(double  timeStep)=0;
                virtual void            setGravity(float x,float y,float z)=0;
 
                virtual int                     createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,