From e05cb1fefc0072ccfc45c63b4d81f4e2bca74cc0 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 14 Jan 2013 23:12:48 +0100 Subject: [PATCH] Fix for zero length normals causing a crash. --- .../MarchingCubesSurfaceExtractor.inl | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 1f251862..33330741 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -440,7 +440,13 @@ namespace PolyVox const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()) + fInterp, static_cast(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast(iZVolSpace - m_regSizeInCells.getLowerCorner().getZ())); Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp)); - v3dNormal.normalise(); + + // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so + // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). + if(v3dNormal.lengthSquared() > 0.000001f) + { + v3dNormal.normalise(); + } //Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of //material IDs does not make sense). We take the largest, so that if we are working on a material-only @@ -467,7 +473,13 @@ namespace PolyVox const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()) + fInterp, static_cast(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ())); Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp)); - v3dNormal.normalise(); + + // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so + // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). + if(v3dNormal.lengthSquared() > 0.000001f) + { + v3dNormal.normalise(); + } //Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of //material IDs does not make sense). We take the largest, so that if we are working on a material-only @@ -494,7 +506,12 @@ namespace PolyVox const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()) + fInterp); Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp)); - v3dNormal.normalise(); + // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so + // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). + if(v3dNormal.lengthSquared() > 0.000001f) + { + v3dNormal.normalise(); + } //Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of //material IDs does not make sense). We take the largest, so that if we are working on a material-only