diff options
Diffstat (limited to 'source/gameengine/Ketsji/KX_Camera.cpp')
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.cpp | 1167 |
1 files changed, 0 insertions, 1167 deletions
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp deleted file mode 100644 index 93f1621255d..00000000000 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ /dev/null @@ -1,1167 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - * Camera in the gameengine. Cameras are also used for views. - */ - -/** \file gameengine/Ketsji/KX_Camera.cpp - * \ingroup ketsji - */ - - -#include "glew-mx.h" -#include "KX_Camera.h" -#include "KX_Scene.h" -#include "KX_PythonInit.h" -#include "EXP_Python.h" -#include "KX_PyMath.h" - -#include "RAS_ICanvas.h" - -KX_Camera::KX_Camera(void* sgReplicationInfo, - SG_Callbacks callbacks, - const RAS_CameraData& camdata, - bool frustum_culling, - bool delete_node) - : - KX_GameObject(sgReplicationInfo,callbacks), - m_camdata(camdata), - m_dirty(true), - m_normalized(false), - m_frustum_culling(frustum_culling), - m_set_projection_matrix(false), - m_set_frustum_center(false), - m_delete_node(delete_node) -{ - // setting a name would be nice... - m_name = "cam"; - m_projection_matrix.setIdentity(); - m_modelview_matrix.setIdentity(); -} - - -KX_Camera::~KX_Camera() -{ - if (m_delete_node && m_pSGNode) - { - // for shadow camera, avoids memleak - delete m_pSGNode; - m_pSGNode = NULL; - } -} - - -CValue* KX_Camera::GetReplica() -{ - KX_Camera* replica = new KX_Camera(*this); - - // this will copy properties and so on... - replica->ProcessReplica(); - - return replica; -} - -void KX_Camera::ProcessReplica() -{ - KX_GameObject::ProcessReplica(); - // replicated camera are always registered in the scene - m_delete_node = false; -} - -MT_Transform KX_Camera::GetWorldToCamera() const -{ - MT_Transform camtrans; - camtrans.invert(MT_Transform(NodeGetWorldPosition(), NodeGetWorldOrientation())); - - return camtrans; -} - - - -MT_Transform KX_Camera::GetCameraToWorld() const -{ - return MT_Transform(NodeGetWorldPosition(), NodeGetWorldOrientation()); -} - - - -void KX_Camera::CorrectLookUp(MT_Scalar speed) -{ -} - - - -const MT_Point3 KX_Camera::GetCameraLocation() const -{ - /* this is the camera locatio in cam coords... */ - //return m_trans1.getOrigin(); - //return MT_Point3(0,0,0); <----- - /* .... I want it in world coords */ - //MT_Transform trans; - //trans.setBasis(NodeGetWorldOrientation()); - - return NodeGetWorldPosition(); -} - - - -/* I want the camera orientation as well. */ -const MT_Quaternion KX_Camera::GetCameraOrientation() const -{ - return NodeGetWorldOrientation().getRotation(); -} - - - -/** - * Sets the projection matrix that is used by the rasterizer. - */ -void KX_Camera::SetProjectionMatrix(const MT_Matrix4x4 & mat) -{ - m_projection_matrix = mat; - m_dirty = true; - m_set_projection_matrix = true; - m_set_frustum_center = false; -} - - - -/** - * Sets the modelview matrix that is used by the rasterizer. - */ -void KX_Camera::SetModelviewMatrix(const MT_Matrix4x4 & mat) -{ - m_modelview_matrix = mat; - m_dirty = true; - m_set_frustum_center = false; -} - - - -/** - * Gets the projection matrix that is used by the rasterizer. - */ -const MT_Matrix4x4& KX_Camera::GetProjectionMatrix() const -{ - return m_projection_matrix; -} - - - -/** - * Gets the modelview matrix that is used by the rasterizer. - */ -const MT_Matrix4x4& KX_Camera::GetModelviewMatrix() const -{ - return m_modelview_matrix; -} - - -bool KX_Camera::hasValidProjectionMatrix() const -{ - return m_set_projection_matrix; -} - -void KX_Camera::InvalidateProjectionMatrix(bool valid) -{ - m_set_projection_matrix = valid; -} - - -/** - * These getters retrieve the clip data and the focal length - */ -float KX_Camera::GetLens() const -{ - return m_camdata.m_lens; -} - -float KX_Camera::GetScale() const -{ - return m_camdata.m_scale; -} - -/** - * Gets the horizontal size of the sensor - for camera matching. - */ -float KX_Camera::GetSensorWidth() const -{ - return m_camdata.m_sensor_x; -} - -/** - * Gets the vertical size of the sensor - for camera matching. - */ -float KX_Camera::GetSensorHeight() const -{ - return m_camdata.m_sensor_y; -} -/** Gets the mode FOV is calculating from sensor dimensions */ -short KX_Camera::GetSensorFit() const -{ - return m_camdata.m_sensor_fit; -} - -/** - * Gets the horizontal shift of the sensor - for camera matching. - */ -float KX_Camera::GetShiftHorizontal() const -{ - return m_camdata.m_shift_x; -} - -/** - * Gets the vertical shift of the sensor - for camera matching. - */ -float KX_Camera::GetShiftVertical() const -{ - return m_camdata.m_shift_y; -} - -float KX_Camera::GetCameraNear() const -{ - return m_camdata.m_clipstart; -} - - - -float KX_Camera::GetCameraFar() const -{ - return m_camdata.m_clipend; -} - -float KX_Camera::GetFocalLength() const -{ - return m_camdata.m_focallength; -} - - - -RAS_CameraData* KX_Camera::GetCameraData() -{ - return &m_camdata; -} - -void KX_Camera::ExtractClipPlanes() -{ - if (!m_dirty) - return; - - MT_Matrix4x4 m = m_projection_matrix * m_modelview_matrix; - // Left clip plane - m_planes[0] = m[3] + m[0]; - // Right clip plane - m_planes[1] = m[3] - m[0]; - // Top clip plane - m_planes[2] = m[3] - m[1]; - // Bottom clip plane - m_planes[3] = m[3] + m[1]; - // Near clip plane - m_planes[4] = m[3] + m[2]; - // Far clip plane - m_planes[5] = m[3] - m[2]; - - m_dirty = false; - m_normalized = false; -} - -void KX_Camera::NormalizeClipPlanes() -{ - if (m_normalized) - return; - - for (unsigned int p = 0; p < 6; p++) - { - MT_Scalar factor = sqrtf(m_planes[p][0]*m_planes[p][0] + m_planes[p][1]*m_planes[p][1] + m_planes[p][2]*m_planes[p][2]); - if (!MT_fuzzyZero(factor)) - m_planes[p] /= factor; - } - - m_normalized = true; -} - -void KX_Camera::ExtractFrustumSphere() -{ - if (m_set_frustum_center) - return; - - // compute sphere for the general case and not only symmetric frustum: - // the mirror code in ImageRender can use very asymmetric frustum. - // We will put the sphere center on the line that goes from origin to the center of the far clipping plane - // This is the optimal position if the frustum is symmetric or very asymmetric and probably close - // to optimal for the general case. The sphere center position is computed so that the distance to - // the near and far extreme frustum points are equal. - - // get the transformation matrix from device coordinate to camera coordinate - MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix; - clip_camcs_matrix.invert(); - - if (m_projection_matrix[3][3] == MT_Scalar(0.0f)) - { - // frustum projection - // 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_Point3 farpoint; // most extreme far point in camera coordinate - MT_Point3 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_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 e, s; // far and near clipping distance (<0) - MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance - MT_Scalar z; // projection of sphere center on z axis (<0) - // tmp value - MT_Vector4 npoint(1.0f, 1.0f, 1.0f, 1.0f); - MT_Vector4 hpoint; - MT_Point3 point; - MT_Scalar len; - for (int i=0; i<4; i++) - { - hpoint = clip_camcs_matrix*npoint; - point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]); - len = point.dot(point); - if (len > F) - { - nfar = npoint; - farpoint = point; - F = len; - } - // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane - len = npoint[0]; - npoint[0] = -npoint[1]; - npoint[1] = len; - farcenter += point; - } - // the far center is the average of the far clipping points - farcenter *= 0.25f; - // the extreme near point is the opposite point on the near clipping plane - nfar.setValue(-nfar[0], -nfar[1], -1.0f, 1.0f); - nfar = clip_camcs_matrix*nfar; - nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]); - // this is a frustum projection - N = nearpoint.dot(nearpoint); - e = farpoint[2]; - s = nearpoint[2]; - // projection on XY plane for distance to axis computation - MT_Point2 farxy(farpoint[0], farpoint[1]); - // f is forced positive by construction - f = farxy.length(); - // get corresponding point on the near plane - farxy *= s/e; - // this formula preserve the sign of n - n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); - c = MT_Point2(farcenter[0], farcenter[1]).length()/e; - // 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))); - m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); - m_frustum_radius = m_frustum_center.distance(farpoint); - } - else - { - // orthographic projection - // The most extreme points on the near and far plane. (normalized device coords) - MT_Vector4 hnear(1.0f, 1.0f, 1.0f, 1.0f), hfar(-1.0f, -1.0f, -1.0f, 1.0f); - - // Transform to hom camera local space - hnear = clip_camcs_matrix*hnear; - hfar = clip_camcs_matrix*hfar; - - // Tranform to 3d camera local space. - MT_Point3 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]); - - // just use mediant point - m_frustum_center = (farpoint + nearpoint)*0.5f; - m_frustum_radius = m_frustum_center.distance(farpoint); - } - // Transform to world space. - m_frustum_center = GetCameraToWorld()(m_frustum_center); - m_frustum_radius /= fabsf(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]); - - m_set_frustum_center = true; -} - -bool KX_Camera::PointInsideFrustum(const MT_Point3& x) -{ - ExtractClipPlanes(); - - for ( unsigned int i = 0; i < 6 ; i++ ) - { - if (m_planes[i][0] * x[0] + m_planes[i][1] * x[1] + m_planes[i][2] * x[2] + m_planes[i][3] < 0.0f) - return false; - } - return true; -} - -int KX_Camera::BoxInsideFrustum(const MT_Point3 *box) -{ - ExtractClipPlanes(); - - unsigned int insideCount = 0; - // 6 view frustum planes - for ( unsigned int p = 0; p < 6 ; p++ ) - { - unsigned int behindCount = 0; - // 8 box vertices. - for (unsigned int v = 0; v < 8 ; v++) - { - if (m_planes[p][0] * box[v][0] + m_planes[p][1] * box[v][1] + m_planes[p][2] * box[v][2] + m_planes[p][3] < 0.0f) - behindCount++; - } - - // 8 points behind this plane - if (behindCount == 8) - return OUTSIDE; - - // Every box vertex is on the front side of this plane - if (!behindCount) - insideCount++; - } - - // All box vertices are on the front side of all frustum planes. - if (insideCount == 6) - return INSIDE; - - return INTERSECT; -} - -int KX_Camera::SphereInsideFrustum(const MT_Point3& center, const MT_Scalar &radius) -{ - ExtractFrustumSphere(); - if (center.distance2(m_frustum_center) > (radius + m_frustum_radius)*(radius + m_frustum_radius)) - return OUTSIDE; - - unsigned int p; - ExtractClipPlanes(); - NormalizeClipPlanes(); - - MT_Scalar distance; - int intersect = INSIDE; - // distance: <-------- OUTSIDE -----|----- INTERSECT -----0----- INTERSECT -----|----- INSIDE --------> - // -radius radius - for (p = 0; p < 6; p++) - { - distance = m_planes[p][0]*center[0] + m_planes[p][1]*center[1] + m_planes[p][2]*center[2] + m_planes[p][3]; - if (fabsf(distance) <= radius) - intersect = INTERSECT; - else if (distance < -radius) - return OUTSIDE; - } - - return intersect; -} - -bool KX_Camera::GetFrustumCulling() const -{ - return m_frustum_culling; -} - -void KX_Camera::EnableViewport(bool viewport) -{ - InvalidateProjectionMatrix(false); // We need to reset projection matrix - m_camdata.m_viewport = viewport; -} - -void KX_Camera::SetViewport(int left, int bottom, int right, int top) -{ - m_camdata.m_viewportleft = left; - m_camdata.m_viewportbottom = bottom; - m_camdata.m_viewportright = right; - m_camdata.m_viewporttop = top; -} - -bool KX_Camera::GetViewport() const -{ - return m_camdata.m_viewport; -} - -int KX_Camera::GetViewportLeft() const -{ - return m_camdata.m_viewportleft; -} - -int KX_Camera::GetViewportBottom() const -{ - return m_camdata.m_viewportbottom; -} - -int KX_Camera::GetViewportRight() const -{ - return m_camdata.m_viewportright; -} - -int KX_Camera::GetViewportTop() const -{ - return m_camdata.m_viewporttop; -} - -#ifdef WITH_PYTHON -//---------------------------------------------------------------------------- -//Python - - -PyMethodDef KX_Camera::Methods[] = { - KX_PYMETHODTABLE(KX_Camera, sphereInsideFrustum), - KX_PYMETHODTABLE_O(KX_Camera, boxInsideFrustum), - KX_PYMETHODTABLE_O(KX_Camera, pointInsideFrustum), - KX_PYMETHODTABLE_NOARGS(KX_Camera, getCameraToWorld), - 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), - {NULL,NULL} //Sentinel -}; - -PyAttributeDef KX_Camera::Attributes[] = { - - KX_PYATTRIBUTE_BOOL_RW("frustum_culling", KX_Camera, m_frustum_culling), - KX_PYATTRIBUTE_RW_FUNCTION("perspective", KX_Camera, pyattr_get_perspective, pyattr_set_perspective), - - KX_PYATTRIBUTE_RW_FUNCTION("lens", KX_Camera, pyattr_get_lens, pyattr_set_lens), - KX_PYATTRIBUTE_RW_FUNCTION("fov", KX_Camera, pyattr_get_fov, pyattr_set_fov), - KX_PYATTRIBUTE_RW_FUNCTION("ortho_scale", KX_Camera, pyattr_get_ortho_scale, pyattr_set_ortho_scale), - KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near), - 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_y", KX_Camera, pyattr_get_shift_y, pyattr_set_shift_y), - - KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport), - - KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix), - KX_PYATTRIBUTE_RO_FUNCTION("modelview_matrix", KX_Camera, pyattr_get_modelview_matrix), - KX_PYATTRIBUTE_RO_FUNCTION("camera_to_world", KX_Camera, pyattr_get_camera_to_world), - KX_PYATTRIBUTE_RO_FUNCTION("world_to_camera", KX_Camera, pyattr_get_world_to_camera), - - /* Grrr, functions for constants? */ - KX_PYATTRIBUTE_RO_FUNCTION("INSIDE", KX_Camera, pyattr_get_INSIDE), - KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE", KX_Camera, pyattr_get_OUTSIDE), - KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT", KX_Camera, pyattr_get_INTERSECT), - - { NULL } //Sentinel -}; - -PyTypeObject KX_Camera::Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "KX_Camera", - sizeof(PyObjectPlus_Proxy), - 0, - py_base_dealloc, - 0, - 0, - 0, - 0, - py_base_repr, - 0, - &KX_GameObject::Sequence, - &KX_GameObject::Mapping, - 0,0,0, - NULL, - NULL, - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - 0,0,0,0,0,0,0, - Methods, - 0, - 0, - &KX_GameObject::Type, - 0,0,0,0,0,0, - py_base_new -}; - -KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, -"sphereInsideFrustum(center, radius) -> Integer\n" -"\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n" -"\tinside/outside/intersects this camera's viewing frustum.\n\n" -"\tcenter = the center of the sphere (in world coordinates.)\n" -"\tradius = the radius of the sphere\n\n" -"\tExample:\n" -"\timport bge.logic\n\n" -"\tco = bge.logic.getCurrentController()\n" -"\tcam = co.GetOwner()\n\n" -"\t# A sphere of radius 4.0 located at [x, y, z] = [1.0, 1.0, 1.0]\n" -"\tif (cam.sphereInsideFrustum([1.0, 1.0, 1.0], 4) != cam.OUTSIDE):\n" -"\t\t# Sphere is inside frustum !\n" -"\t\t# Do something useful !\n" -"\telse:\n" -"\t\t# Sphere is outside frustum\n" -) -{ - PyObject *pycenter; - float radius; - if (PyArg_ParseTuple(args, "Of:sphereInsideFrustum", &pycenter, &radius)) - { - MT_Point3 center; - if (PyVecTo(pycenter, center)) - { - return PyLong_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ - } - } - - PyErr_SetString(PyExc_TypeError, "camera.sphereInsideFrustum(center, radius): KX_Camera, expected arguments: (center, radius)"); - - return NULL; -} - -KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, -"boxInsideFrustum(box) -> Integer\n" -"\treturns INSIDE, OUTSIDE or INTERSECT if the given box is\n" -"\tinside/outside/intersects this camera's viewing frustum.\n\n" -"\tbox = a list of the eight (8) corners of the box (in world coordinates.)\n\n" -"\tExample:\n" -"\timport bge.logic\n\n" -"\tco = bge.logic.getCurrentController()\n" -"\tcam = co.GetOwner()\n\n" -"\tbox = []\n" -"\tbox.append([-1.0, -1.0, -1.0])\n" -"\tbox.append([-1.0, -1.0, 1.0])\n" -"\tbox.append([-1.0, 1.0, -1.0])\n" -"\tbox.append([-1.0, 1.0, 1.0])\n" -"\tbox.append([ 1.0, -1.0, -1.0])\n" -"\tbox.append([ 1.0, -1.0, 1.0])\n" -"\tbox.append([ 1.0, 1.0, -1.0])\n" -"\tbox.append([ 1.0, 1.0, 1.0])\n\n" -"\tif (cam.boxInsideFrustum(box) != cam.OUTSIDE):\n" -"\t\t# Box is inside/intersects frustum !\n" -"\t\t# Do something useful !\n" -"\telse:\n" -"\t\t# Box is outside the frustum !\n" -) -{ - unsigned int num_points = PySequence_Size(value); - if (num_points != 8) - { - PyErr_Format(PyExc_TypeError, "camera.boxInsideFrustum(box): KX_Camera, expected eight (8) points, got %d", num_points); - return NULL; - } - - MT_Point3 box[8]; - for (unsigned int p = 0; p < 8 ; p++) - { - PyObject *item = PySequence_GetItem(value, p); /* new ref */ - bool error = !PyVecTo(item, box[p]); - Py_DECREF(item); - if (error) - return NULL; - } - - return PyLong_FromLong(BoxInsideFrustum(box)); /* new ref */ -} - -KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, -"pointInsideFrustum(point) -> Bool\n" -"\treturns 1 if the given point is inside this camera's viewing frustum.\n\n" -"\tpoint = The point to test (in world coordinates.)\n\n" -"\tExample:\n" -"\timport bge.logic\n\n" -"\tco = bge.logic.getCurrentController()\n" -"\tcam = co.GetOwner()\n\n" -"\t# Test point [0.0, 0.0, 0.0]" -"\tif (cam.pointInsideFrustum([0.0, 0.0, 0.0])):\n" -"\t\t# Point is inside frustum !\n" -"\t\t# Do something useful !\n" -"\telse:\n" -"\t\t# Box is outside the frustum !\n" -) -{ - MT_Point3 point; - if (PyVecTo(value, point)) - { - return PyLong_FromLong(PointInsideFrustum(point)); /* new ref */ - } - - PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); - return NULL; -} - -KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getCameraToWorld, -"getCameraToWorld() -> Matrix4x4\n" -"\treturns the camera to world transformation matrix, as a list of four lists of four values.\n\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 */ -} - -KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getWorldToCamera, -"getWorldToCamera() -> Matrix4x4\n" -"\treturns the world to camera transformation matrix, as a list of four lists of four values.\n\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 */ -} - -KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport, -"setViewport(left, bottom, right, top)\n" -"Sets this camera's viewport\n") -{ - int left, bottom, right, top; - if (!PyArg_ParseTuple(args,"iiii:setViewport",&left, &bottom, &right, &top)) - return NULL; - - SetViewport(left, bottom, right, top); - Py_RETURN_NONE; -} - -KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, -"setOnTop()\n" -"Sets this camera's viewport on top\n") -{ - class KX_Scene* scene = KX_GetActiveScene(); - scene->SetCameraOnTop(this); - Py_RETURN_NONE; -} - -PyObject *KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyBool_FromLong(self->m_camdata.m_perspective); -} - -int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - int param = PyObject_IsTrue( value ); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_perspective= param; - self->InvalidateProjectionMatrix(); - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyFloat_FromDouble(self->m_camdata.m_lens); -} - -int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float param = PyFloat_AsDouble(value); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_lens= param; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_fov(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - - float lens = self->m_camdata.m_lens; - float width = self->m_camdata.m_sensor_x; - float fov = 2.0f * atanf(0.5f * width / lens); - - return PyFloat_FromDouble(fov * MT_DEGS_PER_RAD); -} - -int KX_Camera::pyattr_set_fov(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float fov = PyFloat_AsDouble(value); - if (fov <= 0.0f) { - PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - fov *= MT_RADS_PER_DEG; - float width = self->m_camdata.m_sensor_x; - float lens = width / (2.0f * tanf(0.5f * fov)); - - self->m_camdata.m_lens= lens; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyFloat_FromDouble(self->m_camdata.m_scale); -} - -int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float param = PyFloat_AsDouble(value); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_scale= param; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyFloat_FromDouble(self->m_camdata.m_clipstart); -} - -int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float param = PyFloat_AsDouble(value); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_clipstart= param; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyFloat_FromDouble(self->m_camdata.m_clipend); -} - -int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float param = PyFloat_AsDouble(value); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_clipend= param; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyFloat_FromDouble(self->m_camdata.m_shift_x); -} - -int KX_Camera::pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float param = PyFloat_AsDouble(value); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.shift_x = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_shift_x = param; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyFloat_FromDouble(self->m_camdata.m_shift_y); -} - -int KX_Camera::pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - float param = PyFloat_AsDouble(value); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.shift_y = float: KX_Camera, expected a float greater than zero"); - return PY_SET_ATTR_FAIL; - } - - self->m_camdata.m_shift_y = param; - self->m_set_projection_matrix = false; - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyBool_FromLong(self->GetViewport()); -} - -int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - int param = PyObject_IsTrue( value ); - if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.useViewport = bool: KX_Camera, expected True or False"); - return PY_SET_ATTR_FAIL; - } - self->EnableViewport((bool)param); - return PY_SET_ATTR_SUCCESS; -} - - -PyObject *KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyObjectFrom(self->GetProjectionMatrix()); -} - -int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - MT_Matrix4x4 mat; - if (!PyMatTo(value, mat)) - return PY_SET_ATTR_FAIL; - - self->SetProjectionMatrix(mat); - return PY_SET_ATTR_SUCCESS; -} - -PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyObjectFrom(self->GetWorldToCamera()); -} - -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); - return PyObjectFrom(self->GetCameraToWorld()); -} - -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); - return PyObjectFrom(self->GetWorldToCamera()); -} - - -PyObject *KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromLong(INSIDE); } -PyObject *KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromLong(OUTSIDE); } -PyObject *KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromLong(INTERSECT); } - - -bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix) -{ - if (value==NULL) { - PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); - *object = NULL; - return false; - } - - if (value==Py_None) { - *object = NULL; - - if (py_none_ok) { - return true; - } else { - PyErr_Format(PyExc_TypeError, "%s, expected KX_Camera or a KX_Camera name, None is invalid", error_prefix); - return false; - } - } - - if (PyUnicode_Check(value)) { - STR_String value_str = _PyUnicode_AsString(value); - *object = KX_GetActiveScene()->FindCamera(value_str); - - if (*object) { - return true; - } else { - PyErr_Format(PyExc_ValueError, - "%s, requested name \"%s\" did not match any KX_Camera in this scene", - error_prefix, _PyUnicode_AsString(value)); - return false; - } - } - - if (PyObject_TypeCheck(value, &KX_Camera::Type)) { - *object = static_cast<KX_Camera*>BGE_PROXY_REF(value); - - /* sets the error */ - if (*object==NULL) { - PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); - return false; - } - - return true; - } - - *object = NULL; - - if (py_none_ok) { - PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera, a string or None", error_prefix); - } else { - PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera or a string", error_prefix); - } - - return false; -} - -KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, -"getScreenPosition()\n" -) - -{ - MT_Vector3 vect; - KX_GameObject *obj = NULL; - - if (!PyVecTo(value, vect)) - { - PyErr_Clear(); - - if (ConvertPythonToGameObject(GetScene()->GetLogicManager(), 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; - } - } - - const GLint *viewport; - GLdouble win[3]; - GLdouble modelmatrix[16]; - GLdouble projmatrix[16]; - - MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); - MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); - - m_modelmatrix.getValue(modelmatrix); - m_projmatrix.getValue(projmatrix); - - viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort(); - - 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]; - - vect[1] = 1.0f - vect[1]; //to follow Blender window coordinate system (Top-Down) - - 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; - - y = 1.0 - y; //to follow Blender window coordinate system (Top-Down) - - MT_Vector3 vect; - MT_Point3 campos, screenpos; - - const GLint *viewport; - GLdouble win[3]; - GLdouble modelmatrix[16]; - GLdouble projmatrix[16]; - - MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); - MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); - - m_modelmatrix.getValue(modelmatrix); - m_projmatrix.getValue(projmatrix); - - viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort(); - - vect[0] = x * viewport[2]; - vect[1] = y * viewport[3]; - - vect[0] += viewport[0]; - vect[1] += viewport[1]; - - vect[2] = 0.f; - - 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" -) -{ - 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); - 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 = -dist; - vect += this->GetCameraLocation(); - - 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, PyUnicode_FromString(propName)); - - PyObject *ret= this->PyrayCastTo(argValue,NULL); - Py_DECREF(argValue); - return ret; - } - - return NULL; -} -#endif |