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
This commit is contained in:
Eliot Byte 2025-10-23 12:29:04 +03:00 committed by GitHub
parent 6c01d57d53
commit ed9cf8800a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 10 deletions

View File

@ -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<float>(dot_product) / static_cast<float>(len2);
t = glm::clamp(t, 0.0f, 1.0f);
return a + glm::ivec3(glm::round(glm::vec3(vec) * t));
}
}

View File

@ -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++) {