00001 #include <esg/geometry/FDH14.h>
00002 #include <esg/mesh/FDH14Mesh.h>
00003
00004 using namespace esg;
00005
00006 const double FDH14::SCALE = .5773502691896;
00007 const unsigned FDH14::DIRS = 7;
00008 const unsigned FDH14::SIZE = 14;
00009 const float FDH14::FDHMat[14][3] =
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
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
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)
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
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)
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();
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
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
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
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
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 {
00349 if (d[0] <= d[2]) {
00350
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
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
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
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++)
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
00431 for (register unsigned i = 0; i < SIZE; i++) {
00432 for (register int j = 0; j < 3; j++) {
00433 #if 0
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++)
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
00470 for (register unsigned i = 0; i < SIZE; i++) {
00471 for (register int j = 0; j < 3; j++) {
00472 #if 0
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
00506
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 }