Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj9
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp40
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h7
-rw-r--r--source/gameengine/SceneGraph/SG_DList.h147
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.cpp92
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.h129
-rw-r--r--source/gameengine/SceneGraph/SG_Node.cpp63
-rw-r--r--source/gameengine/SceneGraph/SG_Node.h113
-rw-r--r--source/gameengine/SceneGraph/SG_QList.h144
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.cpp147
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.h178
14 files changed, 658 insertions, 429 deletions
diff --git a/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj b/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj
index 9c63f625820..95e61cc4af8 100644
--- a/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj
+++ b/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj
@@ -4,6 +4,7 @@
Version="9,00"
Name="SG_SceneGraph"
ProjectGUID="{09222F5E-1625-4FF3-A89A-384D16875EE5}"
+ RootNamespace="SG_SceneGraph"
TargetFrameworkVersion="131072"
>
<Platforms>
@@ -510,6 +511,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\gameengine\SceneGraph\SG_DList.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\gameengine\SceneGraph\SG_IObject.h"
>
</File>
@@ -522,6 +527,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\gameengine\SceneGraph\SG_QList.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\gameengine\SceneGraph\SG_Spatial.h"
>
</File>
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 6a570c9e815..c4c71d9dd85 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -2055,7 +2055,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
{
// blender has an additional 'parentinverse' offset in each object
- SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
+ SG_Node* parentinversenode = new SG_Node(NULL,kxscene,SG_Callbacks(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc));
// define a normal parent relationship for this node.
KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
@@ -2249,7 +2249,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
{
// blender has an additional 'parentinverse' offset in each object
- SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
+ SG_Node* parentinversenode = new SG_Node(NULL,kxscene,SG_Callbacks(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc));
// define a normal parent relationship for this node.
KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
index 0e7571031e8..cb933419c57 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
@@ -125,7 +125,9 @@ UpdateChildCoordinates(
else {
child->SetWorldFromLocalTransform();
}
- child->SetModified(false);
+ child->ClearModified();
+ // this node must always be updated, so reschedule it for next time
+ child->ActivateRecheduleUpdateCallback();
return valid_parent_transform;
}
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
index c3b0c21c8e0..c49b6d671a7 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
@@ -63,7 +63,7 @@ UpdateChildCoordinates(
if (parent==NULL) { /* Simple case */
child->SetWorldFromLocalTransform();
- child->SetModified(false);
+ child->ClearModified();
return true; //false;
}
else {
@@ -75,7 +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);
+ child->ClearModified();
return true;
}
}
@@ -137,7 +137,7 @@ UpdateChildCoordinates(
child->SetWorldPosition(child->GetLocalPosition());
child->SetWorldOrientation(child->GetLocalOrientation());
- child->SetModified(false);
+ child->ClearModified();
return true; //parent != NULL;
}
@@ -259,7 +259,9 @@ UpdateChildCoordinates(
child->SetWorldScale(child_w_scale);
child->SetWorldPosition(child_w_pos);
child->SetWorldOrientation(child_w_rotation);
- child->SetModified(false);
+ child->ClearModified();
+ // this node must always be updated, so reschedule it for next time
+ child->ActivateRecheduleUpdateCallback();
return true; //parent != NULL;
}
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 171ed5d130f..d31d451f02e 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -111,7 +111,22 @@ void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
return NULL;
};
-SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(KX_SceneReplicationFunc,KX_SceneDestructionFunc,KX_GameObject::UpdateTransformFunc);
+bool KX_Scene::KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+ return ((SG_Node*)node)->Schedule(((KX_Scene*)scene)->m_sghead);
+}
+
+bool KX_Scene::KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+ return ((SG_Node*)node)->Reschedule(((KX_Scene*)scene)->m_sghead);
+}
+
+SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(
+ KX_SceneReplicationFunc,
+ KX_SceneDestructionFunc,
+ KX_GameObject::UpdateTransformFunc,
+ KX_Scene::KX_ScenegraphUpdateFunc,
+ KX_Scene::KX_ScenegraphRescheduleFunc);
// temporarily var until there is a button in the userinterface
// (defined in KX_PythonInit.cpp)
@@ -1473,15 +1488,28 @@ void KX_Scene::LogicEndFrame()
*/
void KX_Scene::UpdateParents(double curtime)
{
-// int numrootobjects = GetRootParentList()->GetCount();
+ // we use the SG dynamic list
+ SG_Node* node;
- for (int i=0; i<GetRootParentList()->GetCount(); i++)
+ while ((node = SG_Node::GetNextScheduled(m_sghead)) != NULL)
{
- KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
- parentobj->NodeUpdateGS(curtime);
+ node->UpdateWorldData(curtime);
}
-}
+ //for (int i=0; i<GetRootParentList()->GetCount(); i++)
+ //{
+ // KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
+ // parentobj->NodeUpdateGS(curtime);
+ //}
+
+ // the list must be empty here
+ assert(m_sghead.Empty());
+ // some nodes may be ready for reschedule, move them to schedule list for next time
+ while ((node = SG_Node::GetNextRescheduled(m_sghead)) != NULL)
+ {
+ node->Schedule(m_sghead);
+ }
+}
RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated)
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 52a3cd5733e..0cfef8b7bd1 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -118,6 +118,11 @@ protected:
CListValue* m_parentlist; // all 'root' parents
CListValue* m_lightlist;
CListValue* m_inactivelist; // all objects that are not in the active layer
+
+ SG_QList m_sghead; // list of nodes that needs scenegraph update
+ // the Dlist is not object that must be updated
+ // the Qlist is for objects that needs to be rescheduled
+ // for updates after udpate is over (slow parent, bone parent)
/**
* The tree of objects in the scene.
@@ -307,6 +312,8 @@ public:
/**
* Update all transforms according to the scenegraph.
*/
+ static bool KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene);
+ static bool KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene);
void UpdateParents(double curtime);
void DupliGroupRecurse(CValue* gameobj, int level);
bool IsObjectInGroup(CValue* gameobj)
diff --git a/source/gameengine/SceneGraph/SG_DList.h b/source/gameengine/SceneGraph/SG_DList.h
new file mode 100644
index 00000000000..d682be679e6
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_DList.h
@@ -0,0 +1,147 @@
+/**
+ * $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 __SG_DLIST
+#define __SG_DLIST
+
+#include <stdlib.h>
+
+/**
+ * Double circular linked list
+ */
+class SG_DList
+{
+protected :
+ SG_DList* m_flink;
+ SG_DList* m_blink;
+
+public:
+ template<typename T> class iterator
+ {
+ private:
+ SG_DList& m_head;
+ T* m_current;
+ public:
+ typedef iterator<T> _myT;
+ iterator(SG_DList& head) : m_head(head), m_current(NULL) {}
+ ~iterator() {}
+
+ void begin()
+ {
+ m_current = (T*)m_head.Peek();
+ if (m_current == (T*)m_head.Self())
+ {
+ m_current = NULL;
+ }
+ }
+ bool end()
+ {
+ return (NULL == m_current);
+ }
+ T* operator*()
+ {
+ return m_current;
+ }
+ _myT& operator++()
+ {
+ assert(m_current);
+ m_current = (T*)m_current->Peek();
+ if (m_current == (T*)m_head.Self())
+ {
+ m_current = NULL;
+ }
+ return *this;
+ }
+ };
+
+ SG_DList()
+ {
+ m_flink = m_blink = this;
+ }
+ virtual ~SG_DList()
+ {
+ Delink();
+ }
+
+ inline bool Empty() // Check for empty queue
+ {
+ return ( m_flink == this );
+ }
+ bool AddBack( SG_DList *item ) // Add to the back
+ {
+ if (!item->Empty())
+ return false;
+ item->m_blink = m_blink;
+ item->m_flink = this;
+ m_blink->m_flink = item;
+ m_blink = item;
+ return true;
+ }
+ bool AddFront( SG_DList *item ) // Add to the back
+ {
+ if (!item->Empty())
+ return false;
+ item->m_flink = m_flink;
+ item->m_blink = this;
+ m_flink->m_blink = item;
+ m_flink = item;
+ return true;
+ }
+ SG_DList *Remove() // Remove from the front
+ {
+ if (Empty())
+ {
+ return NULL;
+ }
+ SG_DList* item = m_flink;
+ m_flink = item->m_flink;
+ m_flink->m_blink = this;
+ item->m_flink = item->m_blink = item;
+ return item;
+ }
+ void Delink() // Remove from the middle
+ {
+ if (!Empty())
+ {
+ m_blink->m_flink = m_flink;
+ m_flink->m_blink = m_blink;
+ m_flink = m_blink = this;
+ }
+ }
+ inline SG_DList *Peek() // Look at front without removing
+ {
+ return m_flink;
+ }
+ inline SG_DList *Self()
+ {
+ return this;
+ }
+};
+
+#endif //__SG_DLIST
+
diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp
index fbab4032a10..5795ca57113 100644
--- a/source/gameengine/SceneGraph/SG_IObject.cpp
+++ b/source/gameengine/SceneGraph/SG_IObject.cpp
@@ -39,19 +39,20 @@ SG_IObject::
SG_IObject(
void* clientobj,
void* clientinfo,
- SG_Callbacks callbacks
+ SG_Callbacks& callbacks
):
+ SG_QList(),
m_SGclientObject(clientobj),
- m_SGclientInfo(clientinfo),
- m_callbacks(callbacks)
+ m_SGclientInfo(clientinfo)
{
- //nothing to do
+ m_callbacks = callbacks;
}
SG_IObject::
SG_IObject(
const SG_IObject &other
) :
+ SG_QList(),
m_SGclientObject(other.m_SGclientObject),
m_SGclientInfo(other.m_SGclientInfo),
m_callbacks(other.m_callbacks)
@@ -74,92 +75,17 @@ RemoveAllControllers(
m_SGcontrollers.clear();
}
-/// Needed for replication
- SGControllerList&
-SG_IObject::
-GetSGControllerList(
-){
- return m_SGcontrollers;
-}
-
- void*
-SG_IObject::
-GetSGClientObject(
-){
- return m_SGclientObject;
-}
-
-const
- void*
-SG_IObject::
-GetSGClientObject(
-) const {
- return m_SGclientObject;
-}
-
- void
-SG_IObject::
-SetSGClientObject(
- void* clientObject
-){
- m_SGclientObject = clientObject;
-}
-
-
- bool
-SG_IObject::
-ActivateReplicationCallback(
- SG_IObject *replica
-){
- if (m_callbacks.m_replicafunc)
- {
- // Call client provided replication func
- if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL)
- return false;
- }
- return true;
-};
-
- void
-SG_IObject::
-ActivateDestructionCallback(
-){
- if (m_callbacks.m_destructionfunc)
- {
- // Call client provided destruction function on this!
- m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo);
- }
- else
- {
- // no callback but must still destroy the node to avoid memory leak
- delete this;
- }
-}
-
- void
-SG_IObject::
-ActivateUpdateTransformCallback(
-){
- if (m_callbacks.m_updatefunc)
- {
- // Call client provided update func.
- m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo);
- }
-}
-
- void
-SG_IObject::
-SetControllerTime(
- double time
-){
+void SG_IObject::SetControllerTime(double time)
+{
SGControllerList::iterator contit;
-
for (contit = m_SGcontrollers.begin();contit!=m_SGcontrollers.end();++contit)
{
(*contit)->SetSimulatedTime(time);
}
}
+/// Needed for replication
+
SG_IObject::
~SG_IObject()
diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
index 9012b532059..b4dd9a9ddf2 100644
--- a/source/gameengine/SceneGraph/SG_IObject.h
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -29,6 +29,7 @@
#ifndef __SG_IOBJECT
#define __SG_IOBJECT
+#include "SG_QList.h"
#include <vector>
// used for debugging: stage of the game engine main loop at which a Scenegraph modification is done
@@ -84,6 +85,18 @@ typedef void (*SG_UpdateTransformCallback)(
void* clientinfo
);
+typedef bool (*SG_ScheduleUpdateCallback)(
+ SG_IObject* sgobject,
+ void* clientobj,
+ void* clientinfo
+);
+
+typedef bool (*SG_RescheduleUpdateCallback)(
+ SG_IObject* sgobject,
+ void* clientobj,
+ void* clientinfo
+);
+
/**
* SG_Callbacks hold 2 call backs to the outside world.
@@ -106,30 +119,38 @@ struct SG_Callbacks
):
m_replicafunc(NULL),
m_destructionfunc(NULL),
- m_updatefunc(NULL)
+ m_updatefunc(NULL),
+ m_schedulefunc(NULL),
+ m_reschedulefunc(NULL)
{
};
SG_Callbacks(
SG_ReplicationNewCallback repfunc,
SG_DestructionNewCallback destructfunc,
- SG_UpdateTransformCallback updatefunc
+ SG_UpdateTransformCallback updatefunc,
+ SG_ScheduleUpdateCallback schedulefunc,
+ SG_RescheduleUpdateCallback reschedulefunc
):
m_replicafunc(repfunc),
m_destructionfunc(destructfunc),
- m_updatefunc(updatefunc)
+ m_updatefunc(updatefunc),
+ m_schedulefunc(schedulefunc),
+ m_reschedulefunc(reschedulefunc)
{
};
SG_ReplicationNewCallback m_replicafunc;
SG_DestructionNewCallback m_destructionfunc;
SG_UpdateTransformCallback m_updatefunc;
+ SG_ScheduleUpdateCallback m_schedulefunc;
+ SG_RescheduleUpdateCallback m_reschedulefunc;
};
/**
base object that can be part of the scenegraph.
*/
-class SG_IObject
+class SG_IObject : public SG_QList
{
private :
@@ -177,9 +198,10 @@ public:
* using STL?
*/
- SGControllerList&
- GetSGControllerList(
- );
+ SGControllerList& GetSGControllerList()
+ {
+ return m_SGcontrollers;
+ }
/**
@@ -192,16 +214,16 @@ public:
* This may be NULL.
*/
- void*
- GetSGClientObject(
- );
+ inline const void* GetSGClientObject() const
+ {
+ return m_SGclientObject;
+ }
- const
- void*
- GetSGClientObject(
- ) const ;
+ inline void* GetSGClientObject()
+ {
+ return m_SGclientObject;
+ }
-
/**
* Set the client object for this node. This is just a
* pointer to an object allocated that should exist for
@@ -209,10 +231,10 @@ public:
* this function is called again.
*/
- void
- SetSGClientObject(
- void* clientObject
- );
+ void SetSGClientObject(void* clientObject)
+ {
+ m_SGclientObject = clientObject;
+ }
/**
* Set the current simulation time for this node.
@@ -220,10 +242,7 @@ public:
* the nodes list of controllers and calls their SetSimulatedTime methods
*/
- void
- SetControllerTime(
- double time
- );
+ void SetControllerTime(double time);
virtual
void
@@ -235,20 +254,76 @@ protected :
bool
ActivateReplicationCallback(
SG_IObject *replica
- );
+ )
+ {
+ if (m_callbacks.m_replicafunc)
+ {
+ // Call client provided replication func
+ if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL)
+ return false;
+ }
+ return true;
+ }
+
void
ActivateDestructionCallback(
- );
+ )
+ {
+ if (m_callbacks.m_destructionfunc)
+ {
+ // Call client provided destruction function on this!
+ m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo);
+ }
+ else
+ {
+ // no callback but must still destroy the node to avoid memory leak
+ delete this;
+ }
+ }
void
ActivateUpdateTransformCallback(
- );
+ )
+ {
+ if (m_callbacks.m_updatefunc)
+ {
+ // Call client provided update func.
+ m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo);
+ }
+ }
+
+ bool
+ ActivateScheduleUpdateCallback(
+ )
+ {
+ // HACK, this check assumes that the scheduled nodes are put on a DList (see SG_Node.h)
+ // The early check on Empty() allows up to avoid calling the callback function
+ // when the node is already scheduled for update.
+ if (Empty() && m_callbacks.m_schedulefunc)
+ {
+ // Call client provided update func.
+ return m_callbacks.m_schedulefunc(this, m_SGclientObject, m_SGclientInfo);
+ }
+ return false;
+ }
+
+ void
+ ActivateRecheduleUpdateCallback(
+ )
+ {
+ if (m_callbacks.m_reschedulefunc)
+ {
+ // Call client provided update func.
+ m_callbacks.m_reschedulefunc(this, m_SGclientObject, m_SGclientInfo);
+ }
+ }
+
SG_IObject(
void* clientobj,
void* clientinfo,
- SG_Callbacks callbacks
+ SG_Callbacks& callbacks
);
SG_IObject(
diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp
index 64d9019c86a..c4a1b151846 100644
--- a/source/gameengine/SceneGraph/SG_Node.cpp
+++ b/source/gameengine/SceneGraph/SG_Node.cpp
@@ -40,7 +40,7 @@ using namespace std;
SG_Node::SG_Node(
void* clientobj,
void* clientinfo,
- SG_Callbacks callbacks
+ SG_Callbacks& callbacks
)
: SG_Spatial(clientobj,clientinfo,callbacks),
@@ -141,22 +141,6 @@ Destruct()
ActivateDestructionCallback();
}
-
- SG_Node*
-SG_Node::
-GetSGParent(
-) const {
- return m_SGparent;
-}
-
- void
-SG_Node::
-SetSGParent(
- SG_Node* parent
-){
- m_SGparent = parent;
-}
-
const
SG_Node*
SG_Node::
@@ -165,28 +149,6 @@ GetRootSGParent(
return (m_SGparent ? (const SG_Node*) m_SGparent->GetRootSGParent() : (const SG_Node*) this);
}
- bool
-SG_Node::
-IsVertexParent()
-{
- if (m_parent_relation)
- {
- return m_parent_relation->IsVertexRelation();
- }
- return false;
-}
-
- bool
-SG_Node::
-IsSlowParent()
-{
- if (m_parent_relation)
- {
- return m_parent_relation->IsSlowRelation();
- }
- return false;
-}
-
void
SG_Node::
DisconnectFromParent(
@@ -199,8 +161,6 @@ DisconnectFromParent(
}
-
-
void SG_Node::AddChild(SG_Node* child)
{
m_children.push_back(child);
@@ -228,6 +188,9 @@ void SG_Node::UpdateWorldData(double time, bool parentUpdated)
// to update the
ActivateUpdateTransformCallback();
+ // The node is updated, remove it from the update list
+ Delink();
+
// update children's worlddata
for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
{
@@ -236,24 +199,6 @@ void SG_Node::UpdateWorldData(double time, bool parentUpdated)
}
-NodeList& SG_Node::GetSGChildren()
-{
- return this->m_children;
-}
-
-
-const NodeList& SG_Node::GetSGChildren() const
-{
- return this->m_children;
-}
-
-
-void SG_Node::ClearSGChildren()
-{
- m_children.clear();
-}
-
-
void SG_Node::SetSimulatedTime(double time,bool recurse)
{
diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h
index 29943653a81..7c6ef92f670 100644
--- a/source/gameengine/SceneGraph/SG_Node.h
+++ b/source/gameengine/SceneGraph/SG_Node.h
@@ -44,7 +44,7 @@ public:
SG_Node(
void* clientobj,
void* clientinfo,
- SG_Callbacks callbacks
+ SG_Callbacks& callbacks
);
SG_Node(
@@ -85,45 +85,47 @@ public:
* @return a reference to the list of children of this node.
*/
- NodeList&
- GetSGChildren(
- );
+ NodeList& GetSGChildren()
+ {
+ return this->m_children;
+ }
/**
* Get the current list of children.
* @return a const reference to the current list of children of this node.
*/
- const
- NodeList&
- GetSGChildren(
- ) const;
+ const NodeList& GetSGChildren() const
+ {
+ return this->m_children;
+ }
/**
* Clear the list of children associated with this node
*/
- void
- ClearSGChildren(
- );
+ void ClearSGChildren()
+ {
+ m_children.clear();
+ }
/**
* return the parent of this node if it exists.
*/
- SG_Node*
- GetSGParent(
- ) const ;
-
+ SG_Node* GetSGParent() const
+ {
+ return m_SGparent;
+ }
/**
* Set the parent of this node.
*/
- void
- SetSGParent(
- SG_Node* parent
- );
+ void SetSGParent(SG_Node* parent)
+ {
+ m_SGparent = parent;
+ }
/**
* Return the top node in this node's Scene graph hierarchy
@@ -143,30 +145,33 @@ public:
);
/**
- * Tell this node to treat it's parent as a vertex parent.
- */
-
- void
- SetVertexParent(
- bool isvertexparent
- ) ;
-
-
- /**
* Return vertex parent status.
*/
+ bool IsVertexParent()
+ {
+ if (m_parent_relation)
+ {
+ return m_parent_relation->IsVertexRelation();
+ }
+ return false;
+ }
+
- bool
- IsVertexParent(
- ) ;
-
/**
* Return slow parent status.
*/
- bool
- IsSlowParent(
- ) ;
+ bool IsSlowParent()
+ {
+ if (m_parent_relation)
+ {
+ return m_parent_relation->IsSlowRelation();
+ }
+ return false;
+ }
+
+
+
/**
* Update the spatial data of this node. Iterate through
@@ -191,6 +196,42 @@ public:
);
/**
+ * Schedule this node for update by placing it in head queue
+ */
+ bool Schedule(SG_QList& head)
+ {
+ // Put top parent in front of list to make sure they are updated before their
+ // children => the children will be udpated and removed from the list before
+ // we get to them, should they be in the list too.
+ return (m_SGparent)?head.AddBack(this):head.AddFront(this);
+ }
+
+ /**
+ * Used during Scenegraph update
+ */
+ static SG_Node* GetNextScheduled(SG_QList& head)
+ {
+ return static_cast<SG_Node*>(head.Remove());
+ }
+
+ /**
+ * Make this node ready for schedule on next update. This is needed for nodes
+ * that must always be updated (slow parent, bone parent)
+ */
+ bool Reschedule(SG_QList& head)
+ {
+ return head.QAddBack(this);
+ }
+
+ /**
+ * Used during Scenegraph update
+ */
+ static SG_Node* GetNextRescheduled(SG_QList& head)
+ {
+ return static_cast<SG_Node*>(head.QRemove());
+ }
+
+ /**
* Node replication functions.
*/
diff --git a/source/gameengine/SceneGraph/SG_QList.h b/source/gameengine/SceneGraph/SG_QList.h
new file mode 100644
index 00000000000..efaa613bbb9
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_QList.h
@@ -0,0 +1,144 @@
+/**
+ * $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 __SG_QLIST
+#define __SG_QLIST
+
+#include "SG_DList.h"
+
+/**
+ * Double-Double circular linked list
+ * For storing an object is two lists simultaneously
+ */
+class SG_QList : public SG_DList
+{
+protected :
+ SG_QList* m_fqlink;
+ SG_QList* m_bqlink;
+
+public:
+ template<typename T> class iterator
+ {
+ private:
+ SG_QList& m_head;
+ T* m_current;
+ public:
+ typedef iterator<T> _myT;
+ iterator(SG_QList& head) : m_head(head), m_current(NULL) {}
+ ~iterator() {}
+
+ void begin()
+ {
+ m_current = (T*)m_head.QPeek();
+ if (m_current == (T*)m_head.Self())
+ {
+ m_current = NULL;
+ }
+ }
+ bool end()
+ {
+ return (NULL == m_current);
+ }
+ T* operator*()
+ {
+ return m_current;
+ }
+ _myT& operator++()
+ {
+ assert(m_current);
+ m_current = (T*)m_current->QPeek();
+ if (m_current == (T*)m_head.Self())
+ {
+ m_current = NULL;
+ }
+ return *this;
+ }
+ };
+
+ SG_QList() : SG_DList()
+ {
+ m_fqlink = m_bqlink = this;
+ }
+ virtual ~SG_QList()
+ {
+ QDelink();
+ }
+
+ inline bool QEmpty() // Check for empty queue
+ {
+ return ( m_fqlink == this );
+ }
+ bool QAddBack( SG_QList *item ) // Add to the back
+ {
+ if (!item->QEmpty())
+ return false;
+ item->m_bqlink = m_bqlink;
+ item->m_fqlink = this;
+ m_bqlink->m_fqlink = item;
+ m_bqlink = item;
+ return true;
+ }
+ bool QAddFront( SG_QList *item ) // Add to the back
+ {
+ if (!item->Empty())
+ return false;
+ item->m_fqlink = m_fqlink;
+ item->m_bqlink = this;
+ m_fqlink->m_bqlink = item;
+ m_fqlink = item;
+ return true;
+ }
+ SG_QList *QRemove() // Remove from the front
+ {
+ if (QEmpty())
+ {
+ return NULL;
+ }
+ SG_QList* item = m_fqlink;
+ m_fqlink = item->m_fqlink;
+ m_fqlink->m_bqlink = this;
+ item->m_fqlink = item->m_bqlink = item;
+ return item;
+ }
+ void QDelink() // Remove from the middle
+ {
+ if (!QEmpty())
+ {
+ m_bqlink->m_fqlink = m_fqlink;
+ m_fqlink->m_bqlink = m_bqlink;
+ m_fqlink = m_bqlink = this;
+ }
+ }
+ inline SG_QList *QPeek() // Look at front without removing
+ {
+ return m_fqlink;
+ }
+};
+
+#endif //__SG_QLIST
+
diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp
index 2f3176816c6..97b15bdf376 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.cpp
+++ b/source/gameengine/SceneGraph/SG_Spatial.cpp
@@ -40,7 +40,7 @@ SG_Spatial::
SG_Spatial(
void* clientobj,
void* clientinfo,
- SG_Callbacks callbacks
+ SG_Callbacks& callbacks
):
SG_IObject(clientobj,clientinfo,callbacks),
@@ -56,8 +56,9 @@ SG_Spatial(
m_bbox(MT_Point3(-1.0, -1.0, -1.0), MT_Point3(1.0, 1.0, 1.0)),
m_radius(1.0),
- m_modified(true)
+ m_modified(false)
{
+ SetModified();
}
SG_Spatial::
@@ -88,13 +89,6 @@ SG_Spatial::
delete (m_parent_relation);
}
- SG_ParentRelation *
-SG_Spatial::
-GetParentRelation(
-){
- return m_parent_relation;
-}
-
void
SG_Spatial::
SetParentRelation(
@@ -102,7 +96,7 @@ SetParentRelation(
){
delete (m_parent_relation);
m_parent_relation = relation;
- m_modified = true;
+ SetModified();
}
@@ -143,11 +137,6 @@ UpdateSpatialData(
return bComputesWorldTransform;
}
-bool SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated)
-{
- return m_parent_relation->UpdateChildCoordinates(this,parent,parentUpdated);
-}
-
/**
* Position and translation methods
*/
@@ -169,56 +158,14 @@ RelativeTranslate(
m_localPosition += trans;
}
}
- m_modified = true;
+ SetModified();
}
- void
-SG_Spatial::
-SetLocalPosition(
- const MT_Point3& trans
-){
- m_localPosition = trans;
- m_modified = true;
-}
-
- void
-SG_Spatial::
-SetWorldPosition(
- const MT_Point3& trans
-) {
- m_worldPosition = trans;
-}
/**
* Scaling methods.
*/
- void
-SG_Spatial::
-RelativeScale(
- const MT_Vector3& scale
-){
- m_localScaling = m_localScaling * scale;
- m_modified = true;
-}
-
- void
-SG_Spatial::
-SetLocalScale(
- const MT_Vector3& scale
-){
- m_localScaling = scale;
- m_modified = true;
-}
-
-
- void
-SG_Spatial::
-SetWorldScale(
- const MT_Vector3& scale
-){
- m_worldScaling = scale;
-}
/**
* Orientation and rotation methods.
@@ -236,93 +183,11 @@ RelativeRotate(
rot
:
(GetWorldOrientation().inverse() * rot * GetWorldOrientation()));
- m_modified = true;
-}
-
- void
-SG_Spatial::
-SetLocalOrientation(const MT_Matrix3x3& rot)
-{
- m_localRotation = rot;
- m_modified = true;
+ SetModified();
}
- void
-SG_Spatial::
-SetWorldOrientation(
- const MT_Matrix3x3& rot
-) {
- m_worldRotation = rot;
-}
-
-const
- MT_Point3&
-SG_Spatial::
-GetLocalPosition(
-) const {
- return m_localPosition;
-}
-
-const
- MT_Matrix3x3&
-SG_Spatial::
-GetLocalOrientation(
-) const {
- return m_localRotation;
-}
-
-const
- MT_Vector3&
-SG_Spatial::
-GetLocalScale(
-) const{
- return m_localScaling;
-}
-
-
-const
- MT_Point3&
-SG_Spatial::
-GetWorldPosition(
-) const {
- return m_worldPosition;
-}
-
-const
- MT_Matrix3x3&
-SG_Spatial::
-GetWorldOrientation(
-) const {
- return m_worldRotation;
-}
-
-const
- MT_Vector3&
-SG_Spatial::
-GetWorldScaling(
-) const {
- return m_worldScaling;
-}
-
-void SG_Spatial::SetWorldFromLocalTransform()
-{
- m_worldPosition= m_localPosition;
- m_worldScaling= m_localScaling;
- m_worldRotation= m_localRotation;
-}
-
-SG_BBox& SG_Spatial::BBox()
-{
- return m_bbox;
-}
-
-void SG_Spatial::SetBBox(SG_BBox& bbox)
-{
- m_bbox = bbox;
-}
-
MT_Transform SG_Spatial::GetWorldTransform() const
{
return MT_Transform(m_worldPosition,
diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h
index c2ed80d21b2..eb1e87fbf19 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.h
+++ b/source/gameengine/SceneGraph/SG_Spatial.h
@@ -35,6 +35,7 @@
#include <MT_Matrix3x3.h> // or Quaternion later ?
#include "SG_IObject.h"
#include "SG_BBox.h"
+#include "SG_ParentRelation.h"
class SG_Node;
@@ -65,6 +66,16 @@ protected:
public:
+ inline void ClearModified()
+ {
+ m_modified = false;
+ }
+ inline void SetModified()
+ {
+ m_modified = true;
+ ActivateScheduleUpdateCallback();
+ }
+
/**
* Define the realtionship this node has with it's parent
* node. You should pass an unshared instance of an SG_ParentRelation
@@ -84,9 +95,12 @@ public:
SG_ParentRelation *relation
);
- SG_ParentRelation *
- GetParentRelation(
- );
+ SG_ParentRelation * GetParentRelation()
+ {
+ return m_parent_relation;
+ }
+
+
/**
@@ -105,15 +119,17 @@ public:
bool local
);
- void
- SetLocalPosition(
- const MT_Point3& trans
- );
+ void SetLocalPosition(const MT_Point3& trans)
+ {
+ m_localPosition = trans;
+ SetModified();
+ }
+
+ void SetWorldPosition(const MT_Point3& trans)
+ {
+ m_worldPosition = trans;
+ }
- void
- SetWorldPosition(
- const MT_Point3& trans
- );
void
RelativeRotate(
@@ -121,72 +137,95 @@ public:
bool local
);
- void
- SetLocalOrientation(
- const MT_Matrix3x3& rot
- );
-
- void
- SetWorldOrientation(
- const MT_Matrix3x3& rot
- );
-
- void
- RelativeScale(
- const MT_Vector3& scale
- );
-
- void
- SetLocalScale(
- const MT_Vector3& scale
- );
-
- void
- SetWorldScale(
- const MT_Vector3& scale
- );
-
- const
- MT_Point3&
- GetLocalPosition(
- ) const ;
+ void SetLocalOrientation(const MT_Matrix3x3& rot)
+ {
+ m_localRotation = rot;
+ SetModified();
+ }
+
+ void SetWorldOrientation(const MT_Matrix3x3& rot)
+ {
+ m_worldRotation = rot;
+ }
+
+ void RelativeScale(const MT_Vector3& scale)
+ {
+ m_localScaling = m_localScaling * scale;
+ SetModified();
+ }
+
+ void SetLocalScale(const MT_Vector3& scale)
+ {
+ m_localScaling = scale;
+ SetModified();
+ }
+
+ void SetWorldScale(const MT_Vector3& scale)
+ {
+ m_worldScaling = scale;
+ }
+
+ const MT_Point3& GetLocalPosition() const
+ {
+ return m_localPosition;
+ }
+
+ const MT_Matrix3x3& GetLocalOrientation() const
+ {
+ return m_localRotation;
+ }
+
+ const MT_Vector3& GetLocalScale() const
+ {
+ return m_localScaling;
+ }
+
+ const MT_Point3& GetWorldPosition() const
+ {
+ return m_worldPosition;
+ }
+
+ const MT_Matrix3x3& GetWorldOrientation() const
+ {
+ return m_worldRotation;
+ }
+
+ const MT_Vector3& GetWorldScaling() const
+ {
+ return m_worldScaling;
+ }
+
+ void SetWorldFromLocalTransform()
+ {
+ m_worldPosition= m_localPosition;
+ m_worldScaling= m_localScaling;
+ m_worldRotation= m_localRotation;
+ }
- const
- MT_Matrix3x3&
- GetLocalOrientation(
- ) const ;
- const
- MT_Vector3&
- GetLocalScale(
- ) const;
-
- const
- MT_Point3&
- GetWorldPosition(
- ) const ;
-
- const
- MT_Matrix3x3&
- GetWorldOrientation(
- ) const ;
-
- const
- MT_Vector3&
- GetWorldScaling(
- ) const ;
-
- void SetWorldFromLocalTransform();
MT_Transform GetWorldTransform() const;
- bool ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated);
+ bool ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated)
+ {
+ return m_parent_relation->UpdateChildCoordinates(this,parent,parentUpdated);
+ }
+
/**
* Bounding box functions.
*/
- SG_BBox& BBox();
- void SetBBox(SG_BBox & bbox);
+ SG_BBox& BBox()
+ {
+ return m_bbox;
+ }
+
+ void SetBBox(SG_BBox& bbox)
+ {
+ m_bbox = bbox;
+ }
+
+
bool inside(const MT_Point3 &point) const;
void getBBox(MT_Point3 *box) const;
void getAABBox(MT_Point3 *box) const;
@@ -210,7 +249,7 @@ protected:
SG_Spatial(
void* clientobj,
void* clientinfo,
- SG_Callbacks callbacks
+ SG_Callbacks& callbacks
);
SG_Spatial(
@@ -231,7 +270,6 @@ protected:
double time,
bool& parentUpdated
);
- void SetModified(bool modified) { m_modified = modified; }
};