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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user