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 template <typename T>
00030 void
00031 UT_VoxelTileCompress<T>::findMinMax(const UT_VoxelTile<T> &tile,
00032 T &min, T &max) const
00033 {
00034 int x, y, z;
00035
00036 min = max = getValue(tile, 0, 0, 0);
00037
00038
00039 for (z = 0; z < tile.zres(); z++)
00040 {
00041 for (y = 0; y < tile.yres(); y++)
00042 {
00043 for (x = 0; x < tile.xres(); x++)
00044 {
00045 tile.expandMinMax(getValue(tile, x, y, z), min, max);
00046 }
00047 }
00048 }
00049 return;
00050 }
00051
00052
00053
00054
00055
00056 template <typename T>
00057 UT_VoxelTile<T>::UT_VoxelTile(int xres, int yres, int zres)
00058 {
00059 myRes[0] = xres;
00060 myRes[1] = yres;
00061 myRes[2] = zres;
00062
00063 myCompressionType = COMPRESS_CONSTANT;
00064 myData = SYSamalloc(sizeof(T));
00065
00066
00067
00068
00069
00070 ((T *)myData)[0] = 0;
00071 }
00072
00073 template <typename T>
00074 UT_VoxelTile<T>::~UT_VoxelTile()
00075 {
00076 SYSafree(myData);
00077 }
00078
00079 template <typename T>
00080 UT_VoxelTile<T>::UT_VoxelTile(const UT_VoxelTile<T> &src)
00081 {
00082 myData = 0;
00083
00084
00085 *this = src;
00086 }
00087
00088 template <typename T>
00089 const UT_VoxelTile<T> &
00090 UT_VoxelTile<T>::operator=(const UT_VoxelTile<T> &src)
00091 {
00092 if (&src == this)
00093 return *this;
00094
00095 if (myData)
00096 SYSafree(myData);
00097 myData = 0;
00098
00099 myRes[0] = src.myRes[0];
00100 myRes[1] = src.myRes[1];
00101 myRes[2] = src.myRes[2];
00102
00103 myCompressionType = src.myCompressionType;
00104 switch (myCompressionType)
00105 {
00106 case COMPRESS_RAW:
00107 myData = SYSamalloc(
00108 sizeof(T) * myRes[0] * myRes[1] * myRes[2], 128);
00109 memcpy(myData, src.myData, sizeof(T) * myRes[0] * myRes[1] * myRes[2]);
00110 break;
00111 case COMPRESS_CONSTANT:
00112 myData = SYSamalloc(sizeof(T));
00113 memcpy(myData, src.myData, sizeof(T));
00114 break;
00115 case COMPRESS_RAWFULL:
00116 myData = SYSamalloc(
00117 sizeof(T) * TILESIZE * TILESIZE * TILESIZE, 128);
00118 memcpy(myData, src.myData,
00119 sizeof(T) * TILESIZE * TILESIZE * TILESIZE);
00120 break;
00121 default:
00122 {
00123 UT_VoxelTileCompress<T> *engine;
00124
00125 engine = getCompressionEngine(myCompressionType);
00126 myData = SYSamalloc(engine->getDataLength(src));
00127 memcpy(myData, src.myData, engine->getDataLength(src));
00128 break;
00129 }
00130 }
00131
00132 return *this;
00133 }
00134
00135 template <typename T>
00136 bool
00137 UT_VoxelTile<T>::writeThrough(int x, int y, int z, T t)
00138 {
00139 switch (myCompressionType)
00140 {
00141 case COMPRESS_RAW:
00142
00143 ((T *)myData)[ ((z * myRes[1]) + y) * myRes[0] + x ] = t;
00144 return true;
00145
00146 case COMPRESS_CONSTANT:
00147 if (*(T *)myData == t)
00148 {
00149
00150 return true;
00151 }
00152 return false;
00153
00154 case COMPRESS_RAWFULL:
00155 ((T *)myData)[ ((z * TILESIZE) + y) * TILESIZE + x ] = t;
00156 return true;
00157 }
00158
00159
00160 UT_VoxelTileCompress<T> *engine;
00161
00162 engine = getCompressionEngine(myCompressionType);
00163 return engine->writeThrough(*this, x, y, z, t);
00164 }
00165
00166 template <typename T>
00167 T
00168 UT_VoxelTile<T>::lerp(int x, int y, int z, fpreal32 fx, fpreal32 fy, fpreal32 fz) const
00169 {
00170 T vx, vx1, vy, vy1, vz;
00171
00172 switch (myCompressionType)
00173 {
00174 case COMPRESS_RAW:
00175 case COMPRESS_RAWFULL:
00176 {
00177 T *data = (T *) myData;
00178 int offset = (z * myRes[1] + y) * myRes[0] + x;
00179 int yinc = myRes[0];
00180 int zinc = myRes[0] * myRes[1];
00181
00182
00183 vx = lerpValues(data[offset], data[offset+1], fx);
00184
00185 vx1 = lerpValues(data[offset+yinc], data[offset+yinc+1], fx);
00186
00187
00188 vy = lerpValues(vx, vx1, fy);
00189
00190
00191 vx = lerpValues(data[offset+zinc], data[offset+zinc+1], fx);
00192
00193 vx1 = lerpValues(data[offset+zinc+yinc], data[offset+zinc+yinc+1], fx);
00194
00195
00196 vy1 = lerpValues(vx, vx1, fy);
00197
00198
00199 vz = lerpValues(vy, vy1, fz);
00200 break;
00201 }
00202
00203 case COMPRESS_CONSTANT:
00204 {
00205
00206 vz = *(T *) myData;
00207 break;
00208 }
00209
00210 default:
00211 {
00212 UT_VoxelTileCompress<T> *engine;
00213
00214 engine = getCompressionEngine(myCompressionType);
00215
00216 vx = lerpValues(engine->getValue(*this, x, y, z),
00217 engine->getValue(*this, x+1, y, z),
00218 fx);
00219
00220 vx1 = lerpValues(engine->getValue(*this, x, y+1, z),
00221 engine->getValue(*this, x+1, y+1, z),
00222 fx);
00223
00224
00225 vy = lerpValues(vx, vx1, fy);
00226
00227
00228 vx = lerpValues(engine->getValue(*this, x, y, z+1),
00229 engine->getValue(*this, x+1, y, z+1),
00230 fx);
00231
00232 vx1 = lerpValues(engine->getValue(*this, x, y+1, z+1),
00233 engine->getValue(*this, x+1, y+1, z+1),
00234 fx);
00235
00236
00237 vy1 = lerpValues(vx, vx1, fy);
00238
00239
00240 vz = lerpValues(vy, vy1, fz);
00241 break;
00242 }
00243 }
00244
00245 return vz;
00246 }
00247
00248 #if 0
00249 template <typename T>
00250 T
00251 UT_VoxelTile<T>::lerp(v4uf frac, int x, int y, int z) const
00252 {
00253 v4uf a, b;
00254
00255 switch (myCompressionType)
00256 {
00257 case COMPRESS_RAW:
00258 case COMPRESS_RAWFULL:
00259 {
00260 T *data = (T *) myData;
00261 int offset = (z * myRes[1] + y) * myRes[0] + x;
00262 int yinc = myRes[0];
00263 int zinc = myRes[0] * myRes[1];
00264
00265 a = v4uf( data[offset],
00266 data[offset+zinc],
00267 data[offset+yinc],
00268 data[offset+yinc+zinc] );
00269 b = v4uf( data[offset+1],
00270 data[offset+zinc+1],
00271 data[offset+yinc+1],
00272 data[offset+yinc+zinc+1] );
00273 break;
00274 }
00275
00276 case COMPRESS_CONSTANT:
00277 {
00278
00279 return *(T *) myData;
00280 }
00281
00282 default:
00283 {
00284 UT_VoxelTileCompress<T> *engine;
00285
00286 engine = getCompressionEngine(myCompressionType);
00287
00288 a = v4uf( engine->getValue(*this, x, y, z),
00289 engine->getValue(*this, x, y, z+1),
00290 engine->getValue(*this, x, y+1, z),
00291 engine->getValue(*this, x, y+1, z+1) );
00292 b = v4uf( engine->getValue(*this, x+1, y, z),
00293 engine->getValue(*this, x+1, y, z+1),
00294 engine->getValue(*this, x+1, y+1, z),
00295 engine->getValue(*this, x+1, y+1, z+1) );
00296 break;
00297 }
00298 }
00299
00300 v4uf fx, fy, fz;
00301
00302 fx = frac.swizzle<0, 0, 0, 0>();
00303 fy = frac.swizzle<1, 1, 1, 1>();
00304 fz = frac.swizzle<2, 2, 2, 2>();
00305
00306 b -= a;
00307 a = madd(b, fx, a);
00308
00309 b = a.swizzle<2, 3, 0, 1>();
00310 b -= a;
00311 a = madd(b, fy, a);
00312
00313 b = a.swizzle<1, 2, 3, 0>();
00314 b -= a;
00315 a = madd(b, fz, a);
00316
00317 return a[0];
00318 }
00319 #endif
00320
00321 template <typename T>
00322 T *
00323 UT_VoxelTile<T>::fillCacheLine(T *cacheline, int &stride, int x, int y, int z, bool forcecopy, bool strideofone) const
00324 {
00325 UT_ASSERT_P(x >= 0 && y >= 0 && z >= 0);
00326 UT_ASSERT_P(x < myRes[0] && y < myRes[1] && z < myRes[2]);
00327
00328 T *src;
00329 int i, xres = myRes[0];
00330
00331
00332 switch (myCompressionType)
00333 {
00334 case COMPRESS_RAW:
00335 stride = 1;
00336 src = (T *)myData + (z * myRes[1] + y) * xres;
00337 if (!forcecopy)
00338 return &src[x];
00339
00340 for (i = 0; i < xres; i++)
00341 cacheline[i] = src[i];
00342
00343 return &cacheline[x];
00344
00345
00346 case COMPRESS_CONSTANT:
00347 src = (T *) myData;
00348 if (!forcecopy && !strideofone)
00349 {
00350 stride = 0;
00351 return src;
00352 }
00353 stride = 1;
00354
00355 for (i = 0; i < xres; i++)
00356 cacheline[i] = *src;
00357
00358 return &cacheline[x];
00359
00360
00361 case COMPRESS_RAWFULL:
00362 stride = 1;
00363 src = (T *)myData + (z * TILESIZE + y) * TILESIZE;
00364 if (!forcecopy)
00365 return &src[x];
00366
00367 for (i = 0; i < xres; i++)
00368 cacheline[i] = src[i];
00369
00370 return &cacheline[x];
00371 }
00372
00373
00374 UT_VoxelTileCompress<T> *engine;
00375
00376 engine = getCompressionEngine(myCompressionType);
00377
00378
00379
00380 stride = 1;
00381 for (i = 0; i < xres; i++)
00382 cacheline[i] = engine->getValue(*this, i, y, z);
00383
00384 return &cacheline[x];
00385 }
00386
00387 template <typename T>
00388 void
00389 UT_VoxelTile<T>::writeCacheLine(T *cacheline, int y, int z)
00390 {
00391 UT_ASSERT_P(y >= 0 && z >= 0);
00392 UT_ASSERT_P(y < myRes[1] && z < myRes[2]);
00393
00394 T *dst, value;
00395 int i, xres = myRes[0];
00396
00397
00398 switch (myCompressionType)
00399 {
00400 case COMPRESS_RAW:
00401 dst = (T *)myData + (z * myRes[1] + y) * xres;
00402 for (i = 0; i < xres; i++)
00403 *dst++ = *cacheline++;
00404 return;
00405
00406 case COMPRESS_CONSTANT:
00407 value = *(T *) myData;
00408 for (i = 0; i < xres; i++)
00409 if (cacheline[i] != value)
00410 break;
00411
00412 if (i == xres)
00413 return;
00414
00415 break;
00416
00417 case COMPRESS_RAWFULL:
00418 dst = (T *)myData + (z * TILESIZE + y) * TILESIZE;
00419 for (i = 0; i < TILESIZE; i++)
00420 *dst++ = *cacheline++;
00421
00422 return;
00423 }
00424
00425
00426
00427 for (i = 0; i < xres; i++)
00428 if (!writeThrough(i, y, z, cacheline[i]))
00429 break;
00430
00431
00432 if (i != xres)
00433 {
00434
00435 uncompress();
00436 writeCacheLine(cacheline, y, z);
00437 }
00438 }
00439
00440 template <typename T>
00441 void
00442 UT_VoxelTile<T>::setValue(int x, int y, int z, T t)
00443 {
00444 UT_ASSERT_P(x >= 0 && y >= 0 && z >= 0);
00445 UT_ASSERT_P(x < myRes[0] && y < myRes[1] && z < myRes[2]);
00446
00447
00448
00449 if (writeThrough(x, y, z, t))
00450 {
00451 return;
00452 }
00453
00454
00455 uncompress();
00456
00457
00458
00459 bool success;
00460
00461 success = writeThrough(x, y, z, t);
00462 UT_ASSERT_P(success);
00463 }
00464
00465 template <typename T>
00466 void
00467 UT_VoxelTile<T>::uncompress()
00468 {
00469 switch (myCompressionType)
00470 {
00471 case COMPRESS_RAW:
00472
00473 return;
00474
00475 case COMPRESS_CONSTANT:
00476 {
00477
00478 T cval;
00479 int i, n;
00480
00481 myCompressionType = COMPRESS_RAW;
00482
00483 if (myRes[0] == TILESIZE &&
00484 myRes[1] == TILESIZE &&
00485 myRes[2] == TILESIZE)
00486 {
00487
00488 myCompressionType = COMPRESS_RAWFULL;
00489 }
00490
00491 cval = *(T *)myData;
00492 SYSafree(myData);
00493 n = myRes[0] * myRes[1] * myRes[2];
00494 myData = SYSamalloc(sizeof(T) * n, 128);
00495
00496 for (i = 0; i < n; i++)
00497 {
00498 ((T *)myData)[i] = cval;
00499 }
00500 return;
00501 }
00502 case COMPRESS_RAWFULL:
00503 {
00504 T *raw;
00505 int x, y, z, i, n;
00506
00507 if (myRes[0] == TILESIZE &&
00508 myRes[1] == TILESIZE &&
00509 myRes[2] == TILESIZE)
00510 {
00511
00512 return;
00513 }
00514
00515
00516 myCompressionType = COMPRESS_RAW;
00517
00518 n = myRes[0] * myRes[1] * myRes[2];
00519 raw = (T *)SYSamalloc(sizeof(T) * n, 128);
00520 i = 0;
00521 for (z = 0; z < myRes[2]; z++)
00522 {
00523 for (y = 0; y < myRes[1]; y++)
00524 {
00525 for (x = 0; x < myRes[0]; x++)
00526 {
00527 raw[i++] = ((T *)myData)[x+(y+z*TILESIZE)*TILESIZE];
00528 }
00529 }
00530 }
00531 SYSafree(myData);
00532 myData = raw;
00533
00534 return;
00535 }
00536 }
00537
00538
00539 UT_VoxelTileCompress<T> *engine;
00540
00541 engine = getCompressionEngine(myCompressionType);
00542
00543
00544 int x, y, z, i;
00545 T *raw;
00546
00547 raw = (T *) SYSamalloc(sizeof(T) * myRes[0] * myRes[1] * myRes[2], 128);
00548 i = 0;
00549 for (z = 0; z < myRes[2]; z++)
00550 {
00551 for (y = 0; y < myRes[1]; y++)
00552 {
00553 for (x = 0; x < myRes[0]; x++)
00554 {
00555 raw[i++] = engine->getValue(*this, x, y, z);
00556 }
00557 }
00558 }
00559
00560
00561 myCompressionType = COMPRESS_RAW;
00562 if (myRes[0] == TILESIZE &&
00563 myRes[1] == TILESIZE &&
00564 myRes[2] == TILESIZE)
00565 {
00566
00567 myCompressionType = COMPRESS_RAWFULL;
00568 }
00569
00570 SYSafree(myData);
00571 myData = raw;
00572 }
00573
00574 template <typename T>
00575 void
00576 UT_VoxelTile<T>::uncompressFull()
00577 {
00578 T *raw;
00579 int x, y, z, i;
00580
00581 if (myCompressionType == COMPRESS_RAWFULL)
00582 return;
00583
00584 uncompress();
00585
00586 UT_ASSERT(myCompressionType == COMPRESS_RAW);
00587
00588 myCompressionType = COMPRESS_RAWFULL;
00589
00590
00591
00592 if (myRes[0] < TILESIZE || myRes[1] < TILESIZE || myRes[2] < TILESIZE)
00593 {
00594 raw = (T *)SYSamalloc(sizeof(T) * TILESIZE * TILESIZE * TILESIZE, 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[x+(y+z*TILESIZE)*TILESIZE] = ((T *)myData)[i++];
00603 }
00604 }
00605 }
00606 SYSafree(myData);
00607 myData = raw;
00608 }
00609 }
00610
00611
00612 template <typename T>
00613 void
00614 UT_VoxelTile<T>::findMinMax(T &min, T &max) const
00615 {
00616 switch (myCompressionType)
00617 {
00618 case COMPRESS_RAW:
00619 {
00620 int n = myRes[0] * myRes[1] * myRes[2];
00621 int i;
00622
00623 min = max = *(T*)myData;
00624 for (i = 1; i < n; i++)
00625 {
00626 expandMinMax( ((T*)myData)[i], min, max );
00627 }
00628 return;
00629 }
00630
00631 case COMPRESS_CONSTANT:
00632 min = max = *(T*)myData;
00633 return;
00634
00635 case COMPRESS_RAWFULL:
00636 {
00637 int x, y, z, offset;
00638
00639 min = max = *(T*)myData;
00640 offset = 0;
00641 for (z = 0; z < myRes[2]; z++)
00642 {
00643 for (y = 0; y < myRes[1]; y++)
00644 {
00645 for (x = 0; x < myRes[0]; x++)
00646 {
00647 expandMinMax(
00648 ((T*)myData)[x+offset],
00649 min, max );
00650 }
00651 offset += TILESIZE;
00652 }
00653 }
00654 return;
00655 }
00656
00657 default:
00658 {
00659
00660 UT_VoxelTileCompress<T> *engine;
00661
00662 engine = getCompressionEngine(myCompressionType);
00663
00664 engine->findMinMax(*this, min, max);
00665 return;
00666 }
00667 }
00668 }
00669
00670 template <typename T>
00671 bool
00672 UT_VoxelTile<T>::tryCompress(fpreal tol)
00673 {
00674 T min, max;
00675 int i;
00676 UT_VoxelTileCompress<T> *engine;
00677
00678 findMinMax(min, max);
00679
00680
00681 if (dist(min, max) <= tol)
00682 {
00683
00684 if (myCompressionType == COMPRESS_CONSTANT)
00685 return false;
00686
00687
00688 makeConstant( (min + max) / 2 );
00689 return true;
00690 }
00691
00692 for (i = 0; i < getCompressionEngines().entries(); i++)
00693 {
00694 engine = getCompressionEngines()(i);
00695
00696 if (engine->tryCompress(*this, tol, min, max))
00697 {
00698 myCompressionType = i + COMPRESS_ENGINE;
00699 return true;
00700 }
00701 }
00702
00703
00704 return false;
00705 }
00706
00707 template <typename T>
00708 void
00709 UT_VoxelTile<T>::makeConstant(T t)
00710 {
00711 if (!isConstant())
00712 {
00713 SYSafree(myData);
00714 myData = SYSamalloc(sizeof(T));
00715 }
00716
00717 *(T*)myData = t;
00718 myCompressionType = COMPRESS_CONSTANT;
00719 }
00720
00721 template <typename T>
00722 int64
00723 UT_VoxelTile<T>::getMemoryUsage() const
00724 {
00725 int64 usage;
00726
00727 usage = sizeof(*this);
00728 usage += getDataLength();
00729 return usage;
00730 }
00731
00732 template <typename T>
00733 int64
00734 UT_VoxelTile<T>::getDataLength() const
00735 {
00736 int64 usage;
00737
00738 switch (myCompressionType)
00739 {
00740 case COMPRESS_RAW:
00741 usage = sizeof(T) * xres() * yres() * zres();
00742 break;
00743 case COMPRESS_CONSTANT:
00744 usage = sizeof(T);
00745 break;
00746 case COMPRESS_RAWFULL:
00747 usage = sizeof(T) * TILESIZE * TILESIZE * TILESIZE;
00748 break;
00749 default:
00750 {
00751
00752 UT_VoxelTileCompress<T> *engine;
00753 engine = getCompressionEngine(myCompressionType);
00754 usage = engine->getDataLength(*this);
00755 break;
00756 }
00757 }
00758 return usage;
00759 }
00760
00761 template <typename T>
00762 void
00763 UT_VoxelTile<T>::weightedSum(int pstart[3], int pend[3],
00764 float *weights[3], int start[3],
00765 T &result)
00766 {
00767 int ix, iy, iz, i;
00768 int px, py, pz;
00769 int ixstart, ixend;
00770 int tstart[3];
00771 fpreal w, pw;
00772 T psumx, psumy;
00773
00774 switch (myCompressionType)
00775 {
00776 case COMPRESS_CONSTANT:
00777 {
00778 w = 1;
00779 for (i = 0; i < 3; i++)
00780 {
00781 pw = 0;
00782 for (ix = 0; ix < pend[i]-pstart[i]; ix++)
00783 pw += weights[i][ix+pstart[i]-start[i]];
00784 w *= pw;
00785 }
00786 result += w * ((T*)myData)[0];
00787 break;
00788 }
00789
00790 case COMPRESS_RAW:
00791 {
00792 tstart[0] = pstart[0] & TILEMASK;
00793 tstart[1] = pstart[1] & TILEMASK;
00794 tstart[2] = pstart[2] & TILEMASK;
00795 ixstart = pstart[0]-start[0];
00796 ixend = pend[0]-start[0];
00797 pz = tstart[2];
00798 UT_ASSERT(pz < myRes[2]);
00799 UT_ASSERT(ixend - ixstart <= myRes[0]);
00800 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
00801 {
00802 psumy = 0;
00803 py = tstart[1];
00804 UT_ASSERT(py < myRes[1]);
00805 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
00806 {
00807 psumx = 0;
00808 px = ((pz * myRes[1]) + py) * myRes[0] + tstart[0];
00809 for (ix = ixstart; ix < ixend; ix++, px++)
00810 {
00811 psumx += weights[0][ix]* ((T*)myData)[px];
00812 }
00813 psumy += weights[1][iy-start[1]] * psumx;
00814 }
00815 result += weights[2][iz-start[2]] * psumy;
00816 }
00817 break;
00818 }
00819
00820 case COMPRESS_RAWFULL:
00821 {
00822 tstart[0] = pstart[0] & TILEMASK;
00823 tstart[1] = pstart[1] & TILEMASK;
00824 tstart[2] = pstart[2] & TILEMASK;
00825 ixstart = pstart[0]-start[0];
00826 ixend = pend[0]-start[0];
00827 pz = tstart[2];
00828 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
00829 {
00830 psumy = 0;
00831 py = tstart[1];
00832 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
00833 {
00834 psumx = 0;
00835 px = ((pz * TILESIZE) + py) * TILESIZE + tstart[0];
00836 for (ix = ixstart; ix < ixend; ix++, px++)
00837 {
00838 psumx += weights[0][ix]* ((T*)myData)[px];
00839 }
00840 psumy += weights[1][iy-start[1]] * psumx;
00841 }
00842 result += weights[2][iz-start[2]] * psumy;
00843 }
00844 break;
00845 }
00846
00847 default:
00848 {
00849
00850
00851
00852 tstart[0] = pstart[0] & TILEMASK;
00853 tstart[1] = pstart[1] & TILEMASK;
00854 tstart[2] = pstart[2] & TILEMASK;
00855 ixstart = pstart[0]-start[0];
00856 ixend = pend[0]-start[0];
00857 pz = tstart[2];
00858 for (iz = pstart[2]; iz < pend[2]; iz++, pz++)
00859 {
00860 psumy = 0;
00861 py = tstart[1];
00862 for (iy = pstart[1]; iy < pend[1]; iy++, py++)
00863 {
00864 psumx = 0;
00865 px = tstart[0];
00866 for (ix = ixstart; ix < ixend; ix++, px++)
00867 {
00868 psumx += weights[0][ix] *
00869 (*this)(px, py, pz);
00870 }
00871 psumy += weights[1][iy-start[1]] * psumx;
00872 }
00873 result += weights[2][iz-start[2]] * psumy;
00874 }
00875 break;
00876 }
00877 }
00878 }
00879
00880 template <typename T>
00881 void
00882 UT_VoxelTile<T>::registerCompressionEngine(UT_VoxelTileCompress<T> *engine)
00883 {
00884 int i;
00885
00886
00887 for (i = 0; i < getCompressionEngines().entries(); i++)
00888 {
00889 if (!strcmp(engine->getName(), getCompressionEngines()(i)->getName()))
00890 {
00891 getCompressionEngines()(i) = engine;
00892 return;
00893 }
00894 }
00895
00896 getCompressionEngines().append(engine);
00897 }
00898
00899 template <typename T>
00900 int
00901 UT_VoxelTile<T>::lookupCompressionEngine(const char *name)
00902 {
00903 int i;
00904
00905 if (!name)
00906 return -1;
00907
00908 for (i = 0; i < getCompressionEngines().entries(); i++)
00909 {
00910 if (!strcmp(name, getCompressionEngines()(i)->getName()))
00911 {
00912 return i + COMPRESS_ENGINE;
00913 }
00914 }
00915
00916 return -1;
00917 }
00918
00919 template <typename T>
00920 UT_VoxelTileCompress<T> *
00921 UT_VoxelTile<T>::getCompressionEngine(int index)
00922 {
00923 index -= COMPRESS_ENGINE;
00924
00925 return getCompressionEngines()(index);
00926 }
00927
00928 template <typename T>
00929 void
00930 UT_VoxelTile<T>::save(ostream &os)
00931 {
00932
00933 if (myCompressionType >= COMPRESS_ENGINE)
00934 {
00935 UT_VoxelTileCompress<T> *engine = getCompressionEngine(myCompressionType);
00936
00937 if (engine->canSave())
00938 {
00939 char type = myCompressionType;
00940
00941 UTwrite(os, &type, 1);
00942 engine->save(os, *this);
00943 return;
00944 }
00945
00946
00947 uncompress();
00948 }
00949
00950 int len;
00951 char type = myCompressionType;
00952
00953 UT_ASSERT(type >= 0 && type < COMPRESS_ENGINE);
00954
00955 UTwrite(os, &type, 1);
00956
00957 switch (myCompressionType)
00958 {
00959 case COMPRESS_RAW:
00960 len = myRes[2] * myRes[1] * myRes[0];
00961 UTwrite(os, (T *) myData, len);
00962 break;
00963
00964 case COMPRESS_RAWFULL:
00965 len = TILESIZE * TILESIZE * TILESIZE;
00966 UTwrite(os, (T *) myData, len);
00967 break;
00968
00969 case COMPRESS_CONSTANT:
00970 UTwrite(os, (T *) myData, 1);
00971 break;
00972 }
00973 }
00974
00975 template <typename T>
00976 void
00977 UT_VoxelTile<T>::load(UT_IStream &is, const UT_IntArray &compress)
00978 {
00979 char type, otype;
00980 int len;
00981
00982 is.readChar(type);
00983
00984
00985 if (type >= 0 && type < compress.entries())
00986 {
00987 otype = type;
00988 type = compress(type);
00989 if (type == -1)
00990 {
00991 cerr << "Missing compression engine " << (int) otype << endl;
00992 }
00993 }
00994
00995 if (type >= COMPRESS_ENGINE)
00996 {
00997 myCompressionType = type;
00998
00999 UT_VoxelTileCompress<T> *engine = getCompressionEngine(myCompressionType);
01000
01001 engine->load(is, *this);
01002
01003 return;
01004 }
01005
01006 UT_ASSERT(type >= 0);
01007 if (type < 0)
01008 {
01009 return;
01010 }
01011
01012 if (myData)
01013 SYSafree(myData);
01014
01015 myCompressionType = type;
01016
01017 switch (myCompressionType)
01018 {
01019 case COMPRESS_RAW:
01020 len = myRes[2] * myRes[1] * myRes[0];
01021 myData = SYSamalloc(sizeof(T) * len, 128);
01022 is.read((T *) myData, len);
01023 break;
01024
01025 case COMPRESS_RAWFULL:
01026 len = TILESIZE * TILESIZE * TILESIZE;
01027 myData = SYSamalloc(sizeof(T) * len, 128);
01028 is.read((T *) myData, len);
01029 break;
01030
01031 case COMPRESS_CONSTANT:
01032 myData = SYSamalloc(sizeof(T));
01033 is.read((T *) myData, 1);
01034 break;
01035 }
01036 }
01037
01038 template <typename T>
01039 void
01040 UT_VoxelTile<T>::saveCompressionTypes(ostream &os)
01041 {
01042 int16 ntype = getCompressionEngines().entries();
01043 int i;
01044
01045 ntype += COMPRESS_ENGINE;
01046
01047 UTwrite(os, &ntype);
01048
01049 UT_ASSERT(COMPRESS_ENGINE == 3);
01050 UTsaveStringBinary(os, "raw", UT_STRING_8BIT_IO);
01051 UTsaveStringBinary(os, "rawfull", UT_STRING_8BIT_IO);
01052 UTsaveStringBinary(os, "constant", UT_STRING_8BIT_IO);
01053
01054 ntype -= COMPRESS_ENGINE;
01055 for (i = 0; i < ntype; i++)
01056 {
01057 UTsaveStringBinary(os, getCompressionEngines()(i)->getName(), UT_STRING_8BIT_IO);
01058 }
01059 }
01060
01061 template <typename T>
01062 void
01063 UT_VoxelTile<T>::loadCompressionTypes(UT_IStream &is, UT_IntArray &compress)
01064 {
01065 int16 ntype;
01066 int i, idx;
01067
01068 compress.entries(0);
01069
01070 is.read(&ntype);
01071
01072 for (i = 0; i < ntype; i++)
01073 {
01074 UT_String name;
01075
01076 is.readBinaryString(name, UT_ISTREAM_8BIT_IO);
01077 if (name == "raw")
01078 compress.append(COMPRESS_RAW);
01079 else if (name == "rawfull")
01080 compress.append(COMPRESS_RAWFULL);
01081 else if (name == "constant")
01082 compress.append(COMPRESS_CONSTANT);
01083 else
01084 {
01085 idx = lookupCompressionEngine(name);
01086
01087
01088
01089
01090 compress.append(idx);
01091 }
01092 }
01093 }
01094
01095
01096
01097
01098
01099
01100
01101 template <typename T>
01102 UT_VoxelArray<T>::UT_VoxelArray()
01103 {
01104 myRes[0] = 0;
01105 myRes[1] = 0;
01106 myRes[2] = 0;
01107 myTileRes[0] = 0;
01108 myTileRes[1] = 0;
01109 myTileRes[2] = 0;
01110
01111 myTiles = 0;
01112
01113 myBorderValue = 0;
01114 myBorderType = UT_VOXELBORDER_STREAK;
01115
01116 myCompressionTolerance = 0.0;
01117 }
01118
01119 template <typename T>
01120 UT_VoxelArray<T>::~UT_VoxelArray()
01121 {
01122 deleteVoxels();
01123 }
01124
01125 template <typename T>
01126 UT_VoxelArray<T>::UT_VoxelArray(const UT_VoxelArray<T> &src)
01127 {
01128 myRes[0] = 0;
01129 myRes[1] = 0;
01130 myRes[2] = 0;
01131 myTileRes[0] = 0;
01132 myTileRes[1] = 0;
01133 myTileRes[2] = 0;
01134
01135 myTiles = 0;
01136
01137 *this = src;
01138 }
01139
01140 template <typename T>
01141 const UT_VoxelArray<T> &
01142 UT_VoxelArray<T>::operator=(const UT_VoxelArray<T> &src)
01143 {
01144
01145 if (&src == this)
01146 return *this;
01147
01148
01149
01150 deleteVoxels();
01151
01152 myBorderValue = src.myBorderValue;
01153 myBorderType = src.myBorderType;
01154
01155 myCompressionTolerance = src.myCompressionTolerance;
01156
01157
01158 size(src.myRes[0], src.myRes[1], src.myRes[2]);
01159
01160 int i, ntiles;
01161
01162 ntiles = numTiles();
01163
01164 for (i = 0; i < ntiles; i++)
01165 {
01166 *myTiles[i] = *src.myTiles[i];
01167 }
01168
01169 return *this;
01170 }
01171
01172 template <typename T>
01173 void
01174 UT_VoxelArray<T>::deleteVoxels()
01175 {
01176 int i, n;
01177
01178 n = numTiles();
01179 for (i = 0; i < n; i++)
01180 delete myTiles[i];
01181 delete [] myTiles;
01182 myTiles = 0;
01183
01184 myTileRes[0] = myTileRes[1] = myTileRes[2] = 0;
01185 myRes[0] = myRes[1] = myRes[2] = 0;
01186 }
01187
01188 template <typename T>
01189 void
01190 UT_VoxelArray<T>::size(int xres, int yres, int zres)
01191 {
01192 deleteVoxels();
01193
01194 myRes[0] = xres;
01195 myRes[1] = yres;
01196 myRes[2] = zres;
01197
01198
01199 myTileRes[0] = (xres + TILEMASK) >> TILEBITS;
01200 myTileRes[1] = (yres + TILEMASK) >> TILEBITS;
01201 myTileRes[2] = (zres + TILEMASK) >> TILEBITS;
01202
01203 int ntiles;
01204
01205 ntiles = myTileRes[0] * myTileRes[1] * myTileRes[2];
01206
01207 if (ntiles)
01208 {
01209 myTiles = new UT_VoxelTile<T> *[ntiles];
01210
01211 int tx, ty, tz, i;
01212 int xr, yr, zr;
01213
01214 i = 0;
01215 for (tz = 0; tz < myTileRes[2]; tz++)
01216 {
01217 if (tz < myTileRes[2]-1)
01218 zr = TILESIZE;
01219 else
01220 zr = zres - tz * TILESIZE;
01221
01222 for (ty = 0; ty < myTileRes[1]; ty++)
01223 {
01224 if (ty < myTileRes[1]-1)
01225 yr = TILESIZE;
01226 else
01227 yr = yres - ty * TILESIZE;
01228
01229 xr = TILESIZE;
01230 for (tx = 0; tx < myTileRes[0]-1; tx++)
01231 {
01232 myTiles[i] = new UT_VoxelTile<T>(xr, yr, zr);
01233
01234 i++;
01235 }
01236 xr = xres - tx * TILESIZE;
01237 myTiles[i] = new UT_VoxelTile<T>(xr, yr, zr);
01238 i++;
01239 }
01240 }
01241 }
01242 else
01243 myTiles = 0;
01244 }
01245
01246 template <typename T>
01247 void
01248 UT_VoxelArray<T>::match(const UT_VoxelArray<T> &src)
01249 {
01250
01251 if (src.getXRes() != getXRes() ||
01252 src.getYRes() != getYRes() ||
01253 src.getZRes() != getZRes())
01254 {
01255 size(src.getXRes(), src.getYRes(), src.getZRes());
01256 }
01257
01258
01259 myBorderType = src.myBorderType;
01260 myBorderValue = src.myBorderValue;
01261 }
01262
01263 template <typename T>
01264 int64
01265 UT_VoxelArray<T>::getMemoryUsage() const
01266 {
01267 int64 totaltilesize = 0;
01268 int i, ntiles;
01269
01270 ntiles = numTiles();
01271 for (i = 0; i < ntiles; i++)
01272 totaltilesize += myTiles[i]->getMemoryUsage();
01273
01274 return sizeof(*this) + totaltilesize;
01275 }
01276
01277 template <typename T>
01278 void
01279 UT_VoxelArray<T>::constant(T t)
01280 {
01281 int i, ntiles;
01282
01283 ntiles = numTiles();
01284 for (i = 0; i < ntiles; i++)
01285 {
01286 myTiles[i]->makeConstant(t);
01287 }
01288 }
01289
01290 template <typename T>
01291 bool
01292 UT_VoxelArray<T>::isConstant(T *t) const
01293 {
01294 int i, ntiles;
01295 T cval;
01296 const fpreal tol = UT_FTOLERANCE;
01297
01298 ntiles = numTiles();
01299 for (i = 0; i < ntiles; i++)
01300 {
01301 if (!myTiles[i]->isConstant())
01302 {
01303 return false;
01304 }
01305
01306 if (!i)
01307 {
01308
01309 cval = (*myTiles[i])(0, 0, 0);
01310 }
01311 else
01312 {
01313
01314 if (UT_VoxelTile<T>::dist(cval, (*myTiles[i])(0, 0, 0)) > tol)
01315 {
01316 return false;
01317 }
01318 }
01319 }
01320
01321
01322
01323 if (t)
01324 *t = cval;
01325
01326 return true;
01327 }
01328
01329 template <typename T>
01330 T
01331 UT_VoxelArray<T>::operator()(UT_Vector3 pos) const
01332 {
01333 #if 0
01334 v4uf pos4(pos.x(), pos.y(), pos.z(), 0);
01335
01336
01337 return (*this)(pos4);
01338 #else
01339 int x, y, z;
01340
01341 fpreal32 fx, fy, fz;
01342
01343
01344
01345 pos.x() *= myRes[0];
01346 pos.y() *= myRes[1];
01347 pos.z() *= myRes[2];
01348 pos.x() -= 0.5;
01349 pos.y() -= 0.5;
01350 pos.z() -= 0.5;
01351
01352
01353 fx = pos.x();
01354 SYSfastSplitFloat(fx, x);
01355 fy = pos.y();
01356 SYSfastSplitFloat(fy, y);
01357 fz = pos.z();
01358 SYSfastSplitFloat(fz, z);
01359
01360
01361 T vx, vx1, vy, vy1, vz;
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 if ( (x > 0) && (y > 0) && (z > 0) &&
01378
01379
01380 (x < myRes[0]-1) && (y < myRes[1]-1) && (z < myRes[2]-1) )
01381 {
01382 int xm, ym, zm;
01383
01384 xm = x & TILEMASK;
01385 ym = y & TILEMASK;
01386 zm = z & TILEMASK;
01387
01388 if ((xm != TILEMASK) && (ym != TILEMASK) && (zm != TILEMASK))
01389 {
01390 const UT_VoxelTile<T> *tile =
01391 getTile(x >> TILEBITS, y >> TILEBITS, z >> TILEBITS);
01392
01393 vz = tile->lerp(xm, ym, zm, fx, fy, fz);
01394 }
01395 else
01396 {
01397
01398
01399
01400
01401
01402 vx = UT_VoxelTile<T>::lerpValues((*this)(x, y, z),
01403 (*this)(x+1, y, z),
01404 fx);
01405
01406 vx1= UT_VoxelTile<T>::lerpValues((*this)(x, y+1, z),
01407 (*this)(x+1, y+1, z),
01408 fx);
01409
01410 vy = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01411
01412
01413 vx = UT_VoxelTile<T>::lerpValues((*this)(x, y, z+1),
01414 (*this)(x+1, y, z+1),
01415 fx);
01416
01417 vx1= UT_VoxelTile<T>::lerpValues((*this)(x, y+1, z+1),
01418 (*this)(x+1, y+1, z+1),
01419 fx);
01420
01421
01422 vy1 = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01423
01424
01425 vz = UT_VoxelTile<T>::lerpValues(vy, vy1, fz);
01426 }
01427 }
01428 else
01429 {
01430
01431 vx = UT_VoxelTile<T>::lerpValues(getValue(x, y, z),
01432 getValue(x+1, y, z),
01433 fx);
01434
01435 vx1= UT_VoxelTile<T>::lerpValues(getValue(x, y+1, z),
01436 getValue(x+1, y+1, z),
01437 fx);
01438
01439
01440 vy = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01441
01442
01443 vx = UT_VoxelTile<T>::lerpValues(getValue(x, y, z+1),
01444 getValue(x+1, y, z+1),
01445 fx);
01446
01447 vx1= UT_VoxelTile<T>::lerpValues(getValue(x, y+1, z+1),
01448 getValue(x+1, y+1, z+1),
01449 fx);
01450
01451
01452 vy1 = UT_VoxelTile<T>::lerpValues(vx, vx1, fy);
01453
01454
01455 vz = UT_VoxelTile<T>::lerpValues(vy, vy1, fz);
01456 }
01457
01458 return vz;
01459 #endif
01460 }
01461
01462 #if 0
01463 template <typename T>
01464 T
01465 UT_VoxelArray<T>::operator()(v4uf pos) const
01466 {
01467 int x, y, z;
01468
01469 v4ui idx;
01470
01471
01472
01473 pos *= v4uf((float) myRes[0], (float) myRes[1], (float) myRes[2], 0.0f);
01474
01475
01476
01477 pos += 1.5;
01478
01479 idx = pos.splitFloat();
01480
01481
01482 idx -= 2;
01483
01484 x = idx[0];
01485 y = idx[1];
01486 z = idx[2];
01487
01488
01489
01490
01491
01492 v4uf a, b, fx, fy, fz;
01493
01494 int xm, ym, zm;
01495
01496 xm = x & TILEMASK;
01497 ym = y & TILEMASK;
01498 zm = z & TILEMASK;
01499
01500
01501
01502 if ( (x > 0) & (y > 0) & (z > 0) &
01503 (x < myRes[0]-1) & (y < myRes[1]-1) & (z < myRes[2]-1) &
01504 (xm != TILEMASK) & (ym != TILEMASK) & (zm != TILEMASK) )
01505
01506
01507
01508
01509
01510
01511 {
01512 const UT_VoxelTile<T> *tile =
01513 getTile(x >> TILEBITS, y >> TILEBITS, z >> TILEBITS);
01514
01515 return tile->lerp(pos, xm, ym, zm);
01516 }
01517 else
01518 {
01519 a = v4uf( getValue(x, y, z),
01520 getValue(x, y, z+1),
01521 getValue(x, y+1, z),
01522 getValue(x, y+1, z+1) );
01523 b = v4uf( getValue(x+1, y, z),
01524 getValue(x+1, y, z+1),
01525 getValue(x+1, y+1, z),
01526 getValue(x+1, y+1, z+1) );
01527 }
01528
01529 fx = pos.swizzle<0, 0, 0, 0>();
01530 fy = pos.swizzle<1, 1, 1, 1>();
01531 fz = pos.swizzle<2, 2, 2, 2>();
01532
01533 b -= a;
01534 a = madd(b, fx, a);
01535
01536 b = a.swizzle<2, 3, 0, 1>();
01537 b -= a;
01538 a = madd(b, fy, a);
01539
01540 b = a.swizzle<1, 2, 3, 0>();
01541 b -= a;
01542 a = madd(b, fz, a);
01543
01544 return a[0];
01545 }
01546 #endif
01547
01548 static inline int
01549 firstTile(int &start, int &end, int res)
01550 {
01551 if (start < 0)
01552 {
01553 start += res;
01554 end += res;
01555 }
01556 return start;
01557 }
01558
01559 static inline int
01560 nextTile(int &tile, int &pstart, int &start, int &end, int res)
01561 {
01562 int pend;
01563
01564 if (pstart >= res)
01565 {
01566 pstart -= res;
01567 start -= res;
01568 end -= res;
01569 }
01570 tile = pstart >> TILEBITS;
01571 pend = SYSmin((tile+1) * TILESIZE, end, res);
01572
01573 UT_ASSERT(pstart >= 0 && pstart < res);
01574 UT_ASSERT(pend > 0 && pstart <= res);
01575 UT_ASSERT(pend-pstart > 0);
01576 UT_ASSERT(pend-pstart <= TILESIZE);
01577
01578 return pend;
01579 }
01580
01581 template <typename T>
01582 T
01583 UT_VoxelArray<T>::evaluate(const UT_Vector3 &pos, const UT_Filter &filter,
01584 fpreal radius) const
01585 {
01586 UT_Vector3 tpos;
01587 UT_FilterWindow win[3];
01588 UT_FilterWrap wrap;
01589 UT_VoxelTile<T> *tile;
01590 fpreal *weights[3];
01591 fpreal *wdata;
01592 fpreal iradius, visible;
01593 int start[3], end[3], size[3];
01594 int pstart[3], pend[3];
01595 int tx, ty, tz, i;
01596 T result;
01597
01598 result = 0;
01599
01600 radius *= filter.getSupport();
01601 iradius = radius == 0 ? 1000 : 0.5F / radius;
01602
01603
01604 tpos = pos;
01605 for (i = 0; i < 3; i++)
01606 {
01607 tpos[i] = tpos[i]*myRes[i];
01608 win[i].initWeights(tpos[i], radius);
01609 if (win[i].getSize() <= 0)
01610 return result;
01611 }
01612
01613
01614 wdata = (fpreal *)UTstackAlloc(
01615 (win[0].getSize()+win[1].getSize()+win[2].getSize())*
01616 sizeof(fpreal));
01617 weights[0] = wdata;
01618 weights[1] = weights[0] + win[0].getSize();
01619 weights[2] = weights[1] + win[1].getSize();
01620
01621 switch (myBorderType)
01622 {
01623 case UT_VOXELBORDER_CONSTANT: wrap = UT_WRAP_BORDER; break;
01624 case UT_VOXELBORDER_REPEAT: wrap = UT_WRAP_REPEAT; break;
01625 case UT_VOXELBORDER_STREAK: wrap = UT_WRAP_CLAMP; break;
01626 default: wrap = UT_WRAP_CLAMP; break;
01627 }
01628
01629 visible = 1;
01630 for (i = 0; i < 3; i++)
01631 {
01632 win[i].fillWeights(weights[i], filter, tpos[i], iradius,
01633 myRes[i], wrap);
01634 start[i] = win[i].getStart() % myRes[i];
01635 size[i] = win[i].getSize();
01636
01637 UT_ASSERT(start[i] >= 0);
01638 UT_ASSERT(size[i] <= myRes[i]);
01639
01640 end[i] = start[i] + size[i];
01641 visible *= win[i].getVisible();
01642 }
01643
01644
01645 if (weights[0] && weights[1] && weights[2])
01646 {
01647 pstart[2] = firstTile(start[2], end[2], myRes[2]);
01648 while (pstart[2] < end[2])
01649 {
01650 pend[2] = nextTile(tz, pstart[2], start[2], end[2], myRes[2]);
01651 pstart[1] = firstTile(start[1], end[1], myRes[1]);
01652 while (pstart[1] < end[1])
01653 {
01654 pend[1] = nextTile(ty, pstart[1], start[1], end[1], myRes[1]);
01655 pstart[0] = firstTile(start[0], end[0], myRes[0]);
01656 while (pstart[0] < end[0])
01657 {
01658 pend[0] = nextTile(tx, pstart[0], start[0], end[0], myRes[0]);
01659 tile = getTile(tx, ty, tz);
01660 UT_ASSERT(tile);
01661 tile->weightedSum(pstart, pend, weights, start, result);
01662 pstart[0] = pend[0];
01663 }
01664 pstart[1] = pend[1];
01665 }
01666 pstart[2] = pend[2];
01667 }
01668 }
01669 UTstackFree(wdata);
01670
01671 if (visible < 1)
01672 {
01673 result += (1-visible)*myBorderValue;
01674 }
01675
01676 return result;
01677 }
01678
01679 template <typename T>
01680 void
01681 UT_VoxelArray<T>::resample(const UT_VoxelArray<T> &src,
01682 UT_FilterType filtertype)
01683 {
01684 fpreal radius;
01685 UT_Filter *filter;
01686 UT_Vector3 pos;
01687
01688 filter = UT_Filter::getFilter(filtertype);
01689
01690 radius = SYSmax( getXRes() / (fpreal)src.getXRes(),
01691 getYRes() / (fpreal)src.getYRes(),
01692 getZRes() / (fpreal)src.getZRes(),
01693 1.0f );
01694 radius *= 0.5;
01695
01696 resamplethread(src, filter, radius);
01697
01698 UT_Filter::releaseFilter(filter);
01699 }
01700
01701 template <typename T>
01702 void
01703 UT_VoxelArray<T>::resamplethreadPartial(const UT_VoxelArray<T> &src,
01704 const UT_Filter *filter, float radius,
01705 const UT_JobInfo &info)
01706 {
01707 UT_VoxelArrayIterator<T> vit;
01708 UT_Vector3 pos;
01709 UT_Vector3 ratio;
01710
01711 vit.setArray(this);
01712 vit.setPartialRange(info.job(), info.numJobs());
01713 vit.setCompressOnExit(true);
01714
01715 ratio.x() = 1.0f / getXRes();
01716 ratio.y() = 1.0f / getYRes();
01717 ratio.z() = 1.0f / getZRes();
01718
01719 for (vit.rewind(); !vit.atEnd(); vit.advance())
01720 {
01721 pos.x() = vit.x()+0.5f;
01722 pos.y() = vit.y()+0.5f;
01723 pos.z() = vit.z()+0.5f;
01724 pos *= ratio;
01725
01726 vit.setValue(src.evaluate(pos, *filter, radius));
01727 }
01728 }
01729
01730 template <typename T>
01731 bool
01732 UT_VoxelArray<T>::posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
01733 {
01734
01735
01736 pos.x() *= myRes[0];
01737 pos.y() *= myRes[1];
01738 pos.z() *= myRes[2];
01739
01740
01741
01742
01743 x = (int) SYSfloor(pos.x());
01744 y = (int) SYSfloor(pos.y());
01745 z = (int) SYSfloor(pos.z());
01746
01747
01748 return isValidIndex(x, y, z);
01749 }
01750
01751 template <typename T>
01752 bool
01753 UT_VoxelArray<T>::posToIndex(UT_Vector3 pos, UT_Vector3 &ipos) const
01754 {
01755
01756
01757 pos.x() *= myRes[0];
01758 pos.y() *= myRes[1];
01759 pos.z() *= myRes[2];
01760
01761
01762
01763 pos.x() -= 0.5;
01764 pos.y() -= 0.5;
01765 pos.z() -= 0.5;
01766
01767 ipos = pos;
01768
01769
01770 if (pos.x() < 0 || pos.x() >= myRes[0] ||
01771 pos.y() < 0 || pos.y() >= myRes[1] ||
01772 pos.z() < 0 || pos.z() >= myRes[2])
01773 return false;
01774
01775 return true;
01776 }
01777
01778 template <typename T>
01779 bool
01780 UT_VoxelArray<T>::indexToPos(int x, int y, int z, UT_Vector3 &pos) const
01781 {
01782 pos.x() = x;
01783 pos.y() = y;
01784 pos.z() = z;
01785
01786
01787 pos.x() += 0.5;
01788 pos.y() += 0.5;
01789 pos.z() += 0.5;
01790
01791
01792 if (myRes[0])
01793 pos.x() /= (fpreal) myRes[0];
01794 if (myRes[1])
01795 pos.y() /= (fpreal) myRes[1];
01796 if (myRes[2])
01797 pos.z() /= (fpreal) myRes[2];
01798
01799
01800 return isValidIndex(x, y, z);
01801 }
01802
01803 template <typename T>
01804 void
01805 UT_VoxelArray<T>::setBorder(UT_VoxelBorderType type, T t)
01806 {
01807 myBorderType = type;
01808 myBorderValue = t;
01809 }
01810
01811 template <typename T>
01812 void
01813 UT_VoxelArray<T>::collapseAllTiles()
01814 {
01815 int i, ntiles;
01816
01817 ntiles = numTiles();
01818 for (i = 0; i < ntiles; i++)
01819 {
01820 myTiles[i]->tryCompress(getCompressionTolerance());
01821 }
01822 }
01823
01824 template <typename T>
01825 void
01826 UT_VoxelArray<T>::expandAllTiles()
01827 {
01828 int i, ntiles;
01829
01830 ntiles = numTiles();
01831 for (i = 0; i < ntiles; i++)
01832 {
01833 myTiles[i]->uncompress();
01834 }
01835 }
01836
01837 template <typename T>
01838 void
01839 UT_VoxelArray<T>::saveData(ostream &os)
01840 {
01841 T cval;
01842 char version;
01843
01844
01845 if (isConstant(&cval))
01846 {
01847
01848 version = 0;
01849 UTwrite(os, &version, 1);
01850 UTwrite(os, &cval);
01851 return;
01852 }
01853
01854
01855 version = 1;
01856 UTwrite(os, &version, 1);
01857
01858
01859 UT_VoxelTile<T>::saveCompressionTypes(os);
01860
01861 int i, ntiles;
01862
01863 ntiles = numTiles();
01864 for (i = 0; i < ntiles; i++)
01865 {
01866 myTiles[i]->save(os);
01867 }
01868 }
01869
01870
01871 template <typename T>
01872 void
01873 UT_VoxelArray<T>::loadData(UT_IStream &is)
01874 {
01875 T cval;
01876 char version;
01877
01878 is.readChar(version);
01879
01880
01881 if (version == 0)
01882 {
01883
01884 is.read(&cval);
01885
01886 constant(cval);
01887 return;
01888 }
01889
01890 if (version == 1)
01891 {
01892 UT_IntArray compressions;
01893
01894
01895 UT_VoxelTile<T>::loadCompressionTypes(is, compressions);
01896
01897 int i, ntiles;
01898
01899 ntiles = numTiles();
01900 for (i = 0; i < ntiles; i++)
01901 {
01902 myTiles[i]->load(is, compressions);
01903 }
01904 }
01905 }
01906
01907
01908
01909
01910
01911
01912 template <typename T>
01913 UT_VoxelMipMap<T>::UT_VoxelMipMap()
01914 {
01915 initializePrivate();
01916 }
01917
01918 template <typename T>
01919 UT_VoxelMipMap<T>::~UT_VoxelMipMap()
01920 {
01921 destroyPrivate();
01922 }
01923
01924 template <typename T>
01925 UT_VoxelMipMap<T>::UT_VoxelMipMap(const UT_VoxelMipMap<T> &src)
01926 {
01927 initializePrivate();
01928
01929 *this = src;
01930 }
01931
01932 template <typename T>
01933 const UT_VoxelMipMap<T> &
01934 UT_VoxelMipMap<T>::operator=(const UT_VoxelMipMap<T> &src)
01935 {
01936 UT_VoxelArray<T> *levels;
01937 int level, i;
01938
01939 if (&src == this)
01940 return;
01941
01942 destroyPrivate();
01943
01944
01945
01946 myOwnBase = true;
01947 myBaseLevel = new UT_VoxelArray<T>;
01948 *myBaseLevel = *src.myBaseLevel;
01949
01950 myNumLevels = src.myNumLevels;
01951
01952 for (i = 0; i < src.myLevels.entries(); i++)
01953 {
01954 levels = new UT_VoxelArray<T> *[myNumLevels];
01955 myLevels.append(levels);
01956
01957 for (level = 0; level < myNumLevels; level++)
01958 {
01959 levels[level] = new UT_VoxelArray<T>;
01960 *levels[level] = *src.myLevels[i][level];
01961 }
01962 }
01963 }
01964
01965 template <typename T>
01966 void
01967 UT_VoxelMipMap<T>::build(UT_VoxelArray<T> *baselevel,
01968 mipmaptype function)
01969 {
01970 UT_RefArray<mipmaptype> functions;
01971
01972 functions.append(function);
01973 build(baselevel, functions);
01974 }
01975
01976 template <typename T>
01977 void
01978 UT_VoxelMipMap<T>::build(UT_VoxelArray<T> *baselevel,
01979 const UT_RefArray<mipmaptype> &functions)
01980 {
01981 destroyPrivate();
01982
01983
01984 myBaseLevel = baselevel;
01985 myOwnBase = false;
01986
01987
01988
01989 myNumLevels = 0;
01990 int maxres, level;
01991
01992 maxres = SYSmax(myBaseLevel->getXRes(), myBaseLevel->getYRes());
01993 maxres = SYSmax(maxres, myBaseLevel->getZRes());
01994
01995
01996
01997 while (maxres > 1)
01998 {
01999 myNumLevels++;
02000 maxres++;
02001 maxres >>= 1;
02002 }
02003
02004
02005
02006 int x, y, z, ix, iy, iz;
02007 int xres, yres, zres;
02008 UT_VoxelArray<T> *lastlevel;
02009 UT_VoxelArray<T> **levels;
02010 T x1, x2, y1, y2, z1, z2;
02011 mipmaptype function;
02012
02013
02014 for (int i = 0; i < functions.entries(); i++)
02015 {
02016 function = functions(i);
02017
02018 levels = new UT_VoxelArray<T> *[myNumLevels];
02019 myLevels.append(levels);
02020
02021 lastlevel = myBaseLevel;
02022 for (level = myNumLevels-1; level >= 0; level--)
02023 {
02024
02025 xres = (lastlevel->getXRes() + 1) >> 1;
02026 yres = (lastlevel->getYRes() + 1) >> 1;
02027 zres = (lastlevel->getZRes() + 1) >> 1;
02028
02029 levels[level] = new UT_VoxelArray<T>;
02030 levels[level]->size(xres, yres, zres);
02031
02032 iz = 1;
02033 for (z = 0; z < zres; z++)
02034 {
02035 if (z == zres-1)
02036 {
02037 if (2*z + 1 >= lastlevel->getZRes())
02038 iz = 0;
02039 }
02040 iy = 1;
02041 for (y = 0; y < yres; y++)
02042 {
02043 if (y == yres-1)
02044 {
02045 if (2*y + 1 >= lastlevel->getYRes())
02046 iy = 0;
02047 }
02048 ix = 1;
02049 for (x = 0; x < xres; x++)
02050 {
02051 if (x == xres-1)
02052 {
02053 if (2*x + 1 >= lastlevel->getXRes())
02054 ix = 0;
02055 }
02056 x1 = (*lastlevel)(2*x, 2*y, 2*z);
02057 x2 = (*lastlevel)(2*x+ix, 2*y, 2*z);
02058 y1 = mixValues(x1, x2, function);
02059
02060 x1 = (*lastlevel)(2*x, 2*y+iy, 2*z);
02061 x2 = (*lastlevel)(2*x+ix, 2*y+iy, 2*z);
02062 y2 = mixValues(x1, x2, function);
02063
02064 z1 = mixValues(y1, y2, function);
02065
02066 x1 = (*lastlevel)(2*x, 2*y, 2*z+iz);
02067 x2 = (*lastlevel)(2*x+ix, 2*y, 2*z+iz);
02068 y1 = mixValues(x1, x2, function);
02069
02070 x1 = (*lastlevel)(2*x, 2*y+iy, 2*z+iz);
02071 x2 = (*lastlevel)(2*x+ix, 2*y+iy, 2*z+iz);
02072 y2 = mixValues(x1, x2, function);
02073
02074 z2 = mixValues(y1, y2, function);
02075
02076 levels[level]->setValue(x, y, z,
02077 mixValues(z1, z2, function));
02078 }
02079 }
02080 }
02081
02082 lastlevel = levels[level];
02083 }
02084 }
02085 }
02086
02087 template <typename T>
02088 T
02089 UT_VoxelMipMap<T>::mixValues(T t1, T t2, mipmaptype function) const
02090 {
02091 switch (function)
02092 {
02093 case MIPMAP_MAXIMUM:
02094 return SYSmax(t1, t2);
02095
02096 case MIPMAP_AVERAGE:
02097 return (t1 + t2) / 2;
02098
02099 case MIPMAP_MINIMUM:
02100 return SYSmin(t1, t2);
02101 }
02102
02103 return t1;
02104 }
02105
02106 template <typename T>
02107 int64
02108 UT_VoxelMipMap<T>::getMemoryUsage() const
02109 {
02110 int64 totalarraysize = 0;
02111
02112 for (int j = 0; j < myLevels.entries(); j++)
02113 {
02114 for( int i = 0; i < myNumLevels; i++ )
02115 totalarraysize += myLevels[j][i]->getMemoryUsage();
02116 }
02117
02118 return sizeof(*this) + totalarraysize;
02119 }
02120
02121 template <typename T>
02122 void
02123 UT_VoxelMipMap<T>::traverseTopDown(bool (*function)(const UT_RefArray<T> &,
02124 const UT_BoundingBox &,
02125 bool, void *),
02126 void *data) const
02127 {
02128 doTraverse(0, 0, 0, 0, function, data);
02129 }
02130
02131 template <typename T>
02132 void
02133 UT_VoxelMipMap<T>::doTraverse(int x, int y, int z, int level,
02134 bool (*function)(const UT_RefArray<T> &,
02135 const UT_BoundingBox &,
02136 bool, void *),
02137 void *data) const
02138 {
02139 UT_RefArray<T> tval;
02140 bool isfinal;
02141 UT_VoxelArray<T> *vox;
02142 int shift;
02143 int i;
02144
02145 if (level == myNumLevels)
02146 {
02147 isfinal = true;
02148 vox = myBaseLevel;
02149 tval.append((*vox)(x, y, z));
02150 for (i = 1; i < myLevels.entries(); i++)
02151 tval.append(tval(0));
02152 }
02153 else
02154 {
02155 isfinal = false;
02156 for (i = 0; i < myLevels.entries(); i++)
02157 {
02158 vox = myLevels[i][level];
02159 tval.append((*vox)(x, y, z));
02160 }
02161 }
02162
02163 shift = myNumLevels - level;
02164
02165 UT_BoundingBox box;
02166
02167 box.initBounds(SYSmin(x << shift, myBaseLevel->getXRes()),
02168 SYSmin(y << shift, myBaseLevel->getYRes()),
02169 SYSmin(z << shift, myBaseLevel->getZRes()));
02170 box.enlargeBounds(SYSmin((x+1) << shift, myBaseLevel->getXRes()),
02171 SYSmin((y+1) << shift, myBaseLevel->getYRes()),
02172 SYSmin((z+1) << shift, myBaseLevel->getZRes()));
02173
02174 if (!function(tval, box, isfinal, data))
02175 {
02176
02177
02178 return;
02179 }
02180
02181
02182 if (isfinal)
02183 return;
02184
02185 level++;
02186 shift--;
02187 x <<= 1;
02188 y <<= 1;
02189 z <<= 1;
02190
02191 bool xinc, yinc, zinc;
02192
02193
02194 if ( ((x+1) << shift) < myBaseLevel->getXRes() )
02195 xinc = true;
02196 else
02197 xinc = false;
02198 if ( ((y+1) << shift) < myBaseLevel->getYRes() )
02199 yinc = true;
02200 else
02201 yinc = false;
02202 if ( ((z+1) << shift) < myBaseLevel->getZRes() )
02203 zinc = true;
02204 else
02205 zinc = false;
02206
02207
02208 doTraverse(x, y, z, level, function, data);
02209
02210 if (xinc)
02211 {
02212 doTraverse(x+1, y, z, level, function, data);
02213 if (yinc)
02214 {
02215 doTraverse(x+1, y+1, z, level, function, data);
02216 if (zinc)
02217 doTraverse(x+1, y+1, z+1, level, function, data);
02218 }
02219 if (zinc)
02220 {
02221 doTraverse(x+1, y, z+1, level, function, data);
02222 }
02223 }
02224 if (yinc)
02225 {
02226 doTraverse(x, y+1, z, level, function, data);
02227 if (zinc)
02228 doTraverse(x, y+1, z+1, level, function, data);
02229 }
02230 if (zinc)
02231 doTraverse(x, y, z+1, level, function, data);
02232 }
02233
02234 template <typename T>
02235 void
02236 UT_VoxelMipMap<T>::initializePrivate()
02237 {
02238 myNumLevels = 0;
02239 myBaseLevel = 0;
02240 myOwnBase = false;
02241 }
02242
02243 template <typename T>
02244 void
02245 UT_VoxelMipMap<T>::destroyPrivate()
02246 {
02247 int level, i;
02248
02249 for (i = 0; i < myLevels.entries(); i++)
02250 {
02251 for (level = 0; level < myNumLevels; level++)
02252 delete myLevels[i][level];
02253 delete [] myLevels[i];
02254 }
02255 myLevels.entries(0);
02256
02257 if (myOwnBase)
02258 delete myBaseLevel;
02259
02260 initializePrivate();
02261 }
02262
02263 template <typename T>
02264 UT_VoxelArrayIterator<T>::UT_VoxelArrayIterator()
02265 {
02266 myArray = 0;
02267 myHandle.resetHandle();
02268 myCurTile = -1;
02269 myShouldCompressOnExit = false;
02270 myUseTileList = false;
02271 }
02272
02273 template <typename T>
02274 UT_VoxelArrayIterator<T>::UT_VoxelArrayIterator(UT_VoxelArray<T> *vox)
02275 {
02276 myShouldCompressOnExit = false;
02277 myUseTileList = false;
02278 setArray(vox);
02279 }
02280
02281 template <typename T>
02282 UT_VoxelArrayIterator<T>::UT_VoxelArrayIterator(UT_COWReadHandle<UT_VoxelArray<T> > handle)
02283 {
02284 myShouldCompressOnExit = false;
02285 myUseTileList = false;
02286 setHandle(handle);
02287 }
02288
02289 template <typename T>
02290 UT_VoxelArrayIterator<T>::~UT_VoxelArrayIterator()
02291 {
02292 }
02293
02294 template <typename T>
02295 void
02296 UT_VoxelArrayIterator<T>::setPartialRange(int idx, int numranges)
02297 {
02298 int numtiles;
02299 fpreal tileperrange;
02300
02301
02302 UT_ASSERT(myArray);
02303 if (!myArray)
02304 return;
02305
02306
02307 numtiles = myArray->numTiles();
02308
02309
02310 if (myUseTileList)
02311 numtiles = myTileList.entries();
02312
02313
02314 if (!numtiles)
02315 {
02316 myTileStart = 0;
02317 myTileEnd = 0;
02318 return;
02319 }
02320
02321
02322 if (idx < 0 || idx >= numranges)
02323 {
02324 UT_ASSERT(!"Idx out of bounds");
02325 myTileStart = -1;
02326 myTileEnd = -1;
02327 return;
02328 }
02329
02330
02331 if (numranges < 1)
02332 {
02333 UT_ASSERT(!"Invalid range count!");
02334 numranges = 1;
02335 }
02336
02337
02338
02339
02340
02341 tileperrange = (fpreal)numtiles / (fpreal)numranges;
02342
02343 myTileStart = (int) SYSfloor(idx * tileperrange);
02344 myTileEnd = (int) SYSfloor((idx+1) * tileperrange);
02345
02346
02347
02348 if (idx == numranges-1)
02349 myTileEnd = numtiles;
02350
02351 UT_ASSERT(myTileStart >= 0);
02352 UT_ASSERT(myTileEnd <= numtiles);
02353 }
02354
02355 template <typename T>
02356 void
02357 UT_VoxelArrayIterator<T>::restrictToBBox(const UT_BoundingBox &bbox)
02358 {
02359 UT_Vector3 pmin, pmax, vmin, vmax;
02360
02361 pmin = bbox.minvec();
02362 pmax = bbox.maxvec();
02363
02364 pmin.x() = SYSmax(pmin.x(), 0.0f);
02365 pmin.y() = SYSmax(pmin.y(), 0.0f);
02366 pmin.z() = SYSmax(pmin.z(), 0.0f);
02367 pmax.x() = SYSmin(pmax.x(), 1.0f);
02368 pmax.y() = SYSmin(pmax.y(), 1.0f);
02369 pmax.z() = SYSmin(pmax.z(), 1.0f);
02370
02371 myArray->posToIndex(pmin, vmin);
02372 myArray->posToIndex(pmax, vmax);
02373
02374 restrictToBBox(SYSfloor(vmin.x()), SYSceil(vmax.x()),
02375 SYSfloor(vmin.y()), SYSceil(vmax.y()),
02376 SYSfloor(vmin.z()), SYSceil(vmax.z()));
02377 }
02378
02379 template <typename T>
02380 void
02381 UT_VoxelArrayIterator<T>::restrictToBBox(int xmin, int xmax,
02382 int ymin, int ymax,
02383 int zmin, int zmax)
02384 {
02385 int xres, yres, zres, x, y, z;
02386
02387 xres = myArray->getXRes();
02388 yres = myArray->getYRes();
02389 zres = myArray->getZRes();
02390
02391 myTileList.entries(0);
02392 myUseTileList = true;
02393
02394 if (xmin < xres && xmax >= 0 &&
02395 ymin < yres && ymax >= 0 &&
02396 zmin < zres && zmax >= 0)
02397 {
02398
02399 myArray->clampIndex(xmin, ymin, zmin);
02400 myArray->clampIndex(xmax, ymax, zmax);
02401
02402
02403 xmin >>= TILEBITS;
02404 ymin >>= TILEBITS;
02405 zmin >>= TILEBITS;
02406 xmax >>= TILEBITS;
02407 ymax >>= TILEBITS;
02408 zmax >>= TILEBITS;
02409
02410
02411 if (myArray->numTiles() == (xmax-xmin+1)*(ymax-ymin+1)*(zmax-zmin+1))
02412 {
02413 UT_ASSERT(xmin == 0 && ymin == 0 && zmin == 0);
02414
02415 myUseTileList = false;
02416 }
02417 else
02418 {
02419
02420 for (z = zmin; z <= zmax; z++)
02421 {
02422 for (y = ymin; y <= ymax; y++)
02423 {
02424 for (x = xmin; x <= xmax; x++)
02425 {
02426 myTileList.append(myArray->xyzTileToLinear(x, y, z));
02427 }
02428 }
02429 }
02430 }
02431 }
02432
02433
02434 myCurTile = -1;
02435 setPartialRange(0, 1);
02436 }
02437
02438
02439 template <typename T>
02440 void
02441 UT_VoxelArrayIterator<T>::rewind()
02442 {
02443
02444 if (!myArray ||
02445 !myArray->getRes(0) || !myArray->getRes(1) || !myArray->getRes(2))
02446 {
02447 myCurTile = -1;
02448 return;
02449 }
02450
02451 if (myUseTileList)
02452 {
02453 myCurTileListIdx = myTileStart;
02454 if (myCurTileListIdx < 0 || myCurTileListIdx >= myTileEnd)
02455 {
02456 myCurTile = -1;
02457 return;
02458 }
02459 myCurTile = myTileList(myCurTileListIdx);
02460 }
02461 else
02462 {
02463 myCurTile = myTileStart;
02464
02465 if (myCurTile < 0 || myCurTile >= myTileEnd)
02466 {
02467 myCurTile = -1;
02468 return;
02469 }
02470 }
02471
02472 UT_VoxelTile<T> *tile;
02473
02474 tile = myArray->getLinearTile(myCurTile);
02475
02476
02477 if (myCurTile)
02478 {
02479 myArray->linearTileToXYZ(myCurTile,
02480 myTilePos[0], myTilePos[1], myTilePos[2]);
02481 myPos[0] = TILESIZE * myTilePos[0];
02482 myPos[1] = TILESIZE * myTilePos[1];
02483 myPos[2] = TILESIZE * myTilePos[2];
02484 }
02485 else
02486 {
02487 myTilePos[0] = 0;
02488 myTilePos[1] = 0;
02489 myTilePos[2] = 0;
02490 myPos[0] = 0;
02491 myPos[1] = 0;
02492 myPos[2] = 0;
02493 }
02494
02495 myTileLocalPos[0] = 0;
02496 myTileLocalPos[1] = 0;
02497 myTileLocalPos[2] = 0;
02498
02499 myTileSize[0] = tile->xres();
02500 myTileSize[1] = tile->yres();
02501 myTileSize[2] = tile->zres();
02502 }
02503
02504 template <typename T>
02505 void
02506 UT_VoxelArrayIterator<T>::advanceTile()
02507 {
02508 if (myUseTileList)
02509 {
02510 if (getCompressOnExit())
02511 {
02512
02513 if (myCurTile >= 0 && myCurTileListIdx < myTileEnd)
02514 {
02515 myArray->getLinearTile(myCurTile)->tryCompress(myArray->getCompressionTolerance());
02516 }
02517 }
02518
02519
02520 myCurTileListIdx++;
02521 if (myCurTileListIdx >= myTileEnd)
02522 {
02523 myCurTile = -1;
02524 return;
02525 }
02526
02527 myCurTile = myTileList(myCurTileListIdx);
02528
02529 myArray->linearTileToXYZ(myCurTile,
02530 myTilePos[0], myTilePos[1], myTilePos[2]);
02531
02532 UT_VoxelTile<T> *tile;
02533
02534 tile = myArray->getLinearTile(myCurTile);
02535 myTileLocalPos[0] = 0;
02536 myTileLocalPos[1] = 0;
02537 myTileLocalPos[2] = 0;
02538 myTileSize[0] = tile->xres();
02539 myTileSize[1] = tile->yres();
02540 myTileSize[2] = tile->zres();
02541
02542 myPos[0] = TILESIZE * myTilePos[0];
02543 myPos[1] = TILESIZE * myTilePos[1];
02544 myPos[2] = TILESIZE * myTilePos[2];
02545 return;
02546 }
02547
02548
02549 if (getCompressOnExit())
02550 {
02551
02552 if (myCurTile >= 0 && myCurTile < myTileEnd)
02553 {
02554 myArray->getLinearTile(myCurTile)->tryCompress(myArray->getCompressionTolerance());
02555 }
02556 }
02557
02558
02559 myTilePos[0]++;
02560 if (myTilePos[0] >= myArray->getTileRes(0))
02561 {
02562 myTilePos[0] = 0;
02563 myTilePos[1]++;
02564 if (myTilePos[1] >= myArray->getTileRes(1))
02565 {
02566 myTilePos[1] = 0;
02567 myTilePos[2]++;
02568 if (myTilePos[2] >= myArray->getTileRes(2))
02569 {
02570
02571 myCurTile = -1;
02572 return;
02573 }
02574 }
02575 }
02576
02577 UT_VoxelTile<T> *tile;
02578
02579
02580 myCurTile = myArray->xyzTileToLinear(myTilePos[0], myTilePos[1], myTilePos[2]);
02581
02582
02583 if (myCurTile >= myTileEnd)
02584 {
02585 myCurTile = -1;
02586 return;
02587 }
02588
02589 tile = myArray->getLinearTile(myCurTile);
02590 myTileLocalPos[0] = 0;
02591 myTileLocalPos[1] = 0;
02592 myTileLocalPos[2] = 0;
02593 myTileSize[0] = tile->xres();
02594 myTileSize[1] = tile->yres();
02595 myTileSize[2] = tile->zres();
02596
02597 myPos[0] = TILESIZE * myTilePos[0];
02598 myPos[1] = TILESIZE * myTilePos[1];
02599 myPos[2] = TILESIZE * myTilePos[2];
02600 }
02601
02602
02603
02604
02605
02606 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02607 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::UT_VoxelProbe()
02608 {
02609 myCurLine = 0;
02610 myAllocCacheLine = 0;
02611 myDirty = false;
02612 }
02613
02614 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02615 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::UT_VoxelProbe(UT_VoxelArray<T> *vox, int prex, int postx)
02616 {
02617
02618 myCurLine = 0;
02619 myAllocCacheLine = 0;
02620 myDirty = false;
02621
02622 setArray(vox, prex, postx);
02623 }
02624
02625 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02626 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::~UT_VoxelProbe()
02627 {
02628 if (DoWrite)
02629 {
02630 if (!TestForWrites || myDirty)
02631 {
02632
02633 writeCacheLine();
02634 }
02635 }
02636 delete [] myAllocCacheLine;
02637 }
02638
02639 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02640 void
02641 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::setArray(UT_VoxelArray<T> *vox, int prex, int postx)
02642 {
02643
02644 int prepad, postpad;
02645
02646 myCurLine = 0;
02647
02648 prepad = (prex - 3) / 4;
02649 postpad = (postx + 3) / 4;
02650
02651 myAllocCacheLine = new T [TILESIZE - prepad*4 + postpad*4];
02652 myCacheLine = &myAllocCacheLine[-prepad];
02653
02654 myPreX = prex;
02655 myPostX = postx;
02656
02657 myForceCopy = false;
02658 if (myPreX || myPostX)
02659 myForceCopy = true;
02660
02661 if (DoWrite)
02662 myForceCopy = true;
02663 myDirty = false;
02664
02665 myArray = vox;
02666 }
02667
02668 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02669 bool
02670 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::setIndex(int x, int y, int z)
02671 {
02672
02673 if (myCurLine && y == myY && z == myZ)
02674 {
02675 if (x < myMaxValidX)
02676 {
02677 if (x == myX+1)
02678 {
02679
02680 advanceX();
02681 return false;
02682 }
02683
02684 if (x >= myMinValidX)
02685 {
02686
02687 resetX(x);
02688
02689
02690 return true;
02691 }
02692 }
02693 }
02694
02695
02696 if (DoWrite)
02697 {
02698 if (!TestForWrites || myDirty)
02699 writeCacheLine();
02700 }
02701
02702
02703 reloadCache(x, y, z);
02704
02705 if (TestForWrites)
02706 myDirty = false;
02707
02708 return true;
02709 }
02710
02711 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02712 void
02713 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::reloadCache(int x, int y, int z)
02714 {
02715 UT_VoxelTile<T> *tile;
02716 bool xout = false, yout = false, zout = false;
02717
02718 myX = x;
02719 myY = y;
02720 myZ = z;
02721 myMinValidX = x & ~TILEMASK;
02722 myMaxValidX = myMinValidX + TILESIZE;
02723 if (myMaxValidX > myArray->getXRes())
02724 myMaxValidX = myArray->getXRes();
02725
02726 if (x < 0 || x >= myArray->getXRes())
02727 xout = true;
02728 if (y < 0 || y >= myArray->getYRes())
02729 yout = true;
02730 if (z < 0 || z >= myArray->getZRes())
02731 zout = true;
02732
02733
02734 if (yout || zout)
02735 {
02736
02737 switch (myArray->getBorder())
02738 {
02739 case UT_VOXELBORDER_CONSTANT:
02740 buildConstantCache(myArray->getBorderValue());
02741
02742
02743 return;
02744
02745 case UT_VOXELBORDER_REPEAT:
02746
02747 if (yout)
02748 {
02749 y %= myArray->getYRes();
02750 if (y < 0)
02751 y += myArray->getYRes();
02752 }
02753 if (zout)
02754 {
02755 z %= myArray->getZRes();
02756 if (z < 0)
02757 z += myArray->getZRes();
02758 }
02759 break;
02760
02761 case UT_VOXELBORDER_STREAK:
02762 {
02763
02764 int tx = 0;
02765 myArray->clampIndex(tx, y, z);
02766 break;
02767 }
02768 }
02769 }
02770
02771
02772
02773
02774
02775 if (xout)
02776 {
02777
02778 if (!myPreX && !myPostX)
02779 {
02780 buildConstantCache(myArray->getValue(x, y, z));
02781
02782
02783 return;
02784 }
02785 else
02786 {
02787
02788
02789
02790
02791 if (myArray->getBorder() == UT_VOXELBORDER_REPEAT)
02792 {
02793 x %= myArray->getXRes();
02794 if (x < 0)
02795 x += myArray->getXRes();
02796 }
02797 else
02798 {
02799 int i;
02800
02801 for (i = myPreX; i < 0; i++)
02802 {
02803 myCacheLine[i] = myArray->getValue(myMinValidX+i, y, z);
02804 }
02805
02806 T value = myArray->getValue(x, y, z);
02807 for (; i < TILESIZE; i++)
02808 {
02809 myCacheLine[i] = value;
02810 }
02811
02812 for (; i < TILESIZE + myPostX; i++)
02813 {
02814 myCacheLine[i] = myArray->getValue(myMaxValidX+i, y, z);
02815 }
02816
02817 myCurLine = &myCacheLine[x & TILEMASK];
02818 myStride = 1;
02819
02820
02821 return;
02822 }
02823 }
02824 }
02825
02826 int xtile, ytile, ztile, tileidx;
02827 int lx, ly, lz;
02828 int i;
02829
02830 xtile = x >> TILEBITS;
02831 ytile = y >> TILEBITS;
02832 ztile = z >> TILEBITS;
02833
02834
02835 lx = x & TILEMASK;
02836 ly = y & TILEMASK;
02837 lz = z & TILEMASK;
02838
02839 tileidx = (ztile * myArray->getTileRes(1) + ytile) * myArray->getTileRes(0);
02840
02841 if (myPreX)
02842 {
02843 if (xtile)
02844 {
02845
02846 tile = myArray->getLinearTile(tileidx+xtile-1);
02847 for (i = myPreX; i < 0; i++)
02848 {
02849
02850
02851 myCacheLine[i] = (*tile)(i & TILEMASK, ly, lz);
02852 }
02853 }
02854 else
02855 {
02856 if (myArray->getBorder() == UT_VOXELBORDER_REPEAT)
02857 {
02858 int resx = myArray->getXRes();
02859 int xpos;
02860
02861 xpos = myPreX;
02862 xpos %= resx;
02863
02864 xpos += resx;
02865
02866
02867 for (i = myPreX; i < 0; i++)
02868 {
02869 myCacheLine[i] = (*myArray)(xpos, ly, lz);
02870 xpos++;
02871 if (xpos > resx)
02872 xpos -= resx;
02873 }
02874 }
02875 else
02876 {
02877 T value;
02878
02879 if (myArray->getBorder() == UT_VOXELBORDER_STREAK)
02880 {
02881 tile = myArray->getLinearTile(tileidx+xtile);
02882 value = (*tile)(0, ly, lz);
02883 }
02884 else
02885 value = myArray->getBorderValue();
02886
02887
02888 for (i = myPreX; i < 0; i++)
02889 myCacheLine[i] = value;
02890 }
02891 }
02892 }
02893
02894 if (myPostX)
02895 {
02896 int cachelen;
02897 int resx = myArray->getXRes();
02898
02899
02900 cachelen = myMaxValidX - myMinValidX;
02901
02902
02903
02904 if (myMaxValidX + myPostX > myArray->getXRes())
02905 {
02906
02907
02908
02909
02910
02911 int xpos = myMaxValidX;
02912
02913
02914 i = 0;
02915 if (xpos < resx)
02916 {
02917 tile = myArray->getLinearTile(tileidx+xtile+1);
02918 for (; i < myPostX && xpos < resx; i++)
02919 {
02920 myCacheLine[i + cachelen] = (*tile)(i, ly, lz);
02921 xpos++;
02922 }
02923 }
02924
02925 if (i < myPostX)
02926 {
02927 if (myArray->getBorder() == UT_VOXELBORDER_REPEAT)
02928 {
02929 xpos = xpos % resx;
02930
02931
02932 for (; i < myPostX; i++)
02933 {
02934 myCacheLine[i + cachelen] = (*myArray)(xpos, y, z);
02935 xpos++;
02936 if (xpos > resx)
02937 xpos -= resx;
02938 }
02939 }
02940 else
02941 {
02942 T value;
02943
02944 if (myArray->getBorder() == UT_VOXELBORDER_STREAK)
02945 {
02946 tile = myArray->getLinearTile(tileidx+xtile);
02947 value = (*tile)(tile->xres()-1, ly, lz);
02948 }
02949 else
02950 value = myArray->getBorderValue();
02951
02952 for (; i < myPostX; i++)
02953 myCacheLine[i + cachelen] = value;
02954 }
02955 }
02956 }
02957 else
02958 {
02959
02960 tile = myArray->getLinearTile(tileidx+xtile+1);
02961 for (i = 0; i < myPostX; i++)
02962 {
02963
02964
02965 myCacheLine[i + cachelen] = (*tile)(i, ly, lz);
02966 }
02967 }
02968
02969 }
02970
02971 tile = myArray->getLinearTile(tileidx+xtile);
02972 myCurLine = tile->fillCacheLine(myCacheLine, myStride, lx, ly, lz, myForceCopy, DoWrite);
02973 }
02974
02975 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
02976 void
02977 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::buildConstantCache(T value)
02978 {
02979 if (DoWrite)
02980 {
02981
02982 myStride = 1;
02983
02984 int i;
02985
02986 for (i = myPreX; i < TILESIZE+myPostX; i++)
02987 myCacheLine[i] = value;
02988 myCurLine = myCacheLine;
02989 }
02990 else
02991 {
02992 myCacheLine[0] = value;
02993
02994 myCacheLine[1] = value;
02995 myCacheLine[2] = value;
02996 myCacheLine[3] = value;
02997
02998 myCurLine = myCacheLine;
02999 myStride = 0;
03000 }
03001 }
03002
03003 template <typename T, bool DoRead, bool DoWrite, bool TestForWrites>
03004 void
03005 UT_VoxelProbe<T, DoRead, DoWrite, TestForWrites>::writeCacheLine()
03006 {
03007 if (!DoWrite)
03008 {
03009 UT_ASSERT(0);
03010 return;
03011 }
03012
03013
03014 if (!myCurLine)
03015 return;
03016
03017
03018 myCurLine -= myX - myMinValidX;
03019
03020
03021
03022 if (myCurLine != myCacheLine)
03023 return;
03024
03025
03026 int xtile, ytile, ztile, y, z;
03027 UT_VoxelTile<T> *tile;
03028
03029 xtile = myMinValidX >> TILEBITS;
03030 ytile = myY >> TILEBITS;
03031 ztile = myZ >> TILEBITS;
03032 y = myY & TILEMASK;
03033 z = myZ & TILEMASK;
03034
03035 tile = myArray->getTile(xtile, ytile, ztile);
03036
03037
03038 tile->writeCacheLine(myCurLine, y, z);
03039 }
03040
03041
03042
03043
03044 template <typename T>
03045 UT_VoxelProbeCube<T>::UT_VoxelProbeCube()
03046 {
03047 myValid = false;
03048 }
03049
03050 template <typename T>
03051 UT_VoxelProbeCube<T>::~UT_VoxelProbeCube()
03052 {
03053 }
03054
03055 template <typename T>
03056 void
03057 UT_VoxelProbeCube<T>::setCubeArray(UT_VoxelArray<T> *vox)
03058 {
03059 myLines[0][0].setArray(vox, -1, 1);
03060 myLines[0][1].setArray(vox, -1, 1);
03061 myLines[0][2].setArray(vox, -1, 1);
03062
03063 myLines[1][0].setArray(vox, -1, 1);
03064 myLines[1][1].setArray(vox, -1, 1);
03065 myLines[1][2].setArray(vox, -1, 1);
03066
03067 myLines[2][0].setArray(vox, -1, 1);
03068 myLines[2][1].setArray(vox, -1, 1);
03069 myLines[2][2].setArray(vox, -1, 1);
03070
03071 myValid = false;
03072 }
03073
03074 template <typename T>
03075 void
03076 UT_VoxelProbeCube<T>::setPlusArray(UT_VoxelArray<T> *vox)
03077 {
03078
03079
03080 myLines[0][1].setArray(vox, -1, 1);
03081
03082 myLines[1][0].setArray(vox, 0, 0);
03083 myLines[1][1].setArray(vox, -1, 1);
03084 myLines[1][2].setArray(vox, 0, 0);
03085
03086 myLines[2][1].setArray(vox, -1, 1);
03087
03088 myValid = false;
03089 }
03090
03091 template <typename T>
03092 bool
03093 UT_VoxelProbeCube<T>::setIndexCube(int x, int y, int z)
03094 {
03095 if (myValid && myZ == z)
03096 {
03097 if (myY == y)
03098 {
03099
03100 if (x < myMaxValidX && x == myX+1)
03101 {
03102
03103 myLines[0][0].advanceX();
03104 myLines[0][1].advanceX();
03105 myLines[0][2].advanceX();
03106
03107 myLines[1][0].advanceX();
03108 myLines[1][1].advanceX();
03109 myLines[1][2].advanceX();
03110
03111 myLines[2][0].advanceX();
03112 myLines[2][1].advanceX();
03113 myLines[2][2].advanceX();
03114
03115
03116 myX = x;
03117
03118 return false;
03119 }
03120 }
03121 #if 1
03122 else if (y == myY+1 && x < myMaxValidX && x >= myMinValidX)
03123 {
03124
03125
03126
03127
03128 rotateLines(myLines[0][0], myLines[1][0], myLines[2][0]);
03129 rotateLines(myLines[0][1], myLines[1][1], myLines[2][1]);
03130 rotateLines(myLines[0][2], myLines[1][2], myLines[2][2]);
03131
03132
03133
03134 myLines[0][0].resetX(x);
03135 myLines[0][1].resetX(x);
03136 myLines[0][2].resetX(x);
03137
03138 myLines[1][0].resetX(x);
03139 myLines[1][1].resetX(x);
03140 myLines[1][2].resetX(x);
03141
03142
03143 myLines[2][0].setIndex(x, y+1, z-1);
03144 myLines[2][1].setIndex(x, y+1, z);
03145 myLines[2][2].setIndex(x, y+1, z+1);
03146
03147
03148 myX = x;
03149 myY = y;
03150
03151 return true;
03152 }
03153 #endif
03154 }
03155
03156
03157 myLines[0][0].setIndex(x, y-1, z-1);
03158 myLines[0][1].setIndex(x, y-1, z);
03159 myLines[0][2].setIndex(x, y-1, z+1);
03160
03161 myLines[1][0].setIndex(x, y, z-1);
03162 myLines[1][1].setIndex(x, y, z);
03163 myLines[1][2].setIndex(x, y, z+1);
03164
03165 myLines[2][0].setIndex(x, y+1, z-1);
03166 myLines[2][1].setIndex(x, y+1, z);
03167 myLines[2][2].setIndex(x, y+1, z+1);
03168
03169
03170 myX = x;
03171 myY = y;
03172 myZ = z;
03173 myValid = true;
03174 myMinValidX = myLines[1][1].myMinValidX;
03175 myMaxValidX = myLines[1][1].myMaxValidX;
03176
03177 return true;
03178 }
03179
03180 template <typename T>
03181 bool
03182 UT_VoxelProbeCube<T>::setIndexPlus(int x, int y, int z)
03183 {
03184 if (myValid && myZ == z)
03185 {
03186 if (myY == y)
03187 {
03188
03189 if (x < myMaxValidX && x == myX+1)
03190 {
03191
03192 myLines[0][1].advanceX();
03193
03194 myLines[1][0].advanceX();
03195 myLines[1][1].advanceX();
03196 myLines[1][2].advanceX();
03197
03198 myLines[2][1].advanceX();
03199
03200
03201 myX = x;
03202
03203 return false;
03204 }
03205 }
03206 else if (y == myY+1 && x < myMaxValidX && x >= myMinValidX)
03207 {
03208
03209
03210
03211
03212 rotateLines(myLines[0][1], myLines[1][1], myLines[2][1]);
03213
03214 myLines[0][1].resetX(x);
03215 myLines[1][1].resetX(x);
03216
03217 myLines[1][0].setIndex(x, y, z-1);
03218 myLines[1][2].setIndex(x, y, z+1);
03219
03220 myLines[2][1].setIndex(x, y+1, z);
03221
03222 myX = x;
03223 myY = y;
03224 return true;
03225 }
03226 }
03227
03228
03229 myLines[0][1].setIndex(x, y-1, z);
03230
03231 myLines[1][0].setIndex(x, y, z-1);
03232 myLines[1][1].setIndex(x, y, z);
03233 myLines[1][2].setIndex(x, y, z+1);
03234
03235 myLines[2][1].setIndex(x, y+1, z);
03236
03237
03238 myX = x;
03239 myY = y;
03240 myZ = z;
03241 myValid = true;
03242 myMinValidX = myLines[1][1].myMinValidX;
03243 myMaxValidX = myLines[1][1].myMaxValidX;
03244
03245 return true;
03246 }
03247
03248 template <typename T>
03249 void
03250 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)
03251 {
03252 T *tmpcache, *tmpalloc;
03253 const T *tmpcur;
03254
03255
03256
03257 tmpcache = ym.myCacheLine;
03258 tmpalloc = ym.myAllocCacheLine;
03259 tmpcur = ym.myCurLine;
03260
03261 ym.myCacheLine = y0.myCacheLine;
03262 ym.myAllocCacheLine = y0.myAllocCacheLine;
03263 ym.myCurLine = y0.myCurLine;
03264 ym.myStride = y0.myStride;
03265 ym.myY++;
03266
03267 y0.myCacheLine = yp.myCacheLine;
03268 y0.myAllocCacheLine = yp.myAllocCacheLine;
03269 y0.myCurLine = yp.myCurLine;
03270 y0.myStride = yp.myStride;
03271 y0.myY++;
03272
03273 yp.myCacheLine = tmpcache;
03274 yp.myAllocCacheLine = tmpalloc;
03275
03276 yp.myCurLine = 0;
03277 }
03278
03279
03280
03281
03282 template <typename T>
03283 UT_VoxelProbeFace<T>::UT_VoxelProbeFace()
03284 {
03285 myValid = false;
03286 }
03287
03288 template <typename T>
03289 UT_VoxelProbeFace<T>::~UT_VoxelProbeFace()
03290 {
03291 }
03292
03293
03294 template <typename T>
03295 void
03296 UT_VoxelProbeFace<T>::setArray(UT_VoxelArray<T> *vx, UT_VoxelArray<T> *vy, UT_VoxelArray<T> *vz)
03297 {
03298
03299 myLines[0][0].setArray(vx, 0, 1);
03300
03301
03302 myLines[1][0].setArray(vy, 0, 0);
03303 myLines[1][1].setArray(vy, 0, 0);
03304
03305 myLines[2][0].setArray(vz, 0, 0);
03306 myLines[2][1].setArray(vz, 0, 0);
03307
03308 myValid = false;
03309 }
03310
03311 template <typename T>
03312 void
03313 UT_VoxelProbeFace<T>::setVoxelSize(const UT_Vector3 &size)
03314 {
03315 myVoxelSize = size;
03316 myInvVoxelSize = 1;
03317 myInvVoxelSize /= myVoxelSize;
03318 }
03319
03320 template <typename T>
03321 bool
03322 UT_VoxelProbeFace<T>::setIndex(int x, int y, int z)
03323 {
03324 if (myValid && myZ == z)
03325 {
03326 if (myY == y)
03327 {
03328
03329 if (x < myMaxValidX && x == myX+1)
03330 {
03331
03332 myLines[0][0].advanceX();
03333
03334 myLines[1][0].advanceX();
03335 myLines[1][1].advanceX();
03336
03337 myLines[2][0].advanceX();
03338 myLines[2][1].advanceX();
03339
03340
03341 myX = x;
03342
03343 return false;
03344 }
03345 }
03346 else if (y == myY+1 && x < myMaxValidX && x >= myMinValidX)
03347 {
03348
03349
03350
03351 swapLines(myLines[1][0], myLines[1][1]);
03352
03353 myLines[1][0].resetX(x);
03354
03355
03356 myLines[0][0].setIndex(x, y, z);
03357 myLines[1][1].setIndex(x, y+1, z);
03358
03359 myLines[2][0].setIndex(x, y, z);
03360 myLines[2][1].setIndex(x, y, z+1);
03361
03362 myX = x;
03363 myY = y;
03364 return true;
03365 }
03366 }
03367
03368
03369 myLines[0][0].setIndex(x, y, z);
03370
03371 myLines[1][0].setIndex(x, y, z);
03372 myLines[1][1].setIndex(x, y+1, z);
03373
03374 myLines[2][0].setIndex(x, y, z);
03375 myLines[2][1].setIndex(x, y, z+1);
03376
03377
03378 myX = x;
03379 myY = y;
03380 myZ = z;
03381 myValid = true;
03382 myMinValidX = myLines[0][0].myMinValidX;
03383 myMaxValidX = myLines[0][0].myMaxValidX;
03384
03385 return true;
03386 }
03387
03388 template <typename T>
03389 void
03390 UT_VoxelProbeFace<T>::swapLines(UT_VoxelProbe<T, true, false, false> &ym,
03391 UT_VoxelProbe<T, true, false, false> &yp)
03392 {
03393 T *tmpcache, *tmpalloc;
03394 const T *tmpcur;
03395
03396
03397
03398 tmpcache = ym.myCacheLine;
03399 tmpalloc = ym.myAllocCacheLine;
03400 tmpcur = ym.myCurLine;
03401
03402 ym.myCacheLine = yp.myCacheLine;
03403 ym.myAllocCacheLine = yp.myAllocCacheLine;
03404 ym.myCurLine = yp.myCurLine;
03405 ym.myStride = yp.myStride;
03406 ym.myY++;
03407
03408 yp.myCacheLine = tmpcache;
03409 yp.myAllocCacheLine = tmpalloc;
03410
03411 yp.myCurLine = 0;
03412 }
03413
03414
03415
03416
03417 template <typename T, int XStep, int YStep, int ZStep>
03418 void
03419 UT_VoxelProbeAverage<T, XStep, YStep, ZStep>::setArray(UT_VoxelArray<T> *vox)
03420 {
03421 int prex = (XStep < 0) ? XStep : 0;
03422 int postx = (XStep > 0) ? XStep : 0;
03423
03424 myLines[0][0].setArray(vox, prex, postx);
03425 if (YStep)
03426 {
03427 myLines[1][0].setArray(vox, prex, postx);
03428 if (ZStep)
03429 {
03430 myLines[1][1].setArray(vox, prex, postx);
03431 }
03432 }
03433 if (ZStep)
03434 myLines[0][1].setArray(vox, prex, postx);
03435 }
03436
03437 template <typename T, int XStep, int YStep, int ZStep>
03438 bool
03439 UT_VoxelProbeAverage<T, XStep, YStep, ZStep>::setIndex(int x, int y, int z)
03440 {
03441 bool result = false;
03442
03443
03444
03445
03446
03447 if (YStep < 0)
03448 y--;
03449 if (ZStep < 0)
03450 z--;
03451
03452 result |= myLines[0][0].setIndex(x, y, z);
03453 if (YStep)
03454 {
03455 result |= myLines[1][0].setIndex(x, y+1, z);
03456 if (ZStep)
03457 result |= myLines[1][1].setIndex(x, y+1, z+1);
03458 }
03459 if (ZStep)
03460 result |= myLines[0][1].setIndex(x, y, z+1);
03461
03462 return result;
03463 }