IrrlichtEngine
SViewFrustum.h
Go to the documentation of this file.
00001 // Copyright (C) 2002-2011 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