diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2009-05-20 09:33:39 +0400 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2009-05-20 09:33:39 +0400 |
commit | dc6ae673b1d95d28c4fab4dbfbd9947d4a6c3bb2 (patch) | |
tree | 66e3d7b21af2a3bace141e9bbec24d9ccbb2607d | |
parent | fc9f893306c359c8a9102745840d749f056fcbed (diff) |
Moving ScreenSpace methods from Rasterizer to KX_Camera (getScreenPos, getScreenVect, getScreenRay)
The modules were moved in order to access the camera internal matrixes. It will make then compatible with multiple viewports in a near future.
So far the problem I found was:
1) KX_Camera doesn't store the canvas viewport
2) RAS_ICanvas methods: GetDisplayArea and GetWindowArea are affected by multiple viewports (and they shouldn't).
Test file is here: http://www.pasteall.org/blend/68
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.cpp | 144 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.h | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_PythonInit.cpp | 128 | ||||
-rw-r--r-- | source/gameengine/PyDoc/GameTypes.py | 43 | ||||
-rw-r--r-- | source/gameengine/PyDoc/Rasterizer.py | 44 |
5 files changed, 189 insertions, 174 deletions
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index fe50b371475..4bef4936813 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -28,6 +28,7 @@ * Camera in the gameengine. Cameras are also used for views. */ +#include "GL/glew.h" #include "KX_Camera.h" #include "KX_Scene.h" #include "KX_PythonInit.h" @@ -478,7 +479,10 @@ PyMethodDef KX_Camera::Methods[] = { KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera), KX_PYMETHODTABLE(KX_Camera, setViewport), KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop), - + KX_PYMETHODTABLE_O(KX_Camera, getScreenPosition), + KX_PYMETHODTABLE(KX_Camera, getScreenVect), + KX_PYMETHODTABLE(KX_Camera, getScreenRay), + // DEPRECATED KX_PYMETHODTABLE_O(KX_Camera, enableViewport), KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix), @@ -989,4 +993,140 @@ bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok } return false; -}
\ No newline at end of file +} + +KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, +"getScreenPosition()\n" +) + +{ + MT_Vector3 vect; + KX_GameObject *obj = NULL; + + if (!PyVecTo(value, vect)) + { + if(ConvertPythonToGameObject(value, &obj, true, "")) + { + PyErr_Clear(); + vect = MT_Vector3(obj->NodeGetWorldPosition()); + } + else + { + PyErr_SetString(PyExc_TypeError, "Error in getScreenPosition. Expected a Vector3 or a KX_GameObject or a string for a name of a KX_GameObject"); + return NULL; + } + } + + GLint viewport[4]; + GLdouble win[3]; + GLdouble modelmatrix[16]; + GLdouble projmatrix[16]; + + MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); + + m_modelmatrix.getValue(modelmatrix); + m_projmatrix.getValue(projmatrix); + + glGetIntegerv(GL_VIEWPORT, viewport); + + gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); + + vect[0] = win[0] / (viewport[0] + viewport[2]); + vect[1] = win[1] / (viewport[1] + viewport[3]); + + PyObject* ret = PyTuple_New(2); + if(ret){ + PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0])); + PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1])); + return ret; + } + + return NULL; +} + +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, +"getScreenVect()\n" +) +{ + double x,y; + if (!PyArg_ParseTuple(args,"dd:getScreenVect",&x,&y)) + return NULL; + + MT_Vector3 vect; + MT_Point3 campos, screenpos; + + GLint viewport[4]; + GLdouble win[3]; + GLdouble modelmatrix[16]; + GLdouble projmatrix[16]; + + MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); + + m_modelmatrix.getValue(modelmatrix); + m_projmatrix.getValue(projmatrix); + + glGetIntegerv(GL_VIEWPORT, viewport); + + vect[0] = x * viewport[2]; + vect[1] = y * viewport[3]; + + vect[0] += viewport[0]; + vect[1] += viewport[1]; + + glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &vect[2]); + gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); + + campos = this->GetCameraLocation(); + screenpos = MT_Point3(win[0], win[1], win[2]); + vect = campos-screenpos; + + vect.normalize(); + return PyObjectFrom(vect); +} + +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, +"getScreenRay()\n" +) +{ + KX_Camera* cam; + MT_Vector3 vect; + double x,y,dist; + char *propName = NULL; + + if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName)) + return NULL; + + PyObject* argValue = PyTuple_New(2); + if (argValue) { + PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x)); + PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y)); + } + + if(!PyVecTo(PygetScreenVect(argValue), vect)) + { + Py_DECREF(argValue); + PyErr_SetString(PyExc_TypeError, + "Error in getScreenRay. Invalid 2D coordinate. Expected a normalized 2D screen coordinate, a distance and an optional property argument"); + return NULL; + } + Py_DECREF(argValue); + + dist *= -1.0; + + argValue = (propName?PyTuple_New(3):PyTuple_New(2)); + if (argValue) { + PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect)); + PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist)); + if (propName) + PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName)); + + PyObject* ret= this->PyrayCastTo(argValue,NULL); + Py_DECREF(argValue); + return ret; + } + + return NULL; +} + diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index c00741bf43f..2ec60be0404 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -273,6 +273,10 @@ public: KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); + KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenRay); + virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index d32f3b1b8a2..fb99eab7747 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -511,128 +511,6 @@ static struct PyMethodDef game_methods[] = { {NULL, (PyCFunction) NULL, 0, NULL } }; - -static PyObject* gPyGetScreenPosition(PyObject*, PyObject* value) -{ - MT_Vector3 vect; - KX_GameObject *obj = NULL; - - if (!PyVecTo(value, vect)) - { - if(ConvertPythonToGameObject(value, &obj, true, "")) - { - PyErr_Clear(); - vect = MT_Vector3(obj->NodeGetWorldPosition()); - } - else - { - PyErr_SetString(PyExc_TypeError, "Error in getScreenPosition. Expected a Vector3 or a KX_GameObject or a string for a name of a KX_GameObject"); - return NULL; - } - } - - GLdouble modelMatrix[16]; - GLdouble projMatrix[16]; - GLint viewport[4]; - GLdouble win[3]; - - glGetIntegerv(GL_VIEWPORT, viewport); - glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); - glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); - - gluProject(vect[0], vect[1], vect[2], modelMatrix, projMatrix, viewport, &win[0], &win[1], &win[2]); - - vect[0] = win[0] / (viewport[0] + viewport[2]); - vect[1] = win[1] / (viewport[1] + viewport[3]); - - PyObject* ret = PyTuple_New(2); - if(ret){ - PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0])); - PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1])); - return ret; - } - - return NULL; -} - -static PyObject* gPyGetScreenVect(PyObject*, PyObject* args) -{ - double x,y; - if (!PyArg_ParseTuple(args,"dd:getScreenVect",&x,&y)) - return NULL; - - MT_Vector3 vect; - MT_Point3 campos, screenpos; - - GLdouble modelMatrix[16]; - GLdouble projMatrix[16]; - GLint viewport[4]; - GLdouble win[3]; - - glGetIntegerv(GL_VIEWPORT, viewport); - glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); - glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); - - vect[0] = x * viewport[2]; - vect[1] = y * viewport[3]; - - vect[0] += viewport[0]; - vect[1] += viewport[1]; - - glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &vect[2]); - gluUnProject(vect[0], vect[1], vect[2], modelMatrix, projMatrix, viewport, &win[0], &win[1], &win[2]); - - campos = gp_Rasterizer->GetCameraPosition(); - screenpos = MT_Point3(win[0], win[1], win[2]); - vect = campos-screenpos; - - vect.normalize(); - return PyObjectFrom(vect); -} - -static PyObject* gPyGetScreenRay(PyObject* self, PyObject* args) -{ - KX_Camera* cam; - MT_Vector3 vect; - double x,y,dist; - char *propName = NULL; - - if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName)) - return NULL; - - PyObject* argValue = PyTuple_New(2); - if (argValue) { - PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x)); - PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y)); - } - - if(!PyVecTo(gPyGetScreenVect(self,argValue), vect)) - { - Py_DECREF(argValue); - PyErr_SetString(PyExc_TypeError, - "Error in getScreenRay. Invalid 2D coordinate. Expected a normalized 2D screen coordinate and an optional property argument"); - return NULL; - } - Py_DECREF(argValue); - - cam = gp_KetsjiScene->GetActiveCamera(); - dist *= -1.0; - - argValue = (propName?PyTuple_New(3):PyTuple_New(2)); - if (argValue) { - PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect)); - PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist)); - if (propName) - PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName)); - - PyObject* ret= cam->PyrayCastTo(argValue,NULL); - Py_DECREF(argValue); - return ret; - } - - return NULL; -} - static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); @@ -1047,12 +925,6 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args) } static struct PyMethodDef rasterizer_methods[] = { - {"getScreenPosition",(PyCFunction) gPyGetScreenPosition, - METH_O, "getScreenPosition doc"}, - {"getScreenVect",(PyCFunction) gPyGetScreenVect, - METH_VARARGS, "getScreenVect doc"}, - {"getScreenRay",(PyCFunction) gPyGetScreenRay, - METH_VARARGS, "getScreenRay doc"}, {"getWindowWidth",(PyCFunction) gPyGetWindowWidth, METH_VARARGS, "getWindowWidth doc"}, {"getWindowHeight",(PyCFunction) gPyGetWindowHeight, diff --git a/source/gameengine/PyDoc/GameTypes.py b/source/gameengine/PyDoc/GameTypes.py index 5ec6f31e30c..b5dc89e4002 100644 --- a/source/gameengine/PyDoc/GameTypes.py +++ b/source/gameengine/PyDoc/GameTypes.py @@ -5555,6 +5555,49 @@ class KX_Camera(KX_GameObject): @type right: int @type top: int """ + def getScreenPosition(arg): + """ + Gets the position of an object projected on screen space. + + Example: + # For an object in the middle of the screen, coord = [0.5,0.5] + coord = camera.getScreenPosition(object) + + @param arg: L{KX_GameObject}, object name or list [x, y, z] + @rtype: list [x, y] + @return: the object's position in screen coordinates. + """ + def getScreenVect(x, y): + """ + Gets the vector from the camera position in the screen coordinate direction. + + Example: + # Gets the vector of the camera front direction: + m_vect = camera.getScreenVect(0.5,0.5) + + @type x: float + @type y: float + @rtype: 3d vector + @return: the vector from a screen coordinate. + """ + def getScreenRay(x, y, dist, property): + """ + Look towards a screen coordinate (x,y) and find first object hit within dist that matches prop. + The ray is similar to KX_GameObject->rayCastTo. + + Example: + # Gets an object with a property "wall" in front of the camera within a distance of 100: + target = camera.getScreenRay(0.5,0.5,100,"wall") + + @type x: float + @type y: float + @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other + @type dist: float + @param property: property name that object must have; can be omitted => detect any object + @type property: string + @rtype: L{KX_GameObject} + @return: the first object hit or None if no object or object does not match prop + """ # Util func to extract all attrs """ diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index 25877364836..bafcfece473 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -43,50 +43,6 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M @var KX_BLENDER_GLSL_MATERIAL: Materials approximating blender materials with GLSL. """ - -def getScreenPosition(arg): - """ - Gets the position of an object projected on screen space. - - Example: - # For an object in the middle of the screen, coord = [0.5,0.5] - coord = Rasterizer.getScreenPosition(object) - - @param arg: L{KX_GameObject}, object name or list [x, y, z] - @rtype: list [x, y] - @return: the object's position in screen coordinates. - """ -def getScreenVect(x, y): - """ - Gets the vector from the camera position in the screen coordinate direction. - - Example: - # Gets the vector of the camera front direction: - m_vect = Rasterizer.getScreenVect(0.5,0.5) - - @type x: float - @type y: float - @rtype: 3d vector - @return: the vector from a screen coordinate. - """ -def getScreenRay(x, y, dist, property): - """ - Look towards a screen coordinate (x,y) and find first object hit within dist that matches prop. - The ray is similar to KX_GameObject->rayCastTo. - - Example: - # Gets an object with a property "wall" in front of the camera within a distance of 100: - target = Rasterizer.getScreenRay(0.5,0.5,100,"wall") - - @type x: float - @type y: float - @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other - @type dist: float - @param property: property name that object must have; can be omitted => detect any object - @type property: string - @rtype: L{KX_GameObject} - @return: the first object hit or None if no object or object does not match prop - """ def getWindowWidth(): """ Gets the width of the window (in pixels) |