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

panda/src/mathutil/boundingHexahedron.cxx

Go to the documentation of this file.
00001 // Filename: boundingHexahedron.cxx
00002 // Created by:  drose (03Oct99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "boundingHexahedron.h"
00020 #include "boundingSphere.h"
00021 #include "config_mathutil.h"
00022 
00023 #include <math.h>
00024 #include <algorithm>
00025 
00026 TypeHandle BoundingHexahedron::_type_handle;
00027 
00028 BoundingHexahedron::
00029 BoundingHexahedron(const Frustumf &frustum, bool is_ortho,
00030                    CoordinateSystem cs) {
00031   if (cs == CS_default) {
00032     cs = default_coordinate_system;
00033   }
00034 
00035   float fs = 1.0f;
00036   if (!is_ortho) {
00037     fs = frustum._ffar / frustum._fnear;
00038   }
00039 
00040   // We build the points based on a Z-up right-handed frustum.  If the
00041   // requested coordinate system is otherwise, we'll convert it in a
00042   // second pass.
00043   _points[0].set(frustum._l * fs, frustum._ffar, frustum._b * fs);
00044   _points[1].set(frustum._r * fs, frustum._ffar, frustum._b * fs);
00045   _points[2].set(frustum._r * fs, frustum._ffar, frustum._t * fs);
00046   _points[3].set(frustum._l * fs, frustum._ffar, frustum._t * fs);
00047   _points[4].set(frustum._l, frustum._fnear, frustum._b);
00048   _points[5].set(frustum._r, frustum._fnear, frustum._b);
00049   _points[6].set(frustum._r, frustum._fnear, frustum._t);
00050   _points[7].set(frustum._l, frustum._fnear, frustum._t);
00051 
00052   _flags = 0;
00053 
00054   // Now fix the coordinate system, if necessary.
00055   if (cs == CS_zup_right) {
00056     set_centroid();
00057     set_planes();
00058   } else {
00059     xform(LMatrix4f::convert_mat(CS_zup_right, cs));
00060   }
00061 }
00062 
00063 BoundingHexahedron::
00064 BoundingHexahedron(const LPoint3f &fll, const LPoint3f &flr,
00065                    const LPoint3f &fur, const LPoint3f &ful,
00066                    const LPoint3f &nll, const LPoint3f &nlr,
00067                    const LPoint3f &nur, const LPoint3f &nul) {
00068   _points[0] = fll;
00069   _points[1] = flr;
00070   _points[2] = fur;
00071   _points[3] = ful;
00072   _points[4] = nll;
00073   _points[5] = nlr;
00074   _points[6] = nur;
00075   _points[7] = nul;
00076 
00077   _flags = 0;
00078   set_centroid();
00079   set_planes();
00080 }
00081 
00082 BoundingVolume *BoundingHexahedron::
00083 make_copy() const {
00084   return new BoundingHexahedron(*this);
00085 }
00086 
00087 LPoint3f BoundingHexahedron::
00088 get_min() const {
00089   nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
00090   nassertr(!is_infinite(), LPoint3f(0.0f, 0.0f, 0.0f));
00091   int i;
00092   LPoint3f m = _points[0];
00093   for (i = 1; i < num_points; i++) {
00094     m.set(min(m[0], _points[i][0]),
00095           min(m[1], _points[i][1]),
00096           min(m[2], _points[i][2]));
00097   }
00098   return m;
00099 }
00100 
00101 LPoint3f BoundingHexahedron::
00102 get_max() const {
00103   nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
00104   nassertr(!is_infinite(), LPoint3f(0.0f, 0.0f, 0.0f));
00105   int i;
00106   LPoint3f m = _points[0];
00107   for (i = 1; i < num_points; i++) {
00108     m.set(max(m[0], _points[i][0]),
00109           max(m[1], _points[i][1]),
00110           max(m[2], _points[i][2]));
00111   }
00112   return m;
00113 }
00114 
00115 LPoint3f BoundingHexahedron::
00116 get_approx_center() const {
00117   nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
00118   nassertr(!is_infinite(), LPoint3f(0.0f, 0.0f, 0.0f));
00119   return _centroid;
00120 }
00121 
00122 void BoundingHexahedron::
00123 xform(const LMatrix4f &mat) {
00124   if (!is_empty() && !is_infinite()) {
00125     for (int i = 0; i < num_points; i++) {
00126       _points[i] = _points[i] * mat;
00127     }
00128     set_centroid();
00129     set_planes();
00130   }
00131 }
00132 
00133 void BoundingHexahedron::
00134 output(ostream &out) const {
00135   if (is_empty()) {
00136     out << "bhexahedron, empty";
00137   } else if (is_infinite()) {
00138     out << "bhexahedron, infinite";
00139   } else {
00140     out << "bhexahedron, min " << get_min() << " max " << get_max();
00141   }
00142 }
00143 
00144 void BoundingHexahedron::
00145 write(ostream &out, int indent_level) const {
00146   if (is_empty()) {
00147     indent(out, indent_level) << "bhexahedron, empty\n";
00148   } else if (is_infinite()) {
00149     out << "bhexahedron, infinite\n";
00150   } else {
00151     indent(out, indent_level)
00152       << "bhexahedron, min " << get_min() << " max " << get_max() << ":\n";
00153     int i;
00154     for (i = 0; i < num_points; i++) {
00155       indent(out, indent_level + 2) << _points[i] << "\n";
00156     }
00157     indent(out, indent_level + 2) << "centroid is " << _centroid << "\n";
00158   }
00159 }
00160 
00161 bool BoundingHexahedron::
00162 extend_other(BoundingVolume *other) const {
00163   return other->extend_by_hexahedron(this);
00164 }
00165 
00166 bool BoundingHexahedron::
00167 around_other(BoundingVolume *other,
00168              const BoundingVolume **first,
00169              const BoundingVolume **last) const {
00170   return other->around_hexahedrons(first, last);
00171 }
00172 
00173 int BoundingHexahedron::
00174 contains_other(const BoundingVolume *other) const {
00175   return other->contains_hexahedron(this);
00176 }
00177 
00178 
00179 bool BoundingHexahedron::
00180 extend_by_point(const LPoint3f &) {
00181   mathutil_cat.error()
00182     << "BoundingHexahedron::extend_by_point() called\n";
00183   return false;
00184 }
00185 
00186 bool BoundingHexahedron::
00187 extend_by_sphere(const BoundingSphere *) {
00188   mathutil_cat.error()
00189     << "BoundingHexahedron::extend_by_sphere() called\n";
00190   return false;
00191 }
00192 
00193 bool BoundingHexahedron::
00194 extend_by_hexahedron(const BoundingHexahedron *) {
00195   mathutil_cat.error()
00196     << "BoundingHexahedron::extend_by_hexahedron() called\n";
00197   return false;
00198 }
00199 
00200 bool BoundingHexahedron::
00201 around_points(const LPoint3f *, const LPoint3f *) {
00202   mathutil_cat.error()
00203     << "BoundingHexahedron::around_points() called\n";
00204   return false;
00205 }
00206 
00207 bool BoundingHexahedron::
00208 around_spheres(const BoundingVolume **,
00209                const BoundingVolume **) {
00210   mathutil_cat.error()
00211     << "BoundingHexahedron::around_spheres() called\n";
00212   return false;
00213 }
00214 
00215 bool BoundingHexahedron::
00216 around_hexahedrons(const BoundingVolume **,
00217                    const BoundingVolume **) {
00218   mathutil_cat.error()
00219     << "BoundingHexahedron::around_hexahedrons() called\n";
00220   return false;
00221 }
00222 
00223 int BoundingHexahedron::
00224 contains_point(const LPoint3f &point) const {
00225   if (is_empty()) {
00226     return IF_no_intersection;
00227 
00228   } else if (is_infinite()) {
00229     return IF_possible | IF_some | IF_all;
00230 
00231   } else {
00232     // The hexahedron contains the point iff the point is behind all of
00233     // the planes.
00234     for (int i = 0; i < num_planes; i++) {
00235       const Planef &p = _planes[i];
00236       if (p.dist_to_plane(point) > 0.0f) {
00237         return IF_no_intersection;
00238       }
00239     }
00240     return IF_possible | IF_some | IF_all;
00241   }
00242 }
00243 
00244 int BoundingHexahedron::
00245 contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
00246   if (is_empty()) {
00247     return IF_no_intersection;
00248 
00249   } else if (is_infinite()) {
00250     return IF_possible | IF_some | IF_all;
00251 
00252   } else {
00253     // The hexahedron does not contains the line segment if both points
00254     // are in front of any one plane.
00255     for (int i = 0; i < num_planes; i++) {
00256       const Planef &p = _planes[i];
00257       if (p.dist_to_plane(a) > 0.0f ||
00258           p.dist_to_plane(b) > 0.0f) {
00259         return IF_no_intersection;
00260       }
00261     }
00262 
00263     // If there is no plane that both points are in front of, the
00264     // hexahedron may or may not contain the line segment.  For the
00265     // moment, we won't bother to check that more thoroughly, though.
00266     return IF_possible;
00267   }
00268 }
00269 
00270 int BoundingHexahedron::
00271 contains_sphere(const BoundingSphere *sphere) const {
00272   nassertr(!is_empty(), 0);
00273 
00274   // The hexahedron contains the sphere iff the sphere is at least
00275   // partly behind all of the planes.
00276   const LPoint3f &center = sphere->get_center();
00277   float radius = sphere->get_radius();
00278 
00279   int result = IF_possible | IF_some | IF_all;
00280 
00281   for (int i = 0; i < num_planes; i++) {
00282     const Planef &p = _planes[i];
00283     float dist = p.dist_to_plane(center);
00284 
00285     if (dist > radius) {
00286       // The sphere is completely in front of this plane; it's thus
00287       // completely outside of the hexahedron.
00288       return IF_no_intersection;
00289 
00290     } else if (dist > -radius) {
00291       // The sphere is not completely behind this plane, but some of
00292       // it is.
00293       result &= ~IF_all;
00294     }
00295   }
00296 
00297   return result;
00298 }
00299 
00300 int BoundingHexahedron::
00301 contains_hexahedron(const BoundingHexahedron *hexahedron) const {
00302   nassertr(!is_empty(), 0);
00303   nassertr(!hexahedron->is_empty(), 0);
00304 
00305   // Check minmax.
00306   LPoint3f min1 = get_min();
00307   LPoint3f min2 = hexahedron->get_min();
00308   LPoint3f max1 = get_max();
00309   LPoint3f max2 = hexahedron->get_max();
00310 
00311   if (min1[0] > max2[0] || min1[1] > max2[1] || min1[2] > max2[2] ||
00312       min2[0] > max1[0] || min2[1] > max1[1] || min2[2] > max1[2] ||
00313       max1[0] < min2[0] || max1[1] < min2[1] || max1[2] < min2[2] ||
00314       max2[0] < min1[0] || max2[1] < min1[1] || max2[2] < min1[2]) {
00315     return IF_no_intersection;
00316   }
00317 
00318   int result = IF_possible | IF_all;
00319 
00320   for (int i = 0; i < num_points; i++) {
00321     if (contains_point(hexahedron->_points[i])) {
00322       result |= IF_some;
00323     } else {
00324       result &= ~IF_all;
00325     }
00326   }
00327 
00328   return result;
00329 }
00330 
00331 void BoundingHexahedron::
00332 set_planes() {
00333   _planes[0] = Planef(_points[0], _points[3], _points[2]);
00334 
00335   // Test to see if we have accidentally inverted our frustum by
00336   // transforming it with a -1 matrix.  We do this by ensuring that
00337   // the centroid is in front of all of the planes (actually, we only
00338   // need to test the first plane).
00339   if (_planes[0].dist_to_plane(_centroid) > 0) {
00340     // Oops!  We're flipped!  Rebuild the planes in the opposite
00341     // direction.
00342     _planes[0] = Planef(_points[0], _points[2], _points[3]);
00343     _planes[1] = Planef(_points[0], _points[5], _points[1]);
00344     _planes[2] = Planef(_points[1], _points[6], _points[2]);
00345     _planes[3] = Planef(_points[2], _points[7], _points[3]);
00346     _planes[4] = Planef(_points[3], _points[4], _points[0]);
00347     _planes[5] = Planef(_points[4], _points[7], _points[6]);
00348 
00349     nassertv(_planes[0].dist_to_plane(_centroid) < 0);
00350 
00351   } else {
00352     // No, a perfectly sane universe.
00353     _planes[1] = Planef(_points[0], _points[1], _points[5]);
00354     _planes[2] = Planef(_points[1], _points[2], _points[6]);
00355     _planes[3] = Planef(_points[2], _points[3], _points[7]);
00356     _planes[4] = Planef(_points[3], _points[0], _points[4]);
00357     _planes[5] = Planef(_points[4], _points[6], _points[7]);
00358   }
00359 }
00360 
00361 void BoundingHexahedron::
00362 set_centroid() {
00363   LPoint3f net = _points[0];
00364   for (int i = 1; i < num_points; i++) {
00365     net += _points[i];
00366   }
00367   _centroid = net / (float)num_points;
00368 }

Generated on Fri May 2 00:40:21 2003 for Panda by doxygen1.3