From 2b93c91b00b7a05c17bd332b7bc819bb44840032 Mon Sep 17 00:00:00 2001 From: Anders Pistol Date: Sun, 16 Jun 2024 12:05:20 +0200 Subject: [PATCH] Traktor: Improved applying terrain editing brush when editing at a grazing angle etc. --- code/Heightfield/Heightfield.cpp | 23 +++++---- code/Terrain/Editor/TerrainEditModifier.cpp | 54 +++++++++++++++------ 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/code/Heightfield/Heightfield.cpp b/code/Heightfield/Heightfield.cpp index 3df0ef02f..cbf14c005 100644 --- a/code/Heightfield/Heightfield.cpp +++ b/code/Heightfield/Heightfield.cpp @@ -334,30 +334,35 @@ bool Heightfield::queryRay(const Vector4& worldRayOrigin, const Vector4& worldRa { for (int32_t cx = 0; cx < m_size; cx += c_cellSize) { + // Calculate bounding box of cell. float cx1w, cz1w; float cx2w, cz2w; gridToWorld(float(cx), float(cz), cx1w, cz1w); gridToWorld(float(cx + c_cellSize), float(cz + c_cellSize), cx2w, cz2w); - const float cyw[] = - { - unitToWorld(getGridHeightNearest(cx, cz)), - unitToWorld(getGridHeightNearest(cx + c_cellSize, cz)), - unitToWorld(getGridHeightNearest(cx, cz + c_cellSize)), - unitToWorld(getGridHeightNearest(cx + c_cellSize, cz + c_cellSize)) - }; + float cy1w = std::numeric_limits< float >::max(); + float cy2w = -std::numeric_limits< float >::max(); - const float cy1w = *std::min_element(cyw, cyw + sizeof_array(cyw)); - const float cy2w = *std::max_element(cyw, cyw + sizeof_array(cyw)); + for (int32_t iz = cz; iz <= cz + c_cellSize; iz += c_skip) + { + for (int32_t ix = cx; ix <= cx + c_cellSize; ix += c_skip) + { + const float wy = unitToWorld(getGridHeightNearest(ix, iz)); + cy1w = std::min(cy1w, wy); + cy2w = std::max(cy2w, wy); + } + } Aabb3 bb; bb.mn = Vector4(cx1w, cy1w, cz1w, 1.0f); bb.mx = Vector4(cx2w, cy2w, cz2w, 1.0f); + // Check if ray intersect bounding box; skip tracing triangles if not. if (!bb.intersectRay(worldRayOrigin, worldRayDirection, kIn, kOut)) continue; + // Construct and trace triangles. for (int32_t iz = cz; iz <= cz + c_cellSize; iz += c_skip) { for (int32_t ix = cx; ix <= cx + c_cellSize; ix += c_skip) diff --git a/code/Terrain/Editor/TerrainEditModifier.cpp b/code/Terrain/Editor/TerrainEditModifier.cpp index ad0cd3f41..1e1d191e5 100644 --- a/code/Terrain/Editor/TerrainEditModifier.cpp +++ b/code/Terrain/Editor/TerrainEditModifier.cpp @@ -583,27 +583,53 @@ void TerrainEditModifier::apply( if (!m_terrainComponent || m_center.w() <= FUZZY_EPSILON) return; - // Find furthest intersection which allows for editing around hills etc. - Vector4 center = worldRayOrigin; - bool found = false; - for (;;) + Vector4 center = Vector4::zero(); + Scalar distance; + + if (m_applied) { - center += worldRayDirection * 0.01_simd; + // Find furthest intersection which allows for editing around hills etc. + Scalar minD = Scalar(std::numeric_limits< float >::max()); + Vector4 step = worldRayOrigin; + bool found = false; + + for (;;) + { + step += worldRayDirection * 0.01_simd; + + if (!m_heightfield->queryRay( + step, + worldRayDirection, + distance + )) + break; + + step = (step + worldRayDirection * distance).xyz1(); + + const Scalar d = (step - m_center).xyz0().length(); + if (d < minD) + { + center = step; + minD = d; + found = true; + } + } - Scalar distance; + if (!found) + return; + } + else + { if (!m_heightfield->queryRay( - center, + worldRayOrigin, worldRayDirection, distance )) - break; - - center = (center + worldRayDirection * distance).xyz1(); - found = true; + return; + + center = (worldRayOrigin + worldRayDirection * distance).xyz1(); } - if (!found) - return; - + apply(center); }