FDH.cc

Go to the documentation of this file.
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  * 0 = No line
00010  * 1 = Single point
00011  * 2 = Regular line
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     // Liang-Barsky clipping algorithm
00021     //
00022     // t1 = -(N * P_0 + D_1) / (N * P_1)
00023     // t2 = -(N * P_0 + D_2) / (N * P_1)
00024     // where N is normal vector of half-space
00025     //       p_0 is start pont of ray
00026     //       p_1 is direction of ray
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;  // for upper FDH
00038         t2 = - (np0 + _values[i+_dirs]) / np1;  // for lower FDH
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; // no intersection
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             // (origin, direction) forms the line which is intersection of
00091             // planes having normals 'normal1' and 'normal2'
00092             direction.cross(norm1,norm2);
00093             direction.normalize(); // is it necessary ?
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             // get edge from line
00100             line = _cut_line(origin, direction);
00101             if (line == 0) continue;
00102 
00103             // Now the (origin, direction) represents end points of edge.
00104             // Reduce too short line, make the single point from it.
00105             if (line == 2) {
00106                 Vector3d aux(direction);
00107                 aux.sub(origin);
00108                 if (aux.length() < Geometry::EPS) line = 1;
00109             }
00110 
00111             // Check if vertices are already known.
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     // get array of vertices
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     // initiate mesh
00174     PolygonalMesh * pMesh = new PolygonalMesh(corners, numC);
00175 
00176     // for each facet find vertex with minimal (local) u coordinate and then
00177     // find convex hull = edges
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         // set local coordinate system
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]]); // v = arbitrary edge
00193             len = v.length();
00194         } while (k < num[i] && len < Geometry::EPS);
00195         if (len < Geometry::EPS) continue; // skip too small facet
00196         v.scale(1.0/len); // normalize
00197         u.cross(w, v);
00198 
00199         // find vertex with minimal u coord.
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         // find convex hull
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]]); // update 'v'
00236             v.sub(corners[convexHull[j-1]]);
00237             if (v.length() < Geometry::EPS) degenerated = true;
00238             else v.normalize();
00239         }
00240 
00241         // create facet
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     //for (unsigned i = 0; i < numCorners; i++)
00435     //fprintf(stderr,"%f %f %f\n",corners[i].x,corners[i].y,corners[i].z);
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     //for (unsigned i = 0; i < numCorners; i++)
00459     //fprintf(stderr,"%f %f %f\n",corners[i].x,corners[i].y,corners[i].z);
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 //---------- public -----------
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     } // for cycle
00635 
00637 
00638     pPE->mask |= ENV_HAVE_INTERFERENCE;
00639     
00640     if (mask & ENV_WANT_NORMAL) {
00641         if (t_in < Geometry::EPS)    // ray starts inside FDH
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)    // ray starts inside FDH
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     // Get POG of basic cube:
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     // Move POG respecting cutted corners:
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) { // geom is not FDH
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 

Generated on Wed Jun 28 12:24:29 2006 for esg by  doxygen 1.4.6