17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-20 11:34:53 +02:00

feat(editor): the terrain of a scenery begun from nothing grows where the track is laid

The terrain model was made once around the camera when a new scenery
took it; tracks laid on past it went over nothing. While a track is laid
or dragged out, the chunks missing within 400 m of the cursor are now
made from the model too, the nearest first, in a scenery with the
heightmap terrain placed on the map. The formations aren't made anew
after such chunks. A chip in the terrain panel turns it off.
This commit is contained in:
maj00r
2026-10-19 19:01:49 +02:00
parent bedef1f2af
commit af9e836632
3 changed files with 53 additions and 1 deletions

View File

@@ -345,6 +345,9 @@ class editor_mode : public application_mode, private editor_track::observer
std::size_t samples{0};
double band{300.0}; // m from the tracks the chunks made along them reach
bool shape{true}; // the formation and the slopes of the tracks as modifiers of the terrain
bool grow{true}; // while a track is laid, the terrain is made around the cursor where there's none
bool grown{false}; // the chunks waiting were all asked for by growing: the formations aren't made anew after them
double grow_time{-10.0};
double slope{1.5};
double reach{60.0};
std::vector<heightmap::chunk_key> pending; // chunks to make once their model is in
@@ -406,6 +409,7 @@ class editor_mode : public application_mode, private editor_track::observer
// of the modifiers laid
std::size_t nmt_shape_tracks(std::vector<TTrack *> const *Only = nullptr);
void nmt_update();
void nmt_grow();
void render_nmt_ui();
// a scenery begun from nothing, with no tracks nor terrain, is asked as the first track is laid whether it wants the terrain
void nmt_offer();

View File

@@ -452,6 +452,8 @@ void editor_mode::nmt_make(std::vector<heightmap::chunk_key> const &Keys, bool c
++queued;
}
state.made = 0;
if (queued > 0)
state.grown = false;
// the terrain comes with its photos
if (queued > 0 && false == m_orthophoto.enabled())
m_orthophoto.enabled(true);
@@ -597,6 +599,7 @@ void editor_mode::nmt_update()
nmt_finish_fit();
return;
}
nmt_grow();
if (state.pending.empty())
return;
// a few chunks a frame, those whose model is in
@@ -623,7 +626,7 @@ void editor_mode::nmt_update()
state.status = format(STR_C("Chunks made from the terrain model: %zu, waiting for it: %zu"), state.made, state.pending.size());
if (state.pending.empty())
{
if (state.shape)
if (state.shape && false == state.grown)
{
nmt_shape_tracks();
state.status += format(STR_P("; the formation of %zu path shaped", "; the formation of %zu paths shaped", state.shaped), state.shaped);
@@ -637,6 +640,44 @@ void editor_mode::nmt_update()
state.error = STR(error);
}
void editor_mode::nmt_grow()
{
auto &state{m_nmt_state};
auto const now{ImGui::GetTime()};
if (false == state.grow || now - state.grow_time < 0.5 || (false == m_lay.active && false == m_extend.active) || m_streamer.resident() == 0 || false == m_nmt.placed())
return;
state.grow_time = now;
auto const at{m_extend.active ? m_extend.mouse : m_lay.mouse};
glm::dvec2 const cursor{at.x, at.z};
double constexpr grow_reach{400.0}; // m around the cursor
auto const reach{static_cast<int>(std::ceil(grow_reach / heightmap::chunk_size))};
auto const centre{heightmap::chunk_at(at.x, at.z)};
std::vector<std::pair<double, heightmap::chunk_key>> missing;
for (int dz = -reach; dz <= reach; ++dz)
for (int dx = -reach; dx <= reach; ++dx)
{
heightmap::chunk_key const key{centre.first + dx, centre.second + dz};
auto const low{heightmap::chunk_corner(key)};
glm::dvec2 const nearest{std::clamp(cursor.x, low.x, low.x + heightmap::chunk_size), std::clamp(cursor.y, low.y, low.y + heightmap::chunk_size)};
auto const distance{glm::distance(nearest, cursor)};
if (distance <= grow_reach && false == m_streamer.exists(key) && std::find(state.pending.begin(), state.pending.end(), key) == state.pending.end())
missing.emplace_back(distance, key);
}
if (missing.empty())
return;
std::sort(missing.begin(), missing.end());
if (state.pending.empty())
{
state.grown = true;
state.made = 0;
}
for (auto const &chunk : missing)
state.pending.push_back(chunk.second);
if (false == m_orthophoto.enabled())
m_orthophoto.enabled(true);
WriteLog(format("Editor: NMT - %zu chunks around the cursor to make", missing.size()), logtype::generic);
}
void editor_mode::render_nmt_ui()
{
auto &state{m_nmt_state};
@@ -748,6 +789,7 @@ void editor_mode::render_nmt_ui()
STR_C("Loads the terrain model, the real relief of the ground, around the camera")};
ImGui::SetTooltip("%s\n%s", text, STR_C("Terrain model: GUGiK, geoportal.gov.pl"));
}
toggle_chips("nmtgrow", {{STR_C("Make the terrain ahead while laying"), &state.grow, "Where a track is laid past the edge of the terrain, the terrain model is made around the cursor as it goes"}});
// how far it got
if (state.stage == nmt_state::automatic::fetching || state.fitting)
{

View File

@@ -9943,3 +9943,9 @@ msgstr "równolegle do %s"
msgid "%.0f deg to %s"
msgstr "%.0f° do %s"
msgid "Make the terrain ahead while laying"
msgstr "Dobudowuj teren przy układaniu"
msgid "Where a track is laid past the edge of the terrain, the terrain model is made around the cursor as it goes"
msgstr "Gdy tor wychodzi poza teren, NMT dobudowuje się wokół kursora na bieżąco"