From c5008750ce6153ef2905feabfbe463cd00090e9f Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 09:08:07 -0700 Subject: [PATCH] fix(woc): cap triangle count and clamp tile coords on save MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WOC load caps tris at 2M and clamps tile coords to 0..63. Save previously wrote raw size() and tileX/Y — a >2M-tri collision would be silently rejected on round-trip, and OOR tile coords would log a warning every reload. Cap at save and reuse the load-side clamp so the on-disk file is round-trip clean. --- src/pipeline/wowee_collision.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/pipeline/wowee_collision.cpp b/src/pipeline/wowee_collision.cpp index c28aed34..010841ec 100644 --- a/src/pipeline/wowee_collision.cpp +++ b/src/pipeline/wowee_collision.cpp @@ -170,16 +170,25 @@ bool WoweeCollisionBuilder::save(const WoweeCollision& collision, const std::str if (!std::isfinite(v.z)) v.z = 0.0f; return v; }; - uint32_t triCount = static_cast(collision.triangles.size()); + // Cap triangle count at the load-side limit (2M). Save previously + // wrote raw size() so a >2M-tri collision (theoretical, addMesh on + // huge geometry) would be silently rejected on round-trip. + uint32_t triCount = static_cast( + std::min(collision.triangles.size(), 2'000'000)); f.write(reinterpret_cast(&triCount), 4); - f.write(reinterpret_cast(&collision.tileX), 4); - f.write(reinterpret_cast(&collision.tileY), 4); + // Sanitize tile coords too — out-of-range would be clamped on load + // anyway but writing a clean file means no warning on every reload. + uint32_t tileX = collision.tileX > 63 ? 32 : collision.tileX; + uint32_t tileY = collision.tileY > 63 ? 32 : collision.tileY; + f.write(reinterpret_cast(&tileX), 4); + f.write(reinterpret_cast(&tileY), 4); glm::vec3 bmin = sanVec(collision.bounds.min); glm::vec3 bmax = sanVec(collision.bounds.max); f.write(reinterpret_cast(&bmin), 12); f.write(reinterpret_cast(&bmax), 12); - for (const auto& tri : collision.triangles) { + for (uint32_t ti = 0; ti < triCount; ti++) { + const auto& tri = collision.triangles[ti]; glm::vec3 v0 = sanVec(tri.v0), v1 = sanVec(tri.v1), v2 = sanVec(tri.v2); f.write(reinterpret_cast(&v0), 12); f.write(reinterpret_cast(&v1), 12);