source: OGRE/trunk/ogrenew/OgreMain/src/OgreFrustum.cpp @ 657

Revision 657, 32.1 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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                        Vector3 newpos = position;
499                        if (mReflect)
500                        {
501                                newpos = mReflectMatrix * newpos;
502                        }
503            Matrix4 combo = mStandardProjMatrix * mViewMatrix;
504            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
505            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
506            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
507            mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
508
509            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
510            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
511            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
512            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
513
514            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
515            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
516            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
517            mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
518
519            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
520            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
521            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
522            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
523
524            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
525            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
526            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
527                        mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.normalise();
528                        mFrustumPlanes[FRUSTUM_PLANE_NEAR].d =
529                                -(mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.dotProduct(newpos) + mNearDist);
530
531            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
532            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
533            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
534                        mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.normalise();
535                        mFrustumPlanes[FRUSTUM_PLANE_FAR].d =
536                                -(mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.dotProduct(newpos) - mFarDist);
537
538            // Renormalise any normals which were not unit length (not near & far)
539            for(int i=2; i<6; i++ )
540            {
541                float length = mFrustumPlanes[i].normal.normalise();
542                mFrustumPlanes[i].d /= length;
543            }
544
545            // Update worldspace corners
546            Matrix4 eyeToWorld = mViewMatrix.inverse();
547            // Get worldspace frustum corners
548            // Treat infinite fardist as some arbitrary far value
549            Real farDist = (mFarDist == 0)? 100000 : mFarDist;
550            Real y = Math::Tan(mFOVy * 0.5);
551            Real x = mAspect * y;
552            Real neary = y * mNearDist;
553            Real fary = y * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
554            Real nearx = x * mNearDist;
555            Real farx = x * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
556            // near
557            mWorldSpaceCorners[0] = eyeToWorld * Vector3( nearx,  neary, -mNearDist);
558            mWorldSpaceCorners[1] = eyeToWorld * Vector3(-nearx,  neary, -mNearDist);
559            mWorldSpaceCorners[2] = eyeToWorld * Vector3(-nearx, -neary, -mNearDist);
560            mWorldSpaceCorners[3] = eyeToWorld * Vector3( nearx, -neary, -mNearDist);
561            // far
562            mWorldSpaceCorners[4] = eyeToWorld * Vector3( farx,  fary, -farDist);
563            mWorldSpaceCorners[5] = eyeToWorld * Vector3(-farx,  fary, -farDist);
564            mWorldSpaceCorners[6] = eyeToWorld * Vector3(-farx, -fary, -farDist);
565            mWorldSpaceCorners[7] = eyeToWorld * Vector3( farx, -fary, -farDist);
566
567
568            mRecalcView = false;
569
570        }
571
572    }
573
574    //-----------------------------------------------------------------------
575    Real Frustum::getAspectRatio(void) const
576    {
577        return mAspect;
578    }
579
580    //-----------------------------------------------------------------------
581    void Frustum::setAspectRatio(Real r)
582    {
583        mAspect = r;
584        invalidateFrustum();
585    }
586
587    //-----------------------------------------------------------------------
588    const AxisAlignedBox& Frustum::getBoundingBox(void) const
589    {
590        return mBoundingBox;
591    }
592    //-----------------------------------------------------------------------
593    void Frustum::_updateRenderQueue(RenderQueue* queue)
594    {
595        // Add self
596        queue->addRenderable(this);
597    }
598    //-----------------------------------------------------------------------
599    const String& Frustum::getMovableType(void) const
600    {
601        return msMovableType;
602    }
603    //-----------------------------------------------------------------------
604        Real Frustum::getBoundingRadius(void) const
605        {
606        return (mFarDist == 0)? 100000 : mFarDist;
607        }
608    //-----------------------------------------------------------------------
609    const MaterialPtr& Frustum::getMaterial(void) const
610    {
611        return mMaterial;
612    }
613    //-----------------------------------------------------------------------
614    void Frustum::getRenderOperation(RenderOperation& op)
615    {
616        updateView();
617        updateFrustum();
618        op.operationType = RenderOperation::OT_LINE_LIST;
619        op.useIndexes = false;
620        op.vertexData = &mVertexData;
621    }
622    //-----------------------------------------------------------------------
623    void Frustum::getWorldTransforms(Matrix4* xform) const
624    {
625        if (mParentNode)
626            mParentNode->getWorldTransforms(xform);
627    }
628    //-----------------------------------------------------------------------
629    const Quaternion& Frustum::getWorldOrientation(void) const
630    {
631        if (mParentNode)
632            return mParentNode->_getDerivedOrientation();
633        else
634            return Quaternion::IDENTITY;
635    }
636    //-----------------------------------------------------------------------
637    const Vector3& Frustum::getWorldPosition(void) const
638    {
639        if (mParentNode)
640            return mParentNode->_getDerivedPosition();
641        else
642            return Vector3::ZERO;
643    }
644    //-----------------------------------------------------------------------
645    Real Frustum::getSquaredViewDepth(const Camera* cam) const
646    {
647        // Calc from centre
648        if (mParentNode)
649            return (cam->getDerivedPosition()
650                - mParentNode->_getDerivedPosition()).squaredLength();
651        else
652            return 0;
653    }
654    //-----------------------------------------------------------------------
655    const LightList& Frustum::getLights(void) const
656    {
657        // N/A
658        static LightList ll;
659        return ll;
660    }
661    //-----------------------------------------------------------------------
662    const String& Frustum::getName(void) const
663    {
664        // NA
665        return msMovableType;
666    }
667    //-----------------------------------------------------------------------
668    void Frustum::_notifyCurrentCamera(Camera* cam)
669    {
670        // NA
671    }
672
673    // -------------------------------------------------------------------
674    void Frustum::invalidateFrustum() const
675    {
676        mRecalcFrustum = true;
677    }
678    // -------------------------------------------------------------------
679    void Frustum::invalidateView() const
680    {
681        mRecalcView = true;
682    }
683    // -------------------------------------------------------------------
684    const Vector3* Frustum::getWorldSpaceCorners(void) const
685    {
686        updateView();
687
688        return mWorldSpaceCorners;
689    }
690    //-----------------------------------------------------------------------
691    void Frustum::setProjectionType(ProjectionType pt)
692    {
693        mProjType = pt;
694        invalidateFrustum();
695    }
696
697    //-----------------------------------------------------------------------
698    ProjectionType Frustum::getProjectionType(void) const
699    {
700        return mProjType;
701    }
702    //-----------------------------------------------------------------------
703    const Vector3& Frustum::getPositionForViewUpdate(void) const
704    {
705        return mLastParentPosition;
706    }
707    //-----------------------------------------------------------------------
708    const Quaternion& Frustum::getOrientationForViewUpdate(void) const
709    {
710        return mLastParentOrientation;
711    }
712    //-----------------------------------------------------------------------
713    void Frustum::enableReflection(const Plane& p)
714    {
715        mReflect = true;
716        mReflectPlane = p;
717        mLinkedReflectPlane = 0;
718        mReflectMatrix = Math::buildReflectionMatrix(p);
719        invalidateView();
720
721    }
722    //-----------------------------------------------------------------------
723    void Frustum::enableReflection(const MovablePlane* p)
724    {
725        mReflect = true;
726        mLinkedReflectPlane = p;
727        mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
728        mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
729        mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
730        invalidateView();
731    }
732    //-----------------------------------------------------------------------
733    void Frustum::disableReflection(void)
734    {
735        mReflect = false;
736        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
737        invalidateView();
738    }
739    //---------------------------------------------------------------------
740    bool Frustum::projectSphere(const Sphere& sphere,
741        Real* left, Real* top, Real* right, Real* bottom) const
742    {
743        // initialise
744        *left = *bottom = -1.0f;
745        *right = *top = 1.0f;
746
747        // Transform light position into camera space
748        Vector3 eyeSpacePos = getViewMatrix() * sphere.getCenter();
749
750        if (eyeSpacePos.z < 0)
751        {
752            Real r = sphere.getRadius();
753            // early-exit
754            if (eyeSpacePos.squaredLength() <= r * r)
755                return false;
756
757            Vector3 screenSpacePos = getStandardProjectionMatrix() * eyeSpacePos;
758
759
760            // perspective attenuate
761            Vector3 spheresize(r, r, eyeSpacePos.z);
762            spheresize = getStandardProjectionMatrix() * spheresize;
763
764            Real possLeft = screenSpacePos.x - spheresize.x;
765            Real possRight = screenSpacePos.x + spheresize.x;
766            Real possTop = screenSpacePos.y + spheresize.y;
767            Real possBottom = screenSpacePos.y - spheresize.y;
768
769            *left = std::max(static_cast<Real>(-1.0), possLeft);
770            *right = std::min(static_cast<Real>(1.0), possRight);
771            *top = std::min(static_cast<Real>(1.0), possTop);
772            *bottom = std::max(static_cast<Real>(-1.0), possBottom);
773
774        }
775
776        return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f);
777
778    }
779    //---------------------------------------------------------------------
780    void Frustum::enableCustomNearClipPlane(const MovablePlane* plane)
781    {
782        mObliqueDepthProjection = true;
783        mLinkedObliqueProjPlane = plane;
784        mObliqueProjPlane = plane->_getDerivedPlane();
785        invalidateFrustum();
786    }
787    //---------------------------------------------------------------------
788    void Frustum::enableCustomNearClipPlane(const Plane& plane)
789    {
790        mObliqueDepthProjection = true;
791        mLinkedObliqueProjPlane = 0;
792        mObliqueProjPlane = plane;
793        invalidateFrustum();
794    }
795    //---------------------------------------------------------------------
796    void Frustum::disableCustomNearClipPlane(void)
797    {
798        mObliqueDepthProjection = false;
799        mLinkedObliqueProjPlane = 0;
800        invalidateFrustum();
801    }
802    //---------------------------------------------------------------------
803
804#ifdef GTP_VISIBILITY_MODIFIED_OGRE
805    //-----------------------------------------------------------------------
806        //added by matt: 050405
807    bool Frustum::isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy) const
808        {
809                intersects = false;
810
811                // Null boxes always invisible
812        if (bound.isNull()) return false;
813
814        // Make any pending updates to the calculated frustum
815        updateView();
816
817        // Get corners of the box
818        const Vector3* pCorners = bound.getAllCorners();
819
820        // For each plane, see if all points are on the negative side
821        // If so, object is not visible
822        for (int plane = 0; plane < 6; ++plane)
823        {
824            // Skip far plane if infinite view frustum
825            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
826                continue;
827
828                        int corner = 0;
829                        bool visible = false;
830
831                        while((corner < 8) && (!visible || ((plane == FRUSTUM_PLANE_NEAR) && !intersects)))
832                        {
833                                if(mFrustumPlanes[plane].getSide(pCorners[corner++]) == Plane::NEGATIVE_SIDE)
834                                {
835                                        if(plane == FRUSTUM_PLANE_NEAR)
836                                                intersects = true;
837                                }
838                                else
839                                {
840                                        visible = true;
841                                }
842                        }
843           
844                        if(!visible)
845                        {
846                                // ALL corners on negative side therefore out of view
847                                if (culledBy)
848                                        *culledBy = (FrustumPlane)plane;
849                                return false;
850            }
851                }
852
853        return true;
854    }
855#endif // GTP_VISIBILITY_MODIFIED_OGRE
856} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.