00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "UT_VoxelArray.h"
00021 #include <SYS/SYS_Align.h>
00022 #include "UT_BoundingBox.h"
00023 #include "UT_Filter.h"
00024 #include "UT_StackAlloc.h"
00025
00026
00027
00028
00029 inline fpreal16
00030 UTvoxelConvertFP16(fpreal16 a) { return a; }
00031 inline fpreal16
00032 UTvoxelConvertFP16(fpreal32 a) { return a; }
00033 inline fpreal16
00034 UTvoxelConvertFP16(fpreal64 a) { return a; }
00035 inline fpreal16
00036 UTvoxelConvertFP16(int8 a) { return a; }
00037 inline fpreal16
00038 UTvoxelConvertFP16(int16 a) { return a; }
00039 inline fpreal16
00040 UTvoxelConvertFP16(int32 a) { return a; }
00041 inline fpreal16
00042 UTvoxelConvertFP16(int64 a) { return a; }
00043 inline fpreal16
00044 UTvoxelConvertFP16(UT_Vector2 a) { return a.x(); }
00045 inline fpreal16
00046 UTvoxelConvertFP16(UT_Vector3 a) { return a.x(); }
00047 inline fpreal16
00048 UTvoxelConvertFP16(UT_Vector4 a) { return a.x(); }
00049
00050
00051
00052
00053 template <typename T>
00054 void
00055 UT_VoxelTileCompress<T>::findMinMax(const UT_VoxelTile<T> &tile,
00056 T &min, T &max) const
00057 {
00058 int x, y, z;
00059
00060 min = max = getValue(tile, 0, 0, 0);
00061
00062
00063 for (z = 0; z < tile.zres(); z++)
00064 {
00065 for (y = 0; y < tile.yres(); y++)
00066 {
00067 for (x = 0; x < tile.xres(); x++)
00068 {
00069 tile.expandMinMax(getValue(tile, x, y, z), min, max);
00070 }
00071 }
00072 }
00073 return;
00074 }
00075
00076
00077
00078
00079
00080 template <typename T>
00081 UT_VoxelTile<T>::UT_VoxelTile(int xres, int yres, int zres)
00082 {
00083 myRes[0] = xres;
00084 myRes[1] = yres;
00085 myRes[2] = zres;
00086
00087 myCompressionType = COMPRESS_CONSTANT;
00088 myData = SYSamalloc(sizeof(T));
00089
00090
00091
00092
00093
00094 ((T *)myData)[0] = 0;
00095 }
00096
00097 template <typename T>
00098 UT_VoxelTile<T>::~UT_VoxelTile()
00099 {
00100 SYSafree(myData);
00101 }
00102
00103 template <typename T>
00104 UT_VoxelTile<T>::UT_VoxelTile(const UT_VoxelTile<T> &src)
00105 {
00106 myData = 0;
00107
00108
00109 *this = src;
00110 }
00111
00112 template <typename T>
00113 const UT_VoxelTile<T> &
00114 UT_VoxelTile<T>::operator=(const UT_VoxelTile<T> &src)
00115 {
00116 if (&src == this)
00117 return *this;
00118
00119 if (myData)
00120 SYSafree(myData);
00121 myData = 0;
00122
00123 myRes[0] = src.myRes[0];
00124 myRes[1] = src.myRes[1];
00125 myRes[2] = src.myRes[2];
00126
00127 myCompressionType = src.myCompressionType;
00128 switch (myCompressionType)
00129 {
00130 case COMPRESS_RAW:
00131 myData = SYSamalloc(
00132 sizeof(T) * myRes[0] * myRes[1] * myRes[2], 128);
00133 memcpy(myData, src.myData, sizeof(T) * myRes[0] * myRes[1] * myRes[2]);
00134 break;
00135 case COMPRESS_CONSTANT:
00136 myData = SYSamalloc(sizeof(T));
00137 memcpy(myData, src.myData, sizeof(T));
00138 break;
00139 case COMPRESS_RAWFULL:
00140 myData = SYSamalloc(
00141 sizeof(T) * TILESIZE * TILESIZE * TILESIZE, 128);
00142 memcpy(myData, src.myData,
00143 sizeof(T) * TILESIZE * TILESIZE * TILESIZE);
00144 break;
00145 case COMPRESS_FPREAL16:
00146 myData = SYSamalloc(
00147 sizeof(fpreal16) * myRes[0] * myRes[1] * myRes[2], 128);
00148 memcpy(myData, src.myData,
00149 sizeof(fpreal16) * myRes[0] * myRes[1] * myRes[2]);
00150 break;
00151 default:
00152 {
00153 UT_VoxelTileCompress<T> *engine;
00154
00155 engine = getCompressionEngine(myCompressionType);
00156 myData = SYSamalloc(engine->getDataLength(src));
00157 memcpy(myData, src.myData, engine->getDataLength(src));
00158 break;
00159 }
00160 }
00161
00162 return *this;
00163 }
00164
00165 template <typename T>
00166 bool
00167 UT_VoxelTile<T>::writeThrough(int x, int y, int z, T t)
00168 {
00169 switch (myCompressionType)
00170 {
00171 case COMPRESS_RAW:
00172
00173 ((T *)myData)[ ((z * myRes[1]) + y) * myRes[0] + x ] = t;
00174 return true;
00175
00176 case COMPRESS_CONSTANT:
00177 if (*(T *)myData == t)
00178 {
00179
00180 return true;
00181 }
00182 return false;
00183
00184 case COMPRESS_RAWFULL:
00185 ((T *)myData)[ ((z * TILESIZE) + y) * TILESIZE + x ] = t;
00186 return true;
00187
00188 case COMPRESS_FPREAL16:
00189 return false;
00190 }
00191
00192
00193 UT_VoxelTileCompress<T> *engine;
00194
00195 engine = getCompressionEngine(myCompressionType);
00196 return engine->writeThrough(*this, x, y, z, t);
00197 }
00198
00199 template <typename T>
00200 T
00201 UT_VoxelTile<T>::lerp(int x, int y, int z, fpreal32 fx, fpreal32 fy, fpreal32 fz) const
00202 {
00203 T vx, vx1, vy, vy1, vz;
00204
00205 switch (myCompressionType)
00206 {
00207 case COMPRESS_RAW:
00208 case COMPRESS_RAWFULL:
00209 {
00210 T *data = (T *) myData;
00211 int offset = (z * myRes[1] + y) * myRes[0] + x;
00212 int yinc = myRes[0];
00213 int zinc = myRes[0] * myRes[1];
00214
00215
00216 vx = lerpValues(data[offset], data[offset+1], fx);
00217
00218 vx1 = lerpValues(data[offset+yinc], data[offset+yinc+1], fx);
00219
00220
00221 vy = lerpValues(vx, vx1, fy);
00222
00223
00224 vx = lerpValues(data[offset+zinc], data[offset+zinc+1], fx);
00225
00226 vx1 = lerpValues(data[offset+zinc+yinc], data[offset+zinc+yinc+1], fx);
00227
00228
00229 vy1 = lerpValues(vx, vx1, fy);
00230
00231
00232 vz = lerpValues(vy, vy1, fz);
00233 break;
00234 }
00235
00236 case COMPRESS_FPREAL16:
00237 {
00238 fpreal16 *data = (fpreal16 *) myData;
00239 int offset = (z * myRes[1] + y) * myRes[0] + x;
00240 int yinc = myRes[0];
00241 int zinc = myRes[0] * myRes[1];
00242 fpreal16 vx, vx1, vy, vy1, vz;
00243
00244
00245 vx = SYSlerp(data[offset], data[offset+1], fx);
00246
00247 vx1 = SYSlerp(data[offset+yinc], data[offset+yinc+1], fx);
00248
00249
00250 vy = SYSlerp(vx, vx1, fy);
00251
00252
00253 vx = SYSlerp(data[offset+zinc], data[offset+zinc+1], fx);
00254
00255 vx1 = SYSlerp(data[offset+zinc+yinc], data[offset+zinc+yinc+1], fx);
00256
00257
00258 vy1 = SYSlerp(vx, vx1, fy);
00259
00260
00261 vz = lerpValues(vy, vy1, fz);
00262
00263 return T(vz);
00264 }
00265 case COMPRESS_CONSTANT:
00266 {
00267
00268 vz = *(T *) myData;
00269 break;
00270 }
00271
00272 default:
00273 {
00274 UT_VoxelTileCompress<T> *engine;
00275
00276 engine = getCompressionEngine(myCompressionType);
00277
00278 vx = lerpValues(engine->getValue(*this, x, y, z),
00279 engine->getValue(*this, x+1, y, z),
00280 fx);
00281
00282 vx1 = lerpValues(engine->getValue(*this, x, y+1, z),
00283 engine->getValue(*this, x+1, y+1, z),
00284 fx);
00285
00286
00287 vy = lerpValues(vx, vx1, fy);
00288
00289
00290 vx = lerpValues(engine->getValue(*this, x, y, z+1),
00291 engine->getValue(*this, x+1, y, z+1),
00292 fx);
00293
00294 vx1 = lerpValues(engine->getValue(*this, x, y+1, z+1),
00295 engine->getValue(*this, x+1, y+1, z+1),
00296 fx);
00297
00298
00299 vy1 = lerpValues(vx, vx1, fy);
00300
00301
00302 vz = lerpValues(vy, vy1, fz);
00303 break;
00304 }
00305 }
00306
00307 return vz;
00308 }
00309
00310 #if 0
00311 template <typename T>
00312 T
00313 UT_VoxelTile<T>::lerp(v4uf frac, int x, int y, int z) const
00314 {
00315 v4uf a, b;
00316
00317 switch (myCompressionType)
00318 {
00319 case COMPRESS_RAW:
00320 case COMPRESS_RAWFULL:
00321 {
00322 T *data = (T *) myData;
00323 int offset = (z * myRes[1] + y) * myRes[0] + x;
00324 int yinc = myRes[0];
00325 int zinc = myRes[0] * myRes[1];
00326
00327 a = v4uf( data[offset],
00328 data[offset+zinc],
00329 data[offset+yinc],
00330 data[offset+yinc+zinc] );
00331 b = v4uf( data[offset+1],
00332 data[offset+zinc+1],
00333 data[offset+yinc+1],
00334 data[offset+yinc+zinc+1] );
00335 break;
00336 }
00337
00338 case COMPRESS_CONSTANT:
00339 {
00340
00341 return *(T *) myData;
00342 }
00343
00344 default:
00345 {
00346 UT_VoxelTileCompress<T> *engine;
00347
00348 engine = getCompressionEngine(myCompressionType);
00349
00350 a = v4uf( engine->getValue(*this, x, y, z),
00351 engine->getValue(*this, x, y, z+1),
00352 engine->getValue(*this, x, y+1, z),
00353 engine->getValue(*this, x, y+1, z+1) );
00354 b = v4uf( engine->getValue(*this, x+1, y, z),
00355 engine->getValue(*this, x+1, y, z+1),
00356 engine->getValue(*this, x+1, y+1, z),
00357 engine->getValue(*this, x+1, y+1, z+1) );
00358 break;
00359 }
00360 }
00361
00362 v4uf fx, fy, fz;
00363
00364 fx = frac.swizzle<0, 0, 0, 0>();
00365 fy = frac.swizzle<1, 1, 1, 1>();
00366 fz = frac.swizzle<2, 2, 2, 2>();
00367
00368 b -= a;
00369 a = madd(b, fx, a);
00370
00371 b = a.swizzle<2, 3, 0, 1>();
00372 b -= a;
00373 a = madd(b, fy, a);
00374
00375 b = a.swizzle<1, 2, 3, 0>();
00376 b -= a;
00377 a = madd(b, fz, a);
00378
00379 return a[0];
00380 }
00381 #endif
00382
00383 template <typename T>
00384 T *
00385 UT_VoxelTile<T>::fillCacheLine(T *cacheline, int &stride, int x, int y, int z, bool forcecopy, bool strideofone) const
00386 {
00387 UT_ASSERT_P(x >= 0 && y >= 0 && z >= 0);
00388 UT_ASSERT_P(x < myRes[0] && y < myRes[1] && z < myRes[2]);
00389
00390 T *src;
00391 int i, xres = myRes[0];
00392
00393
00394 switch (myCompressionType)
00395 {
00396 case COMPRESS_RAW:
00397 stride = 1;
00398 src = (T *)myData + (z * myRes[1] + y) * xres;
00399 if (!forcecopy)
00400 return &src[x];
00401
00402 for (i = 0; i < xres; i++)
00403 cacheline[i] = src[i];
00404
00405 return &cacheline[x];
00406
00407 case COMPRESS_FPREAL16:
00408 {
00409 fpreal16 *src;
00410
00411 stride = 1;
00412 src = (fpreal16 *)myData + (z * myRes[1] + y) * xres;
00413
00414 for (i = 0; i < xres; i++)
00415 cacheline[i] = src[i];
00416
00417 return &cacheline[x];
00418 }
00419
00420
00421 case COMPRESS_CONSTANT:
00422 src = (T *) myData;
00423 if (!forcecopy && !strideofone)
00424 {
00425 stride = 0;
00426 return src;
00427 }
00428 stride = 1;
00429
00430 for (i = 0; i < xres; i++)
00431 cacheline[i] = *src;
00432
00433 return &cacheline[x];
00434
00435
00436 case COMPRESS_RAWFULL:
00437 stride = 1;
00438 src = (T *)myData + (z * TILESIZE + y) * TILESIZE;
00439 if (!forcecopy)
00440 return &src[x];
00441
00442 for (i = 0; i < xres; i++)
00443 cacheline[i] = src[i];
00444
00445 return &cacheline[x];
00446 }
00447
00448
00449 UT_VoxelTileCompress<T> *engine;
00450
00451 engine = getCompressionEngine(myCompressionType);
00452
00453
00454
00455 stride = 1;
00456 for (i = 0; i < xres; i++)
00457 cacheline[i] = engine->getValue(*this, i, y, z);
00458
00459 return &cacheline[x];
00460 }
00461
00462 template <typename T>
00463 void
00464 UT_VoxelTile<T>::writeCacheLine(T *cacheline, int y, int z)
00465 {
00466 UT_ASSERT_P(y >= 0 && z >= 0);
00467 UT_ASSERT_P(y < myRes[1] && z < myRes[2]);
00468
00469 T *dst, value;
00470 int i, xres = myRes[0];
00471
00472
00473 switch (myCompressionType)
00474 {
00475 case COMPRESS_RAW:
00476 dst = (T *)myData + (z * myRes[1] + y) * xres;
00477 for (i = 0; i < xres; i++)
00478 *dst++ = *cacheline++;
00479 return;
00480
00481 case COMPRESS_CONSTANT:
00482 value = *(T *) myData;
00483 for (i = 0; i < xres; i++)
00484 if (cacheline[i] != value)
00485 break;
00486
00487 if (i == xres)
00488 return;
00489
00490 break;
00491
00492 case COMPRESS_RAWFULL:
00493 dst = (T *)myData + (z * TILESIZE + y) * TILESIZE;
00494 for (i = 0; i < TILESIZE; i++)
00495 *dst++ = *cacheline++;
00496
00497 return;
00498 }
00499
00500
00501
00502 for (i = 0; i < xres; i++)
00503 if (!writeThrough(i, y, z, cacheline[i]))
00504 break;
00505
00506
00507 if (i != xres)
00508 {
00509
00510 uncompress();
00511 writeCacheLine(cacheline, y, z);
00512 }
00513 }
00514
00515 template <typename T>
00516 void
00517 UT_VoxelTile<T>::setValue(int x, int y, int z, T t)
00518 {
00519 UT_ASSERT_P(x >= 0 && y >= 0 && z >= 0);
00520 UT_ASSERT_P(x < myRes[0] && y < myRes[1] && z < myRes[2]);
00521
00522
00523
00524 if (writeThrough(x, y, z, t))
00525 {
00526 return;
00527 }
00528
00529
00530 uncompress();
00531
00532
00533
00534 bool success;
00535
00536 success = writeThrough(x, y, z, t);
00537 UT_ASSERT_P(success);
00538 }
00539
00540 template <typename T>
00541 void
00542 UT_VoxelTile<T>::uncompress()
00543 {
00544 switch (myCompressionType)
00545 {
00546 case COMPRESS_RAW:
00547
00548 return;
00549
00550 case COMPRESS_CONSTANT:
00551 {
00552
00553 T cval;
00554 int i, n;
00555
00556 myCompressionType = COMPRESS_RAW;
00557
00558 if (myRes[0] == TILESIZE &&
00559 myRes[1] == TILESIZE &&
00560 myRes[2] == TILESIZE)
00561 {
00562
00563 myCompressionType = COMPRESS_RAWFULL;
00564 }
00565
00566 cval = *(T *)myData;
00567 SYSafree(myData);
00568 n = myRes[0] * myRes[1] * myRes[2];
00569 myData = SYSamalloc(sizeof(T) * n, 128);
00570
00571 for (i = 0; i < n; i++)
00572 {
00573 ((T *)myData)[i] = cval;
00574 }
00575 return;
00576 }
00577 case COMPRESS_RAWFULL:
00578 {
00579 T *raw;
00580 int x, y, z, i, n;
00581
00582 if (myRes[0] == TILESIZE &&
00583 myRes[1] == TILESIZE &&
00584 myRes[2] == TILESIZE)
00585 {
00586
00587 return;
00588 }
00589
00590
00591 myCompressionType = COMPRESS_RAW;
00592
00593 n = myRes[0] * myRes[1] * myRes[2];
00594 raw = (T *)SYSamalloc(sizeof(T) * n, 128);
00595 i = 0;
00596 for (z = 0; z < myRes[2]; z++)
00597 {
00598 for (y = 0; y < myRes[1]; y++)
00599 {
00600 for (x = 0; x < myRes[0]; x++)
00601 {
00602 raw[i++] = ((T *)myData)[x+(y+z*TILESIZE)*TILESIZE];
00603 }
00604 }
00605 }
00606 SYSafree(myData);
00607 myData = raw;
00608
00609 return;
00610 }
00611
00612 case COMPRESS_FPREAL16:
00613 {
00614 T *raw;
00615 int x, y, z, i, n;
00616 fpreal16 *src = (fpreal16 *) myData;
00617
00618 myCompressionType = COMPRESS_RAW;
00619
00620 n = myRes[0] * myRes[1] * myRes[2];
00621 raw = (T *)SYSamalloc(sizeof(T) * n, 128);
00622 i = 0;
00623 for (z = 0; z < myRes[2]; z++)
00624 {
00625 for (y = 0; y < myRes[1]; y++)
00626 {
00627 for (x = 0; x < myRes[0]; x++)
00628 {
00629 raw[i] = src[i];
00630 i++;
00631 }
00632 }
00633 }
00634 SYSafree(myData);
00635 myData = raw;
00636 return;
00637 }
00638 }
00639
00640
00641 UT_VoxelTileCompress<T> *engine;
00642
00643 engine = getCompressionEngine(myCompressionType);
00644
00645
00646 int x, y, z, i;
00647 T *raw;
00648
00649 raw = (T *) SYSamalloc(sizeof(T) * myRes[0] * myRes[1] * myRes[2], 128);
00650 i = 0;
00651 for (z = 0; z < myRes[2]; z++)
00652 {
00653 for (y = 0; y < myRes[1]; y++)
00654 {
00655 for (x = 0; x < myRes[0]; x++)
00656 {
00657 raw[i++] = engine->getValue(*this, x, y, z);
00658 }
00659 }
00660 }
00661
00662
00663 myCompressionType = COMPRESS_RAW;
00664 if (myRes[0] == TILESIZE &&
00665 myRes[1] == TILESIZE &&
00666 myRes[2] == TILESIZE)
00667 {
00668
00669 myCompressionType = COMPRESS_RAWFULL;
00670 }
00671
00672 SYSafree(myData);
00673 myData = raw;
00674 }
00675
00676 template <typename T>
00677 void
00678 UT_VoxelTile<T>::uncompressFull()
00679 {
00680 T *raw;
00681 int x, y, z, i;
00682
00683 if (myCompressionType == COMPRESS_RAWFULL)
00684 return;
00685
00686 uncompress();
00687
00688 UT_ASSERT(myCompressionType == COMPRESS_RAW);
00689
00690 myCompressionType = COMPRESS_RAWFULL;
00691
00692
00693
00694 if (myRes[0] < TILESIZE || myRes[1] < TILESIZE || myRes[2] < TILESIZE)
00695 {
00696 raw = (T *)SYSamalloc(sizeof(T) * TILESIZE * TILESIZE * TILESIZE, 128);
00697 i = 0;
00698 for (z = 0; z < myRes[2]; z++)
00699 {
00700 for (y = 0; y < myRes[1]; y++)
00701 {
00702 for (x = 0; x < myRes[0]; x++)
00703 {
00704 raw[x+(y+z*TILESIZE)*TILESIZE] = ((T *)myData)[i++];
00705 }
00706 }
00707 }
00708 SYSafree(myData);
00709 myData = raw;
00710 }
00711 }
00712
00713 template <typename T>
00714 void
00715 UT_VoxelTile<T>::findAverage(T &avg) const
00716 {
00717 float irx, iry, irz;
00718
00719 irx = 1.0 / myRes[0];
00720 iry = 1.0 / myRes[1];
00721 irz = 1.0 / myRes[2];
00722 switch (myCompressionType)
00723 {
00724 case COMPRESS_RAW:
00725 {
00726 int i;
00727 const T *data = (const T*) myData;
00728
00729 i = 0;
00730 T zavg;
00731 zavg = 0;
00732 for (int z = 0; z < myRes[2]; z++)
00733 {
00734 T yavg;
00735 yavg = 0;
00736 for (int y = 0; y < myRes[1]; y++)
00737 {
00738 T xavg;
00739 xavg = 0;
00740 for (int x = 0; x < myRes[0]; x++)
00741 {
00742 xavg += data[i++];
00743 }
00744 xavg *= irx;
00745 yavg += xavg;
00746 }
00747 yavg *= iry;
00748 zavg += yavg;
00749 }
00750 zavg *= irz;
00751
00752 avg = zavg;
00753 return;
00754 }
00755
00756 case COMPRESS_FPREAL16:
00757 {
00758 int i;
00759 const fpreal16 *data = (fpreal16 *) myData;
00760
00761 i = 0;
00762 fpreal16 zavg = 0;
00763 for (int z = 0; z < myRes[2]; z++)
00764 {
00765 fpreal16 yavg = 0;
00766 for (int y = 0; y < myRes[1]; y++)
00767 {
00768 fpreal16 xavg = 0;
00769 for (int x = 0; x < myRes[0]; x++)
00770 {
00771 xavg += data[i++];
00772 }
00773 xavg *= irx;
00774 yavg += xavg;
00775 }
00776 yavg *= iry;
00777 zavg += yavg;
00778 }
00779 zavg *= irz;
00780
00781 avg = zavg;
00782 return;
00783 }
00784
00785 case COMPRESS_CONSTANT:
00786 avg = *(T*)myData;
00787 return;
00788
00789 case COMPRESS_RAWFULL:
00790 {
00791 int offset;
00792 const T *data = (const T*) myData;
00793
00794 offset = 0;
00795 T zavg;
00796 zavg = 0;
00797 for (int z = 0; z < myRes[2]; z++)
00798 {
00799 T yavg;
00800 yavg = 0;
00801 for (int y = 0; y < myRes[1]; y++)
00802 {
00803 T xavg;
00804 xavg = 0;
00805 for (int x = 0; x < myRes[0]; x++)
00806 {
00807 xavg += data[x+offset];
00808 }
00809 xavg *= irx;
00810 yavg += xavg;
00811 offset += TILESIZE;
00812 }
00813 yavg *= iry;
00814 zavg += yavg;
00815 }
00816 zavg *= irz;
00817
00818 avg = zavg;
00819 return;
00820 }
00821
00822 default:
00823 {
00824 T zavg;
00825 zavg = 0;
00826 for (int z = 0; z < myRes[2]; z++)
00827 {
00828 T yavg;
00829 yavg = 0;
00830 for (int y = 0; y < myRes[1]; y++)
00831 {
00832 T xavg;
00833 xavg = 0;
00834 for (int x = 0; x < myRes[0]; x++)
00835 {
00836 xavg += (*this)(x, y, z);
00837 }
00838 xavg *= irx;
00839 yavg += xavg;
00840 }
00841 yavg *= iry;
00842 zavg += yavg;
00843 }
00844 zavg *= irz;
00845
00846 avg = zavg;
00847 return;
00848 }
00849 }
00850 }
00851
00852 template <typename T>
00853 void
00854 UT_VoxelTile<T>::findMinMax(T &min, T &max) const
00855 {
00856 switch (myCompressionType)
00857 {
00858 case COMPRESS_RAW:
00859 {
00860 int n = myRes[0] * myRes[1] * myRes[2];
00861 int i;
00862
00863 min = max = *(T*)myData;
00864 for (i = 1; i < n; i++)
00865 {
00866 expandMinMax( ((T*)myData)[i], min, max );
00867 }
00868 return;
00869 }
00870
00871 case COMPRESS_FPREAL16:
00872 {
00873 int n = myRes[0] * myRes[1] * myRes[2];
00874 int i;
00875 fpreal16 *src = (fpreal16 *)myData;
00876
00877 min = max = *src;
00878 for (i = 1; i < n; i++)
00879 {
00880 T val;
00881 val = src[i];
00882 expandMinMax( val, min, max );
00883 }
00884 return;
00885 }
00886
00887 case COMPRESS_CONSTANT:
00888 min = max = *(T*)myData;
00889 return;
00890
00891 case COMPRESS_RAWFULL:
00892 {
00893 int x, y, z, offset;
00894
00895 min = max = *(T*)myData;
00896 offset = 0;
00897 for (z = 0; z < myRes[2]; z++)
00898 {
00899 for (y = 0; y < myRes[1]; y++)
00900 {
00901 for (x = 0; x < myRes[0]; x++)
00902 {
00903 expandMinMax(
00904 ((T*)myData)[x+offset],
00905 min, max );
00906 }
00907 offset += TILESIZE;
00908 }
00909 }
00910 return;
00911 }
00912
00913 default:
00914 {
00915
00916 UT_VoxelTileCompress<T> *engine;
00917
00918 engine = getCompressionEngine(myCompressionType);
00919
00920 engine->findMinMax(*this, min, max);
00921 return;
00922 }
00923 }
00924 }
00925
00926 template <typename T>
00927 bool
00928 UT_VoxelTile<T>::hasNan() const
00929 {
00930 switch (myCompressionType)
00931 {
00932 case COMPRESS_RAW:
00933 case COMPRESS_RAWFULL:
00934 {
00935 int n = myRes[0] * myRes[1] * myRes[2];
00936 int i;
00937
00938 for (i = 0; i < n; i++)
00939 {
00940 if (SYSisNan( ((T*)myData)[i] ))
00941 return true;
00942 }
00943 return false;
00944 }
00945
00946 case COMPRESS_FPREAL16:
00947 {
00948 return false;
00949 }
00950
00951 case COMPRESS_CONSTANT:
00952 if (SYSisNan(*(T*)myData))
00953 return true;
00954 return false;
00955
00956 default:
00957 {
00958
00959 UT_VoxelTileCompress<T> *engine;
00960 int x, y, z;
00961
00962 engine = getCompressionEngine(myCompressionType);
00963
00964 for (z = 0; z < myRes[2]; z++)
00965 for (y = 0; y < myRes[1]; y++)
00966 for (x = 0; x < myRes[0]; x++)
00967 if (SYSisNan(engine->getValue(*this, x, y, z)))
00968 {
00969 return true;
00970 }
00971
00972 return false;
00973 }
00974 }
00975 }
00976
00977 template <typename T>
00978 bool
00979 UT_VoxelTile<T>::tryCompress(const UT_VoxelCompressOptions &options)
00980 {
00981 T min, max;
00982 bool losslessonly = (options.myQuantizeTol == 0.0);
00983 int i;
00984 UT_VoxelTileCompress<T> *engine;
00985
00986
00987 if (myCompressionType == COMPRESS_CONSTANT)
00988 return false;
00989
00990 findMinMax(min, max);
00991
00992
00993 if (dist(min, max) <= options.myConstantTol)
00994 {
00995
00996 if (myCompressionType == COMPRESS_CONSTANT)
00997 return false;
00998
00999
01000 if (min != max)
01001 {
01002 T avg;
01003 findAverage(avg);
01004 makeConstant(avg);
01005 }
01006 else
01007 {
01008 makeConstant(min);
01009 }
01010 return true;
01011 }
01012
01013 bool result = false;
01014
01015 if (options.myAllowFP16)
01016 {
01017 if (myCompressionType == COMPRESS_RAW ||
01018 myCompressionType == COMPRESS_RAWFULL)
01019 {
01020 makeFpreal16();
01021 result = true;
01022 }
01023 }
01024
01025 for (i = 0; i < getCompressionEngines().entries(); i++)
01026 {
01027 engine = getCompressionEngines()(i);
01028
01029
01030 if (losslessonly && !engine->isLossless())
01031 continue;
01032
01033 if (engine->tryCompress(*this, options, min, max))
01034 {
01035 myCompressionType = i + COMPRESS_ENGINE;
01036 result = true;
01037
01038
01039 }
01040 }
01041
01042
01043 return result;
01044 }
01045
01046 template <typename T>
01047 void
01048 UT_VoxelTile<T>::makeConstant(T t)
01049 {
01050 if (!isConstant())
01051 {
01052 SYSafree(myData);
01053 myData = SYSamalloc(sizeof(T));
01054 }
01055
01056 *(T*)myData = t;
01057 myCompressionType = COMPRESS_CONSTANT;
01058 }
01059
01060 template <typename T>
01061 void
01062 UT_VoxelTile<T>::makeFpreal16()
01063 {
01064 if (isConstant())
01065 {
01066 return;
01067 }
01068
01069 if (myCompressionType == COMPRESS_FPREAL16)
01070 return;
01071
01072
01073 int len = myRes[2] * myRes[1] * myRes[0];
01074 fpreal16 *data = (fpreal16 *)SYSamalloc(sizeof(fpreal16) * len, 128);
01075
01076 if (myCompressionType == COMPRESS_RAW ||
01077 myCompressionType == COMPRESS_RAWFULL)
01078 {
01079 for (int i = 0; i < len; i++)
01080 {
01081 data[i] = UTvoxelConvertFP16( ((T*)myData)[i] );
01082 }
01083 }
01084 else
01085 {
01086
01087 int i = 0;
01088
01089 for (int z = 0; z < myRes[2]; z++)
01090 {
01091 for (int y = 0; y < myRes[1]; y++)
01092 {
01093 for (int x = 0; x < myRes[0]; x++)
01094 {
01095 data[i++] = UTvoxelConvertFP16( (*this)(x, y, z));
01096 }
01097 }
01098 }
01099 }
01100
01101 SYSafree(myData);
01102 myData = data;
01103 myCompressionType = COMPRESS_FPREAL16;
01104 }
01105
01106 template <typename T>
01107 int64
01108 UT_VoxelTile<T>::getMemoryUsage() const
01109 {
01110 int64 usage;
01111
01112 usage = sizeof(*this);
01113 usage += getDataLength();
01114 return usage;
01115 }
01116
01117 template <typename T>
01118 int64
01119 UT_VoxelTile<T>::getDataLength() const
01120 {
01121 int64 usage;
01122
01123 switch (myCompressionType)
01124 {
01125 case COMPRESS_RAW:
01126 usage = sizeof(T) * xres() * yres() * zres();
01127 break;
01128 case COMPRESS_FPREAL16:
01129 usage = sizeof(fpreal16) * xres() * yres() * zres();
01130 break;
01131 case COMPRESS_CONSTANT:
01132 usage = sizeof(T);
01133 break;
01134 case COMPRESS_RAWFULL:
01135 usage = sizeof(T) * TILESIZE * TILESIZE * TILESIZE;
01136 break;
01137 default:
01138 {
01139
01140 UT_VoxelTileCompress<T> *engine;
01141 engine = getCompressionEngine(myCompressionType);
01142 usage = engine->getDataLength(*this);
01143 break;
01144 }
01145 }
01146 return usage;
01147 }
01148
01149 template <typename T>
01150 void
01151 UT_VoxelTile<T>::weightedSum(int pstart[3], int pend[3],
01152 float *weights[3], int start[3],
01153 T &result)
01154 {
01155 int ix, iy, iz, i;
01156 int px, py, pz;
01157 int ixstart, ixend;
01158 int tstart[3];
01159 fpreal w, pw;
01160 T psumx, psumy;
01161
01162 switch (myCompressionType)
01163 {
01164 case COMPRESS_CONSTANT:
01165 {
01166 w = 1;
01167 for (i = 0; i < 3; i++)
01168 {
01169 pw = 0;
01170 for (ix = 0; ix < pend[i]-pstart[i]; ix++)
01171 pw += weights[i][ix+pstart[i]-start[i]];
01172 w *= pw;
01173 }
01174 result += w * ((T*)myData)[0];
01175 break;
01176 }
01177
01178 case COMPRESS_RAW:
01179 {
01180 tstart[0] = pstart[0] & TILEMASK;
01181 tstart[1] = pstart[1] & TILEMASK;
01182 tstart[2] = pstart[2] & TILEMASK;
01183 ixstart = pstart[0]-start[0];
01184 ixend = pend[0]-start[0];
01185 pz = tstart[2];
01186 UT_ASSERT(pz < myRes[2]);
01187 UT_ASSERT(ixend - ixstart <= myRes[0]);
01188 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
01189 {
01190 psumy = 0;
01191 py = tstart[1];
01192 UT_ASSERT(py < myRes[1]);
01193 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
01194 {
01195 psumx = 0;
01196 px = ((pz * myRes[1]) + py) * myRes[0] + tstart[0];
01197 for (ix = ixstart; ix < ixend; ix++, px++)
01198 {
01199 psumx += weights[0][ix]* ((T*)myData)[px];
01200 }
01201 psumy += weights[1][iy-start[1]] * psumx;
01202 }
01203 result += weights[2][iz-start[2]] * psumy;
01204 }
01205 break;
01206 }
01207
01208 case COMPRESS_FPREAL16:
01209 {
01210 fpreal16 *src = (fpreal16 *) myData;
01211
01212 tstart[0] = pstart[0] & TILEMASK;
01213 tstart[1] = pstart[1] & TILEMASK;
01214 tstart[2] = pstart[2] & TILEMASK;
01215 ixstart = pstart[0]-start[0];
01216 ixend = pend[0]-start[0];
01217 pz = tstart[2];
01218 UT_ASSERT(pz < myRes[2]);
01219 UT_ASSERT(ixend - ixstart <= myRes[0]);
01220 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
01221 {
01222 psumy = 0;
01223 py = tstart[1];
01224 UT_ASSERT(py < myRes[1]);
01225 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
01226 {
01227 psumx = 0;
01228 px = ((pz * myRes[1]) + py) * myRes[0] + tstart[0];
01229 for (ix = ixstart; ix < ixend; ix++, px++)
01230 {
01231 T val;
01232 val = src[px];
01233 psumx += weights[0][ix]* val;
01234 }
01235 psumy += weights[1][iy-start[1]] * psumx;
01236 }
01237 result += weights[2][iz-start[2]] * psumy;
01238 }
01239 break;
01240 }
01241 case COMPRESS_RAWFULL:
01242 {
01243 tstart[0] = pstart[0] & TILEMASK;
01244 tstart[1] = pstart[1] & TILEMASK;
01245 tstart[2] = pstart[2] & TILEMASK;
01246 ixstart = pstart[0]-start[0];
01247 ixend = pend[0]-start[0];
01248 pz = tstart[2];
01249 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
01250 {
01251 psumy = 0;
01252 py = tstart[1];
01253 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
01254 {
01255 psumx = 0;
01256 px = ((pz * TILESIZE) + py) * TILESIZE + tstart[0];
01257 for (ix = ixstart; ix < ixend; ix++, px++)
01258 {
01259 psumx += weights[0][ix]* ((T*)myData)[px];
01260 }
01261 psumy += weights[1][iy-start[1]] * psumx;
01262 }
01263 result += weights[2][iz-start[2]] * psumy;
01264 }
01265 break;
01266 }
01267
01268 default:
01269 {
01270
01271
01272
01273 tstart[0] = pstart[0] & TILEMASK;
01274 tstart[1] = pstart[1] & TILEMASK;
01275 tstart[2] = pstart[2] & TILEMASK;
01276 ixstart = pstart[0]-start[0];
01277 ixend = pend[0]-start[0];
01278 pz = tstart[2];
01279 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
01280 {
01281 psumy = 0;
01282 py = tstart[1];
01283 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
01284 {
01285 psumx = 0;
01286 px = tstart[0];
01287 for (ix = ixstart; ix < ixend; ix++, px++)
01288 {
01289 psumx += weights[0][ix] *
01290 (*this)(px, py, pz);
01291 }
01292 psumy += weights[1][iy-start[1]] * psumx;
01293 }
01294 result += weights[2][iz-start[2]] * psumy;
01295 }
01296 break;
01297 }
01298 }
01299 }
01300
01301 template <typename T>
01302 void
01303 UT_VoxelTile<T>::registerCompressionEngine(UT_VoxelTileCompress<T> *engine)
01304 {
01305 int i;
01306
01307
01308 for (i = 0; i < getCompressionEngines().entries(); i++)
01309 {
01310 if (!strcmp(engine->getName(), getCompressionEngines()(i)->getName()))
01311 {
01312 getCompressionEngines()(i) = engine;
01313 return;
01314 }
01315 }
01316
01317 getCompressionEngines().append(engine);
01318 }
01319
01320 template <typename T>
01321 int
01322 UT_VoxelTile<T>::lookupCompressionEngine(const char *name)
01323 {
01324 int i;
01325
01326 if (!name)
01327 return -1;
01328
01329 for (i = 0; i < getCompressionEngines().entries(); i++)
01330 {
01331 if (!strcmp(name, getCompressionEngines()(i)->getName()))
01332 {
01333 return i + COMPRESS_ENGINE;
01334 }
01335 }
01336
01337 return -1;
01338 }
01339
01340 template <typename T>
01341 UT_VoxelTileCompress<T> *
01342 UT_VoxelTile<T>::getCompressionEngine(int index)
01343 {
01344 index -= COMPRESS_ENGINE;
01345
01346 return getCompressionEngines()(index);
01347 }
01348
01349 template <typename T>
01350 void
01351 UT_VoxelTile<T>::save(ostream &os)
01352 {
01353
01354 if (myCompressionType >= COMPRESS_ENGINE)
01355 {
01356 UT_VoxelTileCompress<T> *engine = getCompressionEngine(myCompressionType);
01357
01358 if (engine->canSave())
01359 {
01360 char type = myCompressionType;
01361
01362 UTwrite(os, &type, 1);
01363 engine->save(os, *this);
01364 return;
01365 }
01366
01367
01368 uncompress();
01369 }
01370
01371 int len;
01372 char type = myCompressionType;
01373
01374 UT_ASSERT(type >= 0 && type < COMPRESS_ENGINE);
01375
01376 UTwrite(os, &type, 1);
01377
01378 switch (myCompressionType)
01379 {
01380 case COMPRESS_RAW:
01381 len = myRes[2] * myRes[1] * myRes[0];
01382 UTwrite(os, (T *) myData, len);
01383 break;
01384
01385 case COMPRESS_FPREAL16:
01386 len = myRes[2] * myRes[1] * myRes[0];
01387 UTwrite(os, (int16 *) myData, len);
01388 break;
01389
01390 case COMPRESS_RAWFULL:
01391 len = TILESIZE * TILESIZE * TILESIZE;
01392 UTwrite(os, (T *) myData, len);
01393 break;
01394
01395 case COMPRESS_CONSTANT:
01396 UTwrite(os, (T *) myData, 1);
01397 break;
01398 }
01399 }
01400
01401 template <typename T>
01402 void
01403 UT_VoxelTile<T>::load(UT_IStream &is, const UT_IntArray &compress)
01404 {
01405 char type, otype;
01406 int len;
01407
01408 is.readChar(type);
01409
01410
01411 if (type >= 0 && type < compress.entries())
01412 {
01413 otype = type;
01414 type = compress(type);
01415 if (type == -1)
01416 {
01417 cerr << "Missing compression engine " << (int) otype << endl;
01418 }
01419 }
01420
01421 if (type >= COMPRESS_ENGINE)
01422 {
01423 myCompressionType = type;
01424
01425 UT_VoxelTileCompress<T> *engine = getCompressionEngine(myCompressionType);
01426
01427 engine->load(is, *this);
01428
01429 return;
01430 }
01431
01432 UT_ASSERT(type >= 0);
01433 if (type < 0)
01434 {
01435 return;
01436 }
01437
01438 if (myData)
01439 SYSafree(myData);
01440
01441 myCompressionType = type;
01442
01443 switch (myCompressionType)
01444 {
01445 case COMPRESS_RAW:
01446 len = myRes[2] * myRes[1] * myRes[0];
01447 myData = SYSamalloc(sizeof(T) * len, 128);
01448 is.read((T *) myData, len);
01449 break;
01450
01451 case COMPRESS_FPREAL16:
01452 len = myRes[2] * myRes[1] * myRes[0];
01453 myData = SYSamalloc(sizeof(fpreal16) * len, 128);
01454 is.read((int16 *) myData, len);
01455 break;
01456
01457 case COMPRESS_RAWFULL:
01458 len = TILESIZE * TILESIZE * TILESIZE;
01459 myData = SYSamalloc(sizeof(T) * len, 128);
01460 is.read((T *) myData, len);
01461 break;
01462
01463 case COMPRESS_CONSTANT:
01464 myData = SYSamalloc(sizeof(T));
01465 is.read((T *) myData, 1);
01466 break;
01467 }
01468 }
01469
01470 template <typename T>
01471 void
01472 UT_VoxelTile<T>::saveCompressionTypes(ostream &os)
01473 {
01474 int16 ntype = getCompressionEngines().entries();
01475 int i;
01476
01477 ntype += COMPRESS_ENGINE;
01478
01479 UTwrite(os, &ntype);
01480
01481 UT_ASSERT(COMPRESS_ENGINE == 4);
01482 UTsaveStringBinary(os, "raw", UT_STRING_8BIT_IO);
01483 UTsaveStringBinary(os, "rawfull", UT_STRING_8BIT_IO);
01484 UTsaveStringBinary(os, "constant", UT_STRING_8BIT_IO);
01485 UTsaveStringBinary(os, "fpreal16", UT_STRING_8BIT_IO);
01486
01487 ntype -= COMPRESS_ENGINE;
01488 for (i = 0; i < ntype; i++)
01489 {
01490 UTsaveStringBinary(os, getCompressionEngines()(i)->getName(), UT_STRING_8BIT_IO);
01491 }
01492 }
01493
01494 template <typename T>
01495 void
01496 UT_VoxelTile<T>::loadCompressionTypes(UT_IStream &is, UT_IntArray &compress)
01497 {
01498 int16 ntype;
01499 int i, idx;
01500
01501 compress.entries(0);
01502
01503 is.read(&ntype);
01504
01505 for (i = 0; i < ntype; i++)
01506 {
01507 UT_String name;
01508
01509 is.readBinaryString(name, UT_ISTREAM_8BIT_IO);
01510 if (name == "raw")
01511 compress.append(COMPRESS_RAW);
01512 else if (name == "rawfull")
01513 compress.append(COMPRESS_RAWFULL);
01514 else if (name == "constant")
01515 compress.append(COMPRESS_CONSTANT);
01516 else if (name == "fpreal16")
01517 compress.append(COMPRESS_FPREAL16);
01518 else
01519 {
01520 idx = lookupCompressionEngine(name);
01521
01522
01523
01524
01525 compress.append(idx);
01526 }
01527 }
01528 }
01529
01530
01531
01532
01533
01534
01535
01536 template <typename T>
01537 UT_VoxelArray<T>::UT_VoxelArray()
01538 {
01539 myRes[0] = 0;
01540 myRes[1] = 0;
01541 myRes[2] = 0;
01542 myTileRes[0] = 0;
01543 myTileRes[1] = 0;
01544 myTileRes[2] = 0;
01545
01546 myTiles = 0;
01547
01548 myBorderValue = 0;
01549 myBorderScale[0] = 0;
01550 myBorderScale[1] = 0;
01551 myBorderScale[2] = 0;
01552 myBorderType = UT_VOXELBORDER_STREAK;
01553 }
01554
01555 template <typename T>
01556 UT_VoxelArray<T>::~UT_VoxelArray()
01557 {
01558 deleteVoxels();
01559 }
01560
01561 template <typename T>
01562 UT_VoxelArray<T>::UT_VoxelArray(const UT_VoxelArray<T> &src)
01563 {
01564 myRes[0] = 0;
01565 myRes[1] = 0;
01566 myRes[2] = 0;
01567 myTileRes[0] = 0;
01568 myTileRes[1] = 0;
01569 myTileRes[2] = 0;
01570
01571 myTiles = 0;
01572
01573 *this = src;
01574 }
01575
01576 template <typename T>
01577 const UT_VoxelArray<T> &
01578 UT_VoxelArray<T>::operator=(const UT_VoxelArray<T> &src)
01579 {
01580
01581 if (&src == this)
01582 return *this;
01583
01584
01585
01586 deleteVoxels();
01587
01588 myBorderScale[0] = src.myBorderScale[0];
01589 myBorderScale[1] = src.myBorderScale[1];
01590 myBorderScale[2] = src.myBorderScale[2];
01591 myBorderValue = src.myBorderValue;
01592 myBorderType = src.myBorderType;
01593
01594 myCompressionOptions = src.myCompressionOptions;
01595
01596
01597 size(src.myRes[0], src.myRes[1], src.myRes[2]);
01598
01599 int i, ntiles;
01600
01601 ntiles = numTiles();
01602
01603 for (i = 0; i < ntiles; i++)
01604 {
01605 *myTiles[i] = *src.myTiles[i];
01606 }
01607
01608 return *this;
01609 }
01610
01611 template <typename T>
01612 void
01613 UT_VoxelArray<T>::deleteVoxels()
01614 {
01615 int i, n;
01616
01617 n = numTiles();
01618 for (i = 0; i < n; i++)
01619 delete myTiles[i];
01620 delete [] myTiles;
01621 myTiles = 0;
01622
01623 myTileRes[0] = myTileRes[1] = myTileRes[2] = 0;
01624 myRes[0] = myRes[1] = myRes[2] = 0;
01625 }
01626
01627 template <typename T>
01628 void
01629 UT_VoxelArray<T>::size(int xres, int yres, int zres)
01630 {
01631 deleteVoxels();
01632
01633 myRes[0] = xres;
01634 myRes[1] = yres;
01635 myRes[2] = zres;
01636
01637
01638 myTileRes[0] = (xres + TILEMASK) >> TILEBITS;
01639 myTileRes[1] = (yres + TILEMASK) >> TILEBITS;
01640 myTileRes[2] = (zres + TILEMASK) >> TILEBITS;
01641
01642 int ntiles;
01643
01644 ntiles = myTileRes[0] * myTileRes[1] * myTileRes[2];
01645
01646 if (ntiles)
01647 {
01648 myTiles = new UT_VoxelTile<T> *[ntiles];
01649
01650 int tx, ty, tz, i;
01651 int xr, yr, zr;
01652
01653 i = 0;
01654 for (tz = 0; tz < myTileRes[2]; tz++)
01655 {
01656 if (tz < myTileRes[2]-1)
01657 zr = TILESIZE;
01658 else
01659 zr = zres - tz * TILESIZE;
01660
01661 for (ty = 0; ty < myTileRes[1]; ty++)
01662 {
01663 if (ty < myTileRes[1]-1)
01664 yr = TILESIZE;
01665 else
01666 yr = yres - ty * TILESIZE;
01667
01668 xr = TILESIZE;
01669 for (tx = 0; tx < myTileRes[0]-1; tx++)
01670 {
01671 myTiles[i] = new UT_VoxelTile<T>(xr, yr, zr);
01672
01673 i++;
01674 }
01675 xr = xres - tx * TILESIZE;
01676 myTiles[i] = new UT_VoxelTile<T>(xr, yr, zr);
01677 i++;
01678 }
01679 }
01680 }
01681 else
01682 myTiles = 0;
01683 }
01684
01685 template <typename T>
01686 void
01687 UT_VoxelArray<T>::match(const UT_VoxelArray<T> &src)
01688 {
01689
01690 if (src.getXRes() != getXRes() ||
01691 src.getYRes() != getYRes() ||
01692 src.getZRes() != getZRes())
01693 {
01694 size(src.getXRes(), src.getYRes(), src.getZRes());
01695 }
01696
01697
01698 myBorderType = src.myBorderType;
01699 myBorderScale[0] = src.myBorderScale[0];
01700 myBorderScale[1] = src.myBorderScale[1];
01701 myBorderScale[2] = src.myBorderScale[2];
01702 myBorderValue = src.myBorderValue;
01703
01704
01705 myCompressionOptions = src.myCompressionOptions;
01706 }
01707
01708 template <typename T>
01709 int64
01710 UT_VoxelArray<T>::getMemoryUsage() const
01711 {
01712 int64 totaltilesize = 0;
01713 int i, ntiles;
01714
01715 ntiles = numTiles();
01716 for (i = 0; i < ntiles; i++)
01717 totaltilesize += myTiles[i]->getMemoryUsage();
01718
01719 return sizeof(*this) + totaltilesize;
01720 }
01721
01722 template <typename T>
01723 void
01724 UT_VoxelArray<T>::constant(T t)
01725 {
01726 int i, ntiles;
01727
01728 ntiles = numTiles();
01729 for (i = 0; i < ntiles; i++)
01730 {
01731 myTiles[i]->makeConstant(t);
01732 }
01733 }
01734
01735 template <typename T>
01736 bool
01737 UT_VoxelArray<T>::isConstant(T *t) const
01738 {
01739 int i, ntiles;
01740 T cval;
01741 const fpreal tol = UT_FTOLERANCE;
01742
01743 ntiles = numTiles();
01744 for (i = 0; i < ntiles; i++)
01745 {
01746 if (!myTiles[i]->isConstant())
01747 {
01748 return false;
01749 }
01750
01751 if (!i)
01752 {
01753
01754 cval = (*myTiles[i])(0, 0, 0);
01755 }
01756 else
01757 {
01758
01759 if (UT_VoxelTile<T>::dist(cval, (*myTiles[i])(0, 0, 0)) > tol)
01760 {
01761 return false;
01762 }
01763 }
01764 }
01765
01766
01767
01768 if (t)
01769 *t = cval;
01770
01771 return true;
01772 }
01773
01774 template <typename T>
01775 bool
01776 UT_VoxelArray<T>::hasNan() const
01777 {
01778 int i, ntiles;
01779
01780 ntiles = numTiles();
01781 for (i = 0; i < ntiles; i++)
01782 {
01783 if (myTiles[i]->hasNan())
01784 {
01785 return true;
01786 }
01787 }
01788
01789 return false;
01790 }
01791
01792 template <typename T>
01793 T
01794 UT_VoxelArray<T>::operator()(UT_Vector3F pos) const
01795 {
01796 #if 0
01797 v4uf pos4(pos.x(), pos.y(), pos.z(), 0);
01798
01799
01800 return (*this)(pos4);
01801 #else
01802 int x, y, z;
01803
01804 fpreal32 fx, fy, fz;
01805
01806
01807
01808 pos.x() *= myRes[0];
01809 pos.y() *= myRes[1];
01810 pos.z() *= myRes[2];
01811 pos.x() -= 0.5;
01812 pos.y() -= 0.5;
01813 pos.z() -= 0.5;
01814
01815
01816 fx = pos.x();
01817 SYSfastSplitFloat(fx, x);
01818 fy = pos.y();
01819 SYSfastSplitFloat(fy, y);
01820 fz = pos.z();
01821 SYSfastSplitFloat(fz, z);
01822
01823
01824 T vx, vx1, vy, vy1, vz;
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840 if ( (x > 0) && (y > 0) && (z > 0) &&
01841
01842
01843 (x < myRes[0]-1) && (y < myRes[1]-1) && (z < myRes[2]-1) )
01844 {
01845 int xm, ym, zm;
01846
01847 xm = x & TILEMASK;
01848 ym = y & TILEMASK;
01849 zm = z & TILEMASK;
01850
01851 if ((xm != TILEMASK) && (ym != TILEMASK) && (zm != TILEMASK))
01852 {
01853 const UT_VoxelTile<T> *tile =
01854 getTile(x >> TILEBITS, y >> TILEBITS, z >> TILEBITS);
01855
01856 vz = tile->lerp(xm, ym, zm, fx, fy, fz);
01857 }
01858 else
01859 {
01860
01861
01862
01863
01864
01865 vx = UT_VoxelTile<T>::lerpValues((*this)(x, y, z),
01866 (*this)(x+1, y, z),
01867 fx);
01868
01869 vx1= UT_VoxelTile<T>::lerpValues((*this)(x, y+1, z),
01870 (*this)(x+1, y+1, z),
01871 fx);
01872
01873 vy = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01874
01875
01876 vx = UT_VoxelTile<T>::lerpValues((*this)(x, y, z+1),
01877 (*this)(x+1, y, z+1),
01878 fx);
01879
01880 vx1= UT_VoxelTile<T>::lerpValues((*this)(x, y+1, z+1),
01881 (*this)(x+1, y+1, z+1),
01882 fx);
01883
01884
01885 vy1 = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01886
01887
01888 vz = UT_VoxelTile<T>::lerpValues(vy, vy1, fz);
01889 }
01890 }
01891 else
01892 {
01893
01894 vx = UT_VoxelTile<T>::lerpValues(getValue(x, y, z),
01895 getValue(x+1, y, z),
01896 fx);
01897
01898 vx1= UT_VoxelTile<T>::lerpValues(getValue(x, y+1, z),
01899 getValue(x+1, y+1, z),
01900 fx);
01901
01902
01903 vy = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01904
01905
01906 vx = UT_VoxelTile<T>::lerpValues(getValue(x, y, z+1),
01907 getValue(x+1, y, z+1),
01908 fx);
01909
01910 vx1= UT_VoxelTile<T>::lerpValues(getValue(x, y+1, z+1),
01911 getValue(x+1, y+1, z+1),
01912 fx);
01913
01914
01915 vy1 = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01916
01917
01918 vz = UT_VoxelTile<T>::lerpValues(vy, vy1, fz);
01919 }
01920
01921 return vz;
01922 #endif
01923 }
01924
01925 template <typename T>
01926 T
01927 UT_VoxelArray<T>::operator()(UT_Vector3D pos) const
01928 {
01929 int x, y, z;
01930
01931 fpreal32 fx, fy, fz;
01932
01933
01934
01935 pos.x() *= myRes[0];
01936 pos.y() *= myRes[1];
01937 pos.z() *= myRes[2];
01938 pos.x() -= 0.5;
01939 pos.y() -= 0.5;
01940 pos.z() -= 0.5;
01941
01942
01943 fx = pos.x();
01944 SYSfastSplitFloat(fx, x);
01945 fy = pos.y();
01946 SYSfastSplitFloat(fy, y);
01947 fz = pos.z();
01948 SYSfastSplitFloat(fz, z);
01949
01950
01951 T vx, vx1, vy, vy1, vz;
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967 if ( (x > 0) && (y > 0) && (z > 0) &&
01968
01969
01970 (x < myRes[0]-1) && (y < myRes[1]-1) && (z < myRes[2]-1) )
01971 {
01972 int xm, ym, zm;
01973
01974 xm = x & TILEMASK;
01975 ym = y & TILEMASK;
01976 zm = z & TILEMASK;
01977
01978 if ((xm != TILEMASK) && (ym != TILEMASK) && (zm != TILEMASK))
01979 {
01980 const UT_VoxelTile<T> *tile =
01981 getTile(x >> TILEBITS, y >> TILEBITS, z >> TILEBITS);
01982
01983 vz = tile->lerp(xm, ym, zm, fx, fy, fz);
01984 }
01985 else
01986 {
01987
01988
01989
01990
01991
01992 vx = UT_VoxelTile<T>::lerpValues((*this)(x, y, z),
01993 (*this)(x+1, y, z),
01994 fx);
01995
01996 vx1= UT_VoxelTile<T>::lerpValues((*this)(x, y+1, z),
01997 (*this)(x+1, y+1, z),
01998 fx);
01999
02000 vy = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
02001
02002
02003 vx = UT_VoxelTile<T>::lerpValues((*this)(x, y, z+1),
02004 (*this)(x+1, y, z+1),
02005 fx);
02006
02007 vx1= UT_VoxelTile<T>::lerpValues((*this)(x, y+1, z+1),
02008 (*this)(x+1, y+1, z+1),
02009 fx);
02010
02011
02012 vy1 = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
02013
02014
02015 vz = UT_VoxelTile<T>::lerpValues(vy, vy1, fz);
02016 }
02017 }
02018 else
02019 {
02020
02021 vx = UT_VoxelTile<T>::lerpValues(getValue(x, y, z),
02022 getValue(x+1, y, z),
02023 fx);
02024
02025 vx1= UT_VoxelTile<T>::lerpValues(getValue(x, y+1, z),
02026 getValue(x+1, y+1, z),
02027 fx);
02028
02029
02030 vy = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
02031
02032
02033 vx = UT_VoxelTile<T>::lerpValues(getValue(x, y, z+1),
02034 getValue(x+1, y, z+1),
02035 fx);
02036
02037 vx1= UT_VoxelTile<T>::lerpValues(getValue(x, y+1, z+1),
02038 getValue(x+1, y+1, z+1),
02039 fx);
02040
02041
02042 vy1 = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
02043
02044
02045 vz = UT_VoxelTile<T>::lerpValues(vy, vy1, fz);
02046 }
02047
02048 return vz;
02049 }
02050
02051 #if 0
02052 template <typename T>
02053 T
02054 UT_VoxelArray<T>::operator()(v4uf pos) const
02055 {
02056 int x, y, z;
02057
02058 v4ui idx;
02059
02060
02061
02062 pos *= v4uf((float) myRes[0], (float) myRes[1], (float) myRes[2], 0.0f);
02063
02064
02065
02066 pos += 1.5;
02067
02068 idx = pos.splitFloat();
02069
02070
02071 idx -= 2;
02072
02073 x = idx[0];
02074 y = idx[1];
02075 z = idx[2];
02076
02077
02078
02079
02080
02081 v4uf a, b, fx, fy, fz;
02082
02083 int xm, ym, zm;
02084
02085 xm = x & TILEMASK;
02086 ym = y & TILEMASK;
02087 zm = z & TILEMASK;
02088
02089
02090
02091 if ( (x > 0) & (y > 0) & (z > 0) &
02092 (x < myRes[0]-1) & (y < myRes[1]-1) & (z < myRes[2]-1) &
02093 (xm != TILEMASK) & (ym != TILEMASK) & (zm != TILEMASK) )
02094
02095
02096
02097
02098
02099
02100 {
02101 const UT_VoxelTile<T> *tile =
02102 getTile(x >> TILEBITS, y >> TILEBITS, z >> TILEBITS);
02103
02104 return tile->lerp(pos, xm, ym, zm);
02105 }
02106 else
02107 {
02108 a = v4uf( getValue(x, y, z),
02109 getValue(x, y, z+1),
02110 getValue(x, y+1, z),
02111 getValue(x, y+1, z+1) );
02112 b = v4uf( getValue(x+1, y, z),
02113 getValue(x+1, y, z+1),
02114 getValue(x+1, y+1, z),
02115 getValue(x+1, y+1, z+1) );
02116 }
02117
02118 fx = pos.swizzle<0, 0, 0, 0>();
02119 fy = pos.swizzle<1, 1, 1, 1>();
02120 fz = pos.swizzle<2, 2, 2, 2>();
02121
02122 b -= a;
02123 a = madd(b, fx, a);
02124
02125 b = a.swizzle<2, 3, 0, 1>();
02126 b -= a;
02127 a = madd(b, fy, a);
02128
02129 b = a.swizzle<1, 2, 3, 0>();
02130 b -= a;
02131 a = madd(b, fz, a);
02132
02133 return a[0];
02134 }
02135 #endif
02136
02137 static inline int
02138 firstTile(int &start, int &end, int res)
02139 {
02140 if (start < 0)
02141 {
02142 start += res;
02143 end += res;
02144 }
02145 return start;
02146 }
02147
02148 static inline int
02149 nextTile(int &tile, int &pstart, int &start, int &end, int res)
02150 {
02151 int pend;
02152
02153 if (pstart >= res)
02154 {
02155 pstart -= res;
02156 start -= res;
02157 end -= res;
02158 }
02159 tile = pstart >> TILEBITS;
02160 pend = SYSmin((tile+1) * TILESIZE, end, res);
02161
02162 UT_ASSERT(pstart >= 0 && pstart < res);
02163 UT_ASSERT(pend > 0 && pstart <= res);
02164 UT_ASSERT(pend-pstart > 0);
02165 UT_ASSERT(pend-pstart <= TILESIZE);
02166
02167 return pend;
02168 }
02169
02170 template <typename T>
02171 T
02172 UT_VoxelArray<T>::evaluate(const UT_Vector3 &pos, const UT_Filter &filter,
02173 fpreal radius) const
02174 {
02175 UT_Vector3 tpos;
02176 UT_FilterWindow win[3];
02177 UT_FilterWrap wrap;
02178 UT_VoxelTile<T> *tile;
02179 float *weights[3];
02180 float *wdata;
02181 fpreal iradius, visible;
02182 int start[3], end[3], size[3];
02183 int pstart[3], pend[3];
02184 int tx, ty, tz, i;
02185 T result;
02186
02187 if (!myTiles)
02188 {
02189
02190 return myBorderValue;
02191 }
02192
02193 switch (myBorderType)
02194 {
02195 case UT_VOXELBORDER_CONSTANT: wrap = UT_WRAP_BORDER; break;
02196 case UT_VOXELBORDER_REPEAT: wrap = UT_WRAP_REPEAT; break;
02197 case UT_VOXELBORDER_STREAK: wrap = UT_WRAP_CLAMP; break;
02198
02199
02200 case UT_VOXELBORDER_EXTRAP: wrap = UT_WRAP_CLAMP; break;
02201 default: wrap = UT_WRAP_CLAMP; break;
02202 }
02203
02204
02205 result = 0;
02206
02207 radius *= filter.getSupport();
02208 iradius = radius == 0 ? 1000 : 0.5F / radius;
02209
02210
02211 tpos = pos;
02212 for (i = 0; i < 3; i++)
02213 {
02214 tpos[i] = tpos[i]*myRes[i];
02215 win[i].initWeights(tpos[i], radius, myRes[i], wrap);
02216 if (win[i].getSize() <= 0)
02217 return result;
02218 }
02219
02220
02221 wdata = (float *)UTstackAlloc(
02222 (win[0].getSize()+win[1].getSize()+win[2].getSize())*
02223 sizeof(float));
02224 weights[0] = wdata;
02225 weights[1] = weights[0] + win[0].getSize();
02226 weights[2] = weights[1] + win[1].getSize();
02227
02228 visible = 1;
02229 for (i = 0; i < 3; i++)
02230 {
02231 win[i].fillWeights(weights[i], filter, tpos[i], iradius,
02232 myRes[i], wrap);
02233 start[i] = win[i].getStart() % myRes[i];
02234 size[i] = win[i].getSize();
02235
02236 UT_ASSERT(start[i] >= 0);
02237 UT_ASSERT(size[i] <= myRes[i]);
02238
02239 end[i] = start[i] + size[i];
02240 visible *= win[i].getVisible();
02241 }
02242
02243
02244 if (weights[0] && weights[1] && weights[2])
02245 {
02246 pstart[2] = firstTile(start[2], end[2], myRes[2]);
02247 while (pstart[2] < end[2])
02248 {
02249 pend[2] = nextTile(tz, pstart[2], start[2], end[2], myRes[2]);
02250 pstart[1] = firstTile(start[1], end[1], myRes[1]);
02251 while (pstart[1] < end[1])
02252 {
02253 pend[1] = nextTile(ty, pstart[1], start[1], end[1], myRes[1]);
02254 pstart[0] = firstTile(start[0], end[0], myRes[0]);
02255 while (pstart[0] < end[0])
02256 {
02257 pend[0] = nextTile(tx, pstart[0], start[0], end[0], myRes[0]);
02258 tile = getTile(tx, ty, tz);
02259 UT_ASSERT(tile);
02260 tile->weightedSum(pstart, pend, weights, start, result);
02261 pstart[0] = pend[0];
02262 }
02263 pstart[1] = pend[1];
02264 }
02265 pstart[2] = pend[2];
02266 }
02267 }
02268 UTstackFree(wdata);
02269
02270 if (visible < 1)
02271 {
02272 result += (1-visible)*myBorderValue;
02273 }
02274
02275 return result;
02276 }
02277
02278 template <typename T>
02279 void
02280 UT_VoxelArray<T>::resample(const UT_VoxelArray<T> &src,
02281 UT_FilterType filtertype,
02282 float filterwidthscale)
02283 {
02284 fpreal radius;
02285 UT_Filter *filter;
02286 UT_Vector3 pos;
02287
02288 filter = UT_Filter::getFilter(filtertype);
02289
02290 radius = SYSmax( getXRes() / (fpreal)src.getXRes(),
02291 getYRes() / (fpreal)src.getYRes(),
02292 getZRes() / (fpreal)src.getZRes(),
02293 1.0f );
02294 radius *= 0.5 * filterwidthscale;
02295
02296 resamplethread(src, filter, radius);
02297
02298 UT_Filter::releaseFilter(filter);
02299 }
02300
02301 template <typename T>
02302 void
02303 UT_VoxelArray<T>::flattenPartial(T *flatarray, int ystride32, int zstride32,
02304 const UT_JobInfo &info) const
02305 {
02306 UT_VoxelArrayIterator<T> vit;
02307 int64 ystride = ystride32;
02308 int64 zstride = zstride32;
02309
02310
02311 vit.setArray((UT_VoxelArray<T> *)this);
02312 vit.splitByTile(info);
02313
02314 for (vit.rewind(); !vit.atEnd(); vit.advance())
02315 {
02316 flatarray[vit.x() + vit.y()*ystride + vit.z()*zstride] = vit.getValue();
02317 }
02318 }
02319
02320 template <typename T>
02321 void
02322 UT_VoxelArray<T>::extractFromFlattenedPartial(const T *flatarray,
02323 int ystride32, int zstride32,
02324 const UT_JobInfo &info)
02325 {
02326 UT_VoxelArrayIterator<T> vit;
02327 int64 ystride = ystride32;
02328 int64 zstride = zstride32;
02329
02330 vit.setArray(this);
02331 vit.splitByTile(info);
02332 vit.setCompressOnExit(true);
02333
02334 for (vit.rewind(); !vit.atEnd(); vit.advance())
02335 {
02336 vit.setValue(flatarray[vit.x() + vit.y()*ystride + vit.z()*zstride]);
02337 }
02338 }
02339
02340 template <typename T>
02341 void
02342 UT_VoxelArray<T>::resamplethreadPartial(const UT_VoxelArray<T> &src,
02343 const UT_Filter *filter, float radius,
02344 const UT_JobInfo &info)
02345 {
02346 UT_VoxelArrayIterator<T> vit;
02347 UT_Vector3 pos;
02348 UT_Vector3 ratio;
02349
02350 vit.setArray(this);
02351 vit.splitByTile(info);
02352 vit.setCompressOnExit(true);
02353
02354 ratio.x() = 1.0f / getXRes();
02355 ratio.y() = 1.0f / getYRes();
02356 ratio.z() = 1.0f / getZRes();
02357
02358 for (vit.rewind(); !vit.atEnd(); vit.advance())
02359 {
02360 pos.x() = vit.x()+0.5f;
02361 pos.y() = vit.y()+0.5f;
02362 pos.z() = vit.z()+0.5f;
02363 pos *= ratio;
02364
02365 vit.setValue(src.evaluate(pos, *filter, radius));
02366 }
02367 }
02368
02369 template <typename T>
02370 bool
02371 UT_VoxelArray<T>::posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
02372 {
02373
02374
02375 pos.x() *= myRes[0];
02376 pos.y() *= myRes[1];
02377 pos.z() *= myRes[2];
02378
02379
02380
02381
02382 x = (int) SYSfloor(pos.x());
02383 y = (int) SYSfloor(pos.y());
02384 z = (int) SYSfloor(pos.z());
02385
02386
02387 return isValidIndex(x, y, z);
02388 }
02389
02390 template <typename T>
02391 bool
02392 UT_VoxelArray<T>::posToIndex(UT_Vector3 pos, UT_Vector3 &ipos) const
02393 {
02394
02395
02396 pos.x() *= myRes[0];
02397 pos.y() *= myRes[1];
02398 pos.z() *= myRes[2];
02399
02400
02401
02402 pos.x() -= 0.5;
02403 pos.y() -= 0.5;
02404 pos.z() -= 0.5;
02405
02406 ipos = pos;
02407
02408
02409 if (pos.x() < 0 || pos.x() >= myRes[0] ||
02410 pos.y() < 0 || pos.y() >= myRes[1] ||
02411 pos.z() < 0 || pos.z() >= myRes[2])
02412 return false;
02413
02414 return true;
02415 }
02416
02417 template <typename T>
02418 bool
02419 UT_VoxelArray<T>::indexToPos(int x, int y, int z, UT_Vector3F &pos) const
02420 {
02421 pos.x() = x;
02422 pos.y() = y;
02423 pos.z() = z;
02424
02425
02426 pos.x() += 0.5;
02427 pos.y() += 0.5;
02428 pos.z() += 0.5;
02429
02430
02431 if (myRes[0])
02432 pos.x() /= (fpreal) myRes[0];
02433 if (myRes[1])
02434 pos.y() /= (fpreal) myRes[1];
02435 if (myRes[2])
02436 pos.z() /= (fpreal) myRes[2];
02437
02438
02439 return isValidIndex(x, y, z);
02440 }
02441
02442 template <typename T>
02443 bool
02444 UT_VoxelArray<T>::indexToPos(int x, int y, int z, UT_Vector3D &pos) const
02445 {
02446 pos.x() = x;
02447 pos.y() = y;
02448 pos.z() = z;
02449
02450
02451 pos.x() += 0.5;
02452 pos.y() += 0.5;
02453 pos.z() += 0.5;
02454
02455
02456 if (myRes[0])
02457 pos.x() /= (fpreal) myRes[0];
02458 if (myRes[1])
02459 pos.y() /= (fpreal) myRes[1];
02460 if (myRes[2])
02461 pos.z() /= (fpreal) myRes[2];
02462
02463
02464 return isValidIndex(x, y, z);
02465 }
02466
02467 template <typename T>
02468 void
02469 UT_VoxelArray<T>::setBorder(UT_VoxelBorderType type, T t)
02470 {
02471 myBorderType = type;
02472 myBorderValue = t;
02473 }
02474
02475 template <typename T>
02476 void
02477 UT_VoxelArray<T>::setBorderScale(T sx, T sy, T sz)
02478 {
02479 myBorderScale[0] = sx;
02480 myBorderScale[1] = sy;
02481 myBorderScale[2] = sz;
02482 }
02483
02484 template <typename T>
02485 void
02486 UT_VoxelArray<T>::collapseAllTiles()
02487 {
02488 int i, ntiles;
02489
02490 ntiles = numTiles();
02491 for (i = 0; i < ntiles; i++)
02492 {
02493 myTiles[i]->tryCompress(getCompressionOptions());
02494 }
02495 }
02496
02497 template <typename T>
02498 void
02499 UT_VoxelArray<T>::expandAllTiles()
02500 {
02501 int i, ntiles;
02502
02503 ntiles = numTiles();
02504 for (i = 0; i < ntiles; i++)
02505 {
02506 myTiles[i]->uncompress();
02507 }
02508 }
02509
02510 template <typename T>
02511 void
02512 UT_VoxelArray<T>::expandAllNonConstTiles()
02513 {
02514 int i, ntiles;
02515
02516 ntiles = numTiles();
02517 for (i = 0; i < ntiles; i++)
02518 {
02519 if (!myTiles[i]->isConstant())
02520 myTiles[i]->uncompress();
02521 }
02522 }
02523
02524 template <typename T>
02525 void
02526 UT_VoxelArray<T>::saveData(ostream &os)
02527 {
02528 T cval;
02529 char version;
02530
02531
02532 if (isConstant(&cval))
02533 {
02534
02535 version = 0;
02536 UTwrite(os, &version, 1);
02537 UTwrite(os, &cval);
02538 return;
02539 }
02540
02541
02542 version = 1;
02543 UTwrite(os, &version, 1);
02544
02545
02546 UT_VoxelTile<T>::saveCompressionTypes(os);
02547
02548 int i, ntiles;
02549
02550 ntiles = numTiles();
02551 for (i = 0; i < ntiles; i++)
02552 {
02553 myTiles[i]->save(os);
02554 }
02555 }
02556
02557
02558 template <typename T>
02559 void
02560 UT_VoxelArray<T>::loadData(UT_IStream &is)
02561 {
02562 T cval;
02563 char version;
02564
02565 is.readChar(version);
02566
02567
02568 if (version == 0)
02569 {
02570
02571 is.read(&cval);
02572
02573 constant(cval);
02574 return;
02575 }
02576
02577 if (version == 1)
02578 {
02579 UT_IntArray compressions;
02580
02581
02582 UT_VoxelTile<T>::loadCompressionTypes(is, compressions);
02583
02584 int i, ntiles;
02585
02586 ntiles = numTiles();
02587 for (i = 0; i < ntiles; i++)
02588 {
02589 myTiles[i]->load(is, compressions);
02590 }
02591 }
02592 }
02593
02594
02595
02596
02597
02598
02599 template <typename T>
02600 UT_VoxelMipMap<T>::UT_VoxelMipMap()
02601 {
02602 initializePrivate();
02603 }
02604
02605 template <typename T>
02606 UT_VoxelMipMap<T>::~UT_VoxelMipMap()
02607 {
02608 destroyPrivate();
02609 }
02610
02611 template <typename T>
02612 UT_VoxelMipMap<T>::UT_VoxelMipMap(const UT_VoxelMipMap<T> &src)
02613 {
02614 initializePrivate();
02615
02616 *this = src;
02617 }
02618
02619 template <typename T>
02620 const UT_VoxelMipMap<T> &
02621 UT_VoxelMipMap<T>::operator=(const UT_VoxelMipMap<T> &src)
02622 {
02623 UT_VoxelArray<T> *levels;
02624 int level, i;
02625
02626 if (&src == this)
02627 return;
02628
02629 destroyPrivate();
02630
02631
02632
02633 myOwnBase = true;
02634 myBaseLevel = new UT_VoxelArray<T>;
02635 *myBaseLevel = *src.myBaseLevel;
02636
02637 myNumLevels = src.myNumLevels;
02638
02639 for (i = 0; i < src.myLevels.entries(); i++)
02640 {
02641 levels = new UT_VoxelArray<T> *[myNumLevels];
02642 myLevels.append(levels);
02643
02644 for (level = 0; level < myNumLevels; level++)
02645 {
02646 levels[level] = new UT_VoxelArray<T>;
02647 *levels[level] = *src.myLevels[i][level];
02648 }
02649 }
02650 }
02651
02652 template <typename T>
02653 void
02654 UT_VoxelMipMap<T>::build(UT_VoxelArray<T> *baselevel,
02655 mipmaptype function)
02656 {
02657 UT_RefArray<mipmaptype> functions;
02658
02659 functions.append(function);
02660 build(baselevel, functions);
02661 }
02662
02663 template <typename T>
02664 void
02665 UT_VoxelMipMap<T>::build(UT_VoxelArray<T> *baselevel,
02666 const UT_RefArray<mipmaptype> &functions)
02667 {
02668 destroyPrivate();
02669
02670
02671 myBaseLevel = baselevel;
02672 myOwnBase = false;
02673
02674
02675
02676 myNumLevels = 0;
02677 int maxres, level;
02678
02679 maxres = SYSmax(myBaseLevel->getXRes(), myBaseLevel->getYRes());
02680 maxres = SYSmax(maxres, myBaseLevel->getZRes());
02681
02682
02683
02684 while (maxres > 1)
02685 {
02686 myNumLevels++;
02687 maxres++;
02688 maxres >>= 1;
02689 }
02690
02691
02692
02693 int x, y, z, ix, iy, iz;
02694 int xres, yres, zres;
02695 UT_VoxelArray<T> *lastlevel;
02696 UT_VoxelArray<T> **levels;
02697 T x1, x2, y1, y2, z1, z2;
02698 mipmaptype function;
02699
02700
02701 for (int i = 0; i < functions.entries(); i++)
02702 {
02703 function = functions(i);
02704
02705 levels = new UT_VoxelArray<T> *[myNumLevels];
02706 myLevels.append(levels);
02707
02708 lastlevel = myBaseLevel;
02709 for (level = myNumLevels-1; level >= 0; level--)
02710 {
02711
02712 xres = (lastlevel->getXRes() + 1) >> 1;
02713 yres = (lastlevel->getYRes() + 1) >> 1;
02714 zres = (lastlevel->getZRes() + 1) >> 1;
02715
02716 levels[level] = new UT_VoxelArray<T>;
02717 levels[level]->size(xres, yres, zres);
02718
02719 iz = 1;
02720 for (z = 0; z < zres; z++)
02721 {
02722 if (z == zres-1)
02723 {
02724 if (2*z + 1 >= lastlevel->getZRes())
02725 iz = 0;
02726 }
02727 iy = 1;
02728 for (y = 0; y < yres; y++)
02729 {
02730 if (y == yres-1)
02731 {
02732 if (2*y + 1 >= lastlevel->getYRes())
02733 iy = 0;
02734 }
02735 ix = 1;
02736 for (x = 0; x < xres; x++)
02737 {
02738 if (x == xres-1)
02739 {
02740 if (2*x + 1 >= lastlevel->getXRes())
02741 ix = 0;
02742 }
02743 x1 = (*lastlevel)(2*x, 2*y, 2*z);
02744 x2 = (*lastlevel)(2*x+ix, 2*y, 2*z);
02745 y1 = mixValues(x1, x2, function);
02746
02747 x1 = (*lastlevel)(2*x, 2*y+iy, 2*z);
02748 x2 = (*lastlevel)(2*x+ix, 2*y+iy, 2*z);
02749 y2 = mixValues(x1, x2, function);
02750
02751 z1 = mixValues(y1, y2, function);
02752
02753 x1 = (*lastlevel)(2*x, 2*y, 2*z+iz);
02754 x2 = (*lastlevel)(2*x+ix, 2*y, 2*z+iz);
02755 y1 = mixValues(x1, x2, function);
02756
02757 x1 = (*lastlevel)(2*x, 2*y+iy, 2*z+iz);
02758 x2 = (*lastlevel)(2*x+ix, 2*y+iy, 2*z+iz);
02759 y2 = mixValues(x1, x2, function);
02760
02761 z2 = mixValues(y1, y2, function);
02762
02763 levels[level]->setValue(x, y, z,
02764 mixValues(z1, z2, function));
02765 }
02766 }
02767 }
02768
02769 lastlevel = levels[level];
02770 }
02771 }
02772 }
02773
02774 template <typename T>
02775 T
02776 UT_VoxelMipMap<T>::mixValues(T t1, T t2, mipmaptype function) const
02777 {
02778 switch (function)
02779 {
02780 case MIPMAP_MAXIMUM:
02781 return SYSmax(t1, t2);
02782
02783 case MIPMAP_AVERAGE:
02784 return (t1 + t2) / 2;
02785
02786 case MIPMAP_MINIMUM:
02787 return SYSmin(t1, t2);
02788 }
02789
02790 return t1;
02791 }
02792
02793 template <typename T>
02794 int64
02795 UT_VoxelMipMap<T>::getMemoryUsage() const
02796 {
02797 int64 totalarraysize = 0;
02798
02799 for (int j = 0; j < myLevels.entries(); j++)
02800 {
02801 for( int i = 0; i < myNumLevels; i++ )
02802 totalarraysize += myLevels[j][i]->getMemoryUsage();
02803 }
02804
02805 return sizeof(*this) + totalarraysize;
02806 }
02807
02808 template <typename T>
02809 void
02810 UT_VoxelMipMap<T>::traverseTopDown(bool (*function)(const UT_RefArray<T> &,
02811 const UT_BoundingBox &,
02812 bool, void *),
02813 void *data) const
02814 {
02815 doTraverse(0, 0, 0, 0, function, data);
02816 }
02817
02818 template <typename T>
02819 void
02820 UT_VoxelMipMap<T>::doTraverse(int x, int y, int z, int level,
02821 bool (*function)(const UT_RefArray<T> &,
02822 const UT_BoundingBox &,
02823 bool, void *),
02824 void *data) const
02825 {
02826 UT_RefArray<T> tval;
02827 bool isfinal;
02828 UT_VoxelArray<T> *vox;
02829 int shift;
02830 int i;
02831
02832 if (level == myNumLevels)
02833 {
02834 isfinal = true;
02835 vox = myBaseLevel;
02836 tval.append((*vox)(x, y, z));
02837 for (i = 1; i < myLevels.entries(); i++)
02838 tval.append(tval(0));
02839 }
02840 else
02841 {
02842 isfinal = false;
02843 for (i = 0; i < myLevels.entries(); i++)
02844 {
02845 vox = myLevels[i][level];
02846 tval.append((*vox)(x, y, z));
02847 }
02848 }
02849
02850 shift = myNumLevels - level;
02851
02852 UT_BoundingBox box;
02853
02854 box.initBounds(SYSmin(x << shift, myBaseLevel->getXRes()),
02855 SYSmin(y << shift, myBaseLevel->getYRes()),
02856 SYSmin(z << shift, myBaseLevel->getZRes()));
02857 box.enlargeBounds(SYSmin((x+1) << shift, myBaseLevel->getXRes()),
02858 SYSmin((y+1) << shift, myBaseLevel->getYRes()),
02859 SYSmin((z+1) << shift, myBaseLevel->getZRes()));
02860
02861 if (!function(tval, box, isfinal, data))
02862 {
02863
02864
02865 return;
02866 }
02867
02868
02869 if (isfinal)
02870 return;
02871
02872 level++;
02873 shift--;
02874 x <<= 1;
02875 y <<= 1;
02876 z <<= 1;
02877
02878 bool xinc, yinc, zinc;
02879
02880
02881 if ( ((x+1) << shift) < myBaseLevel->getXRes() )
02882 xinc = true;
02883 else
02884 xinc = false;
02885 if ( ((y+1) << shift) < myBaseLevel->getYRes() )
02886 yinc = true;
02887 else
02888 yinc = false;
02889 if ( ((z+1) << shift) < myBaseLevel->getZRes() )
02890 zinc = true;
02891 else
02892 zinc = false;
02893
02894
02895 doTraverse(x, y, z, level, function, data);
02896
02897 if (xinc)
02898 {
02899 doTraverse(x+1, y, z, level, function, data);
02900 if (yinc)
02901 {
02902 doTraverse(x+1, y+1, z, level, function, data);
02903 if (zinc)
02904 doTraverse(x+1, y+1, z+1, level, function, data);
02905 }
02906 if (zinc)
02907 {
02908 doTraverse(x+1, y, z+1, level, function, data);
02909 }
02910 }
02911 if (yinc)
02912 {
02913 doTraverse(x, y+1, z, level, function, data);
02914 if (zinc)
02915 doTraverse(x, y+1, z+1, level, function, data);
02916 }
02917 if (zinc)
02918 doTraverse(x, y, z+1, level, function, data);
02919 }
02920
02921 template <typename T>
02922 void
02923 UT_VoxelMipMap<T>::initializePrivate()
02924 {
02925 myNumLevels = 0;
02926 myBaseLevel = 0;
02927 myOwnBase = false;
02928 }
02929
02930 template <typename T>
02931 void
02932 UT_VoxelMipMap<T>::destroyPrivate()
02933 {
02934 int level, i;
02935
02936 for (i = 0; i < myLevels.entries(); i++)
02937 {
02938 for (level = 0; level < myNumLevels; level++)
02939 delete myLevels[i][level];
02940 delete [] myLevels[i];
02941 }
02942 myLevels.entries(0);
02943
02944 if (myOwnBase)
02945 delete myBaseLevel;
02946
02947 initializePrivate();
02948 }
02949
02950 template <typename T>
02951 UT_VoxelArrayIterator<T>::UT_VoxelArrayIterator()
02952 {
02953 myArray = 0;
02954 myHandle.resetHandle();
02955 myCurTile = -1;
02956 myShouldCompressOnExit = false;
02957 myUseTileList = false;
02958 myJobInfo = 0;
02959 }
02960
02961 template <typename T>
02962 UT_VoxelArrayIterator<T>::UT_VoxelArrayIterator(UT_VoxelArray<T> *vox)
02963 {
02964 myShouldCompressOnExit = false;
02965 myUseTileList = false;
02966 myJobInfo = 0;
02967 setArray(vox);
02968 }
02969
02970 template <typename T>
02971 UT_VoxelArrayIterator<T>::UT_VoxelArrayIterator(UT_COWReadHandle<UT_VoxelArray<T> > handle)
02972 {
02973 myShouldCompressOnExit = false;
02974 myUseTileList = false;
02975 myJobInfo = 0;
02976 setHandle(handle);
02977 }
02978
02979 template <typename T>
02980 UT_VoxelArrayIterator<T>::~UT_VoxelArrayIterator()
02981 {
02982 }
02983
02984 template <typename T>
02985 void
02986 UT_VoxelArrayIterator<T>::setPartialRange(int idx, int numranges)
02987 {
02988 int numtiles;
02989 fpreal tileperrange;
02990
02991
02992 UT_ASSERT(myArray);
02993 if (!myArray)
02994 return;
02995
02996
02997 numtiles = myArray->numTiles();
02998
02999
03000 if (myUseTileList)
03001 numtiles = myTileList.entries();
03002
03003
03004 if (!numtiles)
03005 {
03006 myTileStart = 0;
03007 myTileEnd = 0;
03008 return;
03009 }
03010
03011
03012 if (idx < 0 || idx >= numranges)
03013 {
03014 UT_ASSERT(!"Idx out of bounds");
03015 myTileStart = -1;
03016 myTileEnd = -1;
03017 return;
03018 }
03019
03020
03021 if (numranges < 1)
03022 {
03023 UT_ASSERT(!"Invalid range count!");
03024 numranges = 1;
03025 }
03026
03027
03028
03029
03030
03031 tileperrange = (fpreal)numtiles / (fpreal)numranges;
03032
03033 myTileStart = (int) SYSfloor(idx * tileperrange);
03034 myTileEnd = (int) SYSfloor((idx+1) * tileperrange);
03035
03036
03037
03038 if (idx == numranges-1)
03039 myTileEnd = numtiles;
03040
03041 UT_ASSERT(myTileStart >= 0);
03042 UT_ASSERT(myTileEnd <= numtiles);
03043 }
03044
03045 template <typename T>
03046 void
03047 UT_VoxelArrayIterator<T>::splitByTile(const UT_JobInfo &info)
03048 {
03049
03050 UT_ASSERT(myArray);
03051 if (!myArray)
03052 return;
03053
03054
03055 if (info.numJobs() == 1)
03056 myJobInfo = 0;
03057 else
03058 myJobInfo = &info;
03059 }
03060
03061 template <typename T>
03062 void
03063 UT_VoxelArrayIterator<T>::restrictToBBox(const UT_BoundingBox &bbox)
03064 {
03065 UT_Vector3 pmin, pmax, vmin, vmax;
03066
03067 pmin = bbox.minvec();
03068 pmax = bbox.maxvec();
03069
03070 pmin.x() = SYSmax(pmin.x(), 0.0f);
03071 pmin.y() = SYSmax(pmin.y(), 0.0f);
03072 pmin.z() = SYSmax(pmin.z(), 0.0f);
03073 pmax.x() = SYSmin(pmax.x(), 1.0f);
03074 pmax.y() = SYSmin(pmax.y(), 1.0f);
03075 pmax.z() = SYSmin(pmax.z(), 1.0f);
03076
03077 myArray->posToIndex(pmin, vmin);
03078 myArray->posToIndex(pmax, vmax);
03079
03080 restrictToBBox(SYSfloor(vmin.x()), SYSceil(vmax.x()),
03081 SYSfloor(vmin.y()), SYSceil(vmax.y()),
03082 SYSfloor(vmin.z()), SYSceil(vmax.z()));
03083 }
03084
03085 template <typename T>
03086 void
03087 UT_VoxelArrayIterator<T>::restrictToBBox(int xmin, int xmax,
03088 int ymin, int ymax,
03089 int zmin, int zmax)
03090 {
03091 int xres, yres, zres, x, y, z;
03092
03093 xres = myArray->getXRes();
03094 yres = myArray->getYRes();
03095 zres = myArray->getZRes();
03096
03097 myTileList.entries(0);
03098 myUseTileList = true;
03099
03100 if (xmin < xres && xmax >= 0 &&
03101 ymin < yres && ymax >= 0 &&
03102 zmin < zres && zmax >= 0)
03103 {
03104
03105 myArray->clampIndex(xmin, ymin, zmin);
03106 myArray->clampIndex(xmax, ymax, zmax);
03107
03108
03109 xmin >>= TILEBITS;
03110 ymin >>= TILEBITS;
03111 zmin >>= TILEBITS;
03112 xmax >>= TILEBITS;
03113 ymax >>= TILEBITS;
03114 zmax >>= TILEBITS;
03115
03116
03117 if (myArray->numTiles() == (xmax-xmin+1)*(ymax-ymin+1)*(zmax-zmin+1))
03118 {
03119 UT_ASSERT(xmin == 0 && ymin == 0 && zmin == 0);
03120
03121 myUseTileList = false;
03122 }
03123 else
03124 {
03125
03126 for (z = zmin; z <= zmax; z++)
03127 {
03128 for (y = ymin; y <= ymax; y++)
03129 {
03130 for (x = xmin; x <= xmax; x++)
03131 {
03132 myTileList.append(myArray->xyzTileToLinear(x, y, z));
03133 }
03134 }
03135 }
03136 }
03137 }
03138
03139
03140 myCurTile = -1;
03141 setPartialRange(0, 1);
03142 }
03143
03144
03145 template <typename T>
03146 void
03147 UT_VoxelArrayIterator<T>::rewind()
03148 {
03149
03150 if (!myArray ||
03151 !myArray->getRes(0) || !myArray->getRes(1) || !myArray->getRes(2))
03152 {
03153 myCurTile = -1;
03154 return;
03155 }
03156
03157 if (myUseTileList)
03158 {
03159 if (myJobInfo)
03160 myCurTileListIdx = myJobInfo->nextTask();
03161 else
03162 myCurTileListIdx = myTileStart;
03163 if (myCurTileListIdx < 0 || myCurTileListIdx >= myTileEnd)
03164 {
03165 myCurTile = -1;
03166 return;
03167 }
03168 myCurTile = myTileList(myCurTileListIdx);
03169 }
03170 else
03171 {
03172 if (myJobInfo)
03173 myCurTile = myJobInfo->nextTask();
03174 else
03175 myCurTile = myTileStart;
03176
03177 if (myCurTile < 0 || myCurTile >= myTileEnd)
03178 {
03179 myCurTile = -1;
03180 return;
03181 }
03182 }
03183
03184 UT_VoxelTile<T> *tile;
03185
03186 tile = myArray->getLinearTile(myCurTile);
03187
03188
03189 if (myCurTile)
03190 {
03191 myArray->linearTileToXYZ(myCurTile,
03192 myTilePos[0], myTilePos[1], myTilePos[2]);
03193 myPos[0] = TILESIZE * myTilePos[0];
03194 myPos[1] = TILESIZE * myTilePos[1];
03195 myPos[2] = TILESIZE * myTilePos[2];
03196 }
03197 else
03198 {
03199 myTilePos[0] = 0;
03200 myTilePos[1] = 0;
03201 myTilePos[2] = 0;
03202 myPos[0] = 0;
03203 myPos[1] = 0;
03204 myPos[2] = 0;
03205 }
03206
03207 myTileLocalPos[0] = 0;
03208 myTileLocalPos[1] = 0;
03209 myTileLocalPos[2] = 0;
03210
03211 myTileSize[0] = tile->xres();
03212 myTileSize[1] = tile->yres();
03213 myTileSize[2] = tile->zres();
03214 }
03215
03216 template <typename T>
03217 void
03218 UT_VoxelArrayIterator<T>::advanceTile()
03219 {
03220 if (myUseTileList)
03221 {
03222 if (getCompressOnExit())
03223 {
03224
03225 if (myCurTile >= 0 && myCurTileListIdx < myTileEnd)
03226 {
03227 myArray->getLinearTile(myCurTile)->tryCompress(myArray->getCompressionOptions());
03228 }
03229 }
03230
03231
03232 if (myJobInfo)
03233 myCurTileListIdx = myJobInfo->nextTask();
03234 else
03235 myCurTileListIdx++;
03236 if (myCurTileListIdx >= myTileEnd)
03237 {
03238 myCurTile = -1;
03239 return;
03240 }
03241
03242 myCurTile = myTileList(myCurTileListIdx);
03243
03244 myArray->linearTileToXYZ(myCurTile,
03245 myTilePos[0], myTilePos[1], myTilePos[2]);
03246
03247 UT_VoxelTile<T> *tile;
03248
03249 tile = myArray->getLinearTile(myCurTile);
03250 myTileLocalPos[0] = 0;
03251 myTileLocalPos[1] = 0;
03252 myTileLocalPos[2] = 0;
03253 myTileSize[0] = tile->xres();
03254 myTileSize[1] = tile->yres();
03255 myTileSize[2] = tile->zres();
03256
03257 myPos[0] = TILESIZE * myTilePos[0];
03258 myPos[1] = TILESIZE * myTilePos[1];
03259 myPos[2] = TILESIZE * myTilePos[2];
03260 return;
03261 }
03262
03263
03264 if (getCompressOnExit())
03265 {
03266
03267 if (myCurTile >= 0 && myCurTile < myTileEnd)
03268 {
03269 myArray->getLinearTile(myCurTile)->tryCompress(myArray->getCompressionOptions());
03270 }
03271 }
03272
03273 if (myJobInfo)
03274 {
03275 myCurTile = myJobInfo->nextTask();
03276 if (myCurTile >= myTileEnd)
03277 {
03278 myCurTile = -1;
03279 return;
03280 }
03281 myArray->linearTileToXYZ(myCurTile,
03282 myTilePos[0], myTilePos[1], myTilePos[2]);
03283 }
03284 else
03285 {
03286
03287 myTilePos[0]++;
03288 if (myTilePos[0] >= myArray->getTileRes(0))
03289 {
03290 myTilePos[0] = 0;
03291 myTilePos[1]++;
03292 if (myTilePos[1] >= myArray->getTileRes(1))
03293 {
03294 myTilePos[1] = 0;
03295 myTilePos[2]++;
03296 if (myTilePos[2] >= myArray->getTileRes(2))
03297 {
03298
03299 myCurTile = -1;
03300 return;
03301 }
03302 }
03303 }
03304 myCurTile = myArray->xyzTileToLinear(myTilePos[0], myTilePos[1], myTilePos[2]);
03305 }
03306
03307 UT_VoxelTile<T> *tile;
03308
03309
03310
03311
03312 if (myCurTile >= myTileEnd)
03313 {
03314 myCurTile = -1;
03315 return;
03316 }
03317
03318 tile = myArray->getLinearTile(myCurTile);
03319 myTileLocalPos[0] = 0;
03320 myTileLocalPos[1] = 0;
03321 myTileLocalPos[2] = 0;
03322 myTileSize[0] = tile->xres();
03323 myTileSize[1] = tile->yres();
03324 myTileSize[2] = tile->zres();
03325
03326 myPos[0] = TILESIZE * myTilePos[0];
03327 myPos[1] = TILESIZE * myTilePos[1];
03328 myPos[2] = TILESIZE * myTilePos[2];
03329 }
03330
03331
03332 template <typename T>
03333 void
03334 UT_VoxelArrayIterator<T>::skipToEndOfTile()
03335 {
03336 myTileLocalPos[0] = myTileSize[0];
03337 myTileLocalPos[1] = myTileSize[1];
03338 myTileLocalPos[2] = myTileSize[2];
03339 }
03340
03341 template <typename T>
03342 template <typename OP>
03343 void
03344 UT_VoxelArrayIterator<T>::applyOperation(OP op,
03345 const UT_VoxelArray<T> &a)
03346 {
03347 UT_ASSERT(myArray->isMatching(a));
03348
03349 rewind();
03350
03351 while (!atEnd())
03352 {
03353 UT_VoxelTile<T> *atile, *tile;
03354
03355 tile = myArray->getLinearTile(myCurTile);
03356 atile = a.getLinearTile(myCurTile);
03357
03358 if (!atile->isSimpleCompression())
03359 {
03360
03361 for (int z = 0; z < tile->zres(); z++)
03362 for (int y = 0; y < tile->yres(); y++)
03363 for (int x = 0; x < tile->xres(); x++)
03364 {
03365 T aval, val;
03366
03367 val = tile->operator()(x, y, z);
03368 aval = atile->operator()(x, y, z);
03369
03370 val = op(val, aval);
03371
03372 tile->setValue(x, y, z, val);
03373 }
03374 }
03375 else
03376 {
03377 if (!tile->isSimpleCompression())
03378 tile->uncompress();
03379
03380 int ainc = atile->isConstant() ? 0 : 1;
03381
03382 if (tile->isConstant())
03383 {
03384 if (!ainc)
03385 {
03386
03387 T aval, val;
03388
03389 val = tile->rawData()[0];
03390 aval = atile->rawData()[0];
03391
03392 val = op(val, aval);
03393
03394 tile->rawData()[0] = val;
03395 }
03396 else
03397 {
03398 tile->uncompress();
03399 }
03400 }
03401
03402
03403
03404 if (!tile->isConstant())
03405 {
03406 const T *aval;
03407 T *val;
03408
03409 val = tile->rawData();
03410 aval = atile->rawData();
03411
03412 int n = tile->numVoxels();
03413 for (int i = 0; i < n; i++)
03414 {
03415 val[i] = op(val[i], *aval);
03416 aval += ainc;
03417 }
03418 }
03419 }
03420
03421 advanceTile();
03422 }
03423 }
03424
03425 template <typename T>
03426 template <typename OP>
03427 void
03428 UT_VoxelArrayIterator<T>::applyOperation(OP op, T a)
03429 {
03430 rewind();
03431
03432 while (!atEnd())
03433 {
03434 UT_VoxelTile<T> *tile;
03435
03436 tile = myArray->getLinearTile(myCurTile);
03437
03438 if (!tile->isSimpleCompression())
03439 tile->uncompress();
03440
03441 if (tile->isConstant())
03442 {
03443 T val;
03444
03445 val = tile->rawData()[0];
03446
03447 val = op(val, a);
03448
03449 tile->rawData()[0] = val;
03450 }
03451 else
03452 {
03453 T *val;
03454
03455 val = tile->rawData();
03456
03457 int n = tile->numVoxels();
03458 for (int i = 0; i < n; i++)
03459 {
03460 val[i] = op(val[i], a);
03461 }
03462 }
03463
03464 advanceTile();
03465 }
03466 }
03467
03468 template <typename T>
03469 template <typename OP>
03470 void
03471 UT_VoxelArrayIterator<T>::applyOperation(OP op,
03472 const UT_VoxelArray<T> &a,
03473 const UT_VoxelArray<T> &b)
03474 {
03475 UT_ASSERT(myArray->isMatching(a));
03476 UT_ASSERT(myArray->isMatching(b));
03477
03478 rewind();
03479
03480 while (!atEnd())
03481 {
03482 UT_VoxelTile<T> *atile, *btile, *tile;
03483
03484 tile = myArray->getLinearTile(myCurTile);
03485 atile = a.getLinearTile(myCurTile);
03486 btile = b.getLinearTile(myCurTile);
03487
03488 if (!atile->isSimpleCompression() || !btile->isSimpleCompression())
03489 {
03490
03491 for (int z = 0; z < tile->zres(); z++)
03492 for (int y = 0; y < tile->yres(); y++)
03493 for (int x = 0; x < tile->xres(); x++)
03494 {
03495 T aval, bval, val;
03496
03497 val = tile->operator()(x, y, z);
03498 aval = atile->operator()(x, y, z);
03499 bval = btile->operator()(x, y, z);
03500
03501 val = op(val, aval, bval);
03502
03503 tile->setValue(x, y, z, val);
03504 }
03505 }
03506 else
03507 {
03508 if (!tile->isSimpleCompression())
03509 tile->uncompress();
03510
03511 int ainc = atile->isConstant() ? 0 : 1;
03512 int binc = btile->isConstant() ? 0 : 1;
03513
03514 if (tile->isConstant())
03515 {
03516 if (!ainc && !binc)
03517 {
03518
03519 T aval, bval, val;
03520
03521 val = tile->rawData()[0];
03522 aval = atile->rawData()[0];
03523 bval = btile->rawData()[0];
03524
03525 val = op(val, aval, bval);
03526
03527 tile->rawData()[0] = val;
03528 }
03529 else
03530 {
03531 tile->uncompress();
03532 }
03533 }
03534
03535
03536
03537 if (!tile->isConstant())
03538 {
03539 const T *aval, *bval;
03540 T *val;
03541
03542 val = tile->rawData();
03543 aval = atile->rawData();
03544 bval = btile->rawData();
03545
03546 int n = tile->numVoxels();
03547 for (int i = 0; i < n; i++)
03548 {
03549 val[i] = op(val[i], *aval, *bval);
03550 aval += ainc;
03551 bval += binc;
03552 }
03553 }
03554 }
03555
03556 advanceTile();
03557 }
03558 }
03559
03560
03561
03562
03563 template <typename T>
03564 UT_VoxelTileIterator<T>::UT_VoxelTileIterator()
03565 {
03566 myCurTile = 0;
03567 myArray = 0;
03568 myAtEnd = true;
03569 myShouldCompressOnExit = false;
03570 }
03571
03572 template <typename T>
03573 UT_VoxelTileIterator<T>::UT_VoxelTileIterator(const UT_VoxelArrayIterator<T> &vit)
03574 {
03575 myCurTile = 0;
03576 myArray = 0;
03577 myAtEnd = true;
03578 myShouldCompressOnExit = false;
03579 setTile(vit);
03580 }
03581
03582 template <typename T>
03583 template <typename S>
03584 UT_VoxelTileIterator<T>::UT_VoxelTileIterator(const UT_VoxelArrayIterator<S> &vit, UT_VoxelArray<T> *array)
03585 {
03586 myCurTile = 0;
03587 myArray = 0;
03588 myAtEnd = true;
03589 myShouldCompressOnExit = false;
03590 setTile(vit, array);
03591 }
03592
03593 template <typename T>
03594 UT_VoxelTileIterator<T>::~UT_VoxelTileIterator()
03595 {
03596 }
03597
03598 template <typename T>
03599 void
03600 UT_VoxelTileIterator<T>::rewind()
03601 {
03602
03603 if (!myCurTile ||
03604 !myCurTile->xres() || !myCurTile->yres() || !myCurTile->zres())
03605 {
03606 myCurTile = 0;
03607 return;
03608 }
03609
03610 myPos[0] = myTileStart[0];
03611 myPos[1] = myTileStart[1];
03612 myPos[2] = myTileStart[2];
03613
03614 myTileLocalPos[0] = 0;
03615 myTileLocalPos[1] = 0;
03616 myTileLocalPos[2] = 0;
03617
03618 myTileSize[0] = myCurTile->xres();
03619 myTileSize[1] = myCurTile->yres();
03620 myTileSize[2] = myCurTile->zres();
03621
03622 myAtEnd = false;
03623 }
03624
03625 template <typename T>
03626 void
03627 UT_VoxelTileIterator<T>::advanceTile()
03628 {
03629 if (getCompressOnExit())
03630 {
03631
03632 if (myCurTile)
03633 {
03634 myCurTile->tryCompress(myArray->getCompressionOptions());
03635 }
03636 }
03637 myAtEnd = true;
03638 }
03639
03640 template <typename T>
03641 template <typename OP>
03642 bool
03643 UT_VoxelTileIterator<T>::reduceOperation(OP &op)
03644 {
03645 rewind();
03646
03647 if (!myCurTile->isSimpleCompression())
03648 {
03649
03650 for (int z = 0; z < myTileSize[2]; z++)
03651 for (int y = 0; y < myTileSize[1]; y++)
03652 for (int x = 0; x < myTileSize[0]; x++)
03653 {
03654 T val;
03655
03656 val = myCurTile->operator()(x, y, z);
03657
03658 if (!op.reduce(val))
03659 return false;
03660 }
03661 }
03662 else if (myCurTile->isConstant())
03663 {
03664
03665 T val;
03666
03667 val = myCurTile->rawData()[0];
03668 int n = myCurTile->numVoxels();
03669
03670 if (!op.reduceMany(val, n))
03671 return false;
03672 }
03673 else
03674 {
03675 T *val;
03676
03677 val = myCurTile->rawData();
03678
03679 int n = myCurTile->numVoxels();
03680 for (int i = 0; i < n; i++)
03681 {
03682 if (!op.reduce(val[i]))
03683 return false;
03684 }
03685 }
03686 return true;
03687 }
03688
03689
03690
03691
03692
03693 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03694 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::UT_VoxelProbe()
03695 {
03696 myCurLine = 0;
03697 myAllocCacheLine = 0;
03698 myDirty = false;
03699
03700 myArray = 0;
03701 }
03702
03703 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03704 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::UT_VoxelProbe(UT_VoxelArray<T> *vox, int prex, int postx)
03705 {
03706
03707 myCurLine = 0;
03708 myAllocCacheLine = 0;
03709 myDirty = false;
03710
03711 setArray(vox, prex, postx);
03712 }
03713
03714 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03715 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::~UT_VoxelProbe()
03716 {
03717 if (DoWrite)
03718 {
03719 if (!TestForWrites || myDirty)
03720 {
03721
03722 writeCacheLine();
03723 }
03724 }
03725 delete [] myAllocCacheLine;
03726 }
03727
03728 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03729 void
03730 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::setArray(UT_VoxelArray<T> *vox, int prex, int postx)
03731 {
03732
03733 int prepad, postpad;
03734
03735 myCurLine = 0;
03736
03737 prepad = (prex - 3) / 4;
03738 postpad = (postx + 3) / 4;
03739
03740 myAllocCacheLine = new T [TILESIZE - prepad*4 + postpad*4];
03741 myCacheLine = &myAllocCacheLine[-prepad];
03742
03743 myPreX = prex;
03744 myPostX = postx;
03745
03746 myForceCopy = false;
03747 if (myPreX || myPostX)
03748 myForceCopy = true;
03749
03750 myDirty = false;
03751
03752 myArray = vox;
03753 }
03754
03755 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03756 bool
03757 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::setIndex(int x, int y, int z)
03758 {
03759
03760 if (myCurLine && y == myY && z == myZ)
03761 {
03762 if (x < myMaxValidX)
03763 {
03764 if (x == myX+1)
03765 {
03766
03767 advanceX();
03768 return false;
03769 }
03770
03771 if (x >= myMinValidX)
03772 {
03773
03774 resetX(x);
03775
03776
03777 return true;
03778 }
03779 }
03780 }
03781
03782
03783 if (DoWrite)
03784 {
03785 if (!TestForWrites || myDirty)
03786 writeCacheLine();
03787 }
03788
03789
03790 reloadCache(x, y, z);
03791
03792 if (TestForWrites)
03793 myDirty = false;
03794
03795 return true;
03796 }
03797
03798 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03799 void
03800 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::reloadCache(int x, int y, int z)
03801 {
03802 UT_VoxelTile<T> *tile;
03803 bool xout = false, yout = false, zout = false;
03804 bool manualbuild = false;
03805
03806 myX = x;
03807 myY = y;
03808 myZ = z;
03809 myMinValidX = x & ~TILEMASK;
03810 myMaxValidX = myMinValidX + TILESIZE;
03811 if (myMaxValidX > myArray->getXRes())
03812 myMaxValidX = myArray->getXRes();
03813
03814 if (x < 0 || x >= myArray->getXRes())
03815 xout = true;
03816 if (y < 0 || y >= myArray->getYRes())
03817 yout = true;
03818 if (z < 0 || z >= myArray->getZRes())
03819 zout = true;
03820
03821
03822 if (yout || zout)
03823 {
03824
03825 switch (myArray->getBorder())
03826 {
03827 case UT_VOXELBORDER_CONSTANT:
03828 buildConstantCache(myArray->getBorderValue());
03829
03830
03831 return;
03832
03833 case UT_VOXELBORDER_REPEAT:
03834
03835 if (yout)
03836 {
03837 y %= myArray->getYRes();
03838 if (y < 0)
03839 y += myArray->getYRes();
03840 }
03841 if (zout)
03842 {
03843 z %= myArray->getZRes();
03844 if (z < 0)
03845 z += myArray->getZRes();
03846 }
03847 break;
03848
03849 case UT_VOXELBORDER_STREAK:
03850 {
03851
03852 int tx = 0;
03853 myArray->clampIndex(tx, y, z);
03854 break;
03855 }
03856
03857 case UT_VOXELBORDER_EXTRAP:
03858 {
03859
03860 manualbuild = true;
03861 break;
03862 }
03863 }
03864 }
03865
03866
03867
03868
03869
03870 if (xout || manualbuild)
03871 {
03872
03873 if (!myPreX && !myPostX && !manualbuild)
03874 {
03875 buildConstantCache(myArray->getValue(x, y, z));
03876
03877
03878 return;
03879 }
03880 else
03881 {
03882
03883
03884
03885
03886 if (myArray->getBorder() == UT_VOXELBORDER_REPEAT)
03887 {
03888 x %= myArray->getXRes();
03889 if (x < 0)
03890 x += myArray->getXRes();
03891 }
03892 else
03893 {
03894 int i;
03895
03896 for (i = myPreX; i < 0; i++)
03897 {
03898 myCacheLine[i] = myArray->getValue(myMinValidX+i, y, z);
03899 }
03900
03901 T value = myArray->getValue(x, y, z);
03902 for (; i < TILESIZE; i++)
03903 {
03904 myCacheLine[i] = value;
03905 }
03906
03907 for (; i < TILESIZE + myPostX; i++)
03908 {
03909 myCacheLine[i] = myArray->getValue(myMaxValidX+i, y, z);
03910 }
03911
03912 myCurLine = &myCacheLine[x & TILEMASK];
03913 myStride = 1;
03914
03915
03916 return;
03917 }
03918 }
03919 }
03920
03921 int xtile, ytile, ztile, tileidx;
03922 int lx, ly, lz;
03923 int i;
03924
03925 xtile = x >> TILEBITS;
03926 ytile = y >> TILEBITS;
03927 ztile = z >> TILEBITS;
03928
03929
03930 lx = x & TILEMASK;
03931 ly = y & TILEMASK;
03932 lz = z & TILEMASK;
03933
03934 tileidx = (ztile * myArray->getTileRes(1) + ytile) * myArray->getTileRes(0);
03935
03936 if (myPreX)
03937 {
03938 if (xtile)
03939 {
03940
03941 tile = myArray->getLinearTile(tileidx+xtile-1);
03942 for (i = myPreX; i < 0; i++)
03943 {
03944
03945
03946 myCacheLine[i] = (*tile)(i & TILEMASK, ly, lz);
03947 }
03948 }
03949 else
03950 {
03951 if (myArray->getBorder() == UT_VOXELBORDER_REPEAT)
03952 {
03953 int resx = myArray->getXRes();
03954 int xpos;
03955
03956 xpos = myPreX;
03957 xpos %= resx;
03958
03959 xpos += resx;
03960
03961
03962 for (i = myPreX; i < 0; i++)
03963 {
03964 myCacheLine[i] = (*myArray)(xpos, ly, lz);
03965 xpos++;
03966 if (xpos > resx)
03967 xpos -= resx;
03968 }
03969 }
03970 else
03971 {
03972 T value;
03973
03974 if (myArray->getBorder() == UT_VOXELBORDER_STREAK)
03975 {
03976 tile = myArray->getLinearTile(tileidx+xtile);
03977 value = (*tile)(0, ly, lz);
03978 }
03979 else
03980 value = myArray->getBorderValue();
03981
03982
03983 for (i = myPreX; i < 0; i++)
03984 myCacheLine[i] = value;
03985 }
03986 }
03987 }
03988
03989 if (myPostX)
03990 {
03991 int cachelen;
03992 int resx = myArray->getXRes();
03993
03994
03995 cachelen = myMaxValidX - myMinValidX;
03996
03997
03998
03999 if (myMaxValidX + myPostX > myArray->getXRes())
04000 {
04001
04002
04003
04004
04005
04006 int xpos = myMaxValidX;
04007
04008
04009 i = 0;
04010 if (xpos < resx)
04011 {
04012 tile = myArray->getLinearTile(tileidx+xtile+1);
04013 for (; i < myPostX && xpos < resx; i++)
04014 {
04015 myCacheLine[i + cachelen] = (*tile)(i, ly, lz);
04016 xpos++;
04017 }
04018 }
04019
04020 if (i < myPostX)
04021 {
04022 if (myArray->getBorder() == UT_VOXELBORDER_REPEAT)
04023 {
04024 xpos = xpos % resx;
04025
04026
04027 for (; i < myPostX; i++)
04028 {
04029 myCacheLine[i + cachelen] = (*myArray)(xpos, y, z);
04030 xpos++;
04031 if (xpos > resx)
04032 xpos -= resx;
04033 }
04034 }
04035 else
04036 {
04037 T value;
04038
04039 if (myArray->getBorder() == UT_VOXELBORDER_STREAK)
04040 {
04041 tile = myArray->getLinearTile(tileidx+xtile);
04042 value = (*tile)(tile->xres()-1, ly, lz);
04043 }
04044 else
04045 value = myArray->getBorderValue();
04046
04047 for (; i < myPostX; i++)
04048 myCacheLine[i + cachelen] = value;
04049 }
04050 }
04051 }
04052 else
04053 {
04054
04055 tile = myArray->getLinearTile(tileidx+xtile+1);
04056 for (i = 0; i < myPostX; i++)
04057 {
04058
04059
04060 myCacheLine[i + cachelen] = (*tile)(i, ly, lz);
04061 }
04062 }
04063
04064 }
04065
04066 tile = myArray->getLinearTile(tileidx+xtile);
04067 myCurLine = tile->fillCacheLine(myCacheLine, myStride, lx, ly, lz, myForceCopy, DoWrite);
04068 }
04069
04070 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
04071 void
04072 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::buildConstantCache(T value)
04073 {
04074 if (DoWrite)
04075 {
04076
04077 myStride = 1;
04078
04079 int i;
04080
04081 for (i = myPreX; i < TILESIZE+myPostX; i++)
04082 myCacheLine[i] = value;
04083 myCurLine = myCacheLine;
04084 }
04085 else
04086 {
04087 myCacheLine[0] = value;
04088
04089 myCacheLine[1] = value;
04090 myCacheLine[2] = value;
04091 myCacheLine[3] = value;
04092
04093 myCurLine = myCacheLine;
04094 myStride = 0;
04095 }
04096 }
04097
04098 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
04099 void
04100 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::writeCacheLine()
04101 {
04102 if (!DoWrite)
04103 {
04104 UT_ASSERT(0);
04105 return;
04106 }
04107
04108
04109 if (!myCurLine)
04110 return;
04111
04112
04113 myCurLine -= myX - myMinValidX;
04114
04115
04116
04117 if (myCurLine != myCacheLine)
04118 return;
04119
04120
04121 int xtile, ytile, ztile, y, z;
04122 UT_VoxelTile<T> *tile;
04123
04124 xtile = myMinValidX >> TILEBITS;
04125 ytile = myY >> TILEBITS;
04126 ztile = myZ >> TILEBITS;
04127 y = myY & TILEMASK;
04128 z = myZ & TILEMASK;
04129
04130 tile = myArray->getTile(xtile, ytile, ztile);
04131
04132
04133 tile->writeCacheLine(myCurLine, y, z);
04134 }
04135
04136
04137
04138
04139 template <typename T>
04140 UT_VoxelProbeCube<T>::UT_VoxelProbeCube()
04141 {
04142 myValid = false;
04143 }
04144
04145 template <typename T>
04146 UT_VoxelProbeCube<T>::~UT_VoxelProbeCube()
04147 {
04148 }
04149
04150 template <typename T>
04151 void
04152 UT_VoxelProbeCube<T>::setCubeArray(UT_VoxelArray<T> *vox)
04153 {
04154 myLines[0][0].setArray(vox, -1, 1);
04155 myLines[0][1].setArray(vox, -1, 1);
04156 myLines[0][2].setArray(vox, -1, 1);
04157
04158 myLines[1][0].setArray(vox, -1, 1);
04159 myLines[1][1].setArray(vox, -1, 1);
04160 myLines[1][2].setArray(vox, -1, 1);
04161
04162 myLines[2][0].setArray(vox, -1, 1);
04163 myLines[2][1].setArray(vox, -1, 1);
04164 myLines[2][2].setArray(vox, -1, 1);
04165
04166 myValid = false;
04167 }
04168
04169 template <typename T>
04170 void
04171 UT_VoxelProbeCube<T>::setPlusArray(UT_VoxelArray<T> *vox)
04172 {
04173
04174
04175 myLines[0][1].setArray(vox, -1, 1);
04176
04177 myLines[1][0].setArray(vox, 0, 0);
04178 myLines[1][1].setArray(vox, -1, 1);
04179 myLines[1][2].setArray(vox, 0, 0);
04180
04181 myLines[2][1].setArray(vox, -1, 1);
04182
04183 myValid = false;
04184 }
04185
04186 template <typename T>
04187 bool
04188 UT_VoxelProbeCube<T>::setIndexCube(int x, int y, int z)
04189 {
04190 if (myValid && myZ == z)
04191 {
04192 if (myY == y)
04193 {
04194
04195 if (x < myMaxValidX && x == myX+1)
04196 {
04197
04198 myLines[0][0].advanceX();
04199 myLines[0][1].advanceX();
04200 myLines[0][2].advanceX();
04201
04202 myLines[1][0].advanceX();
04203 myLines[1][1].advanceX();
04204 myLines[1][2].advanceX();
04205
04206 myLines[2][0].advanceX();
04207 myLines[2][1].advanceX();
04208 myLines[2][2].advanceX();
04209
04210
04211 myX = x;
04212
04213 return false;
04214 }
04215 }
04216 #if 1
04217 else if (y == myY+1 && x < myMaxValidX && x >= myMinValidX)
04218 {
04219
04220
04221
04222
04223 rotateLines(myLines[0][0], myLines[1][0], myLines[2][0]);
04224 rotateLines(myLines[0][1], myLines[1][1], myLines[2][1]);
04225 rotateLines(myLines[0][2], myLines[1][2], myLines[2][2]);
04226
04227
04228
04229 myLines[0][0].resetX(x);
04230 myLines[0][1].resetX(x);
04231 myLines[0][2].resetX(x);
04232
04233 myLines[1][0].resetX(x);
04234 myLines[1][1].resetX(x);
04235 myLines[1][2].resetX(x);
04236
04237
04238 myLines[2][0].setIndex(x, y+1, z-1);
04239 myLines[2][1].setIndex(x, y+1, z);
04240 myLines[2][2].setIndex(x, y+1, z+1);
04241
04242
04243 myX = x;
04244 myY = y;
04245
04246 return true;
04247 }
04248 #endif
04249 }
04250
04251
04252 myLines[0][0].setIndex(x, y-1, z-1);
04253 myLines[0][1].setIndex(x, y-1, z);
04254 myLines[0][2].setIndex(x, y-1, z+1);
04255
04256 myLines[1][0].setIndex(x, y, z-1);
04257 myLines[1][1].setIndex(x, y, z);
04258 myLines[1][2].setIndex(x, y, z+1);
04259
04260 myLines[2][0].setIndex(x, y+1, z-1);
04261 myLines[2][1].setIndex(x, y+1, z);
04262 myLines[2][2].setIndex(x, y+1, z+1);
04263
04264
04265 myX = x;
04266 myY = y;
04267 myZ = z;
04268 myValid = true;
04269 myMinValidX = myLines[1][1].myMinValidX;
04270 myMaxValidX = myLines[1][1].myMaxValidX;
04271
04272 return true;
04273 }
04274
04275 template <typename T>
04276 bool
04277 UT_VoxelProbeCube<T>::setIndexPlus(int x, int y, int z)
04278 {
04279 if (myValid && myZ == z)
04280 {
04281 if (myY == y)
04282 {
04283
04284 if (x < myMaxValidX && x == myX+1)
04285 {
04286
04287 myLines[0][1].advanceX();
04288
04289 myLines[1][0].advanceX();
04290 myLines[1][1].advanceX();
04291 myLines[1][2].advanceX();
04292
04293 myLines[2][1].advanceX();
04294
04295
04296 myX = x;
04297
04298 return false;
04299 }
04300 }
04301 else if (y == myY+1 && x < myMaxValidX && x >= myMinValidX)
04302 {
04303
04304
04305
04306
04307 rotateLines(myLines[0][1], myLines[1][1], myLines[2][1]);
04308
04309 myLines[0][1].resetX(x);
04310 myLines[1][1].resetX(x);
04311
04312 myLines[1][0].setIndex(x, y, z-1);
04313 myLines[1][2].setIndex(x, y, z+1);
04314
04315 myLines[2][1].setIndex(x, y+1, z);
04316
04317 myX = x;
04318 myY = y;
04319 return true;
04320 }
04321 }
04322
04323
04324 myLines[0][1].setIndex(x, y-1, z);
04325
04326 myLines[1][0].setIndex(x, y, z-1);
04327 myLines[1][1].setIndex(x, y, z);
04328 myLines[1][2].setIndex(x, y, z+1);
04329
04330 myLines[2][1].setIndex(x, y+1, z);
04331
04332
04333 myX = x;
04334 myY = y;
04335 myZ = z;
04336 myValid = true;
04337 myMinValidX = myLines[1][1].myMinValidX;
04338 myMaxValidX = myLines[1][1].myMaxValidX;
04339
04340 return true;
04341 }
04342
04343 template <typename T>
04344 fpreal64
04345 UT_VoxelProbeCube<T>::curvature(const UT_Vector3 &invvoxelsize) const
04346 {
04347
04348 fpreal64 Px, Py, Pz;
04349 fpreal64 Pxx, Pyy, Pzz;
04350 fpreal64 Pxy, Pxz, Pyz;
04351 fpreal64 gradlen;
04352 fpreal64 k;
04353
04354
04355
04356
04357 Px = getValue(1, 0, 0) - getValue(-1, 0, 0);
04358 Px *= 0.5 * invvoxelsize.x();
04359
04360 Py = getValue(0, 1, 0) - getValue(0, -1, 0);
04361 Py *= 0.5 * invvoxelsize.y();
04362
04363 Pz = getValue(0, 0, 1) - getValue(0, 0, -1);
04364 Pz *= 0.5 * invvoxelsize.z();
04365
04366
04367
04368
04369 Pxx = getValue(1, 0, 0)
04370 - 2 * getValue(0, 0, 0)
04371 + getValue(-1, 0, 0);
04372 Pxx *= invvoxelsize.x() * invvoxelsize.x();
04373
04374 Pyy = getValue(0, 1, 0)
04375 - 2 * getValue(0, 0, 0)
04376 + getValue(0, -1, 0);
04377 Pyy *= invvoxelsize.y() * invvoxelsize.y();
04378
04379 Pzz = getValue(0, 0, 1)
04380 - 2 * getValue(0, 0, 0)
04381 + getValue(0, 0, -1);
04382 Pzz *= invvoxelsize.z() * invvoxelsize.z();
04383
04384
04385 Pxy = getValue(1, 1,0) - getValue(-1, 1,0);
04386 Pxy -= getValue(1,-1,0) - getValue(-1,-1,0);
04387 Pxy *= 0.25 * invvoxelsize.x() * invvoxelsize.y();
04388
04389 Pxz = getValue(1,0, 1) - getValue(-1,0, 1);
04390 Pxz -= getValue(1,0,-1) - getValue(-1,0,-1);
04391 Pxz *= 0.25 * invvoxelsize.x() * invvoxelsize.z();
04392
04393 Pyz = getValue(0,1, 1) - getValue(0,-1, 1);
04394 Pyz -= getValue(0,1,-1) - getValue(0,-1,-1);
04395 Pyz *= 0.25 * invvoxelsize.y() * invvoxelsize.z();
04396
04397
04398 gradlen = SYSsqrt(Px * Px + Py * Py + Pz * Pz);
04399
04400
04401
04402
04403
04404
04405
04406 k = Px*Px * (Pyy + Pzz) + Py*Py * (Pxx + Pzz) + Pz*Pz * (Pxx + Pyy);
04407 k -= 2 * (Pxy*Px*Py + Pyz*Py*Pz + Pxz*Px*Pz);
04408
04409
04410 if (!gradlen)
04411 k = 0;
04412 else
04413 k /= gradlen * gradlen * gradlen;
04414
04415
04416 fpreal64 maxk;
04417
04418 maxk = invvoxelsize.maxComponent();
04419 if (k < -maxk)
04420 k = -maxk;
04421 if (k > maxk)
04422 k = maxk;
04423
04424 return k;
04425 }
04426
04427 template <typename T>
04428 fpreal64
04429 UT_VoxelProbeCube<T>::laplacian(const UT_Vector3 &invvoxelsize) const
04430 {
04431 fpreal64 Pxx, Pyy, Pzz;
04432 fpreal64 centralval;
04433
04434 centralval = getValue(0, 0, 0);
04435
04436
04437 Pxx = getValue(1, 0, 0)
04438 - 2 * centralval
04439 + getValue(-1, 0, 0);
04440 Pxx *= invvoxelsize.x() * invvoxelsize.x();
04441
04442 Pyy = getValue(0, 1, 0)
04443 - 2 * centralval
04444 + getValue(0, -1, 0);
04445 Pyy *= invvoxelsize.y() * invvoxelsize.y();
04446
04447 Pzz = getValue(0, 0, +1)
04448 - 2 * centralval
04449 + getValue(0, 0, -1);
04450 Pzz *= invvoxelsize.z() * invvoxelsize.z();
04451
04452 return Pxx + Pyy + Pzz;
04453 }
04454
04455 template <typename T>
04456 void
04457 UT_VoxelProbeCube<T>::rotateLines(UT_VoxelProbe<T, true, false, false> &ym, UT_VoxelProbe<T, true, false, false> &y0, UT_VoxelProbe<T, true, false, false> &yp)
04458 {
04459 T *tmpcache, *tmpalloc;
04460 const T *tmpcur;
04461
04462
04463
04464 tmpcache = ym.myCacheLine;
04465 tmpalloc = ym.myAllocCacheLine;
04466 tmpcur = ym.myCurLine;
04467
04468 ym.myCacheLine = y0.myCacheLine;
04469 ym.myAllocCacheLine = y0.myAllocCacheLine;
04470 ym.myCurLine = y0.myCurLine;
04471 ym.myStride = y0.myStride;
04472 ym.myY++;
04473
04474 y0.myCacheLine = yp.myCacheLine;
04475 y0.myAllocCacheLine = yp.myAllocCacheLine;
04476 y0.myCurLine = yp.myCurLine;
04477 y0.myStride = yp.myStride;
04478 y0.myY++;
04479
04480 yp.myCacheLine = tmpcache;
04481 yp.myAllocCacheLine = tmpalloc;
04482
04483 yp.myCurLine = 0;
04484 }
04485
04486
04487
04488
04489 template <typename T>
04490 UT_VoxelProbeFace<T>::UT_VoxelProbeFace()
04491 {
04492 myValid = false;
04493 }
04494
04495 template <typename T>
04496 UT_VoxelProbeFace<T>::~UT_VoxelProbeFace()
04497 {
04498 }
04499
04500
04501 template <typename T>
04502 void
04503 UT_VoxelProbeFace<T>::setArray(UT_VoxelArray<T> *vx, UT_VoxelArray<T> *vy, UT_VoxelArray<T> *vz)
04504 {
04505
04506 myLines[0][0].setArray(vx, 0, 1);
04507
04508
04509 myLines[1][0].setArray(vy, 0, 0);
04510 myLines[1][1].setArray(vy, 0, 0);
04511
04512 myLines[2][0].setArray(vz, 0, 0);
04513 myLines[2][1].setArray(vz, 0, 0);
04514
04515 myValid = false;
04516 }
04517
04518 template <typename T>
04519 void
04520 UT_VoxelProbeFace<T>::setVoxelSize(const UT_Vector3 &size)
04521 {
04522 myVoxelSize = size;
04523 myInvVoxelSize = 1;
04524 myInvVoxelSize /= myVoxelSize;
04525 }
04526
04527 template <typename T>
04528 bool
04529 UT_VoxelProbeFace<T>::setIndex(int x, int y, int z)
04530 {
04531 if (myValid && myZ == z)
04532 {
04533 if (myY == y)
04534 {
04535
04536 if (x < myMaxValidX && x == myX+1)
04537 {
04538
04539 myLines[0][0].advanceX();
04540
04541 myLines[1][0].advanceX();
04542 myLines[1][1].advanceX();
04543
04544 myLines[2][0].advanceX();
04545 myLines[2][1].advanceX();
04546
04547
04548 myX = x;
04549
04550 return false;
04551 }
04552 }
04553 else if (y == myY+1 && x < myMaxValidX && x >= myMinValidX)
04554 {
04555
04556
04557
04558 swapLines(myLines[1][0], myLines[1][1]);
04559
04560 myLines[1][0].resetX(x);
04561
04562
04563 myLines[0][0].setIndex(x, y, z);
04564 myLines[1][1].setIndex(x, y+1, z);
04565
04566 myLines[2][0].setIndex(x, y, z);
04567 myLines[2][1].setIndex(x, y, z+1);
04568
04569 myX = x;
04570 myY = y;
04571 return true;
04572 }
04573 }
04574
04575
04576 myLines[0][0].setIndex(x, y, z);
04577
04578 myLines[1][0].setIndex(x, y, z);
04579 myLines[1][1].setIndex(x, y+1, z);
04580
04581 myLines[2][0].setIndex(x, y, z);
04582 myLines[2][1].setIndex(x, y, z+1);
04583
04584
04585 myX = x;
04586 myY = y;
04587 myZ = z;
04588 myValid = true;
04589 myMinValidX = myLines[0][0].myMinValidX;
04590 myMaxValidX = myLines[0][0].myMaxValidX;
04591
04592 return true;
04593 }
04594
04595 template <typename T>
04596 void
04597 UT_VoxelProbeFace<T>::swapLines(UT_VoxelProbe<T, true, false, false> &ym,
04598 UT_VoxelProbe<T, true, false, false> &yp)
04599 {
04600 T *tmpcache, *tmpalloc;
04601 const T *tmpcur;
04602
04603
04604
04605 tmpcache = ym.myCacheLine;
04606 tmpalloc = ym.myAllocCacheLine;
04607 tmpcur = ym.myCurLine;
04608
04609 ym.myCacheLine = yp.myCacheLine;
04610 ym.myAllocCacheLine = yp.myAllocCacheLine;
04611 ym.myCurLine = yp.myCurLine;
04612 ym.myStride = yp.myStride;
04613 ym.myY++;
04614
04615 yp.myCacheLine = tmpcache;
04616 yp.myAllocCacheLine = tmpalloc;
04617
04618 yp.myCurLine = 0;
04619 }
04620
04621
04622
04623
04624 template <typename T, int XStep, int YStep, int ZStep>
04625 void
04626 UT_VoxelProbeAverage<T, XStep, YStep, ZStep>::setArray(UT_VoxelArray<T> *vox)
04627 {
04628 int prex = (XStep < 0) ? XStep : 0;
04629 int postx = (XStep > 0) ? XStep : 0;
04630
04631 myLines[0][0].setArray(vox, prex, postx);
04632 if (YStep)
04633 {
04634 myLines[1][0].setArray(vox, prex, postx);
04635 if (ZStep)
04636 {
04637 myLines[1][1].setArray(vox, prex, postx);
04638 }
04639 }
04640 if (ZStep)
04641 myLines[0][1].setArray(vox, prex, postx);
04642 }
04643
04644 template <typename T, int XStep, int YStep, int ZStep>
04645 bool
04646 UT_VoxelProbeAverage<T, XStep, YStep, ZStep>::setIndex(int x, int y, int z)
04647 {
04648 bool result = false;
04649
04650
04651
04652
04653
04654 if (YStep < 0)
04655 y--;
04656 if (ZStep < 0)
04657 z--;
04658
04659 result |= myLines[0][0].setIndex(x, y, z);
04660 if (YStep)
04661 {
04662 result |= myLines[1][0].setIndex(x, y+1, z);
04663 if (ZStep)
04664 result |= myLines[1][1].setIndex(x, y+1, z+1);
04665 }
04666 if (ZStep)
04667 result |= myLines[0][1].setIndex(x, y, z+1);
04668
04669 return result;
04670 }