• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

PolyVoxCore/include/PolyVoxCore/SurfaceExtractor.inl

Go to the documentation of this file.
00001 /*******************************************************************************
00002 Copyright (c) 2005-2009 David Williams
00003 
00004 This software is provided 'as-is', without any express or implied
00005 warranty. In no event will the authors be held liable for any damages
00006 arising from the use of this software.
00007 
00008 Permission is granted to anyone to use this software for any purpose,
00009 including commercial applications, and to alter it and redistribute it
00010 freely, subject to the following restrictions:
00011 
00012     1. The origin of this software must not be misrepresented; you must not
00013     claim that you wrote the original software. If you use this software
00014     in a product, an acknowledgment in the product documentation would be
00015     appreciated but is not required.
00016 
00017     2. Altered source versions must be plainly marked as such, and must not be
00018     misrepresented as being the original software.
00019 
00020     3. This notice may not be removed or altered from any source
00021     distribution.   
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         //m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion());
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}; // Array dimensions
00046 
00047         //For edge indices
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         //Create a region corresponding to the first slice
00059         m_regSlicePrevious = m_regSizeInVoxels;
00060         Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner();
00061         v3dUpperCorner.setZ(m_regSlicePrevious.getLowerCorner().getZ()); //Set the upper z to the lower z to make it one slice thick.
00062         m_regSlicePrevious.setUpperCorner(v3dUpperCorner);
00063         m_regSliceCurrent = m_regSlicePrevious; 
00064 
00065         uint32_t uNoOfNonEmptyCellsForSlice0 = 0;
00066         uint32_t uNoOfNonEmptyCellsForSlice1 = 0;
00067 
00068         //Process the first slice (previous slice not available)
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         //Process the other slices (previous slice is available)
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         //Process the lower left corner
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         //Process the edge where x is minimal.
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         //Process the edge where y is minimal.
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         //Process all remaining elemnents of the slice. In this case, previous x and y values are always available
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                     //z
00217                     uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00218                     iPreviousCubeIndexZ >>= 4;
00219 
00220                     //y
00221                     uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00222                     iPreviousCubeIndexY &= 192; //192 = 128 + 64
00223                     iPreviousCubeIndexY >>= 2;
00224 
00225                     //x
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 //previous X not available
00235                 {
00236                     v011 = m_sampVolume.peekVoxel0px1py1pz();
00237                     v111 = m_sampVolume.peekVoxel1px1py1pz();
00238 
00239                     //z
00240                     uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00241                     iPreviousCubeIndexZ >>= 4;
00242 
00243                     //y
00244                     uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00245                     iPreviousCubeIndexY &= 192; //192 = 128 + 64
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 //previous Y not available
00255             {
00256                 if(isPrevXAvail)
00257                 {
00258                     v101 = m_sampVolume.peekVoxel1px0py1pz();
00259                     v111 = m_sampVolume.peekVoxel1px1py1pz();
00260 
00261                     //z
00262                     uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
00263                     iPreviousCubeIndexZ >>= 4;
00264 
00265                     //x
00266                     uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00267                     iPreviousCubeIndexX &= 160; //160 = 128+32
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 //previous X not available
00276                 {
00277                     v001 = m_sampVolume.peekVoxel0px0py1pz();
00278                     v101 = m_sampVolume.peekVoxel1px0py1pz();
00279                     v011 = m_sampVolume.peekVoxel0px1py1pz();
00280                     v111 = m_sampVolume.peekVoxel1px1py1pz();
00281 
00282                     //z
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 //previous Z not available
00294         {
00295             if(isPrevYAvail)
00296             {
00297                 if(isPrevXAvail)
00298                 {
00299                     v110 = m_sampVolume.peekVoxel1px1py0pz();
00300                     v111 = m_sampVolume.peekVoxel1px1py1pz();
00301 
00302                     //y
00303                     uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00304                     iPreviousCubeIndexY &= 204; //204 = 128+64+8+4
00305                     iPreviousCubeIndexY >>= 2;
00306 
00307                     //x
00308                     uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00309                     iPreviousCubeIndexX &= 170; //170 = 128+32+8+2
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 //previous X not available
00318                 {
00319                     v010 = m_sampVolume.peekVoxel0px1py0pz();
00320                     v110 = m_sampVolume.peekVoxel1px1py0pz();
00321 
00322                     v011 = m_sampVolume.peekVoxel0px1py1pz();
00323                     v111 = m_sampVolume.peekVoxel1px1py1pz();
00324 
00325                     //y
00326                     uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
00327                     iPreviousCubeIndexY &= 204; //204 = 128+64+8+4
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 //previous Y not available
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                     //x
00349                     uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
00350                     iPreviousCubeIndexX &= 170; //170 = 128+32+8+2
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 //previous X not available
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         //Save the bitmask
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         //Iterate over each cell in the region
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                 //Current position
00410                 const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
00411 
00412                 //Determine the index into the edge table which tells us which vertices are inside of the surface
00413                 uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace];
00414 
00415                 /* Cube is entirely in/out of the surface */
00416                 if (edgeTable[iCubeIndex] == 0)
00417                 {
00418                     continue;
00419                 }
00420 
00421                 //Check whether the generated vertex will lie on the edge of the region
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                 /* Find the vertices where the surface intersects the cube */
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                     //float fInterp = static_cast<float>(v100.getDensity() - VoxelType::getMinDensity()) / static_cast<float>(VoxelType::getMaxDensity() - VoxelType::getMinDensity());
00436                     float fInterp = static_cast<float>(VoxelType::getThreshold() - v000.getDensity()) / static_cast<float>(v100.getDensity() - v000.getDensity());
00437                     //fInterp = 0.5f;
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                     //const Vector3DFloat v3dNormal(v000.getDensity() > v100.getDensity() ? 1.0f : -1.0f,0.0,0.0);
00441 
00442                     Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp));
00443                     v3dNormal.normalise();
00444 
00445                     const uint32_t uMaterial = v000.getMaterial() | v100.getMaterial(); //Because one of these is 0, the or operation takes the max.
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                     //fInterp = 0.5f;
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                     //const Vector3DFloat v3dNormal(0.0,v000.getDensity() > v010.getDensity() ? 1.0f : -1.0f,0.0);
00464 
00465                     Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp));
00466                     v3dNormal.normalise();
00467 
00468                     const uint32_t uMaterial = v000.getMaterial() | v010.getMaterial(); //Because one of these is 0, the or operation takes the max.
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                     //fInterp = 0.5f;
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                     //const Vector3DFloat v3dNormal(0.0,0.0,v000.getDensity() > v001.getDensity() ? 1.0f : -1.0f);
00487 
00488                     Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp));
00489                     v3dNormal.normalise();
00490 
00491                     const uint32_t uMaterial = v000.getMaterial() | v001.getMaterial(); //Because one of these is 0, the or operation takes the max.
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             }//For each cell
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                 //Current position
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                 //Determine the index into the edge table which tells us which vertices are inside of the surface
00529                 uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace];
00530 
00531                 /* Cube is entirely in/out of the surface */
00532                 if (edgeTable[iCubeIndex] == 0)
00533                 {
00534                     continue;
00535                 }
00536 
00537                 /* Find the vertices where the surface intersects the cube */
00538                 if (edgeTable[iCubeIndex] & 1)
00539                 {
00540                     indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace];
00541                     //assert(indlist[0] != -1);
00542                 }
00543                 if (edgeTable[iCubeIndex] & 2)
00544                 {
00545                     indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace];
00546                     //assert(indlist[1] != -1);
00547                 }
00548                 if (edgeTable[iCubeIndex] & 4)
00549                 {
00550                     indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1];
00551                     //assert(indlist[2] != -1);
00552                 }
00553                 if (edgeTable[iCubeIndex] & 8)
00554                 {
00555                     indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace];
00556                     //assert(indlist[3] != -1);
00557                 }
00558                 if (edgeTable[iCubeIndex] & 16)
00559                 {
00560                     indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace];
00561                     //assert(indlist[4] != -1);
00562                 }
00563                 if (edgeTable[iCubeIndex] & 32)
00564                 {
00565                     indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace];
00566                     //assert(indlist[5] != -1);
00567                 }
00568                 if (edgeTable[iCubeIndex] & 64)
00569                 {
00570                     indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1];
00571                     //assert(indlist[6] != -1);
00572                 }
00573                 if (edgeTable[iCubeIndex] & 128)
00574                 {
00575                     indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace];
00576                     //assert(indlist[7] != -1);
00577                 }
00578                 if (edgeTable[iCubeIndex] & 256)
00579                 {
00580                     indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace];
00581                     //assert(indlist[8] != -1);
00582                 }
00583                 if (edgeTable[iCubeIndex] & 512)
00584                 {
00585                     indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace];
00586                     //assert(indlist[9] != -1);
00587                 }
00588                 if (edgeTable[iCubeIndex] & 1024)
00589                 {
00590                     indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1];
00591                     //assert(indlist[10] != -1);
00592                 }
00593                 if (edgeTable[iCubeIndex] & 2048)
00594                 {
00595                     indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1];
00596                     //assert(indlist[11] != -1);
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                 }//For each triangle
00617             }//For each cell
00618         }
00619     }
00620 }

Generated on Sat Nov 19 2011 00:27:31 for PolyVox by  doxygen 1.7.1