00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00041
00042
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
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
00233
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
00254
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
00264
00265
00266 return IF_possible;
00267 }
00268 }
00269
00270 int BoundingHexahedron::
00271 contains_sphere(const BoundingSphere *sphere) const {
00272 nassertr(!is_empty(), 0);
00273
00274
00275
00276 const LPoint3f ¢er = 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
00287
00288 return IF_no_intersection;
00289
00290 } else if (dist > -radius) {
00291
00292
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
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
00336
00337
00338
00339 if (_planes[0].dist_to_plane(_centroid) > 0) {
00340
00341
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
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 }