From 19e860d2919ff3f236ea2ef84254591580e7c1a5 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 6 Jun 2009 11:52:56 +0000 Subject: [PATCH] Renamed some stuff in SurfaceExtractor. Added functions to move samplers to adjacent voxels. --- .../PolyVoxCore/include/SurfaceExtractor.h | 70 ++++++---- library/PolyVoxCore/include/VolumeSampler.h | 18 +-- library/PolyVoxCore/include/VolumeSampler.inl | 130 +++++++++++++++--- .../PolyVoxCore/source/SurfaceExtractor.cpp | 69 ++++++---- 4 files changed, 195 insertions(+), 92 deletions(-) diff --git a/library/PolyVoxCore/include/SurfaceExtractor.h b/library/PolyVoxCore/include/SurfaceExtractor.h index aed3d38b..ff39c894 100644 --- a/library/PolyVoxCore/include/SurfaceExtractor.h +++ b/library/PolyVoxCore/include/SurfaceExtractor.h @@ -44,16 +44,43 @@ namespace PolyVox POLYVOX_SHARED_PTR extractSurfaceForRegion(Region region); private: + //Extract the surface for a particular LOD level + template + void extractSurfaceImpl(void); + //Compute the cell bitmask for a particular slice in z. + template + uint32_t computeBitmaskForSlice(void); + + //Compute the cell bitmask for a given cell. + template + void computeBitmaskForCell(void); + + //Use the cell bitmasks to generate all the vertices needed for that slice + void generateVerticesForSlice(); + + //Use the cell bitmasks to generate all the indices needed for that slice + void generateIndicesForSlice(); + + //Converts a position into an index for accessing scratch areas. + inline uint32_t getIndex(uint32_t x, uint32_t y) + { + return x + (y * m_uScratchPadWidth); + } + + //The lod level can step size. uint8_t m_uLodLevel; uint8_t m_uStepSize; + //The volume data and a sampler to access it. Volume m_volData; VolumeSampler m_sampVolume; + //Cell bitmasks for the current and previous slices. uint8_t* m_pPreviousBitmask; uint8_t* m_pCurrentBitmask; + //Used to keep track of where generated vertices have been placed. int32_t* m_pPreviousVertexIndicesX; int32_t* m_pPreviousVertexIndicesY; int32_t* m_pPreviousVertexIndicesZ; @@ -61,57 +88,40 @@ namespace PolyVox int32_t* m_pCurrentVertexIndicesY; int32_t* m_pCurrentVertexIndicesZ; - uint8_t v000; - uint8_t v100; - uint8_t v010; - uint8_t v110; - uint8_t v001; - uint8_t v101; - uint8_t v011; - uint8_t v111; - + //Holds a position in volume space. uint16_t uXVolSpace; uint16_t uYVolSpace; uint16_t uZVolSpace; + //Holds a position in region space. uint16_t uXRegSpace; uint16_t uYRegSpace; uint16_t uZRegSpace; + //Used to return the number of cells in a slice which contain triangles. uint32_t m_uNoOfOccupiedCells; + //The surface patch we are currently filling. IndexedSurfacePatch* m_ispCurrent; + //Remove this? Vector3DFloat m_v3dRegionOffset; - uint16_t m_uScratchPadWidth; - uint16_t m_uScratchPadHeight; - + //Information about the region we a re currently processing Region m_Region; Region m_UncroppedRegion; Region m_croppedVolume; - Region regSlice0; - Region regSlice1; + Region m_regSlicePrevious; + Region m_regSliceCurrent; + //Store the width and height because they are frequently + //used and have some overhead to compute. uint16_t m_uRegionWidth; uint16_t m_uRegionHeight; - inline uint32_t getIndex(uint32_t x, uint32_t y) - { - return x + (y * m_uScratchPadWidth); - } - - template - void extractSurfaceImpl(void); - - template - uint32_t computeBitmaskForSlice(void); - - template - void computeBitmaskForCell(void); - - void generateIndicesForSlice(); - void generateVerticesForSlice(); + //These are used in several places so best stored. + uint16_t m_uScratchPadWidth; + uint16_t m_uScratchPadHeight; }; } diff --git a/library/PolyVoxCore/include/VolumeSampler.h b/library/PolyVoxCore/include/VolumeSampler.h index 8a886b54..a56136e6 100644 --- a/library/PolyVoxCore/include/VolumeSampler.h +++ b/library/PolyVoxCore/include/VolumeSampler.h @@ -54,6 +54,12 @@ namespace PolyVox void setPosition(uint16_t xPos, uint16_t yPos, uint16_t zPos); void movePositiveX(void); + void movePositiveY(void); + void movePositiveZ(void); + + void moveNegativeX(void); + void moveNegativeY(void); + void moveNegativeZ(void); inline VoxelType peekVoxel1nx1ny1nz(void) const; inline VoxelType peekVoxel1nx1ny0pz(void) const; @@ -95,20 +101,8 @@ namespace PolyVox uint16_t mYPosInVolume; uint16_t mZPosInVolume; - //The position of the current block - uint16_t mXBlock; - uint16_t mYBlock; - uint16_t mZBlock; - - //The offset into the current block - uint16_t mXPosInBlock; - uint16_t mYPosInBlock; - uint16_t mZPosInBlock; - //Other current position information VoxelType* mCurrentVoxel; - uint32_t mBlockIndexInVolume; - uint32_t mVoxelIndexInBlock; }; } diff --git a/library/PolyVoxCore/include/VolumeSampler.inl b/library/PolyVoxCore/include/VolumeSampler.inl index 46f00031..41b02e39 100644 --- a/library/PolyVoxCore/include/VolumeSampler.inl +++ b/library/PolyVoxCore/include/VolumeSampler.inl @@ -190,24 +190,23 @@ namespace PolyVox mYPosInVolume = yPos; mZPosInVolume = zPos; - mXBlock = mXPosInVolume >> mVolume.m_uBlockSideLengthPower; - mYBlock = mYPosInVolume >> mVolume.m_uBlockSideLengthPower; - mZBlock = mZPosInVolume >> mVolume.m_uBlockSideLengthPower; + uint16_t uXBlock = mXPosInVolume >> mVolume.m_uBlockSideLengthPower; + uint16_t uYBlock = mYPosInVolume >> mVolume.m_uBlockSideLengthPower; + uint16_t uZBlock = mZPosInVolume >> mVolume.m_uBlockSideLengthPower; - mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.m_uBlockSideLengthPower); - mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.m_uBlockSideLengthPower); - mZPosInBlock = mZPosInVolume - (mZBlock << mVolume.m_uBlockSideLengthPower); + uint16_t uXPosInBlock = mXPosInVolume - (uXBlock << mVolume.m_uBlockSideLengthPower); + uint16_t uYPosInBlock = mYPosInVolume - (uYBlock << mVolume.m_uBlockSideLengthPower); + uint16_t uZPosInBlock = mZPosInVolume - (uZBlock << mVolume.m_uBlockSideLengthPower); - mBlockIndexInVolume = mXBlock + - mYBlock * mVolume.m_uWidthInBlocks + - mZBlock * mVolume.m_uWidthInBlocks * mVolume.m_uHeightInBlocks; - POLYVOX_SHARED_PTR< Block > currentBlock = mVolume.m_pBlocks[mBlockIndexInVolume]; + uint32_t uBlockIndexInVolume = uXBlock + + uYBlock * mVolume.m_uWidthInBlocks + + uZBlock * mVolume.m_uWidthInBlocks * mVolume.m_uHeightInBlocks; + POLYVOX_SHARED_PTR< Block > currentBlock = mVolume.m_pBlocks[uBlockIndexInVolume]; - mVoxelIndexInBlock = mXPosInBlock + - mYPosInBlock * mVolume.m_uBlockSideLength + - mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; - - mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; + uint32_t uVoxelIndexInBlock = uXPosInBlock + + uYPosInBlock * mVolume.m_uBlockSideLength + + uZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; + mCurrentVoxel = currentBlock->m_tData + uVoxelIndexInBlock; } #pragma endregion @@ -215,17 +214,108 @@ namespace PolyVox template void VolumeSampler::movePositiveX(void) { - ++mXPosInVolume; - if(mXPosInVolume % mVolume.m_uBlockSideLength == 0) + assert(mXPosInVolume < mVolume.m_uWidth - 1); + + //Note the *post* increament here + if((mXPosInVolume++) % mVolume.m_uBlockSideLength == 0) + { + //No need to compute new block. + ++mCurrentVoxel; + } + else { //We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this. setPosition(mXPosInVolume, mYPosInVolume, mZPosInVolume); } - else + } + + template + void VolumeSampler::movePositiveY(void) + { + assert(mYPosInVolume < mVolume.m_uHeight - 1); + + //Note the *post* increament here + if((mYPosInVolume++) % mVolume.m_uBlockSideLength == 0) { //No need to compute new block. - ++mVoxelIndexInBlock; - ++mCurrentVoxel; + mCurrentVoxel += mVolume.m_uBlockSideLength; + } + else + { + //We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this. + setPosition(mXPosInVolume, mYPosInVolume, mZPosInVolume); + } + } + + template + void VolumeSampler::movePositiveZ(void) + { + assert(mZPosInVolume < mVolume.m_uDepth - 1); + + //Note the *post* increament here + if((mZPosInVolume++) % mVolume.m_uBlockSideLength == 0) + { + //No need to compute new block. + mCurrentVoxel += mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; + } + else + { + //We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this. + setPosition(mXPosInVolume, mYPosInVolume, mZPosInVolume); + } + } + + template + void VolumeSampler::moveNegativeX(void) + { + assert(mXPosInVolume > 0); + + //Note the *pre* increament here + if((--mXPosInVolume) % mVolume.m_uBlockSideLength == 0) + { + //No need to compute new block. + ++mCurrentVoxel; + } + else + { + //We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this. + setPosition(mXPosInVolume, mYPosInVolume, mZPosInVolume); + } + } + + template + void VolumeSampler::moveNegativeY(void) + { + assert(mYPosInVolume > 0); + + //Note the *pre* increament here + if((--mYPosInVolume) % mVolume.m_uBlockSideLength == 0) + { + //No need to compute new block. + mCurrentVoxel += mVolume.m_uBlockSideLength; + } + else + { + //We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this. + setPosition(mXPosInVolume, mYPosInVolume, mZPosInVolume); + } + } + + template + void VolumeSampler::moveNegativeZ(void) + { + assert(mZPosInVolume > 0); + + //Note the *pre* increament here + if((--mZPosInVolume) % mVolume.m_uBlockSideLength == 0) + { + //No need to compute new block. + mCurrentVoxel += mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; + } + else + { + //We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this. + setPosition(mXPosInVolume, mYPosInVolume, mZPosInVolume); } } #pragma endregion diff --git a/library/PolyVoxCore/source/SurfaceExtractor.cpp b/library/PolyVoxCore/source/SurfaceExtractor.cpp index e03589ab..df1053a0 100644 --- a/library/PolyVoxCore/source/SurfaceExtractor.cpp +++ b/library/PolyVoxCore/source/SurfaceExtractor.cpp @@ -63,11 +63,11 @@ namespace PolyVox m_v3dRegionOffset = static_cast(m_Region.getLowerCorner()); //Create a region corresponding to the first slice - regSlice0 = m_Region; - Vector3DInt32 v3dUpperCorner = regSlice0.getUpperCorner(); - v3dUpperCorner.setZ(regSlice0.getLowerCorner().getZ()); //Set the upper z to the lower z to make it one slice thick. - regSlice0.setUpperCorner(v3dUpperCorner); - regSlice1 = regSlice0; + m_regSlicePrevious = m_Region; + Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner(); + v3dUpperCorner.setZ(m_regSlicePrevious.getLowerCorner().getZ()); //Set the upper z to the lower z to make it one slice thick. + m_regSlicePrevious.setUpperCorner(v3dUpperCorner); + m_regSliceCurrent = m_regSlicePrevious; switch(m_uLodLevel) { @@ -120,8 +120,8 @@ namespace PolyVox std::swap(m_pPreviousVertexIndicesY, m_pCurrentVertexIndicesY); std::swap(m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesZ); - regSlice0 = regSlice1; - regSlice1.shift(Vector3DInt32(0,0,m_uStepSize)); + m_regSlicePrevious = m_regSliceCurrent; + m_regSliceCurrent.shift(Vector3DInt32(0,0,m_uStepSize)); //Process the other slices (previous slice is available) for(uint32_t uSlice = 1; uSlice <= m_Region.depth(); uSlice += m_uStepSize) @@ -148,13 +148,13 @@ namespace PolyVox std::swap(m_pPreviousVertexIndicesY, m_pCurrentVertexIndicesY); std::swap(m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesZ); - regSlice0 = regSlice1; - regSlice1.shift(Vector3DInt32(0,0,m_uStepSize)); + m_regSlicePrevious = m_regSliceCurrent; + m_regSliceCurrent.shift(Vector3DInt32(0,0,m_uStepSize)); } //A final slice just to close of the volume - regSlice1.shift(Vector3DInt32(0,0,-m_uStepSize)); - if(regSlice1.getLowerCorner().getZ() == m_croppedVolume.getUpperCorner().getZ()) + m_regSliceCurrent.shift(Vector3DInt32(0,0,-m_uStepSize)); + if(m_regSliceCurrent.getLowerCorner().getZ() == m_croppedVolume.getUpperCorner().getZ()) { memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4); memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4); @@ -168,15 +168,15 @@ namespace PolyVox { m_uNoOfOccupiedCells = 0; - const uint16_t uMaxXVolSpace = regSlice1.getUpperCorner().getX(); - const uint16_t uMaxYVolSpace = regSlice1.getUpperCorner().getY(); + const uint16_t uMaxXVolSpace = m_regSliceCurrent.getUpperCorner().getX(); + const uint16_t uMaxYVolSpace = m_regSliceCurrent.getUpperCorner().getY(); - uZVolSpace = regSlice1.getLowerCorner().getZ(); + uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); uZRegSpace = uZVolSpace - m_v3dRegionOffset.getZ(); //Process the lower left corner - uYVolSpace = regSlice1.getLowerCorner().getY(); - uXVolSpace = regSlice1.getLowerCorner().getX(); + uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); + uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXRegSpace = uXVolSpace - m_v3dRegionOffset.getX(); uYRegSpace = uYVolSpace - m_v3dRegionOffset.getY(); @@ -186,8 +186,8 @@ namespace PolyVox //Process the edge where x is minimal. - uXVolSpace = regSlice1.getLowerCorner().getX(); - for(uYVolSpace = regSlice1.getLowerCorner().getY() + m_uStepSize; uYVolSpace <= uMaxYVolSpace; uYVolSpace += m_uStepSize) + uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); + for(uYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + m_uStepSize; uYVolSpace <= uMaxYVolSpace; uYVolSpace += m_uStepSize) { uXRegSpace = uXVolSpace - m_v3dRegionOffset.getX(); uYRegSpace = uYVolSpace - m_v3dRegionOffset.getY(); @@ -197,8 +197,8 @@ namespace PolyVox } //Process the edge where y is minimal. - uYVolSpace = regSlice1.getLowerCorner().getY(); - for(uXVolSpace = regSlice1.getLowerCorner().getX() + m_uStepSize; uXVolSpace <= uMaxXVolSpace; uXVolSpace += m_uStepSize) + uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); + for(uXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + m_uStepSize; uXVolSpace <= uMaxXVolSpace; uXVolSpace += m_uStepSize) { uXRegSpace = uXVolSpace - m_v3dRegionOffset.getX(); uYRegSpace = uYVolSpace - m_v3dRegionOffset.getY(); @@ -208,9 +208,9 @@ namespace PolyVox } //Process all remaining elemnents of the slice. In this case, previous x and y values are always available - for(uYVolSpace = regSlice1.getLowerCorner().getY() + m_uStepSize; uYVolSpace <= uMaxYVolSpace; uYVolSpace += m_uStepSize) + for(uYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + m_uStepSize; uYVolSpace <= uMaxYVolSpace; uYVolSpace += m_uStepSize) { - for(uXVolSpace = regSlice1.getLowerCorner().getX() + m_uStepSize; uXVolSpace <= uMaxXVolSpace; uXVolSpace += m_uStepSize) + for(uXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + m_uStepSize; uXVolSpace <= uMaxXVolSpace; uXVolSpace += m_uStepSize) { uXRegSpace = uXVolSpace - m_v3dRegionOffset.getX(); uYRegSpace = uYVolSpace - m_v3dRegionOffset.getY(); @@ -228,6 +228,15 @@ namespace PolyVox { uint8_t iCubeIndex = 0; + uint8_t v000 = 0; + uint8_t v100 = 0; + uint8_t v010 = 0; + uint8_t v110 = 0; + uint8_t v001 = 0; + uint8_t v101 = 0; + uint8_t v011 = 0; + uint8_t v111 = 0; + if(isPrevZAvail) { if(isPrevYAvail) @@ -524,11 +533,11 @@ namespace PolyVox void SurfaceExtractor::generateVerticesForSlice() { //Iterate over each cell in the region - for(uint16_t uYVolSpace = regSlice1.getLowerCorner().getY(); uYVolSpace <= regSlice1.getUpperCorner().getY(); uYVolSpace += m_uStepSize) + for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); uYVolSpace += m_uStepSize) { - for(uint16_t uXVolSpace = regSlice1.getLowerCorner().getX(); uXVolSpace <= regSlice1.getUpperCorner().getX(); uXVolSpace += m_uStepSize) + for(uint16_t uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); uXVolSpace += m_uStepSize) { - uint16_t uZVolSpace = regSlice1.getLowerCorner().getZ(); + uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); //Current position const uint16_t uXRegSpace = uXVolSpace - m_v3dRegionOffset.getX(); @@ -553,7 +562,7 @@ namespace PolyVox /* Find the vertices where the surface intersects the cube */ if (edgeTable[iCubeIndex] & 1) { - //if(uXVolSpace != regSlice1.getUpperCorner().getX()) + //if(uXVolSpace != m_regSliceCurrent.getUpperCorner().getX()) { m_sampVolume.setPosition(uXVolSpace + m_uStepSize,uYVolSpace,uZVolSpace); const uint8_t v100 = m_sampVolume.getSubSampledVoxel(m_uLodLevel); @@ -567,7 +576,7 @@ namespace PolyVox } if (edgeTable[iCubeIndex] & 8) { - //if(uYVolSpace != regSlice1.getUpperCorner().getY()) + //if(uYVolSpace != m_regSliceCurrent.getUpperCorner().getY()) { m_sampVolume.setPosition(uXVolSpace,uYVolSpace + m_uStepSize,uZVolSpace); const uint8_t v010 = m_sampVolume.getSubSampledVoxel(m_uLodLevel); @@ -605,11 +614,11 @@ namespace PolyVox indlist[i] = -1; } - for(uint16_t uYVolSpace = regSlice0.getLowerCorner().getY(); uYVolSpace < m_UncroppedRegion.getUpperCorner().getY(); uYVolSpace += m_uStepSize) + for(uint16_t uYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); uYVolSpace < m_UncroppedRegion.getUpperCorner().getY(); uYVolSpace += m_uStepSize) { - for(uint16_t uXVolSpace = regSlice0.getLowerCorner().getX(); uXVolSpace < m_UncroppedRegion.getUpperCorner().getX(); uXVolSpace += m_uStepSize) + for(uint16_t uXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); uXVolSpace < m_UncroppedRegion.getUpperCorner().getX(); uXVolSpace += m_uStepSize) { - uint16_t uZVolSpace = regSlice0.getLowerCorner().getZ(); + uint16_t uZVolSpace = m_regSlicePrevious.getLowerCorner().getZ(); m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace); //Current position