00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://ogre.sourceforge.net/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreStableHeaders.h" 00026 #include "OgreFrustum.h" 00027 00028 #include "OgreMath.h" 00029 #include "OgreMatrix3.h" 00030 #include "OgreSceneNode.h" 00031 #include "OgreSphere.h" 00032 #include "OgreLogManager.h" 00033 #include "OgreException.h" 00034 #include "OgreRoot.h" 00035 #include "OgreCamera.h" 00036 #include "OgreHardwareBufferManager.h" 00037 #include "OgreHardwareVertexBuffer.h" 00038 #include "OgreHardwareIndexBuffer.h" 00039 #include "OgreMaterialManager.h" 00040 #include "OgreRenderSystem.h" 00041 00042 namespace Ogre { 00043 00044 String Frustum::msMovableType = "Frustum"; 00045 const Real Frustum::INFINITE_FAR_PLANE_ADJUST = 0.00001; 00046 //----------------------------------------------------------------------- 00047 Frustum::Frustum() : 00048 mProjType(PT_PERSPECTIVE), 00049 mFOVy(Radian(Math::PI/4.0)), 00050 mFarDist(100000.0f), 00051 mNearDist(100.0f), 00052 mAspect(1.33333333333333f), 00053 mProjMatrix(Matrix4::ZERO), 00054 mViewMatrix(Matrix4::ZERO), 00055 mRecalcFrustum(true), 00056 mRecalcView(true), 00057 mReflect(false), 00058 mReflectMatrix(Matrix4::ZERO), 00059 mLinkedReflectPlane(0), 00060 mObliqueDepthProjection(false), 00061 mLinkedObliqueProjPlane(0) 00062 { 00063 // Initialise vertex & index data 00064 mVertexData.vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION); 00065 mVertexData.vertexCount = 32; 00066 mVertexData.vertexStart = 0; 00067 mVertexData.vertexBufferBinding->setBinding( 0, 00068 HardwareBufferManager::getSingleton().createVertexBuffer( 00069 sizeof(Real)*3, 32, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY) ); 00070 00071 // Initialise material 00072 mMaterial = static_cast<Material*>( 00073 MaterialManager::getSingleton().getByName("BaseWhiteNoLighting")); 00074 00075 // Alter superclass members 00076 mVisible = false; 00077 mParentNode = 0; 00078 00079 mLastLinkedReflectionPlane.normal = Vector3::ZERO; 00080 mLastLinkedObliqueProjPlane.normal = Vector3::ZERO; 00081 00082 00083 updateView(); 00084 } 00085 00086 //----------------------------------------------------------------------- 00087 Frustum::~Frustum() 00088 { 00089 // Do nothing 00090 } 00091 00092 //----------------------------------------------------------------------- 00093 void Frustum::setFOVy(const Radian& fov) 00094 { 00095 mFOVy = fov; 00096 invalidateFrustum(); 00097 } 00098 00099 //----------------------------------------------------------------------- 00100 const Radian& Frustum::getFOVy(void) const 00101 { 00102 return mFOVy; 00103 } 00104 00105 00106 //----------------------------------------------------------------------- 00107 void Frustum::setFarClipDistance(Real farPlane) 00108 { 00109 mFarDist = farPlane; 00110 invalidateFrustum(); 00111 } 00112 00113 //----------------------------------------------------------------------- 00114 Real Frustum::getFarClipDistance(void) const 00115 { 00116 return mFarDist; 00117 } 00118 00119 //----------------------------------------------------------------------- 00120 void Frustum::setNearClipDistance(Real nearPlane) 00121 { 00122 if (nearPlane <= 0) 00123 Except(Exception::ERR_INVALIDPARAMS, "Near clip distance must be greater than zero.", 00124 "Frustum::setNearClipDistance"); 00125 mNearDist = nearPlane; 00126 invalidateFrustum(); 00127 } 00128 00129 //----------------------------------------------------------------------- 00130 Real Frustum::getNearClipDistance(void) const 00131 { 00132 return mNearDist; 00133 } 00134 00135 //----------------------------------------------------------------------- 00136 const Matrix4& Frustum::getProjectionMatrix(void) const 00137 { 00138 00139 updateFrustum(); 00140 00141 return mProjMatrix; 00142 } 00143 //----------------------------------------------------------------------- 00144 const Matrix4& Frustum::getStandardProjectionMatrix(void) const 00145 { 00146 00147 updateFrustum(); 00148 00149 return mStandardProjMatrix; 00150 } 00151 //----------------------------------------------------------------------- 00152 const Matrix4& Frustum::getViewMatrix(void) const 00153 { 00154 updateView(); 00155 00156 return mViewMatrix; 00157 00158 } 00159 00160 //----------------------------------------------------------------------- 00161 const Plane& Frustum::getFrustumPlane(unsigned short plane) const 00162 { 00163 // Make any pending updates to the calculated frustum 00164 updateView(); 00165 00166 return mFrustumPlanes[plane]; 00167 00168 } 00169 00170 //----------------------------------------------------------------------- 00171 bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const 00172 { 00173 // Null boxes always invisible 00174 if (bound.isNull()) return false; 00175 00176 // Make any pending updates to the calculated frustum 00177 updateView(); 00178 00179 // Get corners of the box 00180 const Vector3* pCorners = bound.getAllCorners(); 00181 00182 00183 // For each plane, see if all points are on the negative side 00184 // If so, object is not visible 00185 for (int plane = 0; plane < 6; ++plane) 00186 { 00187 // Skip far plane if infinite view frustum 00188 if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR) 00189 continue; 00190 00191 if (mFrustumPlanes[plane].getSide(pCorners[0]) == Plane::NEGATIVE_SIDE && 00192 mFrustumPlanes[plane].getSide(pCorners[1]) == Plane::NEGATIVE_SIDE && 00193 mFrustumPlanes[plane].getSide(pCorners[2]) == Plane::NEGATIVE_SIDE && 00194 mFrustumPlanes[plane].getSide(pCorners[3]) == Plane::NEGATIVE_SIDE && 00195 mFrustumPlanes[plane].getSide(pCorners[4]) == Plane::NEGATIVE_SIDE && 00196 mFrustumPlanes[plane].getSide(pCorners[5]) == Plane::NEGATIVE_SIDE && 00197 mFrustumPlanes[plane].getSide(pCorners[6]) == Plane::NEGATIVE_SIDE && 00198 mFrustumPlanes[plane].getSide(pCorners[7]) == Plane::NEGATIVE_SIDE) 00199 { 00200 // ALL corners on negative side therefore out of view 00201 if (culledBy) 00202 *culledBy = (FrustumPlane)plane; 00203 return false; 00204 } 00205 00206 } 00207 00208 return true; 00209 } 00210 00211 //----------------------------------------------------------------------- 00212 bool Frustum::isVisible(const Vector3& vert, FrustumPlane* culledBy) const 00213 { 00214 // Make any pending updates to the calculated frustum 00215 updateView(); 00216 00217 // For each plane, see if all points are on the negative side 00218 // If so, object is not visible 00219 for (int plane = 0; plane < 6; ++plane) 00220 { 00221 // Skip far plane if infinite view frustum 00222 if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR) 00223 continue; 00224 00225 if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE) 00226 { 00227 // ALL corners on negative side therefore out of view 00228 if (culledBy) 00229 *culledBy = (FrustumPlane)plane; 00230 return false; 00231 } 00232 00233 } 00234 00235 return true; 00236 } 00237 00238 //----------------------------------------------------------------------- 00239 bool Frustum::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const 00240 { 00241 // Make any pending updates to the calculated frustum 00242 updateView(); 00243 00244 // For each plane, see if sphere is on negative side 00245 // If so, object is not visible 00246 for (int plane = 0; plane < 6; ++plane) 00247 { 00248 // Skip far plane if infinite view frustum 00249 if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR) 00250 continue; 00251 00252 // If the distance from sphere center to plane is negative, and 'more negative' 00253 // than the radius of the sphere, sphere is outside frustum 00254 if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius()) 00255 { 00256 // ALL corners on negative side therefore out of view 00257 if (culledBy) 00258 *culledBy = (FrustumPlane)plane; 00259 return false; 00260 } 00261 00262 } 00263 00264 return true; 00265 } 00266 //----------------------------------------------------------------------- 00267 void Frustum::updateFrustum(void) const 00268 { 00269 if (isFrustumOutOfDate()) 00270 { 00271 // Common calcs 00272 Radian thetaY (mFOVy * 0.5f); 00273 Real tanThetaY = Math::Tan(thetaY); 00274 Real tanThetaX = tanThetaY * mAspect; 00275 Real vpTop = tanThetaY * mNearDist; 00276 Real vpRight = tanThetaX * mNearDist; 00277 Real vpBottom = -vpTop; 00278 Real vpLeft = -vpRight; 00279 00280 RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); 00281 // Recalc if frustum params changed 00282 if (mProjType == PT_PERSPECTIVE) 00283 { 00284 00285 // PERSPECTIVE transform, API specific 00286 renderSystem->_makeProjectionMatrix(mFOVy, 00287 mAspect, mNearDist, mFarDist, mProjMatrix); 00288 00289 // PERSPECTIVE transform, API specific for Gpu Programs 00290 renderSystem->_makeProjectionMatrix(mFOVy, 00291 mAspect, mNearDist, mFarDist, mStandardProjMatrix, true); 00292 00293 if (mObliqueDepthProjection) 00294 { 00295 // Translate the plane into view space 00296 Plane viewSpaceNear = mViewMatrix * mObliqueProjPlane; 00297 renderSystem->_applyObliqueDepthProjection( 00298 mProjMatrix, viewSpaceNear, false); 00299 renderSystem->_applyObliqueDepthProjection( 00300 mStandardProjMatrix, viewSpaceNear, true); 00301 } 00302 } 00303 else if (mProjType == PT_ORTHOGRAPHIC) 00304 { 00305 // ORTHOGRAPHIC projection, API specific 00306 Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy, 00307 mAspect, mNearDist, mFarDist, mProjMatrix); 00308 00309 // ORTHOGRAPHIC projection, non-API specific 00310 Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy, 00311 mAspect, mNearDist, mFarDist, mStandardProjMatrix, true); 00312 00313 00314 } 00315 00316 00317 // Calculate bounding box (local) 00318 // Box is from 0, down -Z, max dimensions as determined from far plane 00319 // If infinite view frustum just pick a far value 00320 Real farDist = (mFarDist == 0) ? 100000 : mFarDist; 00321 Real farTop = tanThetaY * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist); 00322 Real farRight = tanThetaX * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist); 00323 Real farBottom = -farTop; 00324 Real farLeft = -farRight; 00325 Vector3 min(-farRight, -farTop, 0); 00326 Vector3 max(farRight, farTop, -farDist); 00327 mBoundingBox.setExtents(min, max); 00328 00329 // Calculate vertex positions (local) 00330 // 0 is the origin 00331 // 1, 2, 3, 4 are the points on the near plane, top left first, clockwise 00332 // 5, 6, 7, 8 are the points on the far plane, top left first, clockwise 00333 HardwareVertexBufferSharedPtr vbuf = mVertexData.vertexBufferBinding->getBuffer(0); 00334 Real* pReal = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); 00335 00336 // near plane (remember frustum is going in -Z direction) 00337 *pReal++ = vpLeft; *pReal++ = vpTop; *pReal++ = -mNearDist; 00338 *pReal++ = vpRight; *pReal++ = vpTop; *pReal++ = -mNearDist; 00339 00340 *pReal++ = vpRight; *pReal++ = vpTop; *pReal++ = -mNearDist; 00341 *pReal++ = vpRight; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00342 00343 *pReal++ = vpRight; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00344 *pReal++ = vpLeft; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00345 00346 *pReal++ = vpLeft; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00347 *pReal++ = vpLeft; *pReal++ = vpTop; *pReal++ = -mNearDist; 00348 00349 // far plane (remember frustum is going in -Z direction) 00350 *pReal++ = farLeft; *pReal++ = farTop; *pReal++ = -farDist; 00351 *pReal++ = farRight; *pReal++ = farTop; *pReal++ = -farDist; 00352 00353 *pReal++ = farRight; *pReal++ = farTop; *pReal++ = -farDist; 00354 *pReal++ = farRight; *pReal++ = farBottom; *pReal++ = -farDist; 00355 00356 *pReal++ = farRight; *pReal++ = farBottom; *pReal++ = -farDist; 00357 *pReal++ = farLeft; *pReal++ = farBottom; *pReal++ = -farDist; 00358 00359 *pReal++ = farLeft; *pReal++ = farBottom; *pReal++ = -farDist; 00360 *pReal++ = farLeft; *pReal++ = farTop; *pReal++ = -farDist; 00361 00362 // Sides of the pyramid 00363 *pReal++ = 0.0f; *pReal++ = 0.0f; *pReal++ = 0.0f; 00364 *pReal++ = vpLeft; *pReal++ = vpTop; *pReal++ = -mNearDist; 00365 00366 *pReal++ = 0.0f; *pReal++ = 0.0f; *pReal++ = 0.0f; 00367 *pReal++ = vpRight; *pReal++ = vpTop; *pReal++ = -mNearDist; 00368 00369 *pReal++ = 0.0f; *pReal++ = 0.0f; *pReal++ = 0.0f; 00370 *pReal++ = vpRight; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00371 00372 *pReal++ = 0.0f; *pReal++ = 0.0f; *pReal++ = 0.0f; 00373 *pReal++ = vpLeft; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00374 00375 // Sides of the box 00376 00377 *pReal++ = vpLeft; *pReal++ = vpTop; *pReal++ = -mNearDist; 00378 *pReal++ = farLeft; *pReal++ = farTop; *pReal++ = -farDist; 00379 00380 *pReal++ = vpRight; *pReal++ = vpTop; *pReal++ = -mNearDist; 00381 *pReal++ = farRight; *pReal++ = farTop; *pReal++ = -farDist; 00382 00383 *pReal++ = vpRight; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00384 *pReal++ = farRight; *pReal++ = farBottom; *pReal++ = -farDist; 00385 00386 *pReal++ = vpLeft; *pReal++ = vpBottom; *pReal++ = -mNearDist; 00387 *pReal++ = farLeft; *pReal++ = farBottom; *pReal++ = -farDist; 00388 00389 00390 vbuf->unlock(); 00391 00392 mRecalcFrustum = false; 00393 } 00394 } 00395 00396 //----------------------------------------------------------------------- 00397 bool Frustum::isViewOutOfDate(void) const 00398 { 00399 bool returnVal = false; 00400 // Attached to node? 00401 if (mParentNode) 00402 { 00403 if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation && 00404 mParentNode->_getDerivedPosition() == mLastParentPosition) 00405 { 00406 returnVal = false; 00407 } 00408 else 00409 { 00410 // Ok, we're out of date with SceneNode we're attached to 00411 mLastParentOrientation = mParentNode->_getDerivedOrientation(); 00412 mLastParentPosition = mParentNode->_getDerivedPosition(); 00413 returnVal = true; 00414 } 00415 } 00416 // Deriving reflection from linked plane? 00417 if (mReflect && mLinkedReflectPlane && 00418 !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane())) 00419 { 00420 mReflectPlane = mLinkedReflectPlane->_getDerivedPlane(); 00421 mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane); 00422 mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane(); 00423 returnVal = true; 00424 } 00425 00426 return mRecalcView || returnVal; 00427 } 00428 00429 //----------------------------------------------------------------------- 00430 bool Frustum::isFrustumOutOfDate(void) const 00431 { 00432 // Deriving custom near plane from linked plane? 00433 bool returnVal = false; 00434 if (mObliqueDepthProjection) 00435 { 00436 // Always out of date since plane needs to be in view space 00437 returnVal = true; 00438 // Update derived plane 00439 if (mLinkedObliqueProjPlane && 00440 !(mLastLinkedObliqueProjPlane == mLinkedObliqueProjPlane->_getDerivedPlane())) 00441 { 00442 mObliqueProjPlane = mLinkedObliqueProjPlane->_getDerivedPlane(); 00443 mLastLinkedObliqueProjPlane = mObliqueProjPlane; 00444 } 00445 } 00446 00447 return mRecalcFrustum || returnVal; 00448 } 00449 00450 //----------------------------------------------------------------------- 00451 void Frustum::updateView(void) const 00452 { 00453 if (isViewOutOfDate()) 00454 { 00455 // ---------------------- 00456 // Update the view matrix 00457 // ---------------------- 00458 00459 // View matrix is: 00460 // 00461 // [ Lx Uy Dz Tx ] 00462 // [ Lx Uy Dz Ty ] 00463 // [ Lx Uy Dz Tz ] 00464 // [ 0 0 0 1 ] 00465 // 00466 // Where T = -(Transposed(Rot) * Pos) 00467 00468 // This is most efficiently done using 3x3 Matrices 00469 00470 // Get orientation from quaternion 00471 00472 Matrix3 rot; 00473 const Quaternion& orientation = getOrientationForViewUpdate(); 00474 const Vector3& position = getPositionForViewUpdate(); 00475 orientation.ToRotationMatrix(rot); 00476 Vector3 left = rot.GetColumn(0); 00477 Vector3 up = rot.GetColumn(1); 00478 Vector3 direction = rot.GetColumn(2); 00479 00480 00481 // Make the translation relative to new axes 00482 Matrix3 rotT = rot.Transpose(); 00483 Vector3 trans = -rotT * position; 00484 00485 // Make final matrix 00486 mViewMatrix = Matrix4::IDENTITY; 00487 mViewMatrix = rotT; // fills upper 3x3 00488 mViewMatrix[0][3] = trans.x; 00489 mViewMatrix[1][3] = trans.y; 00490 mViewMatrix[2][3] = trans.z; 00491 00492 // Deal with reflections 00493 if (mReflect) 00494 { 00495 mViewMatrix = mViewMatrix * mReflectMatrix; 00496 } 00497 00498 // ------------------------- 00499 // Update the frustum planes 00500 // ------------------------- 00501 updateFrustum(); 00502 // Use Frustum view direction for frustum, which is -Z not Z as for matrix calc 00503 Vector3 camDirection = orientation* -Vector3::UNIT_Z; 00504 // Calc distance along direction to position 00505 Real fDdE = camDirection.dotProduct(position); 00506 00507 Matrix4 combo = mStandardProjMatrix * mViewMatrix; 00508 mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0]; 00509 mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1]; 00510 mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2]; 00511 mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3]; 00512 00513 mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0]; 00514 mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1]; 00515 mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2]; 00516 mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3]; 00517 00518 mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0]; 00519 mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1]; 00520 mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2]; 00521 mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3]; 00522 00523 mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0]; 00524 mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1]; 00525 mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2]; 00526 mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3]; 00527 00528 mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0]; 00529 mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1]; 00530 mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2]; 00531 mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3]; 00532 00533 mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0]; 00534 mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1]; 00535 mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2]; 00536 mFrustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3]; 00537 00538 // Renormalise any normals which were not unit length 00539 for(int i=0; i<6; i++ ) 00540 { 00541 float length = mFrustumPlanes[i].normal.normalise(); 00542 mFrustumPlanes[i].d /= length; 00543 } 00544 00545 // Update worldspace corners 00546 Matrix4 eyeToWorld = mViewMatrix.inverse(); 00547 // Get worldspace frustum corners 00548 // Treat infinite fardist as some arbitrary far value 00549 Real farDist = (mFarDist == 0)? 100000 : mFarDist; 00550 Real y = Math::Tan(mFOVy * 0.5); 00551 Real x = mAspect * y; 00552 Real neary = y * mNearDist; 00553 Real fary = y * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist); 00554 Real nearx = x * mNearDist; 00555 Real farx = x * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist); 00556 // near 00557 mWorldSpaceCorners[0] = eyeToWorld * Vector3( nearx, neary, -mNearDist); 00558 mWorldSpaceCorners[1] = eyeToWorld * Vector3(-nearx, neary, -mNearDist); 00559 mWorldSpaceCorners[2] = eyeToWorld * Vector3(-nearx, -neary, -mNearDist); 00560 mWorldSpaceCorners[3] = eyeToWorld * Vector3( nearx, -neary, -mNearDist); 00561 // far 00562 mWorldSpaceCorners[4] = eyeToWorld * Vector3( farx, fary, -farDist); 00563 mWorldSpaceCorners[5] = eyeToWorld * Vector3(-farx, fary, -farDist); 00564 mWorldSpaceCorners[6] = eyeToWorld * Vector3(-farx, -fary, -farDist); 00565 mWorldSpaceCorners[7] = eyeToWorld * Vector3( farx, -fary, -farDist); 00566 00567 00568 mRecalcView = false; 00569 00570 } 00571 00572 } 00573 00574 //----------------------------------------------------------------------- 00575 Real Frustum::getAspectRatio(void) const 00576 { 00577 return mAspect; 00578 } 00579 00580 //----------------------------------------------------------------------- 00581 void Frustum::setAspectRatio(Real r) 00582 { 00583 mAspect = r; 00584 invalidateFrustum(); 00585 } 00586 00587 //----------------------------------------------------------------------- 00588 const AxisAlignedBox& Frustum::getBoundingBox(void) const 00589 { 00590 return mBoundingBox; 00591 } 00592 //----------------------------------------------------------------------- 00593 void Frustum::_updateRenderQueue(RenderQueue* queue) 00594 { 00595 // Add self 00596 queue->addRenderable(this); 00597 } 00598 //----------------------------------------------------------------------- 00599 const String& Frustum::getMovableType(void) const 00600 { 00601 return msMovableType; 00602 } 00603 //----------------------------------------------------------------------- 00604 Real Frustum::getBoundingRadius(void) const 00605 { 00606 return (mFarDist == 0)? 100000 : mFarDist; 00607 } 00608 //----------------------------------------------------------------------- 00609 Material* Frustum::getMaterial(void) const 00610 { 00611 return mMaterial; 00612 } 00613 //----------------------------------------------------------------------- 00614 void Frustum::getRenderOperation(RenderOperation& op) 00615 { 00616 updateView(); 00617 updateFrustum(); 00618 op.operationType = RenderOperation::OT_LINE_LIST; 00619 op.useIndexes = false; 00620 op.vertexData = &mVertexData; 00621 } 00622 //----------------------------------------------------------------------- 00623 void Frustum::getWorldTransforms(Matrix4* xform) const 00624 { 00625 if (mParentNode) 00626 mParentNode->getWorldTransforms(xform); 00627 } 00628 //----------------------------------------------------------------------- 00629 const Quaternion& Frustum::getWorldOrientation(void) const 00630 { 00631 if (mParentNode) 00632 return mParentNode->_getDerivedOrientation(); 00633 else 00634 return Quaternion::IDENTITY; 00635 } 00636 //----------------------------------------------------------------------- 00637 const Vector3& Frustum::getWorldPosition(void) const 00638 { 00639 if (mParentNode) 00640 return mParentNode->_getDerivedPosition(); 00641 else 00642 return Vector3::ZERO; 00643 } 00644 //----------------------------------------------------------------------- 00645 Real Frustum::getSquaredViewDepth(const Camera* cam) const 00646 { 00647 // Calc from centre 00648 if (mParentNode) 00649 return (cam->getDerivedPosition() 00650 - mParentNode->_getDerivedPosition()).squaredLength(); 00651 else 00652 return 0; 00653 } 00654 //----------------------------------------------------------------------- 00655 const LightList& Frustum::getLights(void) const 00656 { 00657 // N/A 00658 static LightList ll; 00659 return ll; 00660 } 00661 //----------------------------------------------------------------------- 00662 const String& Frustum::getName(void) const 00663 { 00664 // NA 00665 return msMovableType; 00666 } 00667 //----------------------------------------------------------------------- 00668 void Frustum::_notifyCurrentCamera(Camera* cam) 00669 { 00670 // NA 00671 } 00672 00673 // ------------------------------------------------------------------- 00674 void Frustum::invalidateFrustum() const 00675 { 00676 mRecalcFrustum = true; 00677 } 00678 // ------------------------------------------------------------------- 00679 void Frustum::invalidateView() const 00680 { 00681 mRecalcView = true; 00682 } 00683 // ------------------------------------------------------------------- 00684 const Vector3* Frustum::getWorldSpaceCorners(void) const 00685 { 00686 updateView(); 00687 00688 return mWorldSpaceCorners; 00689 } 00690 //----------------------------------------------------------------------- 00691 void Frustum::setProjectionType(ProjectionType pt) 00692 { 00693 mProjType = pt; 00694 invalidateFrustum(); 00695 } 00696 00697 //----------------------------------------------------------------------- 00698 ProjectionType Frustum::getProjectionType(void) const 00699 { 00700 return mProjType; 00701 } 00702 //----------------------------------------------------------------------- 00703 const Vector3& Frustum::getPositionForViewUpdate(void) const 00704 { 00705 return mLastParentPosition; 00706 } 00707 //----------------------------------------------------------------------- 00708 const Quaternion& Frustum::getOrientationForViewUpdate(void) const 00709 { 00710 return mLastParentOrientation; 00711 } 00712 //----------------------------------------------------------------------- 00713 void Frustum::enableReflection(const Plane& p) 00714 { 00715 mReflect = true; 00716 mReflectPlane = p; 00717 mLinkedReflectPlane = 0; 00718 mReflectMatrix = Math::buildReflectionMatrix(p); 00719 invalidateView(); 00720 00721 } 00722 //----------------------------------------------------------------------- 00723 void Frustum::enableReflection(const MovablePlane* p) 00724 { 00725 mReflect = true; 00726 mLinkedReflectPlane = p; 00727 mReflectPlane = mLinkedReflectPlane->_getDerivedPlane(); 00728 mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane); 00729 mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane(); 00730 invalidateView(); 00731 } 00732 //----------------------------------------------------------------------- 00733 void Frustum::disableReflection(void) 00734 { 00735 mReflect = false; 00736 mLastLinkedReflectionPlane.normal = Vector3::ZERO; 00737 invalidateView(); 00738 } 00739 //--------------------------------------------------------------------- 00740 bool Frustum::projectSphere(const Sphere& sphere, 00741 Real* left, Real* top, Real* right, Real* bottom) const 00742 { 00743 // initialise 00744 *left = *bottom = -1.0f; 00745 *right = *top = 1.0f; 00746 00747 // Transform light position into camera space 00748 Vector3 eyeSpacePos = getViewMatrix() * sphere.getCenter(); 00749 00750 if (eyeSpacePos.z < 0) 00751 { 00752 Real r = sphere.getRadius(); 00753 // early-exit 00754 if (eyeSpacePos.squaredLength() <= r * r) 00755 return false; 00756 00757 Vector3 screenSpacePos = getStandardProjectionMatrix() * eyeSpacePos; 00758 00759 00760 // perspective attenuate 00761 Vector3 spheresize(r, r, eyeSpacePos.z); 00762 spheresize = getStandardProjectionMatrix() * spheresize; 00763 00764 Real possLeft = screenSpacePos.x - spheresize.x; 00765 Real possRight = screenSpacePos.x + spheresize.x; 00766 Real possTop = screenSpacePos.y + spheresize.y; 00767 Real possBottom = screenSpacePos.y - spheresize.y; 00768 00769 *left = std::max(-1.0f, possLeft); 00770 *right = std::min(1.0f, possRight); 00771 *top = std::min(1.0f, possTop); 00772 *bottom = std::max(-1.0f, possBottom); 00773 00774 } 00775 00776 return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f); 00777 00778 } 00779 //--------------------------------------------------------------------- 00780 void Frustum::enableCustomNearClipPlane(const MovablePlane* plane) 00781 { 00782 mObliqueDepthProjection = true; 00783 mLinkedObliqueProjPlane = plane; 00784 mObliqueProjPlane = plane->_getDerivedPlane(); 00785 invalidateFrustum(); 00786 } 00787 //--------------------------------------------------------------------- 00788 void Frustum::enableCustomNearClipPlane(const Plane& plane) 00789 { 00790 mObliqueDepthProjection = true; 00791 mLinkedObliqueProjPlane = 0; 00792 mObliqueProjPlane = plane; 00793 invalidateFrustum(); 00794 } 00795 //--------------------------------------------------------------------- 00796 void Frustum::disableCustomNearClipPlane(void) 00797 { 00798 mObliqueDepthProjection = false; 00799 mLinkedObliqueProjPlane = 0; 00800 invalidateFrustum(); 00801 } 00802 //--------------------------------------------------------------------- 00803 00804 00805 } // namespace Ogre
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:24 2004