source: GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.h @ 2629

Revision 2629, 11.0 KB checked in by bittner, 17 years ago (diff)

commit after merge with vlastimil

Line 
1// ===================================================================
2// $Id: sbbox.h $
3//
4// sbbox.h
5//
6// Class: SBBox
7//
8// REPLACEMENT_STRING
9//
10// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
11// Initial coding by Vlasta Havran, December 2005
12
13#ifndef __SBBOX_H__
14#define __SBBOX_H__
15
16// ANSI C++ headers
17#include <cassert>
18#include <iostream>
19#include <ostream>
20
21// GOLEM headers
22#include "configh.h"
23#include "common.h"
24#include "AxisAlignedBox3.h"
25#include "SimpleRay.h"
26#include "Vector3.h"
27
28namespace GtpVisibilityPreprocessor {
29
30// Forward declarations
31
32// --------------------------------------------------------
33// The definition of the bounding box having 24 Bytes only
34struct SBBox
35{
36public:
37  SBBox() {}
38  SBBox(const Vector3 &a, const Vector3 &b) {
39    pp[0] = a; pp[1] = b;
40  }
41  // member functions
42  const Vector3& Min() const { return pp[0]; }
43  const Vector3& Max() const { return pp[1]; }
44  Vector3& Min() { return pp[0]; }
45  Vector3& Max() { return pp[1]; }
46  const float& Min(int i) const { return pp[0][i]; }
47  const float& Max(int i) const { return pp[1][i]; }
48  float& Min(int i) { return pp[0][i]; }
49  float& Max(int i) { return pp[1][i]; }
50
51  // Access to individual components, maybe it is not a good idea
52  const float& MinX() const { return pp[0].x; }
53  const float& MaxX() const { return pp[1].x; }
54  float& MinX() { return pp[0].x; }
55  float& MaxX() { return pp[1].x; }
56  const float& MinY() const { return pp[0].y; }
57  const float& MaxY() const { return pp[1].y; }
58  float& MinY() { return pp[0].y; }
59  float& MaxY() { return pp[1].y; }
60  const float& MinZ() const { return pp[0].z; }
61  const float& MaxZ() const { return pp[1].z; }
62  float& MinZ() { return pp[0].z; }
63  float& MaxZ() { return pp[1].z; }
64
65  void SetMin(float x, float y, float z) {
66    pp[0].x=x; pp[0].y=y; pp[0].z=z; }
67  void SetMax(float x, float y, float z) {
68    pp[1].x=x; pp[1].y=y; pp[1].z=z; }
69
70  // initialization to the non existing bounding box
71  inline void Initialize() {
72    pp[0] = Vector3(MAXFLOAT);
73    pp[1] = Vector3(-MAXFLOAT);
74  }
75  inline void Convert(const AxisAlignedBox3 &b) {
76    pp[0] = b.Min();
77    pp[1] = b.Max();
78  }
79  Vector3 Diagonal() const { return pp[1] - pp[0];}
80
81  // Compute the center of the box
82  void ComputeCentroid(Vector3 &c) const {
83    c.x = (pp[0].x + pp[1].x)*0.5f;
84    c.y = (pp[0].y + pp[1].y)*0.5f;
85    c.z = (pp[0].z + pp[1].z)*0.5f;
86  }
87
88  // Compute half of surface area of the box
89  float SA2() const {
90    float t1 = (pp[1].x-pp[0].x);
91    float t2 = (pp[1].y-pp[0].y);
92    float t3 = (pp[1].z-pp[0].z);
93    return t1*t2 + t2*t3 + t1*t3;
94  }
95  // Compute volume of the box
96  float GetVolume() const {
97    return (pp[1].x-pp[0].x)*(pp[1].y-pp[0].y)*(pp[1].z-pp[0].z);
98  }
99 
100  void SetMin(int axis, const float value) {
101    pp[0][axis] = value;
102  }
103  void SetMax(int axis, const float value) {
104    pp[1][axis] = value;
105  }
106  // Write acess to min and max
107  void SetMin(const Vector3& bmin) { pp[0] = bmin;}
108  void SetMax(const Vector3& bmax) { pp[1] = bmax;}
109 
110  // Decrease box by given splitting plane
111  void Reduce(int axis, int right, float value) {
112    if ( (value >= pp[0][axis]) && (value <= pp[1][axis]) ) {
113      if (right)
114        pp[0][axis] = value;
115      else
116        pp[1][axis] = value;
117    }
118  }
119  inline void Include(const AxisAlignedBox3 &bbox);
120  inline void Include(const SBBox  &bbox);
121  inline bool RayIntersect(const SimpleRay &r,
122                           float &tmin,
123                           float &tmax) const;
124
125  inline void ComputeMaxT(const SimpleRay &r,
126                          float &tmax) const;
127  inline void ComputeMinT(const SimpleRay &r,
128                          float &tmin) const;
129 
130  // Query functions
131
132  // Includes returns true if this box includes box b (completely)
133  bool Includes(const SBBox &b) const;
134  bool Includes(const SBBox &b, float eps) const;
135
136  // Returns false if the box 'b' is fully contained in 'this', see the code
137  inline bool ExcludesPartially(const SBBox &b) const;
138
139  // Returs true if this box includes a point
140  inline bool Includes(const Vector3 &vec) const;
141
142  // Includes returns true if this box includes box b including boundary
143  inline bool IncludesS(const Vector3 &vec) const;
144
145  inline bool IncludesS(const Vector3 &vec, float eps) const;
146
147  inline bool Equal(const SBBox &b, float eps = 0.f) const;
148
149  // Returns the intersection of two axis-aligned boxes.
150  friend inline SBBox Intersect(const SBBox &x, const SBBox &y);
151 
152  // Test if the box is really sensefull
153  bool IsCorrect();
154
155  // Overlap returns 1 if the two axis-aligned boxes overlap .. only strongly
156  friend inline bool OverlapS(const SBBox &, const SBBox &);
157 
158protected:
159  // pp[0] is minimum, pp[1] is maximum
160  Vector3 pp[2];
161};
162
163// --------------------------------------------------------
164// Inline functions
165
166inline void
167SBBox::Include(const AxisAlignedBox3 &bbox)
168{
169  Minimize(pp[0], bbox.Min());
170  Maximize(pp[1], bbox.Max());
171}
172
173inline void
174SBBox::Include(const SBBox &bbox)
175{
176  Minimize(pp[0], bbox.pp[0]);
177  Maximize(pp[1], bbox.pp[1]);
178}
179
180inline bool
181SBBox::Equal(const SBBox &b, float eps) const
182{
183  if ( (!EpsilonEqual(pp[0].x, b.pp[0].x, eps)) ||
184       (!EpsilonEqual(pp[0].y, b.pp[0].y, eps)) ||
185       (!EpsilonEqual(pp[0].z, b.pp[0].z, eps)) ||
186       (!EpsilonEqual(pp[1].x, b.pp[1].x, eps)) ||
187       (!EpsilonEqual(pp[1].y, b.pp[1].y, eps)) ||
188       (!EpsilonEqual(pp[1].z, b.pp[1].z, eps)) )
189    return false; // they are not equal
190  return true;
191}
192
193inline bool
194SBBox::IsCorrect()
195{
196  if ( (pp[0].x > pp[1].x) ||
197       (pp[0].y > pp[1].y) ||
198       (pp[0].z > pp[1].z) )
199    return false; // box is not formed
200  return true;
201}
202
203inline bool
204OverlapS(const SBBox &x, const SBBox &y)
205{
206  if (x.pp[1].x <= y.pp[0].x ||
207      x.pp[0].x >= y.pp[1].x ||
208      x.pp[1].y <= y.pp[0].y ||
209      x.pp[0].y >= y.pp[1].y ||
210      x.pp[1].z <= y.pp[0].z ||
211      x.pp[0].z >= y.pp[1].z) {
212    return false;
213  }
214  return true;
215}
216
217// Returns true if the boxes are either disjoint or only
218// share a single face !
219inline bool
220SBBox::ExcludesPartially(const SBBox &b) const
221{
222  if (b.pp[1].x <= pp[0].x ||
223      b.pp[1].y <= pp[0].y ||
224      b.pp[1].z <= pp[0].z ||
225      b.pp[0].x >= pp[1].x ||
226      b.pp[0].y >= pp[1].y ||
227      b.pp[0].z >= pp[1].z)
228    // box 'b' is not fully contained in 'this', also true when neighboring faces
229    return true;
230  return false; // box 'b' contained in this box
231}
232
233inline bool
234SBBox::Includes(const Vector3 &vec) const
235{
236  if (vec.x < pp[0].x ||
237      vec.x > pp[1].x ||
238      vec.y < pp[0].y ||
239      vec.y > pp[1].y ||
240      vec.z < pp[0].z ||
241      vec.z > pp[1].z) {
242    return false;
243  }
244  return true;
245}
246
247inline bool
248SBBox::IncludesS(const Vector3 &vec) const
249{
250  if (vec.x <= pp[0].x ||
251      vec.x >= pp[1].x ||
252      vec.y <= pp[0].y ||
253      vec.y >= pp[1].y ||
254      vec.z <= pp[0].z ||
255      vec.z >= pp[1].z) {
256    return false;
257  }
258  return true;
259}
260
261inline bool
262SBBox::IncludesS(const Vector3 &vec, float eps) const
263{
264  if (vec.x <= (pp[0].x-eps) ||
265      vec.x >= (pp[1].x+eps) ||
266      vec.y <= (pp[0].y-eps) ||
267      vec.y >= (pp[1].y+eps) ||
268      vec.z <= (pp[0].z-eps) ||
269      vec.z >= (pp[1].z+eps) ) {
270    return false; // outside
271  }
272  return true; // point inside
273}
274
275// Function describing the box
276extern void
277Describe(const SBBox &b, std::ostream &app, int indent);
278
279// Function describing the box
280extern void
281DescribeXYZ(const SBBox &b, std::ostream &app, int indent);
282
283inline SBBox
284Intersect(const SBBox &x, const SBBox &y)
285{
286  SBBox ret = x;
287  if (OverlapS(ret, y)) {
288    Maximize(ret.pp[0], y.pp[0]);
289    Minimize(ret.pp[1], y.pp[1]);
290    return ret;
291  }
292
293  // Null intersection.
294  return SBBox(Vector3(0), Vector3(0));
295}
296
297
298#if 1
299// The implementation I, the first version implemented by Vlastimil
300// Havran, without looking into the literature
301inline bool
302SBBox::RayIntersect(const SimpleRay &ray,
303                    float &tmin, float &tmax) const
304{
305   float interval_min = tmin;
306   float interval_max = tmax;
307
308   const Vector3 &rayLoc = ray.mOrigin;
309   const Vector3 &rayDir = ray.mDirection;
310   
311   float t0, t1;
312   if (rayDir.x > 0) {
313     t0 = (pp[0].x - rayLoc.x) / rayDir.x;
314     t1 = (pp[1].x - rayLoc.x) / rayDir.x;
315   }
316   else {
317     t0 = (pp[1].x - rayLoc.x) / rayDir.x;
318     t1 = (pp[0].x - rayLoc.x) / rayDir.x;
319   }
320   assert(t0 <= t1);     
321   if (t0 > interval_min)
322     interval_min = t0;
323   if (t1 < interval_max)
324     interval_max = t1;
325   if (interval_min > interval_max)
326     return false;
327
328   if (rayDir.y > 0) {
329     t0 = (pp[0].y - rayLoc.y) / rayDir.y;
330     t1 = (pp[1].y - rayLoc.y) / rayDir.y;
331   }
332   else {
333     t0 = (pp[1].y - rayLoc.y) / rayDir.y;
334     t1 = (pp[0].y - rayLoc.y) / rayDir.y;
335   }
336   assert(t0 <= t1);     
337   if (t0 > interval_min)
338     interval_min = t0;
339   if (t1 < interval_max)
340     interval_max = t1;
341   if (interval_min > interval_max)
342     return false;
343
344   if (rayDir.z > 0) {
345     t0 = (pp[0].z - rayLoc.z) / rayDir.z;
346     t1 = (pp[1].z - rayLoc.z) / rayDir.z;
347   }
348   else {
349     t0 = (pp[1].z - rayLoc.z) / rayDir.z;
350     t1 = (pp[0].z - rayLoc.z) / rayDir.z;
351   }
352   assert(t0 <= t1);     
353   if (t0 > interval_min)
354     interval_min = t0;
355   if (t1 < interval_max)
356     interval_max = t1;
357
358   // return true if the box is intersected
359   // return false if not intersected by ray
360   if ( (interval_max > 0.0f) &&
361        (interval_min <= interval_max) ) {
362     // yes, intersected, update tmin and tmax for current node
363     tmin = interval_min;
364     tmax = interval_max;
365     return true; // intersected
366   }
367   return false; // not intersected
368}
369#endif
370
371#if 1
372// Here we compute exit signed distance along the ray
373// from the box
374inline void
375SBBox::ComputeMaxT(const SimpleRay &ray,
376                   float &tmax) const
377{
378  float interval_max = tmax;
379
380  const Vector3 &rayLoc = ray.mOrigin;
381  const Vector3 &rayDir = ray.mDirection;
382 
383  float t;
384  assert(pp[1].x >= pp[0].x);
385  if (rayDir.x > 0)
386    t = (pp[1].x - rayLoc.x) / rayDir.x;
387  else
388    t = (pp[0].x - rayLoc.x) / rayDir.x;
389  if (t > interval_max)
390    interval_max = t;
391  assert(pp[1].y >= pp[0].y);
392  if (rayDir.y > 0)
393    t = (pp[1].y - rayLoc.y) / rayDir.y;
394  else
395    t = (pp[0].y - rayLoc.y) / rayDir.y;
396  if (t > interval_max)
397    interval_max = t;
398  assert(pp[1].z >= pp[0].z);
399  if (rayDir.z > 0)
400    t = (pp[1].z - rayLoc.z) / rayDir.z;
401  else
402    t = (pp[0].z - rayLoc.z) / rayDir.z;
403  if (t > interval_max)
404    interval_max = t;
405}
406#endif
407
408#if 1
409// Here we compute entry signed distance along the ray
410// into the box
411inline void
412SBBox::ComputeMinT(const SimpleRay &ray,
413                   float &tmin) const
414{
415  float interval_min = tmin;
416
417  const Vector3 &rayLoc = ray.mOrigin;
418  const Vector3 &rayDir = ray.mDirection;
419 
420  float t;
421  assert(pp[1].x >= pp[0].x);
422  if (rayDir.x > 0)
423    t = (pp[0].x - rayLoc.x) / rayDir.x;
424  else
425    t = (pp[1].x - rayLoc.x) / rayDir.x;
426  if (t < interval_min)
427    interval_min = t;
428  assert(pp[1].y >= pp[0].y);
429  if (rayDir.y > 0)
430    t = (pp[0].y - rayLoc.y) / rayDir.y;
431  else
432    t = (pp[1].y - rayLoc.y) / rayDir.y;
433  if (t < interval_min)
434    interval_min = t;
435  assert(pp[1].z >= pp[0].z);
436  if (rayDir.z > 0)
437    t = (pp[0].z - rayLoc.z) / rayDir.z;
438  else
439    t = (pp[1].z - rayLoc.z) / rayDir.z;
440  if (t < interval_min)
441    interval_min = t;
442}
443#endif
444
445
446}
447
448#endif // __SBBOX_H__
Note: See TracBrowser for help on using the repository browser.