From 9d6f7bfde911155bf37d087bb231cd94f2dbcd00 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 24 Jul 2026 18:59:58 -0700 Subject: [PATCH] fix: footprints rendered three times life size CreatureModelData's FootprintTextureLength/Width are inches, but the loader divided them by 12 -- inches to feet -- and used the result as world units, which are yards. The decal quad is unit-sized and scaled directly by those values, so a human's footprint drew a full yard long. Convert by /36, and rescale the fallback profiles, which were authored against the broken scale (BIPED 1.0 x 0.83 is exactly raw 12 x 10 over 12) and would otherwise have stayed oversized for every creature without a DBC profile. Foot spacing is a body dimension rather than a print-size one, so the stance coefficient absorbs the 3x and the trail stays as wide as before. The degenerate-row guard now tests raw inches so the correction doesn't also raise the cutoff and drop small creatures that resolve a profile today. --- src/rendering/footprint_renderer.cpp | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/rendering/footprint_renderer.cpp b/src/rendering/footprint_renderer.cpp index 39cf79e6..dee33960 100644 --- a/src/rendering/footprint_renderer.cpp +++ b/src/rendering/footprint_renderer.cpp @@ -236,9 +236,15 @@ bool FootprintRenderer::loadFootprintData(pipeline::AssetManager* assets) { auto textureIt = indexById.find(modelDbc->getUInt32(row, 6)); if (textureIt == indexById.end()) continue; std::string path = normalizeModelPath(modelDbc->getString(row, 2)); - const float length = modelDbc->getFloat(row, 7) / 12.0f; - const float width = modelDbc->getFloat(row, 8) / 12.0f; - if (path.empty() || length <= 0.05f || width <= 0.05f) continue; + // FootprintTextureLength/Width are inches; world units are yards, so the + // conversion is /36. Dividing by 12 yields feet and renders every print + // three times its real size — a human's came out a yard long. + const float length = modelDbc->getFloat(row, 7) / 36.0f; + const float width = modelDbc->getFloat(row, 8) / 36.0f; + // Reject degenerate rows on the raw inches, so the /36 correction doesn't + // also quietly raise the cutoff and drop small creatures that used to + // resolve a profile. + if (path.empty() || length * 36.0f <= 0.6f || width * 36.0f <= 0.6f) continue; Profile profile{textureIt->second, length, width}; profilesByPath_[path] = profile; } @@ -262,12 +268,13 @@ FootprintRenderer::Profile FootprintRenderer::resolveProfile( auto base = profilesByBasename_.find(basenameOf(normalized)); if (base != profilesByBasename_.end()) return base->second; + // Yards, to match the converted DBC dimensions above. switch (fallback) { - case FootprintFallback::HOOF: return {4, 1.5f, 1.0f}; - case FootprintFallback::PAW: return {5, 2.0f, 1.5f}; - case FootprintFallback::CLAW: return {2, 2.0f, 1.5f}; - case FootprintFallback::CLOVEN: return {3, 1.8f, 1.3f}; - case FootprintFallback::BIPED: return {0, 1.0f, 0.83f}; + case FootprintFallback::HOOF: return {4, 0.50f, 0.33f}; + case FootprintFallback::PAW: return {5, 0.67f, 0.50f}; + case FootprintFallback::CLAW: return {2, 0.67f, 0.50f}; + case FootprintFallback::CLOVEN: return {3, 0.60f, 0.43f}; + case FootprintFallback::BIPED: return {0, 0.33f, 0.28f}; } return {}; } @@ -293,7 +300,11 @@ void FootprintRenderer::spawn(const std::string& modelName, const glm::vec3& bas const Profile profile = resolveProfile(modelName, fallback); const glm::vec2 forward(std::cos(yawRadians), std::sin(yawRadians)); const glm::vec2 right(-forward.y, forward.x); - const float side = (leftFoot ? -1.0f : 1.0f) * profile.width * 0.24f; + // Stance is how far each foot sits off the centreline — a body dimension, + // roughly three quarters of a footprint's width to either side. The + // coefficient carries the /12-to-/36 correction so the gait stays as wide + // as it was while the prints themselves shrink to life size. + const float side = (leftFoot ? -1.0f : 1.0f) * profile.width * 0.72f; const glm::vec2 xy = glm::vec2(basePosition) + right * side - forward * profile.length * 0.16f; glm::vec3 position(xy.x, xy.y, basePosition.z); position.z = resolveFloorHeight(position) + 0.035f;