Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreFrustum.cpp

Go to the documentation of this file.
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