Work on making the surface extractor use the new Array class.

This commit is contained in:
David Williams 2010-03-14 22:24:32 +00:00
parent dbde097547
commit 34d138417e
4 changed files with 163 additions and 127 deletions

View File

@ -121,7 +121,7 @@ void OpenGLWidget::setVolume(PolyVox::Volume<PolyVox::uint8_t>* volData)
//For decimation built into Mesh //For decimation built into Mesh
//mesh->generateAveragedFaceNormals(true); //mesh->generateAveragedFaceNormals(true);
mesh->decimate(0.999f); //mesh->decimate(0.999f);
//mesh->generateAveragedFaceNormals(true); //mesh->generateAveragedFaceNormals(true);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -154,6 +154,11 @@ namespace PolyVox
rhs.m_pData = temp; rhs.m_pData = temp;
} }
void fillWithUint8(uint8_t value)
{
memset(m_pData, value, m_uWidth * m_uHeight * sizeof(ElementType));
}
private: private:
//Dimensions //Dimensions
uint32_t m_uWidth; uint32_t m_uWidth;

View File

@ -44,22 +44,28 @@ namespace PolyVox
POLYVOX_SHARED_PTR<SurfaceMesh> extractSurfaceForRegion(Region region); POLYVOX_SHARED_PTR<SurfaceMesh> extractSurfaceForRegion(Region region);
private: private:
//Extract the surface for a particular LOD level
void extractSurfaceImpl(void);
//Compute the cell bitmask for a particular slice in z. //Compute the cell bitmask for a particular slice in z.
template<bool isPrevZAvail> template<bool isPrevZAvail>
uint32_t computeBitmaskForSlice(void); uint32_t computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask);
//Compute the cell bitmask for a given cell. //Compute the cell bitmask for a given cell.
template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail> template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
void computeBitmaskForCell(void); void computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask);
//Use the cell bitmasks to generate all the vertices needed for that slice //Use the cell bitmasks to generate all the vertices needed for that slice
void generateVerticesForSlice(); void generateVerticesForSlice(const Array2DUint8& pCurrentBitmask,
Array2DInt32& m_pCurrentVertexIndicesX,
Array2DInt32& m_pCurrentVertexIndicesY,
Array2DInt32& m_pCurrentVertexIndicesZ);
//Use the cell bitmasks to generate all the indices needed for that slice //Use the cell bitmasks to generate all the indices needed for that slice
void generateIndicesForSlice(); void generateIndicesForSlice(const Array2DUint8& pPreviousBitmask,
const Array2DInt32& m_pPreviousVertexIndicesX,
const Array2DInt32& m_pPreviousVertexIndicesY,
const Array2DInt32& m_pPreviousVertexIndicesZ,
const Array2DInt32& m_pCurrentVertexIndicesX,
const Array2DInt32& m_pCurrentVertexIndicesY,
const Array2DInt32& m_pCurrentVertexIndicesZ);
//Converts a position into an index for accessing scratch areas. //Converts a position into an index for accessing scratch areas.
inline uint32_t getIndex(uint32_t x, uint32_t y) inline uint32_t getIndex(uint32_t x, uint32_t y)
@ -71,17 +77,20 @@ namespace PolyVox
Volume<uint8_t> m_volData; Volume<uint8_t> m_volData;
VolumeSampler<uint8_t> m_sampVolume; VolumeSampler<uint8_t> 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. //Used to keep track of where generated vertices have been placed.
int32_t* m_pPreviousVertexIndicesX; /*int32_t* m_pPreviousVertexIndicesX;
int32_t* m_pPreviousVertexIndicesY; int32_t* m_pPreviousVertexIndicesY;
int32_t* m_pPreviousVertexIndicesZ; int32_t* m_pPreviousVertexIndicesZ;
int32_t* m_pCurrentVertexIndicesX; int32_t* m_pCurrentVertexIndicesX;
int32_t* m_pCurrentVertexIndicesY; int32_t* m_pCurrentVertexIndicesY;
int32_t* m_pCurrentVertexIndicesZ; int32_t* m_pCurrentVertexIndicesZ;*/
/*Array2DInt32 m_pPreviousVertexIndicesX;
Array2DInt32 m_pPreviousVertexIndicesY;
Array2DInt32 m_pPreviousVertexIndicesZ;
Array2DInt32 m_pCurrentVertexIndicesX;
Array2DInt32 m_pCurrentVertexIndicesY;
Array2DInt32 m_pCurrentVertexIndicesZ;*/
//Holds a position in volume space. //Holds a position in volume space.
uint16_t uXVolSpace; uint16_t uXVolSpace;

