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

Revision 2582, 10.6 KB checked in by bittner, 16 years ago (diff)

Havran Ray Caster compiles and links, but still does not work

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  // Test if the box is really sensefull
150  bool IsCorrect();
151
152  // Overlap returns 1 if the two axis-aligned boxes overlap .. only strongly
153  friend inline bool OverlapS(const SBBox &, const SBBox &);
154 
155protected:
156  // pp[0] is minimum, pp[1] is maximum
157  Vector3 pp[2];
158};
159
160// --------------------------------------------------------
161// Inline functions
162
163inline void
164SBBox::Include(const AxisAlignedBox3 &bbox)
165{
166  Minimize(pp[0], bbox.Min());
167  Maximize(pp[1], bbox.Max());
168}
169
170inline void
171SBBox::Include(const SBBox &bbox)
172{
173  Minimize(pp[0], bbox.pp[0]);
174  Maximize(pp[1], bbox.pp[1]);
175}
176
177inline bool
178SBBox::Equal(const SBBox &b, float eps) const
179{
180  if ( (!EpsilonEqual(pp[0].x, b.pp[0].x, eps)) ||
181       (!EpsilonEqual(pp[0].y, b.pp[0].y, eps)) ||
182       (!EpsilonEqual(pp[0].z, b.pp[0].z, eps)) ||
183       (!EpsilonEqual(pp[1].x, b.pp[1].x, eps)) ||
184       (!EpsilonEqual(pp[1].y, b.pp[1].y, eps)) ||
185       (!EpsilonEqual(pp[1].z, b.pp[1].z, eps)) )
186    return false; // they are not equal
187  return true;
188}
189
190inline bool
191SBBox::IsCorrect()
192{
193  if ( (pp[0].x > pp[1].x) ||
194       (pp[0].y > pp[1].y) ||
195       (pp[0].z > pp[1].z) )
196    return false; // box is not formed
197  return true;
198}
199
200inline bool
201OverlapS(const SBBox &x, const SBBox &y)
202{
203  if (x.pp[1].x <= y.pp[0].x ||
204      x.pp[0].x >= y.pp[1].x ||
205      x.pp[1].y <= y.pp[0].y ||
206      x.pp[0].y >= y.pp[1].y ||
207      x.pp[1].z <= y.pp[0].z ||
208      x.pp[0].z >= y.pp[1].z) {
209    return false;
210  }
211  return true;
212}
213
214// Returns true if the boxes are either disjoint or only
215// share a single face !
216inline bool
217SBBox::ExcludesPartially(const SBBox &b) const
218{
219  if (b.pp[1].x <= pp[0].x ||
220      b.pp[1].y <= pp[0].y ||
221      b.pp[1].z <= pp[0].z ||
222      b.pp[0].x >= pp[1].x ||
223      b.pp[0].y >= pp[1].y ||
224      b.pp[0].z >= pp[1].z)
225    // box 'b' is not fully contained in 'this', also true when neighboring faces
226    return true;
227  return false; // box 'b' contained in this box
228}
229
230inline bool
231SBBox::Includes(const Vector3 &vec) const
232{
233  if (vec.x < pp[0].x ||
234      vec.x > pp[1].x ||
235      vec.y < pp[0].y ||
236      vec.y > pp[1].y ||
237      vec.z < pp[0].z ||
238      vec.z > pp[1].z) {
239    return false;
240  }
241  return true;
242}
243
244inline bool
245SBBox::IncludesS(const Vector3 &vec) const
246{
247  if (vec.x <= pp[0].x ||
248      vec.x >= pp[1].x ||
249      vec.y <= pp[0].y ||
250      vec.y >= pp[1].y ||
251      vec.z <= pp[0].z ||
252      vec.z >= pp[1].z) {
253    return false;
254  }
255  return true;
256}
257
258inline bool
259SBBox::IncludesS(const Vector3 &vec, float eps) const
260{
261  if (vec.x <= (pp[0].x-eps) ||
262      vec.x >= (pp[1].x+eps) ||
263      vec.y <= (pp[0].y-eps) ||
264      vec.y >= (pp[1].y+eps) ||
265      vec.z <= (pp[0].z-eps) ||
266      vec.z >= (pp[1].z+eps) ) {
267    return false; // outside
268  }
269  return true; // point inside
270}
271
272// Function describing the box
273extern void
274Describe(const SBBox &b, std::ostream &app, int indent);
275
276// Function describing the box
277extern void
278DescribeXYZ(const SBBox &b, std::ostream &app, int indent);
279
280#if 1
281// The implementation I, the first version implemented by Vlastimil
282// Havran, without looking into the literature
283inline bool
284SBBox::RayIntersect(const SimpleRay &ray,
285                    float &tmin, float &tmax) const
286{
287   float interval_min = tmin;
288   float interval_max = tmax;
289
290   const Vector3 &rayLoc = ray.mOrigin;
291   const Vector3 &rayDir = ray.mDirection;
292   
293   float t0, t1;
294   if (rayDir.x > 0) {
295     t0 = (pp[0].x - rayLoc.x) / rayDir.x;
296     t1 = (pp[1].x - rayLoc.x) / rayDir.x;
297   }
298   else {
299     t0 = (pp[1].x - rayLoc.x) / rayDir.x;
300     t1 = (pp[0].x - rayLoc.x) / rayDir.x;
301   }
302   assert(t0 <= t1);     
303   if (t0 > interval_min)
304     interval_min = t0;
305   if (t1 < interval_max)
306     interval_max = t1;
307   if (interval_min > interval_max)
308     return false;
309
310   if (rayDir.y > 0) {
311     t0 = (pp[0].y - rayLoc.y) / rayDir.y;
312     t1 = (pp[1].y - rayLoc.y) / rayDir.y;
313   }
314   else {
315     t0 = (pp[1].y - rayLoc.y) / rayDir.y;
316     t1 = (pp[0].y - rayLoc.y) / rayDir.y;
317   }
318   assert(t0 <= t1);     
319   if (t0 > interval_min)
320     interval_min = t0;
321   if (t1 < interval_max)
322     interval_max = t1;
323   if (interval_min > interval_max)
324     return false;
325
326   if (rayDir.z > 0) {
327     t0 = (pp[0].z - rayLoc.z) / rayDir.z;
328     t1 = (pp[1].z - rayLoc.z) / rayDir.z;
329   }
330   else {
331     t0 = (pp[1].z - rayLoc.z) / rayDir.z;
332     t1 = (pp[0].z - rayLoc.z) / rayDir.z;
333   }
334   assert(t0 <= t1);     
335   if (t0 > interval_min)
336     interval_min = t0;
337   if (t1 < interval_max)
338     interval_max = t1;
339
340   // return true if the box is intersected
341   // return false if not intersected by ray
342   if ( (interval_max > 0.0f) &&
343        (interval_min <= interval_max) ) {
344     // yes, intersected, update tmin and tmax for current node
345     tmin = interval_min;
346     tmax = interval_max;
347     return true; // intersected
348   }
349   return false; // not intersected
350}
351#endif
352
353#if 1
354// Here we compute exit signed distance along the ray
355// from the box
356inline void
357SBBox::ComputeMaxT(const SimpleRay &ray,
358                   float &tmax) const
359{
360  float interval_max = tmax;
361
362  const Vector3 &rayLoc = ray.mOrigin;
363  const Vector3 &rayDir = ray.mDirection;
364 
365  float t;
366  assert(pp[1].x >= pp[0].x);
367  if (rayDir.x > 0)
368    t = (pp[1].x - rayLoc.x) / rayDir.x;
369  else
370    t = (pp[0].x - rayLoc.x) / rayDir.x;
371  if (t > interval_max)
372    interval_max = t;
373  assert(pp[1].y >= pp[0].y);
374  if (rayDir.y > 0)
375    t = (pp[1].y - rayLoc.y) / rayDir.y;
376  else
377    t = (pp[0].y - rayLoc.y) / rayDir.y;
378  if (t > interval_max)
379    interval_max = t;
380  assert(pp[1].z >= pp[0].z);
381  if (rayDir.z > 0)
382    t = (pp[1].z - rayLoc.z) / rayDir.z;
383  else
384    t = (pp[0].z - rayLoc.z) / rayDir.z;
385  if (t > interval_max)
386    interval_max = t;
387}
388#endif
389
390#if 1
391// Here we compute entry signed distance along the ray
392// into the box
393inline void
394SBBox::ComputeMinT(const SimpleRay &ray,
395                   float &tmin) const
396{
397  float interval_min = tmin;
398
399  const Vector3 &rayLoc = ray.mOrigin;
400  const Vector3 &rayDir = ray.mDirection;
401 
402  float t;
403  assert(pp[1].x >= pp[0].x);
404  if (rayDir.x > 0)
405    t = (pp[0].x - rayLoc.x) / rayDir.x;
406  else
407    t = (pp[1].x - rayLoc.x) / rayDir.x;
408  if (t < interval_min)
409    interval_min = t;
410  assert(pp[1].y >= pp[0].y);
411  if (rayDir.y > 0)
412    t = (pp[0].y - rayLoc.y) / rayDir.y;
413  else
414    t = (pp[1].y - rayLoc.y) / rayDir.y;
415  if (t < interval_min)
416    interval_min = t;
417  assert(pp[1].z >= pp[0].z);
418  if (rayDir.z > 0)
419    t = (pp[0].z - rayLoc.z) / rayDir.z;
420  else
421    t = (pp[1].z - rayLoc.z) / rayDir.z;
422  if (t < interval_min)
423    interval_min = t;
424}
425#endif
426
427}
428
429#endif // __SBBOX_H__
Note: See TracBrowser for help on using the repository browser.