|
Blender
V2.59
|
00001 /* 00002 * $Id: KX_Camera.cpp 38273 2011-07-09 19:59:32Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * Camera in the gameengine. Cameras are also used for views. 00029 */ 00030 00036 #include "GL/glew.h" 00037 #include "KX_Camera.h" 00038 #include "KX_Scene.h" 00039 #include "KX_PythonInit.h" 00040 #include "KX_Python.h" 00041 #include "KX_PyMath.h" 00042 KX_Camera::KX_Camera(void* sgReplicationInfo, 00043 SG_Callbacks callbacks, 00044 const RAS_CameraData& camdata, 00045 bool frustum_culling, 00046 bool delete_node) 00047 : 00048 KX_GameObject(sgReplicationInfo,callbacks), 00049 m_camdata(camdata), 00050 m_dirty(true), 00051 m_normalized(false), 00052 m_frustum_culling(frustum_culling), 00053 m_set_projection_matrix(false), 00054 m_set_frustum_center(false), 00055 m_delete_node(delete_node) 00056 { 00057 // setting a name would be nice... 00058 m_name = "cam"; 00059 m_projection_matrix.setIdentity(); 00060 m_modelview_matrix.setIdentity(); 00061 } 00062 00063 00064 KX_Camera::~KX_Camera() 00065 { 00066 if (m_delete_node && m_pSGNode) 00067 { 00068 // for shadow camera, avoids memleak 00069 delete m_pSGNode; 00070 m_pSGNode = NULL; 00071 } 00072 } 00073 00074 00075 CValue* KX_Camera::GetReplica() 00076 { 00077 KX_Camera* replica = new KX_Camera(*this); 00078 00079 // this will copy properties and so on... 00080 replica->ProcessReplica(); 00081 00082 return replica; 00083 } 00084 00085 void KX_Camera::ProcessReplica() 00086 { 00087 KX_GameObject::ProcessReplica(); 00088 // replicated camera are always registered in the scene 00089 m_delete_node = false; 00090 } 00091 00092 MT_Transform KX_Camera::GetWorldToCamera() const 00093 { 00094 MT_Transform camtrans; 00095 camtrans.invert(MT_Transform(NodeGetWorldPosition(), NodeGetWorldOrientation())); 00096 00097 return camtrans; 00098 } 00099 00100 00101 00102 MT_Transform KX_Camera::GetCameraToWorld() const 00103 { 00104 return MT_Transform(NodeGetWorldPosition(), NodeGetWorldOrientation()); 00105 } 00106 00107 00108 00109 void KX_Camera::CorrectLookUp(MT_Scalar speed) 00110 { 00111 } 00112 00113 00114 00115 const MT_Point3 KX_Camera::GetCameraLocation() const 00116 { 00117 /* this is the camera locatio in cam coords... */ 00118 //return m_trans1.getOrigin(); 00119 //return MT_Point3(0,0,0); <----- 00120 /* .... I want it in world coords */ 00121 //MT_Transform trans; 00122 //trans.setBasis(NodeGetWorldOrientation()); 00123 00124 return NodeGetWorldPosition(); 00125 } 00126 00127 00128 00129 /* I want the camera orientation as well. */ 00130 const MT_Quaternion KX_Camera::GetCameraOrientation() const 00131 { 00132 return NodeGetWorldOrientation().getRotation(); 00133 } 00134 00135 00136 00140 void KX_Camera::SetProjectionMatrix(const MT_Matrix4x4 & mat) 00141 { 00142 m_projection_matrix = mat; 00143 m_dirty = true; 00144 m_set_projection_matrix = true; 00145 m_set_frustum_center = false; 00146 } 00147 00148 00149 00153 void KX_Camera::SetModelviewMatrix(const MT_Matrix4x4 & mat) 00154 { 00155 m_modelview_matrix = mat; 00156 m_dirty = true; 00157 m_set_frustum_center = false; 00158 } 00159 00160 00161 00165 const MT_Matrix4x4& KX_Camera::GetProjectionMatrix() const 00166 { 00167 return m_projection_matrix; 00168 } 00169 00170 00171 00175 const MT_Matrix4x4& KX_Camera::GetModelviewMatrix() const 00176 { 00177 return m_modelview_matrix; 00178 } 00179 00180 00181 bool KX_Camera::hasValidProjectionMatrix() const 00182 { 00183 return m_set_projection_matrix; 00184 } 00185 00186 void KX_Camera::InvalidateProjectionMatrix(bool valid) 00187 { 00188 m_set_projection_matrix = valid; 00189 } 00190 00191 00192 /* 00193 * These getters retrieve the clip data and the focal length 00194 */ 00195 float KX_Camera::GetLens() const 00196 { 00197 return m_camdata.m_lens; 00198 } 00199 00200 float KX_Camera::GetScale() const 00201 { 00202 return m_camdata.m_scale; 00203 } 00204 00205 00206 00207 float KX_Camera::GetCameraNear() const 00208 { 00209 return m_camdata.m_clipstart; 00210 } 00211 00212 00213 00214 float KX_Camera::GetCameraFar() const 00215 { 00216 return m_camdata.m_clipend; 00217 } 00218 00219 float KX_Camera::GetFocalLength() const 00220 { 00221 return m_camdata.m_focallength; 00222 } 00223 00224 00225 00226 RAS_CameraData* KX_Camera::GetCameraData() 00227 { 00228 return &m_camdata; 00229 } 00230 00231 void KX_Camera::ExtractClipPlanes() 00232 { 00233 if (!m_dirty) 00234 return; 00235 00236 MT_Matrix4x4 m = m_projection_matrix * m_modelview_matrix; 00237 // Left clip plane 00238 m_planes[0] = m[3] + m[0]; 00239 // Right clip plane 00240 m_planes[1] = m[3] - m[0]; 00241 // Top clip plane 00242 m_planes[2] = m[3] - m[1]; 00243 // Bottom clip plane 00244 m_planes[3] = m[3] + m[1]; 00245 // Near clip plane 00246 m_planes[4] = m[3] + m[2]; 00247 // Far clip plane 00248 m_planes[5] = m[3] - m[2]; 00249 00250 m_dirty = false; 00251 m_normalized = false; 00252 } 00253 00254 void KX_Camera::NormalizeClipPlanes() 00255 { 00256 if (m_normalized) 00257 return; 00258 00259 for (unsigned int p = 0; p < 6; p++) 00260 { 00261 MT_Scalar factor = sqrt(m_planes[p][0]*m_planes[p][0] + m_planes[p][1]*m_planes[p][1] + m_planes[p][2]*m_planes[p][2]); 00262 if (!MT_fuzzyZero(factor)) 00263 m_planes[p] /= factor; 00264 } 00265 00266 m_normalized = true; 00267 } 00268 00269 void KX_Camera::ExtractFrustumSphere() 00270 { 00271 if (m_set_frustum_center) 00272 return; 00273 00274 // compute sphere for the general case and not only symmetric frustum: 00275 // the mirror code in ImageRender can use very asymmetric frustum. 00276 // We will put the sphere center on the line that goes from origin to the center of the far clipping plane 00277 // This is the optimal position if the frustum is symmetric or very asymmetric and probably close 00278 // to optimal for the general case. The sphere center position is computed so that the distance to 00279 // the near and far extreme frustum points are equal. 00280 00281 // get the transformation matrix from device coordinate to camera coordinate 00282 MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix; 00283 clip_camcs_matrix.invert(); 00284 00285 if (m_projection_matrix[3][3] == MT_Scalar(0.0)) 00286 { 00287 // frustrum projection 00288 // detect which of the corner of the far clipping plane is the farthest to the origin 00289 MT_Vector4 nfar; // far point in device normalized coordinate 00290 MT_Point3 farpoint; // most extreme far point in camera coordinate 00291 MT_Point3 nearpoint;// most extreme near point in camera coordinate 00292 MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate 00293 MT_Scalar F=-1.0, N; // square distance of far and near point to origin 00294 MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0 00295 MT_Scalar e, s; // far and near clipping distance (<0) 00296 MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance 00297 MT_Scalar z; // projection of sphere center on z axis (<0) 00298 // tmp value 00299 MT_Vector4 npoint(1., 1., 1., 1.); 00300 MT_Vector4 hpoint; 00301 MT_Point3 point; 00302 MT_Scalar len; 00303 for (int i=0; i<4; i++) 00304 { 00305 hpoint = clip_camcs_matrix*npoint; 00306 point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]); 00307 len = point.dot(point); 00308 if (len > F) 00309 { 00310 nfar = npoint; 00311 farpoint = point; 00312 F = len; 00313 } 00314 // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane 00315 len = npoint[0]; 00316 npoint[0] = -npoint[1]; 00317 npoint[1] = len; 00318 farcenter += point; 00319 } 00320 // the far center is the average of the far clipping points 00321 farcenter *= 0.25; 00322 // the extreme near point is the opposite point on the near clipping plane 00323 nfar.setValue(-nfar[0], -nfar[1], -1., 1.); 00324 nfar = clip_camcs_matrix*nfar; 00325 nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]); 00326 // this is a frustrum projection 00327 N = nearpoint.dot(nearpoint); 00328 e = farpoint[2]; 00329 s = nearpoint[2]; 00330 // projection on XY plane for distance to axis computation 00331 MT_Point2 farxy(farpoint[0], farpoint[1]); 00332 // f is forced positive by construction 00333 f = farxy.length(); 00334 // get corresponding point on the near plane 00335 farxy *= s/e; 00336 // this formula preserve the sign of n 00337 n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); 00338 c = MT_Point2(farcenter[0], farcenter[1]).length()/e; 00339 // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case 00340 z = (F-N)/(2.0*(e-s+c*(f-n))); 00341 m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); 00342 m_frustum_radius = m_frustum_center.distance(farpoint); 00343 } 00344 else 00345 { 00346 // orthographic projection 00347 // The most extreme points on the near and far plane. (normalized device coords) 00348 MT_Vector4 hnear(1., 1., 1., 1.), hfar(-1., -1., -1., 1.); 00349 00350 // Transform to hom camera local space 00351 hnear = clip_camcs_matrix*hnear; 00352 hfar = clip_camcs_matrix*hfar; 00353 00354 // Tranform to 3d camera local space. 00355 MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]); 00356 MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); 00357 00358 // just use mediant point 00359 m_frustum_center = (farpoint + nearpoint)*0.5; 00360 m_frustum_radius = m_frustum_center.distance(farpoint); 00361 } 00362 // Transform to world space. 00363 m_frustum_center = GetCameraToWorld()(m_frustum_center); 00364 m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]); 00365 00366 m_set_frustum_center = true; 00367 } 00368 00369 bool KX_Camera::PointInsideFrustum(const MT_Point3& x) 00370 { 00371 ExtractClipPlanes(); 00372 00373 for( unsigned int i = 0; i < 6 ; i++ ) 00374 { 00375 if (m_planes[i][0]*x[0] + m_planes[i][1]*x[1] + m_planes[i][2]*x[2] + m_planes[i][3] < 0.) 00376 return false; 00377 } 00378 return true; 00379 } 00380 00381 int KX_Camera::BoxInsideFrustum(const MT_Point3 *box) 00382 { 00383 ExtractClipPlanes(); 00384 00385 unsigned int insideCount = 0; 00386 // 6 view frustum planes 00387 for( unsigned int p = 0; p < 6 ; p++ ) 00388 { 00389 unsigned int behindCount = 0; 00390 // 8 box vertices. 00391 for (unsigned int v = 0; v < 8 ; v++) 00392 { 00393 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.) 00394 behindCount++; 00395 } 00396 00397 // 8 points behind this plane 00398 if (behindCount == 8) 00399 return OUTSIDE; 00400 00401 // Every box vertex is on the front side of this plane 00402 if (!behindCount) 00403 insideCount++; 00404 } 00405 00406 // All box vertices are on the front side of all frustum planes. 00407 if (insideCount == 6) 00408 return INSIDE; 00409 00410 return INTERSECT; 00411 } 00412 00413 int KX_Camera::SphereInsideFrustum(const MT_Point3& center, const MT_Scalar &radius) 00414 { 00415 ExtractFrustumSphere(); 00416 if (center.distance2(m_frustum_center) > (radius + m_frustum_radius)*(radius + m_frustum_radius)) 00417 return OUTSIDE; 00418 00419 unsigned int p; 00420 ExtractClipPlanes(); 00421 NormalizeClipPlanes(); 00422 00423 MT_Scalar distance; 00424 int intersect = INSIDE; 00425 // distance: <-------- OUTSIDE -----|----- INTERSECT -----0----- INTERSECT -----|----- INSIDE --------> 00426 // -radius radius 00427 for (p = 0; p < 6; p++) 00428 { 00429 distance = m_planes[p][0]*center[0] + m_planes[p][1]*center[1] + m_planes[p][2]*center[2] + m_planes[p][3]; 00430 if (fabs(distance) <= radius) 00431 intersect = INTERSECT; 00432 else if (distance < -radius) 00433 return OUTSIDE; 00434 } 00435 00436 return intersect; 00437 } 00438 00439 bool KX_Camera::GetFrustumCulling() const 00440 { 00441 return m_frustum_culling; 00442 } 00443 00444 void KX_Camera::EnableViewport(bool viewport) 00445 { 00446 m_camdata.m_viewport = viewport; 00447 } 00448 00449 void KX_Camera::SetViewport(int left, int bottom, int right, int top) 00450 { 00451 m_camdata.m_viewportleft = left; 00452 m_camdata.m_viewportbottom = bottom; 00453 m_camdata.m_viewportright = right; 00454 m_camdata.m_viewporttop = top; 00455 } 00456 00457 bool KX_Camera::GetViewport() const 00458 { 00459 return m_camdata.m_viewport; 00460 } 00461 00462 int KX_Camera::GetViewportLeft() const 00463 { 00464 return m_camdata.m_viewportleft; 00465 } 00466 00467 int KX_Camera::GetViewportBottom() const 00468 { 00469 return m_camdata.m_viewportbottom; 00470 } 00471 00472 int KX_Camera::GetViewportRight() const 00473 { 00474 return m_camdata.m_viewportright; 00475 } 00476 00477 int KX_Camera::GetViewportTop() const 00478 { 00479 return m_camdata.m_viewporttop; 00480 } 00481 00482 #ifdef WITH_PYTHON 00483 //---------------------------------------------------------------------------- 00484 //Python 00485 00486 00487 PyMethodDef KX_Camera::Methods[] = { 00488 KX_PYMETHODTABLE(KX_Camera, sphereInsideFrustum), 00489 KX_PYMETHODTABLE_O(KX_Camera, boxInsideFrustum), 00490 KX_PYMETHODTABLE_O(KX_Camera, pointInsideFrustum), 00491 KX_PYMETHODTABLE_NOARGS(KX_Camera, getCameraToWorld), 00492 KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera), 00493 KX_PYMETHODTABLE(KX_Camera, setViewport), 00494 KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop), 00495 KX_PYMETHODTABLE_O(KX_Camera, getScreenPosition), 00496 KX_PYMETHODTABLE(KX_Camera, getScreenVect), 00497 KX_PYMETHODTABLE(KX_Camera, getScreenRay), 00498 {NULL,NULL} //Sentinel 00499 }; 00500 00501 PyAttributeDef KX_Camera::Attributes[] = { 00502 00503 KX_PYATTRIBUTE_BOOL_RW("frustum_culling", KX_Camera, m_frustum_culling), 00504 KX_PYATTRIBUTE_RW_FUNCTION("perspective", KX_Camera, pyattr_get_perspective, pyattr_set_perspective), 00505 00506 KX_PYATTRIBUTE_RW_FUNCTION("lens", KX_Camera, pyattr_get_lens, pyattr_set_lens), 00507 KX_PYATTRIBUTE_RW_FUNCTION("ortho_scale", KX_Camera, pyattr_get_ortho_scale, pyattr_set_ortho_scale), 00508 KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near), 00509 KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far), 00510 00511 KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport), 00512 00513 KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix), 00514 KX_PYATTRIBUTE_RO_FUNCTION("modelview_matrix", KX_Camera, pyattr_get_modelview_matrix), 00515 KX_PYATTRIBUTE_RO_FUNCTION("camera_to_world", KX_Camera, pyattr_get_camera_to_world), 00516 KX_PYATTRIBUTE_RO_FUNCTION("world_to_camera", KX_Camera, pyattr_get_world_to_camera), 00517 00518 /* Grrr, functions for constants? */ 00519 KX_PYATTRIBUTE_RO_FUNCTION("INSIDE", KX_Camera, pyattr_get_INSIDE), 00520 KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE", KX_Camera, pyattr_get_OUTSIDE), 00521 KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT", KX_Camera, pyattr_get_INTERSECT), 00522 00523 { NULL } //Sentinel 00524 }; 00525 00526 PyTypeObject KX_Camera::Type = { 00527 PyVarObject_HEAD_INIT(NULL, 0) 00528 "KX_Camera", 00529 sizeof(PyObjectPlus_Proxy), 00530 0, 00531 py_base_dealloc, 00532 0, 00533 0, 00534 0, 00535 0, 00536 py_base_repr, 00537 0, 00538 &KX_GameObject::Sequence, 00539 &KX_GameObject::Mapping, 00540 0,0,0, 00541 NULL, 00542 NULL, 00543 0, 00544 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00545 0,0,0,0,0,0,0, 00546 Methods, 00547 0, 00548 0, 00549 &KX_GameObject::Type, 00550 0,0,0,0,0,0, 00551 py_base_new 00552 }; 00553 00554 KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, 00555 "sphereInsideFrustum(center, radius) -> Integer\n" 00556 "\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n" 00557 "\tinside/outside/intersects this camera's viewing frustum.\n\n" 00558 "\tcenter = the center of the sphere (in world coordinates.)\n" 00559 "\tradius = the radius of the sphere\n\n" 00560 "\tExample:\n" 00561 "\timport bge.logic\n\n" 00562 "\tco = bge.logic.getCurrentController()\n" 00563 "\tcam = co.GetOwner()\n\n" 00564 "\t# A sphere of radius 4.0 located at [x, y, z] = [1.0, 1.0, 1.0]\n" 00565 "\tif (cam.sphereInsideFrustum([1.0, 1.0, 1.0], 4) != cam.OUTSIDE):\n" 00566 "\t\t# Sphere is inside frustum !\n" 00567 "\t\t# Do something useful !\n" 00568 "\telse:\n" 00569 "\t\t# Sphere is outside frustum\n" 00570 ) 00571 { 00572 PyObject *pycenter; 00573 float radius; 00574 if (PyArg_ParseTuple(args, "Of:sphereInsideFrustum", &pycenter, &radius)) 00575 { 00576 MT_Point3 center; 00577 if (PyVecTo(pycenter, center)) 00578 { 00579 return PyLong_FromSsize_t(SphereInsideFrustum(center, radius)); /* new ref */ 00580 } 00581 } 00582 00583 PyErr_SetString(PyExc_TypeError, "camera.sphereInsideFrustum(center, radius): KX_Camera, expected arguments: (center, radius)"); 00584 00585 return NULL; 00586 } 00587 00588 KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, 00589 "boxInsideFrustum(box) -> Integer\n" 00590 "\treturns INSIDE, OUTSIDE or INTERSECT if the given box is\n" 00591 "\tinside/outside/intersects this camera's viewing frustum.\n\n" 00592 "\tbox = a list of the eight (8) corners of the box (in world coordinates.)\n\n" 00593 "\tExample:\n" 00594 "\timport bge.logic\n\n" 00595 "\tco = bge.logic.getCurrentController()\n" 00596 "\tcam = co.GetOwner()\n\n" 00597 "\tbox = []\n" 00598 "\tbox.append([-1.0, -1.0, -1.0])\n" 00599 "\tbox.append([-1.0, -1.0, 1.0])\n" 00600 "\tbox.append([-1.0, 1.0, -1.0])\n" 00601 "\tbox.append([-1.0, 1.0, 1.0])\n" 00602 "\tbox.append([ 1.0, -1.0, -1.0])\n" 00603 "\tbox.append([ 1.0, -1.0, 1.0])\n" 00604 "\tbox.append([ 1.0, 1.0, -1.0])\n" 00605 "\tbox.append([ 1.0, 1.0, 1.0])\n\n" 00606 "\tif (cam.boxInsideFrustum(box) != cam.OUTSIDE):\n" 00607 "\t\t# Box is inside/intersects frustum !\n" 00608 "\t\t# Do something useful !\n" 00609 "\telse:\n" 00610 "\t\t# Box is outside the frustum !\n" 00611 ) 00612 { 00613 unsigned int num_points = PySequence_Size(value); 00614 if (num_points != 8) 00615 { 00616 PyErr_Format(PyExc_TypeError, "camera.boxInsideFrustum(box): KX_Camera, expected eight (8) points, got %d", num_points); 00617 return NULL; 00618 } 00619 00620 MT_Point3 box[8]; 00621 for (unsigned int p = 0; p < 8 ; p++) 00622 { 00623 PyObject *item = PySequence_GetItem(value, p); /* new ref */ 00624 bool error = !PyVecTo(item, box[p]); 00625 Py_DECREF(item); 00626 if (error) 00627 return NULL; 00628 } 00629 00630 return PyLong_FromSsize_t(BoxInsideFrustum(box)); /* new ref */ 00631 } 00632 00633 KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, 00634 "pointInsideFrustum(point) -> Bool\n" 00635 "\treturns 1 if the given point is inside this camera's viewing frustum.\n\n" 00636 "\tpoint = The point to test (in world coordinates.)\n\n" 00637 "\tExample:\n" 00638 "\timport bge.logic\n\n" 00639 "\tco = bge.logic.getCurrentController()\n" 00640 "\tcam = co.GetOwner()\n\n" 00641 "\t# Test point [0.0, 0.0, 0.0]" 00642 "\tif (cam.pointInsideFrustum([0.0, 0.0, 0.0])):\n" 00643 "\t\t# Point is inside frustum !\n" 00644 "\t\t# Do something useful !\n" 00645 "\telse:\n" 00646 "\t\t# Box is outside the frustum !\n" 00647 ) 00648 { 00649 MT_Point3 point; 00650 if (PyVecTo(value, point)) 00651 { 00652 return PyLong_FromSsize_t(PointInsideFrustum(point)); /* new ref */ 00653 } 00654 00655 PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); 00656 return NULL; 00657 } 00658 00659 KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getCameraToWorld, 00660 "getCameraToWorld() -> Matrix4x4\n" 00661 "\treturns the camera to world transformation matrix, as a list of four lists of four values.\n\n" 00662 "\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" 00663 ) 00664 { 00665 return PyObjectFrom(GetCameraToWorld()); /* new ref */ 00666 } 00667 00668 KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getWorldToCamera, 00669 "getWorldToCamera() -> Matrix4x4\n" 00670 "\treturns the world to camera transformation matrix, as a list of four lists of four values.\n\n" 00671 "\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" 00672 ) 00673 { 00674 return PyObjectFrom(GetWorldToCamera()); /* new ref */ 00675 } 00676 00677 KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport, 00678 "setViewport(left, bottom, right, top)\n" 00679 "Sets this camera's viewport\n") 00680 { 00681 int left, bottom, right, top; 00682 if (!PyArg_ParseTuple(args,"iiii:setViewport",&left, &bottom, &right, &top)) 00683 return NULL; 00684 00685 SetViewport(left, bottom, right, top); 00686 Py_RETURN_NONE; 00687 } 00688 00689 KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, 00690 "setOnTop()\n" 00691 "Sets this camera's viewport on top\n") 00692 { 00693 class KX_Scene* scene = KX_GetActiveScene(); 00694 scene->SetCameraOnTop(this); 00695 Py_RETURN_NONE; 00696 } 00697 00698 PyObject* KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00699 { 00700 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00701 return PyBool_FromLong(self->m_camdata.m_perspective); 00702 } 00703 00704 int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00705 { 00706 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00707 int param = PyObject_IsTrue( value ); 00708 if (param == -1) { 00709 PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1"); 00710 return PY_SET_ATTR_FAIL; 00711 } 00712 00713 self->m_camdata.m_perspective= param; 00714 self->InvalidateProjectionMatrix(); 00715 return PY_SET_ATTR_SUCCESS; 00716 } 00717 00718 PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00719 { 00720 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00721 return PyFloat_FromDouble(self->m_camdata.m_lens); 00722 } 00723 00724 int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00725 { 00726 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00727 float param = PyFloat_AsDouble(value); 00728 if (param == -1) { 00729 PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero"); 00730 return PY_SET_ATTR_FAIL; 00731 } 00732 00733 self->m_camdata.m_lens= param; 00734 self->m_set_projection_matrix = false; 00735 return PY_SET_ATTR_SUCCESS; 00736 } 00737 00738 PyObject* KX_Camera::pyattr_get_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00739 { 00740 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00741 return PyFloat_FromDouble(self->m_camdata.m_scale); 00742 } 00743 00744 int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00745 { 00746 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00747 float param = PyFloat_AsDouble(value); 00748 if (param == -1) { 00749 PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater then zero"); 00750 return PY_SET_ATTR_FAIL; 00751 } 00752 00753 self->m_camdata.m_scale= param; 00754 self->m_set_projection_matrix = false; 00755 return PY_SET_ATTR_SUCCESS; 00756 } 00757 00758 PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00759 { 00760 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00761 return PyFloat_FromDouble(self->m_camdata.m_clipstart); 00762 } 00763 00764 int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00765 { 00766 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00767 float param = PyFloat_AsDouble(value); 00768 if (param == -1) { 00769 PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero"); 00770 return PY_SET_ATTR_FAIL; 00771 } 00772 00773 self->m_camdata.m_clipstart= param; 00774 self->m_set_projection_matrix = false; 00775 return PY_SET_ATTR_SUCCESS; 00776 } 00777 00778 PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00779 { 00780 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00781 return PyFloat_FromDouble(self->m_camdata.m_clipend); 00782 } 00783 00784 int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00785 { 00786 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00787 float param = PyFloat_AsDouble(value); 00788 if (param == -1) { 00789 PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero"); 00790 return PY_SET_ATTR_FAIL; 00791 } 00792 00793 self->m_camdata.m_clipend= param; 00794 self->m_set_projection_matrix = false; 00795 return PY_SET_ATTR_SUCCESS; 00796 } 00797 00798 00799 PyObject* KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00800 { 00801 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00802 return PyBool_FromLong(self->GetViewport()); 00803 } 00804 00805 int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00806 { 00807 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00808 int param = PyObject_IsTrue( value ); 00809 if (param == -1) { 00810 PyErr_SetString(PyExc_AttributeError, "camera.useViewport = bool: KX_Camera, expected True or False"); 00811 return PY_SET_ATTR_FAIL; 00812 } 00813 self->EnableViewport((bool)param); 00814 return PY_SET_ATTR_SUCCESS; 00815 } 00816 00817 00818 PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00819 { 00820 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00821 return PyObjectFrom(self->GetProjectionMatrix()); 00822 } 00823 00824 int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00825 { 00826 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00827 MT_Matrix4x4 mat; 00828 if (!PyMatTo(value, mat)) 00829 return PY_SET_ATTR_FAIL; 00830 00831 self->SetProjectionMatrix(mat); 00832 return PY_SET_ATTR_SUCCESS; 00833 } 00834 00835 PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00836 { 00837 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00838 return PyObjectFrom(self->GetModelviewMatrix()); 00839 } 00840 00841 PyObject* KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00842 { 00843 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00844 return PyObjectFrom(self->GetCameraToWorld()); 00845 } 00846 00847 PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00848 { 00849 KX_Camera* self= static_cast<KX_Camera*>(self_v); 00850 return PyObjectFrom(self->GetWorldToCamera()); 00851 } 00852 00853 00854 PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00855 { return PyLong_FromSsize_t(INSIDE); } 00856 PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00857 { return PyLong_FromSsize_t(OUTSIDE); } 00858 PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00859 { return PyLong_FromSsize_t(INTERSECT); } 00860 00861 00862 bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix) 00863 { 00864 if (value==NULL) { 00865 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); 00866 *object = NULL; 00867 return false; 00868 } 00869 00870 if (value==Py_None) { 00871 *object = NULL; 00872 00873 if (py_none_ok) { 00874 return true; 00875 } else { 00876 PyErr_Format(PyExc_TypeError, "%s, expected KX_Camera or a KX_Camera name, None is invalid", error_prefix); 00877 return false; 00878 } 00879 } 00880 00881 if (PyUnicode_Check(value)) { 00882 STR_String value_str = _PyUnicode_AsString(value); 00883 *object = KX_GetActiveScene()->FindCamera(value_str); 00884 00885 if (*object) { 00886 return true; 00887 } else { 00888 PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, _PyUnicode_AsString(value)); 00889 return false; 00890 } 00891 } 00892 00893 if (PyObject_TypeCheck(value, &KX_Camera::Type)) { 00894 *object = static_cast<KX_Camera*>BGE_PROXY_REF(value); 00895 00896 /* sets the error */ 00897 if (*object==NULL) { 00898 PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); 00899 return false; 00900 } 00901 00902 return true; 00903 } 00904 00905 *object = NULL; 00906 00907 if (py_none_ok) { 00908 PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera, a string or None", error_prefix); 00909 } else { 00910 PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera or a string", error_prefix); 00911 } 00912 00913 return false; 00914 } 00915 00916 KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, 00917 "getScreenPosition()\n" 00918 ) 00919 00920 { 00921 MT_Vector3 vect; 00922 KX_GameObject *obj = NULL; 00923 00924 if (!PyVecTo(value, vect)) 00925 { 00926 PyErr_Clear(); 00927 00928 if(ConvertPythonToGameObject(value, &obj, true, "")) 00929 { 00930 PyErr_Clear(); 00931 vect = MT_Vector3(obj->NodeGetWorldPosition()); 00932 } 00933 else 00934 { 00935 PyErr_SetString(PyExc_TypeError, "Error in getScreenPosition. Expected a Vector3 or a KX_GameObject or a string for a name of a KX_GameObject"); 00936 return NULL; 00937 } 00938 } 00939 00940 GLint viewport[4]; 00941 GLdouble win[3]; 00942 GLdouble modelmatrix[16]; 00943 GLdouble projmatrix[16]; 00944 00945 MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); 00946 MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); 00947 00948 m_modelmatrix.getValue(modelmatrix); 00949 m_projmatrix.getValue(projmatrix); 00950 00951 glGetIntegerv(GL_VIEWPORT, viewport); 00952 00953 gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); 00954 00955 vect[0] = (win[0] - viewport[0]) / viewport[2]; 00956 vect[1] = (win[1] - viewport[1]) / viewport[3]; 00957 00958 vect[1] = 1.0 - vect[1]; //to follow Blender window coordinate system (Top-Down) 00959 00960 PyObject* ret = PyTuple_New(2); 00961 if(ret){ 00962 PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0])); 00963 PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1])); 00964 return ret; 00965 } 00966 00967 return NULL; 00968 } 00969 00970 KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, 00971 "getScreenVect()\n" 00972 ) 00973 { 00974 double x,y; 00975 if (!PyArg_ParseTuple(args,"dd:getScreenVect",&x,&y)) 00976 return NULL; 00977 00978 y = 1.0 - y; //to follow Blender window coordinate system (Top-Down) 00979 00980 MT_Vector3 vect; 00981 MT_Point3 campos, screenpos; 00982 00983 GLint viewport[4]; 00984 GLdouble win[3]; 00985 GLdouble modelmatrix[16]; 00986 GLdouble projmatrix[16]; 00987 00988 MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); 00989 MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); 00990 00991 m_modelmatrix.getValue(modelmatrix); 00992 m_projmatrix.getValue(projmatrix); 00993 00994 glGetIntegerv(GL_VIEWPORT, viewport); 00995 00996 vect[0] = x * viewport[2]; 00997 vect[1] = y * viewport[3]; 00998 00999 vect[0] += viewport[0]; 01000 vect[1] += viewport[1]; 01001 01002 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &vect[2]); 01003 gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); 01004 01005 campos = this->GetCameraLocation(); 01006 screenpos = MT_Point3(win[0], win[1], win[2]); 01007 vect = campos-screenpos; 01008 01009 vect.normalize(); 01010 return PyObjectFrom(vect); 01011 } 01012 01013 KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, 01014 "getScreenRay()\n" 01015 ) 01016 { 01017 MT_Vector3 vect; 01018 double x,y,dist; 01019 char *propName = NULL; 01020 01021 if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName)) 01022 return NULL; 01023 01024 PyObject* argValue = PyTuple_New(2); 01025 PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x)); 01026 PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y)); 01027 01028 if(!PyVecTo(PygetScreenVect(argValue), vect)) 01029 { 01030 Py_DECREF(argValue); 01031 PyErr_SetString(PyExc_TypeError, 01032 "Error in getScreenRay. Invalid 2D coordinate. Expected a normalized 2D screen coordinate, a distance and an optional property argument"); 01033 return NULL; 01034 } 01035 Py_DECREF(argValue); 01036 01037 dist = -dist; 01038 vect += this->GetCameraLocation(); 01039 01040 argValue = (propName?PyTuple_New(3):PyTuple_New(2)); 01041 if (argValue) { 01042 PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect)); 01043 PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist)); 01044 if (propName) 01045 PyTuple_SET_ITEM(argValue, 2, PyUnicode_FromString(propName)); 01046 01047 PyObject* ret= this->PyrayCastTo(argValue,NULL); 01048 Py_DECREF(argValue); 01049 return ret; 01050 } 01051 01052 return NULL; 01053 } 01054 #endif