FDH14.cc

Go to the documentation of this file.
00001 #include <esg/geometry/FDH14.h>
00002 #include <esg/mesh/FDH14Mesh.h>
00003 
00004 using namespace esg;
00005 
00006 const double   FDH14::SCALE         = .5773502691896; // 1/sqrt(3)
00007 const unsigned FDH14::DIRS          =  7;             // number of directions
00008 const unsigned FDH14::SIZE          =  14;            // 2 * DIRS
00009 const float    FDH14::FDHMat[14][3] =                 // matrix of FDH
00010 {
00011     {      1,      0,      0 },
00012     {      0,      1,      0 },
00013     {      0,      0,      1 },
00014     {  SCALE,  SCALE,  SCALE },
00015     {  SCALE, -SCALE,  SCALE },
00016     { -SCALE,  SCALE,  SCALE },
00017     {  SCALE,  SCALE, -SCALE },
00018     {     -1,      0,      0 },
00019     {      0,     -1,      0 },
00020     {      0,      0,     -1 },
00021     { -SCALE, -SCALE, -SCALE },
00022     { -SCALE,  SCALE, -SCALE },
00023     {  SCALE, -SCALE, -SCALE },
00024     { -SCALE, -SCALE,  SCALE }
00025 };
00026 
00027 
00028 void FDH14::_rotateX(float a)
00029 {
00030     Matrix4 trMat; trMat.rotX(a);
00031     RotInfo r(trMat);
00032     float*  newVal = new float [2*_dirs];
00033         
00034     for (register unsigned i = 0; i < 2*_dirs; i++)
00035         newVal[i] = RotInfo::fast_lp(r.get(i), _values);
00036 
00037     delete [] _values;
00038     _values = newVal;
00039 }
00040 
00041 void FDH14::_rotateY(float a)
00042 {
00043     Matrix4 trMat; trMat.rotY(a);
00044     RotInfo r(trMat);
00045     float*  newVal = new float [2*_dirs];
00046         
00047     for (register unsigned i = 0; i < 2*_dirs; i++)
00048         newVal[i] = RotInfo::fast_lp(r.get(i), _values);
00049 
00050     delete [] _values;
00051     _values = newVal;
00052 }
00053 
00054 void FDH14::_rotateZ(float a)
00055 {
00056     Matrix4 trMat; trMat.rotZ(a);
00057     RotInfo r(trMat);
00058     float*  newVal = new float [2*_dirs];
00059         
00060     for (register unsigned i = 0; i < 2*_dirs; i++)
00061         newVal[i] = RotInfo::fast_lp(r.get(i), _values);
00062 
00063     delete [] _values;
00064     _values = newVal;
00065 }
00066 
00067 void FDH14::_rotate(float a, const Vector3& axis)
00068 {
00069     Matrix4 trMat; trMat.rotationGL(a, axis);
00070     RotInfo r(trMat);
00071     float*  newVal = new float [2*_dirs];
00072         
00073     for (register unsigned i = 0; i < 2*_dirs; i++)
00074         newVal[i] = RotInfo::fast_lp(r.get(i), _values);
00075 
00076     delete [] _values;
00077     _values = newVal;
00078 }
00079 
00080 void FDH14::_rotate(const Matrix3& rotMat)
00081 {
00082     Matrix4 trMat(rotMat);
00083     RotInfo r(trMat);
00084     float*  newVal = new float [2*_dirs];
00085         
00086     for (register unsigned i = 0; i < 2*_dirs; i++)
00087         newVal[i] = RotInfo::fast_lp(r.get(i), _values);
00088 
00089     delete [] _values;
00090     _values = newVal;
00091 }
00092 
00093 void FDH14::_transform(const Matrix4& trMat)
00094 {
00095     Vector3 trVec, scVec;
00096     Matrix3 rotMat;
00097 
00098     trMat.get(rotMat, trVec, scVec);
00099 
00100     if ((scVec.x == scVec.y) && (scVec.y == scVec.z)) {
00101         RotInfo  r(trMat);
00102         float*   newVal = new float [2*_dirs];
00103         
00104         for (register unsigned i = 0; i < 2*_dirs; i++)
00105             newVal[i] = RotInfo::fast_lp(r.get(i), _values);
00106 
00107         delete [] _values;
00108         _values = newVal;
00109     } else 
00110         FDH::_transform(trMat);
00111 }
00112 
00113 Mesh* FDH14::_mesh(int d) const
00114 {
00115     float ar, br, cr;
00116 
00117     ar = _values[0] + _values[7];
00118     br = _values[1] + _values[8];
00119     cr = _values[2] + _values[9];
00120     
00121     return (Mesh*) new FDH14Mesh(_mat, _values, ar, br, cr);
00122 }
00123 
00124 void FDH14::_duplicate_attributes(const Geometry& src)
00125 {
00126     FDH::_duplicate_attributes(src);
00127 }
00128 
00129 
00130 
00131 //---------------------------- public -----------------------------------
00132 
00133 #define BVH_INIT_CACHE  \
00134    if (!pPE->pCache) { \
00135        pPE->pCache = new FDHCache(4); \
00136        co = &(((FDHCache*)pPE->pCache)->oval[0]); \
00137        cd = &(((FDHCache*)pPE->pCache)->dval[0]); \
00138        *(co+0) = SCALE * ( origin.x + origin.y + origin.z); \
00139        *(co+1) = SCALE * ( origin.x - origin.y + origin.z); \
00140        *(co+2) = SCALE * (-origin.x + origin.y + origin.z); \
00141        *(co+3) = SCALE * ( origin.x + origin.y - origin.z); \
00142        *(cd+0) = SCALE * ( direction.x + direction.y + direction.z); \
00143        *(cd+1) = SCALE * ( direction.x - direction.y + direction.z); \
00144        *(cd+2) = SCALE * (-direction.x + direction.y + direction.z); \
00145        *(cd+3) = SCALE * ( direction.x + direction.y - direction.z); \
00146    } else { \
00147        co = &(((FDHCache*)pPE->pCache)->oval[0]); \
00148        cd = &(((FDHCache*)pPE->pCache)->dval[0]); \
00149    }
00150 
00151 void FDH14::rayIntersection(PointEnv*      pPE,
00152                             int            mask,
00153                             const Vector3& origin,
00154                             const Vector3& direction,
00155                             float          maxDist)
00156 {
00157     if (!pPE) {
00158         std::cerr << "FDH14::rayIntersection(): ";
00159         std::cerr << "No point environment structure defined" << std::endl;
00160         return;
00161     }
00162 
00163     pPE->mask = ENV_HAVE_NOTHING;
00164 
00166 
00167     register double t_in, t_out, t1, t2;
00168 
00169     if (mask&ENV_WANT_UV_COORD)
00170         fprintf(stderr,"FDH14::rayIntersection(): UV mapping is not implemented");
00171 
00172     if (mask & ENV_WANT_NORMAL) {
00173         /*
00174          * Use a little slower macros
00175          */
00176         int plane1 = 0, plane2 = 0;
00177         FDH_CLIP_LINE_INDEX_INIT(origin.x, direction.x, 0, 7);
00178         FDH_CLIP_LINE_INDEX_CONT(origin.y, direction.y, 1, 8);
00179         FDH_CLIP_LINE_INDEX_CONT(origin.z, direction.z, 2, 9);
00180         if (mask & ENV_USE_CACHE) {
00181             register float * co, * cd;
00182             BVH_INIT_CACHE;
00183             FDH_CLIP_LINE_INDEX_CONT(*co, *cd, 3, 10); co++; cd++;
00184             FDH_CLIP_LINE_INDEX_CONT(*co, *cd, 4, 11); co++; cd++;
00185             FDH_CLIP_LINE_INDEX_CONT(*co, *cd, 5, 12); co++; cd++;
00186             FDH_CLIP_LINE_INDEX_CONT(*co, *cd, 6, 13);
00187         } else {
00188             register double np0 = SCALE*(origin.x   +origin.y   +origin.z);
00189             register double np1 = SCALE*(direction.x+direction.y+direction.z);
00190             FDH_CLIP_LINE_INDEX_CONT(np0, np1, 3, 10);
00191             np0 = SCALE * (origin.x    - origin.y    + origin.z);
00192             np1 = SCALE * (direction.x - direction.y + direction.z);
00193             FDH_CLIP_LINE_INDEX_CONT(np0, np1, 4, 11);
00194             np0 = SCALE * (-origin.x    + origin.y    + origin.z);
00195             np1 = SCALE * (-direction.x + direction.y + direction.z);
00196             FDH_CLIP_LINE_INDEX_CONT(np0, np1, 5, 12);
00197             np0 = SCALE * (origin.x    + origin.y    - origin.z);
00198             np1 = SCALE * (direction.x + direction.y - direction.z);
00199             FDH_CLIP_LINE_INDEX_CONT(np0, np1, 6, 13);
00200         }
00201         if (t_in < Geometry::EPS)    // ray starts inside FDH
00202             pPE->normal.set(_mat[plane2][0],_mat[plane2][1],_mat[plane2][2]);
00203         else
00204             pPE->normal.set(_mat[plane1][0],_mat[plane1][1],_mat[plane1][2]);
00205         pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00206         pPE->mask |= ENV_HAVE_NORMAL;
00207     } else {
00208         /*
00209          * Use a little bit more efficient macros.
00210          */
00211         FDH_CLIP_LINE_INIT(origin.x, direction.x, 0, 7);
00212         FDH_CLIP_LINE_CONT(origin.y, direction.y, 1, 8);
00213         FDH_CLIP_LINE_CONT(origin.z, direction.z, 2, 9);
00214         if (mask & ENV_USE_CACHE) {
00215             register float * co, * cd;
00216             BVH_INIT_CACHE;
00217             FDH_CLIP_LINE_CONT(*co, *cd, 3, 10); co++; cd++;
00218             FDH_CLIP_LINE_CONT(*co, *cd, 4, 11); co++; cd++;
00219             FDH_CLIP_LINE_CONT(*co, *cd, 5, 12); co++; cd++;
00220             FDH_CLIP_LINE_CONT(*co, *cd, 6, 13);
00221         } else {
00222             register double np0 = SCALE*(origin.x   +origin.y   +origin.z);
00223             register double np1 = SCALE*(direction.x+direction.y+direction.z);
00224             FDH_CLIP_LINE_CONT(np0, np1, 3, 10);
00225             np0 = SCALE * (origin.x    - origin.y    + origin.z);
00226             np1 = SCALE * (direction.x - direction.y + direction.z);
00227             FDH_CLIP_LINE_CONT(np0, np1, 4, 11);
00228             np0 = SCALE * (-origin.x    + origin.y    + origin.z);
00229             np1 = SCALE * (-direction.x + direction.y + direction.z);
00230             FDH_CLIP_LINE_CONT(np0, np1, 5, 12);
00231             np0 = SCALE * (origin.x    + origin.y    - origin.z);
00232             np1 = SCALE * (direction.x + direction.y - direction.z);
00233             FDH_CLIP_LINE_CONT(np0, np1, 6, 13);
00234         } 
00235     }
00237     
00238     pPE->mask |= ENV_HAVE_INTERFERENCE;
00239     
00240     if (mask & ENV_WANT_INTERSECTION) {
00241         pPE->intersection.set(direction);
00242         if (t_in < Geometry::EPS)    // ray starts inside FDH
00243             pPE->intersection.scaleAdd(t_out, origin);
00244         else
00245             pPE->intersection.scaleAdd(t_in, origin);
00246         pPE->mask |= ENV_HAVE_INTERSECTION;
00247     }
00248     
00249     if (mask & ENV_WANT_DISTANCE) {
00250         if (t_in < Geometry::EPS) pPE->distance = t_out;
00251         else                      pPE->distance = t_in;
00252         pPE->mask |= ENV_HAVE_DISTANCE;
00253     }
00254 }
00255 
00256 #undef BVH_INIT_CACHE
00257 
00258 Interval FDH14::extent(const Vector3& direction) const
00259 {
00260     Interval interval;
00261     int      counter = 0;
00262     Vector3  dir(direction);
00263     
00264     if (direction.x < 0.) counter++;
00265     if (direction.y < 0.) counter++;
00266     if (direction.z < 0.) counter++;
00267     if (counter > 1) dir.negate(); // lower direction
00268     
00269     RotInfo r(dir);
00270 
00271     interval.max =   RotInfo::fast_lp(r.get(0), _values);
00272     interval.min = - RotInfo::fast_lp(r.get(1), _values);
00273     
00274     return interval;
00275 }
00276 
00277 Geometry* FDH14::clone(const Matrix4* pTrMat) const
00278 {
00279     FDH14* pRet = new FDH14();
00280     pRet->_duplicate_attributes(*this);
00281     if (pTrMat) pRet->_transform(*pTrMat);
00282     return pRet;
00283 }
00284 
00285 
00286 
00287 
00288 
00290 //                        subclass FDH_14::RotInfo                           //
00292 
00293 const double FDH14::RotInfo::ROT_EPS        = .0;
00294 const double FDH14::RotInfo::ROT_SCALE      = .8660254;
00295 const int    FDH14::RotInfo::_SgnCtrl[8][4] =
00296 {
00297     /* --- */ {10, 12, 11, 13},
00298     /* +-- */ {12, 10,  6,  4},
00299     /* -+- */ {11,  6, 10,  5},
00300     /* ++- */ { 6, 11, 12,  3},
00301     /* --+ */ {13,  4,  5, 10},
00302     /* +-+ */ { 4, 13,  3, 12},
00303     /* -++ */ { 5,  3, 13, 11},
00304     /* +++ */ { 3,  5,  4,  6}
00305 };
00306 
00307 #define SWAPF(x,y) { float ftmp; ftmp=x; x=y; y=ftmp; }
00308 void FDH14::RotInfo::fdh_precomp(FDH_Precomp *r, const float c[])
00309 {
00310     float d[3];
00311     int  pt[3];
00312     register int i, j;
00313     
00314     j = 0;
00315     for (i = 0; i < 3; i++) {
00316         if (c[i] < 0.) {
00317             pt[i] = i + 7;
00318             d[i] = -c[i];
00319         } else {
00320             j = j | (1 << i);
00321             pt[i] = i;
00322             d[i] = c[i];
00323         }
00324     }
00325     
00326     r->p[2] = _SgnCtrl[j][0];
00327     
00328     if (d[0] <= d[1]) {
00329         if (d[1] <= d[2]) {
00330             /* d[0]<=d[1]<=d[2] */
00331             r->p[0] = pt[1];
00332             r->p[1] = pt[2];
00333             r->p[3] = _SgnCtrl[j][0 + 1];
00334         } else if (d[0] <= d[2]) {
00335             /* d[0]<=d[2]< d[1] */
00336             r->p[0] = pt[2];
00337             r->p[1] = pt[1];
00338             r->p[3] = _SgnCtrl[j][0 + 1];
00339             SWAPF(d[1], d[2]);
00340         } else {
00341             /* d[2]< d[0]<=d[1] */
00342             r->p[0] = pt[0];
00343             r->p[1] = pt[1];
00344             r->p[3] = _SgnCtrl[j][2 + 1];
00345             SWAPF(d[0], d[2]);
00346             SWAPF(d[1], d[2]);
00347         }
00348     } else {                      /* d[1]< d[0] */
00349         if (d[0] <= d[2]) {
00350             /* d[1]< d[0]<=d[2] */
00351             r->p[0] = pt[0];
00352             r->p[1] = pt[2];
00353             r->p[3] = _SgnCtrl[j][1 + 1];
00354             SWAPF(d[0], d[1]);
00355         } else if (d[1] <= d[2]) {
00356             /* d[1]<=d[2]< d[0] */
00357             r->p[0] = pt[2];
00358             r->p[1] = pt[0];
00359             r->p[3] = _SgnCtrl[j][1 + 1];
00360             SWAPF(d[0], d[1]);
00361             SWAPF(d[1], d[2]);
00362         } else {
00363             /* d[2]< d[1]< d[0] */
00364             r->p[0] = pt[1];
00365             r->p[1] = pt[0];
00366             r->p[3] = _SgnCtrl[j][2 + 1];
00367             SWAPF(d[0], d[2]);
00368         }
00369     }
00370     
00371     r->v1[0] = d[1] - d[0];
00372     r->v1[1] = d[2] - d[0];
00373     r->v1[2] = d[0] / SCALE;
00374     
00375     r->v2[0] = d[2] - d[1];
00376     r->v2[1] = (d[0] + d[1]) * ROT_SCALE;
00377     r->v2[2] = (d[1] - d[0]) * ROT_SCALE;
00378 }
00379 #undef SWAPF
00380 
00381 
00382 
00383 //----------------------------- public -------------------------------
00384 
00385 FDH14::RotInfo::RotInfo()
00386 {
00387     float trMat [4][4] = {{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1}};
00388   
00389     rotation = 0;
00390     r = NULL;
00391     recompute(trMat);
00392 }
00393 
00394 FDH14::RotInfo::RotInfo(const float trMat[4][4])
00395 {
00396     rotation = 0;
00397     r = NULL;
00398     recompute(trMat);
00399 }
00400 
00401 FDH14::RotInfo::RotInfo(const Matrix4f& trMat)
00402 {
00403     rotation = 0;
00404     r = NULL;
00405     recompute(trMat);
00406 }
00407 
00408 FDH14::RotInfo::RotInfo(const Vector3& direction)
00409 {
00410     rotation = 1;
00411     r = NULL;
00412     recompute(direction);
00413 }
00414 
00415 void FDH14::RotInfo::recompute(const float trMat[4][4])
00416 {
00417     float c[3];
00418     
00419     if (rotation == 1) {
00420         for (register int i = 0; i < 4; i++) // Check if values are actual
00421             for (register int j = 0; j < 4; j++)
00422                 if (mat[i][j] != trMat[i][j]) goto NOT_ACTUAL;
00423         return;
00424     }
00425     
00426  NOT_ACTUAL:
00427     if (r) delete [] r;
00428     if ((r = new FDH_Precomp [SIZE]) == NULL) return;
00429     
00430     /* Precomupte array r */
00431     for (register unsigned i = 0; i < SIZE; i++) {
00432         for (register int j = 0; j < 3; j++) {
00433 #if 0 // probably bug - reverse rotation
00434             c[j] = FDHMat[i][0] * trMat[j][0] +
00435                 FDHMat[i][1] * trMat[j][1] +
00436                 FDHMat[i][2] * trMat[j][2];
00437 #endif
00438             c[j] = FDHMat[i][0] * trMat[0][j] +
00439                 FDHMat[i][1] * trMat[1][j] +
00440                 FDHMat[i][2] * trMat[2][j];
00441         }
00442         fdh_precomp(&r[i], c);
00443         r[i].tau = FDHMat[i][0] * trMat[0][3] +
00444             FDHMat[i][1] * trMat[1][3] +
00445             FDHMat[i][2] * trMat[2][3];
00446     }
00447     
00448     for (register int i = 0; i < 4; i++)
00449         for (register int j = 0; j < 4; j++)
00450             mat[i][j] = trMat[i][j];
00451     rotation = 1;
00452 }
00453 
00454 void FDH14::RotInfo::recompute(const Matrix4f& trMat)
00455 {
00456     float c[3];
00457     
00458     if (rotation == 1) {
00459         for (register int i = 0; i < 4; i++) // Check if values are actual
00460             for (register int j = 0; j < 4; j++)
00461                 if (mat[i][j] != trMat(i,j)) goto NOT_ACTUAL;
00462         return;
00463     }
00464     
00465  NOT_ACTUAL:
00466     if (r) delete [] r;
00467     if ((r = new FDH_Precomp [SIZE]) == NULL) return;
00468     
00469     /* Precomupte array r */
00470     for (register unsigned i = 0; i < SIZE; i++) {
00471         for (register int j = 0; j < 3; j++) {
00472 #if 0 // probably bug - reverse rotation
00473             c[j] = FDHMat[i][0] * trMat(j,0) +
00474                 FDHMat[i][1] * trMat(j,1) +
00475                 FDHMat[i][2] * trMat(j,2);
00476 #endif
00477             c[j] = (FDHMat[i][0] * trMat(0,j) +
00478                     FDHMat[i][1] * trMat(1,j) +
00479                     FDHMat[i][2] * trMat(2,j));
00480         }
00481         fdh_precomp(&r[i], c);
00482         r[i].tau = (FDHMat[i][0] * trMat(0,3) +
00483                     FDHMat[i][1] * trMat(1,3) +
00484                     FDHMat[i][2] * trMat(2,3));
00485     }
00486     
00487     for (register int i = 0; i < 4; i++)
00488         for (register int j = 0; j < 4; j++)
00489             mat[i][j] = trMat(i,j);
00490     rotation = 1;
00491 }
00492 
00493 
00494 void FDH14::RotInfo::recompute(const Vector3& direction)
00495 {
00496     float backdir[3], dir[3];
00497     
00498     dir[0] = (float) direction.x;
00499     dir[1] = (float) direction.y;
00500     dir[2] = (float) direction.z;
00501     
00502     for (register int i = 0; i < 3; i++) backdir[i] = -dir[i];
00503     
00504     if (rotation == 0) { 
00505         // It is not necessary to compute values if there was not any rotation.
00506         // We can use stored values instead.
00507         if (mat[0][3] == direction.x &&
00508             mat[1][3] == direction.y &&
00509             mat[2][3] == direction.z) return;
00510         if (mat[0][3] == -direction.x &&
00511             mat[1][3] == -direction.y &&
00512             mat[2][3] == -direction.z) return;
00513     }
00514     
00515     delete [] r;
00516     if ((r = new FDH_Precomp [2]) == NULL) return;
00517     
00518     fdh_precomp(&r[0], dir);
00519     fdh_precomp(&r[1], backdir);
00520     r[0].tau = 0;
00521     r[1].tau = 0;
00522     
00523     mat[0][3] = direction.x;
00524     mat[1][3] = direction.y;
00525     mat[2][3] = direction.z;
00526     rotation = 0;
00527 }
00528 
00529 FDH14::RotInfo* FDH14::RotInfo::clone() const
00530 {
00531     FDH14::RotInfo* pRet = new RotInfo();
00532     unsigned        rSize;
00533     
00534     for (register unsigned i = 0; i < 4; i++)
00535         for (register unsigned j = 0; j < 4; j++)
00536             pRet->mat[i][j] = mat[i][j];
00537     
00538     pRet->rotation = rotation;
00539     
00540     if (rotation) rSize = SIZE;
00541     else rSize = 2;
00542     
00543     if ((pRet->r = new FDH_Precomp [ rSize ]) == NULL) {
00544         delete pRet;
00545         return NULL;
00546     }
00547     
00548     for (register unsigned i = 0; i < rSize; i++) pRet->r[i] = r[i];
00549     
00550     return pRet;
00551 }
00552 
00553 Matrix4 FDH14::RotInfo::getMat() const
00554 {
00555     Matrix4 retMat;
00556     for (register unsigned i = 0; i < 4; i++)
00557         for (register unsigned j = 0; j < 4; j++)
00558             retMat.setElement(i,j, mat[i][j]);
00559     return retMat;
00560 }

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