View File

@ -23,6 +23,7 @@ freely, subject to the following restrictions:
#include "SurfaceExtractor.h" #include "SurfaceExtractor.h"
#include "Array.h"
#include "SurfaceMesh.h" #include "SurfaceMesh.h"
#include "PolyVoxImpl/MarchingCubesTables.h" #include "PolyVoxImpl/MarchingCubesTables.h"
#include "SurfaceVertex.h" #include "SurfaceVertex.h"
@ -57,16 +58,23 @@ namespace PolyVox
m_uScratchPadHeight = m_uRegionHeight+1; m_uScratchPadHeight = m_uRegionHeight+1;
//For edge indices //For edge indices
m_pPreviousVertexIndicesX = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight]; /*m_pPreviousVertexIndicesX = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight];
m_pPreviousVertexIndicesY = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight]; m_pPreviousVertexIndicesY = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight];
m_pPreviousVertexIndicesZ = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight]; m_pPreviousVertexIndicesZ = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight];
m_pCurrentVertexIndicesX = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight]; m_pCurrentVertexIndicesX = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight];
m_pCurrentVertexIndicesY = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight]; m_pCurrentVertexIndicesY = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight];
m_pCurrentVertexIndicesZ = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight]; m_pCurrentVertexIndicesZ = new int32_t[m_uScratchPadWidth * m_uScratchPadHeight];*/
Array2DInt32 m_pPreviousVertexIndicesX(m_uScratchPadWidth, m_uScratchPadHeight);
Array2DInt32 m_pPreviousVertexIndicesY(m_uScratchPadWidth, m_uScratchPadHeight);
Array2DInt32 m_pPreviousVertexIndicesZ(m_uScratchPadWidth, m_uScratchPadHeight);
Array2DInt32 m_pCurrentVertexIndicesX(m_uScratchPadWidth, m_uScratchPadHeight);
Array2DInt32 m_pCurrentVertexIndicesY(m_uScratchPadWidth, m_uScratchPadHeight);
Array2DInt32 m_pCurrentVertexIndicesZ(m_uScratchPadWidth, m_uScratchPadHeight);
//Cell bitmasks //Cell bitmasks
m_pPreviousBitmask = new uint8_t[m_uScratchPadWidth * m_uScratchPadHeight]; Array2DUint8 pPreviousBitmask(m_uScratchPadWidth, m_uScratchPadHeight);
m_pCurrentBitmask = new uint8_t[m_uScratchPadWidth * m_uScratchPadHeight]; Array2DUint8 pCurrentBitmask(m_uScratchPadWidth, m_uScratchPadHeight);
//Create a region corresponding to the first slice //Create a region corresponding to the first slice
m_regSlicePrevious = m_regInputCropped; m_regSlicePrevious = m_regInputCropped;
@ -75,16 +83,87 @@ namespace PolyVox
m_regSlicePrevious.setUpperCorner(v3dUpperCorner); m_regSlicePrevious.setUpperCorner(v3dUpperCorner);
m_regSliceCurrent = m_regSlicePrevious; m_regSliceCurrent = m_regSlicePrevious;
extractSurfaceImpl(); uint32_t uNoOfNonEmptyCellsForSlice0 = 0;
uint32_t uNoOfNonEmptyCellsForSlice1 = 0;
delete[] m_pPreviousBitmask; //Process the first slice (previous slice not available)
delete[] m_pCurrentBitmask; computeBitmaskForSlice<false>(pPreviousBitmask, pCurrentBitmask);
delete[] m_pPreviousVertexIndicesX; uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
if(uNoOfNonEmptyCellsForSlice1 != 0)
{
/*memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesZ, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);*/
m_pCurrentVertexIndicesX.fillWithUint8(0xff);
m_pCurrentVertexIndicesY.fillWithUint8(0xff);
m_pCurrentVertexIndicesZ.fillWithUint8(0xff);
generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
}
std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
pPreviousBitmask.swap(pCurrentBitmask);
m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX);
m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY);
m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ);
m_regSlicePrevious = m_regSliceCurrent;
m_regSliceCurrent.shift(Vector3DInt16(0,0,1));
//Process the other slices (previous slice is available)
for(int16_t uSlice = 1; uSlice <= m_regInputCropped.depth(); uSlice++)
{
computeBitmaskForSlice<true>(pPreviousBitmask, pCurrentBitmask);
uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
if(uNoOfNonEmptyCellsForSlice1 != 0)
{
/*memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesZ, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);*/
m_pCurrentVertexIndicesX.fillWithUint8(0xff);
m_pCurrentVertexIndicesY.fillWithUint8(0xff);
m_pCurrentVertexIndicesZ.fillWithUint8(0xff);
generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
}
if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0))
{
generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
}
std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
pPreviousBitmask.swap(pCurrentBitmask);
m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX);
m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY);
m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ);
/*std::swap(m_pPreviousVertexIndicesX, m_pCurrentVertexIndicesX);
std::swap(m_pPreviousVertexIndicesY, m_pCurrentVertexIndicesY);
std::swap(m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesZ);*/
m_regSlicePrevious = m_regSliceCurrent;
m_regSliceCurrent.shift(Vector3DInt16(0,0,1));
}
//A final slice just to close of the volume
m_regSliceCurrent.shift(Vector3DInt16(0,0,-1));
if(m_regSliceCurrent.getLowerCorner().getZ() == m_regVolumeCropped.getUpperCorner().getZ())
{
/*memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesZ, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);*/
m_pCurrentVertexIndicesX.fillWithUint8(0xff);
m_pCurrentVertexIndicesY.fillWithUint8(0xff);
m_pCurrentVertexIndicesZ.fillWithUint8(0xff);
generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
}
/*delete[] m_pPreviousVertexIndicesX;
delete[] m_pCurrentVertexIndicesX; delete[] m_pCurrentVertexIndicesX;
delete[] m_pPreviousVertexIndicesY; delete[] m_pPreviousVertexIndicesY;
delete[] m_pCurrentVertexIndicesY; delete[] m_pCurrentVertexIndicesY;
delete[] m_pPreviousVertexIndicesZ; delete[] m_pPreviousVertexIndicesZ;
delete[] m_pCurrentVertexIndicesZ; delete[] m_pCurrentVertexIndicesZ; */
m_meshCurrent->m_Region = m_regInputUncropped; m_meshCurrent->m_Region = m_regInputUncropped;
@ -97,74 +176,8 @@ namespace PolyVox
return POLYVOX_SHARED_PTR<SurfaceMesh>(m_meshCurrent); return POLYVOX_SHARED_PTR<SurfaceMesh>(m_meshCurrent);
} }
void SurfaceExtractor::extractSurfaceImpl(void)
{
uint32_t uNoOfNonEmptyCellsForSlice0 = 0;
uint32_t uNoOfNonEmptyCellsForSlice1 = 0;
//Process the first slice (previous slice not available)
computeBitmaskForSlice<false>();
uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
if(uNoOfNonEmptyCellsForSlice1 != 0)
{
memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesZ, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
generateVerticesForSlice();
}
std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
std::swap(m_pPreviousBitmask, m_pCurrentBitmask);
std::swap(m_pPreviousVertexIndicesX, m_pCurrentVertexIndicesX);
std::swap(m_pPreviousVertexIndicesY, m_pCurrentVertexIndicesY);
std::swap(m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesZ);
m_regSlicePrevious = m_regSliceCurrent;
m_regSliceCurrent.shift(Vector3DInt16(0,0,1));
//Process the other slices (previous slice is available)
for(int16_t uSlice = 1; uSlice <= m_regInputCropped.depth(); uSlice++)
{
computeBitmaskForSlice<true>();
uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
if(uNoOfNonEmptyCellsForSlice1 != 0)
{
memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesZ, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
generateVerticesForSlice();
}
if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0))
{
generateIndicesForSlice();
}
std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
std::swap(m_pPreviousBitmask, m_pCurrentBitmask);
std::swap(m_pPreviousVertexIndicesX, m_pCurrentVertexIndicesX);
std::swap(m_pPreviousVertexIndicesY, m_pCurrentVertexIndicesY);
std::swap(m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesZ);
m_regSlicePrevious = m_regSliceCurrent;
m_regSliceCurrent.shift(Vector3DInt16(0,0,1));
}
//A final slice just to close of the volume
m_regSliceCurrent.shift(Vector3DInt16(0,0,-1));
if(m_regSliceCurrent.getLowerCorner().getZ() == m_regVolumeCropped.getUpperCorner().getZ())
{
memset(m_pCurrentVertexIndicesX, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesY, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
memset(m_pCurrentVertexIndicesZ, 0xff, m_uScratchPadWidth * m_uScratchPadHeight * 4);
generateIndicesForSlice();
}
}
template<bool isPrevZAvail> template<bool isPrevZAvail>
uint32_t SurfaceExtractor::computeBitmaskForSlice(void) uint32_t SurfaceExtractor::computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask)
{ {
m_uNoOfOccupiedCells = 0; m_uNoOfOccupiedCells = 0;
@ -182,7 +195,7 @@ namespace PolyVox
uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY(); uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY();
m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace); m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace);
computeBitmaskForCell<false, false, isPrevZAvail>(); computeBitmaskForCell<false, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
//Process the edge where x is minimal. //Process the edge where x is minimal.
uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
@ -194,7 +207,7 @@ namespace PolyVox
m_sampVolume.movePositiveY(); m_sampVolume.movePositiveY();
computeBitmaskForCell<false, true, isPrevZAvail>(); computeBitmaskForCell<false, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
} }
//Process the edge where y is minimal. //Process the edge where y is minimal.
@ -207,7 +220,7 @@ namespace PolyVox
m_sampVolume.movePositiveX(); m_sampVolume.movePositiveX();
computeBitmaskForCell<true, false, isPrevZAvail>(); computeBitmaskForCell<true, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
} }
//Process all remaining elemnents of the slice. In this case, previous x and y values are always available //Process all remaining elemnents of the slice. In this case, previous x and y values are always available
@ -221,7 +234,7 @@ namespace PolyVox
m_sampVolume.movePositiveX(); m_sampVolume.movePositiveX();
computeBitmaskForCell<true, true, isPrevZAvail>(); computeBitmaskForCell<true, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
} }
} }
@ -229,7 +242,7 @@ namespace PolyVox
} }
template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail> template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
void SurfaceExtractor::computeBitmaskForCell(void) void SurfaceExtractor::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask)
{ {
uint8_t iCubeIndex = 0; uint8_t iCubeIndex = 0;
@ -251,16 +264,16 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//z //z
uint8_t iPreviousCubeIndexZ = m_pPreviousBitmask[getIndex(uXRegSpace,uYRegSpace)]; uint8_t iPreviousCubeIndexZ = pPreviousBitmask.getElement(uXRegSpace,uYRegSpace);
iPreviousCubeIndexZ >>= 4; iPreviousCubeIndexZ >>= 4;
//y //y
uint8_t iPreviousCubeIndexY = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace-1)]; uint8_t iPreviousCubeIndexY = pCurrentBitmask.getElement(uXRegSpace,uYRegSpace-1);
iPreviousCubeIndexY &= 192; //192 = 128 + 64 iPreviousCubeIndexY &= 192; //192 = 128 + 64
iPreviousCubeIndexY >>= 2; iPreviousCubeIndexY >>= 2;
//x //x
uint8_t iPreviousCubeIndexX = m_pCurrentBitmask[getIndex(uXRegSpace-1,uYRegSpace)]; uint8_t iPreviousCubeIndexX = pCurrentBitmask.getElement(uXRegSpace-1,uYRegSpace);
iPreviousCubeIndexX &= 128; iPreviousCubeIndexX &= 128;
iPreviousCubeIndexX >>= 1; iPreviousCubeIndexX >>= 1;
@ -274,11 +287,11 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//z //z
uint8_t iPreviousCubeIndexZ = m_pPreviousBitmask[getIndex(uXRegSpace,uYRegSpace)]; uint8_t iPreviousCubeIndexZ = pPreviousBitmask.getElement(uXRegSpace,uYRegSpace);
iPreviousCubeIndexZ >>= 4; iPreviousCubeIndexZ >>= 4;
//y //y
uint8_t iPreviousCubeIndexY = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace-1)]; uint8_t iPreviousCubeIndexY = pCurrentBitmask.getElement(uXRegSpace,uYRegSpace-1);
iPreviousCubeIndexY &= 192; //192 = 128 + 64 iPreviousCubeIndexY &= 192; //192 = 128 + 64
iPreviousCubeIndexY >>= 2; iPreviousCubeIndexY >>= 2;
@ -296,11 +309,11 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//z //z
uint8_t iPreviousCubeIndexZ = m_pPreviousBitmask[getIndex(uXRegSpace,uYRegSpace)]; uint8_t iPreviousCubeIndexZ = pPreviousBitmask.getElement(uXRegSpace,uYRegSpace);
iPreviousCubeIndexZ >>= 4; iPreviousCubeIndexZ >>= 4;
//x //x
uint8_t iPreviousCubeIndexX = m_pCurrentBitmask[getIndex(uXRegSpace-1,uYRegSpace)]; uint8_t iPreviousCubeIndexX = pCurrentBitmask.getElement(uXRegSpace-1,uYRegSpace);
iPreviousCubeIndexX &= 160; //160 = 128+32 iPreviousCubeIndexX &= 160; //160 = 128+32
iPreviousCubeIndexX >>= 1; iPreviousCubeIndexX >>= 1;
@ -317,7 +330,7 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//z //z
uint8_t iPreviousCubeIndexZ = m_pPreviousBitmask[getIndex(uXRegSpace,uYRegSpace)]; uint8_t iPreviousCubeIndexZ = pPreviousBitmask.getElement(uXRegSpace,uYRegSpace);
iCubeIndex = iPreviousCubeIndexZ >> 4; iCubeIndex = iPreviousCubeIndexZ >> 4;
if (v001 == 0) iCubeIndex |= 16; if (v001 == 0) iCubeIndex |= 16;
@ -337,12 +350,12 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//y //y
uint8_t iPreviousCubeIndexY = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace-1)]; uint8_t iPreviousCubeIndexY = pCurrentBitmask.getElement(uXRegSpace,uYRegSpace-1);
iPreviousCubeIndexY &= 204; //204 = 128+64+8+4 iPreviousCubeIndexY &= 204; //204 = 128+64+8+4
iPreviousCubeIndexY >>= 2; iPreviousCubeIndexY >>= 2;
//x //x
uint8_t iPreviousCubeIndexX = m_pCurrentBitmask[getIndex(uXRegSpace-1,uYRegSpace)]; uint8_t iPreviousCubeIndexX = pCurrentBitmask.getElement(uXRegSpace-1,uYRegSpace);
iPreviousCubeIndexX &= 170; //170 = 128+32+8+2 iPreviousCubeIndexX &= 170; //170 = 128+32+8+2
iPreviousCubeIndexX >>= 1; iPreviousCubeIndexX >>= 1;
@ -360,7 +373,7 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//y //y
uint8_t iPreviousCubeIndexY = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace-1)]; uint8_t iPreviousCubeIndexY = pCurrentBitmask.getElement(uXRegSpace,uYRegSpace-1);
iPreviousCubeIndexY &= 204; //204 = 128+64+8+4 iPreviousCubeIndexY &= 204; //204 = 128+64+8+4
iPreviousCubeIndexY >>= 2; iPreviousCubeIndexY >>= 2;
@ -383,7 +396,7 @@ namespace PolyVox
v111 = m_sampVolume.peekVoxel1px1py1pz(); v111 = m_sampVolume.peekVoxel1px1py1pz();
//x //x
uint8_t iPreviousCubeIndexX = m_pCurrentBitmask[getIndex(uXRegSpace-1,uYRegSpace)]; uint8_t iPreviousCubeIndexX = pCurrentBitmask.getElement(uXRegSpace-1,uYRegSpace);
iPreviousCubeIndexX &= 170; //170 = 128+32+8+2 iPreviousCubeIndexX &= 170; //170 = 128+32+8+2
iPreviousCubeIndexX >>= 1; iPreviousCubeIndexX >>= 1;
@ -419,7 +432,7 @@ namespace PolyVox
} }
//Save the bitmask //Save the bitmask
m_pCurrentBitmask[getIndex(uXRegSpace,uYVolSpace- m_regInputCropped.getLowerCorner().getY())] = iCubeIndex; pCurrentBitmask.setElement(uXRegSpace,uYVolSpace- m_regInputCropped.getLowerCorner().getY(), iCubeIndex);
if(edgeTable[iCubeIndex] != 0) if(edgeTable[iCubeIndex] != 0)
{ {
@ -427,7 +440,10 @@ namespace PolyVox
} }
} }
void SurfaceExtractor::generateVerticesForSlice() void SurfaceExtractor::generateVerticesForSlice(const Array2DUint8& pCurrentBitmask,
Array2DInt32& m_pCurrentVertexIndicesX,
Array2DInt32& m_pCurrentVertexIndicesY,
Array2DInt32& m_pCurrentVertexIndicesZ)
{ {
uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ(); const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ();
@ -452,7 +468,7 @@ namespace PolyVox
bool isPosXEdge = (uXVolSpace == m_regInputCropped.getUpperCorner().getX()); bool isPosXEdge = (uXVolSpace == m_regInputCropped.getUpperCorner().getX());
//Determine the index into the edge table which tells us which vertices are inside of the surface //Determine the index into the edge table which tells us which vertices are inside of the surface
uint8_t iCubeIndex = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace)]; uint8_t iCubeIndex = pCurrentBitmask.getElement(uXRegSpace,uYRegSpace);
/* Cube is entirely in/out of the surface */ /* Cube is entirely in/out of the surface */
if (edgeTable[iCubeIndex] == 0) if (edgeTable[iCubeIndex] == 0)
@ -483,7 +499,7 @@ namespace PolyVox
surfaceVertex.setOnGeometryEdgeNegZ(isNegZEdge); surfaceVertex.setOnGeometryEdgeNegZ(isNegZEdge);
surfaceVertex.setOnGeometryEdgePosZ(isPosZEdge); surfaceVertex.setOnGeometryEdgePosZ(isPosZEdge);
uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
m_pCurrentVertexIndicesX[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; m_pCurrentVertexIndicesX.setElement(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY(), uLastVertexIndex);
} }
if (edgeTable[iCubeIndex] & 8) if (edgeTable[iCubeIndex] & 8)
{ {
@ -501,7 +517,7 @@ namespace PolyVox
surfaceVertex.setOnGeometryEdgeNegZ(isNegZEdge); surfaceVertex.setOnGeometryEdgeNegZ(isNegZEdge);
surfaceVertex.setOnGeometryEdgePosZ(isPosZEdge); surfaceVertex.setOnGeometryEdgePosZ(isPosZEdge);
uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
m_pCurrentVertexIndicesY[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; m_pCurrentVertexIndicesY.setElement(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY(), uLastVertexIndex);
} }
if (edgeTable[iCubeIndex] & 256) if (edgeTable[iCubeIndex] & 256)
{ {
@ -519,13 +535,19 @@ namespace PolyVox
surfaceVertex.setOnGeometryEdgeNegZ(isNegZEdge); surfaceVertex.setOnGeometryEdgeNegZ(isNegZEdge);
surfaceVertex.setOnGeometryEdgePosZ(isPosZEdge); surfaceVertex.setOnGeometryEdgePosZ(isPosZEdge);
uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
m_pCurrentVertexIndicesZ[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; m_pCurrentVertexIndicesZ.setElement(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY(), uLastVertexIndex);
} }
}//For each cell }//For each cell
} }
} }
void SurfaceExtractor::generateIndicesForSlice() void SurfaceExtractor::generateIndicesForSlice(const Array2DUint8& pPreviousBitmask,
const Array2DInt32& m_pPreviousVertexIndicesX,
const Array2DInt32& m_pPreviousVertexIndicesY,
const Array2DInt32& m_pPreviousVertexIndicesZ,
const Array2DInt32& m_pCurrentVertexIndicesX,
const Array2DInt32& m_pCurrentVertexIndicesY,
const Array2DInt32& m_pCurrentVertexIndicesZ)
{ {
int32_t indlist[12]; int32_t indlist[12];
for(int i = 0; i < 12; i++) for(int i = 0; i < 12; i++)
@ -546,7 +568,7 @@ namespace PolyVox
const uint16_t uZRegSpace = m_sampVolume.getPosZ() - m_regInputCropped.getLowerCorner().getZ(); const uint16_t uZRegSpace = m_sampVolume.getPosZ() - m_regInputCropped.getLowerCorner().getZ();
//Determine the index into the edge table which tells us which vertices are inside of the surface //Determine the index into the edge table which tells us which vertices are inside of the surface
uint8_t iCubeIndex = m_pPreviousBitmask[getIndex(uXRegSpace,uYRegSpace)]; uint8_t iCubeIndex = pPreviousBitmask.getElement(uXRegSpace,uYRegSpace);
/* Cube is entirely in/out of the surface */ /* Cube is entirely in/out of the surface */
if (edgeTable[iCubeIndex] == 0) if (edgeTable[iCubeIndex] == 0)
@ -557,62 +579,62 @@ namespace PolyVox
/* Find the vertices where the surface intersects the cube */ /* Find the vertices where the surface intersects the cube */
if (edgeTable[iCubeIndex] & 1) if (edgeTable[iCubeIndex] & 1)
{ {
indlist[0] = m_pPreviousVertexIndicesX[getIndex(uXRegSpace,uYRegSpace)]; indlist[0] = m_pPreviousVertexIndicesX.getElement(uXRegSpace,uYRegSpace);
//assert(indlist[0] != -1); //assert(indlist[0] != -1);
} }
if (edgeTable[iCubeIndex] & 2) if (edgeTable[iCubeIndex] & 2)
{ {
indlist[1] = m_pPreviousVertexIndicesY[getIndex(uXRegSpace+1,uYRegSpace)]; indlist[1] = m_pPreviousVertexIndicesY.getElement(uXRegSpace+1,uYRegSpace);
//assert(indlist[1] != -1); //assert(indlist[1] != -1);
} }
if (edgeTable[iCubeIndex] & 4) if (edgeTable[iCubeIndex] & 4)
{ {
indlist[2] = m_pPreviousVertexIndicesX[getIndex(uXRegSpace,uYRegSpace+1)]; indlist[2] = m_pPreviousVertexIndicesX.getElement(uXRegSpace,uYRegSpace+1);
//assert(indlist[2] != -1); //assert(indlist[2] != -1);
} }
if (edgeTable[iCubeIndex] & 8) if (edgeTable[iCubeIndex] & 8)
{ {
indlist[3] = m_pPreviousVertexIndicesY[getIndex(uXRegSpace,uYRegSpace)]; indlist[3] = m_pPreviousVertexIndicesY.getElement(uXRegSpace,uYRegSpace);
//assert(indlist[3] != -1); //assert(indlist[3] != -1);
} }
if (edgeTable[iCubeIndex] & 16) if (edgeTable[iCubeIndex] & 16)
{ {
indlist[4] = m_pCurrentVertexIndicesX[getIndex(uXRegSpace,uYRegSpace)]; indlist[4] = m_pCurrentVertexIndicesX.getElement(uXRegSpace,uYRegSpace);
//assert(indlist[4] != -1); //assert(indlist[4] != -1);
} }
if (edgeTable[iCubeIndex] & 32) if (edgeTable[iCubeIndex] & 32)
{ {
indlist[5] = m_pCurrentVertexIndicesY[getIndex(uXRegSpace+1,uYRegSpace)]; indlist[5] = m_pCurrentVertexIndicesY.getElement(uXRegSpace+1,uYRegSpace);
//assert(indlist[5] != -1); //assert(indlist[5] != -1);
} }
if (edgeTable[iCubeIndex] & 64) if (edgeTable[iCubeIndex] & 64)
{ {
indlist[6] = m_pCurrentVertexIndicesX[getIndex(uXRegSpace,uYRegSpace+1)]; indlist[6] = m_pCurrentVertexIndicesX.getElement(uXRegSpace,uYRegSpace+1);
//assert(indlist[6] != -1); //assert(indlist[6] != -1);
} }
if (edgeTable[iCubeIndex] & 128) if (edgeTable[iCubeIndex] & 128)
{ {
indlist[7] = m_pCurrentVertexIndicesY[getIndex(uXRegSpace,uYRegSpace)]; indlist[7] = m_pCurrentVertexIndicesY.getElement(uXRegSpace,uYRegSpace);
//assert(indlist[7] != -1); //assert(indlist[7] != -1);
} }
if (edgeTable[iCubeIndex] & 256) if (edgeTable[iCubeIndex] & 256)
{ {
indlist[8] = m_pPreviousVertexIndicesZ[getIndex(uXRegSpace,uYRegSpace)]; indlist[8] = m_pPreviousVertexIndicesZ.getElement(uXRegSpace,uYRegSpace);
//assert(indlist[8] != -1); //assert(indlist[8] != -1);
} }
if (edgeTable[iCubeIndex] & 512) if (edgeTable[iCubeIndex] & 512)
{ {
indlist[9] = m_pPreviousVertexIndicesZ[getIndex(uXRegSpace+1,uYRegSpace)]; indlist[9] = m_pPreviousVertexIndicesZ.getElement(uXRegSpace+1,uYRegSpace);
//assert(indlist[9] != -1); //assert(indlist[9] != -1);
} }
if (edgeTable[iCubeIndex] & 1024) if (edgeTable[iCubeIndex] & 1024)
{ {
indlist[10] = m_pPreviousVertexIndicesZ[getIndex(uXRegSpace+1,uYRegSpace+1)]; indlist[10] = m_pPreviousVertexIndicesZ.getElement(uXRegSpace+1,uYRegSpace+1);
//assert(indlist[10] != -1); //assert(indlist[10] != -1);
} }
if (edgeTable[iCubeIndex] & 2048) if (edgeTable[iCubeIndex] & 2048)
{ {
indlist[11] = m_pPreviousVertexIndicesZ[getIndex(uXRegSpace,uYRegSpace+1)]; indlist[11] = m_pPreviousVertexIndicesZ.getElement(uXRegSpace,uYRegSpace+1);
//assert(indlist[11] != -1); //assert(indlist[11] != -1);
} }