From 1b76395856ceca484026595fba1f86db37c1908b Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 3 Apr 2009 21:37:37 +0000 Subject: [PATCH] Removed source folder which slipped through... --- .../source/PolyVoxCore/GradientEstimators.cpp | 125 ---- .../PolyVoxCore/IndexedSurfacePatch.cpp | 118 ---- .../PolyVoxImpl/DecimatedSurfaceExtractor.cpp | 595 ------------------ .../PolyVoxImpl/FastSurfaceExtractor.cpp | 543 ---------------- .../PolyVoxImpl/MarchingCubesTables.cpp | 326 ---------- .../PolyVoxImpl/ReferenceSurfaceExtractor.cpp | 334 ---------- .../PolyVoxCore/PolyVoxImpl/Utility.cpp | 63 -- library/source/PolyVoxCore/Region.cpp | 102 --- .../source/PolyVoxCore/SurfaceAdjusters.cpp | 150 ----- library/source/PolyVoxCore/SurfaceEdge.cpp | 106 ---- .../source/PolyVoxCore/SurfaceExtractors.cpp | 41 -- .../source/PolyVoxCore/SurfaceTriangle.cpp | 59 -- library/source/PolyVoxCore/SurfaceVertex.cpp | 82 --- library/source/PolyVoxCore/VoxelFilters.cpp | 51 -- library/source/PolyVoxUtil/Serialization.cpp | 184 ------ .../PolyVoxUtil/VolumeChangeTracker.cpp | 216 ------- 16 files changed, 3095 deletions(-) delete mode 100644 library/source/PolyVoxCore/GradientEstimators.cpp delete mode 100644 library/source/PolyVoxCore/IndexedSurfacePatch.cpp delete mode 100644 library/source/PolyVoxCore/PolyVoxImpl/DecimatedSurfaceExtractor.cpp delete mode 100644 library/source/PolyVoxCore/PolyVoxImpl/FastSurfaceExtractor.cpp delete mode 100644 library/source/PolyVoxCore/PolyVoxImpl/MarchingCubesTables.cpp delete mode 100644 library/source/PolyVoxCore/PolyVoxImpl/ReferenceSurfaceExtractor.cpp delete mode 100644 library/source/PolyVoxCore/PolyVoxImpl/Utility.cpp delete mode 100644 library/source/PolyVoxCore/Region.cpp delete mode 100644 library/source/PolyVoxCore/SurfaceAdjusters.cpp delete mode 100644 library/source/PolyVoxCore/SurfaceEdge.cpp delete mode 100644 library/source/PolyVoxCore/SurfaceExtractors.cpp delete mode 100644 library/source/PolyVoxCore/SurfaceTriangle.cpp delete mode 100644 library/source/PolyVoxCore/SurfaceVertex.cpp delete mode 100644 library/source/PolyVoxCore/VoxelFilters.cpp delete mode 100644 library/source/PolyVoxUtil/Serialization.cpp delete mode 100644 library/source/PolyVoxUtil/VolumeChangeTracker.cpp diff --git a/library/source/PolyVoxCore/GradientEstimators.cpp b/library/source/PolyVoxCore/GradientEstimators.cpp deleted file mode 100644 index 4b8c393f..00000000 --- a/library/source/PolyVoxCore/GradientEstimators.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "PolyVoxCore/GradientEstimators.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/SurfaceVertex.h" - -using namespace std; - -namespace PolyVox -{ - POLYVOX_API void computeNormalsForVertices(Volume* volumeData, IndexedSurfacePatch& isp, NormalGenerationMethod normalGenerationMethod) - { - std::vector& vecVertices = isp.getRawVertexData(); - std::vector::iterator iterSurfaceVertex = vecVertices.begin(); - while(iterSurfaceVertex != vecVertices.end()) - { - const Vector3DFloat& v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - const Vector3DInt32 v3dFloor = static_cast(v3dPos); - - VolumeIterator volIter(*volumeData); - - //Check all corners are within the volume, allowing a boundary for gradient estimation - bool lowerCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor,2); - bool upperCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor+Vector3DInt32(1,1,1),2); - - if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was - { - Vector3DFloat v3dGradient = computeNormal(volumeData, v3dPos, normalGenerationMethod); - - if(v3dGradient.lengthSquared() > 0.0001) - { - //If we got a normal of significant length then update it. - //Otherwise leave it as it was (should be the 'simple' version) - v3dGradient.normalise(); - iterSurfaceVertex->setNormal(v3dGradient); - } - } //(lowerCornerInside && upperCornerInside) - ++iterSurfaceVertex; - } - } - - Vector3DFloat computeNormal(Volume* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod) - { - Vector3DFloat v3dGradient; //To store the result - - VolumeIterator volIter(*volumeData); - - const Vector3DInt32 v3dFloor = static_cast(v3dPos); - - volIter.setPosition(static_cast(v3dFloor)); - Vector3DFloat gradFloor; - switch(normalGenerationMethod) - { - case SOBEL_SMOOTHED: - gradFloor = computeSmoothSobelGradient(volIter); - break; - case CENTRAL_DIFFERENCE_SMOOTHED: - gradFloor = computeSmoothCentralDifferenceGradient(volIter); - break; - case SOBEL: - gradFloor = computeSobelGradient(volIter); - break; - case CENTRAL_DIFFERENCE: - gradFloor = computeCentralDifferenceGradient(volIter); - break; - } - - if((v3dPos.getX() - v3dFloor.getX()) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(1,0,0))); - } - if((v3dPos.getY() - v3dFloor.getY()) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(0,1,0))); - } - if((v3dPos.getZ() - v3dFloor.getZ()) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(0,0,1))); - } - - Vector3DFloat gradCeil; - switch(normalGenerationMethod) - { - case SOBEL_SMOOTHED: - gradCeil = computeSmoothSobelGradient(volIter); - break; - case CENTRAL_DIFFERENCE_SMOOTHED: - gradCeil = computeSmoothCentralDifferenceGradient(volIter); - break; - case SOBEL: - gradCeil = computeSobelGradient(volIter); - break; - case CENTRAL_DIFFERENCE: - gradCeil = computeCentralDifferenceGradient(volIter); - break; - } - - v3dGradient = (gradFloor + gradCeil); - if(v3dGradient.lengthSquared() < 0.0001) - { - //Operation failed - fall back on simple gradient estimation - normalGenerationMethod = SIMPLE; - } - - if(normalGenerationMethod == SIMPLE) - { - volIter.setPosition(static_cast(v3dFloor)); - const uint8_t uFloor = volIter.getVoxel() > 0 ? 1 : 0; - if((v3dPos.getX() - v3dFloor.getX()) > 0.25) //The result should be 0.0 or 0.5 - { - uint8_t uCeil = volIter.peekVoxel1px0py0pz() > 0 ? 1 : 0; - v3dGradient = Vector3DFloat(static_cast(uFloor - uCeil),0.0,0.0); - } - else if((v3dPos.getY() - v3dFloor.getY()) > 0.25) //The result should be 0.0 or 0.5 - { - uint8_t uCeil = volIter.peekVoxel0px1py0pz() > 0 ? 1 : 0; - v3dGradient = Vector3DFloat(0.0,static_cast(uFloor - uCeil),0.0); - } - else if((v3dPos.getZ() - v3dFloor.getZ()) > 0.25) //The result should be 0.0 or 0.5 - { - uint8_t uCeil = volIter.peekVoxel0px0py1pz() > 0 ? 1 : 0; - v3dGradient = Vector3DFloat(0.0, 0.0,static_cast(uFloor - uCeil)); - } - } - return v3dGradient; - } -} diff --git a/library/source/PolyVoxCore/IndexedSurfacePatch.cpp b/library/source/PolyVoxCore/IndexedSurfacePatch.cpp deleted file mode 100644 index 78f58dd9..00000000 --- a/library/source/PolyVoxCore/IndexedSurfacePatch.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include "PolyVoxCore/IndexedSurfacePatch.h" - -using namespace std; - -namespace PolyVox -{ - IndexedSurfacePatch::IndexedSurfacePatch() - { - m_iTimeStamp = -1; - } - - IndexedSurfacePatch::~IndexedSurfacePatch() - { - } - - const std::vector& IndexedSurfacePatch::getIndices(void) const - { - return m_vecTriangleIndices; - } - - uint32_t IndexedSurfacePatch::getNoOfIndices(void) const - { - return m_vecTriangleIndices.size(); - } - - uint32_t IndexedSurfacePatch::getNoOfNonUniformTrianges(void) const - { - uint32_t result = 0; - for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) - { - if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) - && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) - { - } - else - { - result++; - } - } - return result; - } - - uint32_t IndexedSurfacePatch::getNoOfUniformTrianges(void) const - { - uint32_t result = 0; - for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) - { - if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) - && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) - { - result++; - } - } - return result; - } - - uint32_t IndexedSurfacePatch::getNoOfVertices(void) const - { - return m_vecVertices.size(); - } - - std::vector& IndexedSurfacePatch::getRawVertexData(void) - { - return m_vecVertices; - } - - const std::vector& IndexedSurfacePatch::getVertices(void) const - { - return m_vecVertices; - } - - void IndexedSurfacePatch::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) - { - m_vecTriangleIndices.push_back(index0); - m_vecTriangleIndices.push_back(index1); - m_vecTriangleIndices.push_back(index2); - } - - uint32_t IndexedSurfacePatch::addVertex(const SurfaceVertex& vertex) - { - m_vecVertices.push_back(vertex); - return m_vecVertices.size() - 1; - } - - void IndexedSurfacePatch::clear(void) - { - m_vecVertices.clear(); - m_vecTriangleIndices.clear(); - } - - const bool IndexedSurfacePatch::isEmpty(void) const - { - return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); - } - - -} diff --git a/library/source/PolyVoxCore/PolyVoxImpl/DecimatedSurfaceExtractor.cpp b/library/source/PolyVoxCore/PolyVoxImpl/DecimatedSurfaceExtractor.cpp deleted file mode 100644 index 96e21b6a..00000000 --- a/library/source/PolyVoxCore/PolyVoxImpl/DecimatedSurfaceExtractor.cpp +++ /dev/null @@ -1,595 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include "PolyVoxCore/PolyVoxImpl/DecimatedSurfaceExtractor.h" - -#include "PolyVoxCore/Volume.h" -#include "PolyVoxCore/GradientEstimators.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/PolyVoxImpl/MarchingCubesTables.h" -#include "PolyVoxCore/Region.h" -#include "PolyVoxCore/VolumeIterator.h" - -#include - -using namespace std; - -namespace PolyVox -{ - uint32_t getDecimatedIndex(uint32_t x, uint32_t y , uint32_t regionWidth) - { - return x + (y * (regionWidth+1)); - } - - void extractDecimatedSurfaceImpl(Volume* volumeData, uint8_t uLevel, Region region, IndexedSurfacePatch* singleMaterialPatch) - { - singleMaterialPatch->clear(); - - //For edge indices - //FIXME - do the slices need to be this big? Surely for a decimated mesh they can be smaller? - //FIXME - Instead of region.width()+2 we used to use POLYVOX_REGION_SIDE_LENGTH+1 - //Normally POLYVOX_REGION_SIDE_LENGTH is the same as region.width() (often 32) but at the - //edges of the volume it is 1 smaller. Need to think what values really belong here. - int32_t* vertexIndicesX0 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesY0 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesZ0 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesX1 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesY1 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesZ1 = new int32_t[(region.width()+2) * (region.height()+2)]; - - //Cell bitmasks - uint8_t* bitmask0 = new uint8_t[(region.width()+2) * (region.height()+2)]; - uint8_t* bitmask1 = new uint8_t[(region.width()+2) * (region.height()+2)]; - - const uint8_t uStepSize = uLevel == 0 ? 1 : 1 << uLevel; - - //When generating the mesh for a region we actually look outside it in the - // back, bottom, right direction. Protect against access violations by cropping region here - Region regVolume = volumeData->getEnclosingRegion(); - regVolume.setUpperCorner(regVolume.getUpperCorner() - Vector3DInt32(2*uStepSize-1,2*uStepSize-1,2*uStepSize-1)); - region.cropTo(regVolume); - - //Offset from volume corner - const Vector3DFloat offset = static_cast(region.getLowerCorner()); - - //Create a region corresponding to the first slice - Region regSlice0(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); - - //Iterator to access the volume data - VolumeIterator volIter(*volumeData); - - //Compute bitmask for initial slice - uint32_t uNoOfNonEmptyCellsForSlice0 = computeInitialDecimatedBitmaskForSlice(volIter, uLevel, regSlice0, offset, bitmask0); - if(uNoOfNonEmptyCellsForSlice0 != 0) - { - //If there were some non-empty cells then generate initial slice vertices for them - generateDecimatedVerticesForSlice(volIter, uLevel, regSlice0, offset, bitmask0, singleMaterialPatch, vertexIndicesX0, vertexIndicesY0, vertexIndicesZ0); - } - - for(uint32_t uSlice = 1; ((uSlice <= region.depth()) && (uSlice + offset.getZ() <= regVolume.getUpperCorner().getZ())); uSlice += uStepSize) - { - Region regSlice1(regSlice0); - regSlice1.shift(Vector3DInt32(0,0,uStepSize)); - - uint32_t uNoOfNonEmptyCellsForSlice1 = computeDecimatedBitmaskForSliceFromPrevious(volIter, uLevel, regSlice1, offset, bitmask1, bitmask0); - - if(uNoOfNonEmptyCellsForSlice1 != 0) - { - generateDecimatedVerticesForSlice(volIter, uLevel, regSlice1, offset, bitmask1, singleMaterialPatch, vertexIndicesX1, vertexIndicesY1, vertexIndicesZ1); - } - - if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0)) - { - generateDecimatedIndicesForSlice(volIter, uLevel, regSlice0, singleMaterialPatch, offset, bitmask0, bitmask1, vertexIndicesX0, vertexIndicesY0, vertexIndicesZ0, vertexIndicesX1, vertexIndicesY1, vertexIndicesZ1); - } - - std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1); - std::swap(bitmask0, bitmask1); - std::swap(vertexIndicesX0, vertexIndicesX1); - std::swap(vertexIndicesY0, vertexIndicesY1); - std::swap(vertexIndicesZ0, vertexIndicesZ1); - - regSlice0 = regSlice1; - } - - delete[] bitmask0; - delete[] bitmask1; - delete[] vertexIndicesX0; - delete[] vertexIndicesX1; - delete[] vertexIndicesY0; - delete[] vertexIndicesY1; - delete[] vertexIndicesZ0; - delete[] vertexIndicesZ1; - - - /*std::vector::iterator iterSurfaceVertex = singleMaterialPatch->getVertices().begin(); - while(iterSurfaceVertex != singleMaterialPatch->getVertices().end()) - { - Vector3DFloat tempNormal = computeDecimatedNormal(volumeData, static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); - const_cast(*iterSurfaceVertex).setNormal(tempNormal); - ++iterSurfaceVertex; - }*/ - } - - uint32_t computeInitialDecimatedBitmaskForSlice(VolumeIterator& volIter, uint8_t uLevel, const Region& regSlice, const Vector3DFloat& offset, uint8_t* bitmask) - { - const uint8_t uStepSize = uLevel == 0 ? 1 : 1 << uLevel; - uint32_t uNoOfNonEmptyCells = 0; - - //Iterate over each cell in the region - for(uint16_t y = regSlice.getLowerCorner().getY(); y <= regSlice.getUpperCorner().getY(); y += uStepSize) - { - for(uint16_t x = regSlice.getLowerCorner().getX(); x <= regSlice.getUpperCorner().getX(); x += uStepSize) - { - //Current position - volIter.setPosition(x,y,regSlice.getLowerCorner().getZ()); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = 0; - - if((x==regSlice.getLowerCorner().getX()) && (y==regSlice.getLowerCorner().getY())) - { - volIter.setPosition(x,y,regSlice.getLowerCorner().getZ()); - const uint8_t v000 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y,regSlice.getLowerCorner().getZ()); - const uint8_t v100 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x,y+uStepSize,regSlice.getLowerCorner().getZ()); - const uint8_t v010 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()); - const uint8_t v110 = volIter.getSubSampledVoxel(uLevel); - - volIter.setPosition(x,y,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v001 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v101 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v011 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - if (v000 == 0) iCubeIndex |= 1; - if (v100 == 0) iCubeIndex |= 2; - if (v110 == 0) iCubeIndex |= 4; - if (v010 == 0) iCubeIndex |= 8; - if (v001 == 0) iCubeIndex |= 16; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else if((x>regSlice.getLowerCorner().getX()) && y==regSlice.getLowerCorner().getY()) - { - volIter.setPosition(x+uStepSize,y,regSlice.getLowerCorner().getZ()); - const uint8_t v100 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()); - const uint8_t v110 = volIter.getSubSampledVoxel(uLevel); - - volIter.setPosition(x+uStepSize,y,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v101 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //x - uint8_t iPreviousCubeIndexX = bitmask[getDecimatedIndex(x- offset.getX()-uStepSize,y- offset.getY(), regSlice.width()+1)]; - uint8_t srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - uint8_t srcBit5 = iPreviousCubeIndexX & 32; - uint8_t destBit4 = srcBit5 >> 1; - - uint8_t srcBit2 = iPreviousCubeIndexX & 4; - uint8_t destBit3 = srcBit2 << 1; - - uint8_t srcBit1 = iPreviousCubeIndexX & 2; - uint8_t destBit0 = srcBit1 >> 1; - - iCubeIndex |= destBit0; - if (v100 == 0) iCubeIndex |= 2; - if (v110 == 0) iCubeIndex |= 4; - iCubeIndex |= destBit3; - iCubeIndex |= destBit4; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - else if((x==regSlice.getLowerCorner().getX()) && (y>regSlice.getLowerCorner().getY())) - { - volIter.setPosition(x,y+uStepSize,regSlice.getLowerCorner().getZ()); - const uint8_t v010 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()); - const uint8_t v110 = volIter.getSubSampledVoxel(uLevel); - - volIter.setPosition(x,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v011 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //y - uint8_t iPreviousCubeIndexY = bitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY()-uStepSize, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - uint8_t srcBit3 = iPreviousCubeIndexY & 8; - uint8_t destBit0 = srcBit3 >> 3; - - uint8_t srcBit2 = iPreviousCubeIndexY & 4; - uint8_t destBit1 = srcBit2 >> 1; - - iCubeIndex |= destBit0; - iCubeIndex |= destBit1; - if (v110 == 0) iCubeIndex |= 4; - if (v010 == 0) iCubeIndex |= 8; - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else - { - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()); - const uint8_t v110 = volIter.getSubSampledVoxel(uLevel); - - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //y - uint8_t iPreviousCubeIndexY = bitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY()-uStepSize, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - uint8_t srcBit3 = iPreviousCubeIndexY & 8; - uint8_t destBit0 = srcBit3 >> 3; - - uint8_t srcBit2 = iPreviousCubeIndexY & 4; - uint8_t destBit1 = srcBit2 >> 1; - - //x - uint8_t iPreviousCubeIndexX = bitmask[getDecimatedIndex(x- offset.getX()-uStepSize,y- offset.getY(), regSlice.width()+1)]; - srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - srcBit2 = iPreviousCubeIndexX & 4; - uint8_t destBit3 = srcBit2 << 1; - - iCubeIndex |= destBit0; - iCubeIndex |= destBit1; - if (v110 == 0) iCubeIndex |= 4; - iCubeIndex |= destBit3; - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - - //Save the bitmask - bitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY(), regSlice.width()+1)] = iCubeIndex; - - if(edgeTable[iCubeIndex] != 0) - { - ++uNoOfNonEmptyCells; - } - - } - } - - return uNoOfNonEmptyCells; - } - - uint32_t computeDecimatedBitmaskForSliceFromPrevious(VolumeIterator& volIter, uint8_t uLevel, const Region& regSlice, const Vector3DFloat& offset, uint8_t* bitmask, uint8_t* previousBitmask) - { - const uint8_t uStepSize = uLevel == 0 ? 1 : 1 << uLevel; - uint32_t uNoOfNonEmptyCells = 0; - - //Iterate over each cell in the region - for(uint16_t y = regSlice.getLowerCorner().getY(); y <= regSlice.getUpperCorner().getY(); y += uStepSize) - { - for(uint16_t x = regSlice.getLowerCorner().getX(); x <= regSlice.getUpperCorner().getX(); x += uStepSize) - { - //Current position - volIter.setPosition(x,y,regSlice.getLowerCorner().getZ()); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = 0; - - if((x==regSlice.getLowerCorner().getX()) && (y==regSlice.getLowerCorner().getY())) - { - volIter.setPosition(x,y,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v001 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v101 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v011 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY(), regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - if (v001 == 0) iCubeIndex |= 16; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else if((x>regSlice.getLowerCorner().getX()) && y==regSlice.getLowerCorner().getY()) - { - volIter.setPosition(x+uStepSize,y,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v101 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY(), regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - //x - uint8_t iPreviousCubeIndexX = bitmask[getDecimatedIndex(x- offset.getX()-uStepSize,y- offset.getY(), regSlice.width()+1)]; - uint8_t srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - uint8_t srcBit5 = iPreviousCubeIndexX & 32; - uint8_t destBit4 = srcBit5 >> 1; - - iCubeIndex |= destBit4; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - else if((x==regSlice.getLowerCorner().getX()) && (y>regSlice.getLowerCorner().getY())) - { - volIter.setPosition(x,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v011 = volIter.getSubSampledVoxel(uLevel); - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY(), regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - //y - uint8_t iPreviousCubeIndexY = bitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY()-uStepSize, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else - { - volIter.setPosition(x+uStepSize,y+uStepSize,regSlice.getLowerCorner().getZ()+uStepSize); - const uint8_t v111 = volIter.getSubSampledVoxel(uLevel); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY(), regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - //y - uint8_t iPreviousCubeIndexY = bitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY()-uStepSize, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - //x - uint8_t iPreviousCubeIndexX = bitmask[getDecimatedIndex(x- offset.getX()-uStepSize,y- offset.getY(), regSlice.width()+1)]; - srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - - //Save the bitmask - bitmask[getDecimatedIndex(x- offset.getX(),y- offset.getY(), regSlice.width()+1)] = iCubeIndex; - - if(edgeTable[iCubeIndex] != 0) - { - ++uNoOfNonEmptyCells; - } - - }//For each cell - } - - return uNoOfNonEmptyCells; - } - - void generateDecimatedVerticesForSlice(VolumeIterator& volIter, uint8_t uLevel, Region& regSlice, const Vector3DFloat& offset, uint8_t* bitmask, IndexedSurfacePatch* singleMaterialPatch,int32_t vertexIndicesX[],int32_t vertexIndicesY[],int32_t vertexIndicesZ[]) - { - const uint8_t uStepSize = uLevel == 0 ? 1 : 1 << uLevel; - - //Iterate over each cell in the region - for(uint16_t y = regSlice.getLowerCorner().getY(); y <= regSlice.getUpperCorner().getY(); y += uStepSize) - { - for(uint16_t x = regSlice.getLowerCorner().getX(); x <= regSlice.getUpperCorner().getX(); x += uStepSize) - { - //Current position - const uint16_t z = regSlice.getLowerCorner().getZ(); - - volIter.setPosition(x,y,z); - const uint8_t v000 = volIter.getSubSampledVoxel(uLevel); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = bitmask[getDecimatedIndex(x - offset.getX(),y - offset.getY(), regSlice.width()+1)]; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - if(x != regSlice.getUpperCorner().getX()) - { - volIter.setPosition(x + uStepSize,y,z); - const uint8_t v100 = volIter.getSubSampledVoxel(uLevel); - const Vector3DFloat v3dPosition(x - offset.getX() + 0.5f * uStepSize, y - offset.getY(), z - offset.getZ()); - const Vector3DFloat v3dNormal(v000 > v100 ? 1.0f : -1.0f,0.0,0.0); - const uint8_t uMaterial = v000 | v100; //Because one of these is 0, the or operation takes the max. - SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = singleMaterialPatch->addVertex(surfaceVertex); - vertexIndicesX[getDecimatedIndex(x - offset.getX(),y - offset.getY(), regSlice.width()+1)] = uLastVertexIndex; - } - } - if (edgeTable[iCubeIndex] & 8) - { - if(y != regSlice.getUpperCorner().getY()) - { - volIter.setPosition(x,y + uStepSize,z); - const uint8_t v010 = volIter.getSubSampledVoxel(uLevel); - const Vector3DFloat v3dPosition(x - offset.getX(), y - offset.getY() + 0.5f * uStepSize, z - offset.getZ()); - const Vector3DFloat v3dNormal(0.0,v000 > v010 ? 1.0f : -1.0f,0.0); - const uint8_t uMaterial = v000 | v010; //Because one of these is 0, the or operation takes the max. - SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = singleMaterialPatch->addVertex(surfaceVertex); - vertexIndicesY[getDecimatedIndex(x - offset.getX(),y - offset.getY(), regSlice.width()+1)] = uLastVertexIndex; - } - } - if (edgeTable[iCubeIndex] & 256) - { - //if(z != regSlice.getUpperCorner.getZ()) - { - volIter.setPosition(x,y,z + uStepSize); - const uint8_t v001 = volIter.getSubSampledVoxel(uLevel); - const Vector3DFloat v3dPosition(x - offset.getX(), y - offset.getY(), z - offset.getZ() + 0.5f * uStepSize); - const Vector3DFloat v3dNormal(0.0,0.0,v000 > v001 ? 1.0f : -1.0f); - const uint8_t uMaterial = v000 | v001; //Because one of these is 0, the or operation takes the max. - const SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = singleMaterialPatch->addVertex(surfaceVertex); - vertexIndicesZ[getDecimatedIndex(x - offset.getX(),y - offset.getY(), regSlice.width()+1)] = uLastVertexIndex; - } - } - }//For each cell - } - } - - void generateDecimatedIndicesForSlice(VolumeIterator& volIter, uint8_t uLevel, const Region& regSlice, IndexedSurfacePatch* singleMaterialPatch, const Vector3DFloat& offset, uint8_t* bitmask0, uint8_t* bitmask1, int32_t vertexIndicesX0[],int32_t vertexIndicesY0[],int32_t vertexIndicesZ0[], int32_t vertexIndicesX1[],int32_t vertexIndicesY1[],int32_t vertexIndicesZ1[]) - { - const uint8_t uStepSize = uLevel == 0 ? 1 : 1 << uLevel; - uint32_t indlist[12]; - - for(uint16_t y = regSlice.getLowerCorner().getY() - offset.getY(); y < regSlice.getUpperCorner().getY() - offset.getY(); y += uStepSize) - { - for(uint16_t x = regSlice.getLowerCorner().getX() - offset.getX(); x < regSlice.getUpperCorner().getX() - offset.getX(); x += uStepSize) - { - //Current position - const uint16_t z = regSlice.getLowerCorner().getZ() - offset.getZ(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = bitmask0[getDecimatedIndex(x,y, regSlice.width()+1)]; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - indlist[0] = vertexIndicesX0[getDecimatedIndex(x,y, regSlice.width()+1)]; - assert(indlist[0] != -1); - } - if (edgeTable[iCubeIndex] & 2) - { - indlist[1] = vertexIndicesY0[getDecimatedIndex(x+uStepSize,y, regSlice.width()+1)]; - assert(indlist[1] != -1); - } - if (edgeTable[iCubeIndex] & 4) - { - indlist[2] = vertexIndicesX0[getDecimatedIndex(x,y+uStepSize, regSlice.width()+1)]; - assert(indlist[2] != -1); - } - if (edgeTable[iCubeIndex] & 8) - { - indlist[3] = vertexIndicesY0[getDecimatedIndex(x,y, regSlice.width()+1)]; - assert(indlist[3] != -1); - } - if (edgeTable[iCubeIndex] & 16) - { - indlist[4] = vertexIndicesX1[getDecimatedIndex(x,y, regSlice.width()+1)]; - assert(indlist[4] != -1); - } - if (edgeTable[iCubeIndex] & 32) - { - indlist[5] = vertexIndicesY1[getDecimatedIndex(x+uStepSize,y, regSlice.width()+1)]; - assert(indlist[5] != -1); - } - if (edgeTable[iCubeIndex] & 64) - { - indlist[6] = vertexIndicesX1[getDecimatedIndex(x,y+uStepSize, regSlice.width()+1)]; - assert(indlist[6] != -1); - } - if (edgeTable[iCubeIndex] & 128) - { - indlist[7] = vertexIndicesY1[getDecimatedIndex(x,y, regSlice.width()+1)]; - assert(indlist[7] != -1); - } - if (edgeTable[iCubeIndex] & 256) - { - indlist[8] = vertexIndicesZ0[getDecimatedIndex(x,y, regSlice.width()+1)]; - assert(indlist[8] != -1); - } - if (edgeTable[iCubeIndex] & 512) - { - indlist[9] = vertexIndicesZ0[getDecimatedIndex(x+uStepSize,y, regSlice.width()+1)]; - assert(indlist[9] != -1); - } - if (edgeTable[iCubeIndex] & 1024) - { - indlist[10] = vertexIndicesZ0[getDecimatedIndex(x+uStepSize,y+uStepSize, regSlice.width()+1)]; - assert(indlist[10] != -1); - } - if (edgeTable[iCubeIndex] & 2048) - { - indlist[11] = vertexIndicesZ0[getDecimatedIndex(x,y+uStepSize, regSlice.width()+1)]; - assert(indlist[11] != -1); - } - - for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) - { - uint32_t ind0 = indlist[triTable[iCubeIndex][i ]]; - uint32_t ind1 = indlist[triTable[iCubeIndex][i+1]]; - uint32_t ind2 = indlist[triTable[iCubeIndex][i+2]]; - - singleMaterialPatch->addTriangle(ind0, ind1, ind2); - }//For each triangle - }//For each cell - } - } -} diff --git a/library/source/PolyVoxCore/PolyVoxImpl/FastSurfaceExtractor.cpp b/library/source/PolyVoxCore/PolyVoxImpl/FastSurfaceExtractor.cpp deleted file mode 100644 index b65960de..00000000 --- a/library/source/PolyVoxCore/PolyVoxImpl/FastSurfaceExtractor.cpp +++ /dev/null @@ -1,543 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include "PolyVoxCore/PolyVoxImpl/FastSurfaceExtractor.h" - -#include "PolyVoxCore/VolumeIterator.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/PolyVoxImpl/MarchingCubesTables.h" -#include "PolyVoxCore/SurfaceVertex.h" - -namespace PolyVox -{ - - void extractFastSurfaceImpl(Volume* volumeData, Region region, IndexedSurfacePatch* singleMaterialPatch) - { - singleMaterialPatch->clear(); - - //For edge indices - int32_t* vertexIndicesX0 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesY0 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesZ0 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesX1 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesY1 = new int32_t[(region.width()+2) * (region.height()+2)]; - int32_t* vertexIndicesZ1 = new int32_t[(region.width()+2) * (region.height()+2)]; - - //Cell bitmasks - uint8_t* bitmask0 = new uint8_t[(region.width()+2) * (region.height()+2)]; - uint8_t* bitmask1 = new uint8_t[(region.width()+2) * (region.height()+2)]; - - //When generating the mesh for a region we actually look one voxel outside it in the - // back, bottom, right direction. Protect against access violations by cropping region here - Region regVolume = volumeData->getEnclosingRegion(); - regVolume.setUpperCorner(regVolume.getUpperCorner() - Vector3DInt32(1,1,1)); - region.cropTo(regVolume); - - //Offset from volume corner - const Vector3DFloat offset = static_cast(region.getLowerCorner()); - - //Create a region corresponding to the first slice - Region regSlice0(region); - regSlice0.setUpperCorner(Vector3DInt32(regSlice0.getUpperCorner().getX(),regSlice0.getUpperCorner().getY(),regSlice0.getLowerCorner().getZ())); - - //Iterator to access the volume data - VolumeIterator volIter(*volumeData); - - //Compute bitmask for initial slice - uint32_t uNoOfNonEmptyCellsForSlice0 = computeInitialRoughBitmaskForSlice(volIter, regSlice0, offset, bitmask0); - if(uNoOfNonEmptyCellsForSlice0 != 0) - { - //If there were some non-empty cells then generate initial slice vertices for them - generateRoughVerticesForSlice(volIter,regSlice0, offset, bitmask0, singleMaterialPatch, vertexIndicesX0, vertexIndicesY0, vertexIndicesZ0); - } - - for(uint32_t uSlice = 0; ((uSlice <= region.depth()-1) && (uSlice + offset.getZ() < region.getUpperCorner().getZ())); ++uSlice) - { - Region regSlice1(regSlice0); - regSlice1.shift(Vector3DInt32(0,0,1)); - - uint32_t uNoOfNonEmptyCellsForSlice1 = computeRoughBitmaskForSliceFromPrevious(volIter, regSlice1, offset, bitmask1, bitmask0); - - if(uNoOfNonEmptyCellsForSlice1 != 0) - { - generateRoughVerticesForSlice(volIter,regSlice1, offset, bitmask1, singleMaterialPatch, vertexIndicesX1, vertexIndicesY1, vertexIndicesZ1); - } - - if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0)) - { - generateRoughIndicesForSlice(volIter, regSlice0, singleMaterialPatch, offset, bitmask0, bitmask1, vertexIndicesX0, vertexIndicesY0, vertexIndicesZ0, vertexIndicesX1, vertexIndicesY1, vertexIndicesZ1); - } - - std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1); - std::swap(bitmask0, bitmask1); - std::swap(vertexIndicesX0, vertexIndicesX1); - std::swap(vertexIndicesY0, vertexIndicesY1); - std::swap(vertexIndicesZ0, vertexIndicesZ1); - - regSlice0 = regSlice1; - } - - delete[] bitmask0; - delete[] bitmask1; - delete[] vertexIndicesX0; - delete[] vertexIndicesX1; - delete[] vertexIndicesY0; - delete[] vertexIndicesY1; - delete[] vertexIndicesZ0; - delete[] vertexIndicesZ1; - } - - uint32_t getIndex(uint32_t x, uint32_t y, uint32_t regionWidth) - { - return x + (y * (regionWidth+1)); - } - - uint32_t computeInitialRoughBitmaskForSlice(VolumeIterator& volIter, const Region& regSlice, const Vector3DFloat& offset, uint8_t* bitmask) - { - uint32_t uNoOfNonEmptyCells = 0; - - //Iterate over each cell in the region - volIter.setPosition(regSlice.getLowerCorner().getX(),regSlice.getLowerCorner().getY(), regSlice.getLowerCorner().getZ()); - volIter.setValidRegion(regSlice); - do - { - //Current position - const uint16_t x = volIter.getPosX() - offset.getX(); - const uint16_t y = volIter.getPosY() - offset.getY(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = 0; - - if((x==0) && (y==0)) - { - const uint8_t v000 = volIter.getVoxel(); - const uint8_t v100 = volIter.peekVoxel1px0py0pz(); - const uint8_t v010 = volIter.peekVoxel0px1py0pz(); - const uint8_t v110 = volIter.peekVoxel1px1py0pz(); - - const uint8_t v001 = volIter.peekVoxel0px0py1pz(); - const uint8_t v101 = volIter.peekVoxel1px0py1pz(); - const uint8_t v011 = volIter.peekVoxel0px1py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - if (v000 == 0) iCubeIndex |= 1; - if (v100 == 0) iCubeIndex |= 2; - if (v110 == 0) iCubeIndex |= 4; - if (v010 == 0) iCubeIndex |= 8; - if (v001 == 0) iCubeIndex |= 16; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else if((x>0) && y==0) - { - const uint8_t v100 = volIter.peekVoxel1px0py0pz(); - const uint8_t v110 = volIter.peekVoxel1px1py0pz(); - - const uint8_t v101 = volIter.peekVoxel1px0py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //x - uint8_t iPreviousCubeIndexX = bitmask[getIndex(x-1,y, regSlice.width()+1)]; - uint8_t srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - uint8_t srcBit5 = iPreviousCubeIndexX & 32; - uint8_t destBit4 = srcBit5 >> 1; - - uint8_t srcBit2 = iPreviousCubeIndexX & 4; - uint8_t destBit3 = srcBit2 << 1; - - uint8_t srcBit1 = iPreviousCubeIndexX & 2; - uint8_t destBit0 = srcBit1 >> 1; - - iCubeIndex |= destBit0; - if (v100 == 0) iCubeIndex |= 2; - if (v110 == 0) iCubeIndex |= 4; - iCubeIndex |= destBit3; - iCubeIndex |= destBit4; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - else if((x==0) && (y>0)) - { - const uint8_t v010 = volIter.peekVoxel0px1py0pz(); - const uint8_t v110 = volIter.peekVoxel1px1py0pz(); - - const uint8_t v011 = volIter.peekVoxel0px1py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //y - uint8_t iPreviousCubeIndexY = bitmask[getIndex(x,y-1, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - uint8_t srcBit3 = iPreviousCubeIndexY & 8; - uint8_t destBit0 = srcBit3 >> 3; - - uint8_t srcBit2 = iPreviousCubeIndexY & 4; - uint8_t destBit1 = srcBit2 >> 1; - - iCubeIndex |= destBit0; - iCubeIndex |= destBit1; - if (v110 == 0) iCubeIndex |= 4; - if (v010 == 0) iCubeIndex |= 8; - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else - { - const uint8_t v110 = volIter.peekVoxel1px1py0pz(); - - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //y - uint8_t iPreviousCubeIndexY = bitmask[getIndex(x,y-1, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - uint8_t srcBit3 = iPreviousCubeIndexY & 8; - uint8_t destBit0 = srcBit3 >> 3; - - uint8_t srcBit2 = iPreviousCubeIndexY & 4; - uint8_t destBit1 = srcBit2 >> 1; - - //x - uint8_t iPreviousCubeIndexX = bitmask[getIndex(x-1,y, regSlice.width()+1)]; - srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - srcBit2 = iPreviousCubeIndexX & 4; - uint8_t destBit3 = srcBit2 << 1; - - iCubeIndex |= destBit0; - iCubeIndex |= destBit1; - if (v110 == 0) iCubeIndex |= 4; - iCubeIndex |= destBit3; - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - - //Save the bitmask - bitmask[getIndex(x,y, regSlice.width()+1)] = iCubeIndex; - - if(edgeTable[iCubeIndex] != 0) - { - ++uNoOfNonEmptyCells; - } - - }while(volIter.moveForwardInRegionXYZ());//For each cell - - return uNoOfNonEmptyCells; - } - - uint32_t computeRoughBitmaskForSliceFromPrevious(VolumeIterator& volIter, const Region& regSlice, const Vector3DFloat& offset, uint8_t* bitmask, uint8_t* previousBitmask) - { - uint32_t uNoOfNonEmptyCells = 0; - - //Iterate over each cell in the region - volIter.setPosition(regSlice.getLowerCorner().getX(),regSlice.getLowerCorner().getY(), regSlice.getLowerCorner().getZ()); - volIter.setValidRegion(regSlice); - do - { - //Current position - const uint16_t x = volIter.getPosX() - offset.getX(); - const uint16_t y = volIter.getPosY() - offset.getY(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = 0; - - if((x==0) && (y==0)) - { - const uint8_t v001 = volIter.peekVoxel0px0py1pz(); - const uint8_t v101 = volIter.peekVoxel1px0py1pz(); - const uint8_t v011 = volIter.peekVoxel0px1py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getIndex(x,y, regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - if (v001 == 0) iCubeIndex |= 16; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else if((x>0) && y==0) - { - const uint8_t v101 = volIter.peekVoxel1px0py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getIndex(x,y, regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - //x - uint8_t iPreviousCubeIndexX = bitmask[getIndex(x-1,y, regSlice.width()+1)]; - uint8_t srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - uint8_t srcBit5 = iPreviousCubeIndexX & 32; - uint8_t destBit4 = srcBit5 >> 1; - - iCubeIndex |= destBit4; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - else if((x==0) && (y>0)) - { - const uint8_t v011 = volIter.peekVoxel0px1py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getIndex(x,y, regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - //y - uint8_t iPreviousCubeIndexY = bitmask[getIndex(x,y-1, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - } - else - { - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = previousBitmask[getIndex(x,y, regSlice.width()+1)]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - //y - uint8_t iPreviousCubeIndexY = bitmask[getIndex(x,y-1, regSlice.width()+1)]; - uint8_t srcBit7 = iPreviousCubeIndexY & 128; - uint8_t destBit4 = srcBit7 >> 3; - - uint8_t srcBit6 = iPreviousCubeIndexY & 64; - uint8_t destBit5 = srcBit6 >> 1; - - //x - uint8_t iPreviousCubeIndexX = bitmask[getIndex(x-1,y, regSlice.width()+1)]; - srcBit6 = iPreviousCubeIndexX & 64; - uint8_t destBit7 = srcBit6 << 1; - - iCubeIndex |= destBit4; - iCubeIndex |= destBit5; - if (v111 == 0) iCubeIndex |= 64; - iCubeIndex |= destBit7; - } - - //Save the bitmask - bitmask[getIndex(x,y, regSlice.width()+1)] = iCubeIndex; - - if(edgeTable[iCubeIndex] != 0) - { - ++uNoOfNonEmptyCells; - } - - }while(volIter.moveForwardInRegionXYZ());//For each cell - - return uNoOfNonEmptyCells; - } - - void generateRoughVerticesForSlice(VolumeIterator& volIter, Region& regSlice, const Vector3DFloat& offset, uint8_t* bitmask, IndexedSurfacePatch* singleMaterialPatch,int32_t vertexIndicesX[],int32_t vertexIndicesY[],int32_t vertexIndicesZ[]) - { - //Iterate over each cell in the region - volIter.setPosition(regSlice.getLowerCorner().getX(),regSlice.getLowerCorner().getY(), regSlice.getLowerCorner().getZ()); - volIter.setValidRegion(regSlice); - //while(volIter.moveForwardInRegionXYZ()) - do - { - //Current position - const uint16_t x = volIter.getPosX() - offset.getX(); - const uint16_t y = volIter.getPosY() - offset.getY(); - const uint16_t z = volIter.getPosZ() - offset.getZ(); - - const uint8_t v000 = volIter.getVoxel(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = bitmask[getIndex(x,y, regSlice.width()+1)]; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - if((x + offset.getX()) != regSlice.getUpperCorner().getX()) - { - const uint8_t v100 = volIter.peekVoxel1px0py0pz(); - const Vector3DFloat v3dPosition(x + 0.5f, y, z); - const Vector3DFloat v3dNormal(v000 > v100 ? 1.0f : -1.0f, 0.0f, 0.0f); - const uint8_t uMaterial = v000 | v100; //Because one of these is 0, the or operation takes the max. - const SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = singleMaterialPatch->addVertex(surfaceVertex); - vertexIndicesX[getIndex(x,y, regSlice.width()+1)] = uLastVertexIndex; - } - } - if (edgeTable[iCubeIndex] & 8) - { - if((y + offset.getY()) != regSlice.getUpperCorner().getY()) - { - const uint8_t v010 = volIter.peekVoxel0px1py0pz(); - const Vector3DFloat v3dPosition(x, y + 0.5f, z); - const Vector3DFloat v3dNormal(0.0f, v000 > v010 ? 1.0f : -1.0f, 0.0f); - const uint8_t uMaterial = v000 | v010; - SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = singleMaterialPatch->addVertex(surfaceVertex); - vertexIndicesY[getIndex(x,y, regSlice.width()+1)] = uLastVertexIndex; - } - } - if (edgeTable[iCubeIndex] & 256) - { - //if((z + offset.getZ()) != upperCorner.getZ()) - { - const uint8_t v001 = volIter.peekVoxel0px0py1pz(); - const Vector3DFloat v3dPosition(x, y, z + 0.5f); - const Vector3DFloat v3dNormal(0.0f, 0.0f, v000 > v001 ? 1.0f : -1.0f); - const uint8_t uMaterial = v000 | v001; - SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = singleMaterialPatch->addVertex(surfaceVertex); - vertexIndicesZ[getIndex(x,y, regSlice.width()+1)] = uLastVertexIndex; - } - } - }while(volIter.moveForwardInRegionXYZ());//For each cell - } - - void generateRoughIndicesForSlice(VolumeIterator& volIter, const Region& regSlice, IndexedSurfacePatch* singleMaterialPatch, const Vector3DFloat& offset, uint8_t* bitmask0, uint8_t* bitmask1, int32_t vertexIndicesX0[],int32_t vertexIndicesY0[],int32_t vertexIndicesZ0[], int32_t vertexIndicesX1[],int32_t vertexIndicesY1[],int32_t vertexIndicesZ1[]) - { - uint32_t indlist[12]; - - Region regCroppedSlice(regSlice); - regCroppedSlice.setUpperCorner(regCroppedSlice.getUpperCorner() - Vector3DInt32(1,1,0)); - - volIter.setPosition(regCroppedSlice.getLowerCorner().getX(),regCroppedSlice.getLowerCorner().getY(), regCroppedSlice.getLowerCorner().getZ()); - volIter.setValidRegion(regCroppedSlice); - do - { - //Current position - const uint16_t x = volIter.getPosX() - offset.getX(); - const uint16_t y = volIter.getPosY() - offset.getY(); - const uint16_t z = volIter.getPosZ() - offset.getZ(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = bitmask0[getIndex(x,y, regSlice.width()+1)]; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - indlist[0] = vertexIndicesX0[getIndex(x,y, regSlice.width()+1)]; - assert(indlist[0] != -1); - } - if (edgeTable[iCubeIndex] & 2) - { - indlist[1] = vertexIndicesY0[getIndex(x+1,y, regSlice.width()+1)]; - assert(indlist[1] != -1); - } - if (edgeTable[iCubeIndex] & 4) - { - indlist[2] = vertexIndicesX0[getIndex(x,y+1, regSlice.width()+1)]; - assert(indlist[2] != -1); - } - if (edgeTable[iCubeIndex] & 8) - { - indlist[3] = vertexIndicesY0[getIndex(x,y, regSlice.width()+1)]; - assert(indlist[3] != -1); - } - if (edgeTable[iCubeIndex] & 16) - { - indlist[4] = vertexIndicesX1[getIndex(x,y, regSlice.width()+1)]; - assert(indlist[4] != -1); - } - if (edgeTable[iCubeIndex] & 32) - { - indlist[5] = vertexIndicesY1[getIndex(x+1,y, regSlice.width()+1)]; - assert(indlist[5] != -1); - } - if (edgeTable[iCubeIndex] & 64) - { - indlist[6] = vertexIndicesX1[getIndex(x,y+1, regSlice.width()+1)]; - assert(indlist[6] != -1); - } - if (edgeTable[iCubeIndex] & 128) - { - indlist[7] = vertexIndicesY1[getIndex(x,y, regSlice.width()+1)]; - assert(indlist[7] != -1); - } - if (edgeTable[iCubeIndex] & 256) - { - indlist[8] = vertexIndicesZ0[getIndex(x,y, regSlice.width()+1)]; - assert(indlist[8] != -1); - } - if (edgeTable[iCubeIndex] & 512) - { - indlist[9] = vertexIndicesZ0[getIndex(x+1,y, regSlice.width()+1)]; - assert(indlist[9] != -1); - } - if (edgeTable[iCubeIndex] & 1024) - { - indlist[10] = vertexIndicesZ0[getIndex(x+1,y+1, regSlice.width()+1)]; - assert(indlist[10] != -1); - } - if (edgeTable[iCubeIndex] & 2048) - { - indlist[11] = vertexIndicesZ0[getIndex(x,y+1, regSlice.width()+1)]; - assert(indlist[11] != -1); - } - - for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) - { - uint32_t ind0 = indlist[triTable[iCubeIndex][i ]]; - uint32_t ind1 = indlist[triTable[iCubeIndex][i+1]]; - uint32_t ind2 = indlist[triTable[iCubeIndex][i+2]]; - - singleMaterialPatch->addTriangle(ind0, ind1, ind2); - }//For each triangle - }while(volIter.moveForwardInRegionXYZ());//For each cell - } -} \ No newline at end of file diff --git a/library/source/PolyVoxCore/PolyVoxImpl/MarchingCubesTables.cpp b/library/source/PolyVoxCore/PolyVoxImpl/MarchingCubesTables.cpp deleted file mode 100644 index e843fcce..00000000 --- a/library/source/PolyVoxCore/PolyVoxImpl/MarchingCubesTables.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -//Based on code by Paul Bourke -//From the article "Polygonising a scalar field" - -// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/index.html - -#include "PolyVoxCore/PolyVoxImpl/MarchingCubesTables.h" - -namespace PolyVox -{ - int edgeTable[256]= - { - 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, - 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, - 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, - 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, - 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, - 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, - 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, - 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, - 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, - 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, - 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, - 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, - 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, - 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, - 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , - 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, - 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, - 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, - 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, - 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, - 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, - 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, - 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, - 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, - 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, - 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, - 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, - 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, - 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, - 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, - 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, - 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 - }; - - int triTable[256][16] = - { - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, - {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, - {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, - {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, - {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, - {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, - {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, - {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, - {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, - {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, - {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, - {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, - {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, - {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, - {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, - {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, - {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, - {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, - {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, - {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, - {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, - {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, - {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, - {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, - {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, - {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, - {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, - {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, - {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, - {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, - {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, - {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, - {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, - {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, - {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, - {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, - {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, - {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, - {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, - {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, - {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, - {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, - {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, - {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, - {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, - {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, - {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, - {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, - {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, - {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, - {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, - {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, - {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, - {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, - {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, - {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, - {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, - {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, - {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, - {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, - {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, - {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, - {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, - {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, - {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, - {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, - {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, - {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, - {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, - {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, - {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, - {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, - {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, - {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, - {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, - {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, - {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, - {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, - {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, - {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, - {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, - {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, - {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, - {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, - {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, - {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, - {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, - {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, - {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, - {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, - {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, - {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, - {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, - {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, - {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, - {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, - {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, - {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, - {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, - {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, - {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, - {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, - {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, - {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, - {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, - {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, - {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, - {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, - {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, - {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, - {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, - {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, - {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, - {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, - {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, - {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, - {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, - {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, - {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, - {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, - {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, - {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, - {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, - {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, - {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, - {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, - {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, - {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, - {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, - {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, - {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, - {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, - {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, - {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, - {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, - {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, - {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, - {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, - {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, - {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, - {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, - {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, - {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, - {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, - {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, - {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, - {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, - {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, - {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, - {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, - {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, - {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, - {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, - {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, - {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, - {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, - {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, - {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, - {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, - {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, - {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, - {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, - {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, - {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, - {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, - {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, - {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, - {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, - {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, - {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, - {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, - {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, - {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, - {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, - {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, - {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, - {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, - {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, - {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, - {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} - }; -} diff --git a/library/source/PolyVoxCore/PolyVoxImpl/ReferenceSurfaceExtractor.cpp b/library/source/PolyVoxCore/PolyVoxImpl/ReferenceSurfaceExtractor.cpp deleted file mode 100644 index 1bbe8d27..00000000 --- a/library/source/PolyVoxCore/PolyVoxImpl/ReferenceSurfaceExtractor.cpp +++ /dev/null @@ -1,334 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include "PolyVoxCore/PolyVoxImpl/ReferenceSurfaceExtractor.h" - -#include "PolyVoxCore/Volume.h" -#include "PolyVoxCore/VolumeIterator.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/PolyVoxImpl/MarchingCubesTables.h" -#include "PolyVoxCore/Region.h" -#include "PolyVoxCore/SurfaceVertex.h" -#include "PolyVoxCore/Vector.h" - -namespace PolyVox -{ - void extractReferenceSurfaceImpl(Volume* volumeData, Region region, IndexedSurfacePatch* singleMaterialPatch) - { - /*static int32_t vertexIndicesX[POLYVOX_REGION_SIDE_LENGTH+1][POLYVOX_REGION_SIDE_LENGTH+1][POLYVOX_REGION_SIDE_LENGTH+1]; - static int32_t vertexIndicesY[POLYVOX_REGION_SIDE_LENGTH+1][POLYVOX_REGION_SIDE_LENGTH+1][POLYVOX_REGION_SIDE_LENGTH+1]; - static int32_t vertexIndicesZ[POLYVOX_REGION_SIDE_LENGTH+1][POLYVOX_REGION_SIDE_LENGTH+1][POLYVOX_REGION_SIDE_LENGTH+1];*/ - - Vector3DInt32 regionDimensions = region.dimensions() + Vector3DInt32(1,1,1); - std::vector vertexIndicesX(regionDimensions.getX() * regionDimensions.getY() * regionDimensions.getZ()); - std::vector vertexIndicesY(regionDimensions.getX() * regionDimensions.getY() * regionDimensions.getZ()); - std::vector vertexIndicesZ(regionDimensions.getX() * regionDimensions.getY() * regionDimensions.getZ()); - - memset(&vertexIndicesX[0],0xFF,sizeof(vertexIndicesX[0]) * vertexIndicesX.size()); //0xFF is -1 as two's complement - this may not be portable... - memset(&vertexIndicesY[0],0xFF,sizeof(vertexIndicesY[0]) * vertexIndicesY.size()); //FIXME - can we just use sizeof(vertexIndicesY)? - memset(&vertexIndicesZ[0],0xFF,sizeof(vertexIndicesZ[0]) * vertexIndicesZ.size()); - - //When generating the mesh for a region we actually look one voxel outside it in the - // back, bottom, right direction. Protect against access violations by cropping region here - Region regVolume = volumeData->getEnclosingRegion(); - //regVolume.setUpperCorner(regVolume.getUpperCorner() - Vector3DInt32(1,1,1)); - region.cropTo(regVolume); - region.setUpperCorner(region.getUpperCorner() - Vector3DInt32(1,1,1)); - - //Offset from lower block corner - const Vector3DFloat offset = static_cast(region.getLowerCorner()); - - Vector3DFloat vertlist[12]; - Vector3DFloat normlist[12]; - uint8_t vertMaterials[12]; - VolumeIterator volIter(*volumeData); - volIter.setValidRegion(region); - - ////////////////////////////////////////////////////////////////////////// - //Get mesh data - ////////////////////////////////////////////////////////////////////////// - - //Iterate over each cell in the region - volIter.setPosition(region.getLowerCorner().getX(),region.getLowerCorner().getY(), region.getLowerCorner().getZ()); - while(volIter.moveForwardInRegionXYZ()) - { - //Current position - const uint16_t x = volIter.getPosX(); - const uint16_t y = volIter.getPosY(); - const uint16_t z = volIter.getPosZ(); - - //Voxels values - const uint8_t v000 = volIter.getVoxel(); - const uint8_t v100 = volIter.peekVoxel1px0py0pz(); - const uint8_t v010 = volIter.peekVoxel0px1py0pz(); - const uint8_t v110 = volIter.peekVoxel1px1py0pz(); - const uint8_t v001 = volIter.peekVoxel0px0py1pz(); - const uint8_t v101 = volIter.peekVoxel1px0py1pz(); - const uint8_t v011 = volIter.peekVoxel0px1py1pz(); - const uint8_t v111 = volIter.peekVoxel1px1py1pz(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = 0; - - if (v000 == 0) iCubeIndex |= 1; - if (v100 == 0) iCubeIndex |= 2; - if (v110 == 0) iCubeIndex |= 4; - if (v010 == 0) iCubeIndex |= 8; - if (v001 == 0) iCubeIndex |= 16; - if (v101 == 0) iCubeIndex |= 32; - if (v111 == 0) iCubeIndex |= 64; - if (v011 == 0) iCubeIndex |= 128; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - vertlist[0].setX(x + 0.5f); - vertlist[0].setY(y); - vertlist[0].setZ(z); - normlist[0].setX(v000 > v100 ? 1.0f : -1.0f); - normlist[0].setY(0.0f); - normlist[0].setZ(0.0f); - vertMaterials[0] = v000 | v100; //Because one of these is 0, the or operation takes the max. - } - if (edgeTable[iCubeIndex] & 2) - { - vertlist[1].setX(x + 1.0f); - vertlist[1].setY(y + 0.5f); - vertlist[1].setZ(z); - normlist[1].setX(0.0f); - normlist[1].setY(v100 > v110 ? 1.0f : -1.0f); - normlist[1].setZ(0.0f); - vertMaterials[1] = v100 | v110; - } - if (edgeTable[iCubeIndex] & 4) - { - vertlist[2].setX(x + 0.5f); - vertlist[2].setY(y + 1.0f); - vertlist[2].setZ(z); - normlist[2].setX(v010 > v110 ? 1.0f : -1.0f); - normlist[2].setY(0.0f); - normlist[2].setZ(0.0f); - vertMaterials[2] = v010 | v110; - } - if (edgeTable[iCubeIndex] & 8) - { - vertlist[3].setX(x); - vertlist[3].setY(y + 0.5f); - vertlist[3].setZ(z); - normlist[3].setX(0.0f); - normlist[3].setY(v000 > v010 ? 1.0f : -1.0f); - normlist[3].setZ(0.0f); - vertMaterials[3] = v000 | v010; - } - if (edgeTable[iCubeIndex] & 16) - { - vertlist[4].setX(x + 0.5f); - vertlist[4].setY(y); - vertlist[4].setZ(z + 1.0f); - normlist[4].setX(v001 > v101 ? 1.0f : -1.0f); - normlist[4].setY(0.0f); - normlist[4].setZ(0.0f); - vertMaterials[4] = v001 | v101; - } - if (edgeTable[iCubeIndex] & 32) - { - vertlist[5].setX(x + 1.0f); - vertlist[5].setY(y + 0.5f); - vertlist[5].setZ(z + 1.0f); - normlist[5].setX(0.0f); - normlist[5].setY(v101 > v111 ? 1.0f : -1.0f); - normlist[5].setZ(0.0f); - vertMaterials[5] = v101 | v111; - } - if (edgeTable[iCubeIndex] & 64) - { - vertlist[6].setX(x + 0.5f); - vertlist[6].setY(y + 1.0f); - vertlist[6].setZ(z + 1.0f); - normlist[6].setX(v011 > v111 ? 1.0f : -1.0f); - normlist[6].setY(0.0f); - normlist[6].setZ(0.0f); - vertMaterials[6] = v011 | v111; - } - if (edgeTable[iCubeIndex] & 128) - { - vertlist[7].setX(x); - vertlist[7].setY(y + 0.5f); - vertlist[7].setZ(z + 1.0f); - normlist[7].setX(0.0f); - normlist[7].setY(v001 > v011 ? 1.0f : -1.0f); - normlist[7].setZ(0.0f); - vertMaterials[7] = v001 | v011; - } - if (edgeTable[iCubeIndex] & 256) - { - vertlist[8].setX(x); - vertlist[8].setY(y); - vertlist[8].setZ(z + 0.5f); - normlist[8].setX(0.0f); - normlist[8].setY(0.0f); - normlist[8].setZ(v000 > v001 ? 1.0f : -1.0f); - vertMaterials[8] = v000 | v001; - } - if (edgeTable[iCubeIndex] & 512) - { - vertlist[9].setX(x + 1.0f); - vertlist[9].setY(y); - vertlist[9].setZ(z + 0.5f); - normlist[9].setX(0.0f); - normlist[9].setY(0.0f); - normlist[9].setZ(v100 > v101 ? 1.0f : -1.0f); - vertMaterials[9] = v100 | v101; - } - if (edgeTable[iCubeIndex] & 1024) - { - vertlist[10].setX(x + 1.0f); - vertlist[10].setY(y + 1.0f); - vertlist[10].setZ(z + 0.5f); - normlist[10].setX(0.0f); - normlist[10].setY(0.0f); - normlist[10].setZ(v110 > v111 ? 1.0f : -1.0f); - vertMaterials[10] = v110 | v111; - } - if (edgeTable[iCubeIndex] & 2048) - { - vertlist[11].setX(x); - vertlist[11].setY(y + 1.0f); - vertlist[11].setZ(z + 0.5f); - normlist[11].setX(0.0f); - normlist[11].setY(0.0f); - normlist[11].setZ(v010 > v011 ? 1.0f : -1.0f); - vertMaterials[11] = v010 | v011; - } - - for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) - { - //The three vertices forming a triangle - const Vector3DFloat vertex0 = vertlist[triTable[iCubeIndex][i ]] - offset; - const Vector3DFloat vertex1 = vertlist[triTable[iCubeIndex][i+1]] - offset; - const Vector3DFloat vertex2 = vertlist[triTable[iCubeIndex][i+2]] - offset; - - const Vector3DFloat normal0 = normlist[triTable[iCubeIndex][i ]]; - const Vector3DFloat normal1 = normlist[triTable[iCubeIndex][i+1]]; - const Vector3DFloat normal2 = normlist[triTable[iCubeIndex][i+2]]; - - //Cast to floats and divide by two. - //const Vector3DFloat vertex0AsFloat = (static_cast(vertex0) / 2.0f) - offset; - //const Vector3DFloat vertex1AsFloat = (static_cast(vertex1) / 2.0f) - offset; - //const Vector3DFloat vertex2AsFloat = (static_cast(vertex2) / 2.0f) - offset; - - const uint8_t material0 = vertMaterials[triTable[iCubeIndex][i ]]; - const uint8_t material1 = vertMaterials[triTable[iCubeIndex][i+1]]; - const uint8_t material2 = vertMaterials[triTable[iCubeIndex][i+2]]; - - //If all the materials are the same, we just need one triangle for that material with all the alphas set high. - SurfaceVertex v0(vertex0, normal0, material0 + 0.1f); - SurfaceVertex v1(vertex1, normal1, material1 + 0.1f); - SurfaceVertex v2(vertex2, normal2, material2 + 0.1f); - - int32_t index0 = getIndexFor(v0.getPosition(), regionDimensions, vertexIndicesX, vertexIndicesY, vertexIndicesZ); - if(index0 == -1) - { - index0 = singleMaterialPatch->addVertex(v0); - setIndexFor(v0.getPosition(), regionDimensions, index0, vertexIndicesX, vertexIndicesY, vertexIndicesZ); - } - - int32_t index1 = getIndexFor(v1.getPosition(), regionDimensions, vertexIndicesX, vertexIndicesY, vertexIndicesZ); - if(index1 == -1) - { - index1 = singleMaterialPatch->addVertex(v1); - setIndexFor(v1.getPosition(), regionDimensions, index1, vertexIndicesX, vertexIndicesY, vertexIndicesZ); - } - - int32_t index2 = getIndexFor(v2.getPosition(), regionDimensions, vertexIndicesX, vertexIndicesY, vertexIndicesZ); - if(index2 == -1) - { - index2 = singleMaterialPatch->addVertex(v2); - setIndexFor(v2.getPosition(), regionDimensions, index2, vertexIndicesX, vertexIndicesY, vertexIndicesZ); - } - - singleMaterialPatch->addTriangle(index0, index1, index2); - }//For each triangle - }//For each cell - } - - int32_t getIndexFor(const Vector3DFloat& pos, const Vector3DInt32& regionDimensions, const std::vector& vertexIndicesX, const std::vector& vertexIndicesY, const std::vector& vertexIndicesZ) - { - float xIntPartAsFloat; - float xFracPart = std::modf(pos.getX(), &xIntPartAsFloat); - float yIntPartAsFloat; - float yFracPart = std::modf(pos.getY(), &yIntPartAsFloat); - float zIntPartAsFloat; - float zFracPart = std::modf(pos.getZ(), &zIntPartAsFloat); - - uint16_t xIntPart = static_cast(xIntPartAsFloat); - uint16_t yIntPart = static_cast(yIntPartAsFloat); - uint16_t zIntPart = static_cast(zIntPartAsFloat); - - //Of all the fractional parts, two should be zero and one should be 0.5. - if(xFracPart > 0.25f) - { - return vertexIndicesX[xIntPart + yIntPart * regionDimensions.getX() + zIntPart * regionDimensions.getX() * regionDimensions.getY()]; - } - if(yFracPart > 0.25f) - { - return vertexIndicesY[xIntPart + yIntPart * regionDimensions.getX() + zIntPart * regionDimensions.getX() * regionDimensions.getY()]; - } - if(zFracPart > 0.25f) - { - return vertexIndicesZ[xIntPart + yIntPart * regionDimensions.getX() + zIntPart * regionDimensions.getX() * regionDimensions.getY()]; - } - } - - void setIndexFor(const Vector3DFloat& pos, const Vector3DInt32& regionDimensions, int32_t newIndex, std::vector& vertexIndicesX, std::vector& vertexIndicesY, std::vector& vertexIndicesZ) - { - float xIntPartAsFloat; - float xFracPart = std::modf(pos.getX(), &xIntPartAsFloat); - float yIntPartAsFloat; - float yFracPart = std::modf(pos.getY(), &yIntPartAsFloat); - float zIntPartAsFloat; - float zFracPart = std::modf(pos.getZ(), &zIntPartAsFloat); - - uint16_t xIntPart = static_cast(xIntPartAsFloat); - uint16_t yIntPart = static_cast(yIntPartAsFloat); - uint16_t zIntPart = static_cast(zIntPartAsFloat); - - //Of all the fractional parts, two should be zero and one should be 0.5. - if(xFracPart > 0.25f) - { - vertexIndicesX[xIntPart + yIntPart * regionDimensions.getX() + zIntPart * regionDimensions.getX() * regionDimensions.getY()] = newIndex; - } - if(yFracPart > 0.25f) - { - vertexIndicesY[xIntPart + yIntPart * regionDimensions.getX() + zIntPart * regionDimensions.getX() * regionDimensions.getY()] = newIndex; - } - if(zFracPart > 0.25f) - { - vertexIndicesZ[xIntPart + yIntPart * regionDimensions.getX() + zIntPart * regionDimensions.getX() * regionDimensions.getY()] = newIndex; - } - } -} \ No newline at end of file diff --git a/library/source/PolyVoxCore/PolyVoxImpl/Utility.cpp b/library/source/PolyVoxCore/PolyVoxImpl/Utility.cpp deleted file mode 100644 index e6565331..00000000 --- a/library/source/PolyVoxCore/PolyVoxImpl/Utility.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include "PolyVoxCore/PolyVoxImpl/Utility.h" - -#include -#include - -namespace PolyVox -{ - //Note: this function only works for inputs which are a power of two and not zero - //If this is not the case then the output is undefined. - uint8_t logBase2(uint32_t uInput) - { - //Debug mode validation - assert(uInput != 0); - assert(isPowerOf2(uInput)); - - //Release mode validation - if(uInput == 0) - { - throw std::invalid_argument("Cannot compute the log of zero."); - } - if(!isPowerOf2(uInput)) - { - throw std::invalid_argument("Input must be a power of two in order to compute the log."); - } - - uint32_t uResult = 0; - while( (uInput >> uResult) != 0) - { - ++uResult; - } - return static_cast(uResult-1); - } - - - bool isPowerOf2(uint32_t uInput) - { - if(uInput == 0) - return false; - else - return ((uInput & (uInput-1)) == 0); - } -} diff --git a/library/source/PolyVoxCore/Region.cpp b/library/source/PolyVoxCore/Region.cpp deleted file mode 100644 index 011f63c5..00000000 --- a/library/source/PolyVoxCore/Region.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "PolyVoxCore/Region.h" - -namespace PolyVox -{ - Region::Region() - :m_v3dLowerCorner(0,0,0) - ,m_v3dUpperCorner(0,0,0) - { - } - - Region::Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner) - :m_v3dLowerCorner(v3dLowerCorner) - ,m_v3dUpperCorner(v3dUpperCorner) - { - } - - const Vector3DInt32& Region::getLowerCorner(void) const - { - return m_v3dLowerCorner; - } - - const Vector3DInt32& Region::getUpperCorner(void) const - { - return m_v3dUpperCorner; - } - - void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner) - { - m_v3dLowerCorner = v3dLowerCorner; - } - - void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner) - { - m_v3dUpperCorner = v3dUpperCorner; - } - - bool Region::containsPoint(const Vector3DFloat& pos, float boundary) const - { - return (pos.getX() <= m_v3dUpperCorner.getX() - boundary) - && (pos.getY() <= m_v3dUpperCorner.getY() - boundary) - && (pos.getZ() <= m_v3dUpperCorner.getZ() - boundary) - && (pos.getX() >= m_v3dLowerCorner.getX() + boundary) - && (pos.getY() >= m_v3dLowerCorner.getY() + boundary) - && (pos.getZ() >= m_v3dLowerCorner.getZ() + boundary); - } - - bool Region::containsPoint(const Vector3DInt32& pos, uint8_t boundary) const - { - return (pos.getX() <= m_v3dUpperCorner.getX() - boundary) - && (pos.getY() <= m_v3dUpperCorner.getY() - boundary) - && (pos.getZ() <= m_v3dUpperCorner.getZ() - boundary) - && (pos.getX() >= m_v3dLowerCorner.getX() + boundary) - && (pos.getY() >= m_v3dLowerCorner.getY() + boundary) - && (pos.getZ() >= m_v3dLowerCorner.getZ() + boundary); - } - - void Region::cropTo(const Region& other) - { - m_v3dLowerCorner.setX((std::max)(m_v3dLowerCorner.getX(), other.m_v3dLowerCorner.getX())); - m_v3dLowerCorner.setY((std::max)(m_v3dLowerCorner.getY(), other.m_v3dLowerCorner.getY())); - m_v3dLowerCorner.setZ((std::max)(m_v3dLowerCorner.getZ(), other.m_v3dLowerCorner.getZ())); - m_v3dUpperCorner.setX((std::min)(m_v3dUpperCorner.getX(), other.m_v3dUpperCorner.getX())); - m_v3dUpperCorner.setY((std::min)(m_v3dUpperCorner.getY(), other.m_v3dUpperCorner.getY())); - m_v3dUpperCorner.setZ((std::min)(m_v3dUpperCorner.getZ(), other.m_v3dUpperCorner.getZ())); - } - - int32_t Region::depth(void) const - { - return m_v3dUpperCorner.getZ() - m_v3dLowerCorner.getZ(); - } - - int32_t Region::height(void) const - { - return m_v3dUpperCorner.getY() - m_v3dLowerCorner.getY(); - } - - void Region::shift(const Vector3DInt32& amount) - { - m_v3dLowerCorner += amount; - m_v3dUpperCorner += amount; - } - - void Region::shiftLowerCorner(const Vector3DInt32& amount) - { - m_v3dLowerCorner += amount; - } - - void Region::shiftUpperCorner(const Vector3DInt32& amount) - { - m_v3dUpperCorner += amount; - } - - Vector3DInt32 Region::dimensions(void) - { - return m_v3dUpperCorner - m_v3dLowerCorner; - } - - int32_t Region::width(void) const - { - return m_v3dUpperCorner.getX() - m_v3dLowerCorner.getX(); - } -} diff --git a/library/source/PolyVoxCore/SurfaceAdjusters.cpp b/library/source/PolyVoxCore/SurfaceAdjusters.cpp deleted file mode 100644 index 2e06af47..00000000 --- a/library/source/PolyVoxCore/SurfaceAdjusters.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "PolyVoxCore/SurfaceAdjusters.h" - -#include "PolyVoxCore/VolumeIterator.h" -#include "PolyVoxCore/GradientEstimators.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/PolyVoxImpl/Utility.h" -#include "PolyVoxCore/VoxelFilters.h" - -#include - -using namespace std; - -namespace PolyVox -{ - void smoothRegionGeometry(Volume* volumeData, IndexedSurfacePatch& isp) - { - const uint8_t uSmoothingFactor = 2; - const float fThreshold = 0.5f; - - VolumeIterator volIter(*volumeData); - - std::vector& vecVertices = isp.getRawVertexData(); - std::vector::iterator iterSurfaceVertex = vecVertices.begin(); - while(iterSurfaceVertex != vecVertices.end()) - { - for(int ct = 0; ct < uSmoothingFactor; ++ct) - { - const Vector3DFloat& v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - const Vector3DInt32 v3dFloor = static_cast(v3dPos); - const Vector3DFloat& v3dRem = v3dPos - static_cast(v3dFloor); - - //Check all corners are within the volume, allowing a boundary for gradient estimation - bool lowerCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor,2); - bool upperCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor+Vector3DInt32(1,1,1),2); - - if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was - { - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,0,0))); - const float v000 = computeSmoothedVoxel(volIter); - Vector3DFloat grad000 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,0,0))); - const float v100 = computeSmoothedVoxel(volIter); - Vector3DFloat grad100 = computeSmoothCentralDifferenceGradient(volIter); - - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,1,0))); - const float v010 = computeSmoothedVoxel(volIter); - Vector3DFloat grad010 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,1,0))); - const float v110 = computeSmoothedVoxel(volIter); - Vector3DFloat grad110 = computeSmoothCentralDifferenceGradient(volIter); - - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,0,1))); - const float v001 = computeSmoothedVoxel(volIter); - Vector3DFloat grad001 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,0,1))); - const float v101 = computeSmoothedVoxel(volIter); - Vector3DFloat grad101 = computeSmoothCentralDifferenceGradient(volIter); - - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,1,1))); - const float v011 = computeSmoothedVoxel(volIter); - Vector3DFloat grad011 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,1,1))); - const float v111 = computeSmoothedVoxel(volIter); - Vector3DFloat grad111 = computeSmoothCentralDifferenceGradient(volIter); - - float fInterVal = trilinearlyInterpolate(v000,v100,v010,v110,v001,v101,v011,v111,v3dRem.getX(),v3dRem.getY(),v3dRem.getZ()); - Vector3DFloat fInterGrad = trilinearlyInterpolate(grad000,grad100,grad010,grad110,grad001,grad101,grad011,grad111,v3dRem.getX(),v3dRem.getY(),v3dRem.getZ()); - - fInterGrad.normalise(); - float fDiff = fInterVal - fThreshold; - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() + (fInterGrad * fDiff)); - iterSurfaceVertex->setNormal(fInterGrad); //This is actually the gradient for the previous position, but it won't have moved much. - } //if(lowerCornerInside && upperCornerInside) - } //for(int ct = 0; ct < uSmoothingFactor; ++ct) - ++iterSurfaceVertex; - } //while(iterSurfaceVertex != vecVertices.end()) - } - - void adjustDecimatedGeometry(Volume* volumeData, IndexedSurfacePatch& isp, uint8_t val) - { - VolumeIterator volIter(*volumeData); - - std::vector& vecVertices = isp.getRawVertexData(); - std::vector::iterator iterSurfaceVertex = vecVertices.begin(); - while(iterSurfaceVertex != vecVertices.end()) - { - Vector3DFloat v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - Vector3DInt32 v3dFloor = static_cast(v3dPos); - - VolumeIterator volIter(*volumeData); - - //Check all corners are within the volume, allowing a boundary for gradient estimation - bool lowerCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor,1); - bool upperCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor+Vector3DInt32(1,1,1),1); - - if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was - { - //volIter.setPosition(static_cast(v3dFloor)); - //const uint8_t uFloor = volIter.getVoxel(); - if(((v3dPos.getX() - v3dFloor.getX()) < 0.001) && ((v3dPos.getY() - v3dFloor.getY()) < 0.001) && ((v3dPos.getZ() - v3dFloor.getZ()) < 0.001)) - //int x = v3dPos.getX(); - //if(x % 2 != 0) - //if((iterSurfaceVertex->getNormal().getX() > 0.5f) || (iterSurfaceVertex->getNormal().getX() < -0.5f)) - { - //exit(0); - //volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(1,0,0))); - //const uint8_t uCeil = volIter.getVoxel(); - //if(uFloor == uCeil) //In this case they must both be zero - { - //if(iterSurfaceVertex->getNormal().getX() > 0) - { - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() - iterSurfaceVertex->getNormal() * 0.5f); - v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - v3dFloor = static_cast(v3dPos); - - volIter.setPosition(static_cast(v3dFloor)); - const uint8_t uFloor = volIter.getVoxel(); - - uint8_t uCeil; - if((iterSurfaceVertex->getNormal().getX() > 0.5f) || (iterSurfaceVertex->getNormal().getX() < -0.5f)) - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(1,0,0))); - uCeil = volIter.getVoxel(); - } - if((iterSurfaceVertex->getNormal().getY() > 0.5f) || (iterSurfaceVertex->getNormal().getY() < -0.5f)) - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(0,1,0))); - uCeil = volIter.getVoxel(); - } - if((iterSurfaceVertex->getNormal().getZ() > 0.5f) || (iterSurfaceVertex->getNormal().getZ() < -0.5f)) - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(0,0,1))); - uCeil = volIter.getVoxel(); - } - - if(uFloor == uCeil) - { - //NOTE: The normal should actually be multiplied by 1.0f. This works - //for the simple cube but causes depth fighting on more complex shapes. - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() - iterSurfaceVertex->getNormal() * 0.5f); - } - } - } - } - } - - ++iterSurfaceVertex; - } //while(iterSurfaceVertex != vecVertices.end()) - } -} \ No newline at end of file diff --git a/library/source/PolyVoxCore/SurfaceEdge.cpp b/library/source/PolyVoxCore/SurfaceEdge.cpp deleted file mode 100644 index e491c0ba..00000000 --- a/library/source/PolyVoxCore/SurfaceEdge.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include - -#include "SurfaceEdge.h" -#include "SurfaceTriangle.h" -#include "SurfaceVertex.h" - -namespace PolyVox -{ - SurfaceEdge::SurfaceEdge(const SurfaceVertexIterator& targetToSet,const SurfaceVertexIterator& sourceToSet) - { - target = targetToSet; - source = sourceToSet; - } - - std::string SurfaceEdge::tostring(void) - { - std::stringstream ss; - ss << "SurfaceEdge: Target Vertex = " << target->tostring() << "Source Vertex = " << source->tostring(); - return ss.str(); - } - - bool operator == (const SurfaceEdge& lhs, const SurfaceEdge& rhs) - { - //Vertices are unique in the set, so if the two positions are the same the - //two iterators must also be the same. So we just check the iterators. - return - ( - (lhs.target == rhs.target) && - (lhs.source == rhs.source) - ); - } - - bool SurfaceEdge::isDegenerate(void) - { - return (target == source); - } - - bool operator < (const SurfaceEdge& lhs, const SurfaceEdge& rhs) - { - //Unlike the equality operator, we can't compare iterators. - //So dereference and compare the results. - if ((*lhs.target) < (*rhs.target)) - return true; - if ((*rhs.target) < (*lhs.target)) - return false; - - if ((*lhs.source) < (*rhs.source)) - return true; - if ((*rhs.source) < (*lhs.source)) - return false; - - return false; - } - - const SurfaceVertexIterator& SurfaceEdge::getTarget(void) const - { - return target; - } - - const SurfaceVertexIterator& SurfaceEdge::getSource(void) const - { - return source; - } - - void SurfaceEdge::pairWithOtherHalfEdge(const SurfaceEdgeIterator& otherHalfEdgeToPair) - { - otherHalfEdge = otherHalfEdgeToPair; - previousHalfEdge = otherHalfEdgeToPair; - nextHalfEdge = otherHalfEdgeToPair; - } - - const SurfaceEdgeIterator& SurfaceEdge::getOtherHalfEdge(void) const - { - return otherHalfEdge; - } - - const SurfaceEdgeIterator& SurfaceEdge::getPreviousHalfEdge(void) const - { - return previousHalfEdge; - } - - const SurfaceEdgeIterator& SurfaceEdge::getNextHalfEdge(void) const - { - return nextHalfEdge; - } - - const SurfaceTriangleIterator& SurfaceEdge::getTriangle(void) const - { - return triangle; - } - - void SurfaceEdge::setPreviousHalfEdge(const SurfaceEdgeIterator& previousHalfEdgeToSet) - { - previousHalfEdge = previousHalfEdgeToSet; - } - - void SurfaceEdge::setNextHalfEdge(const SurfaceEdgeIterator& nextHalfEdgeToSet) - { - nextHalfEdge = nextHalfEdgeToSet; - } - - void SurfaceEdge::setTriangle(const SurfaceTriangleIterator& triangleToSet) - { - triangle = triangleToSet; - } -} diff --git a/library/source/PolyVoxCore/SurfaceExtractors.cpp b/library/source/PolyVoxCore/SurfaceExtractors.cpp deleted file mode 100644 index 171bbf34..00000000 --- a/library/source/PolyVoxCore/SurfaceExtractors.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "PolyVoxCore/SurfaceExtractors.h" - -#include "PolyVoxCore/Volume.h" -#include "PolyVoxCore/GradientEstimators.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/PolyVoxImpl/MarchingCubesTables.h" -#include "PolyVoxCore/Region.h" -#include "PolyVoxCore/SurfaceAdjusters.h" -#include "PolyVoxCore/VolumeIterator.h" - -#include "PolyVoxCore/PolyVoxImpl/DecimatedSurfaceExtractor.h" -#include "PolyVoxCore/PolyVoxImpl/FastSurfaceExtractor.h" -#include "PolyVoxCore/PolyVoxImpl/ReferenceSurfaceExtractor.h" - -#include - -using namespace std; - -namespace PolyVox -{ - void extractSurface(Volume* volumeData, uint8_t uLevel, Region region, IndexedSurfacePatch* singleMaterialPatch) - { - if(uLevel == 0) - { - extractFastSurfaceImpl(volumeData, region, singleMaterialPatch); - } - else - { - extractDecimatedSurfaceImpl(volumeData, uLevel, region, singleMaterialPatch); - } - - singleMaterialPatch->m_v3dRegionPosition = region.getLowerCorner(); - } - - void extractReferenceSurface(Volume* volumeData, Region region, IndexedSurfacePatch* singleMaterialPatch) - { - extractReferenceSurfaceImpl(volumeData, region, singleMaterialPatch); - - singleMaterialPatch->m_v3dRegionPosition = region.getLowerCorner(); - } -} diff --git a/library/source/PolyVoxCore/SurfaceTriangle.cpp b/library/source/PolyVoxCore/SurfaceTriangle.cpp deleted file mode 100644 index e9b703a4..00000000 --- a/library/source/PolyVoxCore/SurfaceTriangle.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "SurfaceTriangle.h" -#include "SurfaceVertex.h" -#include "SurfaceEdge.h" - -namespace PolyVox -{ - SurfaceTriangle::SurfaceTriangle() - { - } - - const SurfaceEdgeIterator& SurfaceTriangle::getEdge(void) const - { - return edge; - } - - void SurfaceTriangle::setEdge(const SurfaceEdgeIterator& edgeToSet) - { - edge = edgeToSet; - } - - /*std::string SurfaceTriangle::tostring(void) - { - std::stringstream ss; - - uint16_t ct = 0; - SurfaceEdgeIterator edgeIter = edge; - ss << "SurfaceTriangle:"; - do - { - ss << "\n Edge " << ct << " = " << edgeIter->tostring(); - if(edgeIter->hasOtherHalfEdge) - { - ss << "\n Opp Edge " << ct << " = " << edgeIter->otherHalfEdge->tostring(); - } - else - { - ss << "\n No Other Half"; - } - edgeIter = edgeIter->nextHalfEdge; - ++ct; - } - while(edgeIter != edge); - return ss.str(); - }*/ - - bool operator == (const SurfaceTriangle& lhs, const SurfaceTriangle& rhs) - { - //Edges are unique in the set, so if the two positions are the same the - //two iterators must also be the same. So we just check the iterators. - return (lhs.edge == rhs.edge); - } - - bool operator < (const SurfaceTriangle& lhs, const SurfaceTriangle& rhs) - { - //Unlike the equality operator, we can't compare iterators. - //So dereference and compare the results. - return (*lhs.edge < *rhs.edge); - } -} diff --git a/library/source/PolyVoxCore/SurfaceVertex.cpp b/library/source/PolyVoxCore/SurfaceVertex.cpp deleted file mode 100644 index 12cdc360..00000000 --- a/library/source/PolyVoxCore/SurfaceVertex.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include - -#include "PolyVoxCore/SurfaceVertex.h" - -namespace PolyVox -{ - SurfaceVertex::SurfaceVertex() - { - } - - SurfaceVertex::SurfaceVertex(Vector3DFloat positionToSet, float materialToSet) - :position(positionToSet) - ,material(materialToSet) - { - - } - - SurfaceVertex::SurfaceVertex(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet) - :position(positionToSet) - ,normal(normalToSet) - ,material(materialToSet) - { - } - - float SurfaceVertex::getMaterial(void) const - { - return material; - } - - const Vector3DFloat& SurfaceVertex::getNormal(void) const - { - return normal; - } - - const Vector3DFloat& SurfaceVertex::getPosition(void) const - { - return position; - } - - void SurfaceVertex::setMaterial(float materialToSet) - { - material = materialToSet; - } - - void SurfaceVertex::setNormal(const Vector3DFloat& normalToSet) - { - normal = normalToSet; - } - - void SurfaceVertex::setPosition(const Vector3DFloat& positionToSet) - { - position = positionToSet; - } - - std::string SurfaceVertex::tostring(void) const - { - std::stringstream ss; - ss << "SurfaceVertex: Position = (" << position.getX() << "," << position.getY() << "," << position.getZ() << "), Normal = " << normal; - return ss.str(); - } -} diff --git a/library/source/PolyVoxCore/VoxelFilters.cpp b/library/source/PolyVoxCore/VoxelFilters.cpp deleted file mode 100644 index 7746ec41..00000000 --- a/library/source/PolyVoxCore/VoxelFilters.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "PolyVoxCore/VoxelFilters.h" - -#include "PolyVoxCore/VolumeIterator.h" - -namespace PolyVox -{ - float computeSmoothedVoxel(VolumeIterator& volIter) - { - assert(volIter.getPosX() >= 1); - assert(volIter.getPosY() >= 1); - assert(volIter.getPosZ() >= 1); - assert(volIter.getPosX() <= volIter.getVolume().getSideLength() - 2); - assert(volIter.getPosY() <= volIter.getVolume().getSideLength() - 2); - assert(volIter.getPosZ() <= volIter.getVolume().getSideLength() - 2); - - float sum = 0.0; - - if(volIter.peekVoxel1nx1ny1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx1ny0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx1ny1pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx0py1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx0py0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx0py1pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx1py1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx1py0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1nx1py1pz() != 0) sum += 1.0f; - - if(volIter.peekVoxel0px1ny1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel0px1ny0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel0px1ny1pz() != 0) sum += 1.0f; - if(volIter.peekVoxel0px0py1nz() != 0) sum += 1.0f; - if(volIter.getVoxel() != 0) sum += 1.0f; - if(volIter.peekVoxel0px0py1pz() != 0) sum += 1.0f; - if(volIter.peekVoxel0px1py1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel0px1py0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel0px1py1pz() != 0) sum += 1.0f; - - if(volIter.peekVoxel1px1ny1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px1ny0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px1ny1pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px0py1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px0py0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px0py1pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px1py1nz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px1py0pz() != 0) sum += 1.0f; - if(volIter.peekVoxel1px1py1pz() != 0) sum += 1.0f; - - sum /= 27.0f; - return sum; - } -} \ No newline at end of file diff --git a/library/source/PolyVoxUtil/Serialization.cpp b/library/source/PolyVoxUtil/Serialization.cpp deleted file mode 100644 index 1e1cdd21..00000000 --- a/library/source/PolyVoxUtil/Serialization.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "PolyVoxUtil/Serialization.h" - -#include "PolyVoxCore/Volume.h" -#include "PolyVoxCore/VolumeIterator.h" -#include "PolyVoxCore/PolyVoxImpl/Utility.h" - -using namespace std; - -namespace PolyVox -{ - //Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller. - //FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow - Volume* loadVolumeRaw(istream& stream) - { - //Read volume dimensions - uint8_t volumeWidthPower = 0; - uint8_t volumeHeightPower = 0; - uint8_t volumeDepthPower = 0; - stream.read(reinterpret_cast(&volumeWidthPower), sizeof(volumeWidthPower)); - stream.read(reinterpret_cast(&volumeHeightPower), sizeof(volumeHeightPower)); - stream.read(reinterpret_cast(&volumeDepthPower), sizeof(volumeDepthPower)); - - uint16_t volumeWidth = 0x0001 << volumeWidthPower; - uint16_t volumeHeight = 0x0001 << volumeHeightPower; - uint16_t volumeDepth = 0x0001 << volumeDepthPower; - - //FIXME - need to support non cubic volumes - Volume* volume = new Volume(volumeWidth); - - //Read data - for(uint16_t z = 0; z < volumeDepth; ++z) - { - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - uint8_t value = 0; - stream.read(reinterpret_cast(&value), sizeof(value)); - - volume->setVoxelAt(x,y,z,value); - } - } - } - - return volume; - } - - void saveVolumeRaw(std::ostream& stream, Volume& volume) - { - //Write volume dimensions - uint16_t volumeWidth = volume.getSideLength(); - uint16_t volumeHeight = volume.getSideLength(); - uint16_t volumeDepth = volume.getSideLength(); - - uint8_t volumeWidthPower = logBase2(volumeWidth); - uint8_t volumeHeightPower = logBase2(volumeHeight); - uint8_t volumeDepthPower = logBase2(volumeDepth); - - stream.write(reinterpret_cast(&volumeWidthPower), sizeof(volumeWidthPower)); - stream.write(reinterpret_cast(&volumeHeightPower), sizeof(volumeHeightPower)); - stream.write(reinterpret_cast(&volumeDepthPower), sizeof(volumeDepthPower)); - - //Write data - VolumeIterator volIter(volume); - for(uint16_t z = 0; z < volumeDepth; ++z) - { - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - volIter.setPosition(x,y,z); - uint8_t value = volIter.getVoxel(); - stream.write(reinterpret_cast(&value), sizeof(value)); - } - } - } - } - - //Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller. - //FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow - Volume* loadVolumeRle(istream& stream) - { - //Read volume dimensions - uint8_t volumeWidthPower = 0; - uint8_t volumeHeightPower = 0; - uint8_t volumeDepthPower = 0; - stream.read(reinterpret_cast(&volumeWidthPower), sizeof(volumeWidthPower)); - stream.read(reinterpret_cast(&volumeHeightPower), sizeof(volumeHeightPower)); - stream.read(reinterpret_cast(&volumeDepthPower), sizeof(volumeDepthPower)); - - uint16_t volumeWidth = 0x0001 << volumeWidthPower; - uint16_t volumeHeight = 0x0001 << volumeHeightPower; - uint16_t volumeDepth = 0x0001 << volumeDepthPower; - - //FIXME - need to support non cubic volumes - Volume* volume = new Volume(volumeWidth); - - //Read data - bool firstTime = true; - uint32_t runLength = 0; - uint8_t value = 0; - stream.read(reinterpret_cast(&value), sizeof(value)); - stream.read(reinterpret_cast(&runLength), sizeof(runLength)); - for(uint16_t z = 0; z < volumeDepth; ++z) - { - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - if(runLength != 0) - { - volume->setVoxelAt(x,y,z,value); - runLength--; - } - else - { - stream.read(reinterpret_cast(&value), sizeof(value)); - stream.read(reinterpret_cast(&runLength), sizeof(runLength)); - - volume->setVoxelAt(x,y,z,value); - runLength--; - } - } - } - } - - return volume; - } - - void saveVolumeRle(std::ostream& stream, Volume& volume) - { - //Write volume dimensions - uint16_t volumeWidth = volume.getSideLength(); - uint16_t volumeHeight = volume.getSideLength(); - uint16_t volumeDepth = volume.getSideLength(); - - uint8_t volumeWidthPower = logBase2(volumeWidth); - uint8_t volumeHeightPower = logBase2(volumeHeight); - uint8_t volumeDepthPower = logBase2(volumeDepth); - - stream.write(reinterpret_cast(&volumeWidthPower), sizeof(volumeWidthPower)); - stream.write(reinterpret_cast(&volumeHeightPower), sizeof(volumeHeightPower)); - stream.write(reinterpret_cast(&volumeDepthPower), sizeof(volumeDepthPower)); - - //Write data - VolumeIterator volIter(volume); - uint8_t current = 0; - uint32_t runLength = 0; - bool firstTime = true; - for(uint16_t z = 0; z < volumeDepth; ++z) - { - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - volIter.setPosition(x,y,z); - uint8_t value = volIter.getVoxel(); - if(firstTime) - { - current = value; - runLength = 1; - firstTime = false; - } - else - { - if(value == current) - { - runLength++; - } - else - { - stream.write(reinterpret_cast(¤t), sizeof(current)); - stream.write(reinterpret_cast(&runLength), sizeof(runLength)); - current = value; - runLength = 1; - } - } - } - } - } - stream.write(reinterpret_cast(¤t), sizeof(current)); - stream.write(reinterpret_cast(&runLength), sizeof(runLength)); - } -} \ No newline at end of file diff --git a/library/source/PolyVoxUtil/VolumeChangeTracker.cpp b/library/source/PolyVoxUtil/VolumeChangeTracker.cpp deleted file mode 100644 index a4d14190..00000000 --- a/library/source/PolyVoxUtil/VolumeChangeTracker.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#include "PolyVoxUtil/VolumeChangeTracker.h" - -#include "PolyVoxCore/GradientEstimators.h" -#include "PolyVoxCore/IndexedSurfacePatch.h" -#include "PolyVoxCore/PolyVoxImpl/MarchingCubesTables.h" -#include "PolyVoxCore/SurfaceExtractors.h" -#include "PolyVoxCore/SurfaceVertex.h" -#include "PolyVoxCore/PolyVoxImpl/Utility.h" -#include "PolyVoxCore/Vector.h" -#include "PolyVoxCore/Volume.h" -#include "PolyVoxCore/VolumeIterator.h" - -using namespace std; - -namespace PolyVox -{ - int32_t VolumeChangeTracker::m_iCurrentTime = 0; - - ////////////////////////////////////////////////////////////////////////// - // VolumeChangeTracker - ////////////////////////////////////////////////////////////////////////// - VolumeChangeTracker::VolumeChangeTracker(Volume* volumeDataToSet, uint16_t regionSideLength) - :m_bIsLocked(false) - ,volumeData(0) - ,m_uRegionSideLength(regionSideLength) - { - volumeData = volumeDataToSet; - m_uVolumeSideLengthInRegions = volumeData->getSideLength() / m_uRegionSideLength; - m_uRegionSideLengthPower = PolyVox::logBase2(m_uRegionSideLength); - - volRegionLastModified = new BlockData(m_uRegionSideLength); - } - - VolumeChangeTracker::~VolumeChangeTracker() - { - } - - void VolumeChangeTracker::setAllRegionsModified(void) - { - for(uint16_t blockZ = 0; blockZ < m_uVolumeSideLengthInRegions; ++blockZ) - { - for(uint16_t blockY = 0; blockY < m_uVolumeSideLengthInRegions; ++blockY) - { - for(uint16_t blockX = 0; blockX < m_uVolumeSideLengthInRegions; ++blockX) - { - volRegionLastModified->setVoxelAt(blockX, blockY, blockZ, m_iCurrentTime); - ++m_iCurrentTime; - } - } - } - } - - int32_t VolumeChangeTracker::getCurrentTime(void) const - { - return m_iCurrentTime; - } - - uint16_t VolumeChangeTracker::getSideLength(void) - { - return volumeData->getSideLength(); - } - - Region VolumeChangeTracker::getEnclosingRegion(void) const - { - return volumeData->getEnclosingRegion(); - } - - int32_t VolumeChangeTracker::getLastModifiedTimeForRegion(uint16_t uX, uint16_t uY, uint16_t uZ) - { - return volRegionLastModified->getVoxelAt(uX, uY, uZ); - } - - uint8_t VolumeChangeTracker::getVoxelAt(const Vector3DUint16& pos) - { - return getVoxelAt(pos.getX(), pos.getY(), pos.getZ()); - } - - uint8_t VolumeChangeTracker::getVoxelAt(uint16_t uX, uint16_t uY, uint16_t uZ) - { - assert(uX < volumeData->getSideLength()); - assert(uY < volumeData->getSideLength()); - assert(uZ < volumeData->getSideLength()); - - VolumeIterator volIter(*volumeData); - volIter.setPosition(uX,uY,uZ); - return volIter.getVoxel(); - } - - Volume* VolumeChangeTracker::getVolumeData(void) const - { - return volumeData; - } - - //NOTE - Document the fact that the time stamp is incremented at the start, not the end. - void VolumeChangeTracker::setVoxelAt(uint16_t x, uint16_t y, uint16_t z, uint8_t value) - { - ++m_iCurrentTime; - //FIXME - rather than creating a iterator each time we should have one stored - //VolumeIterator iterVol(*volumeData); - /*iterVol.setPosition(x,y,z); - iterVol.setVoxel(value);*/ - - volumeData->setVoxelAt(x,y,z,value); - - //If we are not on a boundary, just mark one region. - if((x % m_uRegionSideLength != 0) && - (x % m_uRegionSideLength != m_uRegionSideLength-1) && - (y % m_uRegionSideLength != 0) && - (y % m_uRegionSideLength != m_uRegionSideLength-1) && - (z % m_uRegionSideLength != 0) && - (z % m_uRegionSideLength != m_uRegionSideLength-1)) - { - volRegionLastModified->setVoxelAt(x >> m_uRegionSideLengthPower, y >> m_uRegionSideLengthPower, z >> m_uRegionSideLengthPower, m_iCurrentTime); - } - else //Mark surrounding regions as well - { - const uint16_t regionX = x >> m_uRegionSideLengthPower; - const uint16_t regionY = y >> m_uRegionSideLengthPower; - const uint16_t regionZ = z >> m_uRegionSideLengthPower; - - const uint16_t minRegionX = (std::max)(uint16_t(0),uint16_t(regionX-1)); - const uint16_t minRegionY = (std::max)(uint16_t(0),uint16_t(regionY-1)); - const uint16_t minRegionZ = (std::max)(uint16_t(0),uint16_t(regionZ-1)); - - const uint16_t maxRegionX = (std::min)(uint16_t(m_uVolumeSideLengthInRegions-1),uint16_t(regionX+1)); - const uint16_t maxRegionY = (std::min)(uint16_t(m_uVolumeSideLengthInRegions-1),uint16_t(regionY+1)); - const uint16_t maxRegionZ = (std::min)(uint16_t(m_uVolumeSideLengthInRegions-1),uint16_t(regionZ+1)); - - for(uint16_t zCt = minRegionZ; zCt <= maxRegionZ; zCt++) - { - for(uint16_t yCt = minRegionY; yCt <= maxRegionY; yCt++) - { - for(uint16_t xCt = minRegionX; xCt <= maxRegionX; xCt++) - { - volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_iCurrentTime); - } - } - } - } - //++m_iCurrentTime; - } - - void VolumeChangeTracker::setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, uint8_t value) - { - assert(m_bIsLocked); - - //FIXME - rather than creating a iterator each time we should have one stored - /*VolumeIterator iterVol(*volumeData); - iterVol.setPosition(x,y,z); - iterVol.setVoxel(value);*/ - volumeData->setVoxelAt(x,y,z,value); - } - - void VolumeChangeTracker::lockRegion(const Region& regToLock) - { - if(m_bIsLocked) - { - throw std::logic_error("A region is already locked. Please unlock it before locking another."); - } - - m_regLastLocked = regToLock; - m_bIsLocked = true; - } - - void VolumeChangeTracker::unlockRegion(void) - { - ++m_iCurrentTime; - if(!m_bIsLocked) - { - throw std::logic_error("No region is locked. You must lock a region before you can unlock it."); - } - - const uint16_t firstRegionX = m_regLastLocked.getLowerCorner().getX() >> m_uRegionSideLengthPower; - const uint16_t firstRegionY = m_regLastLocked.getLowerCorner().getY() >> m_uRegionSideLengthPower; - const uint16_t firstRegionZ = m_regLastLocked.getLowerCorner().getZ() >> m_uRegionSideLengthPower; - - const uint16_t lastRegionX = m_regLastLocked.getUpperCorner().getX() >> m_uRegionSideLengthPower; - const uint16_t lastRegionY = m_regLastLocked.getUpperCorner().getY() >> m_uRegionSideLengthPower; - const uint16_t lastRegionZ = m_regLastLocked.getUpperCorner().getZ() >> m_uRegionSideLengthPower; - - for(uint16_t zCt = firstRegionZ; zCt <= lastRegionZ; zCt++) - { - for(uint16_t yCt = firstRegionY; yCt <= lastRegionY; yCt++) - { - for(uint16_t xCt = firstRegionX; xCt <= lastRegionX; xCt++) - { - volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_iCurrentTime); - } - } - } - - //++m_iCurrentTime; - m_bIsLocked = false; - } -}