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