diff --git a/PD2ModelParser/Exporters/GltfExporter.cs b/PD2ModelParser/Exporters/GltfExporter.cs index f9457b3..0bd251e 100644 --- a/PD2ModelParser/Exporters/GltfExporter.cs +++ b/PD2ModelParser/Exporters/GltfExporter.cs @@ -254,9 +254,20 @@ GLTF.Mesh GetMeshForModel(Model model) if (geometry.normals.Count > 0) { - Vector3 MakeNormal(Nexus.Vector3D norm) + Vector3 MakeNormal(Nexus.Vector3D norm, int idx) { - return Vector3.Normalize(norm.ToVector3()); + var normalized = Vector3.Normalize(norm.ToVector3()); + if(!normalized.IsFinite()) + { + Log.Default.Warn("Vertex {0} of geometry {1}|{2} is bogus ({3})", idx, geometry.SectionId, geometry.hashname, norm); + return new Vector3(1, 0, 0); + } + if(!normalized.IsUnitLength()) + { + Log.Default.Warn("Vertex {0} of geometry {1}|{2} is bogus length {4} ({3})", idx, geometry.SectionId, geometry.hashname, norm, norm.Length()); + return new Vector3(1, 0, 0); + } + return normalized; } var a_norm = MakeVertexAttributeAccessor("vnorm", geometry.normals, 12, GLTF.DimensionType.VEC3, MakeNormal, ma => ma.AsVector3Array()); result.Add(("NORMAL", a_norm)); diff --git a/PD2ModelParser/Utils.cs b/PD2ModelParser/Utils.cs index af7ce82..285b63c 100644 --- a/PD2ModelParser/Utils.cs +++ b/PD2ModelParser/Utils.cs @@ -169,6 +169,26 @@ public static byte ClampFloatToByte(double input) var rounded = Math.Round(scaled); return (byte)rounded; } + + public static Boolean IsFinite(this System.Numerics.Vector3 vec) + { + return !( + float.IsInfinity(vec.X) + || float.IsInfinity(vec.Y) + || float.IsInfinity(vec.Z) + || float.IsNaN(vec.X) + || float.IsNaN(vec.Y) + || float.IsNaN(vec.Z) + ); + } + + // From https://github.com/KhronosGroup/glTF-Validator/blob/master/lib/src/errors.dart + // which says, "these values are slightly greater than the maximum error from signed 8-bit quantization" + const float UnitLengthThresholdVec3 = 0.00674f; + const float UnitLengthThresholdVec4 = 0.00769f; + + public static Boolean IsUnitLength(this System.Numerics.Vector3 vec) => + Math.Abs(vec.Length() - 1) <= UnitLengthThresholdVec3; } public static class MatrixExtensions