From e32294730008834fd659e4e4652f4a1cc333d510 Mon Sep 17 00:00:00 2001 From: maj00r Date: Sat, 24 Oct 2026 18:00:21 +0200 Subject: [PATCH] fix(editor): the track shown while it's laid over the ground no longer holds up the frames: its grade line is fitted on a thread of its own, the line fitted a moment ago stretched over the track meanwhile, and the click takes the line fitted for the same ground instead of fitting it again; the terrain follows the tracks once the laying ends, not after each click of a chain Fitting the grade line took 3 ms for 250 m of track, 30 ms for 1 km, 65 ms for 2 km and 200 ms for 4 km, and the preview of the lay tool and of the drag from a free end fitted it every frame, twice for the drag; on the terrain model the preview of some 800 m took 10 to 17 ms a frame, the cursor standing or not. Now the frame waits under 1.5 ms for 4 km. The formations of the tracks led into the terrain went through every chunk under them 0.3 s after each click, some 50 ms, while the cursor went on to the next point; they wait for the laying to end. The tracks laid and the terrain are the same as before. Selftests: perf logs the longest frame and those over 33 ms, fittime the time of the fit by length, terrainhash a hash of the chunks in memory. --- application/editormode.h | 7 + application/editormodelay.cpp | 10 + application/editormodenmt.cpp | 4 + application/editormodeselftest.cpp | 16 +- application/editormodeselftest.h | 13 ++ application/editormodeselftestjoin.cpp | 29 +++ application/editormodeselftestscene.cpp | 4 +- application/editormodeselftestterrain.cpp | 18 ++ application/editormodetrack.cpp | 6 +- application/editormodetrackbed.cpp | 12 +- editor/editorGroundFollow.cpp | 223 ++++++++++++++++++---- editor/editorGroundFollow.hpp | 55 +++++- 12 files changed, 354 insertions(+), 43 deletions(-) diff --git a/application/editormode.h b/application/editormode.h index 987ba5d3..d55ffc09 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -39,6 +39,7 @@ http://mozilla.org/MPL/2.0/. #include "editor/editorSpeed.hpp" #include "editor/editorRoad.hpp" #include "editor/editorProfile.hpp" +#include "editor/editorGroundFollow.hpp" #include "editor/editorInfra.hpp" #include "editor/editorGauge.hpp" #include "editor/editorClips.hpp" @@ -1512,6 +1513,8 @@ class editor_mode : public application_mode, private editor_track::observer, pri bool start_extend(editor_track::snap_target const &End); void finish_extend(); std::vector extend_pieces() const; + // the same for the track shown while it's dragged: its grade line fitted on the thread of the fitter, the frame not waiting for it + std::vector extend_preview() const; // the free end of the path as the start of a new track; false if it isn't free or has no direction static bool free_end(TTrack &Track, int const Path, bool const Atend, extend_tool &Tool); // the free end new pieces are added at: the selected point if it's one, else the end, else the start @@ -1732,6 +1735,10 @@ class editor_mode : public application_mode, private editor_track::observer, pri static std::pair trackbed(TTrack const *Style); std::vector bed_heights(std::vector const &Points, std::vector const &Directions, TTrack const *Style) const; void follow_ground(std::vector &Pieces, double const Height0, double const Grade0, double const Height1, double const Grade1, TTrack const *Style) const; + ground_follow::grading laying_grading(TTrack const *Style) const; + // the grade lines of the tracks shown while they're laid are fitted on a thread of their own, not to hold up the frames + mutable ground_follow::fitter m_fitter; + mutable bool m_follow_preview{false}; glm::dvec3 lay_bed(glm::dvec3 const &Point); std::optional m_cursor_override; bool sweep_grabs(glm::dvec3 const &Point); diff --git a/application/editormodelay.cpp b/application/editormodelay.cpp index 9e4e6bcb..53e3a7fa 100644 --- a/application/editormodelay.cpp +++ b/application/editormodelay.cpp @@ -101,7 +101,9 @@ void editor_mode::update_build_tools() if (plan_distance(lay.mouse, points.back()) > 1.0) points.push_back(lay.mouse); } + m_follow_preview = true; lay.preview = lay_pieces(points, end, lay.preview_length, lay.preview_error); + m_follow_preview = false; } bool editor_mode::free_end(TTrack &Track, int const Path, bool const Atend, extend_tool &Tool) @@ -490,6 +492,14 @@ std::vector editor_mode::extend_pieces() const return pieces; } +std::vector editor_mode::extend_preview() const +{ + m_follow_preview = true; + auto pieces{extend_pieces()}; + m_follow_preview = false; + return pieces; +} + TTrack const *editor_mode::speed_track(TTrack const *From, TTrack const *To) const { if (m_lay.own_speed && m_lay.style.velocity > 0.0) diff --git a/application/editormodenmt.cpp b/application/editormodenmt.cpp index e13e5c2e..9630cb94 100644 --- a/application/editormodenmt.cpp +++ b/application/editormodenmt.cpp @@ -691,6 +691,10 @@ void editor_mode::nmt_follow_tracks() return; if (state.stage != nmt_state::automatic::idle || state.fitting || ImGui::GetTime() - state.changed_time < 0.3 || ImGui::IsMouseDown(ImGuiMouseButton_Left) || ImGui::IsMouseDown(ImGuiMouseButton_Right)) return; + // laying on, from the end of the track laid or dragged from a free end, the terrain waits for the laying to end: shaping it + // goes through every chunk under the tracks, a stall each click + if ((m_lay.active && false == m_lay.points.empty()) || m_extend.active) + return; if (false == m_streamer.active()) { state.changed.clear(); diff --git a/application/editormodeselftest.cpp b/application/editormodeselftest.cpp index 749ad391..b74389cb 100644 --- a/application/editormodeselftest.cpp +++ b/application/editormodeselftest.cpp @@ -151,7 +151,11 @@ editor_mode::selftest_result editor_mode::selftest_dispatch(std::string const &c // screenshot // save // log -// perf