From b10b995a846ebd7583feb6f2a65ebe8b4144e7f0 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 Nov 2012 18:13:41 +0100 Subject: [PATCH 1/5] Fixed compiler warning. --- library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl index 4e679477..54df09c5 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl @@ -622,8 +622,8 @@ namespace PolyVox template float LargeVolume::calculateCompressionRatio(void) { - float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType); - float fCompressedSize = calculateSizeInBytes(); + float fRawSize = static_cast(m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType)); + float fCompressedSize = static_cast(calculateSizeInBytes()); return fCompressedSize/fRawSize; } From a026546bb40683a877fd39ae1f4298dc4abc6b12 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 Nov 2012 18:16:32 +0100 Subject: [PATCH 2/5] Making some functions in Vector use the new 'OperationType'. --- .../PolyVoxCore/include/PolyVoxCore/Vector.h | 8 +++---- .../include/PolyVoxCore/Vector.inl | 22 +++++++++---------- tests/testvector.cpp | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Vector.h b/library/PolyVoxCore/include/PolyVoxCore/Vector.h index 9f4b51de..fc689dc5 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Vector.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Vector.h @@ -131,15 +131,15 @@ namespace PolyVox void setW(StorageType tW); ///Get the length of the vector. - double length(void) const; + float length(void) const; ///Get the squared length of the vector. - double lengthSquared(void) const; + OperationType lengthSquared(void) const; ///Find the angle between this vector and that which is passed as a parameter. - double angleTo(const Vector& vector) const; + float angleTo(const Vector& vector) const; ///Find the cross product between this vector and the vector passed as a parameter. Vector cross(const Vector& vector) const; ///Find the dot product between this vector and the vector passed as a parameter. - StorageType dot(const Vector& rhs) const; + OperationType dot(const Vector& rhs) const; ///Normalise the vector. void normalise(void); diff --git a/library/PolyVoxCore/include/PolyVoxCore/Vector.inl b/library/PolyVoxCore/include/PolyVoxCore/Vector.inl index 504c4fbb..c93a0b9b 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Vector.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Vector.inl @@ -573,23 +573,23 @@ namespace PolyVox \return Length of the Vector. */ template - inline double Vector::length(void) const + inline float Vector::length(void) const { - return sqrt(lengthSquared()); + return sqrt(static_cast(lengthSquared())); } /** \return Squared length of the Vector. */ template - inline double Vector::lengthSquared(void) const + inline OperationType Vector::lengthSquared(void) const { - double result = 0.0f; + OperationType tLengthSquared = static_cast(0); for(uint32_t ct = 0; ct < Size; ++ct) { - result += m_tElements[ct] * m_tElements[ct]; + tLengthSquared += static_cast(m_tElements[ct]) * static_cast(m_tElements[ct]); } - return result; + return tLengthSquared; } /** @@ -602,9 +602,9 @@ namespace PolyVox \return The angle between them in radians. */ template - inline double Vector::angleTo(const Vector& vector) const + inline float Vector::angleTo(const Vector& vector) const { - return acos(dot(vector) / (vector.length() * this->length())); + return acos(static_cast(dot(vector)) / (vector.length() * this->length())); } /** @@ -636,12 +636,12 @@ namespace PolyVox \see cross() */ template - inline StorageType Vector::dot(const Vector& rhs) const + inline OperationType Vector::dot(const Vector& rhs) const { - StorageType dotProduct = static_cast(0); + OperationType dotProduct = static_cast(0); for(uint32_t ct = 0; ct < Size; ++ct) { - dotProduct += m_tElements[ct] * rhs.m_tElements[ct]; + dotProduct += static_cast(m_tElements[ct]) * static_cast(rhs.m_tElements[ct]); } return dotProduct; } diff --git a/tests/testvector.cpp b/tests/testvector.cpp index 0239bd0f..78d24383 100644 --- a/tests/testvector.cpp +++ b/tests/testvector.cpp @@ -32,7 +32,7 @@ using namespace PolyVox; void TestVector::testLength() { Vector3DInt8 vec(3, 4, 5); - QCOMPARE(vec.lengthSquared(), double(3*3+4*4+5*5)); + QCOMPARE(vec.lengthSquared(), int32_t(3*3+4*4+5*5)); // QCOMPARE is strict on types. For an int8 vector, the OperationType is int32_t. } void TestVector::testDotProduct() @@ -40,7 +40,7 @@ void TestVector::testDotProduct() Vector3DInt8 vecxy(3, 4, 0); Vector3DInt8 vecz(0, 0, 1); - QCOMPARE(vecxy.dot(vecz), int8_t(0)); //QCOMPARE is very strict on the types matching + QCOMPARE(vecxy.dot(vecz), int32_t(0)); // QCOMPARE is strict on types. For an int8 vector, the OperationType is int32_t . } void TestVector::testEquality() From 8792d1bd481011e03cea56cfe0cfb317dc59520f Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 2 Dec 2012 14:15:34 +0100 Subject: [PATCH 3/5] Fixed build error on VS2008 --- library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h b/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h index 5775c4ba..81ddb9e5 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h +++ b/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h @@ -24,7 +24,7 @@ freely, subject to the following restrictions: #ifndef __PolyVox_DefaultIsQuadNeeded_H__ #define __PolyVox_DefaultIsQuadNeeded_H__ -#include +#include "PolyVoxCore/Impl/TypeDef.h" namespace PolyVox { From e7f4c69102ac51ec51b4c89f0cb2a6f99f901adb Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 2 Dec 2012 14:17:41 +0100 Subject: [PATCH 4/5] Fixed bug with peek function checking in wrong direction. --- library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl b/library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl index 758e578d..39f51f3e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl @@ -238,7 +238,7 @@ namespace PolyVox template VoxelType RawVolume::Sampler::peekVoxel0px1ny1nz(void) const { - if( BORDER_LOWX(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) ) + if( BORDER_LOWY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) ) { return *(mCurrentVoxel - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } From 7e38fc135e1ab08ed0f56e30b06cee106038d130 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 3 Dec 2012 21:22:57 +0100 Subject: [PATCH 5/5] Removed features which were deprecated in release 0.2. --- CHANGELOG.txt | 4 + library/PolyVoxCore/CMakeLists.txt | 5 - .../include/PolyVoxCore/MeshDecimator.h | 187 -------- .../include/PolyVoxCore/MeshDecimator.inl | 347 -------------- .../include/PolyVoxCore/SimpleInterface.h | 46 -- library/PolyVoxCore/source/MeshDecimator.cpp | 181 -------- .../PolyVoxCore/source/SimpleInterface.cpp | 43 -- library/PolyVoxUtil/CMakeLists.txt | 5 +- .../include/PolyVoxUtil/Placeholder.txt | 1 + .../include/PolyVoxUtil/Serialization.h | 77 ---- .../include/PolyVoxUtil/Serialization.inl | 433 ------------------ .../include/PolyVoxUtil/VolumeChangeTracker.h | 83 ---- .../PolyVoxUtil/VolumeChangeTracker.inl | 212 --------- 13 files changed, 6 insertions(+), 1618 deletions(-) delete mode 100644 library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.h delete mode 100644 library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.inl delete mode 100644 library/PolyVoxCore/include/PolyVoxCore/SimpleInterface.h delete mode 100644 library/PolyVoxCore/source/MeshDecimator.cpp delete mode 100644 library/PolyVoxCore/source/SimpleInterface.cpp create mode 100644 library/PolyVoxUtil/include/PolyVoxUtil/Placeholder.txt delete mode 100644 library/PolyVoxUtil/include/PolyVoxUtil/Serialization.h delete mode 100644 library/PolyVoxUtil/include/PolyVoxUtil/Serialization.inl delete mode 100644 library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.h delete mode 100644 library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.inl diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2fdb7e5a..f0464eb1 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -7,6 +7,10 @@ Removed functionality Functionality deprecated for the previous release has now been removed. This includes: - Region::getWidth() and related functions. You should now use Region::getWidthInVoxels() or Region::getWidthInCells. + - The MeshDecimator. We don't have a direct replacement for this so you should consider an alternative such as downsampling the volume or using an external mesh processing library. + - The SimpleInterface. This was primarily for the bindings, and we are making other efforts to get those working. + - Serialisation. You should implement ay required serialisation yourself. + - This had a number of problems and was a little too high-level for PolyVox. You should implement change tracking yourself. The Region class has been tidied up and enhanced with new functionality. It now contains functions for growing and shrinking regions, as well as 'accumulate()' functions which ensure the Region contains a given point. The concept of an invalid region has also been introduced - this is one whose lower corner is greater than it's upper corner. diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index e4b4f443..a8bae984 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -29,9 +29,7 @@ SET(CORE_SRC_FILES source/ArraySizes.cpp source/AStarPathfinder.cpp source/Log.cpp - source/MeshDecimator.cpp source/Region.cpp - source/SimpleInterface.cpp source/VertexTypes.cpp ) @@ -70,8 +68,6 @@ SET(CORE_INC_FILES include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl include/PolyVoxCore/Material.h include/PolyVoxCore/MaterialDensityPair.h - include/PolyVoxCore/MeshDecimator.h - include/PolyVoxCore/MeshDecimator.inl include/PolyVoxCore/PolyVoxForwardDeclarations.h include/PolyVoxCore/RawVolume.h include/PolyVoxCore/RawVolume.inl @@ -79,7 +75,6 @@ SET(CORE_INC_FILES include/PolyVoxCore/Raycast.h include/PolyVoxCore/Raycast.inl include/PolyVoxCore/Region.h - include/PolyVoxCore/SimpleInterface.h include/PolyVoxCore/SimpleVolume.h include/PolyVoxCore/SimpleVolume.inl include/PolyVoxCore/SimpleVolumeBlock.inl diff --git a/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.h b/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.h deleted file mode 100644 index 9b8dafb9..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.h +++ /dev/null @@ -1,187 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_MeshDecimator_H__ -#define __PolyVox_MeshDecimator_H__ - -#include "PolyVoxCore/SurfaceMesh.h" -#include "PolyVoxCore/Vector.h" -#include "PolyVoxCore/VertexTypes.h" - -#include -#include - -namespace PolyVox -{ - /// The MeshDecimator reduces the number of triangles in a mesh. - //////////////////////////////////////////////////////////////////////////////// - /// Meshes generated by the PolyVox surface extractors typically have a very high - /// number of triangles in them. This can pose difficulties both for the rendering - /// storage of such meshes. The MeshDecimator provides a way of reducing the triangle - /// count with minimal visual effect. - /// - /// The MeshDecimator is based on the principle of edge collapse, and currently works - /// with meshes generated by the MarchingCubesSurfaceExtractor or CubicSurfaceExtractor. It does - /// not work with meshes generated by the CubicSurfaceExtractorWithNormals, although - /// this may be addressed in the future. The algorithm iterates over each pair of - /// connected vertices in the mesh and attemps to determine if they can be collapsed - /// into a single vertex. - /// - /// The main criteria used in deciding whether two vertices can collapse is whether - /// they have the same normal. In the case of the cubic surfaces the normals must be - /// exactly the same, whereas in the case of the Marching Cubes surfaces a threshold - /// is used to determine whether two normals are 'close enough'. Additional constraints - /// apply to vertices which lie on the edges of regions or on the boundary between two - /// regions - these vertices are much less likely to be collapsed. - /// - /// Given a mesh called 'mesh', you can create a decimated version as follows: - /// \code - /// SurfaceMesh decimatedMesh; - /// MeshDecimator decimator(&mesh, &decimatedMesh); - /// decimator.execute(); - /// \endcode - /// - /// The above applies for a cubic mesh, for a Marching Cubes mesh you need to parametise - /// the MeshDecimator and resulting SurfaceMesh on the 'PositionMaterialNormal' type - /// instead of the 'PositionMaterial' type. - /// - /// \deprecated - template - class MeshDecimator - { - //Used to keep track of when a vertex is - //on one or more faces of the region - enum RegionFaceFlags - { - RFF_ON_REGION_FACE_NEG_X, - RFF_ON_REGION_FACE_POS_X , - RFF_ON_REGION_FACE_NEG_Y , - RFF_ON_REGION_FACE_POS_Y , - RFF_ON_REGION_FACE_NEG_Z , - RFF_ON_REGION_FACE_POS_Z, - RFF_NO_OF_REGION_FACE_FLAGS - }; - - //Data about the initial mesh - this - //will be fill in once at the start - struct InitialVertexMetadata - { - Vector3DFloat normal; - bool isOnMaterialEdge; - std::bitset isOnRegionFace; - }; - - //Representing a triangle for decimation purposes. - struct Triangle - { - uint32_t v0; - uint32_t v1; - uint32_t v2; - Vector3DFloat normal; - }; - - struct IntVertex - { - int32_t x; - int32_t y; - int32_t z; - uint32_t index; - - IntVertex(int32_t xVal, int32_t yVal, int32_t zVal, uint32_t indexVal) - :x(xVal) - ,y(yVal) - ,z(zVal) - ,index(indexVal) - { - } - - bool operator==(const IntVertex& rhs) const - { - return (x == rhs.x) && (y == rhs.y) && (z == rhs.z); - } - - bool operator<(const IntVertex& rhs) const - { - if (z < rhs.z) - return true; - if (rhs.z < z) - return false; - - if (y < rhs.y) - return true; - if (rhs.y < y) - return false; - - if (x < rhs.x) - return true; - if (rhs.x < x) - return false; - - return false; - } - }; - - public: - ///Constructor - POLYVOX_DEPRECATED MeshDecimator(const SurfaceMesh* pInputMesh, SurfaceMesh* pOutputMesh, float fEdgeCollapseThreshold = 0.95f); - - ///Performs the decimation. - POLYVOX_DEPRECATED void execute(); - - private: - - void fillInitialVertexMetadata(std::vector& vecInitialVertexMetadata); - - void buildConnectivityData(void); - - bool attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst); - - const SurfaceMesh* m_pInputMesh; - SurfaceMesh* m_pOutputMesh; - - uint32_t performDecimationPass(float m_fMinDotProductForCollapse); - bool isSubset(std::bitset a, std::bitset b); - - bool canCollapseEdge(uint32_t uSrc, uint32_t uDst); - bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst); - bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst); - bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDst); - bool collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold); - - //Data structures used during decimation - - std::vector vertexLocked; - std::vector vertexMapper; - - std::vector m_vecTriangles; - std::vector< std::vector > trianglesUsingVertex; //Should probably use vector of vectors, and resise in advance. - - std::vector m_vecInitialVertexMetadata; - - float m_fMinDotProductForCollapse; - }; -} - -#include "PolyVoxCore/MeshDecimator.inl" - -#endif //__PolyVox_MeshDecimator_H__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.inl b/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.inl deleted file mode 100644 index 4a1df584..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.inl +++ /dev/null @@ -1,347 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -namespace PolyVox -{ - //////////////////////////////////////////////////////////////////////////////// - /// Builds a MeshDecimator. - /// \param pInputMesh A pointer to the mesh to be decimated. - /// \param[out] pOutputMesh A pointer to where the result should be stored. Any existing - /// contents will be deleted. - /// \param fEdgeCollapseThreshold This is only use in the case of a Marching Cubes - /// surface and controls how close two normals must be to collapse. The dot product - /// between the normals is computed and compared to this threshold. A threshold of - /// 1.0 means nothing will collapse, a threshold of 0.0 means everything will collapse. - //////////////////////////////////////////////////////////////////////////////// - template - MeshDecimator::MeshDecimator(const SurfaceMesh* pInputMesh, SurfaceMesh* pOutputMesh, float fEdgeCollapseThreshold) - :m_pInputMesh(pInputMesh) - ,m_pOutputMesh(pOutputMesh) - ,m_fMinDotProductForCollapse(fEdgeCollapseThreshold) - { - *m_pOutputMesh = *m_pInputMesh; - } - - template - void MeshDecimator::execute() - { - //Sanity check. - if((m_pOutputMesh->m_vecVertices.empty()) || (m_pOutputMesh->m_vecTriangleIndices.empty())) - { - return; - } - - buildConnectivityData(); - fillInitialVertexMetadata(m_vecInitialVertexMetadata); - - uint32_t noOfEdgesCollapsed; - do - { - noOfEdgesCollapsed = performDecimationPass(m_fMinDotProductForCollapse); - m_pOutputMesh->removeDegenerateTris(); - if(noOfEdgesCollapsed > 0) - { - //Build the connectivity data for the next pass. If this is slow, then look - //at adjusting it (based on vertex mapper?) rather than bulding from scratch. - buildConnectivityData(); - } - }while(noOfEdgesCollapsed > 0); - - m_pOutputMesh->removeUnusedVertices(); - - //Decimation will have invalidated LOD levels. - m_pOutputMesh->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = m_pOutputMesh->getNoOfIndices(); - m_pOutputMesh->m_vecLodRecords.push_back(lodRecord); - } - - template - void MeshDecimator::buildConnectivityData(void) - { - //Build a list of all the triangles, complete with face normals. - m_vecTriangles.clear(); - m_vecTriangles.resize(m_pOutputMesh->m_vecTriangleIndices.size() / 3); - for(uint32_t triCt = 0; triCt < m_vecTriangles.size(); triCt++) - { - m_vecTriangles[triCt].v0 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 0]; - m_vecTriangles[triCt].v1 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 1]; - m_vecTriangles[triCt].v2 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 2]; - - Vector3DFloat v0Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v0].position; - Vector3DFloat v1Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v1].position; - Vector3DFloat v2Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v2].position; - - Vector3DFloat v0v1 = v1Pos - v0Pos; - Vector3DFloat v0v2 = v2Pos - v0Pos; - Vector3DFloat normal = v0v1.cross(v0v2); - normal.normalise(); - - m_vecTriangles[triCt].normal = normal; - } - - //For each vertex, determine which triangles are using it. - trianglesUsingVertex.clear(); - trianglesUsingVertex.resize(m_pOutputMesh->m_vecVertices.size()); - for(uint32_t ct = 0; ct < trianglesUsingVertex.size(); ct++) - { - trianglesUsingVertex[ct].reserve(6); - } - for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++) - { - trianglesUsingVertex[m_vecTriangles[ct].v0].push_back(ct); - trianglesUsingVertex[m_vecTriangles[ct].v1].push_back(ct); - trianglesUsingVertex[m_vecTriangles[ct].v2].push_back(ct); - } - } - - template - uint32_t MeshDecimator::performDecimationPass(float /*m_fMinDotProductForCollapse*/) - { - // Count how many edges we have collapsed - uint32_t noOfEdgesCollapsed = 0; - - // The vertex mapper track whick vertices collapse onto which. - vertexMapper.clear(); - vertexMapper.resize(m_pOutputMesh->m_vecVertices.size()); - - // Once a vertex is involved in a collapse (either because it - // moves onto a different vertex, or because a different vertex - // moves onto it) it is forbidden to take part in another collapse - // this pass. We enforce this by setting the vertex locked flag. - vertexLocked.clear(); - vertexLocked.resize(m_pOutputMesh->m_vecVertices.size()); - - // Initialise the vectors - for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++) - { - // Initiall all vertices points to themselves - vertexMapper[ct] = ct; - // All vertices are initially unlocked - vertexLocked[ct] = false; - } - - //For each triangle... - for(uint32_t ctIter = 0; ctIter < m_vecTriangles.size(); ctIter++) - { - if(attemptEdgeCollapse(m_vecTriangles[ctIter].v0, m_vecTriangles[ctIter].v1)) - { - ++noOfEdgesCollapsed; - } - - if(attemptEdgeCollapse(m_vecTriangles[ctIter].v1, m_vecTriangles[ctIter].v2)) - { - ++noOfEdgesCollapsed; - } - - if(attemptEdgeCollapse(m_vecTriangles[ctIter].v2, m_vecTriangles[ctIter].v0)) - { - ++noOfEdgesCollapsed; - } - } - - if(noOfEdgesCollapsed > 0) - { - //Fix up the indices - for(uint32_t triCt = 0; triCt < m_pOutputMesh->m_vecTriangleIndices.size(); triCt++) - { - uint32_t before = m_pOutputMesh->m_vecTriangleIndices[triCt]; - uint32_t after = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]]; - if(before != after) - { - m_pOutputMesh->m_vecTriangleIndices[triCt] = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]]; - } - } - } - - return noOfEdgesCollapsed; - } - - template - bool MeshDecimator::attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst) - { - //A vertex will be locked if it has already been involved in a collapse this pass. - if(vertexLocked[uSrc] || vertexLocked[uDst]) - { - return false; - } - - if(canCollapseEdge(uSrc, uDst)) - { - //Move v0 onto v1 - vertexMapper[uSrc] = uDst; //vertexMapper[v1]; - vertexLocked[uSrc] = true; - vertexLocked[uDst] = true; - - //Increment the counter - return true; - } - - return false; - } - - template - bool MeshDecimator::canCollapseEdge(uint32_t uSrc, uint32_t uDst) - { - bool bCanCollapse = true; - - if(m_vecInitialVertexMetadata[uSrc].isOnMaterialEdge) - { - bCanCollapse &= canCollapseMaterialEdge(uSrc, uDst); - } - - if(m_vecInitialVertexMetadata[uSrc].isOnRegionFace.any()) - { - bCanCollapse &= canCollapseRegionEdge(uSrc, uDst); - } - - if(bCanCollapse) //Only bother with this if the earlier tests passed. - { - bCanCollapse &= canCollapseNormalEdge(uSrc, uDst); - } - - return bCanCollapse; - } - - template - bool MeshDecimator::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst) - { - // We can collapse normal vertices onto edge vertices, and edge vertices - // onto corner vertices, but not vice-versa. Hence we check whether all - // the edge flags in the source vertex are also set in the destination vertex. - if(isSubset(m_vecInitialVertexMetadata[uSrc].isOnRegionFace, m_vecInitialVertexMetadata[uDst].isOnRegionFace) == false) - { - return false; - } - - // In general adjacent regions surface meshes may collapse differently - // and this can cause cracks. We solve this by only allowing the collapse - // is the normals are exactly the same. We do not use the user provided - // tolerence here (but do allow for floating point error). - if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[uDst].normal) < 0.999f) - { - return false; - } - - return true; - } - - template - bool MeshDecimator::canCollapseMaterialEdge(uint32_t /*uSrc*/, uint32_t /*uDst*/) - { - return false; - } - - //This function should really use some work. For a start we already have the - //faces normals for the input mesh yet we are computing them on the fly here. - template - bool MeshDecimator::collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold) - { - bool faceFlipped = false; - std::vector& triangles = trianglesUsingVertex[uSrc]; - - for(std::vector::iterator triIter = triangles.begin(); triIter != triangles.end(); triIter++) - { - uint32_t tri = *triIter; - - const uint32_t& v0Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3]; - const uint32_t& v1Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 1]; - const uint32_t& v2Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 2]; - - //Check if degenerate - if((v0Old == v1Old) || (v1Old == v2Old) || (v2Old == v0Old)) - { - continue; - } - - uint32_t v0New = v0Old; - uint32_t v1New = v1Old; - uint32_t v2New = v2Old; - - if(v0New == uSrc) - v0New = uDst; - if(v1New == uSrc) - v1New = uDst; - if(v2New == uSrc) - v2New = uDst; - - //Check if degenerate - if((v0New == v1New) || (v1New == v2New) || (v2New == v0New)) - { - continue; - } - - const Vector3DFloat& v0OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition(); //Note: we need the vertex mapper here. These neighbouring vertices may have been moved. - const Vector3DFloat& v1OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition(); - const Vector3DFloat& v2OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition(); - - const Vector3DFloat& v0NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0New]].getPosition(); - const Vector3DFloat& v1NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1New]].getPosition(); - const Vector3DFloat& v2NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2New]].getPosition(); - - Vector3DFloat OldNormal = (v1OldPos - v0OldPos).cross(v2OldPos - v1OldPos); - Vector3DFloat NewNormal = (v1NewPos - v0NewPos).cross(v2NewPos - v1NewPos); - - OldNormal.normalise(); - NewNormal.normalise(); - - float dotProduct = OldNormal.dot(NewNormal); - //NOTE: I don't think we should be using the threshold here, we're just checking for a complete face flip - if(dotProduct < fThreshold) - { - //cout << " Face flipped!!" << endl; - - faceFlipped = true; - - /*vertexLocked[v0] = true; - vertexLocked[v1] = true;*/ - - break; - } - } - - return faceFlipped; - } - - // Returns true if every bit which is set in 'a' is also set in 'b'. The reverse does not need to be true. - template - bool MeshDecimator::isSubset(std::bitset a, std::bitset b) - { - bool result = true; - - for(int ct = 0; ct < RFF_NO_OF_REGION_FACE_FLAGS; ct++) - { - if(a.test(ct)) - { - if(b.test(ct) == false) - { - result = false; - break; - } - } - } - - return result; - } -} diff --git a/library/PolyVoxCore/include/PolyVoxCore/SimpleInterface.h b/library/PolyVoxCore/include/PolyVoxCore/SimpleInterface.h deleted file mode 100644 index f0fbac99..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/SimpleInterface.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_SimpleInterface_H__ -#define __PolyVox_SimpleInterface_H__ - -#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h" -#include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/SimpleVolume.h" -#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" - -namespace PolyVox -{ - //The PolyVox simple interface only exposes one voxel type and one volume type. But if you like you can - //adjust these typedefs and rebuild the library in order to modify which one volume and voxel is exposed. - typedef SimpleVolume Volume; - typedef SurfaceMesh Mesh; - - /// \deprecated - POLYVOX_DEPRECATED void extractCubicMesh(Volume& volume, const Region& region, Mesh& resultMesh); - /// \deprecated - POLYVOX_DEPRECATED void extractSmoothMesh(Volume& volume, const Region& region, Mesh& resultMesh); - -} - -#endif //__PolyVox_SimpleInterface_H__ diff --git a/library/PolyVoxCore/source/MeshDecimator.cpp b/library/PolyVoxCore/source/MeshDecimator.cpp deleted file mode 100644 index 8df0ca39..00000000 --- a/library/PolyVoxCore/source/MeshDecimator.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#include "PolyVoxCore/MeshDecimator.h" -#include "PolyVoxCore/SurfaceMesh.h" - -using namespace std; - -namespace PolyVox -{ - template<> - POLYVOX_API void MeshDecimator::fillInitialVertexMetadata(std::vector& vecVertexMetadata) - { - vecVertexMetadata.clear(); - vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size()); - //Initialise the metadata - for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++) - { - vecVertexMetadata[ct].normal.setElements(0,0,0); - vecVertexMetadata[ct].isOnMaterialEdge = false; - vecVertexMetadata[ct].isOnRegionFace.reset(); - } - - //Identify duplicate vertices, as they lie on the material edge. To do this we convert into integers and sort - //(first on z, then y, then x). They should be mostly in order as this is the order they come out of the - //CubicSurfaceExtractor in. Duplicates are now neighbours in the resulting list so just scan through for pairs. - std::vector intVertices; - intVertices.reserve(m_pOutputMesh->m_vecVertices.size()); - for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++) - { - const Vector3DFloat& floatPos = m_pOutputMesh->m_vecVertices[ct].position; - IntVertex intVertex(static_cast(floatPos.getX()), static_cast(floatPos.getY()), static_cast(floatPos.getZ()), ct); - intVertices.push_back(intVertex); - } - - //Do the sorting so that duplicate become neighbours - sort(intVertices.begin(), intVertices.end()); - - //Find neighbours which are duplicates. - for(uint32_t ct = 0; ct < intVertices.size() - 1; ct++) - { - const IntVertex& v0 = intVertices[ct+0]; - const IntVertex& v1 = intVertices[ct+1]; - - if((v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z)) - { - vecVertexMetadata[v0.index].isOnMaterialEdge = true; - vecVertexMetadata[v1.index].isOnMaterialEdge = true; - } - } - - //Compute an approcimation to the normal, used when deciding if an edge can collapse. - for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++) - { - Vector3DFloat sumOfNormals(0.0f,0.0f,0.0f); - for(vector::iterator iter = trianglesUsingVertex[ct].begin(); iter != trianglesUsingVertex[ct].end(); iter++) - { - sumOfNormals += m_vecTriangles[*iter].normal; - } - - vecVertexMetadata[ct].normal = sumOfNormals; - vecVertexMetadata[ct].normal.normalise(); - } - - //Identify those vertices on the edge of a region. Care will need to be taken when moving them. - for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++) - { - Region regTransformed = m_pOutputMesh->m_Region; - regTransformed.shift(regTransformed.getLowerCorner() * static_cast(-1)); - - //Plus and minus X - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f); - //Plus and minus Y - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f); - //Plus and minus Z - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f); - } - } - - template<> - POLYVOX_API void MeshDecimator::fillInitialVertexMetadata(std::vector& vecVertexMetadata) - { - vecVertexMetadata.clear(); - vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size()); - - //Initialise the metadata - for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++) - { - vecVertexMetadata[ct].isOnRegionFace.reset(); - vecVertexMetadata[ct].isOnMaterialEdge = false; - vecVertexMetadata[ct].normal = m_pOutputMesh->m_vecVertices[ct].normal; - } - - //Identify those vertices on the edge of a region. Care will need to be taken when moving them. - for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++) - { - Region regTransformed = m_pOutputMesh->m_Region; - regTransformed.shift(regTransformed.getLowerCorner() * static_cast(-1)); - - //Plus and minus X - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f); - //Plus and minus Y - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f); - //Plus and minus Z - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f); - } - - //If all three vertices have the same material then we are not on a material edge. If any vertex has a different - //material then all three vertices are on a material edge. E.g. If one vertex has material 'a' and the other two - //have material 'b', then the two 'b's are still on an edge (with 'a') even though they are the same as eachother. - for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++) - { - uint32_t v0 = m_vecTriangles[ct].v0; - uint32_t v1 = m_vecTriangles[ct].v1; - uint32_t v2 = m_vecTriangles[ct].v2; - - bool allMatch = - (m_pOutputMesh->m_vecVertices[v0].material - m_pOutputMesh->m_vecVertices[v1].material < 0.001f) && - (m_pOutputMesh->m_vecVertices[v1].material - m_pOutputMesh->m_vecVertices[v2].material < 0.001f); - - if(!allMatch) - { - vecVertexMetadata[v0].isOnMaterialEdge = true; - vecVertexMetadata[v1].isOnMaterialEdge = true; - vecVertexMetadata[v2].isOnMaterialEdge = true; - } - } - } - - template<> - POLYVOX_API bool MeshDecimator::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst) - { - if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[uDst].normal) < m_fMinDotProductForCollapse) - { - return false; - } - - //With the marching cubes surface we honour the user specified threshold - return !collapseChangesFaceNormals(uSrc, uDst, m_fMinDotProductForCollapse); - } - - template<> - POLYVOX_API bool MeshDecimator::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst) - { - //We don't actually use the normal here, because we want to allow face - //vertices to collapse onto edge vertices. Simply checking whether anything - //has flipped has proved to be the most robust approach, though rather slow. - //It's not sufficient to just check the normals, there can be holes in the middle - //of the mesh for example. - - //User specified threshold is not used for cubic surface, any - //movement is too much (but allow for floating point error). - return !collapseChangesFaceNormals(uSrc, uDst, 0.999f); - } -} diff --git a/library/PolyVoxCore/source/SimpleInterface.cpp b/library/PolyVoxCore/source/SimpleInterface.cpp deleted file mode 100644 index e098e175..00000000 --- a/library/PolyVoxCore/source/SimpleInterface.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#include "PolyVoxCore/SimpleInterface.h" - -//DOESN'T BELONG HERE - JUST FOR TESTING!! -#include "PolyVoxCore/Density.h" -#include "PolyVoxCore/MaterialDensityPair.h" - -namespace PolyVox -{ - void extractCubicMesh(Volume& volume, const Region& region, Mesh& resultMesh) - { - CubicSurfaceExtractorWithNormals< SimpleVolume > surfaceExtractor(&volume, region, &resultMesh); - surfaceExtractor.execute(); - } - - void extractSmoothMesh(Volume& volume, const Region& region, Mesh& resultMesh) - { - MarchingCubesSurfaceExtractor< SimpleVolume > surfaceExtractor(&volume, region, &resultMesh); - surfaceExtractor.execute(); - } -} diff --git a/library/PolyVoxUtil/CMakeLists.txt b/library/PolyVoxUtil/CMakeLists.txt index 97dbb8da..85065346 100644 --- a/library/PolyVoxUtil/CMakeLists.txt +++ b/library/PolyVoxUtil/CMakeLists.txt @@ -31,10 +31,7 @@ SET(UTIL_SRC_FILES #Projects headers files SET(UTIL_INC_FILES - include/PolyVoxUtil/Serialization.h - include/PolyVoxUtil/Serialization.inl - include/PolyVoxUtil/VolumeChangeTracker.h - include/PolyVoxUtil/VolumeChangeTracker.inl + #Nothing here at the moment... ) ADD_DEFINITIONS(-DPOLYVOX_SHARED_EXPORTS) #Export symbols in the .dll diff --git a/library/PolyVoxUtil/include/PolyVoxUtil/Placeholder.txt b/library/PolyVoxUtil/include/PolyVoxUtil/Placeholder.txt new file mode 100644 index 00000000..eb0a80de --- /dev/null +++ b/library/PolyVoxUtil/include/PolyVoxUtil/Placeholder.txt @@ -0,0 +1 @@ +I don't think Git allows empty directories, so this is just a placeholder until we decide what to do with PolyVoxUtil. \ No newline at end of file diff --git a/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.h b/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.h deleted file mode 100644 index f2a2f9ed..00000000 --- a/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_Serialization_H__ -#define __PolyVox_Serialization_H__ - -#include "PolyVoxCore/Impl/Utility.h" - -#include "PolyVoxCore/Region.h" - -#include -#include - -namespace PolyVox -{ - /// \deprecated - class POLYVOX_DEPRECATED VolumeSerializationProgressListener - { - public: - virtual void onProgressUpdated(float fProgress) = 0; - }; - - //////////////////////////////////////////////////////////////////////////////// - // THESE FUNCTIONS ARE DEPRECATED. - //////////////////////////////////////////////////////////////////////////////// - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED polyvox_shared_ptr< VolumeType > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0); - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED void saveVolumeRaw(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0); - - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED polyvox_shared_ptr< VolumeType > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0); - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED void saveVolumeRle(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0); - - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED bool loadVolume(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0); - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED bool saveVolume(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0); - - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED bool loadVersion0(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0); - /// \deprecated - template< typename VolumeType > - POLYVOX_DEPRECATED bool saveVersion0(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0); -} - -#include "PolyVoxUtil/Serialization.inl" - -#endif diff --git a/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.inl b/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.inl deleted file mode 100644 index f251af9e..00000000 --- a/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.inl +++ /dev/null @@ -1,433 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -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 - template< typename VolumeType > - polyvox_shared_ptr< VolumeType > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener) - { - assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP. - - //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 - polyvox_shared_ptr< VolumeType > volume(new LargeVolume(volumeWidth, volumeHeight, volumeDepth)); - - //Read data - for(uint16_t z = 0; z < volumeDepth; ++z) - { - //Update progress once per slice. - if(progressListener) - { - float fProgress = static_cast(z) / static_cast(volumeDepth); - progressListener->onProgressUpdated(fProgress); - } - - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - VolumeType::VoxelType value; - stream.read(reinterpret_cast(&value), sizeof(value)); - - volume->setVoxelAt(x,y,z,value); - } - } - } - - //Finished - if(progressListener) - { - progressListener->onProgressUpdated(1.0f); - } - - return volume; - } - - template< typename VolumeType > - void saveVolumeRaw(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener) - { - assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP. - - //Write volume dimensions - uint16_t volumeWidth = volume.getWidth(); - uint16_t volumeHeight = volume.getHeight(); - uint16_t volumeDepth = volume.getDepth(); - - 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 - VolumeType::Sampler volIter(&volume); - for(uint16_t z = 0; z < volumeDepth; ++z) - { - //Update progress once per slice. - if(progressListener) - { - float fProgress = static_cast(z) / static_cast(volumeDepth); - progressListener->onProgressUpdated(fProgress); - } - - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - volIter.setPosition(x,y,z); - VolumeType::VoxelType value = volIter.getVoxel(); - stream.write(reinterpret_cast(&value), sizeof(value)); - } - } - } - - //Finished - if(progressListener) - { - progressListener->onProgressUpdated(1.0f); - } - } - - //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 - template< typename VolumeType > - polyvox_shared_ptr< VolumeType > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener) - { - assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP. - - //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 - polyvox_shared_ptr< VolumeType > volume(new LargeVolume(volumeWidth, volumeHeight, volumeDepth)); - - //Read data - bool firstTime = true; - uint32_t runLength = 0; - VolumeType::VoxelType value; - stream.read(reinterpret_cast(&value), sizeof(value)); - stream.read(reinterpret_cast(&runLength), sizeof(runLength)); - for(uint16_t z = 0; z < volumeDepth; ++z) - { - //Update progress once per slice. - if(progressListener) - { - float fProgress = static_cast(z) / static_cast(volumeDepth); - progressListener->onProgressUpdated(fProgress); - } - - 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--; - } - } - } - } - - //Finished - if(progressListener) - { - progressListener->onProgressUpdated(1.0f); - } - - return volume; - } - - template< typename VolumeType > - void saveVolumeRle(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener) - { - assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP. - - //Write volume dimensions - uint16_t volumeWidth = volume.getWidth(); - uint16_t volumeHeight = volume.getHeight(); - uint16_t volumeDepth = volume.getDepth(); - - 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 - VolumeType::Sampler volIter(&volume); - VolumeType::VoxelType current; - uint32_t runLength = 0; - bool firstTime = true; - for(uint16_t z = 0; z < volumeDepth; ++z) - { - //Update progress once per slice. - if(progressListener) - { - float fProgress = static_cast(z) / static_cast(volumeDepth); - progressListener->onProgressUpdated(fProgress); - } - - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - volIter.setPosition(x,y,z); - VolumeType::VoxelType 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)); - - //Finished - if(progressListener) - { - progressListener->onProgressUpdated(1.0f); - } - } - - //////////////////////////////////////////////////////////////////////////////////////////////////// - // New version of load/save code with versioning - //////////////////////////////////////////////////////////////////////////////////////////////////// - - template< typename VolumeType > - bool loadVolume(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener) - { - char pIdentifier[8]; - stream.read(pIdentifier, 7); - pIdentifier[7] = '\0'; //Set the null terminator - if(strcmp(pIdentifier, "PolyVox") != 0) - { - return false; - } - - uint16_t uVersion; - stream.read(reinterpret_cast(&uVersion), sizeof(uVersion)); - - switch(uVersion) - { - case 0: - return loadVersion0(stream, volume, progressListener); - //Return means no need to break... - default: - return false; - } - - } - - template< typename VolumeType > - bool saveVolume(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener) - { - char pIdentifier[] = "PolyVox"; - stream.write(pIdentifier, 7); - - uint16_t uVersion = 0; - stream.write(reinterpret_cast(&uVersion), sizeof(uVersion)); - - return saveVersion0(stream, volume, progressListener); - } - - //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 - template< typename VolumeType > - bool loadVersion0(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener) - { - //Read volume dimensions - uint16_t volumeWidth = 0; - uint16_t volumeHeight = 0; - uint16_t volumeDepth = 0; - stream.read(reinterpret_cast(&volumeWidth), sizeof(volumeWidth)); - stream.read(reinterpret_cast(&volumeHeight), sizeof(volumeHeight)); - stream.read(reinterpret_cast(&volumeDepth), sizeof(volumeDepth)); - - //Resize the volume - //HACK - Forces block size to 32. This functions needs reworking anyway due to large volume support. - volume.resize(Region(Vector3DInt32(0,0,0), Vector3DInt32(volumeWidth-1, volumeHeight-1, volumeDepth-1)), 32); - - //Read data - bool firstTime = true; - uint32_t runLength = 0; - VolumeType::VoxelType value; - stream.read(reinterpret_cast(&value), sizeof(value)); - stream.read(reinterpret_cast(&runLength), sizeof(runLength)); - for(uint16_t z = 0; z < volumeDepth; ++z) - { - //Update progress once per slice. - if(progressListener) - { - float fProgress = static_cast(z) / static_cast(volumeDepth); - progressListener->onProgressUpdated(fProgress); - } - - 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--; - } - } - } - } - - //Finished - if(progressListener) - { - progressListener->onProgressUpdated(1.0f); - } - - return true; - } - - template< typename VolumeType > - bool saveVersion0(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener) - { - //Write volume dimensions - uint16_t volumeWidth = volume.getWidth(); - uint16_t volumeHeight = volume.getHeight(); - uint16_t volumeDepth = volume.getDepth(); - - stream.write(reinterpret_cast(&volumeWidth), sizeof(volumeWidth)); - stream.write(reinterpret_cast(&volumeHeight), sizeof(volumeHeight)); - stream.write(reinterpret_cast(&volumeDepth), sizeof(volumeDepth)); - - //Write data - VolumeType::Sampler volIter(&volume); - VolumeType::VoxelType current; - uint32_t runLength = 0; - bool firstTime = true; - for(uint16_t z = 0; z < volumeDepth; ++z) - { - //Update progress once per slice. - if(progressListener) - { - float fProgress = static_cast(z) / static_cast(volumeDepth); - progressListener->onProgressUpdated(fProgress); - } - - for(uint16_t y = 0; y < volumeHeight; ++y) - { - for(uint16_t x = 0; x < volumeWidth; ++x) - { - volIter.setPosition(x,y,z); - VolumeType::VoxelType 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)); - - //Finished - if(progressListener) - { - progressListener->onProgressUpdated(1.0f); - } - - return true; - } -} diff --git a/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.h b/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.h deleted file mode 100644 index 39245623..00000000 --- a/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_VolumeChangeTracker_H__ -#define __PolyVox_VolumeChangeTracker_H__ - -#include "Impl/Utility.h" - -#include "PolyVoxCore/Region.h" -#include "PolyVoxCore/SurfaceMesh.h" -#include "PolyVoxCore/Vector.h" - -namespace PolyVox -{ - /// Voxel scene manager - /// \deprecated - template - class POLYVOX_DEPRECATED VolumeChangeTracker - { - public: - //Constructors, etc - VolumeChangeTracker(LargeVolume* volumeDataToSet, uint16_t regionSideLength); - ~VolumeChangeTracker(); - - //Getters - int32_t getCurrentTime(void) const; - int32_t getLastModifiedTimeForRegion(uint16_t uX, uint16_t uY, uint16_t uZ); - LargeVolume* getWrappedVolume(void) const; - - //Setters - void setAllRegionsModified(void); - void setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value); - void setVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value); - - //Others - void lockRegion(const Region& regToLock); - void unlockRegion(void); - //void markRegionChanged(uint16_t firstX, uint16_t firstY, uint16_t firstZ, uint16_t lastX, uint16_t lastY, uint16_t lastZ); - - public: - void incrementCurrentTime(void); - bool m_bIsLocked; - Region m_regLastLocked; - LargeVolume* volumeData; - - uint16_t m_uRegionSideLength; - uint8_t m_uRegionSideLengthPower; - uint16_t m_uVolumeWidthInRegions; - uint16_t m_uVolumeHeightInRegions; - uint16_t m_uVolumeDepthInRegions; - - - //It's not what the block class was designed for, but it - //provides a handy way of storing a 3D grid of values. - LargeVolume* volRegionLastModified; - - static uint32_t m_uCurrentTime; - }; -} - -#include "PolyVoxUtil/VolumeChangeTracker.inl" - -#endif diff --git a/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.inl b/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.inl deleted file mode 100644 index a426e653..00000000 --- a/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.inl +++ /dev/null @@ -1,212 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -namespace PolyVox -{ - template - uint32_t VolumeChangeTracker::m_uCurrentTime = 0; - - ////////////////////////////////////////////////////////////////////////// - // VolumeChangeTracker - ////////////////////////////////////////////////////////////////////////// - template - VolumeChangeTracker::VolumeChangeTracker(LargeVolume* volumeDataToSet, uint16_t regionSideLength) - :m_bIsLocked(false) - ,volumeData(0) - ,m_uRegionSideLength(regionSideLength) - { - volumeData = volumeDataToSet; - m_uVolumeWidthInRegions = volumeData->getWidth() / m_uRegionSideLength; - m_uVolumeHeightInRegions = volumeData->getHeight() / m_uRegionSideLength; - m_uVolumeDepthInRegions = volumeData->getDepth() / m_uRegionSideLength; - m_uRegionSideLengthPower = PolyVox::logBase2(m_uRegionSideLength); - - volRegionLastModified = new LargeVolume(m_uVolumeWidthInRegions, m_uVolumeHeightInRegions, m_uVolumeDepthInRegions, 0); - } - - template - VolumeChangeTracker::~VolumeChangeTracker() - { - } - - template - void VolumeChangeTracker::setAllRegionsModified(void) - { - incrementCurrentTime(); - for(uint16_t blockZ = 0; blockZ < m_uVolumeDepthInRegions; ++blockZ) - { - for(uint16_t blockY = 0; blockY < m_uVolumeHeightInRegions; ++blockY) - { - for(uint16_t blockX = 0; blockX < m_uVolumeWidthInRegions; ++blockX) - { - volRegionLastModified->setVoxelAt(blockX, blockY, blockZ, m_uCurrentTime); - } - } - } - } - - template - int32_t VolumeChangeTracker::getCurrentTime(void) const - { - return m_uCurrentTime; - } - - template - int32_t VolumeChangeTracker::getLastModifiedTimeForRegion(uint16_t uX, uint16_t uY, uint16_t uZ) - { - return volRegionLastModified->getVoxelAt(uX, uY, uZ); - } - - template - LargeVolume* VolumeChangeTracker::getWrappedVolume(void) const - { - return volumeData; - } - - template - void VolumeChangeTracker::setVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value) - { - //Note: We increase the time stamp both at the start and the end - //to avoid ambiguity about whether the timestamp comparison should - //be '<' vs '<=' or '>' vs '>=' in the users code. - incrementCurrentTime(); - - 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_uCurrentTime); - } - 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_uVolumeWidthInRegions-1),uint16_t(regionX+1)); - const uint16_t maxRegionY = (std::min)(uint16_t(m_uVolumeHeightInRegions-1),uint16_t(regionY+1)); - const uint16_t maxRegionZ = (std::min)(uint16_t(m_uVolumeDepthInRegions-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_uCurrentTime); - } - } - } - } - - //Increment time stamp. See earlier note. - incrementCurrentTime(); - } - - template - void VolumeChangeTracker::setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value) - { - assert(m_bIsLocked); - - //FIXME - rather than creating a iterator each time we should have one stored - /*Sampler iterVol(*volumeData); - iterVol.setPosition(x,y,z); - iterVol.setVoxel(value);*/ - volumeData->setVoxelAt(x,y,z,value); - } - - template - 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; - } - - template - void VolumeChangeTracker::unlockRegion(void) - { - if(!m_bIsLocked) - { - throw std::logic_error("No region is locked. You must lock a region before you can unlock it."); - } - - //Note: We increase the time stamp both at the start and the end - //to avoid ambiguity about whether the timestamp comparison should - //be '<' vs '<=' or '>' vs '>=' in the users code. - incrementCurrentTime(); - - 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_uCurrentTime); - } - } - } - - m_bIsLocked = false; - - //Increment time stamp. See earlier note. - incrementCurrentTime(); - } - - template - void VolumeChangeTracker::incrementCurrentTime(void) - { - //Increment the current time. - uint32_t time = m_uCurrentTime++; - - //Watch out for wraparound. Hopefully this will never happen - //as we have a pretty big counter, but it's best to be sure... - assert(time < m_uCurrentTime); - if(time >= m_uCurrentTime) - { - throw std::overflow_error("The VolumeChangeTracker time has overflowed."); - } - } -}