|
IrrlichtEngine
|
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