00001 #include <esg/Definitions.h>
00002 #include <esg/geometry/FDH.h>
00003 #include <esg/explorer/NExtentsExplorer.h>
00004 #include <esg/mesh/PolygonalMesh.h>
00005
00006 using namespace esg;
00007
00008
00009
00010
00011
00012
00013 int FDH::_cut_line(Vector3d& origin, Vector3d& direction) const
00014 {
00015 double np0, np1;
00016 double t_in = -MAXDOUBLE;
00017 double t_out = MAXDOUBLE;
00018 double t1, t2;
00019
00020
00021
00022
00023
00024
00025
00026
00027 for (register unsigned i = 0; i < _dirs; i++) {
00028 np0 = (_mat[i][0] * origin.x +
00029 _mat[i][1] * origin.y +
00030 _mat[i][2] * origin.z);
00031 np1 = (_mat[i][0] * direction.x +
00032 _mat[i][1] * direction.y +
00033 _mat[i][2] * direction.z);
00034
00035 if (np1 > -Geometry::EPS && np1 < Geometry::EPS) continue;
00036
00037 t1 = - (np0 - _values[i]) / np1;
00038 t2 = - (np0 + _values[i+_dirs]) / np1;
00039
00040 if (t1 > t2) { float t3 = t1; t1 = t2; t2 = t3; }
00041 if (t_in < t1) t_in = t1;
00042 if (t_out > t2) t_out = t2;
00043 if (t_in > t_out) return 0;
00044 }
00045
00046 Vector3d aux(origin);
00047 origin.set(direction);
00048 origin.scaleAdd(t_in, aux);
00049
00050 if (t_in == t_out) return 1;
00051
00052 direction.scaleAdd(t_out, aux);
00053 return 2;
00054 }
00055
00056 #define FDH_UPDATE_FACET(i, k) { \
00057 if (facetVert && nFacetVert) { \
00058 bool found = false; \
00059 for (register unsigned m = 0; m < nFacetVert[(i)] && !found; m++) \
00060 if (facetVert[(i)][m] == (k)) found = true; \
00061 if (!found) facetVert[(i)][nFacetVert[(i)]++] = (k); \
00062 } \
00063 }
00064
00065 Vector3d* FDH::_get_corners(unsigned & numCorners,
00066 unsigned (*facetVert)[100],
00067 unsigned nFacetVert[]) const
00068 {
00069 Vector3d norm1, norm2;
00070 Vector3d origin, direction;
00071 double cosinus;
00072 unsigned reposSize = 0;
00073 Vector3d* vertRepos = new Vector3d [_dirs*1000];
00074 int mask;
00075 int line;
00076 Vector3d v;
00077
00078 if (nFacetVert)
00079 for (register unsigned i = 0; i < 2*_dirs; i++) nFacetVert[i] = 0;
00080
00081 for (register unsigned i = 0; i < 2*_dirs; i++) {
00082 norm1.set(_mat[i][0], _mat[i][1], _mat[i][2]);
00083
00084 for (register unsigned j = 0; j < i; j++) {
00085 norm2.set(_mat[j][0],_mat[j][1],_mat[j][2]);
00086 cosinus = norm1.dot(norm2);
00087
00088 if (cosinus < 0.0 || cosinus == 1.0) continue;
00089
00090
00091
00092 direction.cross(norm1,norm2);
00093 direction.normalize();
00094 v.set(norm1);
00095 v.scale(_values[i]);
00096 origin.cross(norm1, direction);
00097 origin.scaleAdd((_values[j]-norm2.dot(v)) / norm2.dot(origin), v);
00098
00099
00100 line = _cut_line(origin, direction);
00101 if (line == 0) continue;
00102
00103
00104
00105 if (line == 2) {
00106 Vector3d aux(direction);
00107 aux.sub(origin);
00108 if (aux.length() < Geometry::EPS) line = 1;
00109 }
00110
00111
00112 mask = 0;
00113 for (register unsigned k = 0; k < reposSize; k++) {
00114 if (vertRepos[k].epsilonEquals(origin, Geometry::EPS)) {
00115 mask |= (1<<0);
00116 FDH_UPDATE_FACET(i, k);
00117 FDH_UPDATE_FACET(j, k);
00118 }
00119 if (line == 2 &&
00120 vertRepos[k].epsilonEquals(direction, Geometry::EPS)) {
00121 mask |= (1<<1);
00122 FDH_UPDATE_FACET(i, k);
00123 FDH_UPDATE_FACET(j, k);
00124 }
00125 }
00126
00127
00128 if (!(mask & (1<<0))) {
00129 FDH_UPDATE_FACET(i, reposSize);
00130 FDH_UPDATE_FACET(j, reposSize);
00131 vertRepos[reposSize++].set(origin);
00132 }
00133 if (line == 2 && !(mask & (1<<1))) {
00134 FDH_UPDATE_FACET(i, reposSize);
00135 FDH_UPDATE_FACET(j, reposSize);
00136 vertRepos[reposSize++].set(direction);
00137 }
00138 }
00139 }
00140
00141 if (reposSize > 0) {
00142 Vector3d* pRet = new Vector3 [reposSize];
00143 numCorners = reposSize;
00144 for (register unsigned l = 0; l < numCorners; l++)
00145 pRet[l].set(vertRepos[l]);
00146 delete [] vertRepos;
00147 return pRet;
00148 } else {
00149 delete [] vertRepos;
00150 numCorners = 0;
00151 return NULL;
00152 }
00153 }
00154
00155 #undef FDH_UPDATE_FACET
00156
00157 Mesh* FDH::_mesh(int) const
00158 {
00159
00160 unsigned numC;
00161 unsigned (*planeVert)[100] = new unsigned [2*_dirs] [100];
00162 unsigned *num = new unsigned [2*_dirs];
00163
00164 Vector3d* corners = _get_corners(numC, planeVert, num);
00165
00166 if (!(corners && numC)) {
00167 if (corners) delete [] corners;
00168 delete [] planeVert;
00169 delete [] num;
00170 return NULL;
00171 }
00172
00173
00174 PolygonalMesh * pMesh = new PolygonalMesh(corners, numC);
00175
00176
00177
00178 Vector3d u, v, w;
00179 unsigned minUindex = 0;
00180 double minUval = 0.0;
00181 unsigned k;
00182 double len, d;
00183 unsigned* convexHull;
00184 for (register unsigned i = 0; i < 2*_dirs; i++) {
00185 if (num[i] < 3) continue;
00186
00187
00188 w.set(_mat[i][0], _mat[i][1], _mat[i][2]);
00189 k = 1;
00190 do {
00191 v.set(corners[planeVert[i][k++]]);
00192 v.sub(corners[planeVert[i][0]]);
00193 len = v.length();
00194 } while (k < num[i] && len < Geometry::EPS);
00195 if (len < Geometry::EPS) continue;
00196 v.scale(1.0/len);
00197 u.cross(w, v);
00198
00199
00200 minUval = MAXFLOAT;
00201 for (register unsigned j = 0; j < num[i]; j++) {
00202 d = corners[planeVert[i][j]].dot(u);
00203 if (d < minUval) { minUval = d; minUindex = j; }
00204 }
00205
00206
00207 bool degenerated;
00208 int newVert;
00209 Vector3d edge;
00210 double maxCos, cos;
00211 ESGbitmask flag;
00212
00213 convexHull = new unsigned [num[i]];
00214 flag = (1<<minUindex);
00215 degenerated = false;
00216 convexHull[0] = planeVert[i][minUindex];
00217 for (register unsigned j = 1; j < num[i] && !degenerated; j++) {
00218 maxCos = -MAXFLOAT;
00219 newVert = -1;
00220 for (k = 0; k < num[i] && !degenerated; k++) {
00221 if (flag & (1<<k)) continue;
00222 edge.set(corners[planeVert[i][k]]);
00223 edge.sub(corners[convexHull[j-1]]);
00224 if (edge.length() < Geometry::EPS) {
00225 degenerated = true;
00226 continue;
00227 }
00228 edge.normalize();
00229 cos = edge.dot(v);
00230 if (cos > maxCos) { maxCos = cos; newVert = k; }
00231 }
00232 if (degenerated || newVert < 0) continue;
00233 convexHull[j] = planeVert[i][newVert];
00234 flag |= (1<<newVert);
00235 v.set(corners[convexHull[j]]);
00236 v.sub(corners[convexHull[j-1]]);
00237 if (v.length() < Geometry::EPS) degenerated = true;
00238 else v.normalize();
00239 }
00240
00241
00242 if (!degenerated)
00243 if (!pMesh->addFacet(convexHull, NULL, num[i])) {
00244 cerr << "FDH::_mesh(): " << "Skipping mesh generation because of problems with topology" << endl;
00245 delete [] convexHull;
00246 delete [] corners;
00247 delete [] planeVert;
00248 delete [] num;
00249 delete pMesh;
00250 return NULL;
00251 }
00252 delete [] convexHull;
00253 }
00254
00255 delete [] corners;
00256 delete [] planeVert;
00257 delete [] num;
00258
00259 return pMesh;
00260 }
00261
00262 void FDH::_duplicate_attributes(const Geometry& src)
00263 {
00264 Geometry::_duplicate_attributes(src);
00265 _values = new float [_dirs*2];
00266 for (register unsigned i = 0; i < _dirs*2; i++)
00267 _values[i] = ((FDH&)src)._values[i];
00268 }
00269
00270 void FDH::_rotateX(float a)
00271 {
00272 unsigned numCorners;
00273 Vertex3* corners = _get_corners(numCorners, NULL, NULL);
00274
00275 if (!corners) return;
00276
00277 Matrix3 trMat;
00278 trMat.rotX(a);
00279
00280 for (register unsigned i = 0; i < _dirs; i++) {
00281 _values[i] = -MAXFLOAT;
00282 _values[i+_dirs] = -MAXFLOAT;
00283 }
00284
00285 for (register unsigned i = 0; i < numCorners; i++) {
00286 trMat.transform(corners[i]);
00287 for (register unsigned j = 0; j < _dirs; j++) {
00288 float dist = corners[i].dot(Vector3(_mat[j][0], _mat[j][1], _mat[j][2]));
00289 if (dist > _values[j]) _values[j] = dist;
00290 if (dist < -_values[j+_dirs]) _values[j+_dirs] = - dist;
00291 }
00292 }
00293
00294 delete [] corners;
00295 }
00296
00297 void FDH::_rotateY(float a)
00298 {
00299 unsigned numCorners;
00300 Vertex3* corners = _get_corners(numCorners, NULL, NULL);
00301
00302 if (!corners) return;
00303
00304 #if defined(_MSC_VER)
00305 Vector3 *rotDirs = new Vector3[_dirs];
00306 #else
00307 Vector3 rotDirs[_dirs];
00308 #endif
00309 Matrix3 trMat;
00310 trMat.rotY(a);
00311
00312 for (register unsigned i = 0; i < _dirs; i++) {
00313 _values[i] = -MAXFLOAT;
00314 _values[i+_dirs] = -MAXFLOAT;
00315 rotDirs[i].set(_mat[i][0], _mat[i][1], _mat[i][2]);
00316 trMat.transform(rotDirs[i]);
00317 }
00318
00319 for (register unsigned i = 0; i < numCorners; i++) {
00320 trMat.transform(corners[i]);
00321 for (register unsigned j = 0; j < _dirs; j++) {
00322 float dist = corners[i].dot(Vector3(_mat[j][0], _mat[j][1], _mat[j][2]));
00323 if (dist > _values[j]) _values[j] = dist;
00324 if (dist < -_values[j+_dirs]) _values[j+_dirs] = - dist;
00325 }
00326 }
00327
00328 delete [] corners;
00329
00330 #if defined(_MSC_VER)
00331 delete [] rotDirs;
00332 #endif
00333 }
00334
00335 void FDH::_rotateZ(float a)
00336 {
00337 unsigned numCorners;
00338 Vertex3* corners = _get_corners(numCorners, NULL, NULL);
00339
00340 if (!corners) return;
00341
00342 Matrix3 trMat;
00343 trMat.rotZ(a);
00344
00345 for (register unsigned i = 0; i < _dirs; i++) {
00346 _values[i] = -MAXFLOAT;
00347 _values[i+_dirs] = -MAXFLOAT;
00348 }
00349
00350 for (register unsigned i = 0; i < numCorners; i++) {
00351 trMat.transform(corners[i]);
00352 for (register unsigned j = 0; j < _dirs; j++) {
00353 float dist = corners[i].dot(Vector3(_mat[j][0], _mat[j][1], _mat[j][2]));
00354 if (dist > _values[j]) _values[j] = dist;
00355 if (dist < -_values[j+_dirs]) _values[j+_dirs] = - dist;
00356 }
00357 }
00358
00359 delete [] corners;
00360 }
00361
00362 void FDH::_rotate(float a, const Vector3& axis)
00363 {
00364 unsigned numCorners;
00365 Vertex3* corners = _get_corners(numCorners, NULL, NULL);
00366
00367 if (!corners) return;
00368
00369 Matrix4 trMat;
00370 Matrix3 rotMat;
00371 trMat.rotationGL(a, axis);
00372 trMat.get(rotMat);
00373
00374 for (register unsigned i = 0; i < _dirs; i++) {
00375 _values[i] = -MAXFLOAT;
00376 _values[i+_dirs] = -MAXFLOAT;
00377 }
00378
00379 for (register unsigned i = 0; i < numCorners; i++) {
00380 rotMat.transform(corners[i]);
00381 for (register unsigned j = 0; j < _dirs; j++) {
00382 float dist = corners[i].dot(Vector3(_mat[j][0], _mat[j][1], _mat[j][2]));
00383 if (dist > _values[j]) _values[j] = dist;
00384 if (dist < -_values[j+_dirs]) _values[j+_dirs] = - dist;
00385 }
00386 }
00387
00388 delete [] corners;
00389 }
00390
00391 void FDH::_rotate(const Matrix3& rotMat)
00392 {
00393 unsigned numCorners;
00394 Vertex3* corners = _get_corners(numCorners, NULL, NULL);
00395
00396 if (!corners) return;
00397
00398 for (register unsigned i = 0; i < _dirs; i++) {
00399 _values[i] = -MAXFLOAT;
00400 _values[i+_dirs] = -MAXFLOAT;
00401 }
00402
00403 for (register unsigned i = 0; i < numCorners; i++) {
00404 rotMat.transform(corners[i]);
00405 for (register unsigned j = 0; j < _dirs; j++) {
00406 float dist = corners[i].dot(Vector3(_mat[j][0], _mat[j][1], _mat[j][2]));
00407 if (dist > _values[j]) _values[j] = dist;
00408 if (dist < -_values[j+_dirs]) _values[j+_dirs] = - dist;
00409 }
00410 }
00411
00412 delete [] corners;
00413 }
00414
00415 void FDH::_translate(float x, float y, float z)
00416 {
00417 Vector3 v(x,y,z);
00418 float d;
00419
00420 for (register unsigned i = 0; i < _dirs; i++) {
00421 d = v.dot(Vector3(_mat[i][0],_mat[i][1],_mat[i][2]));
00422 _values[i] += d;
00423 _values[i+_dirs] -= d;
00424 }
00425 }
00426
00427 void FDH::_transform(const Matrix4& trMat)
00428 {
00429 unsigned numCorners;
00430 Vertex3* corners = _get_corners(numCorners, NULL, NULL);
00431
00432 if (!corners) return;
00433
00434
00435
00436
00437 #ifdef WIN32
00438 Vector3 *dirs = new Vector3[_dirs];
00439 #else
00440 Vector3 dirs[_dirs];
00441 #endif
00442
00443 for (register unsigned i = 0; i < _dirs; i++) {
00444 _values[i] = -MAXFLOAT;
00445 _values[i+_dirs] = -MAXFLOAT;
00446 dirs[i].set(_mat[i][0], _mat[i][1], _mat[i][2]);
00447 }
00448
00449 for (register unsigned i = 0; i < numCorners; i++) {
00450 trMat.transform(corners[i]);
00451 for (register unsigned j = 0; j < _dirs; j++) {
00452 float dist = corners[i].dot(dirs[j]);
00453 if (dist > _values[j]) _values[j] = dist;
00454 if (dist < -_values[j+_dirs]) _values[j+_dirs] = - dist;
00455 }
00456 }
00457
00458
00459
00460
00461 delete [] corners;
00462
00463 #ifdef WIN32
00464 delete [] dirs;
00465 #endif
00466 }
00467
00468 void FDH::_scale(float s)
00469 {
00470 for (register unsigned i = 0; i < 2*_dirs; i++) _values[i] *= s;
00471 }
00472
00473
00474
00475
00476 FDH::FDH(unsigned dirs,
00477 const float (*mat)[3],
00478 SceneGraphObject& object)
00479 : _dirs(dirs), _mat(mat)
00480 {
00481 _values = new float [_dirs*2];
00482
00483 Interval interval;
00484 NExtentsExplorer explorer(_mat, _dirs);
00485 explorer.explore(object);
00486 for (register unsigned i = 0; i < _dirs; i++) {
00487 interval = explorer.result(i);
00488 _values[i] = interval.max;
00489 _values[i+_dirs] = - interval.min;
00490 }
00491 }
00492
00493 FDH::FDH(unsigned dirs,
00494 const float (*mat)[3],
00495 List<SceneGraphObject>& list)
00496 : _dirs(dirs), _mat(mat)
00497 {
00498 _values = new float [_dirs*2];
00499 for (register unsigned i = 0; i < _dirs; i++)
00500 _values[i] = (_values[i+_dirs] = - MAXFLOAT);
00501
00502 Interval interval;
00503 SceneGraphObject* pObject = list.firstItem();
00504 while (pObject) {
00505 NExtentsExplorer explorer(_mat, _dirs);
00506 explorer.explore(*pObject);
00507 for (register unsigned i = 0; i < _dirs; i++) {
00508 interval = explorer.result(i);
00509 if (interval.max > _values[i])
00510 _values[i] = interval.max;
00511 if (interval.min < -_values[i+_dirs])
00512 _values[i+_dirs] = - interval.min;
00513 }
00514 pObject = list.nextItem();
00515 }
00516 }
00517
00518 FDH::FDH(unsigned dirs,
00519 const float (*mat)[3],
00520 const Geometry& geom1,
00521 const Geometry& geom2)
00522 : _dirs(dirs), _mat(mat)
00523 {
00524 _values = new float [_dirs*2];
00525
00526 Interval interval1, interval2;
00527 for (register unsigned i = 0; i < _dirs; i++) {
00528 interval1 = geom1.extent(_mat[i][0], _mat[i][1], _mat[i][2]);
00529 interval2 = geom2.extent(_mat[i][0], _mat[i][1], _mat[i][2]);
00530 if (interval1.max > interval2.max) _values[i] = interval1.max;
00531 else _values[i] = interval2.max;
00532 if (interval1.min < interval2.min) _values[i+_dirs] = -interval1.min;
00533 else _values[i+_dirs] = -interval2.min;
00534 }
00535 }
00536
00537 FDH::FDH(unsigned dirs,
00538 const float (*mat)[3],
00539 const Geometry& geom)
00540 : _dirs(dirs), _mat(mat)
00541 {
00542 _values = new float [_dirs*2];
00543
00544 Interval interval;
00545 for (register unsigned i = 0; i < _dirs; i++) {
00546 interval = geom.extent(_mat[i][0], _mat[i][1], _mat[i][2]);
00547 _values[i] = interval.max;
00548 _values[i+_dirs] = -interval.min;
00549 }
00550 }
00551
00552 FDH::FDH(unsigned dirs,
00553 const float (*mat)[3],
00554 const float values[])
00555 : _dirs(dirs), _mat(mat)
00556 {
00557 _values = new float [_dirs*2];
00558
00559 for (register unsigned i = 0; i < 2*_dirs; i++) _values[i] = values[i];
00560 }
00561
00562 FDH::~FDH()
00563 {
00564 if (_values) delete [] _values;
00565 }
00566
00567 void FDH::rayIntersection(PointEnv* pPE,
00568 int mask,
00569 const Vector3& origin,
00570 const Vector3& direction,
00571 float maxDist)
00572 {
00573 if (!pPE) {
00574 fprintf(stderr,"FDH error: No point environment structure defined\n");
00575 return;
00576 }
00577
00578 pPE->mask = ENV_HAVE_NOTHING;
00579
00581
00582 int plane1 = 0, plane2 = 0;
00583 float t_in = -MAXFLOAT, t_out = MAXFLOAT;
00584 float t1, t2;
00585
00586 if (mask&ENV_WANT_UV_COORD)
00587 fprintf(stderr,"FDH::rayIntersection(): UV mapping is not implemented\n");
00588
00589 if (mask&ENV_USE_CACHE) {
00590 if (!pPE->pCache)
00591 pPE->pCache = new FDHCache(_mat,_dirs,origin,direction);
00592 FDHCache * c = (FDHCache*) pPE->pCache;
00593 if (mask & ENV_WANT_NORMAL) {
00594 FDH_CLIP_LINE_INDEX_INIT(c->oval[0], c->dval[0], 0, _dirs);
00595 for (register unsigned i = 1; i < _dirs; i++) {
00596 FDH_CLIP_LINE_INDEX_CONT(c->oval[i], c->dval[i], i, i+_dirs);
00597 }
00598 } else {
00599 FDH_CLIP_LINE_INIT(c->oval[0], c->dval[0], 0, _dirs);
00600 for (register unsigned i = 1; i < _dirs; i++) {
00601 FDH_CLIP_LINE_CONT(c->oval[i], c->dval[i], i, i+_dirs);
00602 }
00603 }
00604 } else {
00605 register double np1 = (_mat[0][0] * direction.x +
00606 _mat[0][1] * direction.y +
00607 _mat[0][2] * direction.z);
00608 register double np0 = (_mat[0][0] * origin.x +
00609 _mat[0][1] * origin.y +
00610 _mat[0][2] * origin.z);
00611 if (mask & ENV_WANT_NORMAL) {
00612 FDH_CLIP_LINE_INDEX_INIT(np0, np1, 0, _dirs);
00613 for (register unsigned i = 1; i < _dirs; i++) {
00614 np1 = (_mat[i][0] * direction.x +
00615 _mat[i][1] * direction.y +
00616 _mat[i][2] * direction.z);
00617 np0 = (_mat[i][0] * origin.x +
00618 _mat[i][1] * origin.y +
00619 _mat[i][2] * origin.z);
00620 FDH_CLIP_LINE_INDEX_CONT(np0, np1, 0, _dirs);
00621 }
00622 } else {
00623 FDH_CLIP_LINE_INIT(np0, np1, 0, _dirs);
00624 for (register unsigned i = 1; i < _dirs; i++) {
00625 np1 = (_mat[i][0] * direction.x +
00626 _mat[i][1] * direction.y +
00627 _mat[i][2] * direction.z);
00628 np0 = (_mat[i][0] * origin.x +
00629 _mat[i][1] * origin.y +
00630 _mat[i][2] * origin.z);
00631 FDH_CLIP_LINE_CONT(np0, np1, 0, _dirs);
00632 }
00633 }
00634 }
00635
00637
00638 pPE->mask |= ENV_HAVE_INTERFERENCE;
00639
00640 if (mask & ENV_WANT_NORMAL) {
00641 if (t_in < Geometry::EPS)
00642 pPE->normal.set(_mat[plane2][0],_mat[plane2][1],_mat[plane2][2]);
00643 else
00644 pPE->normal.set(_mat[plane1][0],_mat[plane1][1],_mat[plane1][2]);
00645 pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00646 pPE->mask |= ENV_HAVE_NORMAL;
00647 }
00648
00649 if (mask & ENV_WANT_INTERSECTION) {
00650 pPE->intersection.set(direction);
00651 if (t_in < Geometry::EPS)
00652 pPE->intersection.scaleAdd(t_out, origin);
00653 else
00654 pPE->intersection.scaleAdd(t_in, origin);
00655 pPE->mask |= ENV_HAVE_INTERSECTION;
00656 }
00657
00658 if (mask & ENV_WANT_DISTANCE) {
00659 if (t_in < Geometry::EPS) pPE->distance = t_out;
00660 else pPE->distance = t_in;
00661 pPE->mask |= ENV_HAVE_DISTANCE;
00662 }
00663 }
00664
00665 bool FDH::mapToUV(const Vector3& v, Vector2& uv)
00666 {
00667 fprintf(stderr,"FDH::mapToUV(): Not implemented\n");
00668 return false;
00669 }
00670
00671 void FDH::randomSample(int mask, PointEnv& pe, double* pdf)
00672 {
00673 pe.mask = ENV_HAVE_NOTHING;
00674
00675 fprintf(stderr,"FDH::randomSample(): Not implemented\n");
00676 }
00677
00678 bool FDH::randomDirection(const Vector3& pov, Vector3& dir, double* pdf)
00679 {
00680 fprintf(stderr,"FDH::randomDirection(): Not implemented\n");
00681 return false;
00682 }
00683
00684 Interval FDH::extent(const Vector3& direction) const
00685 {
00686 Interval retInt;
00687 unsigned numCorners;
00688 float dist;
00689 Vertex3* corners;
00690
00691 for (register unsigned i = 0; i < _dirs; i++)
00692 if (_mat[i][0] == direction.x &&
00693 _mat[i][1] == direction.y &&
00694 _mat[i][2] == direction.z) {
00695 retInt.max = _values[i];
00696 retInt.min = -_values[i+_dirs];
00697 return retInt;
00698 }
00699
00700 retInt.min = MAXFLOAT;
00701 retInt.max = -MAXFLOAT;
00702
00703 if (!(corners = _get_corners(numCorners, NULL, NULL))) return retInt;
00704
00705 for (register unsigned i = 0; i < numCorners; i++) {
00706 dist = direction.dot(corners[i]);
00707 if (dist < retInt.min) retInt.min = dist;
00708 if (dist > retInt.max) retInt.max = dist;
00709 }
00710
00711 delete [] corners;
00712
00713 return retInt;
00714 }
00715
00716 Geometry* FDH::clone(const Matrix4* pTrMat) const
00717 {
00718 FDH* pRet = new FDH(_dirs, _mat);
00719 pRet->_duplicate_attributes(*this);
00720 if (pTrMat) pRet->_transform(*pTrMat);
00721 return pRet;
00722 }
00723
00724 Vector3 FDH::centroid() const
00725 {
00726 register float dist;
00727
00728
00729 Vector3 pog((_values[0] - _values[0+_dirs]) / 2,
00730 (_values[1] - _values[1+_dirs]) / 2,
00731 (_values[2] - _values[2+_dirs]) / 2);
00732
00733
00734 for (register unsigned i = 3; i < _dirs; i++) {
00735 dist = ((_values[i] - _values[i+_dirs]) / 2) - (_mat[i][0] * pog.x +
00736 _mat[i][1] * pog.y +
00737 _mat[i][2] * pog.z);
00738 pog.x += _mat[i][0]*dist;
00739 pog.y += _mat[i][1]*dist;
00740 pog.z += _mat[i][2]*dist;
00741 }
00742
00743 return pog;
00744 }
00745
00746 double FDH::radius(const Vector3& centroid) const
00747 {
00748 register double r = - MAXDOUBLE;
00749 register double d,e;
00750 for (register unsigned i = 0; i < _dirs; i++) {
00751 d = (centroid.x * _mat[i][0] +
00752 centroid.y * _mat[i][1] +
00753 centroid.z * _mat[i][2]);
00754 e = _values[i] - d;
00755 if (e > r) r = e;
00756 e = d - _values[i+_dirs];
00757 if (e > r) r = e;
00758 }
00759 return r;
00760 }
00761
00762 bool FDH::separation(Geometry& geom, Vector3* pDir)
00763 {
00764 Interval ext;
00765 try {
00766 FDH& fdh = dynamic_cast<FDH&>(geom);
00767 for (register unsigned i = 0; i < _dirs; i++) {
00768 if (_values[i] < - fdh._values[i+_dirs]) {
00769 if (pDir) pDir->set(_mat[i][0], _mat[i][1], _mat[i][2]);
00770 return true;
00771 }
00772 if (-_values[i+_dirs] > fdh._values[i]) {
00773 if (pDir) pDir->set(_mat[i+_dirs][0],
00774 _mat[i+_dirs][1],
00775 _mat[i+_dirs][2]);
00776 return true;
00777 }
00778 }
00779 } catch (bad_cast) {
00780 for (register unsigned i = 0; i < _dirs; i++) {
00781 ext = geom.extent(_mat[i][0], _mat[i][1], _mat[i][2]);
00782 if (_values[i] < ext.min || - _values[i+_dirs] > ext.max) {
00783 if (pDir) pDir->set(_mat[i][0], _mat[i][1], _mat[i][2]);
00784 return true;
00785 }
00786 }
00787 }
00788 return false;
00789 }
00790
00791 double FDH::distance(const Geometry& geom, Vector3* pDir)
00792 {
00793 double ret = -MAXDOUBLE;
00794 double d;
00795 Interval ext;
00796
00797 for (register unsigned i = 0; i < _dirs; i++) {
00798 ext = geom.extent(_mat[i][0], _mat[i][1], _mat[i][2]);
00799 d = ext.min - _values[i];
00800 if (d > ret) {
00801 if (pDir) pDir->set(_mat[i][0], _mat[i][1], _mat[i][2]);
00802 ret = d;
00803 }
00804 d = - (_values[i+_dirs] + ext.max);
00805 if (d > ret) {
00806 if (pDir) pDir->set(_mat[i+_dirs][0],
00807 _mat[i+_dirs][1],
00808 _mat[i+_dirs][2]);
00809 ret = d;
00810 }
00811 }
00812
00813 return ret;
00814 }
00815
00816 void FDH::dump(const char* intent, const char* tab)
00817 {
00818 printf("%s geometry FDH {\n", intent);
00819 printf("%s %s dimension %d\n", intent, tab, _dirs);
00820 printf("%s %s direction [\n", intent, tab);
00821 for (register unsigned i = 0; i < _dirs; i++)
00822 printf("%s %s %s %f %f %f\n", intent, tab, tab, _mat[i][0], _mat[i][1], _mat[i][2]);
00823 printf("%s %s ]\n", intent, tab);
00824 printf("%s %s extent [ # upper, lower\n", intent, tab);
00825 for (register unsigned i = 0; i < _dirs; i++)
00826 printf("%s %s %s %f, %f\n", intent, tab, tab, _values[i], -_values[i+_dirs]);
00827 printf("%s %s ]\n", intent, tab);
00828 printf("%s }\n", intent);
00829 }
00830
00831 bool FDH::checkVolume() const
00832 {
00833 for (register unsigned i = 0; i < _dirs; i++)
00834 if (_values[i] < -_values[i+_dirs]) return false;
00835 return true;
00836 }
00837