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