Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   Related Pages  

sglBoxBound.hpp

00001 /*****************************************************************************
00002  * SGL: A Scene Graph Library
00003  *
00004  * Copyright (C) 1997-2001  Scott McMillan   All Rights Reserved.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public
00017  * License along with this library; if not, write to the Free
00018  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *****************************************************************************
00020  *     File: sglBoxBound.hpp
00021  *  Created: 14 November 1998
00022  *  Summary: bounding boxes for sglGeoSets
00023  *****************************************************************************/
00024 
00025 #ifndef __SGL_BOX_BOUND_HPP
00026 #define __SGL_BOX_BOUND_HPP
00027 
00028 #include <sgl.h>
00029 #include <sglVector.hpp>
00030 #include <sglBound.hpp>
00031 #include <sglPlane.hpp>
00032 #include <sglPolytope.hpp>
00033 #include <sglSegment.hpp>
00034 
00035 class SGL_DLL_API sglBoxBound : public sglBound
00036 {
00037 public:
00038    sglBoxBound();
00039    sglBoxBound(const sglBoxBound &);
00040    sglBoxBound &operator=(const sglBoxBound &);
00041 
00042    ~sglBoxBound() {};
00043 
00044    void makeEmpty();
00045    bool isEmpty() const { return (m_min[0]>m_max[0]); }
00046 
00047    // ---------------------------------------------------------
00048    // get/set min and max
00049    void setMin(float x, float y, float z) { m_min.set(x,y,z); }
00050    void setMin(const sglVec3f &min) { m_min = min; }
00051    const sglVec3f &getMin() const   { return m_min; }
00052 
00053    void setMax(float x, float y, float z) { m_max.set(x,y,z); }
00054    void setMax(const sglVec3f &max) { m_max = max; }
00055    const sglVec3f &getMax() const   { return m_max; }
00056 
00057    // ---------------------------------------------------------
00058    // generating bounding boxes from other volumes
00059    void expandToInclude(const sglVec3f & point);  // assumes min/max set
00060    void expandToInclude(const sglBoxBound &box);
00061    static void expandToInclude2s(sglBoxBound *bbox, const void *ptr);
00062    static void expandToInclude2i(sglBoxBound *bbox, const void *ptr);
00063    static void expandToInclude2f(sglBoxBound *bbox, const void *ptr);
00064    static void expandToInclude2d(sglBoxBound *bbox, const void *ptr);
00065    static void expandToInclude3s(sglBoxBound *bbox, const void *ptr);
00066    static void expandToInclude3i(sglBoxBound *bbox, const void *ptr);
00067    static void expandToInclude3f(sglBoxBound *bbox, const void *ptr);
00068    static void expandToInclude3d(sglBoxBound *bbox, const void *ptr);
00069    static void expandToInclude4s(sglBoxBound *bbox, const void *ptr);
00070    static void expandToInclude4i(sglBoxBound *bbox, const void *ptr);
00071    static void expandToInclude4f(sglBoxBound *bbox, const void *ptr);
00072    static void expandToInclude4d(sglBoxBound *bbox, const void *ptr);
00073 
00074    typedef void (*ExpandToIncludeFunc)(sglBoxBound *, const void *vtx);
00075 
00076    // Get the expandToInclude function for the given vertex data type.
00077    static ExpandToIncludeFunc getExpandToIncludeFunc(int vertex_type)
00078       { return s_expand_to_include_func_table[vertex_type]; }
00079 
00080    // ---------------------------------------------------------
00081    // intersection routines
00082 
00083    // Adapted from "Fast Ray-Box Intersection" by Andrew Woo
00084    // from _Graphics Gems_, Academic Press, 1990
00085    template <class S>
00086    IntersectResultEnum intersect(sglSegment<S> &ray) const
00087       {
00088          // check special case of empty bounding box
00089          if (isEmpty()) return eOUTSIDE;
00090 
00091          enum LocationEnum {eRIGHT = 0, eLEFT = 1, eMIDDLE = 2};
00092          int quadrant[3];
00093          register unsigned int i;
00094          unsigned int whichPlane;
00095          sglVec3<S> maxT;
00096          sglVec3<S> candidatePlane;
00097          sglVec3<S> coord;
00098 
00099          // The following is inefficient, but simplifies the code for
00100          // the time being 
00101          sglVec3<S> origin(ray.getPos());
00102          sglVec3<S> dir(ray.getDir());
00103 
00104          // Find candidate planes; i.e. sides of box facing the origin
00105          // of the ray (also detects is ray starts inside the bbox
00106          bool inside = TRUE;
00107          for (i=0; i<3; i++)
00108          {
00109             if (origin[i] < m_min[i])
00110             {
00111                quadrant[i] = eLEFT;
00112                candidatePlane[i] = m_min[i];
00113                inside = FALSE;
00114             }
00115             else if (origin[i] > m_max[i])
00116             {
00117                quadrant[i] = eRIGHT;
00118                candidatePlane[i] = m_max[i];
00119                inside = FALSE;
00120             }
00121             else
00122             {
00123                quadrant[i] = eMIDDLE;
00124             }
00125          }
00126 
00127          // Ray origin inside bounding box
00128          if (inside)
00129          {
00130             return eINSIDE;
00131          }
00132 
00133 
00134          // Calculate T distances to candidate planes 
00135          for (i = 0; i < 3; i++)
00136          {
00137             if ((quadrant[i] != eMIDDLE) && (dir[i] != 0.))
00138                maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
00139             else
00140                maxT[i] = -1.;
00141          }
00142 
00143          // Get largest of the maxT's for final choice of intersection 
00144          whichPlane = 0;
00145          for (i = 1; i < 3; i++)
00146          {
00147             if (maxT[whichPlane] < maxT[i])
00148             {
00149                whichPlane = i;
00150             }
00151          }
00152 
00153          // Check final candidate actually inside box
00154          if (maxT[whichPlane] < 0. || maxT[whichPlane] > ray.getLen())
00155          {
00156             return eOUTSIDE;
00157          }
00158 
00159          for (i = 0; i < 3; i++)
00160          {
00161             if (whichPlane != i)
00162             {
00163                coord[i] = origin[i] + maxT[whichPlane] *dir[i];
00164                if (coord[i] < m_min[i] || coord[i] > m_max[i])
00165                {
00166                   return eOUTSIDE;
00167                }
00168             }
00169             else
00170             {
00171                coord[i] = candidatePlane[i];
00172             }
00173          }
00174 
00175          ray.setLen(maxT[whichPlane]);
00176          return eINTERSECT;            // ray hits box 
00177       }
00178 
00179 
00180    template <class S>
00181    IntersectResultEnum intersect(const sglPlane<S> &plane) const 
00182       {
00183          // empty box is not intersected
00184          if (m_max[0] < m_min[0])
00185             return eOUTSIDE;
00186 
00187          // find the extremities
00188          sglVec3f vmin, vmax;
00189          sglVec3f pnorm = plane.getNormal();
00190 
00191          if (pnorm[0] > 0.f)
00192          {
00193             vmin[0] = m_min[0];
00194             vmax[0] = m_max[0];
00195          }
00196          else
00197          {
00198             vmin[0] = m_max[0];
00199             vmax[0] = m_min[0];
00200          }
00201 
00202          if (pnorm[1] > 0.f)
00203          {
00204             vmin[1] = m_min[1];
00205             vmax[1] = m_max[1];
00206          }
00207          else
00208          {
00209             vmin[1] = m_max[1];
00210             vmax[1] = m_min[1];
00211          }
00212 
00213          if (pnorm[2] > 0.f)
00214          {
00215             vmin[2] = m_min[2];
00216             vmax[2] = m_max[2];
00217          }
00218          else
00219          {
00220             vmin[2] = m_max[2];
00221             vmax[2] = m_min[2];
00222          }
00223 
00224          // now lets do the math
00225          if (plane.signedDistance(vmax) < 0.f)
00226             return eOUTSIDE;
00227          else if (plane.signedDistance(vmin) >= 0.f)
00228             return eINSIDE;
00229          else 
00230             return eINTERSECT;
00231       }
00232 
00233    template <class S>
00234    IntersectResultEnum intersect(const sglPolytope<S> &ptope) const 
00235       {
00236          bool intersect_flag = false;
00237 
00238          for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00239          {
00240             IntersectResultEnum result = intersect(ptope.getPlane(i));
00241             if (result == eOUTSIDE)
00242             {
00243                return eOUTSIDE;
00244             }
00245             else if (result == eINTERSECT)
00246             {
00247                intersect_flag = true;
00248             }
00249          }
00250 
00251          if (!intersect_flag)
00252          {
00253             return eINSIDE;
00254          }
00255 
00256          // note: this is not optimal as we may be outside at a corner and
00257          // still return Intersect
00258          return eINTERSECT;
00259       }
00260 
00261 #if 1 //defined(WIN32)
00262    template <class S>
00263    IntersectResultEnum intersect(const sglPolytope<S> &ptope,
00264                                  unsigned int &plane_flags) const 
00265       {
00266          unsigned int cull_flags = 0;
00267 
00268          for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00269          {
00270             // only check those planes that intersected the previous
00271             // bounding volume 
00272             if (plane_flags & (1<<i))
00273             {
00274                IntersectResultEnum result = intersect(ptope.getPlane(i));
00275                if (result == eOUTSIDE)
00276                {
00277                   plane_flags=0;
00278                   return eOUTSIDE;
00279                }
00280                else if (result == eINTERSECT)
00281                {
00282                   cull_flags |= (1<<i);
00283                }
00284             }
00285          }
00286 
00287          if (cull_flags == 0)
00288          {
00289             plane_flags=0;
00290             return eINSIDE;
00291          }
00292 
00293          // note: this is not optimal as we may be outside at a corner and
00294          // still return Intersect
00295          plane_flags = cull_flags;
00296          return eINTERSECT;
00297       }
00298 #else
00299    IntersectResultEnum intersect(const sglPolytope<float> &ptope,
00300                                  unsigned int &plane_flags) const 
00301       {
00302          unsigned int cull_flags = 0;
00303 
00304          for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00305          {
00306             // only check those planes that intersected the previous
00307             // bounding volume 
00308             if (plane_flags & (1<<i))
00309             {
00310                IntersectResultEnum result = intersect(ptope.getPlane(i));
00311                if (result == eOUTSIDE)
00312                {
00313                   plane_flags=0;
00314                   return eOUTSIDE;
00315                }
00316                else if (result == eINTERSECT)
00317                {
00318                   cull_flags |= (1<<i);
00319                }
00320             }
00321          }
00322 
00323          if (cull_flags == 0)
00324          {
00325             plane_flags=0;
00326             return eINSIDE;
00327          }
00328 
00329          // note: this is not optimal as we may be outside at a corner and
00330          // still return Intersect
00331          plane_flags = cull_flags;
00332          return eINTERSECT;
00333       }
00334 
00335    IntersectResultEnum intersect(const sglPolytope<double> &ptope,
00336                                  unsigned int &plane_flags) const 
00337       {
00338          unsigned int cull_flags = 0;
00339 
00340          for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00341          {
00342             // only check those planes that intersected the previous
00343             // bounding volume 
00344             if (plane_flags & (1<<i))
00345             {
00346                IntersectResultEnum result = intersect(ptope.getPlane(i));
00347                if (result == eOUTSIDE)
00348                {
00349                   plane_flags=0;
00350                   return eOUTSIDE;
00351                }
00352                else if (result == eINTERSECT)
00353                {
00354                   cull_flags |= (1<<i);
00355                }
00356             }
00357          }
00358 
00359          if (cull_flags == 0)
00360          {
00361             plane_flags=0;
00362             return eINSIDE;
00363          }
00364 
00365          // note: this is not optimal as we may be outside at a corner and
00366          // still return Intersect
00367          plane_flags = cull_flags;
00368          return eINTERSECT;
00369       }
00370 #endif
00371 
00372    // ---------------------------------------------------------
00373    // Informational output
00374    void drawImmediate() const;
00375    void drawOcclusionBox() const;
00376 
00377    friend SGL_DLL_API ostream &operator<<(ostream &ostrm,
00378                                           const sglBoxBound &box);
00379 
00380 private:
00381    static ExpandToIncludeFunc s_expand_to_include_func_table[24];
00382 
00383    sglVec3f m_min;
00384    sglVec3f m_max;
00385 };
00386 
00387 SGL_DLL_API ostream &operator<<(ostream &ostrm, const sglBoxBound &box);
00388 
00389 #endif

Generated at Mon Jul 1 18:00:04 2002 for SGL by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001