Changeset View
Changeset View
Standalone View
Standalone View
source/gameengine/Ketsji/KX_Camera.cpp
| Context not available. | |||||
| #include "glew-mx.h" | #include "glew-mx.h" | ||||
| #include "KX_Camera.h" | #include "KX_Camera.h" | ||||
| #include "KX_Scene.h" | #include "KX_Scene.h" | ||||
| #include "KX_PythonInit.h" | #include "KX_Globals.h" | ||||
| #include "EXP_Python.h" | #include "EXP_Python.h" | ||||
| #include "KX_PyMath.h" | #include "KX_PyMath.h" | ||||
| Context not available. | |||||
| m_frustum_culling(frustum_culling), | m_frustum_culling(frustum_culling), | ||||
| m_set_projection_matrix(false), | m_set_projection_matrix(false), | ||||
| m_set_frustum_center(false), | m_set_frustum_center(false), | ||||
| m_delete_node(delete_node) | m_delete_node(delete_node), | ||||
| m_lodDistanceFactor(1.0f) | |||||
| { | { | ||||
| // setting a name would be nice... | // setting a name would be nice... | ||||
| m_name = "cam"; | m_name = "cam"; | ||||
| Context not available. | |||||
| const MT_Point3 KX_Camera::GetCameraLocation() const | const MT_Vector3 KX_Camera::GetCameraLocation() const | ||||
| { | { | ||||
| /* this is the camera locatio in cam coords... */ | /* this is the camera locatio in cam coords... */ | ||||
| //return m_trans1.getOrigin(); | //return m_trans1.getOrigin(); | ||||
| //return MT_Point3(0,0,0); <----- | //return MT_Vector3(0,0,0); <----- | ||||
| /* .... I want it in world coords */ | /* .... I want it in world coords */ | ||||
| //MT_Transform trans; | //MT_Transform trans; | ||||
| //trans.setBasis(NodeGetWorldOrientation()); | //trans.setBasis(NodeGetWorldOrientation()); | ||||
| Context not available. | |||||
| return &m_camdata; | return &m_camdata; | ||||
| } | } | ||||
| float KX_Camera::GetLodDistanceFactor() const | |||||
| { | |||||
| return m_lodDistanceFactor; | |||||
| } | |||||
| void KX_Camera::SetLodDistanceFactor(float lodfactor) | |||||
| { | |||||
| m_lodDistanceFactor = lodfactor; | |||||
| } | |||||
| void KX_Camera::ExtractClipPlanes() | void KX_Camera::ExtractClipPlanes() | ||||
| { | { | ||||
| if (!m_dirty) | if (!m_dirty) | ||||
| Context not available. | |||||
| // frustum projection | // frustum projection | ||||
| // detect which of the corner of the far clipping plane is the farthest to the origin | // detect which of the corner of the far clipping plane is the farthest to the origin | ||||
| MT_Vector4 nfar; // far point in device normalized coordinate | MT_Vector4 nfar; // far point in device normalized coordinate | ||||
| MT_Point3 farpoint; // most extreme far point in camera coordinate | MT_Vector3 farpoint; // most extreme far point in camera coordinate | ||||
| MT_Point3 nearpoint;// most extreme near point in camera coordinate | MT_Vector3 nearpoint;// most extreme near point in camera coordinate | ||||
| MT_Point3 farcenter(0.0f, 0.0f, 0.0f);// center of far cliping plane in camera coordinate | MT_Vector3 farcenter(0.0f, 0.0f, 0.0f);// center of far cliping plane in camera coordinate | ||||
| MT_Scalar F=-1.0f, N; // square distance of far and near point to origin | MT_Scalar F=-1.0f, N; // square distance of far and near point to origin | ||||
| MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0 | MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0 | ||||
| MT_Scalar e, s; // far and near clipping distance (<0) | MT_Scalar e, s; // far and near clipping distance (<0) | ||||
| Context not available. | |||||
| // tmp value | // tmp value | ||||
| MT_Vector4 npoint(1.0f, 1.0f, 1.0f, 1.0f); | MT_Vector4 npoint(1.0f, 1.0f, 1.0f, 1.0f); | ||||
| MT_Vector4 hpoint; | MT_Vector4 hpoint; | ||||
| MT_Point3 point; | MT_Vector3 point; | ||||
| MT_Scalar len; | MT_Scalar len; | ||||
| for (int i=0; i<4; i++) | for (int i=0; i<4; i++) | ||||
| { | { | ||||
| Context not available. | |||||
| e = farpoint[2]; | e = farpoint[2]; | ||||
| s = nearpoint[2]; | s = nearpoint[2]; | ||||
| // projection on XY plane for distance to axis computation | // projection on XY plane for distance to axis computation | ||||
| MT_Point2 farxy(farpoint[0], farpoint[1]); | MT_Vector2 farxy(farpoint[0], farpoint[1]); | ||||
| // f is forced positive by construction | // f is forced positive by construction | ||||
| f = farxy.length(); | f = farxy.length(); | ||||
| // get corresponding point on the near plane | // get corresponding point on the near plane | ||||
| farxy *= s/e; | farxy *= s/e; | ||||
| // this formula preserve the sign of n | // this formula preserve the sign of n | ||||
| n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); | n = f*s/e - MT_Vector2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); | ||||
| c = MT_Point2(farcenter[0], farcenter[1]).length()/e; | c = MT_Vector2(farcenter[0], farcenter[1]).length()/e; | ||||
| // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case | // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case | ||||
| z = (F-N)/(2.0f*(e-s+c*(f-n))); | z = (F-N)/(2.0f*(e-s+c*(f-n))); | ||||
| m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); | m_frustum_center = MT_Vector3(farcenter[0]*z/e, farcenter[1]*z/e, z); | ||||
| m_frustum_radius = m_frustum_center.distance(farpoint); | m_frustum_radius = m_frustum_center.distance(farpoint); | ||||
| } | } | ||||
| else | else | ||||
| Context not available. | |||||
| hfar = clip_camcs_matrix*hfar; | hfar = clip_camcs_matrix*hfar; | ||||
| // Tranform to 3d camera local space. | // Tranform to 3d camera local space. | ||||
| MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]); | MT_Vector3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]); | ||||
| MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); | MT_Vector3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); | ||||
| // just use mediant point | // just use mediant point | ||||
| m_frustum_center = (farpoint + nearpoint)*0.5f; | m_frustum_center = (farpoint + nearpoint)*0.5f; | ||||
| Context not available. | |||||
| m_set_frustum_center = true; | m_set_frustum_center = true; | ||||
| } | } | ||||
| bool KX_Camera::PointInsideFrustum(const MT_Point3& x) | bool KX_Camera::PointInsideFrustum(const MT_Vector3& x) | ||||
| { | { | ||||
| ExtractClipPlanes(); | ExtractClipPlanes(); | ||||
| Context not available. | |||||
| return true; | return true; | ||||
| } | } | ||||
| int KX_Camera::BoxInsideFrustum(const MT_Point3 *box) | int KX_Camera::BoxInsideFrustum(const MT_Vector3 *box) | ||||
| { | { | ||||
| ExtractClipPlanes(); | ExtractClipPlanes(); | ||||
| Context not available. | |||||
| return INTERSECT; | return INTERSECT; | ||||
| } | } | ||||
| int KX_Camera::SphereInsideFrustum(const MT_Point3& center, const MT_Scalar &radius) | int KX_Camera::SphereInsideFrustum(const MT_Vector3& center, const MT_Scalar &radius) | ||||
| { | { | ||||
| ExtractFrustumSphere(); | ExtractFrustumSphere(); | ||||
| if (center.distance2(m_frustum_center) > (radius + m_frustum_radius)*(radius + m_frustum_radius)) | if (center.distance2(m_frustum_center) > (radius + m_frustum_radius)*(radius + m_frustum_radius)) | ||||
| Context not available. | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far), | KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("shift_x", KX_Camera, pyattr_get_shift_x, pyattr_set_shift_x), | KX_PYATTRIBUTE_RW_FUNCTION("shift_x", KX_Camera, pyattr_get_shift_x, pyattr_set_shift_x), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("shift_y", KX_Camera, pyattr_get_shift_y, pyattr_set_shift_y), | KX_PYATTRIBUTE_RW_FUNCTION("shift_y", KX_Camera, pyattr_get_shift_y, pyattr_set_shift_y), | ||||
| KX_PYATTRIBUTE_FLOAT_RW("lodDistanceFactor", 0.0f, FLT_MAX, KX_Camera, m_lodDistanceFactor), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport), | KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport), | ||||
| Context not available. | |||||
| KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE", KX_Camera, pyattr_get_OUTSIDE), | KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE", KX_Camera, pyattr_get_OUTSIDE), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT", KX_Camera, pyattr_get_INTERSECT), | KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT", KX_Camera, pyattr_get_INTERSECT), | ||||
| { NULL } //Sentinel | KX_PYATTRIBUTE_NULL //Sentinel | ||||
| }; | }; | ||||
| PyTypeObject KX_Camera::Type = { | PyTypeObject KX_Camera::Type = { | ||||
| Context not available. | |||||
| float radius; | float radius; | ||||
| if (PyArg_ParseTuple(args, "Of:sphereInsideFrustum", &pycenter, &radius)) | if (PyArg_ParseTuple(args, "Of:sphereInsideFrustum", &pycenter, &radius)) | ||||
| { | { | ||||
| MT_Point3 center; | MT_Vector3 center; | ||||
| if (PyVecTo(pycenter, center)) | if (PyVecTo(pycenter, center)) | ||||
| { | { | ||||
| return PyLong_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ | return PyLong_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ | ||||
| Context not available. | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| MT_Point3 box[8]; | MT_Vector3 box[8]; | ||||
| for (unsigned int p = 0; p < 8 ; p++) | for (unsigned int p = 0; p < 8 ; p++) | ||||
| { | { | ||||
| PyObject *item = PySequence_GetItem(value, p); /* new ref */ | PyObject *item = PySequence_GetItem(value, p); /* new ref */ | ||||
| Context not available. | |||||
| "\t\t# Box is outside the frustum !\n" | "\t\t# Box is outside the frustum !\n" | ||||
| ) | ) | ||||
| { | { | ||||
| MT_Point3 point; | MT_Vector3 point; | ||||
| if (PyVecTo(value, point)) | if (PyVecTo(value, point)) | ||||
| { | { | ||||
| return PyLong_FromLong(PointInsideFrustum(point)); /* new ref */ | return PyLong_FromLong(PointInsideFrustum(point)); /* new ref */ | ||||
| Context not available. | |||||
| "\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" | "\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 PyObjectFrom(GetCameraToWorld()); /* new ref */ | return PyObjectFrom(MT_Matrix4x4(GetCameraToWorld())); /* new ref */ | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getWorldToCamera, | KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getWorldToCamera, | ||||
| Context not available. | |||||
| "\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" | "\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 PyObjectFrom(GetWorldToCamera()); /* new ref */ | return PyObjectFrom(MT_Matrix4x4(GetWorldToCamera())); /* new ref */ | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport, | KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport, | ||||
| Context not available. | |||||
| "setOnTop()\n" | "setOnTop()\n" | ||||
| "Sets this camera's viewport on top\n") | "Sets this camera's viewport on top\n") | ||||
| { | { | ||||
| class KX_Scene* scene = KX_GetActiveScene(); | GetScene()->SetCameraOnTop(this); | ||||
| scene->SetCameraOnTop(this); | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_Camera* self = static_cast<KX_Camera*>(self_v); | KX_Camera* self = static_cast<KX_Camera*>(self_v); | ||||
| Context not available. | |||||
| PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_Camera* self = static_cast<KX_Camera*>(self_v); | KX_Camera* self = static_cast<KX_Camera*>(self_v); | ||||
| return PyObjectFrom(self->GetWorldToCamera()); | return PyObjectFrom(MT_Matrix4x4(self->GetWorldToCamera())); | ||||
| } | } | ||||
| PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_Camera* self = static_cast<KX_Camera*>(self_v); | KX_Camera* self = static_cast<KX_Camera*>(self_v); | ||||
| return PyObjectFrom(self->GetCameraToWorld()); | return PyObjectFrom(MT_Matrix4x4(self->GetCameraToWorld())); | ||||
| } | } | ||||
| PyObject *KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_Camera* self = static_cast<KX_Camera*>(self_v); | KX_Camera* self = static_cast<KX_Camera*>(self_v); | ||||
| return PyObjectFrom(self->GetWorldToCamera()); | return PyObjectFrom(MT_Matrix4x4(self->GetWorldToCamera())); | ||||
| } | } | ||||
| Context not available. | |||||
| { return PyLong_FromLong(INTERSECT); } | { return PyLong_FromLong(INTERSECT); } | ||||
| bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix) | bool ConvertPythonToCamera(KX_Scene *scene, PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix) | ||||
| { | { | ||||
| if (value==NULL) { | if (value==NULL) { | ||||
| PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); | PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); | ||||
| Context not available. | |||||
| } | } | ||||
| if (PyUnicode_Check(value)) { | if (PyUnicode_Check(value)) { | ||||
| STR_String value_str = _PyUnicode_AsString(value); | std::string value_str = _PyUnicode_AsString(value); | ||||
| *object = KX_GetActiveScene()->FindCamera(value_str); | *object = (KX_Camera*)scene->GetCameraList()->FindValue(value_str); | ||||
| if (*object) { | if (*object) { | ||||
| return true; | return true; | ||||
| Context not available. | |||||
| { | { | ||||
| PyErr_Clear(); | PyErr_Clear(); | ||||
| if (ConvertPythonToGameObject(GetScene()->GetLogicManager(), value, &obj, true, "")) | if (ConvertPythonToGameObject(GetScene()->GetLogicManager(), value, &obj, false, "")) | ||||
| { | { | ||||
| PyErr_Clear(); | PyErr_Clear(); | ||||
| vect = MT_Vector3(obj->NodeGetWorldPosition()); | vect = MT_Vector3(obj->NodeGetWorldPosition()); | ||||
| Context not available. | |||||
| GLdouble modelmatrix[16]; | GLdouble modelmatrix[16]; | ||||
| GLdouble projmatrix[16]; | GLdouble projmatrix[16]; | ||||
| MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); | MT_Matrix4x4 m_modelmatrix = MT_Matrix4x4(GetWorldToCamera()); | ||||
| MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); | MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); | ||||
| m_modelmatrix.getValue(modelmatrix); | m_modelmatrix.getValue(modelmatrix); | ||||
| Context not available. | |||||
| y = 1.0 - y; //to follow Blender window coordinate system (Top-Down) | y = 1.0 - y; //to follow Blender window coordinate system (Top-Down) | ||||
| MT_Vector3 vect; | MT_Vector3 vect; | ||||
| MT_Point3 campos, screenpos; | MT_Vector3 campos, screenpos; | ||||
| const GLint *viewport; | const GLint *viewport; | ||||
| GLdouble win[3]; | GLdouble win[3]; | ||||
| GLdouble modelmatrix[16]; | GLdouble modelmatrix[16]; | ||||
| GLdouble projmatrix[16]; | GLdouble projmatrix[16]; | ||||
| MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); | MT_Matrix4x4 m_modelmatrix = MT_Matrix4x4(GetWorldToCamera()); | ||||
| MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); | MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); | ||||
| m_modelmatrix.getValue(modelmatrix); | m_modelmatrix.getValue(modelmatrix); | ||||
| Context not available. | |||||
| gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); | gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); | ||||
| campos = this->GetCameraLocation(); | campos = this->GetCameraLocation(); | ||||
| screenpos = MT_Point3(win[0], win[1], win[2]); | screenpos = MT_Vector3(win[0], win[1], win[2]); | ||||
| vect = campos-screenpos; | vect = campos-screenpos; | ||||
| vect.normalize(); | vect.normalize(); | ||||
| Context not available. | |||||