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