00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 namespace PolyVox
00025 {
00026 template< template<typename> class VolumeType, typename VoxelType>
00027 SurfaceExtractor<VolumeType, VoxelType>::SurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result)
00028 :m_volData(volData)
00029 ,m_sampVolume(volData)
00030 ,m_meshCurrent(result)
00031 ,m_regSizeInVoxels(region)
00032 {
00033
00034 m_regSizeInCells = m_regSizeInVoxels;
00035 m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1));
00036 }
00037
00038 template< template<typename> class VolumeType, typename VoxelType>
00039 void SurfaceExtractor<VolumeType, VoxelType>::execute()
00040 {
00041 m_meshCurrent->clear();
00042
00043 uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1;
00044 uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1;
00045 uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight};
00046
00047
00048 Array2DInt32 m_pPreviousVertexIndicesX(arraySizes);
00049 Array2DInt32 m_pPreviousVertexIndicesY(arraySizes);
00050 Array2DInt32 m_pPreviousVertexIndicesZ(arraySizes);
00051 Array2DInt32 m_pCurrentVertexIndicesX(arraySizes);
00052 Array2DInt32 m_pCurrentVertexIndicesY(arraySizes);
00053 Array2DInt32 m_pCurrentVertexIndicesZ(arraySizes);
00054
00055 Array2DUint8 pPreviousBitmask(arraySizes);
00056 Array2DUint8 pCurrentBitmask(arraySizes);
00057
00058
00059 m_regSlicePrevious = m_regSizeInVoxels;
00060 Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner();
00061 v3dUpperCorner.setZ(m_regSlicePrevious.getLowerCorner().getZ());
00062 m_regSlicePrevious.setUpperCorner(v3dUpperCorner);
00063 m_regSliceCurrent = m_regSlicePrevious;
00064
00065 uint32_t uNoOfNonEmptyCellsForSlice0 = 0;
00066 uint32_t uNoOfNonEmptyCellsForSlice1 = 0;
00067
00068
00069 computeBitmaskForSlice<false>(pPreviousBitmask, pCurrentBitmask);
00070 uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
00071
00072 if(uNoOfNonEmptyCellsForSlice1 != 0)
00073 {
00074 memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4);
00075 memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4);
00076 memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4);
00077 generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
00078 }
00079
00080 std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
00081 pPreviousBitmask.swap(pCurrentBitmask);
00082 m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX);
00083 m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY);
00084 m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ);
00085
00086 m_regSlicePrevious = m_regSliceCurrent;
00087 m_regSliceCurrent.shift(Vector3DInt32(0,0,1));
00088
00089
00090 for(int32_t uSlice = 1; uSlice <= m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ(); uSlice++)
00091 {
00092 computeBitmaskForSlice<true>(pPreviousBitmask, pCurrentBitmask);
00093 uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
00094
00095 if(uNoOfNonEmptyCellsForSlice1 != 0)
00096 {
00097 memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4);
00098 memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4);
00099 memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4);
00100 generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
00101 }
00102
00103 if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0))
00104 {
00105 generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY);
00106 }
00107
00108 std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
00109 pPreviousBitmask.swap(pCurrentBitmask);
00110 m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX);
00111 m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY);
00112 m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ);
00113
00114 m_regSlicePrevious = m_regSliceCurrent;
00115 m_regSliceCurrent.shift(Vector3DInt32(0,0,1));
00116 }
00117
00118 m_meshCurrent->m_Region = m_regSizeInVoxels;
00119
00120 m_meshCurrent->m_vecLodRecords.clear();
00121 LodRecord lodRecord;
00122 lodRecord.beginIndex = 0;
00123 lodRecord.endIndex = m_meshCurrent->getNoOfIndices();
00124 m_meshCurrent->m_vecLodRecords.push_back(lodRecord);
00125 }
00126
00127 template< template<typename> class VolumeType, typename VoxelType>
00128 template<bool isPrevZAvail>
00129 uint32_t SurfaceExtractor<VolumeType, VoxelType>::computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask)
00130 {
00131 m_uNoOfOccupiedCells = 0;
00132
00133 const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperCorner().getX();
00134 const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperCorner().getY();
00135
00136 iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
00137 uZRegSpace = iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ();
00138
00139
00140 iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
00141 iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
00142
00143 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
00144 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
00145
00146 m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
00147 computeBitmaskForCell<false, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
00148
00149
00150 iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
00151 m_sampVolume.setPosition(iXVolSpace, m_regSliceCurrent.getLowerCorner().getY(), iZVolSpace);
00152 for(iYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++)
00153 {
00154 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
00155 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
00156
00157 m_sampVolume.movePositiveY();
00158
00159 computeBitmaskForCell<false, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
00160 }
00161
00162
00163 iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
00164 m_sampVolume.setPosition(m_regSliceCurrent.getLowerCorner().getX(), iYVolSpace, iZVolSpace);
00165 for(iXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++)
00166 {
00167 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
00168 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
00169
00170 m_sampVolume.movePositiveX();
00171
00172 computeBitmaskForCell<true, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
00173 }
00174
00175
00176 for(iYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++)
00177 {
00178 m_sampVolume.setPosition(m_regSliceCurrent.getLowerCorner().getX(), iYVolSpace, iZVolSpace);
00179 for(iXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++)
00180 {
00181 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
00182 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
00183
00184 m_sampVolume.movePositiveX();
00185
00186 computeBitmaskForCell<true, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
00187 }
00188 }
00189
00190 return m_uNoOfOccupiedCells;
00191 }
00192
00193 template< template<typename> class VolumeType, typename VoxelType>
00194 template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
00195 void SurfaceExtractor<VolumeType, VoxelType>::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask)
00196 {
00197 uint8_t iCubeIndex = 0;
00198
00199 VoxelType v000;
00200 VoxelType v100;
00201 VoxelType v010;
00202 VoxelType v110;
00203 VoxelType v001;
00204 VoxelType v101;
00205 VoxelType v011;
00206 VoxelType v111;
00207
00208 if(isPrevZAvail)
00209 {
00210 if(isPrevYAvail)
00211 {
00212 if(isPrevXAvail)
00213 {
00214 v111 = m_sampVolume.peekVoxel1px1py1pz();
00215
00216
00217 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00218 iPreviousCubeIndexZ >>= 4;
00219
00220
00221 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00222 iPreviousCubeIndexY &= 192;
00223 iPreviousCubeIndexY >>= 2;
00224
00225
00226 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00227 iPreviousCubeIndexX &= 128;
00228 iPreviousCubeIndexX >>= 1;
00229
00230 iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY | iPreviousCubeIndexZ;
00231
00232 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00233 }
00234 else
00235 {
00236 v011 = m_sampVolume.peekVoxel0px1py1pz();
00237 v111 = m_sampVolume.peekVoxel1px1py1pz();
00238
00239
00240 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00241 iPreviousCubeIndexZ >>= 4;
00242
00243
00244 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00245 iPreviousCubeIndexY &= 192;
00246 iPreviousCubeIndexY >>= 2;
00247
00248 iCubeIndex = iPreviousCubeIndexY | iPreviousCubeIndexZ;
00249
00250 if (v011.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 64;
00251 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00252 }
00253 }
00254 else
00255 {
00256 if(isPrevXAvail)
00257 {
00258 v101 = m_sampVolume.peekVoxel1px0py1pz();
00259 v111 = m_sampVolume.peekVoxel1px1py1pz();
00260
00261
00262 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00263 iPreviousCubeIndexZ >>= 4;
00264
00265
00266 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00267 iPreviousCubeIndexX &= 160;
00268 iPreviousCubeIndexX >>= 1;
00269
00270 iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexZ;
00271
00272 if (v101.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 32;
00273 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00274 }
00275 else
00276 {
00277 v001 = m_sampVolume.peekVoxel0px0py1pz();
00278 v101 = m_sampVolume.peekVoxel1px0py1pz();
00279 v011 = m_sampVolume.peekVoxel0px1py1pz();
00280 v111 = m_sampVolume.peekVoxel1px1py1pz();
00281
00282
00283 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00284 iCubeIndex = iPreviousCubeIndexZ >> 4;
00285
00286 if (v001.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 16;
00287 if (v101.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 32;
00288 if (v011.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 64;
00289 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00290 }
00291 }
00292 }
00293 else
00294 {
00295 if(isPrevYAvail)
00296 {
00297 if(isPrevXAvail)
00298 {
00299 v110 = m_sampVolume.peekVoxel1px1py0pz();
00300 v111 = m_sampVolume.peekVoxel1px1py1pz();
00301
00302
00303 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00304 iPreviousCubeIndexY &= 204;
00305 iPreviousCubeIndexY >>= 2;
00306
00307
00308 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00309 iPreviousCubeIndexX &= 170;
00310 iPreviousCubeIndexX >>= 1;
00311
00312 iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY;
00313
00314 if (v110.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 8;
00315 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00316 }
00317 else
00318 {
00319 v010 = m_sampVolume.peekVoxel0px1py0pz();
00320 v110 = m_sampVolume.peekVoxel1px1py0pz();
00321
00322 v011 = m_sampVolume.peekVoxel0px1py1pz();
00323 v111 = m_sampVolume.peekVoxel1px1py1pz();
00324
00325
00326 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00327 iPreviousCubeIndexY &= 204;
00328 iPreviousCubeIndexY >>= 2;
00329
00330 iCubeIndex = iPreviousCubeIndexY;
00331
00332 if (v010.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 4;
00333 if (v110.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 8;
00334 if (v011.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 64;
00335 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00336 }
00337 }
00338 else
00339 {
00340 if(isPrevXAvail)
00341 {
00342 v100 = m_sampVolume.peekVoxel1px0py0pz();
00343 v110 = m_sampVolume.peekVoxel1px1py0pz();
00344
00345 v101 = m_sampVolume.peekVoxel1px0py1pz();
00346 v111 = m_sampVolume.peekVoxel1px1py1pz();
00347
00348
00349 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00350 iPreviousCubeIndexX &= 170;
00351 iPreviousCubeIndexX >>= 1;
00352
00353 iCubeIndex = iPreviousCubeIndexX;
00354
00355 if (v100.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 2;
00356 if (v110.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 8;
00357 if (v101.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 32;
00358 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00359 }
00360 else
00361 {
00362 v000 = m_sampVolume.getVoxel();
00363 v100 = m_sampVolume.peekVoxel1px0py0pz();
00364 v010 = m_sampVolume.peekVoxel0px1py0pz();
00365 v110 = m_sampVolume.peekVoxel1px1py0pz();
00366
00367 v001 = m_sampVolume.peekVoxel0px0py1pz();
00368 v101 = m_sampVolume.peekVoxel1px0py1pz();
00369 v011 = m_sampVolume.peekVoxel0px1py1pz();
00370 v111 = m_sampVolume.peekVoxel1px1py1pz();
00371
00372 if (v000.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 1;
00373 if (v100.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 2;
00374 if (v010.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 4;
00375 if (v110.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 8;
00376 if (v001.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 16;
00377 if (v101.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 32;
00378 if (v011.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 64;
00379 if (v111.getDensity() < VoxelType::getThreshold()) iCubeIndex |= 128;
00380 }
00381 }
00382 }
00383
00384
00385 pCurrentBitmask[uXRegSpace][iYVolSpace- m_regSizeInVoxels.getLowerCorner().getY()] = iCubeIndex;
00386
00387 if(edgeTable[iCubeIndex] != 0)
00388 {
00389 ++m_uNoOfOccupiedCells;
00390 }
00391 }
00392
00393 template< template<typename> class VolumeType, typename VoxelType>
00394 void SurfaceExtractor<VolumeType, VoxelType>::generateVerticesForSlice(const Array2DUint8& pCurrentBitmask,
00395 Array2DInt32& m_pCurrentVertexIndicesX,
00396 Array2DInt32& m_pCurrentVertexIndicesY,
00397 Array2DInt32& m_pCurrentVertexIndicesZ)
00398 {
00399 int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
00400 const uint32_t uZRegSpace = iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ();
00401
00402
00403 for(int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); iYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); iYVolSpace++)
00404 {
00405 const uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
00406
00407 for(int32_t iXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); iXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); iXVolSpace++)
00408 {
00409
00410 const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
00411
00412
00413 uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace];
00414
00415
00416 if (edgeTable[iCubeIndex] == 0)
00417 {
00418 continue;
00419 }
00420
00421
00422
00423
00424 m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
00425 const VoxelType v000 = m_sampVolume.getVoxel();
00426 const Vector3DFloat n000 = computeCentralDifferenceGradient(m_sampVolume);
00427
00428
00429 if (edgeTable[iCubeIndex] & 1)
00430 {
00431 m_sampVolume.movePositiveX();
00432 const VoxelType v100 = m_sampVolume.getVoxel();
00433 const Vector3DFloat n100 = computeCentralDifferenceGradient(m_sampVolume);
00434
00435
00436 float fInterp = static_cast<float>(VoxelType::getThreshold() - v000.getDensity()) / static_cast<float>(v100.getDensity() - v000.getDensity());
00437
00438
00439 const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerCorner().getZ()));
00440
00441
00442 Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp));
00443 v3dNormal.normalise();
00444
00445 const uint32_t uMaterial = v000.getMaterial() | v100.getMaterial();
00446
00447 PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
00448 uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
00449 m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
00450
00451 m_sampVolume.moveNegativeX();
00452 }
00453 if (edgeTable[iCubeIndex] & 8)
00454 {
00455 m_sampVolume.movePositiveY();
00456 const VoxelType v010 = m_sampVolume.getVoxel();
00457 const Vector3DFloat n010 = computeCentralDifferenceGradient(m_sampVolume);
00458
00459 float fInterp = static_cast<float>(VoxelType::getThreshold() - v000.getDensity()) / static_cast<float>(v010.getDensity() - v000.getDensity());
00460
00461
00462 const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()));
00463
00464
00465 Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp));
00466 v3dNormal.normalise();
00467
00468 const uint32_t uMaterial = v000.getMaterial() | v010.getMaterial();
00469
00470 PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
00471 uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
00472 m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
00473
00474 m_sampVolume.moveNegativeY();
00475 }
00476 if (edgeTable[iCubeIndex] & 256)
00477 {
00478 m_sampVolume.movePositiveZ();
00479 const VoxelType v001 = m_sampVolume.getVoxel();
00480 const Vector3DFloat n001 = computeCentralDifferenceGradient(m_sampVolume);
00481
00482 float fInterp = static_cast<float>(VoxelType::getThreshold() - v000.getDensity()) / static_cast<float>(v001.getDensity() - v000.getDensity());
00483
00484
00485 const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()) + fInterp);
00486
00487
00488 Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp));
00489 v3dNormal.normalise();
00490
00491 const uint32_t uMaterial = v000.getMaterial() | v001.getMaterial();
00492
00493 PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
00494 uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
00495 m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
00496
00497 m_sampVolume.moveNegativeZ();
00498 }
00499 }
00500 }
00501 }
00502
00503 template< template<typename> class VolumeType, typename VoxelType>
00504 void SurfaceExtractor<VolumeType, VoxelType>::generateIndicesForSlice(const Array2DUint8& pPreviousBitmask,
00505 const Array2DInt32& m_pPreviousVertexIndicesX,
00506 const Array2DInt32& m_pPreviousVertexIndicesY,
00507 const Array2DInt32& m_pPreviousVertexIndicesZ,
00508 const Array2DInt32& m_pCurrentVertexIndicesX,
00509 const Array2DInt32& m_pCurrentVertexIndicesY)
00510 {
00511 int32_t indlist[12];
00512 for(int i = 0; i < 12; i++)
00513 {
00514 indlist[i] = -1;
00515 }
00516
00517 for(int32_t iYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); iYVolSpace <= m_regSizeInCells.getUpperCorner().getY(); iYVolSpace++)
00518 {
00519 for(int32_t iXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); iXVolSpace <= m_regSizeInCells.getUpperCorner().getX(); iXVolSpace++)
00520 {
00521 int32_t iZVolSpace = m_regSlicePrevious.getLowerCorner().getZ();
00522 m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
00523
00524
00525 const uint32_t uXRegSpace = m_sampVolume.getPosX() - m_regSizeInVoxels.getLowerCorner().getX();
00526 const uint32_t uYRegSpace = m_sampVolume.getPosY() - m_regSizeInVoxels.getLowerCorner().getY();
00527
00528
00529 uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace];
00530
00531
00532 if (edgeTable[iCubeIndex] == 0)
00533 {
00534 continue;
00535 }
00536
00537
00538 if (edgeTable[iCubeIndex] & 1)
00539 {
00540 indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace];
00541
00542 }
00543 if (edgeTable[iCubeIndex] & 2)
00544 {
00545 indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace];
00546
00547 }
00548 if (edgeTable[iCubeIndex] & 4)
00549 {
00550 indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1];
00551
00552 }
00553 if (edgeTable[iCubeIndex] & 8)
00554 {
00555 indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace];
00556
00557 }
00558 if (edgeTable[iCubeIndex] & 16)
00559 {
00560 indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace];
00561
00562 }
00563 if (edgeTable[iCubeIndex] & 32)
00564 {
00565 indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace];
00566
00567 }
00568 if (edgeTable[iCubeIndex] & 64)
00569 {
00570 indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1];
00571
00572 }
00573 if (edgeTable[iCubeIndex] & 128)
00574 {
00575 indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace];
00576
00577 }
00578 if (edgeTable[iCubeIndex] & 256)
00579 {
00580 indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace];
00581
00582 }
00583 if (edgeTable[iCubeIndex] & 512)
00584 {
00585 indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace];
00586
00587 }
00588 if (edgeTable[iCubeIndex] & 1024)
00589 {
00590 indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1];
00591
00592 }
00593 if (edgeTable[iCubeIndex] & 2048)
00594 {
00595 indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1];
00596
00597 }
00598
00599 for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3)
00600 {
00601 int32_t ind0 = indlist[triTable[iCubeIndex][i ]];
00602 int32_t ind1 = indlist[triTable[iCubeIndex][i+1]];
00603 int32_t ind2 = indlist[triTable[iCubeIndex][i+2]];
00604
00605 if((ind0 != -1) && (ind1 != -1) && (ind2 != -1))
00606 {
00607 assert(ind0 >= 0);
00608 assert(ind1 >= 0);
00609 assert(ind2 >= 0);
00610
00611 assert(ind0 < 1000000);
00612 assert(ind1 < 1000000);
00613 assert(ind2 < 1000000);
00614 m_meshCurrent->addTriangle(ind0, ind1, ind2);
00615 }
00616 }
00617 }
00618 }
00619 }
00620 }