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:
Diffstat (limited to 'source/gameengine/Ketsji/KX_Scene.cpp')
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp274
1 files changed, 192 insertions, 82 deletions
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 0fded15f1a1..aa7bd65f240 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -32,7 +32,6 @@
#pragma warning (disable : 4786)
#endif //WIN32
-
#include "KX_Scene.h"
#include "MT_assert.h"
@@ -77,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"
@@ -90,6 +91,8 @@
#include "CcdPhysicsController.h"
#endif
+#include "KX_Light.h"
+
void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
{
KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
@@ -134,6 +137,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_suspendedtime = 0.0;
m_suspendeddelta = 0.0;
+ m_dbvt_culling = false;
+ m_dbvt_occlusion_res = 0;
m_activity_culling = false;
m_suspend = false;
m_isclearingZbuffer = true;
@@ -191,7 +196,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_canvasDesignWidth = 0;
m_canvasDesignHeight = 0;
- m_attrlist = PyDict_New(); /* new ref */
+ m_attr_dict = PyDict_New(); /* new ref */
}
@@ -245,7 +250,8 @@ KX_Scene::~KX_Scene()
{
delete m_bucketmanager;
}
- //Py_DECREF(m_attrlist);
+ PyDict_Clear(m_attr_dict);
+ Py_DECREF(m_attr_dict);
}
void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
@@ -408,6 +414,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;
@@ -486,7 +499,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;
}
@@ -698,9 +718,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation();
replica->NodeSetLocalOrientation(newori);
-
+ MT_Point3 offset(group->dupli_ofs);
MT_Point3 newpos = groupobj->NodeGetWorldPosition() +
- newscale*(groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldPosition());
+ newscale*(groupobj->NodeGetWorldOrientation() * (gameobj->NodeGetWorldPosition()-offset));
replica->NodeSetLocalPosition(newpos);
replica->GetSGNode()->UpdateWorldData(0);
@@ -725,6 +745,12 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
(*git)->Relink(&m_map_gameobject_to_replica);
// add the object in the layer of the parent
(*git)->SetLayer(groupobj->GetLayer());
+ // If the object was a light, we need to update it's RAS_LightObject as well
+ if ((*git)->IsLight())
+ {
+ KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
+ lightobj->GetLightData()->m_layer = groupobj->GetLayer();
+ }
}
// replicate crosslinks etc. between logic bricks
@@ -793,6 +819,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)
@@ -807,6 +851,12 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
(*git)->Relink(&m_map_gameobject_to_replica);
// add the object in the layer of the parent
(*git)->SetLayer(parentobj->GetLayer());
+ // If the object was a light, we need to update it's RAS_LightObject as well
+ if ((*git)->IsLight())
+ {
+ KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
+ lightobj->GetLightData()->m_layer = parentobj->GetLayer();
+ }
}
// replicate crosslinks etc. between logic bricks
@@ -815,21 +865,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)
@@ -937,7 +972,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
newobj->RemoveMeshes();
ret = 1;
- if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell
+ if (newobj->IsLight() && m_lightlist->RemoveValue(newobj))
ret = newobj->Release();
if (m_objectlist->RemoveValue(newobj))
ret = newobj->Release();
@@ -963,6 +998,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
if (m_sceneConverter)
m_sceneConverter->UnregisterGameObject(newobj);
// return value will be 0 if the object is actually deleted (all reference gone)
+
return ret;
}
@@ -1164,7 +1200,6 @@ void KX_Scene::UpdateMeshTransformations()
{
KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
gameobj->GetOpenGLMatrix();
-// gameobj->UpdateNonDynas();
}
}
@@ -1299,21 +1334,47 @@ 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[6];
+ // get the clip planes
+ MT_Vector4* cplanes = cam->GetNormalizedClipPlanes();
+ // and convert
+ planes[0].setValue(cplanes[4].getValue()); // near
+ planes[1].setValue(cplanes[5].getValue()); // far
+ planes[2].setValue(cplanes[0].getValue()); // left
+ planes[3].setValue(cplanes[1].getValue()); // right
+ planes[4].setValue(cplanes[2].getValue()); // top
+ planes[5].setValue(cplanes[3].getValue()); // bottom
+ CullingInfo info(layer);
+ dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res);
+ }
+ 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
@@ -1394,7 +1455,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);
}
}
@@ -1518,22 +1579,22 @@ double KX_Scene::getSuspendedDelta()
//Python
PyTypeObject KX_Scene::Type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0,
"KX_Scene",
- sizeof(KX_Scene),
+ sizeof(PyObjectPlus_Proxy),
0,
- PyDestructor,
+ py_base_dealloc,
0,
- __getattr,
- __setattr,
- 0, //&MyPyCompare,
- __repr,
- 0, //&cvalue_as_number,
0,
0,
0,
- 0, 0, 0, 0, 0, 0
+ py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
PyParentObject KX_Scene::Parents[] = {
@@ -1551,52 +1612,102 @@ PyMethodDef KX_Scene::Methods[] = {
{NULL,NULL} //Sentinel
};
+PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ return PyString_FromString(self->GetName().ReadPtr());
+}
+
+PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ return self->GetObjectList()->GetProxy();
+}
+
+PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ return self->GetActiveCamera()->GetProxy();
+}
+
+/* __dict__ only for the purpose of giving useful dir() results */
+PyObject* KX_Scene::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ /* Useually done by py_getattro_up but in this case we want to include m_attr_dict dict */
+ PyObject *dict_str= PyString_FromString("__dict__");
+ PyObject *dict= py_getattr_dict(self->PyObjectPlus::py_getattro(dict_str), Type.tp_dict);
+ Py_DECREF(dict_str);
+
+ PyDict_Update(dict, self->m_attr_dict);
+ return dict;
+}
+
PyAttributeDef KX_Scene::Attributes[] = {
+ KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name),
+ KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects),
+ KX_PYATTRIBUTE_RO_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera),
+ 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
};
-PyObject* KX_Scene::_getattr(const char *attr)
+
+PyObject* KX_Scene::py_getattro__internal(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *pyvalue)
{
- if (!strcmp(attr, "name"))
- return PyString_FromString(GetName());
-
- if (!strcmp(attr, "objects"))
- return (PyObject*) m_objectlist->AddRef();
-
- if (!strcmp(attr, "active_camera"))
- return (PyObject*) GetActiveCamera()->AddRef();
-
- if (!strcmp(attr, "suspended"))
- return PyInt_FromLong(m_suspend);
-
- if (!strcmp(attr, "activity_culling"))
- return PyInt_FromLong(m_activity_culling);
-
- if (!strcmp(attr, "activity_culling_radius"))
- return PyFloat_FromDouble(m_activity_box_radius);
+ return PyObjectPlus::py_setattro(attr, pyvalue);
+}
+
+PyObject* KX_Scene::py_getattro(PyObject *attr)
+{
+ PyObject *object = py_getattro__internal(attr);
- PyObject* value = PyDict_GetItemString(m_attrlist, attr);
- if (value)
+ if (object==NULL)
{
- Py_INCREF(value);
- return value;
+ PyErr_Clear();
+ object = PyDict_GetItem(m_attr_dict, attr);
+ if(object) {
+ Py_INCREF(object);
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError, "value = scene.myAttr: KX_Scene, attribute \"%s\" not found", PyString_AsString(attr));
+ }
}
- _getattr_up(PyObjectPlus);
+ return object;
}
-int KX_Scene::_delattr(const char *attr)
+
+int KX_Scene::py_setattro(PyObject *attr, PyObject *value)
{
- PyDict_DelItemString(m_attrlist, attr);
- return 0;
+ int ret= py_setattro__internal(attr, value);
+
+ if (ret==PY_SET_ATTR_MISSING) {
+ if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
+ PyErr_Clear();
+ ret= PY_SET_ATTR_SUCCESS;
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "scene.UserAttr = value: KX_Scenes, failed assigning value to internal dictionary");
+ ret= PY_SET_ATTR_FAIL;
+ }
+ }
+
+ return ret;
}
-int KX_Scene::_setattr(const char *attr, PyObject *pyvalue)
+int KX_Scene::py_delattro(PyObject *attr)
{
- if (!PyDict_SetItemString(m_attrlist, attr, pyvalue))
- return 0;
-
- return PyObjectPlus::_setattr(attr, pyvalue);
+ PyDict_DelItem(m_attr_dict, attr);
+ return 0;
}
KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList,
@@ -1604,7 +1715,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList,
"Returns a list of all lights in the scene.\n"
)
{
- return (PyObject*) m_lightlist->AddRef();
+ return m_lightlist->GetProxy();
}
KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList,
@@ -1613,7 +1724,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList,
)
{
// ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work?
- return (PyObject*) m_objectlist->AddRef();
+ return m_objectlist->GetProxy();
}
KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName,
@@ -1633,15 +1744,14 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
int time = 0;
- if (!PyArg_ParseTuple(args, "OO|i", &pyob, &pyother, &time))
+ if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time))
return NULL;
- if (!ConvertPythonToGameObject(pyob, &ob, false)
- || !ConvertPythonToGameObject(pyother, &other, false))
+ if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") ||
+ !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") )
return NULL;
SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time);
- replica->AddRef();
- return replica;
+ return replica->GetProxy();
} \ No newline at end of file