From 29ae850307d45d119934417f9f91aeff3da06d09 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 05:14:35 -0700 Subject: [PATCH] fix(wom): per-vertex NaN/inf scrub on load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even after the bound-field guards, individual vertex floats (position, normal, texCoord) could still poison the GPU. NaN positions would crash the M2 vertex shader on some drivers (silent device-lost). Now each component defaults to 0 (or 1 for normal Z) when non-finite — vertex ends up at origin instead of corrupting the whole pipeline. --- src/pipeline/wowee_model.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/pipeline/wowee_model.cpp b/src/pipeline/wowee_model.cpp index cc6924fa..15ac0d16 100644 --- a/src/pipeline/wowee_model.cpp +++ b/src/pipeline/wowee_model.cpp @@ -73,6 +73,19 @@ WoweeModel WoweeModelLoader::load(const std::string& basePath) { model.vertices[i].texCoord = v1.uv; } } + // Sanitize per-vertex floats. NaN/inf positions crash the M2 vertex + // shader (silent device-lost on some drivers) — safer to render the + // vertex at the origin than corrupt the whole pipeline. + for (auto& v : model.vertices) { + if (!std::isfinite(v.position.x)) v.position.x = 0.0f; + if (!std::isfinite(v.position.y)) v.position.y = 0.0f; + if (!std::isfinite(v.position.z)) v.position.z = 0.0f; + if (!std::isfinite(v.normal.x)) v.normal.x = 0.0f; + if (!std::isfinite(v.normal.y)) v.normal.y = 0.0f; + if (!std::isfinite(v.normal.z)) v.normal.z = 1.0f; + if (!std::isfinite(v.texCoord.x)) v.texCoord.x = 0.0f; + if (!std::isfinite(v.texCoord.y)) v.texCoord.y = 0.0f; + } model.indices.resize(indexCount); f.read(reinterpret_cast(model.indices.data()), indexCount * 4);