Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
opbox.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 1998 by Jorrit Tyberghein
3  Largely rewritten by Ivan Avramovic <ivan@avramovic.com>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public
16  License along with this library; if not, write to the Free
17  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #define MIN(a,b) ((a)<(b)?(a):(b))
20 #define MAX(a,b) ((a)>(b)?(a):(b))
21 #include <math.h>
23 #include "opbox.h"
24 
25 //---------------------------------------------------------------------------
26 
27 //---------------------------------------------------------------------------
28 
29 // We have a coordinate system around our box which is
30 // divided into 27 regions. The center region at coordinate (1,1,1)
31 // is the node itself. Every one of the 26 remaining regions
32 // defines an number of vertices which are the convex outline
33 // as seen from a camera view point in that region.
34 // The numbers inside the outlines table are indices from 0 to
35 // 7 which describe the 8 vertices outlining the node:
36 // 0: left/down/front vertex
37 // 1: left/down/back
38 // 2: left/up/front
39 // 3: left/up/back
40 // 4: right/down/front
41 // 5: right/down/back
42 // 6: right/up/front
43 // 7: right/up/back
44 // This table also contains an array of sides visible from that region.
45 struct Outline
46 {
47  int num;
48  int vertices[7];
49  int num_sides;
50  int sides[3];
51 };
53 static Outline outlines[27] =
54 {
55  { 7, {3,2,6,4,5,1,0}, 3, {BOX_SIDE_x,BOX_SIDE_y,BOX_SIDE_z} }, // 0,0,0
56  { 6, {3,2,0,4,5,1,-1}, 2, {BOX_SIDE_x,BOX_SIDE_y,-1} }, // 0,0,1
57  { 7, {7,3,2,0,4,5,1}, 3, {BOX_SIDE_x,BOX_SIDE_y,BOX_SIDE_Z} }, // 0,0,2
58  { 6, {3,2,6,4,0,1,-1}, 2, {BOX_SIDE_x,BOX_SIDE_z,-1} }, // 0,1,0
59  { 4, {3,2,0,1,-1,-1,-1}, 1, {BOX_SIDE_x,-1,-1} }, // 0,1,1
60  { 6, {7,3,2,0,1,5,-1}, 2, {BOX_SIDE_x,BOX_SIDE_Z,-1} }, // 0,1,2
61  { 7, {3,7,6,4,0,1,2}, 3, {BOX_SIDE_x,BOX_SIDE_Y,BOX_SIDE_z} }, // 0,2,0
62  { 6, {3,7,6,2,0,1,-1}, 2, {BOX_SIDE_x,BOX_SIDE_Y,-1} }, // 0,2,1
63  { 7, {7,6,2,0,1,5,3}, 3, {BOX_SIDE_x,BOX_SIDE_Y,BOX_SIDE_Z} }, // 0,2,2
64  { 6, {2,6,4,5,1,0,-1}, 2, {BOX_SIDE_y,BOX_SIDE_z,-1} }, // 1,0,0
65  { 4, {0,4,5,1,-1,-1,-1}, 1, {BOX_SIDE_y,-1,-1} }, // 1,0,1
66  { 6, {3,1,0,4,5,7,-1}, 2, {BOX_SIDE_y,BOX_SIDE_Z,-1} }, // 1,0,2
67  { 4, {2,6,4,0,-1,-1,-1}, 1, {BOX_SIDE_z,-1,-1} }, // 1,1,0
68  { 0, {-1,-1,-1,-1,-1,-1,-1}, 0, {-1,-1,-1} }, // 1,1,1
69  { 4, {7,3,1,5,-1,-1,-1}, 1, {BOX_SIDE_Z,-1,-1} }, // 1,1,2
70  { 6, {3,7,6,4,0,2,-1}, 2, {BOX_SIDE_Y,BOX_SIDE_z,-1} }, // 1,2,0
71  { 4, {3,7,6,2,-1,-1,-1}, 1, {BOX_SIDE_Y,-1,-1} }, // 1,2,1
72  { 6, {2,3,1,5,7,6,-1}, 2, {BOX_SIDE_Y,BOX_SIDE_Z,-1} }, // 1,2,2
73  { 7, {2,6,7,5,1,0,4}, 3, {BOX_SIDE_X,BOX_SIDE_y,BOX_SIDE_z} }, // 2,0,0
74  { 6, {6,7,5,1,0,4,-1}, 2, {BOX_SIDE_X,BOX_SIDE_y,-1} }, // 2,0,1
75  { 7, {6,7,3,1,0,4,5}, 3, {BOX_SIDE_X,BOX_SIDE_y,BOX_SIDE_Z} }, // 2,0,2
76  { 6, {2,6,7,5,4,0,-1}, 2, {BOX_SIDE_X,BOX_SIDE_z,-1} }, // 2,1,0
77  { 4, {6,7,5,4,-1,-1,-1}, 1, {BOX_SIDE_X,-1,-1} }, // 2,1,1
78  { 6, {6,7,3,1,5,4,-1}, 2, {BOX_SIDE_X,BOX_SIDE_Z,-1} }, // 2,1,2
79  { 7, {2,3,7,5,4,0,6}, 3, {BOX_SIDE_X,BOX_SIDE_Y,BOX_SIDE_z} }, // 2,2,0
80  { 6, {2,3,7,5,4,6,-1}, 2, {BOX_SIDE_X,BOX_SIDE_Y,-1} }, // 2,2,1
81  { 7, {6,2,3,1,5,4,7}, 3, {BOX_SIDE_X,BOX_SIDE_Y,BOX_SIDE_Z} } // 2,2,2
82 };
83 
85  {
94 
103 
112  };
113 // Index by BOX_SIDE_? number.
115  {
122  };
123 
124 csVector3 csBox3::GetCorner (int corner) const
125 {
126  switch (corner)
127  {
128  case BOX_CORNER_xyz: return Min ();
129  case BOX_CORNER_xyZ: return csVector3 (MinX (), MinY (), MaxZ ());
130  case BOX_CORNER_xYz: return csVector3 (MinX (), MaxY (), MinZ ());
131  case BOX_CORNER_xYZ: return csVector3 (MinX (), MaxY (), MaxZ ());
132  case BOX_CORNER_Xyz: return csVector3 (MaxX (), MinY (), MinZ ());
133  case BOX_CORNER_XyZ: return csVector3 (MaxX (), MinY (), MaxZ ());
134  case BOX_CORNER_XYz: return csVector3 (MaxX (), MaxY (), MinZ ());
135  case BOX_CORNER_XYZ: return Max ();
136  }
137  return csVector3 (0, 0, 0);
138 }
139 
141 {
142  csVector3 move = c-GetCenter ();
143  minbox += move;
144  maxbox += move;
145 }
146 
147 void csBox3::SetSize (const csVector3& s)
148 {
150  minbox = center - s*(float).5;
151  maxbox = center + s*(float).5;
152 }
153 
154 
155 bool csBox3::AdjacentX (const csBox3& other) const
156 {
157  if (ABS (other.MinX () - MaxX ()) < SMALL_EPSILON ||
158  ABS (other.MaxX () - MinX ()) < SMALL_EPSILON)
159  {
160  if (MaxY () < other.MinY () || MinY () > other.MaxY ()) return false;
161  if (MaxZ () < other.MinZ () || MinZ () > other.MaxZ ()) return false;
162  return true;
163  }
164  return false;
165 }
166 
167 bool csBox3::AdjacentY (const csBox3& other) const
168 {
169  if (ABS (other.MinY () - MaxY ()) < SMALL_EPSILON ||
170  ABS (other.MaxY () - MinY ()) < SMALL_EPSILON)
171  {
172  if (MaxX () < other.MinX () || MinX () > other.MaxX ()) return false;
173  if (MaxZ () < other.MinZ () || MinZ () > other.MaxZ ()) return false;
174  return true;
175  }
176  return false;
177 }
178 
179 bool csBox3::AdjacentZ (const csBox3& other) const
180 {
181  if (ABS (other.MinZ () - MaxZ ()) < SMALL_EPSILON ||
182  ABS (other.MaxZ () - MinZ ()) < SMALL_EPSILON)
183  {
184  if (MaxX () < other.MinX () || MinX () > other.MaxX ()) return false;
185  if (MaxY () < other.MinY () || MinY () > other.MaxY ()) return false;
186  return true;
187  }
188  return false;
189 }
190 
191 int csBox3::Adjacent (const csBox3& other) const
192 {
193  if (AdjacentX (other))
194  {
195  if (other.MaxX () > MaxX ()) return BOX_SIDE_X;
196  else return BOX_SIDE_x;
197  }
198  if (AdjacentY (other))
199  {
200  if (other.MaxY () > MaxY ()) return BOX_SIDE_Y;
201  else return BOX_SIDE_y;
202  }
203  if (AdjacentZ (other))
204  {
205  if (other.MaxZ () > MaxZ ()) return BOX_SIDE_Z;
206  else return BOX_SIDE_z;
207  }
208  return -1;
209 }
210 
211 int csBox3::GetVisibleSides (const csVector3& pos, int* visible_sides) const
212 {
213  const csVector3& bmin = Min ();
214  const csVector3& bmax = Max ();
215  int idx;
216  // First select x part of coordinate.
217  if (pos.x < bmin.x) idx = 0*9;
218  else if (pos.x > bmax.x) idx = 2*9;
219  else idx = 1*9;
220  // Then y part.
221  if (pos.y < bmin.y) idx += 0*3;
222  else if (pos.y > bmax.y) idx += 2*3;
223  else idx += 1*3;
224  // Then z part.
225  if (pos.z < bmin.z) idx += 0;
226  else if (pos.z > bmax.z) idx += 2;
227  else idx += 1;
228  const Outline& ol = outlines[idx];
229  int num_array = ol.num_sides;
230  int i;
231  for (i = 0 ; i < num_array ; i++)
232  visible_sides[i] = ol.sides[i];
233  return num_array;
234 }
235 
237  csVector3* ar, int& num_array, bool bVisible) const
238 {
239  const csVector3& bmin = Min ();
240  const csVector3& bmax = Max ();
241  int idx;
242  // First select x part of coordinate.
243  if (pos.x < bmin.x) idx = 0*9;
244  else if (pos.x > bmax.x) idx = 2*9;
245  else idx = 1*9;
246  // Then y part.
247  if (pos.y < bmin.y) idx += 0*3;
248  else if (pos.y > bmax.y) idx += 2*3;
249  else idx += 1*3;
250  // Then z part.
251  if (pos.z < bmin.z) idx += 0;
252  else if (pos.z > bmax.z) idx += 2;
253  else idx += 1;
254 
255  const Outline& ol = outlines[idx];
256  num_array = (bVisible ? ol.num : MIN (ol.num, 6));
257  int i;
258  for (i = 0 ; i < num_array ; i++)
259  {
260  switch (ol.vertices[i])
261  {
262  case 0: ar[i].x = bmin.x; ar[i].y = bmin.y; ar[i].z = bmin.z; break;
263  case 1: ar[i].x = bmin.x; ar[i].y = bmin.y; ar[i].z = bmax.z; break;
264  case 2: ar[i].x = bmin.x; ar[i].y = bmax.y; ar[i].z = bmin.z; break;
265  case 3: ar[i].x = bmin.x; ar[i].y = bmax.y; ar[i].z = bmax.z; break;
266  case 4: ar[i].x = bmax.x; ar[i].y = bmin.y; ar[i].z = bmin.z; break;
267  case 5: ar[i].x = bmax.x; ar[i].y = bmin.y; ar[i].z = bmax.z; break;
268  case 6: ar[i].x = bmax.x; ar[i].y = bmax.y; ar[i].z = bmin.z; break;
269  case 7: ar[i].x = bmax.x; ar[i].y = bmax.y; ar[i].z = bmax.z; break;
270  }
271  }
272 }
273 
274 bool csBox3::Between (const csBox3& box1, const csBox3& box2) const
275 {
276  // First the trival test to see if the coordinates are
277  // at least within the right intervals.
278  if (((maxbox.x >= box1.minbox.x && minbox.x <= box2.maxbox.x) ||
279  (maxbox.x >= box2.minbox.x && minbox.x <= box1.maxbox.x)) &&
280  ((maxbox.y >= box1.minbox.y && minbox.y <= box2.maxbox.y) ||
281  (maxbox.y >= box2.minbox.y && minbox.y <= box1.maxbox.y)) &&
282  ((maxbox.z >= box1.minbox.z && minbox.z <= box2.maxbox.z) ||
283  (maxbox.z >= box2.minbox.z && minbox.z <= box1.maxbox.z)))
284  {
285  // @@@ Ok, let's just return true here. Maybe this test is already
286  // enough? We could have used the planes as well.
287  return true;
288  }
289  return false;
290 }
291 
292 void csBox3::ManhattanDistance (const csBox3& other, csVector3& dist) const
293 {
294  if (other.MinX () >= MaxX ()) dist.x = other.MinX () - MaxX ();
295  else if (MinX () >= other.MaxX ()) dist.x = MinX () - other.MaxX ();
296  else dist.x = 0;
297  if (other.MinY () >= MaxY ()) dist.y = other.MinY () - MaxY ();
298  else if (MinY () >= other.MaxY ()) dist.y = MinY () - other.MaxY ();
299  else dist.y = 0;
300  if (other.MinZ () >= MaxZ ()) dist.z = other.MinZ () - MaxZ ();
301  else if (MinZ () >= other.MaxZ ()) dist.z = MinZ () - other.MaxZ ();
302  else dist.z = 0;
303 }
304 
305 
307 {
308  // Thanks to Ivan Avramovic for the original.
309  // Adapted by Norman Kramer, Jorrit Tyberghein and Wouter Wijngaards.
310  float res = 0;
311  if (minbox.x > 0) res = minbox.x*minbox.x;
312  else if (maxbox.x < 0) res = maxbox.x*maxbox.x;
313  if (minbox.y > 0) res += minbox.y*minbox.y;
314  else if (maxbox.y < 0) res += maxbox.y*maxbox.y;
315  if (minbox.z > 0) res += minbox.z*minbox.z;
316  else if (maxbox.z < 0) res += maxbox.z*maxbox.z;;
317  return res;
318 }
319 
321 {
322  // Thanks to Ivan Avramovic for the original.
323  // Adapted by Norman Kramer, Jorrit Tyberghein and Wouter Wijngaards.
324  float res;
325  if (minbox.x > 0) res = maxbox.x*maxbox.x;
326  else if (maxbox.x < 0) res = minbox.x*minbox.x;
327  else res = MAX (maxbox.x*maxbox.x, minbox.x*minbox.x);
328  if (minbox.y > 0) res += maxbox.y*maxbox.y;
329  else if (maxbox.y < 0) res += minbox.y*minbox.y;
330  else res += MAX (maxbox.y*maxbox.y, minbox.y*minbox.y);
331  if (minbox.z > 0) res += maxbox.z*maxbox.z;
332  else if (maxbox.z < 0) res += minbox.z*minbox.z;
333  else res += MAX (maxbox.z*maxbox.z, minbox.z*minbox.z);
334  return res;
335 }
336 
337 
339 {
340  if (box.minbox.x < minbox.x) minbox.x = box.minbox.x;
341  if (box.minbox.y < minbox.y) minbox.y = box.minbox.y;
342  if (box.minbox.z < minbox.z) minbox.z = box.minbox.z;
343  if (box.maxbox.x > maxbox.x) maxbox.x = box.maxbox.x;
344  if (box.maxbox.y > maxbox.y) maxbox.y = box.maxbox.y;
345  if (box.maxbox.z > maxbox.z) maxbox.z = box.maxbox.z;
346  return *this;
347 }
348 
350 {
351  if (point.x < minbox.x) minbox.x = point.x;
352  if (point.x > maxbox.x) maxbox.x = point.x;
353  if (point.y < minbox.y) minbox.y = point.y;
354  if (point.y > maxbox.y) maxbox.y = point.y;
355  if (point.z < minbox.z) minbox.z = point.z;
356  if (point.z > maxbox.z) maxbox.z = point.z;
357  return *this;
358 }
359 
361 {
362  if (box.minbox.x > minbox.x) minbox.x = box.minbox.x;
363  if (box.minbox.y > minbox.y) minbox.y = box.minbox.y;
364  if (box.minbox.z > minbox.z) minbox.z = box.minbox.z;
365  if (box.maxbox.x < maxbox.x) maxbox.x = box.maxbox.x;
366  if (box.maxbox.y < maxbox.y) maxbox.y = box.maxbox.y;
367  if (box.maxbox.z < maxbox.z) maxbox.z = box.maxbox.z;
368  return *this;
369 }
370 
371 csBox3 operator+ (const csBox3& box1, const csBox3& box2)
372 {
373  return csBox3(
374  MIN(box1.minbox.x,box2.minbox.x),
375  MIN(box1.minbox.y,box2.minbox.y),
376  MIN(box1.minbox.z,box2.minbox.z),
377  MAX(box1.maxbox.x,box2.maxbox.x),
378  MAX(box1.maxbox.y,box2.maxbox.y),
379  MAX(box1.maxbox.z,box2.maxbox.z) );
380 }
381 
382 csBox3 operator+ (const csBox3& box, const csVector3& point)
383 {
384  return csBox3(
385  MIN(box.minbox.x,point.x),
386  MIN(box.minbox.y,point.y),
387  MIN(box.minbox.z,point.z),
388  MAX(box.maxbox.x,point.x),
389  MAX(box.maxbox.y,point.y),
390  MAX(box.maxbox.z,point.z) );
391 }
392 
393 csBox3 operator* (const csBox3& box1, const csBox3& box2)
394 {
395  return csBox3(
396  MAX(box1.minbox.x,box2.minbox.x),
397  MAX(box1.minbox.y,box2.minbox.y),
398  MAX(box1.minbox.z,box2.minbox.z),
399  MIN(box1.maxbox.x,box2.maxbox.x),
400  MIN(box1.maxbox.y,box2.maxbox.y),
401  MIN(box1.maxbox.z,box2.maxbox.z));
402 }
403 
404 bool operator== (const csBox3& box1, const csBox3& box2)
405 {
406  return ( (box1.minbox.x == box2.minbox.x)
407  && (box1.minbox.y == box2.minbox.y)
408  && (box1.minbox.z == box2.minbox.z)
409  && (box1.maxbox.x == box2.maxbox.x)
410  && (box1.maxbox.y == box2.maxbox.y)
411  && (box1.maxbox.z == box2.maxbox.z) );
412 }
413 
414 bool operator!= (const csBox3& box1, const csBox3& box2)
415 {
416  return ( (box1.minbox.x != box2.minbox.x)
417  || (box1.minbox.y != box2.minbox.y)
418  || (box1.minbox.z != box2.minbox.z)
419  || (box1.maxbox.x != box2.maxbox.x)
420  || (box1.maxbox.y != box2.maxbox.y)
421  || (box1.maxbox.z != box2.maxbox.z) );
422 }
423 
424 bool operator< (const csBox3& box1, const csBox3& box2)
425 {
426  return ( (box1.minbox.x >= box2.minbox.x)
427  && (box1.minbox.y >= box2.minbox.y)
428  && (box1.minbox.z >= box2.minbox.z)
429  && (box1.maxbox.x <= box2.maxbox.x)
430  && (box1.maxbox.y <= box2.maxbox.y)
431  && (box1.maxbox.z <= box2.maxbox.z) );
432 }
433 
434 bool operator> (const csBox3& box1, const csBox3& box2)
435 {
436  return ( (box2.minbox.x >= box1.minbox.x)
437  && (box2.minbox.y >= box1.minbox.y)
438  && (box2.minbox.z >= box1.minbox.z)
439  && (box2.maxbox.x <= box1.maxbox.x)
440  && (box2.maxbox.y <= box1.maxbox.y)
441  && (box2.maxbox.z <= box1.maxbox.z) );
442 }
443 
444 bool operator< (const csVector3& point, const csBox3& box)
445 {
446  return ( (point.x >= box.minbox.x)
447  && (point.x <= box.maxbox.x)
448  && (point.y >= box.minbox.y)
449  && (point.y <= box.maxbox.y)
450  && (point.z >= box.minbox.z)
451  && (point.z <= box.maxbox.z) );
452 }
453 
454 //---------------------------------------------------------------------------