Revision: 19887 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19887 Author: dfelinto Date: 2009-04-23 02:49:38 +0200 (Thu, 23 Apr 2009)
Log Message: ----------- BGE Rasterizer methods to handle Screen Space - (getScreenPosition, getScreenVect, getScreenRay) getScreenPosition(obj): - Gets the position of an object projected on screen space. getScreenVect(x, y): - Gets the vector from the camera position in the screen coordinate direction. 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 a call to KX_GameObject->rayCastTo from the KX_Camera object. Patch [#18589] test files can be found there. Patch reviewed by Campbell Modified Paths: -------------- trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp trunk/blender/source/gameengine/PyDoc/KX_GameObject.py trunk/blender/source/gameengine/PyDoc/Rasterizer.py Modified: trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp =================================================================== --- trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp 2009-04-23 00:47:45 UTC (rev 19886) +++ trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp 2009-04-23 00:49:38 UTC (rev 19887) @@ -484,6 +484,127 @@ }; +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)); @@ -897,6 +1018,12 @@ } 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, Modified: trunk/blender/source/gameengine/PyDoc/KX_GameObject.py =================================================================== --- trunk/blender/source/gameengine/PyDoc/KX_GameObject.py 2009-04-23 00:47:45 UTC (rev 19886) +++ trunk/blender/source/gameengine/PyDoc/KX_GameObject.py 2009-04-23 00:49:38 UTC (rev 19887) @@ -82,7 +82,7 @@ @ivar isValid: Retuerns fails when the object has been removed from the scene and can no longer be used. @type isValid: bool """ - def endObject(visible): + def endObject(): """ Delete this object, can be used inpace of the EndObject Actuator. The actual removal of the object from the scene is delayed. Modified: trunk/blender/source/gameengine/PyDoc/Rasterizer.py =================================================================== --- trunk/blender/source/gameengine/PyDoc/Rasterizer.py 2009-04-23 00:47:45 UTC (rev 19886) +++ trunk/blender/source/gameengine/PyDoc/Rasterizer.py 2009-04-23 00:49:38 UTC (rev 19887) @@ -44,6 +44,49 @@ """ +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 prop: property name that object must have; can be omitted => detect any object + @type prop: 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) _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs