259
274
if (m_set_frustum_center)
262
// The most extreme points on the near and far plane. (normalized device coords)
263
MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.);
277
// compute sphere for the general case and not only symmetric frustum:
278
// the mirror code in ImageRender can use very asymmetric frustum.
279
// We will put the sphere center on the line that goes from origin to the center of the far clipping plane
280
// This is the optimal position if the frustum is symmetric or very asymmetric and probably close
281
// to optimal for the general case. The sphere center position is computed so that the distance to
282
// the near and far extreme frustum points are equal.
284
// get the transformation matrix from device coordinate to camera coordinate
264
285
MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix;
265
286
clip_camcs_matrix.invert();
267
// Transform to hom camera local space
268
hnear = clip_camcs_matrix*hnear;
269
hfar = clip_camcs_matrix*hfar;
271
// Tranform to 3d camera local space.
272
MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]);
273
MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]);
276
m_frustum_center = MT_Point3(0., 0.,
277
(nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(m_camdata.m_clipend - m_camdata.m_clipstart)));
278
m_frustum_radius = m_frustum_center.distance(farpoint);
288
if (m_projection_matrix[3][3] == MT_Scalar(0.0))
290
// frustrum projection
291
// detect which of the corner of the far clipping plane is the farthest to the origin
292
MT_Vector4 nfar; // far point in device normalized coordinate
293
MT_Point3 farpoint; // most extreme far point in camera coordinate
294
MT_Point3 nearpoint;// most extreme near point in camera coordinate
295
MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate
296
MT_Scalar F=-1.0, N; // square distance of far and near point to origin
297
MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0
298
MT_Scalar e, s; // far and near clipping distance (<0)
299
MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance
300
MT_Scalar z; // projection of sphere center on z axis (<0)
302
MT_Vector4 npoint(1., 1., 1., 1.);
306
for (int i=0; i<4; i++)
308
hpoint = clip_camcs_matrix*npoint;
309
point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]);
310
len = point.dot(point);
317
// rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane
319
npoint[0] = -npoint[1];
323
// the far center is the average of the far clipping points
325
// the extreme near point is the opposite point on the near clipping plane
326
nfar.setValue(-nfar[0], -nfar[1], -1., 1.);
327
nfar = clip_camcs_matrix*nfar;
328
nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]);
329
// this is a frustrum projection
330
N = nearpoint.dot(nearpoint);
333
// projection on XY plane for distance to axis computation
334
MT_Point2 farxy(farpoint[0], farpoint[1]);
335
// f is forced positive by construction
337
// get corresponding point on the near plane
339
// this formula preserve the sign of n
340
n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length();
341
c = MT_Point2(farcenter[0], farcenter[1]).length()/e;
342
// the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case
343
z = (F-N)/(2.0*(e-s+c*(f-n)));
344
m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z);
345
m_frustum_radius = m_frustum_center.distance(farpoint);
349
// orthographic projection
350
// The most extreme points on the near and far plane. (normalized device coords)
351
MT_Vector4 hnear(1., 1., 1., 1.), hfar(-1., -1., -1., 1.);
353
// Transform to hom camera local space
354
hnear = clip_camcs_matrix*hnear;
355
hfar = clip_camcs_matrix*hfar;
357
// Tranform to 3d camera local space.
358
MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]);
359
MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]);
361
// just use mediant point
362
m_frustum_center = (farpoint + nearpoint)*0.5;
363
m_frustum_radius = m_frustum_center.distance(farpoint);
280
365
// Transform to world space.
281
366
m_frustum_center = GetCameraToWorld()(m_frustum_center);
282
367
m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]);
404
489
PyMethodDef KX_Camera::Methods[] = {
405
490
KX_PYMETHODTABLE(KX_Camera, sphereInsideFrustum),
406
KX_PYMETHODTABLE(KX_Camera, boxInsideFrustum),
407
KX_PYMETHODTABLE(KX_Camera, pointInsideFrustum),
408
KX_PYMETHODTABLE(KX_Camera, getCameraToWorld),
409
KX_PYMETHODTABLE(KX_Camera, getWorldToCamera),
410
KX_PYMETHODTABLE(KX_Camera, getProjectionMatrix),
411
KX_PYMETHODTABLE(KX_Camera, setProjectionMatrix),
412
KX_PYMETHODTABLE(KX_Camera, enableViewport),
491
KX_PYMETHODTABLE_O(KX_Camera, boxInsideFrustum),
492
KX_PYMETHODTABLE_O(KX_Camera, pointInsideFrustum),
493
KX_PYMETHODTABLE_NOARGS(KX_Camera, getCameraToWorld),
494
KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera),
413
495
KX_PYMETHODTABLE(KX_Camera, setViewport),
414
KX_PYMETHODTABLE(KX_Camera, setOnTop),
496
KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop),
497
KX_PYMETHODTABLE_O(KX_Camera, getScreenPosition),
498
KX_PYMETHODTABLE(KX_Camera, getScreenVect),
499
KX_PYMETHODTABLE(KX_Camera, getScreenRay),
502
KX_PYMETHODTABLE_O(KX_Camera, enableViewport),
503
KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix),
504
KX_PYMETHODTABLE_O(KX_Camera, setProjectionMatrix),
416
506
{NULL,NULL} //Sentinel
419
char KX_Camera::doc[] = "Module KX_Camera\n\n"
426
"\t\tThe camera's lens value\n"
428
"\t\tThe camera's near clip distance\n"
430
"\t\tThe camera's far clip distance\n"
431
"\tfrustum_culling -> bool\n"
432
"\t\tNon zero if this camera is frustum culling.\n"
433
"\tprojection_matrix -> [[float]]\n"
434
"\t\tThis camera's projection matrix.\n"
435
"\tmodelview_matrix -> [[float]] (read only)\n"
436
"\t\tThis camera's model view matrix.\n"
437
"\t\tRegenerated every frame from the camera's position and orientation.\n"
438
"\tcamera_to_world -> [[float]] (read only)\n"
439
"\t\tThis camera's camera to world transform.\n"
440
"\t\tRegenerated every frame from the camera's position and orientation.\n"
441
"\tworld_to_camera -> [[float]] (read only)\n"
442
"\t\tThis camera's world to camera transform.\n"
443
"\t\tRegenerated every frame from the camera's position and orientation.\n"
444
"\t\tThis is camera_to_world inverted.\n";
509
PyAttributeDef KX_Camera::Attributes[] = {
511
KX_PYATTRIBUTE_BOOL_RW("frustum_culling", KX_Camera, m_frustum_culling),
512
KX_PYATTRIBUTE_RW_FUNCTION("perspective", KX_Camera, pyattr_get_perspective, pyattr_set_perspective),
514
KX_PYATTRIBUTE_RW_FUNCTION("lens", KX_Camera, pyattr_get_lens, pyattr_set_lens),
515
KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near),
516
KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far),
518
KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport),
520
KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix),
521
KX_PYATTRIBUTE_RO_FUNCTION("modelview_matrix", KX_Camera, pyattr_get_modelview_matrix),
522
KX_PYATTRIBUTE_RO_FUNCTION("camera_to_world", KX_Camera, pyattr_get_camera_to_world),
523
KX_PYATTRIBUTE_RO_FUNCTION("world_to_camera", KX_Camera, pyattr_get_world_to_camera),
525
/* Grrr, functions for constants? */
526
KX_PYATTRIBUTE_RO_FUNCTION("INSIDE", KX_Camera, pyattr_get_INSIDE),
527
KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE", KX_Camera, pyattr_get_OUTSIDE),
528
KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT", KX_Camera, pyattr_get_INTERSECT),
446
533
PyTypeObject KX_Camera::Type = {
447
PyObject_HEAD_INIT(&PyType_Type)
534
#if (PY_VERSION_HEX >= 0x02060000)
535
PyVarObject_HEAD_INIT(NULL, 0)
537
/* python 2.5 and below */
538
PyObject_HEAD_INIT( NULL ) /* required py macro */
458
0, //&cvalue_as_number,
542
sizeof(PyObjectPlus_Proxy),
551
&KX_GameObject::Sequence,
552
&KX_GameObject::Mapping,
466
567
PyParentObject KX_Camera::Parents[] = {
467
568
&KX_Camera::Type,
468
569
&KX_GameObject::Type,
474
PyObject* KX_Camera::_getattr(const STR_String& attr)
476
if (attr == "INSIDE")
477
return PyInt_FromLong(INSIDE); /* new ref */
478
if (attr == "OUTSIDE")
479
return PyInt_FromLong(OUTSIDE); /* new ref */
480
if (attr == "INTERSECT")
481
return PyInt_FromLong(INTERSECT); /* new ref */
484
return PyFloat_FromDouble(GetLens()); /* new ref */
486
return PyFloat_FromDouble(GetCameraNear()); /* new ref */
488
return PyFloat_FromDouble(GetCameraFar()); /* new ref */
489
if (attr == "frustum_culling")
490
return PyInt_FromLong(m_frustum_culling); /* new ref */
491
if (attr == "perspective")
492
return PyInt_FromLong(m_camdata.m_perspective); /* new ref */
493
if (attr == "projection_matrix")
494
return PyObjectFrom(GetProjectionMatrix()); /* new ref */
495
if (attr == "modelview_matrix")
496
return PyObjectFrom(GetModelviewMatrix()); /* new ref */
497
if (attr == "camera_to_world")
498
return PyObjectFrom(GetCameraToWorld()); /* new ref */
499
if (attr == "world_to_camera")
500
return PyObjectFrom(GetWorldToCamera()); /* new ref */
502
_getattr_up(KX_GameObject);
505
int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue)
507
if (PyInt_Check(pyvalue))
509
if (attr == "frustum_culling")
511
m_frustum_culling = PyInt_AsLong(pyvalue);
515
if (attr == "perspective")
517
m_camdata.m_perspective = PyInt_AsLong(pyvalue);
522
if (PyFloat_Check(pyvalue))
526
m_camdata.m_lens = PyFloat_AsDouble(pyvalue);
527
m_set_projection_matrix = false;
532
m_camdata.m_clipstart = PyFloat_AsDouble(pyvalue);
533
m_set_projection_matrix = false;
538
m_camdata.m_clipend = PyFloat_AsDouble(pyvalue);
539
m_set_projection_matrix = false;
544
if (PyObject_IsMT_Matrix(pyvalue, 4))
546
if (attr == "projection_matrix")
549
if (PyMatTo(pyvalue, mat))
551
SetProjectionMatrix(mat);
557
return KX_GameObject::_setattr(attr, pyvalue);
560
KX_PYMETHODDEF_DOC(KX_Camera, sphereInsideFrustum,
575
PyObject* KX_Camera::py_getattro(PyObject *attr)
577
py_getattro_up(KX_GameObject);
580
PyObject* KX_Camera::py_getattro_dict() {
581
py_getattro_dict_up(KX_GameObject);
584
int KX_Camera::py_setattro(PyObject *attr, PyObject *value)
586
py_setattro_up(KX_GameObject);
589
KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum,
561
590
"sphereInsideFrustum(center, radius) -> Integer\n"
562
591
"\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n"
563
592
"\tinside/outside/intersects this camera's viewing frustum.\n\n"
738
761
"\tcam = co.getOwner()\n"
739
762
"\tcam.setProjectionMatrix(Perspective(-1.0, 1.0, -1.0, 1.0, 0.1, 1))\n")
742
if (PyArg_ParseTuple(args, "O", &pymat))
764
ShowDeprecationWarning("setProjectionMatrix(mat)", "the projection_matrix property");
767
if (!PyMatTo(value, mat))
745
if (PyMatTo(pymat, mat))
747
SetProjectionMatrix(mat);
769
PyErr_SetString(PyExc_TypeError, "camera.setProjectionMatrix(matrix): KX_Camera, expected 4x4 list as matrix argument.");
752
PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument.");
773
SetProjectionMatrix(mat);
756
KX_PYMETHODDEF_DOC(KX_Camera, enableViewport,
777
KX_PYMETHODDEF_DOC_O(KX_Camera, enableViewport,
757
778
"enableViewport(viewport)\n"
758
779
"Sets this camera's viewport status\n"
762
if (PyArg_ParseTuple(args,"i",&viewport))
765
EnableViewport(true);
767
EnableViewport(false);
782
ShowDeprecationWarning("enableViewport(bool)", "the useViewport property");
784
int viewport = PyObject_IsTrue(value);
785
if (viewport == -1) {
786
PyErr_SetString(PyExc_ValueError, "camera.enableViewport(bool): KX_Camera, expected True/False or 0/1");
791
EnableViewport(true);
793
EnableViewport(false);
776
KX_PYMETHODDEF_DOC(KX_Camera, setViewport,
798
KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport,
777
799
"setViewport(left, bottom, right, top)\n"
778
800
"Sets this camera's viewport\n")
780
802
int left, bottom, right, top;
781
if (PyArg_ParseTuple(args,"iiii",&left, &bottom, &right, &top))
783
SetViewport(left, bottom, right, top);
803
if (!PyArg_ParseTuple(args,"iiii:setViewport",&left, &bottom, &right, &top))
806
SetViewport(left, bottom, right, top);
790
KX_PYMETHODDEF_DOC(KX_Camera, setOnTop,
810
KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop,
792
812
"Sets this camera's viewport on top\n")
794
class KX_Scene* scene;
796
scene = PHY_GetActiveScene();
814
class KX_Scene* scene = KX_GetActiveScene();
798
815
scene->SetCameraOnTop(this);
819
PyObject* KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
821
KX_Camera* self= static_cast<KX_Camera*>(self_v);
822
return PyBool_FromLong(self->m_camdata.m_perspective);
825
int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
827
KX_Camera* self= static_cast<KX_Camera*>(self_v);
828
int param = PyObject_IsTrue( value );
830
PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1");
831
return PY_SET_ATTR_FAIL;
834
self->m_camdata.m_perspective= param;
835
return PY_SET_ATTR_SUCCESS;
838
PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
840
KX_Camera* self= static_cast<KX_Camera*>(self_v);
841
return PyFloat_FromDouble(self->m_camdata.m_lens);
844
int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
846
KX_Camera* self= static_cast<KX_Camera*>(self_v);
847
float param = PyFloat_AsDouble(value);
849
PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero");
850
return PY_SET_ATTR_FAIL;
853
self->m_camdata.m_lens= param;
854
self->m_set_projection_matrix = false;
855
return PY_SET_ATTR_SUCCESS;
858
PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
860
KX_Camera* self= static_cast<KX_Camera*>(self_v);
861
return PyFloat_FromDouble(self->m_camdata.m_clipstart);
864
int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
866
KX_Camera* self= static_cast<KX_Camera*>(self_v);
867
float param = PyFloat_AsDouble(value);
869
PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero");
870
return PY_SET_ATTR_FAIL;
873
self->m_camdata.m_clipstart= param;
874
self->m_set_projection_matrix = false;
875
return PY_SET_ATTR_SUCCESS;
878
PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
880
KX_Camera* self= static_cast<KX_Camera*>(self_v);
881
return PyFloat_FromDouble(self->m_camdata.m_clipend);
884
int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
886
KX_Camera* self= static_cast<KX_Camera*>(self_v);
887
float param = PyFloat_AsDouble(value);
889
PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero");
890
return PY_SET_ATTR_FAIL;
893
self->m_camdata.m_clipend= param;
894
self->m_set_projection_matrix = false;
895
return PY_SET_ATTR_SUCCESS;
899
PyObject* KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
901
KX_Camera* self= static_cast<KX_Camera*>(self_v);
902
return PyBool_FromLong(self->GetViewport());
905
int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
907
KX_Camera* self= static_cast<KX_Camera*>(self_v);
908
int param = PyObject_IsTrue( value );
910
PyErr_SetString(PyExc_AttributeError, "camera.useViewport = bool: KX_Camera, expected True or False");
911
return PY_SET_ATTR_FAIL;
913
self->EnableViewport((bool)param);
914
return PY_SET_ATTR_SUCCESS;
918
PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
920
KX_Camera* self= static_cast<KX_Camera*>(self_v);
921
return PyObjectFrom(self->GetProjectionMatrix());
924
int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
926
KX_Camera* self= static_cast<KX_Camera*>(self_v);
928
if (!PyMatTo(value, mat))
929
return PY_SET_ATTR_FAIL;
931
self->SetProjectionMatrix(mat);
932
return PY_SET_ATTR_SUCCESS;
935
PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
937
KX_Camera* self= static_cast<KX_Camera*>(self_v);
938
return PyObjectFrom(self->GetModelviewMatrix());
941
PyObject* KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
943
KX_Camera* self= static_cast<KX_Camera*>(self_v);
944
return PyObjectFrom(self->GetCameraToWorld());
947
PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
949
KX_Camera* self= static_cast<KX_Camera*>(self_v);
950
return PyObjectFrom(self->GetWorldToCamera());
954
PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
955
{ return PyInt_FromLong(INSIDE); }
956
PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
957
{ return PyInt_FromLong(OUTSIDE); }
958
PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
959
{ return PyInt_FromLong(INTERSECT); }
962
bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix)
965
PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
970
if (value==Py_None) {
976
PyErr_Format(PyExc_TypeError, "%s, expected KX_Camera or a KX_Camera name, None is invalid", error_prefix);
981
if (PyString_Check(value)) {
982
STR_String value_str = PyString_AsString(value);
983
*object = KX_GetActiveScene()->FindCamera(value_str);
988
PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, PyString_AsString(value));
993
if (PyObject_TypeCheck(value, &KX_Camera::Type)) {
994
*object = static_cast<KX_Camera*>BGE_PROXY_REF(value);
998
PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
1008
PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera, a string or None", error_prefix);
1010
PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera or a string", error_prefix);
1016
KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
1017
"getScreenPosition()\n"
1022
KX_GameObject *obj = NULL;
1024
if (!PyVecTo(value, vect))
1026
if(ConvertPythonToGameObject(value, &obj, true, ""))
1029
vect = MT_Vector3(obj->NodeGetWorldPosition());
1033
PyErr_SetString(PyExc_TypeError, "Error in getScreenPosition. Expected a Vector3 or a KX_GameObject or a string for a name of a KX_GameObject");
1040
GLdouble modelmatrix[16];
1041
GLdouble projmatrix[16];
1043
MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix();
1044
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
1046
m_modelmatrix.getValue(modelmatrix);
1047
m_projmatrix.getValue(projmatrix);
1049
glGetIntegerv(GL_VIEWPORT, viewport);
1051
gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
1053
vect[0] = (win[0] - viewport[0]) / viewport[2];
1054
vect[1] = (win[1] - viewport[1]) / viewport[3];
1056
vect[1] = 1.0 - vect[1]; //to follow Blender window coordinate system (Top-Down)
1058
PyObject* ret = PyTuple_New(2);
1060
PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0]));
1061
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1]));
1068
KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect,
1073
if (!PyArg_ParseTuple(args,"dd:getScreenVect",&x,&y))
1076
y = 1.0 - y; //to follow Blender window coordinate system (Top-Down)
1079
MT_Point3 campos, screenpos;
1083
GLdouble modelmatrix[16];
1084
GLdouble projmatrix[16];
1086
MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix();
1087
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
1089
m_modelmatrix.getValue(modelmatrix);
1090
m_projmatrix.getValue(projmatrix);
1092
glGetIntegerv(GL_VIEWPORT, viewport);
1094
vect[0] = x * viewport[2];
1095
vect[1] = y * viewport[3];
1097
vect[0] += viewport[0];
1098
vect[1] += viewport[1];
1100
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &vect[2]);
1101
gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
1103
campos = this->GetCameraLocation();
1104
screenpos = MT_Point3(win[0], win[1], win[2]);
1105
vect = campos-screenpos;
1108
return PyObjectFrom(vect);
1111
KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay,
1117
char *propName = NULL;
1119
if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName))
1122
PyObject* argValue = PyTuple_New(2);
1124
PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x));
1125
PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y));
1128
if(!PyVecTo(PygetScreenVect(argValue), vect))
1130
Py_DECREF(argValue);
1131
PyErr_SetString(PyExc_TypeError,
1132
"Error in getScreenRay. Invalid 2D coordinate. Expected a normalized 2D screen coordinate, a distance and an optional property argument");
1135
Py_DECREF(argValue);
1138
vect += this->GetCameraLocation();
1140
argValue = (propName?PyTuple_New(3):PyTuple_New(2));
1142
PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect));
1143
PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist));
1145
PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName));
1147
PyObject* ret= this->PyrayCastTo(argValue,NULL);
1148
Py_DECREF(argValue);