00001
00002
00003
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 const core::aabbox3d<f32> &getBoundingBox() const;
00077
00079 inline void recalculateBoundingBox();
00080
00082 core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state);
00083
00085 const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const;
00086
00088
00089 bool clipLine(core::line3d<f32>& line) const;
00090
00092 core::vector3df cameraPosition;
00093
00095 core::plane3d<f32> planes[VF_PLANE_COUNT];
00096
00098 core::aabbox3d<f32> boundingBox;
00099
00100 private:
00102 enum E_TRANSFORMATION_STATE_FRUSTUM
00103 {
00104 ETS_VIEW = 0,
00105 ETS_PROJECTION = 1,
00106 ETS_COUNT_FRUSTUM
00107 };
00108
00110 core::matrix4 Matrices[ETS_COUNT_FRUSTUM];
00111 };
00112
00113
00117 inline SViewFrustum::SViewFrustum(const SViewFrustum& other)
00118 {
00119 cameraPosition=other.cameraPosition;
00120 boundingBox=other.boundingBox;
00121
00122 u32 i;
00123 for (i=0; i<VF_PLANE_COUNT; ++i)
00124 planes[i]=other.planes[i];
00125
00126 for (i=0; i<ETS_COUNT_FRUSTUM; ++i)
00127 Matrices[i]=other.Matrices[i];
00128 }
00129
00130 inline SViewFrustum::SViewFrustum(const core::matrix4& mat)
00131 {
00132 setFrom ( mat );
00133 }
00134
00135
00136 inline void SViewFrustum::transform(const core::matrix4& mat)
00137 {
00138 for (u32 i=0; i<VF_PLANE_COUNT; ++i)
00139 mat.transformPlane(planes[i]);
00140
00141 mat.transformVect(cameraPosition);
00142 recalculateBoundingBox();
00143 }
00144
00145
00146 inline core::vector3df SViewFrustum::getFarLeftUp() const
00147 {
00148 core::vector3df p;
00149 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
00150 planes[scene::SViewFrustum::VF_TOP_PLANE],
00151 planes[scene::SViewFrustum::VF_LEFT_PLANE], p);
00152
00153 return p;
00154 }
00155
00156 inline core::vector3df SViewFrustum::getFarLeftDown() const
00157 {
00158 core::vector3df p;
00159 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
00160 planes[scene::SViewFrustum::VF_BOTTOM_PLANE],
00161 planes[scene::SViewFrustum::VF_LEFT_PLANE], p);
00162
00163 return p;
00164 }
00165
00166 inline core::vector3df SViewFrustum::getFarRightUp() const
00167 {
00168 core::vector3df p;
00169 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
00170 planes[scene::SViewFrustum::VF_TOP_PLANE],
00171 planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);
00172
00173 return p;
00174 }
00175
00176 inline core::vector3df SViewFrustum::getFarRightDown() const
00177 {
00178 core::vector3df p;
00179 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(
00180 planes[scene::SViewFrustum::VF_BOTTOM_PLANE],
00181 planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);
00182
00183 return p;
00184 }
00185
00186 inline const core::aabbox3d<f32> &SViewFrustum::getBoundingBox() const
00187 {
00188 return boundingBox;
00189 }
00190
00191 inline void SViewFrustum::recalculateBoundingBox()
00192 {
00193 boundingBox.reset ( cameraPosition );
00194
00195 boundingBox.addInternalPoint(getFarLeftUp());
00196 boundingBox.addInternalPoint(getFarRightUp());
00197 boundingBox.addInternalPoint(getFarLeftDown());
00198 boundingBox.addInternalPoint(getFarRightDown());
00199 }
00200
00203 inline void SViewFrustum::setFrom(const core::matrix4& mat)
00204 {
00205
00206 planes[VF_LEFT_PLANE].Normal.X = mat[3 ] + mat[0];
00207 planes[VF_LEFT_PLANE].Normal.Y = mat[7 ] + mat[4];
00208 planes[VF_LEFT_PLANE].Normal.Z = mat[11] + mat[8];
00209 planes[VF_LEFT_PLANE].D = mat[15] + mat[12];
00210
00211
00212 planes[VF_RIGHT_PLANE].Normal.X = mat[3 ] - mat[0];
00213 planes[VF_RIGHT_PLANE].Normal.Y = mat[7 ] - mat[4];
00214 planes[VF_RIGHT_PLANE].Normal.Z = mat[11] - mat[8];
00215 planes[VF_RIGHT_PLANE].D = mat[15] - mat[12];
00216
00217
00218 planes[VF_TOP_PLANE].Normal.X = mat[3 ] - mat[1];
00219 planes[VF_TOP_PLANE].Normal.Y = mat[7 ] - mat[5];
00220 planes[VF_TOP_PLANE].Normal.Z = mat[11] - mat[9];
00221 planes[VF_TOP_PLANE].D = mat[15] - mat[13];
00222
00223
00224 planes[VF_BOTTOM_PLANE].Normal.X = mat[3 ] + mat[1];
00225 planes[VF_BOTTOM_PLANE].Normal.Y = mat[7 ] + mat[5];
00226 planes[VF_BOTTOM_PLANE].Normal.Z = mat[11] + mat[9];
00227 planes[VF_BOTTOM_PLANE].D = mat[15] + mat[13];
00228
00229
00230 planes[VF_FAR_PLANE].Normal.X = mat[3 ] - mat[2];
00231 planes[VF_FAR_PLANE].Normal.Y = mat[7 ] - mat[6];
00232 planes[VF_FAR_PLANE].Normal.Z = mat[11] - mat[10];
00233 planes[VF_FAR_PLANE].D = mat[15] - mat[14];
00234
00235
00236 planes[VF_NEAR_PLANE].Normal.X = mat[2];
00237 planes[VF_NEAR_PLANE].Normal.Y = mat[6];
00238 planes[VF_NEAR_PLANE].Normal.Z = mat[10];
00239 planes[VF_NEAR_PLANE].D = mat[14];
00240
00241
00242 u32 i;
00243 for ( i=0; i != VF_PLANE_COUNT; ++i)
00244 {
00245 const f32 len = -core::reciprocal_squareroot(
00246 planes[i].Normal.getLengthSQ());
00247 planes[i].Normal *= len;
00248 planes[i].D *= len;
00249 }
00250
00251
00252 recalculateBoundingBox();
00253 }
00254
00258 inline core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state )
00259 {
00260 u32 index = 0;
00261 switch ( state )
00262 {
00263 case video::ETS_PROJECTION:
00264 index = SViewFrustum::ETS_PROJECTION; break;
00265 case video::ETS_VIEW:
00266 index = SViewFrustum::ETS_VIEW; break;
00267 default:
00268 break;
00269 }
00270 return Matrices [ index ];
00271 }
00272
00276 inline const core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state ) const
00277 {
00278 u32 index = 0;
00279 switch ( state )
00280 {
00281 case video::ETS_PROJECTION:
00282 index = SViewFrustum::ETS_PROJECTION; break;
00283 case video::ETS_VIEW:
00284 index = SViewFrustum::ETS_VIEW; break;
00285 default:
00286 break;
00287 }
00288 return Matrices [ index ];
00289 }
00290
00292 inline bool SViewFrustum::clipLine(core::line3d<f32>& line) const
00293 {
00294 bool wasClipped = false;
00295 for (u32 i=0; i < VF_PLANE_COUNT; ++i)
00296 {
00297 if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT)
00298 {
00299 line.start = line.start.getInterpolated(line.end,
00300 planes[i].getKnownIntersectionWithLine(line.start, line.end));
00301 wasClipped = true;
00302 }
00303 if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT)
00304 {
00305 line.end = line.start.getInterpolated(line.end,
00306 planes[i].getKnownIntersectionWithLine(line.start, line.end));
00307 wasClipped = true;
00308 }
00309 }
00310 return wasClipped;
00311 }
00312
00313
00314 }
00315 }
00316
00317 #endif
00318