diff --git a/tools/editor/npc_spawner.cpp b/tools/editor/npc_spawner.cpp index 2f725def..a6573415 100644 --- a/tools/editor/npc_spawner.cpp +++ b/tools/editor/npc_spawner.cpp @@ -177,6 +177,12 @@ bool NpcSpawner::loadFromFile(const std::string& path) { s.position = glm::vec3(js["position"][0].get(), js["position"][1].get(), js["position"][2].get()); + // Reject NaN/inf positions — they crash the M2 renderer's + // matrix math and produce invisible / chaos-shaped instances. + if (!std::isfinite(s.position.x) || !std::isfinite(s.position.y) || + !std::isfinite(s.position.z)) { + s.position = glm::vec3(0.0f); + } } if (js.contains("patrol") && js["patrol"].is_array()) { diff --git a/tools/editor/object_placer.cpp b/tools/editor/object_placer.cpp index 25b92d60..3d29dfa4 100644 --- a/tools/editor/object_placer.cpp +++ b/tools/editor/object_placer.cpp @@ -301,11 +301,19 @@ bool ObjectPlacer::loadFromFile(const std::string& path) { obj.position = glm::vec3(jo["pos"][0].get(), jo["pos"][1].get(), jo["pos"][2].get()); + if (!std::isfinite(obj.position.x) || !std::isfinite(obj.position.y) || + !std::isfinite(obj.position.z)) { + obj.position = glm::vec3(0.0f); + } } if (jo.contains("rot") && jo["rot"].is_array() && jo["rot"].size() >= 3) { obj.rotation = glm::vec3(jo["rot"][0].get(), jo["rot"][1].get(), jo["rot"][2].get()); + if (!std::isfinite(obj.rotation.x) || !std::isfinite(obj.rotation.y) || + !std::isfinite(obj.rotation.z)) { + obj.rotation = glm::vec3(0.0f); + } } if (!obj.path.empty()) {