diff options
author | Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz> | 2004-05-21 13:18:42 +0400 |
---|---|---|
committer | Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz> | 2004-05-21 13:18:42 +0400 |
commit | 1217928e662bd74980dc17c8d32797b0bc6f7002 (patch) | |
tree | 1d46e362c2e3e114ebc2f30f5a942646d0f3bfc4 /source/gameengine/Ketsji | |
parent | 22883f9232da3df2bcba995bb0d84d4cf95803e8 (diff) |
Fixes for Camera objects and python:
Normalise clip planes for sphere testing.
Do a frustum-sphere <-> sphere test
Reference count all python objects (!)
Diffstat (limited to 'source/gameengine/Ketsji')
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.cpp | 147 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.h | 21 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_PyMath.cpp | 48 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_PythonInit.cpp | 36 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_PythonInit.h | 3 |
5 files changed, 181 insertions, 74 deletions
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index cad6501bd13..2e103e64445 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -42,13 +42,16 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, SG_Callbacks callbacks, const RAS_CameraData& camdata, - bool frustum_culling) + bool frustum_culling, + PyTypeObject *T) : - KX_GameObject(sgReplicationInfo,callbacks), + KX_GameObject(sgReplicationInfo,callbacks,T), m_camdata(camdata), m_dirty(true), + m_normalised(false), m_frustum_culling(frustum_culling), - m_set_projection_matrix(false) + m_set_projection_matrix(false), + m_set_frustum_centre(false) { // setting a name would be nice... m_name = "cam"; @@ -58,7 +61,6 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, } - KX_Camera::~KX_Camera() { } @@ -131,6 +133,7 @@ void KX_Camera::SetProjectionMatrix(const MT_Matrix4x4 & mat) m_projection_matrix = mat; m_dirty = true; m_set_projection_matrix = true; + m_set_frustum_centre = false; } @@ -142,6 +145,7 @@ void KX_Camera::SetModelviewMatrix(const MT_Matrix4x4 & mat) { m_modelview_matrix = mat; m_dirty = true; + m_set_frustum_centre = false; } @@ -201,6 +205,9 @@ RAS_CameraData* KX_Camera::GetCameraData() void KX_Camera::ExtractClipPlanes() { + if (!m_dirty) + return; + MT_Matrix4x4 m = m_projection_matrix * GetWorldToCamera(); // Left clip plane m_planes[0] = m[3] + m[0]; @@ -216,12 +223,52 @@ void KX_Camera::ExtractClipPlanes() m_planes[5] = m[3] - m[2]; m_dirty = false; + m_normalised = false; +} + +void KX_Camera::NormaliseClipPlanes() +{ + if (m_normalised) + return; + + for (unsigned int p = 0; p < 6; p++) + m_planes[p] /= sqrt(m_planes[p][0]*m_planes[p][0] + m_planes[p][1]*m_planes[p][1] + m_planes[p][2]*m_planes[p][2]); + + m_normalised = true; +} + +void KX_Camera::ExtractFrustumSphere() +{ + if (m_set_frustum_centre) + return; + + // The most extreme points on the near and far plane. (normalised device coords) + MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.); + MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix; + clip_camcs_matrix.invert(); + + // Transform to hom camera local space + hnear = clip_camcs_matrix*hnear; + hfar = clip_camcs_matrix*hfar; + + // Tranform to 3d camera local space. + MT_Point3 near(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]); + MT_Point3 far(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); + + // Compute centre + m_frustum_centre = MT_Point3(0., 0., + (near.dot(near) - far.dot(far))/(2.0*(m_camdata.m_clipend - m_camdata.m_clipstart))); + m_frustum_radius = m_frustum_centre.distance(far); + + // Transform to world space. + m_frustum_centre = GetCameraToWorld()(m_frustum_centre); + + m_set_frustum_centre = true; } bool KX_Camera::PointInsideFrustum(const MT_Point3& x) { - if (m_dirty) - ExtractClipPlanes(); + ExtractClipPlanes(); for( unsigned int i = 0; i < 6 ; i++ ) { @@ -233,26 +280,30 @@ bool KX_Camera::PointInsideFrustum(const MT_Point3& x) int KX_Camera::BoxInsideFrustum(const MT_Point3 *box) { - if (m_dirty) - ExtractClipPlanes(); + ExtractClipPlanes(); unsigned int insideCount = 0; + // 6 view frustum planes for( unsigned int p = 0; p < 6 ; p++ ) { unsigned int behindCount = 0; + // 8 box verticies. for (unsigned int v = 0; v < 8 ; v++) { if (m_planes[p][0]*box[v][0] + m_planes[p][1]*box[v][1] + m_planes[p][2]*box[v][2] + m_planes[p][3] < 0.) behindCount++; } + // 8 points behind this plane if (behindCount == 8) return OUTSIDE; + // Every box vertex is on the front side of this plane if (!behindCount) insideCount++; } + // All box verticies are on the front side of all frustum planes. if (insideCount == 6) return INSIDE; @@ -261,16 +312,28 @@ int KX_Camera::BoxInsideFrustum(const MT_Point3 *box) int KX_Camera::SphereInsideFrustum(const MT_Point3& centre, const MT_Scalar &radius) { + ExtractFrustumSphere(); + if (centre.distance2(m_frustum_centre) > (radius + m_frustum_radius)*(radius + m_frustum_radius)) + return OUTSIDE; + + unsigned int p; + ExtractClipPlanes(); + NormaliseClipPlanes(); + MT_Scalar distance; - for (unsigned int p = 0; p < 6; p++) + int intersect = INSIDE; + // distance: <-------- OUTSIDE -----|----- INTERSECT -----0----- INTERSECT -----|----- INSIDE --------> + // -radius radius + for (p = 0; p < 6; p++) { distance = m_planes[p][0]*centre[0] + m_planes[p][1]*centre[1] + m_planes[p][2]*centre[2] + m_planes[p][3]; - if (distance < -radius) + if (fabs(distance) <= radius) + intersect = INTERSECT; + else if (distance < -radius) return OUTSIDE; - if (fabs(distance) < radius) - return INTERSECT; } - return INSIDE; + + return intersect; } bool KX_Camera::GetFrustumCulling() const @@ -352,28 +415,28 @@ PyParentObject KX_Camera::Parents[] = { PyObject* KX_Camera::_getattr(const STR_String& attr) { if (attr == "INSIDE") - return PyInt_FromLong(INSIDE); + return PyInt_FromLong(INSIDE); /* new ref */ if (attr == "OUTSIDE") - return PyInt_FromLong(OUTSIDE); + return PyInt_FromLong(OUTSIDE); /* new ref */ if (attr == "INTERSECT") - return PyInt_FromLong(INTERSECT); + return PyInt_FromLong(INTERSECT); /* new ref */ if (attr == "lens") - return PyFloat_FromDouble(GetLens()); + return PyFloat_FromDouble(GetLens()); /* new ref */ if (attr == "near") - return PyFloat_FromDouble(GetCameraNear()); + return PyFloat_FromDouble(GetCameraNear()); /* new ref */ if (attr == "far") - return PyFloat_FromDouble(GetCameraFar()); + return PyFloat_FromDouble(GetCameraFar()); /* new ref */ if (attr == "frustum_culling") - return PyInt_FromLong(m_frustum_culling); + return PyInt_FromLong(m_frustum_culling); /* new ref */ if (attr == "projection_matrix") - return PyObjectFromMT_Matrix4x4(GetProjectionMatrix()); + return PyObjectFromMT_Matrix4x4(GetProjectionMatrix()); /* new ref */ if (attr == "modelview_matrix") - return PyObjectFromMT_Matrix4x4(GetModelviewMatrix()); + return PyObjectFromMT_Matrix4x4(GetModelviewMatrix()); /* new ref */ if (attr == "camera_to_world") - return PyObjectFromMT_Matrix4x4(GetCameraToWorld()); + return PyObjectFromMT_Matrix4x4(GetCameraToWorld()); /* new ref */ if (attr == "world_to_camera") - return PyObjectFromMT_Matrix4x4(GetWorldToCamera()); + return PyObjectFromMT_Matrix4x4(GetWorldToCamera()); /* new ref */ _getattr_up(KX_GameObject); } @@ -446,15 +509,15 @@ KX_PYMETHODDEF_DOC(KX_Camera, sphereInsideFrustum, if (PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "Expected list for argument centre."); - return Py_None; + Py_Return; } - return PyInt_FromLong(SphereInsideFrustum(centre, radius)); + return PyInt_FromLong(SphereInsideFrustum(centre, radius)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "Expected arguments: (centre, radius)"); - return Py_None; + Py_Return; } KX_PYMETHODDEF_DOC(KX_Camera, boxInsideFrustum, @@ -489,25 +552,27 @@ KX_PYMETHODDEF_DOC(KX_Camera, boxInsideFrustum, if (num_points != 8) { PyErr_Format(PyExc_TypeError, "Expected eight (8) points, got %d", num_points); - return Py_None; + Py_Return; } MT_Point3 box[8]; for (unsigned int p = 0; p < 8 ; p++) { - box[p] = MT_Point3FromPyList(PySequence_GetItem(pybox, p)); + PyObject *item = PySequence_GetItem(pybox, p); /* new ref */ + box[p] = MT_Point3FromPyList(item); + Py_DECREF(item); if (PyErr_Occurred()) { - return Py_None; + Py_Return; } } - return PyInt_FromLong(BoxInsideFrustum(box)); + return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "Expected argument: list of points."); - return Py_None; + Py_Return; } KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, @@ -531,13 +596,13 @@ KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, { MT_Point3 point = MT_Point3FromPyList(pypoint); if (PyErr_Occurred()) - return Py_None; + Py_Return; - return PyInt_FromLong(PointInsideFrustum(point)); + return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "Expected point argument."); - return Py_None; + Py_Return; } KX_PYMETHODDEF_DOC(KX_Camera, getCameraToWorld, @@ -546,7 +611,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getCameraToWorld, "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" ) { - return PyObjectFromMT_Matrix4x4(GetCameraToWorld()); + return PyObjectFromMT_Matrix4x4(GetCameraToWorld()); /* new ref */ } KX_PYMETHODDEF_DOC(KX_Camera, getWorldToCamera, @@ -555,7 +620,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getWorldToCamera, "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" ) { - return PyObjectFromMT_Matrix4x4(GetWorldToCamera()); + return PyObjectFromMT_Matrix4x4(GetWorldToCamera()); /* new ref */ } KX_PYMETHODDEF_DOC(KX_Camera, getProjectionMatrix, @@ -564,7 +629,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getProjectionMatrix, "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" ) { - return PyObjectFromMT_Matrix4x4(GetProjectionMatrix()); + return PyObjectFromMT_Matrix4x4(GetProjectionMatrix()); /* new ref */ } KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, @@ -615,13 +680,13 @@ KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, MT_Matrix4x4 mat = MT_Matrix4x4FromPyObject(pymat); if (PyErr_Occurred()) { - return Py_None; + Py_Return; } SetProjectionMatrix(mat); - return Py_None; + Py_Return; } PyErr_SetString(PyExc_TypeError, "Expected 4x4 list as matrix argument."); - return Py_None; + Py_Return; } diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 29bb35183f0..103c47fc3d6 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -82,6 +82,10 @@ protected: * regenerated. */ bool m_dirty; + /** + * true if the frustum planes have been normalised. + */ + bool m_normalised; /** * View Frustum clip planes. @@ -98,6 +102,13 @@ protected: * true if this camera has a valid projection matrix. */ bool m_set_projection_matrix; + + /** + * The centre point of the frustum. + */ + MT_Point3 m_frustum_centre; + MT_Scalar m_frustum_radius; + bool m_set_frustum_centre; /** * Python module doc string. @@ -108,11 +119,19 @@ protected: * Extracts the camera clip frames from the projection and world-to-camera matrices. */ void ExtractClipPlanes(); + /** + * Normalise the camera clip frames. + */ + void NormaliseClipPlanes(); + /** + * Extracts the bound sphere of the view frustum. + */ + void ExtractFrustumSphere(); public: typedef enum { INSIDE, INTERSECT, OUTSIDE } ; - KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true); + KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, PyTypeObject *T = &Type); virtual ~KX_Camera(); MT_Transform GetWorldToCamera() const; diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 3fd1b7be69b..287ae500ea5 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -69,12 +69,14 @@ MT_Vector3 MT_Vector3FromPyList(PyObject* pylist) } else { // assert the list is long enough... - unsigned int numitems = PyList_Size(pylist); + unsigned int numitems = PySequence_Size(pylist); if (numitems <= 3) { for (unsigned int index=0;index<numitems;index++) { - vec[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index)); + PyObject *item = PySequence_GetItem(pylist,index); /* new ref */ + vec[index] = PyFloat_AsDouble(item); + Py_DECREF(item); } } else @@ -111,12 +113,14 @@ MT_Point3 MT_Point3FromPyList(PyObject* pylist) } else { // assert the list is long enough... - unsigned int numitems = PyList_Size(pylist); + unsigned int numitems = PySequence_Size(pylist); if (numitems <= 3) { for (unsigned int index=0;index<numitems;index++) { - point[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index)); + PyObject *item = PySequence_GetItem(pylist,index); /* new ref */ + point[index] = PyFloat_AsDouble(item); + Py_DECREF(item); } } else @@ -153,12 +157,14 @@ MT_Vector4 MT_Vector4FromPyList(PyObject* pylist) } else { // assert the list is long enough... - unsigned int numitems = PyList_Size(pylist); + unsigned int numitems = PySequence_Size(pylist); if (numitems <= 4) { for (unsigned index=0;index<numitems;index++) { - vec[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index)); + PyObject *item = PySequence_GetItem(pylist,index); /* new ref */ + vec[index] = PyFloat_AsDouble(item); + Py_DECREF(item); } } else @@ -181,15 +187,18 @@ MT_Matrix4x4 MT_Matrix4x4FromPyObject(PyObject *pymat) unsigned int rows = PySequence_Size(pymat); for (unsigned int y = 0; y < rows && y < 4; y++) { - PyObject *pyrow = PySequence_GetItem(pymat, y); + PyObject *pyrow = PySequence_GetItem(pymat, y); /* new ref */ if (PySequence_Check(pyrow)) { unsigned int cols = PySequence_Size(pyrow); for( unsigned int x = 0; x < cols && x < 4; x++) { - mat[y][x] = PyFloat_AsDouble(PySequence_GetItem(pyrow, x)); + PyObject *item = PySequence_GetItem(pyrow, x); /* new ref */ + mat[y][x] = PyFloat_AsDouble(item); + Py_DECREF(item); } } + Py_DECREF(pyrow); } } @@ -206,15 +215,18 @@ MT_Matrix3x3 MT_Matrix3x3FromPyObject(PyObject *pymat) unsigned int rows = PySequence_Size(pymat); for (unsigned int y = 0; y < rows && y < 3; y++) { - PyObject *pyrow = PySequence_GetItem(pymat, y); + PyObject *pyrow = PySequence_GetItem(pymat, y); /* new ref */ if (PySequence_Check(pyrow)) { unsigned int cols = PySequence_Size(pyrow); for( unsigned int x = 0; x < cols && x < 3; x++) { - mat[y][x] = PyFloat_AsDouble(PySequence_GetItem(pyrow, x)); + PyObject *pyitem = PySequence_GetItem(pyrow, x); /* new ref */ + mat[y][x] = PyFloat_AsDouble(pyitem); + Py_DECREF(pyitem); } } + Py_DECREF(pyrow); } } @@ -223,16 +235,10 @@ MT_Matrix3x3 MT_Matrix3x3FromPyObject(PyObject *pymat) PyObject* PyObjectFromMT_Matrix4x4(const MT_Matrix4x4 &mat) { - PyObject *pymat = PyList_New(0); - for (unsigned int y = 0; y < 4; y++) - { - PyObject *row = PyList_New(0); - for( unsigned int x = 0; x < 4; x++ ) - { - PyList_Append(row, PyFloat_FromDouble(mat[y][x])); - } - PyList_Append(pymat, row); - } - return pymat; + return Py_BuildValue("[[ffff][ffff][ffff][ffff]]", + PyFloat_FromDouble(mat[0][0]), PyFloat_FromDouble(mat[0][1]), PyFloat_FromDouble(mat[0][2]), PyFloat_FromDouble(mat[0][3]), + PyFloat_FromDouble(mat[1][0]), PyFloat_FromDouble(mat[1][1]), PyFloat_FromDouble(mat[1][2]), PyFloat_FromDouble(mat[1][3]), + PyFloat_FromDouble(mat[2][0]), PyFloat_FromDouble(mat[2][1]), PyFloat_FromDouble(mat[2][2]), PyFloat_FromDouble(mat[2][3]), + PyFloat_FromDouble(mat[3][0]), PyFloat_FromDouble(mat[3][1]), PyFloat_FromDouble(mat[3][2]), PyFloat_FromDouble(mat[3][3])); } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index ee6a9f4a6cd..f4736f4c423 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -594,19 +594,40 @@ void setSandbox(TPythonSecurityLevel level) } } +/** + * Python is not initialised. + */ +PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level) +{ + STR_String pname = progname; + Py_SetProgramName(pname.Ptr()); + Py_NoSiteFlag=1; + Py_FrozenFlag=1; + Py_Initialize(); + //importBlenderModules() + + setSandbox(level); + PyObject* moduleobj = PyImport_AddModule("__main__"); + return PyModule_GetDict(moduleobj); +} + +void exitGamePlayerPythonScripting() +{ + Py_Finalize(); +} + +/** + * Python is already initialized. + */ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level) { STR_String pname = progname; Py_SetProgramName(pname.Ptr()); Py_NoSiteFlag=1; Py_FrozenFlag=1; -#ifndef USE_BLENDER_PYTHON - Py_Initialize(); -#else - BPY_start_python(); -#endif + setSandbox(level); PyObject* moduleobj = PyImport_AddModule("__main__"); @@ -617,11 +638,6 @@ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLev void exitGamePythonScripting() { -#ifndef USE_BLENDER_PYTHON - Py_Finalize(); -#else - BPY_end_python(); -#endif } diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 7999014991a..dc4bad05efb 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -46,9 +46,10 @@ extern bool gUseVisibilityTemp; PyObject* initGameLogic(class KX_Scene* ketsjiscene); PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); +PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level); +void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); void exitGamePythonScripting(); -void exitGamePythonScripting(); void PHY_SetActiveScene(class KX_Scene* scene); #endif //__KX_PYTHON_INIT |