source: trunk/VUT/work/ogre_changes/OgreMain/src/OgreFrustum.cpp @ 61

Revision 61, 31.8 KB checked in by mattausch, 19 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://ogre.sourceforge.net/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreFrustum.h"
27
28#include "OgreMath.h"
29#include "OgreMatrix3.h"
30#include "OgreSceneNode.h"
31#include "OgreSphere.h"
32#include "OgreLogManager.h"
33#include "OgreException.h"
34#include "OgreRoot.h"
35#include "OgreCamera.h"
36#include "OgreHardwareBufferManager.h"
37#include "OgreHardwareVertexBuffer.h"
38#include "OgreHardwareIndexBuffer.h"
39#include "OgreMaterialManager.h"
40#include "OgreRenderSystem.h"
41
42namespace Ogre {
43
44    String Frustum::msMovableType = "Frustum";
45    const Real Frustum::INFINITE_FAR_PLANE_ADJUST = 0.00001;
46    //-----------------------------------------------------------------------
47    Frustum::Frustum() :
48        mProjType(PT_PERSPECTIVE),
49        mFOVy(Radian(Math::PI/4.0)),
50        mFarDist(100000.0f),
51        mNearDist(100.0f),
52        mAspect(1.33333333333333f),
53        mProjMatrix(Matrix4::ZERO),
54        mViewMatrix(Matrix4::ZERO),
55        mRecalcFrustum(true),
56        mRecalcView(true),
57        mReflect(false),
58        mReflectMatrix(Matrix4::ZERO),
59        mLinkedReflectPlane(0),
60        mObliqueDepthProjection(false),
61        mLinkedObliqueProjPlane(0)
62    {
63        // Initialise vertex & index data
64        mVertexData.vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
65        mVertexData.vertexCount = 32;
66        mVertexData.vertexStart = 0;
67        mVertexData.vertexBufferBinding->setBinding( 0,
68            HardwareBufferManager::getSingleton().createVertexBuffer(
69                sizeof(float)*3, 32, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY) );
70
71        // Initialise material
72        mMaterial = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
73       
74        // Alter superclass members
75        mVisible = false;
76        mParentNode = 0;
77
78        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
79        mLastLinkedObliqueProjPlane.normal = Vector3::ZERO;
80
81
82        updateView();
83    }
84
85    //-----------------------------------------------------------------------
86    Frustum::~Frustum()
87    {
88        // Do nothing
89    }
90
91    //-----------------------------------------------------------------------
92    void Frustum::setFOVy(const Radian& fov)
93    {
94        mFOVy = fov;
95        invalidateFrustum();
96    }
97
98    //-----------------------------------------------------------------------
99    const Radian& Frustum::getFOVy(void) const
100    {
101        return mFOVy;
102    }
103
104
105    //-----------------------------------------------------------------------
106    void Frustum::setFarClipDistance(Real farPlane)
107    {
108        mFarDist = farPlane;
109        invalidateFrustum();
110    }
111
112    //-----------------------------------------------------------------------
113    Real Frustum::getFarClipDistance(void) const
114    {
115        return mFarDist;
116    }
117
118    //-----------------------------------------------------------------------
119    void Frustum::setNearClipDistance(Real nearPlane)
120    {
121        if (nearPlane <= 0)
122            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Near clip distance must be greater than zero.",
123                "Frustum::setNearClipDistance");
124        mNearDist = nearPlane;
125        invalidateFrustum();
126    }
127
128    //-----------------------------------------------------------------------
129    Real Frustum::getNearClipDistance(void) const
130    {
131        return mNearDist;
132    }
133
134    //-----------------------------------------------------------------------
135    const Matrix4& Frustum::getProjectionMatrix(void) const
136    {
137
138        updateFrustum();
139
140        return mProjMatrix;
141    }
142    //-----------------------------------------------------------------------
143    const Matrix4& Frustum::getStandardProjectionMatrix(void) const
144    {
145
146        updateFrustum();
147
148        return mStandardProjMatrix;
149    }
150    //-----------------------------------------------------------------------
151    const Matrix4& Frustum::getViewMatrix(void) const
152    {
153        updateView();
154
155        return mViewMatrix;
156
157    }
158
159    //-----------------------------------------------------------------------
160    const Plane& Frustum::getFrustumPlane(unsigned short plane) const
161    {
162        // Make any pending updates to the calculated frustum
163        updateView();
164
165        return mFrustumPlanes[plane];
166
167    }
168
169    //-----------------------------------------------------------------------
170    bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
171    {
172        // Null boxes always invisible
173        if (bound.isNull()) return false;
174
175        // Make any pending updates to the calculated frustum
176        updateView();
177
178        // Get corners of the box
179        const Vector3* pCorners = bound.getAllCorners();
180
181
182        // For each plane, see if all points are on the negative side
183        // If so, object is not visible
184        for (int plane = 0; plane < 6; ++plane)
185        {
186            // Skip far plane if infinite view frustum
187            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
188                continue;
189
190            if (mFrustumPlanes[plane].getSide(pCorners[0]) == Plane::NEGATIVE_SIDE &&
191                mFrustumPlanes[plane].getSide(pCorners[1]) == Plane::NEGATIVE_SIDE &&
192                mFrustumPlanes[plane].getSide(pCorners[2]) == Plane::NEGATIVE_SIDE &&
193                mFrustumPlanes[plane].getSide(pCorners[3]) == Plane::NEGATIVE_SIDE &&
194                mFrustumPlanes[plane].getSide(pCorners[4]) == Plane::NEGATIVE_SIDE &&
195                mFrustumPlanes[plane].getSide(pCorners[5]) == Plane::NEGATIVE_SIDE &&
196                mFrustumPlanes[plane].getSide(pCorners[6]) == Plane::NEGATIVE_SIDE &&
197                mFrustumPlanes[plane].getSide(pCorners[7]) == Plane::NEGATIVE_SIDE)
198            {
199                // ALL corners on negative side therefore out of view
200                if (culledBy)
201                    *culledBy = (FrustumPlane)plane;
202                return false;
203            }
204
205        }
206
207        return true;
208    }
209
210    //-----------------------------------------------------------------------
211    bool Frustum::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
212    {
213        // Make any pending updates to the calculated frustum
214        updateView();
215
216        // For each plane, see if all points are on the negative side
217        // If so, object is not visible
218        for (int plane = 0; plane < 6; ++plane)
219        {
220            // Skip far plane if infinite view frustum
221            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
222                continue;
223
224            if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE)
225            {
226                // ALL corners on negative side therefore out of view
227                if (culledBy)
228                    *culledBy = (FrustumPlane)plane;
229                return false;
230            }
231
232        }
233
234        return true;
235    }
236
237    //-----------------------------------------------------------------------
238    bool Frustum::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const
239    {
240        // Make any pending updates to the calculated frustum
241        updateView();
242
243        // For each plane, see if sphere is on negative side
244        // If so, object is not visible
245        for (int plane = 0; plane < 6; ++plane)
246        {
247            // Skip far plane if infinite view frustum
248            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
249                continue;
250
251            // If the distance from sphere center to plane is negative, and 'more negative'
252            // than the radius of the sphere, sphere is outside frustum
253            if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius())
254            {
255                // ALL corners on negative side therefore out of view
256                if (culledBy)
257                    *culledBy = (FrustumPlane)plane;
258                return false;
259            }
260
261        }
262
263        return true;
264    }
265    //-----------------------------------------------------------------------
266    void Frustum::updateFrustum(void) const
267    {
268        if (isFrustumOutOfDate())
269        {
270            // Common calcs
271            Radian thetaY (mFOVy * 0.5f);
272            Real tanThetaY = Math::Tan(thetaY);
273            Real tanThetaX = tanThetaY * mAspect;
274            Real vpTop = tanThetaY * mNearDist;
275            Real vpRight = tanThetaX * mNearDist;
276            Real vpBottom = -vpTop;
277            Real vpLeft = -vpRight;
278
279            RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
280            // Recalc if frustum params changed
281            if (mProjType == PT_PERSPECTIVE)
282            {
283
284                // PERSPECTIVE transform, API specific
285                renderSystem->_makeProjectionMatrix(mFOVy,
286                    mAspect, mNearDist, mFarDist, mProjMatrix);
287
288                // PERSPECTIVE transform, API specific for Gpu Programs
289                renderSystem->_makeProjectionMatrix(mFOVy,
290                    mAspect, mNearDist, mFarDist, mStandardProjMatrix, true);
291
292                if (mObliqueDepthProjection)
293                {
294                    // Translate the plane into view space
295                    Plane viewSpaceNear = mViewMatrix * mObliqueProjPlane;
296                    renderSystem->_applyObliqueDepthProjection(
297                        mProjMatrix, viewSpaceNear, false);
298                    renderSystem->_applyObliqueDepthProjection(
299                        mStandardProjMatrix, viewSpaceNear, true);
300                }
301            }
302            else if (mProjType == PT_ORTHOGRAPHIC)
303            {
304                // ORTHOGRAPHIC projection, API specific
305                Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy,
306                    mAspect, mNearDist, mFarDist, mProjMatrix);
307
308                // ORTHOGRAPHIC projection, non-API specific
309                Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy,
310                    mAspect, mNearDist, mFarDist, mStandardProjMatrix, true);
311
312
313            }
314
315           
316            // Calculate bounding box (local)
317            // Box is from 0, down -Z, max dimensions as determined from far plane
318            // If infinite view frustum just pick a far value
319            Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
320            Real farTop = tanThetaY * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
321            Real farRight = tanThetaX * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
322            Real farBottom = -farTop;
323            Real farLeft = -farRight;
324            Vector3 min(-farRight, -farTop, 0);
325            Vector3 max(farRight, farTop, -farDist);
326            mBoundingBox.setExtents(min, max);
327
328            // Calculate vertex positions (local)
329            // 0 is the origin
330            // 1, 2, 3, 4 are the points on the near plane, top left first, clockwise
331            // 5, 6, 7, 8 are the points on the far plane, top left first, clockwise
332            HardwareVertexBufferSharedPtr vbuf = mVertexData.vertexBufferBinding->getBuffer(0);
333            float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
334
335            // near plane (remember frustum is going in -Z direction)
336            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
337            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
338
339            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
340            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
341
342            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
343            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
344
345            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
346            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
347
348            // far plane (remember frustum is going in -Z direction)
349            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
350            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
351
352            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
353            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
354
355            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
356            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
357
358            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
359            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
360
361            // Sides of the pyramid
362            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
363            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
364
365            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
366            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
367
368            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
369            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
370
371            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
372            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
373
374            // Sides of the box
375
376            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
377            *pFloat++ = farLeft;  *pFloat++ = farTop;  *pFloat++ = -farDist;
378
379            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
380            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
381
382            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
383            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
384
385            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
386            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
387
388
389            vbuf->unlock();
390
391            mRecalcFrustum = false;
392        }
393    }
394
395    //-----------------------------------------------------------------------
396    bool Frustum::isViewOutOfDate(void) const
397    {
398        bool returnVal = false;
399        // Attached to node?
400        if (mParentNode)
401        {
402            if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation &&
403                mParentNode->_getDerivedPosition() == mLastParentPosition)
404            {
405                returnVal = false;
406            }
407            else
408            {
409                // Ok, we're out of date with SceneNode we're attached to
410                mLastParentOrientation = mParentNode->_getDerivedOrientation();
411                mLastParentPosition = mParentNode->_getDerivedPosition();
412                returnVal = true;
413            }
414        }
415        // Deriving reflection from linked plane?
416        if (mReflect && mLinkedReflectPlane &&
417            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
418        {
419            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
420            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
421            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
422            returnVal = true;
423        }
424
425        return mRecalcView || returnVal;
426    }
427
428    //-----------------------------------------------------------------------
429    bool Frustum::isFrustumOutOfDate(void) const
430    {
431        // Deriving custom near plane from linked plane?
432        bool returnVal = false;
433        if (mObliqueDepthProjection)
434        {
435            // Always out of date since plane needs to be in view space
436            returnVal = true;
437            // Update derived plane
438            if (mLinkedObliqueProjPlane &&
439                !(mLastLinkedObliqueProjPlane == mLinkedObliqueProjPlane->_getDerivedPlane()))
440            {
441                mObliqueProjPlane = mLinkedObliqueProjPlane->_getDerivedPlane();
442                mLastLinkedObliqueProjPlane = mObliqueProjPlane;
443            }
444        }
445
446        return mRecalcFrustum || returnVal;
447    }
448
449    //-----------------------------------------------------------------------
450    void Frustum::updateView(void) const
451    {
452        if (isViewOutOfDate())
453        {
454            // ----------------------
455            // Update the view matrix
456            // ----------------------
457
458            // View matrix is:
459            //
460            //  [ Lx  Uy  Dz  Tx  ]
461            //  [ Lx  Uy  Dz  Ty  ]
462            //  [ Lx  Uy  Dz  Tz  ]
463            //  [ 0   0   0   1   ]
464            //
465            // Where T = -(Transposed(Rot) * Pos)
466
467            // This is most efficiently done using 3x3 Matrices
468
469            // Get orientation from quaternion
470
471                        Matrix3 rot;
472            const Quaternion& orientation = getOrientationForViewUpdate();
473            const Vector3& position = getPositionForViewUpdate();
474                        orientation.ToRotationMatrix(rot);
475
476            // Make the translation relative to new axes
477            Matrix3 rotT = rot.Transpose();
478            Vector3 trans = -rotT * position;
479
480            // Make final matrix
481            mViewMatrix = Matrix4::IDENTITY;
482            mViewMatrix = rotT; // fills upper 3x3
483            mViewMatrix[0][3] = trans.x;
484            mViewMatrix[1][3] = trans.y;
485            mViewMatrix[2][3] = trans.z;
486
487            // Deal with reflections
488            if (mReflect)
489            {
490                mViewMatrix = mViewMatrix * mReflectMatrix;
491            }
492
493            // -------------------------
494            // Update the frustum planes
495            // -------------------------
496            updateFrustum();
497
498            Matrix4 combo = mStandardProjMatrix * mViewMatrix;
499            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
500            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
501            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
502            mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
503
504            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
505            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
506            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
507            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
508
509            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
510            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
511            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
512            mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
513
514            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
515            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
516            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
517            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
518
519            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
520            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
521            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
522            mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3];
523
524            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
525            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
526            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
527            mFrustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3];
528
529            // Renormalise any normals which were not unit length
530            for(int i=0; i<6; i++ )
531            {
532                float length = mFrustumPlanes[i].normal.normalise();
533                mFrustumPlanes[i].d /= length;
534            }
535
536            // Update worldspace corners
537            Matrix4 eyeToWorld = mViewMatrix.inverse();
538            // Get worldspace frustum corners
539            // Treat infinite fardist as some arbitrary far value
540            Real farDist = (mFarDist == 0)? 100000 : mFarDist;
541            Real y = Math::Tan(mFOVy * 0.5);
542            Real x = mAspect * y;
543            Real neary = y * mNearDist;
544            Real fary = y * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
545            Real nearx = x * mNearDist;
546            Real farx = x * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
547            // near
548            mWorldSpaceCorners[0] = eyeToWorld * Vector3( nearx,  neary, -mNearDist);
549            mWorldSpaceCorners[1] = eyeToWorld * Vector3(-nearx,  neary, -mNearDist);
550            mWorldSpaceCorners[2] = eyeToWorld * Vector3(-nearx, -neary, -mNearDist);
551            mWorldSpaceCorners[3] = eyeToWorld * Vector3( nearx, -neary, -mNearDist);
552            // far
553            mWorldSpaceCorners[4] = eyeToWorld * Vector3( farx,  fary, -farDist);
554            mWorldSpaceCorners[5] = eyeToWorld * Vector3(-farx,  fary, -farDist);
555            mWorldSpaceCorners[6] = eyeToWorld * Vector3(-farx, -fary, -farDist);
556            mWorldSpaceCorners[7] = eyeToWorld * Vector3( farx, -fary, -farDist);
557
558
559            mRecalcView = false;
560
561        }
562
563    }
564
565    //-----------------------------------------------------------------------
566    Real Frustum::getAspectRatio(void) const
567    {
568        return mAspect;
569    }
570
571    //-----------------------------------------------------------------------
572    void Frustum::setAspectRatio(Real r)
573    {
574        mAspect = r;
575        invalidateFrustum();
576    }
577
578    //-----------------------------------------------------------------------
579    const AxisAlignedBox& Frustum::getBoundingBox(void) const
580    {
581        return mBoundingBox;
582    }
583    //-----------------------------------------------------------------------
584    void Frustum::_updateRenderQueue(RenderQueue* queue)
585    {
586        // Add self
587        queue->addRenderable(this);
588    }
589    //-----------------------------------------------------------------------
590    const String& Frustum::getMovableType(void) const
591    {
592        return msMovableType;
593    }
594    //-----------------------------------------------------------------------
595        Real Frustum::getBoundingRadius(void) const
596        {
597        return (mFarDist == 0)? 100000 : mFarDist;
598        }
599    //-----------------------------------------------------------------------
600    const MaterialPtr& Frustum::getMaterial(void) const
601    {
602        return mMaterial;
603    }
604    //-----------------------------------------------------------------------
605    void Frustum::getRenderOperation(RenderOperation& op)
606    {
607        updateView();
608        updateFrustum();
609        op.operationType = RenderOperation::OT_LINE_LIST;
610        op.useIndexes = false;
611        op.vertexData = &mVertexData;
612    }
613    //-----------------------------------------------------------------------
614    void Frustum::getWorldTransforms(Matrix4* xform) const
615    {
616        if (mParentNode)
617            mParentNode->getWorldTransforms(xform);
618    }
619    //-----------------------------------------------------------------------
620    const Quaternion& Frustum::getWorldOrientation(void) const
621    {
622        if (mParentNode)
623            return mParentNode->_getDerivedOrientation();
624        else
625            return Quaternion::IDENTITY;
626    }
627    //-----------------------------------------------------------------------
628    const Vector3& Frustum::getWorldPosition(void) const
629    {
630        if (mParentNode)
631            return mParentNode->_getDerivedPosition();
632        else
633            return Vector3::ZERO;
634    }
635    //-----------------------------------------------------------------------
636    Real Frustum::getSquaredViewDepth(const Camera* cam) const
637    {
638        // Calc from centre
639        if (mParentNode)
640            return (cam->getDerivedPosition()
641                - mParentNode->_getDerivedPosition()).squaredLength();
642        else
643            return 0;
644    }
645    //-----------------------------------------------------------------------
646    const LightList& Frustum::getLights(void) const
647    {
648        // N/A
649        static LightList ll;
650        return ll;
651    }
652    //-----------------------------------------------------------------------
653    const String& Frustum::getName(void) const
654    {
655        // NA
656        return msMovableType;
657    }
658    //-----------------------------------------------------------------------
659    void Frustum::_notifyCurrentCamera(Camera* cam)
660    {
661        // NA
662    }
663
664    // -------------------------------------------------------------------
665    void Frustum::invalidateFrustum() const
666    {
667        mRecalcFrustum = true;
668    }
669    // -------------------------------------------------------------------
670    void Frustum::invalidateView() const
671    {
672        mRecalcView = true;
673    }
674    // -------------------------------------------------------------------
675    const Vector3* Frustum::getWorldSpaceCorners(void) const
676    {
677        updateView();
678
679        return mWorldSpaceCorners;
680    }
681    //-----------------------------------------------------------------------
682    void Frustum::setProjectionType(ProjectionType pt)
683    {
684        mProjType = pt;
685        invalidateFrustum();
686    }
687
688    //-----------------------------------------------------------------------
689    ProjectionType Frustum::getProjectionType(void) const
690    {
691        return mProjType;
692    }
693    //-----------------------------------------------------------------------
694    const Vector3& Frustum::getPositionForViewUpdate(void) const
695    {
696        return mLastParentPosition;
697    }
698    //-----------------------------------------------------------------------
699    const Quaternion& Frustum::getOrientationForViewUpdate(void) const
700    {
701        return mLastParentOrientation;
702    }
703    //-----------------------------------------------------------------------
704    void Frustum::enableReflection(const Plane& p)
705    {
706        mReflect = true;
707        mReflectPlane = p;
708        mLinkedReflectPlane = 0;
709        mReflectMatrix = Math::buildReflectionMatrix(p);
710        invalidateView();
711
712    }
713    //-----------------------------------------------------------------------
714    void Frustum::enableReflection(const MovablePlane* p)
715    {
716        mReflect = true;
717        mLinkedReflectPlane = p;
718        mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
719        mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
720        mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
721        invalidateView();
722    }
723    //-----------------------------------------------------------------------
724    void Frustum::disableReflection(void)
725    {
726        mReflect = false;
727        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
728        invalidateView();
729    }
730    //---------------------------------------------------------------------
731    bool Frustum::projectSphere(const Sphere& sphere,
732        Real* left, Real* top, Real* right, Real* bottom) const
733    {
734        // initialise
735        *left = *bottom = -1.0f;
736        *right = *top = 1.0f;
737
738        // Transform light position into camera space
739        Vector3 eyeSpacePos = getViewMatrix() * sphere.getCenter();
740
741        if (eyeSpacePos.z < 0)
742        {
743            Real r = sphere.getRadius();
744            // early-exit
745            if (eyeSpacePos.squaredLength() <= r * r)
746                return false;
747
748            Vector3 screenSpacePos = getStandardProjectionMatrix() * eyeSpacePos;
749
750
751            // perspective attenuate
752            Vector3 spheresize(r, r, eyeSpacePos.z);
753            spheresize = getStandardProjectionMatrix() * spheresize;
754
755            Real possLeft = screenSpacePos.x - spheresize.x;
756            Real possRight = screenSpacePos.x + spheresize.x;
757            Real possTop = screenSpacePos.y + spheresize.y;
758            Real possBottom = screenSpacePos.y - spheresize.y;
759
760            *left = std::max(static_cast<Real>(-1.0), possLeft);
761            *right = std::min(static_cast<Real>(1.0), possRight);
762            *top = std::min(static_cast<Real>(1.0), possTop);
763            *bottom = std::max(static_cast<Real>(-1.0), possBottom);
764
765        }
766
767        return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f);
768
769    }
770    //---------------------------------------------------------------------
771    void Frustum::enableCustomNearClipPlane(const MovablePlane* plane)
772    {
773        mObliqueDepthProjection = true;
774        mLinkedObliqueProjPlane = plane;
775        mObliqueProjPlane = plane->_getDerivedPlane();
776        invalidateFrustum();
777    }
778    //---------------------------------------------------------------------
779    void Frustum::enableCustomNearClipPlane(const Plane& plane)
780    {
781        mObliqueDepthProjection = true;
782        mLinkedObliqueProjPlane = 0;
783        mObliqueProjPlane = plane;
784        invalidateFrustum();
785    }
786    //---------------------------------------------------------------------
787    void Frustum::disableCustomNearClipPlane(void)
788    {
789        mObliqueDepthProjection = false;
790        mLinkedObliqueProjPlane = 0;
791        invalidateFrustum();
792    }
793    //---------------------------------------------------------------------
794
795#ifdef GTP_VISIBILITY_MODIFIED_OGRE
796    //-----------------------------------------------------------------------
797        //added by matt: 050405
798    bool Frustum::isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy) const
799        {
800                intersects = false;
801
802                // Null boxes always invisible
803        if (bound.isNull()) return false;
804
805        // Make any pending updates to the calculated frustum
806        updateView();
807
808        // Get corners of the box
809        const Vector3* pCorners = bound.getAllCorners();
810
811        // For each plane, see if all points are on the negative side
812        // If so, object is not visible
813        for (int plane = 0; plane < 6; ++plane)
814        {
815            // Skip far plane if infinite view frustum
816            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
817                continue;
818                       
819                        int corner = 0;
820                        bool visible = false;
821
822                        while((corner < 8) && (!visible || ((plane == FRUSTUM_PLANE_NEAR) && !intersects)))
823                        {
824                                if(mFrustumPlanes[plane].getSide(pCorners[corner++]) == Plane::NEGATIVE_SIDE)
825                                {
826                                        if(plane == FRUSTUM_PLANE_NEAR)
827                                                intersects = true;
828                                }
829                                else
830                                {
831                                        visible = true;
832                                }
833                        }
834           
835                        if(!visible)
836                        {
837                                // ALL corners on negative side therefore out of view
838                                if (culledBy)
839                                        *culledBy = (FrustumPlane)plane;
840                                return false;
841            }
842                }
843
844        return true;
845    }
846#endif // GTP_VISIBILITY_MODIFIED_OGRE
847} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.