]> git.lizzy.rs Git - irrlicht.git/blob - include/SViewFrustum.h
Drop ETS_TEXTURE_1
[irrlicht.git] / include / SViewFrustum.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __S_VIEW_FRUSTUM_H_INCLUDED__\r
6 #define __S_VIEW_FRUSTUM_H_INCLUDED__\r
7 \r
8 #include "plane3d.h"\r
9 #include "vector3d.h"\r
10 #include "line3d.h"\r
11 #include "aabbox3d.h"\r
12 #include "matrix4.h"\r
13 #include "IVideoDriver.h"\r
14 \r
15 namespace irr\r
16 {\r
17 namespace scene\r
18 {\r
19 \r
20         //! Defines the view frustum. That's the space visible by the camera.\r
21         /** The view frustum is enclosed by 6 planes. These six planes share\r
22         eight points. A bounding box around these eight points is also stored in\r
23         this structure.\r
24         */\r
25         struct SViewFrustum\r
26         {\r
27                 enum VFPLANES\r
28                 {\r
29                         //! Far plane of the frustum. That is the plane furthest away from the eye.\r
30                         VF_FAR_PLANE = 0,\r
31                         //! Near plane of the frustum. That is the plane nearest to the eye.\r
32                         VF_NEAR_PLANE,\r
33                         //! Left plane of the frustum.\r
34                         VF_LEFT_PLANE,\r
35                         //! Right plane of the frustum.\r
36                         VF_RIGHT_PLANE,\r
37                         //! Bottom plane of the frustum.\r
38                         VF_BOTTOM_PLANE,\r
39                         //! Top plane of the frustum.\r
40                         VF_TOP_PLANE,\r
41 \r
42                         //! Amount of planes enclosing the view frustum. Should be 6.\r
43                         VF_PLANE_COUNT\r
44                 };\r
45 \r
46 \r
47                 //! Default Constructor\r
48                 SViewFrustum() : BoundingRadius(0.f), FarNearDistance(0.f) {}\r
49 \r
50                 //! Copy Constructor\r
51                 SViewFrustum(const SViewFrustum& other);\r
52 \r
53                 //! This constructor creates a view frustum based on a projection and/or view matrix.\r
54                 //\param zClipFromZero: Clipping of z can be projected from 0 to w when true (D3D style) and from -w to w when false (OGL style).\r
55                 SViewFrustum(const core::matrix4& mat, bool zClipFromZero);\r
56 \r
57                 //! This constructor creates a view frustum based on a projection and/or view matrix.\r
58                 //\param zClipFromZero: Clipping of z can be projected from 0 to w when true (D3D style) and from -w to w when false (OGL style).\r
59                 inline void setFrom(const core::matrix4& mat, bool zClipFromZero);\r
60 \r
61                 //! transforms the frustum by the matrix\r
62                 /** \param mat: Matrix by which the view frustum is transformed.*/\r
63                 void transform(const core::matrix4& mat);\r
64 \r
65                 //! returns the point which is on the far left upper corner inside the the view frustum.\r
66                 core::vector3df getFarLeftUp() const;\r
67 \r
68                 //! returns the point which is on the far left bottom corner inside the the view frustum.\r
69                 core::vector3df getFarLeftDown() const;\r
70 \r
71                 //! returns the point which is on the far right top corner inside the the view frustum.\r
72                 core::vector3df getFarRightUp() const;\r
73 \r
74                 //! returns the point which is on the far right bottom corner inside the the view frustum.\r
75                 core::vector3df getFarRightDown() const;\r
76 \r
77                 //! returns the point which is on the near left upper corner inside the the view frustum.\r
78                 core::vector3df getNearLeftUp() const;\r
79 \r
80                 //! returns the point which is on the near left bottom corner inside the the view frustum.\r
81                 core::vector3df getNearLeftDown() const;\r
82 \r
83                 //! returns the point which is on the near right top corner inside the the view frustum.\r
84                 core::vector3df getNearRightUp() const;\r
85 \r
86                 //! returns the point which is on the near right bottom corner inside the the view frustum.\r
87                 core::vector3df getNearRightDown() const;\r
88 \r
89                 //! returns a bounding box enclosing the whole view frustum\r
90                 const core::aabbox3d<f32> &getBoundingBox() const;\r
91 \r
92                 //! recalculates the bounding box and sphere based on the planes\r
93                 inline void recalculateBoundingBox();\r
94 \r
95                 //! get the bounding sphere's radius (of an optimized sphere, not the AABB's)\r
96                 float getBoundingRadius() const;\r
97 \r
98                 //! get the bounding sphere's radius (of an optimized sphere, not the AABB's)\r
99                 core::vector3df getBoundingCenter() const;\r
100 \r
101                 //! the cam should tell the frustum the distance between far and near\r
102                 void setFarNearDistance(float distance);\r
103 \r
104                 //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE\r
105                 core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state);\r
106 \r
107                 //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE\r
108                 const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const;\r
109 \r
110                 //! clips a line to the view frustum.\r
111                 /** \return True if the line was clipped, false if not */\r
112                 bool clipLine(core::line3d<f32>& line) const;\r
113 \r
114                 //! the position of the camera\r
115                 core::vector3df cameraPosition;\r
116 \r
117                 //! all planes enclosing the view frustum.\r
118                 core::plane3d<f32> planes[VF_PLANE_COUNT];\r
119 \r
120                 //! bounding box around the view frustum\r
121                 core::aabbox3d<f32> boundingBox;\r
122 \r
123         private:\r
124                 //! Hold a copy of important transform matrices\r
125                 enum E_TRANSFORMATION_STATE_FRUSTUM\r
126                 {\r
127                         ETS_VIEW = 0,\r
128                         ETS_PROJECTION = 1,\r
129                         ETS_COUNT_FRUSTUM\r
130                 };\r
131 \r
132                 //! recalculates the bounding sphere based on the planes\r
133                 inline void recalculateBoundingSphere();\r
134 \r
135                 //! Hold a copy of important transform matrices\r
136                 core::matrix4 Matrices[ETS_COUNT_FRUSTUM];\r
137 \r
138                 float BoundingRadius;\r
139                 float FarNearDistance;\r
140                 core::vector3df BoundingCenter;\r
141         };\r
142 \r
143 \r
144         /*!\r
145                 Copy constructor ViewFrustum\r
146         */\r
147         inline SViewFrustum::SViewFrustum(const SViewFrustum& other)\r
148         {\r
149                 cameraPosition=other.cameraPosition;\r
150                 boundingBox=other.boundingBox;\r
151 \r
152                 u32 i;\r
153                 for (i=0; i<VF_PLANE_COUNT; ++i)\r
154                         planes[i]=other.planes[i];\r
155 \r
156                 for (i=0; i<ETS_COUNT_FRUSTUM; ++i)\r
157                         Matrices[i]=other.Matrices[i];\r
158 \r
159                 BoundingRadius = other.BoundingRadius;\r
160                 FarNearDistance = other.FarNearDistance;\r
161                 BoundingCenter = other.BoundingCenter;\r
162         }\r
163 \r
164         inline SViewFrustum::SViewFrustum(const core::matrix4& mat, bool zClipFromZero)\r
165         {\r
166                 setFrom(mat, zClipFromZero);\r
167         }\r
168 \r
169 \r
170         inline void SViewFrustum::transform(const core::matrix4& mat)\r
171         {\r
172                 for (u32 i=0; i<VF_PLANE_COUNT; ++i)\r
173                         mat.transformPlane(planes[i]);\r
174 \r
175                 mat.transformVect(cameraPosition);\r
176                 recalculateBoundingBox();\r
177         }\r
178 \r
179 \r
180         inline core::vector3df SViewFrustum::getFarLeftUp() const\r
181         {\r
182                 core::vector3df p;\r
183                 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(\r
184                         planes[scene::SViewFrustum::VF_TOP_PLANE],\r
185                         planes[scene::SViewFrustum::VF_LEFT_PLANE], p);\r
186 \r
187                 return p;\r
188         }\r
189 \r
190         inline core::vector3df SViewFrustum::getFarLeftDown() const\r
191         {\r
192                 core::vector3df p;\r
193                 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(\r
194                         planes[scene::SViewFrustum::VF_BOTTOM_PLANE],\r
195                         planes[scene::SViewFrustum::VF_LEFT_PLANE], p);\r
196 \r
197                 return p;\r
198         }\r
199 \r
200         inline core::vector3df SViewFrustum::getFarRightUp() const\r
201         {\r
202                 core::vector3df p;\r
203                 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(\r
204                         planes[scene::SViewFrustum::VF_TOP_PLANE],\r
205                         planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);\r
206 \r
207                 return p;\r
208         }\r
209 \r
210         inline core::vector3df SViewFrustum::getFarRightDown() const\r
211         {\r
212                 core::vector3df p;\r
213                 planes[scene::SViewFrustum::VF_FAR_PLANE].getIntersectionWithPlanes(\r
214                         planes[scene::SViewFrustum::VF_BOTTOM_PLANE],\r
215                         planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);\r
216 \r
217                 return p;\r
218         }\r
219 \r
220         inline core::vector3df SViewFrustum::getNearLeftUp() const\r
221         {\r
222                 core::vector3df p;\r
223                 planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(\r
224                         planes[scene::SViewFrustum::VF_TOP_PLANE],\r
225                         planes[scene::SViewFrustum::VF_LEFT_PLANE], p);\r
226 \r
227                 return p;\r
228         }\r
229 \r
230         inline core::vector3df SViewFrustum::getNearLeftDown() const\r
231         {\r
232                 core::vector3df p;\r
233                 planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(\r
234                         planes[scene::SViewFrustum::VF_BOTTOM_PLANE],\r
235                         planes[scene::SViewFrustum::VF_LEFT_PLANE], p);\r
236 \r
237                 return p;\r
238         }\r
239 \r
240         inline core::vector3df SViewFrustum::getNearRightUp() const\r
241         {\r
242                 core::vector3df p;\r
243                 planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(\r
244                         planes[scene::SViewFrustum::VF_TOP_PLANE],\r
245                         planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);\r
246 \r
247                 return p;\r
248         }\r
249 \r
250         inline core::vector3df SViewFrustum::getNearRightDown() const\r
251         {\r
252                 core::vector3df p;\r
253                 planes[scene::SViewFrustum::VF_NEAR_PLANE].getIntersectionWithPlanes(\r
254                         planes[scene::SViewFrustum::VF_BOTTOM_PLANE],\r
255                         planes[scene::SViewFrustum::VF_RIGHT_PLANE], p);\r
256 \r
257                 return p;\r
258         }\r
259 \r
260         inline const core::aabbox3d<f32> &SViewFrustum::getBoundingBox() const\r
261         {\r
262                 return boundingBox;\r
263         }\r
264 \r
265         inline void SViewFrustum::recalculateBoundingBox()\r
266         {\r
267                 boundingBox.reset(getNearLeftUp());\r
268                 boundingBox.addInternalPoint(getNearRightUp());\r
269                 boundingBox.addInternalPoint(getNearLeftDown());\r
270                 boundingBox.addInternalPoint(getNearRightDown());\r
271                 boundingBox.addInternalPoint(getFarRightUp());\r
272                 boundingBox.addInternalPoint(getFarLeftDown());\r
273                 boundingBox.addInternalPoint(getFarRightDown());\r
274                 boundingBox.addInternalPoint(getFarLeftUp());\r
275 \r
276                 // Also recalculate the bounding sphere when the bbox changes\r
277                 recalculateBoundingSphere();\r
278         }\r
279 \r
280         inline float SViewFrustum::getBoundingRadius() const\r
281         {\r
282                 return BoundingRadius;\r
283         }\r
284 \r
285         inline core::vector3df SViewFrustum::getBoundingCenter() const\r
286         {\r
287                 return BoundingCenter;\r
288         }\r
289 \r
290         inline void SViewFrustum::setFarNearDistance(float distance)\r
291         {\r
292                 FarNearDistance = distance;\r
293         }\r
294 \r
295         //! This constructor creates a view frustum based on a projection\r
296         //! and/or view matrix.\r
297         inline void SViewFrustum::setFrom(const core::matrix4& mat, bool zClipFromZero)\r
298         {\r
299                 // left clipping plane\r
300                 planes[VF_LEFT_PLANE].Normal.X = mat[3 ] + mat[0];\r
301                 planes[VF_LEFT_PLANE].Normal.Y = mat[7 ] + mat[4];\r
302                 planes[VF_LEFT_PLANE].Normal.Z = mat[11] + mat[8];\r
303                 planes[VF_LEFT_PLANE].D =        mat[15] + mat[12];\r
304 \r
305                 // right clipping plane\r
306                 planes[VF_RIGHT_PLANE].Normal.X = mat[3 ] - mat[0];\r
307                 planes[VF_RIGHT_PLANE].Normal.Y = mat[7 ] - mat[4];\r
308                 planes[VF_RIGHT_PLANE].Normal.Z = mat[11] - mat[8];\r
309                 planes[VF_RIGHT_PLANE].D =        mat[15] - mat[12];\r
310 \r
311                 // top clipping plane\r
312                 planes[VF_TOP_PLANE].Normal.X = mat[3 ] - mat[1];\r
313                 planes[VF_TOP_PLANE].Normal.Y = mat[7 ] - mat[5];\r
314                 planes[VF_TOP_PLANE].Normal.Z = mat[11] - mat[9];\r
315                 planes[VF_TOP_PLANE].D =        mat[15] - mat[13];\r
316 \r
317                 // bottom clipping plane\r
318                 planes[VF_BOTTOM_PLANE].Normal.X = mat[3 ] + mat[1];\r
319                 planes[VF_BOTTOM_PLANE].Normal.Y = mat[7 ] + mat[5];\r
320                 planes[VF_BOTTOM_PLANE].Normal.Z = mat[11] + mat[9];\r
321                 planes[VF_BOTTOM_PLANE].D =        mat[15] + mat[13];\r
322 \r
323                 // far clipping plane\r
324                 planes[VF_FAR_PLANE].Normal.X = mat[3 ] - mat[2];\r
325                 planes[VF_FAR_PLANE].Normal.Y = mat[7 ] - mat[6];\r
326                 planes[VF_FAR_PLANE].Normal.Z = mat[11] - mat[10];\r
327                 planes[VF_FAR_PLANE].D =        mat[15] - mat[14];\r
328 \r
329                 // near clipping plane\r
330                 if ( zClipFromZero )\r
331                 {\r
332                         planes[VF_NEAR_PLANE].Normal.X = mat[2];\r
333                         planes[VF_NEAR_PLANE].Normal.Y = mat[6];\r
334                         planes[VF_NEAR_PLANE].Normal.Z = mat[10];\r
335                         planes[VF_NEAR_PLANE].D =        mat[14];\r
336                 }\r
337                 else\r
338                 {\r
339                         // near clipping plane\r
340                         planes[VF_NEAR_PLANE].Normal.X = mat[3 ] + mat[2];\r
341                         planes[VF_NEAR_PLANE].Normal.Y = mat[7 ] + mat[6];\r
342                         planes[VF_NEAR_PLANE].Normal.Z = mat[11] + mat[10];\r
343                         planes[VF_NEAR_PLANE].D =        mat[15] + mat[14];\r
344                 }\r
345 \r
346                 // normalize normals\r
347                 u32 i;\r
348                 for ( i=0; i != VF_PLANE_COUNT; ++i)\r
349                 {\r
350                         const f32 len = -core::reciprocal_squareroot(\r
351                                         planes[i].Normal.getLengthSQ());\r
352                         planes[i].Normal *= len;\r
353                         planes[i].D *= len;\r
354                 }\r
355 \r
356                 // make bounding box\r
357                 recalculateBoundingBox();\r
358         }\r
359 \r
360         /*!\r
361                 View Frustum depends on Projection & View Matrix\r
362         */\r
363         inline core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state)\r
364         {\r
365                 u32 index = 0;\r
366                 switch ( state )\r
367                 {\r
368                         case video::ETS_PROJECTION:\r
369                                 index = SViewFrustum::ETS_PROJECTION; break;\r
370                         case video::ETS_VIEW:\r
371                                 index = SViewFrustum::ETS_VIEW; break;\r
372                         default:\r
373                                 break;\r
374                 }\r
375                 return Matrices [ index ];\r
376         }\r
377 \r
378         /*!\r
379                 View Frustum depends on Projection & View Matrix\r
380         */\r
381         inline const core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state) const\r
382         {\r
383                 u32 index = 0;\r
384                 switch ( state )\r
385                 {\r
386                         case video::ETS_PROJECTION:\r
387                                 index = SViewFrustum::ETS_PROJECTION; break;\r
388                         case video::ETS_VIEW:\r
389                                 index = SViewFrustum::ETS_VIEW; break;\r
390                         default:\r
391                                 break;\r
392                 }\r
393                 return Matrices [ index ];\r
394         }\r
395 \r
396         //! Clips a line to the frustum\r
397         inline bool SViewFrustum::clipLine(core::line3d<f32>& line) const\r
398         {\r
399                 bool wasClipped = false;\r
400                 for (u32 i=0; i < VF_PLANE_COUNT; ++i)\r
401                 {\r
402                         if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT)\r
403                         {\r
404                                 line.start = line.start.getInterpolated(line.end,\r
405                                                 1.f-planes[i].getKnownIntersectionWithLine(line.start, line.end));\r
406                                 wasClipped = true;\r
407                         }\r
408                         if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT)\r
409                         {\r
410                                 line.end = line.start.getInterpolated(line.end,\r
411                                                 1.f-planes[i].getKnownIntersectionWithLine(line.start, line.end));\r
412                                 wasClipped = true;\r
413                         }\r
414                 }\r
415                 return wasClipped;\r
416         }\r
417 \r
418         inline void SViewFrustum::recalculateBoundingSphere()\r
419         {\r
420                 // Find the center\r
421                 const float shortlen = (getNearLeftUp() - getNearRightUp()).getLength();\r
422                 const float longlen = (getFarLeftUp() - getFarRightUp()).getLength();\r
423 \r
424                 const float farlen = FarNearDistance;\r
425                 const float fartocenter = (farlen + (shortlen - longlen) * (shortlen + longlen)/(4*farlen)) / 2;\r
426                 const float neartocenter = farlen - fartocenter;\r
427 \r
428                 BoundingCenter = cameraPosition + -planes[VF_NEAR_PLANE].Normal * neartocenter;\r
429 \r
430                 // Find the radius\r
431                 core::vector3df dir[8];\r
432                 dir[0] = getFarLeftUp() - BoundingCenter;\r
433                 dir[1] = getFarRightUp() - BoundingCenter;\r
434                 dir[2] = getFarLeftDown() - BoundingCenter;\r
435                 dir[3] = getFarRightDown() - BoundingCenter;\r
436                 dir[4] = getNearRightDown() - BoundingCenter;\r
437                 dir[5] = getNearLeftDown() - BoundingCenter;\r
438                 dir[6] = getNearRightUp() - BoundingCenter;\r
439                 dir[7] = getNearLeftUp() - BoundingCenter;\r
440 \r
441                 u32 i = 0;\r
442                 float diam[8] = { 0.f };\r
443 \r
444                 for (i = 0; i < 8; ++i)\r
445                         diam[i] = dir[i].getLengthSQ();\r
446 \r
447                 float longest = 0;\r
448 \r
449                 for (i = 0; i < 8; ++i)\r
450                 {\r
451                         if (diam[i] > longest)\r
452                                 longest = diam[i];\r
453                 }\r
454 \r
455                 BoundingRadius = sqrtf(longest);\r
456         }\r
457 \r
458 } // end namespace scene\r
459 } // end namespace irr\r
460 \r
461 #endif\r
462 \r