]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/clouds3d/SkyMinMaxBox.cpp
Clouds3D crashes because there is no Light
[simgear.git] / simgear / scene / sky / clouds3d / SkyMinMaxBox.cpp
1 //------------------------------------------------------------------------------
2 // File : SkyMinMaxBox.cpp
3 //------------------------------------------------------------------------------
4 // SkyWorks : Copyright 2002 Mark J. Harris and
5 //                                              The University of North Carolina at Chapel Hill
6 //------------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software and its 
8 // documentation for any purpose is hereby granted without fee, provided that 
9 // the above copyright notice appear in all copies and that both that copyright 
10 // notice and this permission notice appear in supporting documentation. 
11 // Binaries may be compiled with this software without any royalties or 
12 // restrictions. 
13 //
14 // The author(s) and The University of North Carolina at Chapel Hill make no 
15 // representations about the suitability of this software for any purpose. 
16 // It is provided "as is" without express or 
17 // implied warranty.
18 /**
19  * @file SkyMinMaxBox.cpp
20  * 
21  * Implementation of a bounding box class.  Modified from Wes Hunt's BoundingBox.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include <simgear_config.h>
26 #endif
27
28 #ifdef HAVE_WINDOWS_H
29 #  include <windows.h>
30 #endif
31
32 #include <GL/gl.h>
33
34 #include "SkyMinMaxBox.hpp"
35 #include "camutils.hpp"
36 #include <float.h>
37
38
39 //------------------------------------------------------------------------------
40 // Function               : SkyMinMaxBox::SkyMinMaxBox
41 // Description      : 
42 //------------------------------------------------------------------------------
43 /**
44  * @fn SkyMinMaxBox::SkyMinMaxBox()
45  * @brief Constructor
46  */ 
47 SkyMinMaxBox::SkyMinMaxBox()
48 {
49   Clear();
50 }
51
52
53 //------------------------------------------------------------------------------
54 // Function               : SkyMinMaxBox::Clear
55 // Description      : 
56 //------------------------------------------------------------------------------
57 /**
58  * @fn SkyMinMaxBox::Clear()
59  * @brief Reset the min and max to floating point extremes.
60  * 
61  */ 
62 void SkyMinMaxBox::Clear()
63 {
64         _min.x =  FLT_MAX;
65         _min.y =  FLT_MAX;
66         _min.z =  FLT_MAX;
67         _max.x = -FLT_MAX;
68         _max.y = -FLT_MAX;
69         _max.z = -FLT_MAX;
70 }
71
72
73 //------------------------------------------------------------------------------
74 // Function               : SkyMinMaxBox::PointInBBox
75 // Description      : 
76 //------------------------------------------------------------------------------
77 /**
78  * @fn SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
79  * @brief Queries pt to see if it is inside the SkyMinMaxBox.
80  * 
81  */ 
82 bool SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
83 {
84         if( (pt.x >= _min.x) && ( pt.x <= _max.x ) )
85         {
86                 if( (pt.y >= _min.y) && ( pt.y <= _max.y ) )
87                 {
88                         if( (pt.z >= _min.z) && ( pt.z <= _max.z ) )
89                                 return true;
90                 }
91         }
92
93         return false;
94 }
95
96
97 //------------------------------------------------------------------------------
98 // Function               : SkyMinMaxBox::AddPoint
99 // Description      : 
100 //------------------------------------------------------------------------------
101 /**
102  * @fn SkyMinMaxBox::AddPoint( float x , float y , float z )
103  * @brief Adds a point and adjusts bounds if necessary.             
104  */ 
105 void SkyMinMaxBox::AddPoint( float x , float y , float z )
106 {
107         if( x > _max.x )
108                 _max.x = x;
109         if( x < _min.x )
110                 _min.x = x;
111         
112         if( y > _max.y )
113                 _max.y = y;
114         if( y < _min.y )
115                 _min.y = y;
116
117         if( z > _max.z )
118                 _max.z = z;
119         if( z < _min.z )
120                 _min.z = z;
121
122   // update the center and radius
123   _UpdateSphere();
124 }
125
126
127 //------------------------------------------------------------------------------
128 // Function               : SkyMinMaxBox::AddPoint
129 // Description      : 
130 //------------------------------------------------------------------------------
131 /**
132  * @fn SkyMinMaxBox::AddPoint( const Vec3f &pt )
133  * @brief Adds a point and adjusts bounds if necessary.             
134  */ 
135 void SkyMinMaxBox::AddPoint( const Vec3f &pt )
136 {
137         if( pt.x > _max.x )
138                 _max.x = pt.x;
139         if( pt.x < _min.x )
140                 _min.x = pt.x;
141         
142         if( pt.y > _max.y )
143                 _max.y = pt.y;
144         if( pt.y < _min.y )
145                 _min.y = pt.y;
146
147         if( pt.z > _max.z )
148                 _max.z = pt.z;
149         if( pt.z < _min.z )
150                 _min.z = pt.z;
151
152   // update the center and radius
153   _UpdateSphere();
154 }
155
156
157 //------------------------------------------------------------------------------
158 // Function               : SkyMinMaxBox::ViewFrustumCull
159 // Description      : 
160 //------------------------------------------------------------------------------
161 /**
162  * @fn SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
163  * @brief Returns true if bounding volume culled against cam.
164  * 
165  * This function must transform the object space min and max then adjust the new 
166  * min and max box by expanding it.  Each of the 8 points must be tested.  This 
167  * is faster then doing an xform of all the geometry points and finding a tight
168  * fitting min max box, however this will be enlarged.
169  */ 
170 bool SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
171 {
172   SkyMinMaxBox xBV;                // Xformed Bounding Volume
173   Vec3f xMin   = mat * _min;      // Xformed _min
174   Vec3f xMax   = mat * _max;      // Xformed _max
175   Vec3f offset = _max - _min;     // Offset for sides of MinMaxBox
176   Vec3f tmp;
177
178   xBV.Clear(); // Clear the values first
179
180   // First find the new minimum x,y,z
181   // Find min + x
182   tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
183   tmp *= offset.x;
184   tmp += xMin;
185   xBV.AddPoint(tmp);
186
187   // Find min + y
188   tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
189   tmp *= offset.y;
190   tmp += xMin;
191   xBV.AddPoint(tmp);
192
193   // Find min + z
194   tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
195   tmp *= offset.z;
196   tmp += xMin;
197   xBV.AddPoint(tmp);
198   
199   // Second find the new maximum x,y,z
200   // Find max - x
201   tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
202   tmp *= -offset.x;
203   tmp += xMax;
204   xBV.AddPoint(tmp);
205   
206   // Find max - y
207   tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
208   tmp *= -offset.y;
209   tmp += xMax;
210   xBV.AddPoint(tmp);
211   
212   // Find max - z
213   tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
214   tmp *= -offset.z;
215   tmp += xMax;
216   xBV.AddPoint(tmp);
217   
218   // Use the camera utility function that already exists for minmax boxes
219   return VFC(&cam, xBV.GetMin(), xBV.GetMax());
220 }
221
222
223 //------------------------------------------------------------------------------
224 // Function               : SkyMinMaxBox::Transform
225 // Description      : 
226 //------------------------------------------------------------------------------
227 /**
228  * @fn SkyMinMaxBox::Transform(const Mat44f& mat)
229  * @brief @todo <WRITE BRIEF SkyMinMaxBox::Transform DOCUMENTATION>
230  * 
231  * @todo <WRITE EXTENDED SkyMinMaxBox::Transform FUNCTION DOCUMENTATION>
232  */ 
233 void SkyMinMaxBox::Transform(const Mat44f& mat)
234 {
235   Vec3f verts[8];
236   _CalcVerts(verts);
237   Clear();
238   for (int i = 0; i < 8; ++i)
239   {
240     AddPoint(mat * verts[i]);
241   }
242 }
243
244 //------------------------------------------------------------------------------
245 // Function               : SkyMinMaxBox::_UpdateSphere
246 // Description      : 
247 //------------------------------------------------------------------------------
248 /**
249 * @fn SkyMinMaxBox::_UpdateSphere()
250 * @brief Updates the bounding sphere based on min and max.
251 */ 
252 void SkyMinMaxBox::_UpdateSphere()
253 {
254   _vecCenter =  _min;
255   _vecCenter += _max;
256   _vecCenter *= 0.5f;
257   
258   Vec3f rad  =  _max;
259   rad        -= _vecCenter;
260   _rRadius   =  rad.Length();
261 }
262
263
264
265 //------------------------------------------------------------------------------
266 // Function               : SkyMinMaxBox::Display
267 // Description      : 
268 //------------------------------------------------------------------------------
269 /**
270  * @fn SkyMinMaxBox::Display() const
271  * @brief @todo <WRITE BRIEF SkyMinMaxBox::Display DOCUMENTATION>
272  * 
273  * @todo <WRITE EXTENDED SkyMinMaxBox::Display FUNCTION DOCUMENTATION>
274  */ 
275 void SkyMinMaxBox::Display() const
276 {
277   Vec3f V[8];
278   _CalcVerts(V);
279   
280   glPushAttrib(GL_LINE_BIT);
281   glLineWidth(1.0);
282   
283   glBegin(GL_LINE_LOOP);  // TOP FACE
284   glVertex3fv(V[4]); glVertex3fv(V[5]); glVertex3fv(V[1]); glVertex3fv(V[0]);
285   glEnd();
286   glBegin(GL_LINE_LOOP);  // BOTTOM FACE
287   glVertex3fv(V[3]); glVertex3fv(V[2]); glVertex3fv(V[6]); glVertex3fv(V[7]); 
288   glEnd();
289   glBegin(GL_LINE_LOOP);  // LEFT FACE
290   glVertex3fv(V[1]); glVertex3fv(V[5]); glVertex3fv(V[6]); glVertex3fv(V[2]); 
291   glEnd();
292   glBegin(GL_LINE_LOOP);  // RIGHT FACE
293   glVertex3fv(V[0]); glVertex3fv(V[3]); glVertex3fv(V[7]); glVertex3fv(V[4]); 
294   glEnd();
295   glBegin(GL_LINE_LOOP);  // NEAR FACE
296   glVertex3fv(V[1]); glVertex3fv(V[2]); glVertex3fv(V[3]); glVertex3fv(V[0]); 
297   glEnd();
298   glBegin(GL_LINE_LOOP);  // FAR FACE
299   glVertex3fv(V[4]); glVertex3fv(V[7]); glVertex3fv(V[6]); glVertex3fv(V[5]); 
300   glEnd();
301   
302   glPopAttrib();
303 }
304
305 //-----------------------------------------------------------------------------
306 // Calculates the eight corner vertices of the MinMaxBox.
307 // V must be prealloced.
308 //       5---4
309 //      /   /|
310 //     1---0 |   VERTS : 0=RTN,1=LTN,2=LBN,3=RBN,4=RTF,5=LTF,6=LBF,7=RBF
311 //     |   | 7   (L,R, B,T, N,F) = (Left,Right, Bottom,Top, Near,Far)
312 //     |   |/
313 //     2---3
314 //-----------------------------------------------------------------------------
315
316 //------------------------------------------------------------------------------
317 // Function               : SkyMinMaxBox::_CalcVerts
318 // Description      : 
319 //------------------------------------------------------------------------------
320 /**
321  * @fn SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
322  * @brief @todo <WRITE BRIEF SkyMinMaxBox::_CalcVerts DOCUMENTATION>
323  * 
324  * @todo <WRITE EXTENDED SkyMinMaxBox::_CalcVerts FUNCTION DOCUMENTATION>
325  */ 
326 void SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
327 {
328   pVerts[0].Set(_max); pVerts[4].Set(_max.x, _max.y, _min.z);
329   pVerts[1].Set(_min.x, _max.y, _max.z); pVerts[5].Set(_min.x, _max.y, _min.z);
330   pVerts[2].Set(_min.x, _min.y, _max.z); pVerts[6].Set(_min);
331   pVerts[3].Set(_max.x, _min.y, _max.z); pVerts[7].Set(_max.x, _min.y, _min.z);
332 }