From ed9cf8800aea07c169719a3efddae7020e6be7e9 Mon Sep 17 00:00:00 2001 From: Eliot Byte Date: Thu, 23 Oct 2025 12:29:04 +0300 Subject: [PATCH] fix correct line generation algorithm and bounds calculation (#657) * fix correct line generation algorithm and bounds calculation - Fix closest_point_on_segment algorithm using proper dot product projection - Correct loop bounds calculation for radius=0 lines - Use precise integer arithmetic to avoid rounding errors - Resolves missing blocks in vertical line structures * fix ai hallucinations * polishing closest_point_on_segment * refactor: extract dot product calculation --- src/maths/util.hpp | 24 +++++++++++++++++------- src/world/generator/WorldGenerator.cpp | 6 +++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/maths/util.hpp b/src/maths/util.hpp index 00345942..2aa3605c 100644 --- a/src/maths/util.hpp +++ b/src/maths/util.hpp @@ -118,6 +118,11 @@ namespace util { return x * x + y * y + z * z; } + /// @return integer dot product of two vectors + inline int dot(const glm::ivec3& a, const glm::ivec3& b) { + return a.x * b.x + a.y * b.y + a.z * b.z; + } + /// @brief Find nearest point on segment to given /// @param a segment point A /// @param b segment point B @@ -144,12 +149,17 @@ namespace util { inline glm::ivec3 closest_point_on_segment( const glm::ivec3& a, const glm::ivec3& b, const glm::ivec3& point ) { - auto vec = b - a; - float da = distance2(point, a); - float db = distance2(point, b); - float len = length2(vec); - float t = (((da - db) / len) * 0.5f + 0.5f); - t = std::min(1.0f, std::max(0.0f, t)); - return a + glm::ivec3(glm::vec3(vec) * t); + glm::ivec3 vec = b - a; + int len2 = length2(vec); + + if (len2 == 0) return a; + + glm::ivec3 ap = point - a; + int dot_product = dot(ap, vec); + + float t = static_cast(dot_product) / static_cast(len2); + t = glm::clamp(t, 0.0f, 1.0f); + + return a + glm::ivec3(glm::round(glm::vec3(vec) * t)); } } diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index e2bf4a86..ccd52db1 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -547,13 +547,13 @@ void WorldGenerator::generateLine( auto b = line.b; int minX = std::max(0, std::min(a.x-radius-cgx, b.x-radius-cgx)); - int maxX = std::min(CHUNK_W, std::max(a.x+radius-cgx, b.x+radius-cgx)); + int maxX = std::min(CHUNK_W, std::max(a.x+radius-cgx, b.x+radius-cgx) + 1); int minZ = std::max(0, std::min(a.z-radius-cgz, b.z-radius-cgz)); - int maxZ = std::min(CHUNK_D, std::max(a.z+radius-cgz, b.z+radius-cgz)); + int maxZ = std::min(CHUNK_D, std::max(a.z+radius-cgz, b.z+radius-cgz) + 1); int minY = std::max(0, std::min(a.y-radius, b.y-radius)); - int maxY = std::min(CHUNK_H, std::max(a.y+radius, b.y+radius)); + int maxY = std::min(CHUNK_H, std::max(a.y+radius, b.y+radius) + 1); for (int y = minY; y < maxY; y++) { for (int z = minZ; z < maxZ; z++) {