diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index 3826543d..2c0fff6d 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -92,14 +92,14 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVe // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedPosition))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, normal))); + glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedNormal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index a95d66e5..12d1068f 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -130,8 +130,9 @@ int main(int argc, char *argv[]) // The returned mesh needs to be decoded to be appropriate for GPU rendering. auto decodedMesh = decode(mesh); - //Pass the surface to the OpenGL window - openGLWidget.addMesh(decodedMesh, Vector3DInt32(x, y, z)); + // Pass the surface to the OpenGL window. Note that we are also passing an offset in this multi-mesh example. This is because + // the surface extractors return a mesh with 'local space' positions to reduce storage requirements and precision problems. + openGLWidget.addMesh(decodedMesh, decodedMesh.getOffset()); meshCounter++; } diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index a0150556..1bbbc1e4 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -71,7 +71,7 @@ public: // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(Vertex< DataType >), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PolyVox::Vertex< DataType >), vecVertices.data(), GL_STATIC_DRAW); // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -80,20 +80,20 @@ public: // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, normal))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' GLint size = (std::min)(sizeof(DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, data))); + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, data))); // We're done uploading and can now unbind. glBindVertexArray(0); diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 3fbb260b..db5caaa8 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -27,7 +27,6 @@ SET(CORE_SRC_FILES source/ArraySizes.cpp source/AStarPathfinder.cpp source/Region.cpp - source/VertexTypes.cpp ) #Projects headers files @@ -66,6 +65,8 @@ SET(CORE_INC_FILES include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl include/PolyVoxCore/Material.h include/PolyVoxCore/MaterialDensityPair.h + include/PolyVoxCore/Mesh.h + include/PolyVoxCore/Mesh.inl include/PolyVoxCore/MinizBlockCompressor.h include/PolyVoxCore/MinizBlockCompressor.inl include/PolyVoxCore/Pager.h @@ -84,13 +85,11 @@ SET(CORE_INC_FILES include/PolyVoxCore/SimpleVolume.inl include/PolyVoxCore/SimpleVolumeBlock.inl include/PolyVoxCore/SimpleVolumeSampler.inl - include/PolyVoxCore/Mesh.h - include/PolyVoxCore/Mesh.inl include/PolyVoxCore/UncompressedBlock.h include/PolyVoxCore/UncompressedBlock.inl include/PolyVoxCore/Vector.h include/PolyVoxCore/Vector.inl - include/PolyVoxCore/VertexTypes.h + include/PolyVoxCore/Vertex.h include/PolyVoxCore/VolumeResampler.h include/PolyVoxCore/VolumeResampler.inl include/PolyVoxCore/VoxelFilters.h diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 03e973a3..c2ba3481 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -32,9 +32,46 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/DefaultIsQuadNeeded.h" #include "PolyVoxCore/Mesh.h" +#include "PolyVoxCore/Vertex.h" namespace PolyVox { +#ifdef SWIG + struct CubicVertex +#else + template + struct POLYVOX_API CubicVertex +#endif + { + typedef _DataType DataType; + + // Each component of the position is stored as a single unsigned byte. + // The true position is found by offseting each component by 0.5f. + Vector3DUint8 encodedPosition; + + // User data + DataType data; + }; + + /// Decodes a position from a CubicVertex + inline Vector3DFloat decode(const Vector3DUint8& encodedPosition) + { + Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ()); + result -= 0.5f; // Apply the required offset + return result; + } + + /// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering. + template + Vertex decode(const CubicVertex& cubicVertex) + { + Vertex result; + result.position = decode(cubicVertex.encodedPosition); + result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated + result.data = cubicVertex.data; // Data is not encoded + return result; + } + /// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Introduction diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 7fe9286b..d05a7c57 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -190,13 +190,13 @@ namespace PolyVox for(typename std::list::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) { Quad& quad = *quadIter; - m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]); - m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]); + m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[1],quad.vertices[2]); + m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[2],quad.vertices[3]); } } } - m_meshCurrent->m_Region = m_regSizeInVoxels; + m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); m_meshCurrent->removeUnusedVertices(); m_meshCurrent->m_vecLodRecords.clear(); @@ -221,7 +221,7 @@ namespace PolyVox { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. CubicVertex cubicVertex; - cubicVertex.position.setElements(static_cast(uX), static_cast(uY), static_cast(uZ)); + cubicVertex.encodedPosition.setElements(static_cast(uX), static_cast(uY), static_cast(uZ)); cubicVertex.data = uMaterialIn; rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex); rEntry.uMaterial = uMaterialIn; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 6510ac5c..4b96b432 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -31,9 +31,70 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/DefaultMarchingCubesController.h" +#include "PolyVoxCore/Vertex.h" namespace PolyVox { +#ifdef SWIG + struct MarchingCubesVertex +#else + template + struct POLYVOX_API MarchingCubesVertex +#endif + { + typedef _DataType DataType; + + // Each component of the position is stored using 8.8 fixed-point encoding. + Vector3DUint16 encodedPosition; + + // Each component of the normal is encoded using 5 bits of this variable. + // The 16 bits are -xxxxxyyyyyzzzzz (note the left-most bit is currently + // unused). Some extra shifting and scaling is required to make it signed. + uint16_t encodedNormal; + + // User data + DataType data; + }; + + /// Decodes a position from a MarchingCubesVertex + inline Vector3DFloat decode(const Vector3DUint16& encodedPosition) + { + Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ()); + result *= (1.0f / 256.0f); // Division is compile-time constant + return result; + } + + /// Decodes a normal from a MarchingCubesVertex + inline Vector3DFloat decode(const uint16_t encodedNormal) + { + // Get normal components in the range 0 to 31 + uint16_t x = (encodedNormal >> 10) & 0x1F; + uint16_t y = (encodedNormal >> 5) & 0x1F; + uint16_t z = (encodedNormal) & 0x1F; + + // Build the resulting vector + Vector3DFloat result(x, y, z); + + // Convert to range 0.0 to 2.0 + result *= (1.0f / 15.5f); // Division is compile-time constant + + // Convert to range -1.0 to 1.0 + result -= Vector3DFloat(1.0f, 1.0f, 1.0f); + + return result; + } + + /// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering. + template + Vertex decode(const MarchingCubesVertex& marchingCubesVertex) + { + Vertex result; + result.position = decode(marchingCubesVertex.encodedPosition); + result.normal = decode(marchingCubesVertex.encodedNormal); + result.data = marchingCubesVertex.data; // Data is not encoded + return result; + } + template< typename VolumeType, typename Controller = DefaultMarchingCubesController > class MarchingCubesSurfaceExtractor { diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 9514e22e..382dc85a 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -122,7 +122,7 @@ namespace PolyVox m_regSliceCurrent.shift(Vector3DInt32(0,0,1)); } - m_meshCurrent->m_Region = m_regSizeInVoxels; + m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); m_meshCurrent->m_vecLodRecords.clear(); LodRecord lodRecord; @@ -470,8 +470,8 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = encodedNormal; + surfaceVertex.encodedPosition = v3dScaledPosition; + surfaceVertex.encodedNormal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -513,8 +513,8 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = encodedNormal; + surfaceVertex.encodedPosition = v3dScaledPosition; + surfaceVertex.encodedNormal = encodedNormal; surfaceVertex.data = uMaterial; uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -555,8 +555,8 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = encodedNormal; + surfaceVertex.encodedPosition = v3dScaledPosition; + surfaceVertex.encodedNormal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index f0ce39ea..18537e9e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -27,7 +27,7 @@ freely, subject to the following restrictions: #include "Impl/TypeDef.h" #include "PolyVoxCore/Region.h" -#include "PolyVoxCore/VertexTypes.h" //Should probably do away with this on in the future... +#include "PolyVoxCore/Vertex.h" //Should probably do away with this on in the future... #include #include @@ -52,54 +52,31 @@ namespace PolyVox typedef _VertexType VertexType; - Mesh(); - ~Mesh(); + Mesh(); + ~Mesh(); - const std::vector& getIndices(void) const; - uint32_t getNoOfIndices(void) const; - uint32_t getNoOfNonUniformTrianges(void) const; - uint32_t getNoOfUniformTrianges(void) const; - uint32_t getNoOfVertices(void) const; - std::vector& getRawVertexData(void); //FIXME - this should be removed - const std::vector& getVertices(void) const; + const std::vector& getIndices(void) const; + uint32_t getNoOfIndices(void) const; + uint32_t getNoOfVertices(void) const; + const std::vector& getVertices(void) const; + const Vector3DInt32& getOffset(void) const; - void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); - void addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2); - uint32_t addVertex(const VertexType& vertex); - void clear(void); - bool isEmpty(void) const; + void setOffset(const Vector3DInt32& offset); - void scaleVertices(float amount); - void translateVertices(const Vector3DFloat& amount); + void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); + uint32_t addVertex(const VertexType& vertex); + void clear(void); + bool isEmpty(void) const; + void removeUnusedVertices(void); - //THESE FUNCTIONS TO BE REMOVED IN THE FUTURE. OR AT LEAST MOVED OUT OF THIS CLASS INTO FREE FUNCTIONS. - //THEY ARE CAUSING PROBLEMS WITH THE SWIG BINDINGS. THE FUNCTIONS REGARDING NORMALS MAKE NO SENSE WHEN - //A VERTEX MIGHT NOT HAVE NORMALS. THE EXTRACT SUBSET FUNCTION SHOULD MAYBE BE APPLICATION CODE, AT ANY - //RATE THE STD::SET CAUSES PROBLEMS WITH SWIG. IF YOU UNCOMMENT ANY OF THESE FUNCTIONS, PLEASE POST ON - //THE FORUM SO WE CAN KNOW THE FUNCTIONALITY IS STILL NEEDED IN SOME FORM. - //void sumNearbyNormals(bool bNormaliseResult = true); - //std::shared_ptr< Mesh > extractSubset(std::set setMaterials); - //void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false); - - int noOfDegenerateTris(void); - void removeDegenerateTris(void); - void removeUnusedVertices(void); - - Region m_Region; - - int32_t m_iTimeStamp; - - int32_t m_iNoOfLod0Tris; + Vector3DInt32 m_offset; public: std::vector m_vecTriangleIndices; std::vector m_vecVertices; std::vector m_vecLodRecords; - }; - - template - std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials); + }; template Mesh< Vertex< typename MeshType::VertexType::DataType > > decode(const MeshType& mesh) @@ -114,7 +91,7 @@ namespace PolyVox result.m_vecTriangleIndices = mesh.m_vecTriangleIndices; - result.m_Region = mesh.m_Region; + result.m_offset = mesh.m_offset; return result; } diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index 44fc5320..d2363046 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -26,7 +26,6 @@ namespace PolyVox template Mesh::Mesh() { - m_iTimeStamp = -1; } template @@ -44,39 +43,6 @@ namespace PolyVox uint32_t Mesh::getNoOfIndices(void) const { return m_vecTriangleIndices.size(); - } - - template - uint32_t Mesh::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; - } - - template - uint32_t Mesh::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; } template @@ -85,33 +51,26 @@ namespace PolyVox return m_vecVertices.size(); } - template - std::vector& Mesh::getRawVertexData(void) - { - return m_vecVertices; - } - template const std::vector& Mesh::getVertices(void) const { return m_vecVertices; - } - - template - void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) - { - //Make sure the specified indices correspond to valid vertices. - POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex."); - - m_vecTriangleIndices.push_back(index0); - m_vecTriangleIndices.push_back(index1); - m_vecTriangleIndices.push_back(index2); } template - void Mesh::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2) + const Vector3DInt32& Mesh::getOffset(void) const + { + return m_offset; + } + + template + void Mesh::setOffset(const Vector3DInt32& offset) + { + m_offset = offset; + } + + template + void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) { //Make sure the specified indices correspond to valid vertices. POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); @@ -135,7 +94,6 @@ namespace PolyVox { m_vecVertices.clear(); m_vecTriangleIndices.clear(); - m_vecLodRecords.clear(); } template @@ -144,223 +102,6 @@ namespace PolyVox return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); } - //////////////////////////////////////////////////////////////////////////////// - /// This function can help improve the visual appearance of a surface patch by - /// smoothing normals with other nearby normals. It iterates over each triangle - /// in the surface patch and determines the sum of its corners normals. For any - /// given vertex, these sums are in turn summed for any triangles which use the - /// vertex. Usually, the resulting normals should be renormalised afterwards. - /// Note: This function can cause lighting discontinuities accross region boundaries. - //////////////////////////////////////////////////////////////////////////////// - /*template - void Mesh::sumNearbyNormals(bool bNormaliseResult) - { - if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return; - } - - std::vector summedNormals(m_vecVertices.size()); - - //Initialise all normals to zero. Should be ok as the vector should store all elements contiguously. - memset(&summedNormals[0], 0, summedNormals.size() * sizeof(Vector3DFloat)); - - for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) - { - PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; - Vector3DFloat& v0New = summedNormals[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; - Vector3DFloat& v1New = summedNormals[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; - Vector3DFloat& v2New = summedNormals[*iterIndex]; - iterIndex++; - - Vector3DFloat sumOfNormals = v0.getNormal() + v1.getNormal() + v2.getNormal(); - - v0New += sumOfNormals; - v1New += sumOfNormals; - v2New += sumOfNormals; - } - - for(uint32_t uIndex = 0; uIndex < summedNormals.size(); uIndex++) - { - if(bNormaliseResult) - { - summedNormals[uIndex].normalise(); - } - m_vecVertices[uIndex].setNormal(summedNormals[uIndex]); - } - }*/ - - /*template - void Mesh::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices) - { - Vector3DFloat offset = static_cast(m_Region.getLowerCorner()); - - //Initially zero the normals - for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) - { - if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001)) - { - iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f)); - } - } - - for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) - { - PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; - iterIndex++; - - Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition()); - - if(m_Region.containsPoint(v0.getPosition() + offset, 0.001)) - { - v0.setNormal(v0.getNormal() + triangleNormal); - } - if(m_Region.containsPoint(v1.getPosition() + offset, 0.001)) - { - v1.setNormal(v1.getNormal() + triangleNormal); - } - if(m_Region.containsPoint(v2.getPosition() + offset, 0.001)) - { - v2.setNormal(v2.getNormal() + triangleNormal); - } - } - - if(bNormalise) - { - for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) - { - Vector3DFloat normal = iterVertex->getNormal(); - normal.normalise(); - iterVertex->setNormal(normal); - } - } - }*/ - - /*template - std::shared_ptr< Mesh > Mesh::extractSubset(std::set setMaterials) - { - std::shared_ptr< Mesh > result(new Mesh); - - if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return result; - } - - assert(m_vecLodRecords.size() == 1); - if(m_vecLodRecords.size() != 1) - { - //If we have done progressive LOD then it's too late to split into subsets. - return result; - } - - std::vector indexMap(m_vecVertices.size()); - std::fill(indexMap.begin(), indexMap.end(), -1); - - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt += 3) - { - - PositionMaterialNormal& v0 = m_vecVertices[m_vecTriangleIndices[triCt]]; - PositionMaterialNormal& v1 = m_vecVertices[m_vecTriangleIndices[triCt + 1]]; - PositionMaterialNormal& v2 = m_vecVertices[m_vecTriangleIndices[triCt + 2]]; - - if( - (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v2.getMaterial()) != setMaterials.end())) - { - uint32_t i0; - if(indexMap[m_vecTriangleIndices[triCt]] == -1) - { - indexMap[m_vecTriangleIndices[triCt]] = result->addVertex(v0); - } - i0 = indexMap[m_vecTriangleIndices[triCt]]; - - uint32_t i1; - if(indexMap[m_vecTriangleIndices[triCt+1]] == -1) - { - indexMap[m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); - } - i1 = indexMap[m_vecTriangleIndices[triCt+1]]; - - uint32_t i2; - if(indexMap[m_vecTriangleIndices[triCt+2]] == -1) - { - indexMap[m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); - } - i2 = indexMap[m_vecTriangleIndices[triCt+2]]; - - result->addTriangle(i0,i1,i2); - } - } - - result->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = result->getNoOfIndices(); - result->m_vecLodRecords.push_back(lodRecord); - - return result; - }*/ - - template - int Mesh::noOfDegenerateTris(void) - { - int count = 0; - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) - { - int v0 = m_vecTriangleIndices[triCt]; - triCt++; - int v1 = m_vecTriangleIndices[triCt]; - triCt++; - int v2 = m_vecTriangleIndices[triCt]; - triCt++; - - if((v0 == v1) || (v1 == v2) || (v2 == v0)) - { - count++; - } - } - return count; - } - - template - void Mesh::removeDegenerateTris(void) - { - int noOfNonDegenerate = 0; - int targetCt = 0; - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) - { - int v0 = m_vecTriangleIndices[triCt]; - triCt++; - int v1 = m_vecTriangleIndices[triCt]; - triCt++; - int v2 = m_vecTriangleIndices[triCt]; - triCt++; - - if((v0 != v1) && (v1 != v2) & (v2 != v0)) - { - m_vecTriangleIndices[targetCt] = v0; - targetCt++; - m_vecTriangleIndices[targetCt] = v1; - targetCt++; - m_vecTriangleIndices[targetCt] = v2; - targetCt++; - - noOfNonDegenerate++; - } - } - - m_vecTriangleIndices.resize(noOfNonDegenerate * 3); - } - template void Mesh::removeUnusedVertices(void) { @@ -392,97 +133,4 @@ namespace PolyVox m_vecTriangleIndices[triCt] = newPos[m_vecTriangleIndices[triCt]]; } } - - //Currently a free function - think where this needs to go. - template - std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials) - { - std::shared_ptr< Mesh > result(new Mesh); - - result->m_Region = inputMesh.m_Region; - - if(inputMesh.m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return result; - } - - POLYVOX_ASSERT(inputMesh.m_vecLodRecords.size() == 1, "Number of LOD records must equal one."); - if(inputMesh.m_vecLodRecords.size() != 1) - { - //If we have done progressive LOD then it's too late to split into subsets. - return result; - } - - std::vector indexMap(inputMesh.m_vecVertices.size()); - std::fill(indexMap.begin(), indexMap.end(), -1); - - for(uint32_t triCt = 0; triCt < inputMesh.m_vecTriangleIndices.size(); triCt += 3) - { - - VertexType& v0 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt]]; - VertexType& v1 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 1]]; - VertexType& v2 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 2]]; - - if( - (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v2.getMaterial()) != setMaterials.end())) - { - uint32_t i0; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt]] = result->addVertex(v0); - } - i0 = indexMap[inputMesh.m_vecTriangleIndices[triCt]]; - - uint32_t i1; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); - } - i1 = indexMap[inputMesh.m_vecTriangleIndices[triCt+1]]; - - uint32_t i2; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); - } - i2 = indexMap[inputMesh.m_vecTriangleIndices[triCt+2]]; - - result->addTriangle(i0,i1,i2); - } - } - - result->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = result->getNoOfIndices(); - result->m_vecLodRecords.push_back(lodRecord); - - return result; - } - - template - void Mesh::scaleVertices(float amount) - { - for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) - { - //TODO: Should rethink accessors here to provide faster access - Vector3DFloat position = m_vecVertices[ct].getPosition(); - position *= amount; - m_vecVertices[ct].setPosition(position); - } - } - - template - void Mesh::translateVertices(const Vector3DFloat& amount) - { - for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) - { - //TODO: Should rethink accessors here to provide faster access - Vector3DFloat position = m_vecVertices[ct].getPosition(); - position += amount; - m_vecVertices[ct].setPosition(position); - } - } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/Vertex.h b/library/PolyVoxCore/include/PolyVoxCore/Vertex.h new file mode 100644 index 00000000..1eb6f429 --- /dev/null +++ b/library/PolyVoxCore/include/PolyVoxCore/Vertex.h @@ -0,0 +1,51 @@ +/******************************************************************************* +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_Vertex_H__ +#define __PolyVox_Vertex_H__ + +#include "Impl/TypeDef.h" + +#include "PolyVoxCore/Vector.h" + +#include +#include + +namespace PolyVox +{ + #ifdef SWIG + struct Vertex +#else + template + struct POLYVOX_API Vertex +#endif + { + typedef _DataType DataType; + + Vector3DFloat position; + Vector3DFloat normal; + DataType data; + }; +} + +#endif // __PolyVox_Vertex_H__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h deleted file mode 100644 index a4c31b27..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ /dev/null @@ -1,112 +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_SurfaceVertex_H__ -#define __PolyVox_SurfaceVertex_H__ - -#include "Impl/TypeDef.h" - -#include "PolyVoxCore/Vector.h" - -#include -#include - -namespace PolyVox -{ - #ifdef SWIG - struct Vertex -#else - template - struct POLYVOX_API Vertex -#endif - { - typedef _DataType DataType; - - Vector3DFloat position; - Vector3DFloat normal; - DataType data; - }; - -#ifdef SWIG - struct CubicVertex -#else - template - struct POLYVOX_API CubicVertex -#endif - { - typedef _DataType DataType; - - Vector3DUint8 position; - uint8_t normal; - DataType data; - }; - -#ifdef SWIG - struct MarchingCubesVertex -#else - template - struct POLYVOX_API MarchingCubesVertex -#endif - { - typedef _DataType DataType; - - Vector3DUint16 position; - uint16_t normal; - DataType data; - }; - - // Hopefully the compiler will implement the 'Return value optimization' here, but - // performance critical code will most likely decode the vertices in a shader anyway. - template - Vertex decode(const CubicVertex& cubicVertex) - { - Vertex result; - Vector3DUint8 temp = cubicVertex.position; // For some reason we can't cast Vector3DUint8 to Vector3DFloat - investigate why. - result.position = Vector3DFloat(temp.getX(), temp.getY(), temp.getZ()) - Vector3DFloat(0.5, 0.5, 0.5); - //result.normal = cubicVertex.normal; - result.data = cubicVertex.data; - return result; - } - - // Hopefully the compiler will implement the 'Return value optimization' here, but - // performance critical code will most likely decode the vertices in a shader anyway. - template - Vertex decode(const MarchingCubesVertex& marchingCubesVertex) - { - Vertex result; - result.position = Vector3DFloat(marchingCubesVertex.position.getX(), marchingCubesVertex.position.getY(), marchingCubesVertex.position.getZ()); - result.position *= (1.0 / 256.0); - - uint16_t encodedX = (marchingCubesVertex.normal >> 10) & 0x1F; - uint16_t encodedY = (marchingCubesVertex.normal >> 5) & 0x1F; - uint16_t encodedZ = (marchingCubesVertex.normal) & 0x1F; - result.normal = Vector3DFloat(encodedX, encodedY, encodedZ); - result.normal /= 15.5f; - result.normal -= Vector3DFloat(1.0f, 1.0f, 1.0f); - - result.data = marchingCubesVertex.data; - return result; - } -} - -#endif diff --git a/library/PolyVoxCore/source/VertexTypes.cpp b/library/PolyVoxCore/source/VertexTypes.cpp deleted file mode 100644 index 8b137891..00000000 --- a/library/PolyVoxCore/source/VertexTypes.cpp +++ /dev/null @@ -1 +0,0 @@ -