From 2c916300eaabbc550e5b741faa6c0dc751b59961 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 21:45:26 +0200 Subject: [PATCH] Work on encoded marching cubes normals. --- .../MarchingCubesSurfaceExtractor.inl | 33 +++++++++++++++++-- .../include/PolyVoxCore/VertexTypes.h | 17 +++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 3fedba49..9514e22e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -457,12 +457,21 @@ namespace PolyVox v3dNormal.normalise(); } + v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f); + uint16_t encodedX = static_cast(roundToNearestInteger(v3dNormal.getX() * 15.5f)); + uint16_t encodedY = static_cast(roundToNearestInteger(v3dNormal.getY() * 15.5f)); + uint16_t encodedZ = static_cast(roundToNearestInteger(v3dNormal.getZ() * 15.5f)); + POLYVOX_ASSERT(encodedX < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedY < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedZ < 32, "Encoded value out of range"); + uint16_t encodedNormal = (encodedX << 10) | (encodedY << 5) | encodedZ; + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = v3dNormal; + surfaceVertex.normal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -491,12 +500,21 @@ namespace PolyVox v3dNormal.normalise(); } + v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f); + uint16_t encodedX = static_cast(roundToNearestInteger(v3dNormal.getX() * 15.5f)); + uint16_t encodedY = static_cast(roundToNearestInteger(v3dNormal.getY() * 15.5f)); + uint16_t encodedZ = static_cast(roundToNearestInteger(v3dNormal.getZ() * 15.5f)); + POLYVOX_ASSERT(encodedX < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedY < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedZ < 32, "Encoded value out of range"); + uint16_t encodedNormal = (encodedX << 10) | (encodedY << 5) | encodedZ; + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = v3dNormal; + surfaceVertex.normal = encodedNormal; surfaceVertex.data = uMaterial; uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -524,12 +542,21 @@ namespace PolyVox v3dNormal.normalise(); } + v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f); + uint16_t encodedX = static_cast(roundToNearestInteger(v3dNormal.getX() * 15.5f)); + uint16_t encodedY = static_cast(roundToNearestInteger(v3dNormal.getY() * 15.5f)); + uint16_t encodedZ = static_cast(roundToNearestInteger(v3dNormal.getZ() * 15.5f)); + POLYVOX_ASSERT(encodedX < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedY < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedZ < 32, "Encoded value out of range"); + uint16_t encodedNormal = (encodedX << 10) | (encodedY << 5) | encodedZ; + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = v3dNormal; + surfaceVertex.normal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index dcab6c17..a4c31b27 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -71,7 +71,7 @@ namespace PolyVox typedef _DataType DataType; Vector3DUint16 position; - Vector3DFloat normal; + uint16_t normal; DataType data; }; @@ -91,13 +91,20 @@ namespace PolyVox // 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& cubicVertex) + Vertex decode(const MarchingCubesVertex& marchingCubesVertex) { Vertex result; - result.position = Vector3DFloat(cubicVertex.position.getX(), cubicVertex.position.getY(), cubicVertex.position.getZ()); + result.position = Vector3DFloat(marchingCubesVertex.position.getX(), marchingCubesVertex.position.getY(), marchingCubesVertex.position.getZ()); result.position *= (1.0 / 256.0); - result.normal = cubicVertex.normal; - result.data = cubicVertex.data; + + 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; } }