| Irrlicht 3D Engine |

SViewFrustum.h
Go to the documentation of this file.

    00001 // Copyright (C) 2002-2012 Nikolaus Gebhardt
    00002 // This file is part of the "Irrlicht Engine".
    00003 // For conditions of distribution and use, see copyright notice in irrlicht.h
    00004
    00005 #ifndef __S_VIEW_FRUSTUM_H_INCLUDED__
    00006 #define __S_VIEW_FRUSTUM_H_INCLUDED__
    00007
    00008 #include "plane3d.h"
    00009 #include "vector3d.h"
    00010 #include "line3d.h"
    00011 #include "aabbox3d.h"
    00012 #include "matrix4.h"
    00013 #include "IVideoDriver.h"
    00014
    00015 namespace irr
    00016 {
    00017 namespace scene
    00018 {
    00019
    00021
    00025     struct SViewFrustum
    00026     {
    00027         enum VFPLANES
    00028         {
    00030             VF_FAR_PLANE = 0,
    00032             VF_NEAR_PLANE,
    00034             VF_LEFT_PLANE,
    00036             VF_RIGHT_PLANE,
    00038             VF_BOTTOM_PLANE,
    00040             VF_TOP_PLANE,
    00041
    00043             VF_PLANE_COUNT
    00044         };
    00045
    00046
    00048         SViewFrustum() {}
    00049
    00051         SViewFrustum(const SViewFrustum& other);
    00052
    00054         SViewFrustum(const core::matrix4& mat);
    00055
    00057         inline void setFrom(const core::matrix4& mat);
    00058
    00060
    00061         void transform(const core::matrix4& mat);
    00062
    00064         core::vector3df getFarLeftUp() const;
    00065
    00067         core::vector3df getFarLeftDown() const;
    00068
    00070         core::vector3df getFarRightUp() const;
    00071
    00073         core::vector3df getFarRightDown() const;
    00074
    00076         core::vector3df getNearLeftUp() const;
    00077
    00079         core::vector3df getNearLeftDown() const;
    00080
    00082         core::vector3df getNearRightUp() const;
    00083
    00085         core::vector3df getNearRightDown() const;
    00086
    00088         const core::aabbox3d<f32> &getBoundingBox() const;
    00089
    00091         inline void recalculateBoundingBox();
    00092
    00094         core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state);
    00095
    00097         const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const;
    00098
    00100
    00101         bool clipLine(core::line3d<f32>& line) const;
    00102
    00104         core::vector3df cameraPosition;
    00105
    00107         core::plane3d<f32> planes[VF_PLANE_COUNT];
    00108
    00110         core::aabbox3d<f32> boundingBox;
    00111
    00112     private:
    00114         enum E_TRANSFORMATION_STATE_FRUSTUM
    00115         {
    00116             ETS_VIEW = 0,
    00117             ETS_PROJECTION = 1,
    00118             ETS_COUNT_FRUSTUM
    00119         };
    00120
    00122         core::matrix4 Matrices[ETS_COUNT_FRUSTUM];
    00123     };
    00124
    00125
    00129     inline SViewFrustum::SViewFrustum(const SViewFrustum& other)
    00130     {
    00131         cameraPosition=other.cameraPosition;
    00132         boundingBox=other.boundingBox;
    00133
    00134         u32 i;
    00135         for (i=0; i<VF_PLANE_COUNT; ++i)
    00136             planes[i]=other.planes[i];
    00137
    00138         for (i=0; i<ETS_COUNT_FRUSTUM; ++i)
    00139             Matrices[i]=other.Matrices[i];
    00140     }
    00141
    00142     inline SViewFrustum::SViewFrustum(const core::matrix4& mat)
    00143     {
    00144         setFrom ( mat );
    00145     }
    00146
    00147
    00148     inline void SViewFrustum::transform(const core::matrix4& mat)
    00149     {
    00150         for (u32 i=0; i<VF_PLANE_COUNT; ++i)
    00151             mat.transformPlane(planes[i]);
    00152
    00153         mat.transformVect(cameraPosition);
    00154         recalculateBoundingBox();
    00155     }
    00156
    00157
    00158     inline core::vector3df SViewFrustum::getFarLeftUp() const
    00159     {
    00160         core::vector3df p;
    00161         planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
    00162             planes[scene::SViewFrustum::VF_TOP_PLANE],
    00163             planes[scene::SViewFrustum::VF_LEFT_PLANE], p);
    00164
    00165         return p;
    00166     }
    00167
    00168     inline core::vector3df SViewFrustum::getFarLeftDown() const
    00169     {
    00170         core::vector3df p;
    00171         planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
    00172             planes[scene::SViewFrustum::VF_BOTTOM_PLANE],
    00173             planes[scene::SViewFrustum::VF_LEFT_PLANE], p);
    00174
    00175         return p;
    00176     }
    00177
    00178     inline core::vector3df SViewFrustum::getFarRightUp() const
    00179     {
    00180         core::vector3df p;
    00181         planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
    00182             planes[scene::SViewFrustum::VF_TOP_PLANE],
    00183             planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);
    00184
    00185         return p;
    00186     }
    00187
    00188     inline core::vector3df SViewFrustum::getFarRightDown() const
    00189     {
    00190         core::vector3df p;
    00191         planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
    00192             planes[scene::SViewFrustum::VF_BOTTOM_PLANE],
    00193             planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);
    00194
    00195         return p;
    00196     }
    00197
    00198     inline core::vector3df SViewFrustum::getNearLeftUp() const
    00199     {
    00200         core::vector3df p;
    00201         planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(
    00202             planes[scene::SViewFrustum::VF_TOP_PLANE],
    00203             planes[scene::SViewFrustum::VF_LEFT_PLANE], p);
    00204
    00205         return p;
    00206     }
    00207
    00208     inline core::vector3df SViewFrustum::getNearLeftDown() const
    00209     {
    00210         core::vector3df p;
    00211         planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(
    00212             planes[scene::SViewFrustum::VF_BOTTOM_PLANE],
    00213             planes[scene::SViewFrustum::VF_LEFT_PLANE], p);
    00214
    00215         return p;
    00216     }
    00217
    00218     inline core::vector3df SViewFrustum::getNearRightUp() const
    00219     {
    00220         core::vector3df p;
    00221         planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(
    00222             planes[scene::SViewFrustum::VF_TOP_PLANE],
    00223             planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);
    00224
    00225         return p;
    00226     }
    00227
    00228     inline core::vector3df SViewFrustum::getNearRightDown() const
    00229     {
    00230         core::vector3df p;
    00231         planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(
    00232             planes[scene::SViewFrustum::VF_BOTTOM_PLANE],
    00233             planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);
    00234
    00235         return p;
    00236     }
    00237
    00238     inline const core::aabbox3d<f32> &SViewFrustum::getBoundingBox() const
    00239     {
    00240         return boundingBox;
    00241     }
    00242
    00243     inline void SViewFrustum::recalculateBoundingBox()
    00244     {
    00245         boundingBox.reset ( cameraPosition );
    00246
    00247         boundingBox.addInternalPoint(getFarLeftUp());
    00248         boundingBox.addInternalPoint(getFarRightUp());
    00249         boundingBox.addInternalPoint(getFarLeftDown());
    00250         boundingBox.addInternalPoint(getFarRightDown());
    00251     }
    00252
    00255     inline void SViewFrustum::setFrom(const core::matrix4& mat)
    00256     {
    00257         // left clipping plane
    00258         planes[VF_LEFT_PLANE].Normal.X = mat[3 ] + mat[0];
    00259         planes[VF_LEFT_PLANE].Normal.Y = mat[7 ] + mat[4];
    00260         planes[VF_LEFT_PLANE].Normal.Z = mat[11] + mat[8];
    00261         planes[VF_LEFT_PLANE].D =        mat[15] + mat[12];
    00262
    00263         // right clipping plane
    00264         planes[VF_RIGHT_PLANE].Normal.X = mat[3 ] - mat[0];
    00265         planes[VF_RIGHT_PLANE].Normal.Y = mat[7 ] - mat[4];
    00266         planes[VF_RIGHT_PLANE].Normal.Z = mat[11] - mat[8];
    00267         planes[VF_RIGHT_PLANE].D =        mat[15] - mat[12];
    00268
    00269         // top clipping plane
    00270         planes[VF_TOP_PLANE].Normal.X = mat[3 ] - mat[1];
    00271         planes[VF_TOP_PLANE].Normal.Y = mat[7 ] - mat[5];
    00272         planes[VF_TOP_PLANE].Normal.Z = mat[11] - mat[9];
    00273         planes[VF_TOP_PLANE].D =        mat[15] - mat[13];
    00274
    00275         // bottom clipping plane
    00276         planes[VF_BOTTOM_PLANE].Normal.X = mat[3 ] + mat[1];
    00277         planes[VF_BOTTOM_PLANE].Normal.Y = mat[7 ] + mat[5];
    00278         planes[VF_BOTTOM_PLANE].Normal.Z = mat[11] + mat[9];
    00279         planes[VF_BOTTOM_PLANE].D =        mat[15] + mat[13];
    00280
    00281         // far clipping plane
    00282         planes[VF_FAR_PLANE].Normal.X = mat[3 ] - mat[2];
    00283         planes[VF_FAR_PLANE].Normal.Y = mat[7 ] - mat[6];
    00284         planes[VF_FAR_PLANE].Normal.Z = mat[11] - mat[10];
    00285         planes[VF_FAR_PLANE].D =        mat[15] - mat[14];
    00286
    00287         // near clipping plane
    00288         planes[VF_NEAR_PLANE].Normal.X = mat[2];
    00289         planes[VF_NEAR_PLANE].Normal.Y = mat[6];
    00290         planes[VF_NEAR_PLANE].Normal.Z = mat[10];
    00291         planes[VF_NEAR_PLANE].D =        mat[14];
    00292
    00293         // normalize normals
    00294         u32 i;
    00295         for ( i=0; i != VF_PLANE_COUNT; ++i)
    00296         {
    00297             const f32 len = -core::reciprocal_squareroot(
    00298                     planes[i].Normal.getLengthSQ());
    00299             planes[i].Normal *= len;
    00300             planes[i].D *= len;
    00301         }
    00302
    00303         // make bounding box
    00304         recalculateBoundingBox();
    00305     }
    00306
    00310     inline core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state )
    00311     {
    00312         u32 index = 0;
    00313         switch ( state )
    00314         {
    00315             case video::ETS_PROJECTION:
    00316                 index = SViewFrustum::ETS_PROJECTION; break;
    00317             case video::ETS_VIEW:
    00318                 index = SViewFrustum::ETS_VIEW; break;
    00319             default:
    00320                 break;
    00321         }
    00322         return Matrices [ index ];
    00323     }
    00324
    00328     inline const core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state ) const
    00329     {
    00330         u32 index = 0;
    00331         switch ( state )
    00332         {
    00333             case video::ETS_PROJECTION:
    00334                 index = SViewFrustum::ETS_PROJECTION; break;
    00335             case video::ETS_VIEW:
    00336                 index = SViewFrustum::ETS_VIEW; break;
    00337             default:
    00338                 break;
    00339         }
    00340         return Matrices [ index ];
    00341     }
    00342
    00344     inline bool SViewFrustum::clipLine(core::line3d<f32>& line) const
    00345     {
    00346         bool wasClipped = false;
    00347         for (u32 i=0; i < VF_PLANE_COUNT; ++i)
    00348         {
    00349             if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT)
    00350             {
    00351                 line.start = line.start.getInterpolated(line.end,
    00352                         planes[i].getKnownIntersectionWithLine(line.start, line.end));
    00353                 wasClipped = true;
    00354             }
    00355             if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT)
    00356             {
    00357                 line.end = line.start.getInterpolated(line.end,
    00358                         planes[i].getKnownIntersectionWithLine(line.start, line.end));
    00359                 wasClipped = true;
    00360             }
    00361         }
    00362         return wasClipped;
    00363     }
    00364
    00365
    00366 } // end namespace scene
    00367 } // end namespace irr
    00368
    00369 #endif
    00370