source: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreFrustum.h @ 921

Revision 921, 27.0 KB checked in by mattausch, 18 years ago (diff)

added updates for visibility

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
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#ifndef __Frustum_H__
26#define __Frustum_H__
27
28#include "OgrePrerequisites.h"
29#include "OgreMovableObject.h"
30#include "OgreRenderable.h"
31#include "OgreAxisAlignedBox.h"
32#include "OgreVertexIndexData.h"
33#include "OgreMovablePlane.h"
34
35namespace Ogre
36{
37    /** Specifies perspective (realistic) or orthographic (architectural) projection.
38    */
39    enum ProjectionType
40    {
41        PT_ORTHOGRAPHIC,
42        PT_PERSPECTIVE
43    };
44
45    /** Worldspace clipping planes.
46    */
47    enum FrustumPlane
48    {
49        FRUSTUM_PLANE_NEAR   = 0,
50        FRUSTUM_PLANE_FAR    = 1,
51        FRUSTUM_PLANE_LEFT   = 2,
52        FRUSTUM_PLANE_RIGHT  = 3,
53        FRUSTUM_PLANE_TOP    = 4,
54        FRUSTUM_PLANE_BOTTOM = 5
55    };
56
57    /** A frustum represents a pyramid, capped at the near and far end which is
58        used to represent either a visible area or a projection area. Can be used
59        for a number of applications.
60    */
61    class _OgreExport Frustum : public MovableObject, public Renderable
62    {
63    protected:
64        /// Orthographic or perspective?
65        ProjectionType mProjType;
66
67        /// y-direction field-of-view (default 45)
68        Radian mFOVy;
69        /// Far clip distance - default 10000
70        Real mFarDist;
71        /// Near clip distance - default 100
72        Real mNearDist;
73        /// x/y viewport ratio - default 1.3333
74        Real mAspect;
75        /// Off-axis frustum center offset - default (0.0, 0.0)
76        Vector2 mFrustumOffset;
77        /// Focal length of frustum (for stereo rendering, defaults to 1.0)
78        Real mFocalLength;
79
80        /// The 6 main clipping planes
81        mutable Plane mFrustumPlanes[6];
82
83        /// Stored versions of parent orientation / position
84        mutable Quaternion mLastParentOrientation;
85        mutable Vector3 mLastParentPosition;
86
87        /// Pre-calced projection matrix for the specific render system
88        mutable Matrix4 mProjMatrixRS;
89        /// Pre-calced standard projection matrix but with render system depth range
90        mutable Matrix4 mProjMatrixRSDepth;
91        /// Pre-calced standard projection matrix
92        mutable Matrix4 mProjMatrix;
93        /// Pre-calced view matrix
94        mutable Matrix4 mViewMatrix;
95        /// Something's changed in the frustrum shape?
96        mutable bool mRecalcFrustum;
97        /// Something re the view pos has changed
98        mutable bool mRecalcView;
99        /// Something re the frustum planes has changed
100        mutable bool mRecalcFrustumPlanes;
101        /// Something re the world space corners has changed
102        mutable bool mRecalcWorldSpaceCorners;
103        /// Something re the vertex data has changed
104        mutable bool mRecalcVertexData;
105                /// Are we using a custom view matrix?
106                bool mCustomViewMatrix;
107                /// Are we using a custom projection matrix?
108                bool mCustomProjMatrix;
109
110               
111        // Internal functions for calcs
112        virtual void calcProjectionParameters(Real& left, Real& right, Real& bottom, Real& top) const;
113                /// Update frustum if out of date
114        virtual void updateFrustum(void) const;
115                /// Update view if out of date
116        virtual void updateView(void) const;
117                /// Implementation of updateFrustum (called if out of date)
118                virtual void updateFrustumImpl(void) const;
119                /// Implementation of updateView (called if out of date)
120                virtual void updateViewImpl(void) const;
121        virtual void updateFrustumPlanes(void) const;
122                /// Implementation of updateFrustumPlanes (called if out of date)
123                virtual void updateFrustumPlanesImpl(void) const;
124        virtual void updateWorldSpaceCorners(void) const;
125                /// Implementation of updateWorldSpaceCorners (called if out of date)
126                virtual void updateWorldSpaceCornersImpl(void) const;
127        virtual void updateVertexData(void) const;
128        virtual bool isViewOutOfDate(void) const;
129        virtual bool isFrustumOutOfDate(void) const;
130        /// Signal to update frustum information.
131        virtual void invalidateFrustum(void) const;
132        /// Signal to update view information.
133        virtual void invalidateView(void) const;
134
135        /// Shared class-level name for Movable type
136        static String msMovableType;
137
138        mutable AxisAlignedBox mBoundingBox;
139        mutable VertexData mVertexData;
140
141        MaterialPtr mMaterial;
142        mutable Vector3 mWorldSpaceCorners[8];
143
144        /// Is this frustum to act as a reflection of itself?
145        bool mReflect;
146                /// Derived reflection matrix
147        mutable Matrix4 mReflectMatrix;
148        /// Fixed reflection plane
149                mutable Plane mReflectPlane;
150                /// Pointer to a reflection plane (automatically updated)
151                const MovablePlane* mLinkedReflectPlane;
152                /// Record of the last world-space reflection plane info used
153                mutable Plane mLastLinkedReflectionPlane;
154               
155        /// Is this frustum using an oblique depth projection?
156                bool mObliqueDepthProjection;
157                /// Fixed oblique projection plane
158                mutable Plane mObliqueProjPlane;
159                /// Pointer to oblique projection plane (automatically updated)
160                const MovablePlane* mLinkedObliqueProjPlane;
161                /// Record of the last world-space oblique depth projection plane info used
162                mutable Plane mLastLinkedObliqueProjPlane;
163
164               
165                /** Get the derived position of this frustum. */
166        virtual const Vector3& getPositionForViewUpdate(void) const;
167        /** Get the derived orientation of this frustum. */
168        virtual const Quaternion& getOrientationForViewUpdate(void) const;
169
170
171    public:
172
173        Frustum();
174        virtual ~Frustum();
175        /** Sets the Y-dimension Field Of View (FOV) of the frustum.
176            @remarks
177                Field Of View (FOV) is the angle made between the frustum's position, and the edges
178                of the 'screen' onto which the scene is projected. High values (90+ degrees) result in a wide-angle,
179                fish-eye kind of view, low values (30- degrees) in a stretched, telescopic kind of view. Typical values
180                are between 45 and 60 degrees.
181            @par
182                This value represents the VERTICAL field-of-view. The horizontal field of view is calculated from
183                this depending on the dimensions of the viewport (they will only be the same if the viewport is square).
184            @note
185                Setting the FOV overrides the value supplied for frustum::setNearClipPlane.
186         */
187        virtual void setFOVy(const Radian& fovy);
188#ifndef OGRE_FORCE_ANGLE_TYPES
189        inline void setFOVy(Real fovy) {
190            setFOVy ( Angle(fovy) );
191        }
192#endif//OGRE_FORCE_ANGLE_TYPES
193
194        /** Retrieves the frustums Y-dimension Field Of View (FOV).
195        */
196        virtual const Radian& getFOVy(void) const;
197
198        /** Sets the position of the near clipping plane.
199            @remarks
200                The position of the near clipping plane is the distance from the frustums position to the screen
201                on which the world is projected. The near plane distance, combined with the field-of-view and the
202                aspect ratio, determines the size of the viewport through which the world is viewed (in world
203                co-ordinates). Note that this world viewport is different to a screen viewport, which has it's
204                dimensions expressed in pixels. The frustums viewport should have the same aspect ratio as the
205                screen viewport it renders into to avoid distortion.
206            @param
207                near The distance to the near clipping plane from the frustum in world coordinates.
208         */
209        virtual void setNearClipDistance(Real nearDist);
210
211        /** Sets the position of the near clipping plane.
212        */
213        virtual Real getNearClipDistance(void) const;
214
215        /** Sets the distance to the far clipping plane.
216            @remarks
217                The view frustrum is a pyramid created from the frustum position and the edges of the viewport.
218                This method sets the distance for the far end of that pyramid.
219                Different applications need different values: e.g. a flight sim
220                needs a much further far clipping plane than a first-person
221                shooter. An important point here is that the larger the ratio
222                between near and far clipping planes, the lower the accuracy of
223                the Z-buffer used to depth-cue pixels. This is because the
224                Z-range is limited to the size of the Z buffer (16 or 32-bit)
225                and the max values must be spread over the gap between near and
226                far clip planes. As it happens, you can affect the accuracy far
227                more by altering the near distance rather than the far distance,
228                but keep this in mind.
229            @param
230                far The distance to the far clipping plane from the frustum in
231                world coordinates.If you specify 0, this means an infinite view
232                distance which is useful especially when projecting shadows; but
233                be careful not to use a near distance too close.
234        */
235        virtual void setFarClipDistance(Real farDist);
236
237        /** Retrieves the distance from the frustum to the far clipping plane.
238        */
239        virtual Real getFarClipDistance(void) const;
240
241        /** Sets the aspect ratio for the frustum viewport.
242            @remarks
243                The ratio between the x and y dimensions of the rectangular area visible through the frustum
244                is known as aspect ratio: aspect = width / height .
245            @par
246                The default for most fullscreen windows is 1.3333 - this is also assumed by Ogre unless you
247                use this method to state otherwise.
248        */
249        virtual void setAspectRatio(Real ratio);
250
251        /** Retreives the current aspect ratio.
252        */
253        virtual Real getAspectRatio(void) const;
254
255        /** Sets frustum offsets, used in stereo rendering.
256            @remarks
257                You can set both horizontal and vertical plane offsets of "eye"; in
258                stereo rendering frustum is moved in horizontal plane. To be able to
259                render from two "eyes" you'll need two cameras rendering on two
260                RenderTargets.
261            @par
262                The frustum offsets is in world coordinates, and default to (0, 0) - no offsets.
263            @param
264                offset The horizontal and vertical plane offsets.
265        */
266        virtual void setFrustumOffset(const Vector2& offset);
267
268        /** Sets frustum offsets, used in stereo rendering.
269            @remarks
270                You can set both horizontal and vertical plane offsets of "eye"; in
271                stereo rendering frustum is moved in horizontal plane. To be able to
272                render from two "eyes" you'll need two cameras rendering on two
273                RenderTargets.
274            @par
275                The frustum offsets is in world coordinates, and default to (0, 0) - no offsets.
276            @param
277                horizontal The horizontal plane offset.
278            @param
279                vertical The vertical plane offset.
280        */
281        virtual void setFrustumOffset(Real horizontal = 0.0, Real vertical = 0.0);
282
283        /** Retreives the frustum offsets.
284        */
285        virtual const Vector2& getFrustumOffset() const;
286
287        /** Sets frustum focal length (used in stereo rendering).
288            @param
289                focalLength The distance to the focal plane from the frustum in world coordinates.
290        */
291        virtual void setFocalLength(Real focalLength = 1.0);
292
293        /** Returns focal length of frustum.
294        */
295        virtual Real getFocalLength() const;
296
297        /** Gets the projection matrix for this frustum adjusted for the current
298                        rendersystem specifics (may be right or left-handed, depth range
299                        may vary).
300        @remarks
301            This method retrieves the rendering-API dependent version of the projection
302            matrix. If you want a 'typical' projection matrix then use
303            getProjectionMatrix.
304
305        */
306        virtual const Matrix4& getProjectionMatrixRS(void) const;
307        /** Gets the depth-adjusted projection matrix for the current rendersystem,
308                        but one which still conforms to right-hand rules.
309        @remarks
310            This differs from the rendering-API dependent getProjectionMatrix
311            in that it always returns a right-handed projection matrix result
312            no matter what rendering API is being used - this is required for
313            vertex and fragment programs for example. However, the resulting depth
314            range may still vary between render systems since D3D uses [0,1] and
315            GL uses [-1,1], and the range must be kept the same between programmable
316            and fixed-function pipelines.
317        */
318        virtual const Matrix4& getProjectionMatrixWithRSDepth(void) const;
319        /** Gets the normal projection matrix for this frustum, ie the
320        projection matrix which conforms to standard right-handed rules and
321        uses depth range [-1,+1].
322        @remarks
323            This differs from the rendering-API dependent getRenderSystemProjectionMatrix
324            in that it always returns a right-handed projection matrix with depth
325            range [-1,+1], result no matter what rendering API is being used - this
326            is required for some uniform algebra for example.
327        */
328        virtual const Matrix4& getProjectionMatrix(void) const;
329
330        /** Gets the view matrix for this frustum. Mainly for use by OGRE internally.
331        */
332        virtual const Matrix4& getViewMatrix(void) const;
333
334                /** Set whether to use a custom view matrix on this frustum.
335                @remarks
336                        This is an advanced method which allows you to manually set
337                        the view matrix on this frustum, rather than having it calculate
338                        itself based on it's position and orientation.
339                @note
340                        After enabling a custom view matrix, the frustum will no longer
341                        update on its own based on position / orientation changes. You
342                        are completely responsible for keeping the view matrix up to date.
343                        The custom matrix will be returned from getViewMatrix.
344                @param enable If true, the custom view matrix passed as the second
345                        parameter will be used in preference to an auto calculated one. If
346                        false, the frustum will revert to auto calculating the view matrix.
347                @param viewMatrix The custom view matrix to use
348                @see Frustum::setCustomProjectionMatrix
349                */
350                virtual void setCustomViewMatrix(bool enable,
351                        const Matrix4& viewMatrix = Matrix4::IDENTITY);
352                /// Returns whether a custom view matrix is in use
353                virtual bool isCustomViewMatrixEnabled(void) const
354                { return mCustomViewMatrix; }
355               
356                /** Set whether to use a custom projection matrix on this frustum.
357                @remarks
358                        This is an advanced method which allows you to manually set
359                        the projection matrix on this frustum, rather than having it
360                        calculate itself based on it's position and orientation.
361                @note
362                        After enabling a custom projection matrix, the frustum will no
363                        longer update on its own based on field of view and near / far
364                        distance changes. You are completely responsible for keeping the
365                        projection matrix up to date if those values change. The custom
366                        matrix will be returned from getProjectionMatrix and derivative
367                        functions.
368                @param enable If true, the custom projection matrix passed as the
369                        second parameter will be used in preference to an auto calculated
370                        one. If false, the frustum will revert to auto calculating the
371                        projection matrix.
372                @param projectionMatrix The custom view matrix to use
373                @see Frustum::setCustomViewMatrix
374                */
375                virtual void setCustomProjectionMatrix(bool enable,
376                        const Matrix4& projectionMatrix = Matrix4::IDENTITY);
377                /// Returns whether a custom projection matrix is in use
378                virtual bool isCustomProjectionMatrixEnabled(void) const
379                { return mCustomProjMatrix; }
380
381                /** Retrieves the clipping planes of the frustum.
382        @remarks
383            The clipping planes are ordered as declared in enumerate constants FrustumPlane.
384        */
385        virtual const Plane* getFrustumPlanes(void) const;
386
387        /** Retrieves a specified plane of the frustum.
388            @remarks
389                Gets a reference to one of the planes which make up the frustum frustum, e.g. for clipping purposes.
390        */
391        virtual const Plane& getFrustumPlane( unsigned short plane ) const;
392
393        /** Tests whether the given container is visible in the Frustum.
394            @param
395                bound Bounding box to be checked
396            @param
397                culledBy Optional pointer to an int which will be filled by the plane number which culled
398                the box if the result was false;
399            @returns
400                If the box was visible, true is returned.
401            @par
402                Otherwise, false is returned.
403        */
404        virtual bool isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy = 0) const;
405
406        /** Tests whether the given container is visible in the Frustum.
407            @param
408                bound Bounding sphere to be checked
409            @param
410                culledBy Optional pointer to an int which will be filled by the plane number which culled
411                the box if the result was false;
412            @returns
413                If the sphere was visible, true is returned.
414            @par
415                Otherwise, false is returned.
416        */
417        virtual bool isVisible(const Sphere& bound, FrustumPlane* culledBy = 0) const;
418
419        /** Tests whether the given vertex is visible in the Frustum.
420            @param
421                vert Vertex to be checked
422            @param
423                culledBy Optional pointer to an int which will be filled by the plane number which culled
424                the box if the result was false;
425            @returns
426                If the box was visible, true is returned.
427            @par
428                Otherwise, false is returned.
429        */
430        virtual bool isVisible(const Vector3& vert, FrustumPlane* culledBy = 0) const;
431
432
433        /** Overridden from MovableObject */
434        const AxisAlignedBox& getBoundingBox(void) const;
435
436        /** Overridden from MovableObject */
437                Real getBoundingRadius(void) const;
438
439                /** Overridden from MovableObject */
440        void _updateRenderQueue(RenderQueue* queue);
441
442        /** Overridden from MovableObject */
443        const String& getMovableType(void) const;
444
445        /** Overridden from MovableObject */
446        void _notifyCurrentCamera(Camera* cam);
447
448        /** Overridden from Renderable */
449        const MaterialPtr& getMaterial(void) const;
450
451        /** Overridden from Renderable */
452        void getRenderOperation(RenderOperation& op);
453
454        /** Overridden from Renderable */
455        void getWorldTransforms(Matrix4* xform) const;
456
457        /** Overridden from Renderable */
458        const Quaternion& getWorldOrientation(void) const;
459
460        /** Overridden from Renderable */
461        const Vector3& getWorldPosition(void) const;
462
463        /** Overridden from Renderable */
464        Real getSquaredViewDepth(const Camera* cam) const;
465
466        /** Overridden from Renderable */
467        const LightList& getLights(void) const;
468
469        /** Gets the world space corners of the frustum.
470        @remarks
471            The corners are ordered as follows: top-right near,
472            top-left near, bottom-left near, bottom-right near,
473            top-right far, top-left far, bottom-left far, bottom-right far.
474        */
475        virtual const Vector3* getWorldSpaceCorners(void) const;
476
477        /** Sets the type of projection to use (orthographic or perspective). Default is perspective.
478        */
479        virtual void setProjectionType(ProjectionType pt);
480
481        /** Retrieves info on the type of projection used (orthographic or perspective).
482        */
483        virtual ProjectionType getProjectionType(void) const;
484
485        /** Modifies this frustum so it always renders from the reflection of itself through the
486        plane specified.
487        @remarks
488        This is obviously useful for performing planar reflections.
489        */
490        virtual void enableReflection(const Plane& p);
491        /** Modifies this frustum so it always renders from the reflection of itself through the
492        plane specified. Note that this version of the method links to a plane
493                so that changes to it are picked up automatically. It is important that
494                this plane continues to exist whilst this object does; do not destroy
495                the plane before the frustum.
496        @remarks
497        This is obviously useful for performing planar reflections.
498        */
499        virtual void enableReflection(const MovablePlane* p);
500
501        /** Disables reflection modification previously turned on with enableReflection */
502        virtual void disableReflection(void);
503
504        /// Returns whether this frustum is being reflected
505        virtual bool isReflected(void) const { return mReflect; }
506        /// Returns the reflection matrix of the frustum if appropriate
507        virtual const Matrix4& getReflectionMatrix(void) const { return mReflectMatrix; }
508        /// Returns the reflection plane of the frustum if appropriate
509        virtual const Plane& getReflectionPlane(void) const { return mReflectPlane; }
510
511        /** Project a sphere onto the near plane and get the bounding rectangle.
512        @param sphere The world-space sphere to project
513        @param radius Radius of the sphere
514        @param left, top, right, bottom Pointers to destination values, these
515            will be completed with the normalised device coordinates (in the
516            range {-1,1})
517        @returns true if the sphere was projected to a subset of the near plane,
518            false if the entire near plane was contained
519        */
520        virtual bool projectSphere(const Sphere& sphere,
521            Real* left, Real* top, Real* right, Real* bottom) const;
522
523
524                /** Links the frustum to a custom near clip plane, which can be used
525                        to clip geometry in a custom manner without using user clip planes.
526                @remarks
527                        There are several applications for clipping a scene arbitrarily by
528                        a single plane; the most common is when rendering a reflection to
529                        a texture, and you only want to render geometry that is above the
530                        water plane (to do otherwise results in artefacts). Whilst it is
531                        possible to use user clip planes, they are not supported on all
532                        cards, and sometimes are not hardware accelerated when they are
533                        available. Instead, where a single clip plane is involved, this
534                        technique uses a 'fudging' of the near clip plane, which is
535                        available and fast on all hardware, to perform as the arbitrary
536                        clip plane. This does change the shape of the frustum, leading
537                        to some depth buffer loss of precision, but for many of the uses of
538                        this technique that is not an issue.
539                @par
540                        This version of the method links to a plane, rather than requiring
541                        a by-value plane definition, and therefore you can
542                        make changes to the plane (e.g. by moving / rotating the node it is
543                        attached to) and they will automatically affect this object.
544                @note This technique only works for perspective projection.
545                @param plane The plane to link to to perform the clipping. This plane
546                        must continue to exist while the camera is linked to it; do not
547                        destroy it before the frustum.
548                */
549                virtual void enableCustomNearClipPlane(const MovablePlane* plane);
550                /** Links the frustum to a custom near clip plane, which can be used
551                        to clip geometry in a custom manner without using user clip planes.
552                @remarks
553                        There are several applications for clipping a scene arbitrarily by
554                        a single plane; the most common is when rendering a reflection to 
555                        a texture, and you only want to render geometry that is above the
556                        water plane (to do otherwise results in artefacts). Whilst it is
557                        possible to use user clip planes, they are not supported on all
558                        cards, and sometimes are not hardware accelerated when they are
559                        available. Instead, where a single clip plane is involved, this
560                        technique uses a 'fudging' of the near clip plane, which is
561                        available and fast on all hardware, to perform as the arbitrary
562                        clip plane. This does change the shape of the frustum, leading
563                        to some depth buffer loss of precision, but for many of the uses of
564                        this technique that is not an issue.
565                @note This technique only works for perspective projection.
566                @param plane The plane to link to to perform the clipping. This plane
567                        must continue to exist while the camera is linked to it; do not
568                        destroy it before the frustum.
569                */
570                virtual void enableCustomNearClipPlane(const Plane& plane);
571                /** Disables any custom near clip plane. */
572                virtual void disableCustomNearClipPlane(void);
573                /** Is a custom near clip plane in use? */
574                virtual bool isCustomNearClipPlaneEnabled(void) const
575                { return mObliqueDepthProjection; }
576               
577
578        /// Small constant used to reduce far plane projection to avoid inaccuracies
579        static const Real INFINITE_FAR_PLANE_ADJUST;
580
581#ifdef GTP_VISIBILITY_MODIFIED_OGRE
582                //added by matt: 050405
583                /** Tests whether the given container is visible in the Frustum.
584            @param
585                bound Bounding box to be checked
586            @param
587                culledBy Optional pointer to an int which will be filled by the plane number which culled
588                the box if the result was false;
589                        @param
590                                intersects returns the information if the box intersects the near plane.
591            @returns
592                If the box was visible, true is returned.
593            @par
594                Otherwise, false is returned.
595        */
596        virtual bool isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy = 0) const;
597#endif // GTP_VISIBILITY_MODIFIED_OGRE
598    };
599
600
601}
602
603#endif
Note: See TracBrowser for help on using the repository browser.