mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-05 15:42:31 +01: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:
@@ -345,6 +345,9 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
std::size_t samples{0};
|
std::size_t samples{0};
|
||||||
double band{300.0}; // m from the tracks the chunks made along them reach
|
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 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 slope{1.5};
|
||||||
double reach{60.0};
|
double reach{60.0};
|
||||||
std::vector<heightmap::chunk_key> pending; // chunks to make once their model is in
|
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
|
// of the modifiers laid
|
||||||
std::size_t nmt_shape_tracks(std::vector<TTrack *> const *Only = nullptr);
|
std::size_t nmt_shape_tracks(std::vector<TTrack *> const *Only = nullptr);
|
||||||
void nmt_update();
|
void nmt_update();
|
||||||
|
void nmt_grow();
|
||||||
void render_nmt_ui();
|
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
|
// 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();
|
void nmt_offer();
|
||||||
|
|||||||
@@ -452,6 +452,8 @@ void editor_mode::nmt_make(std::vector<heightmap::chunk_key> const &Keys, bool c
|
|||||||
++queued;
|
++queued;
|
||||||
}
|
}
|
||||||
state.made = 0;
|
state.made = 0;
|
||||||
|
if (queued > 0)
|
||||||
|
state.grown = false;
|
||||||
// the terrain comes with its photos
|
// the terrain comes with its photos
|
||||||
if (queued > 0 && false == m_orthophoto.enabled())
|
if (queued > 0 && false == m_orthophoto.enabled())
|
||||||
m_orthophoto.enabled(true);
|
m_orthophoto.enabled(true);
|
||||||
@@ -597,6 +599,7 @@ void editor_mode::nmt_update()
|
|||||||
nmt_finish_fit();
|
nmt_finish_fit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
nmt_grow();
|
||||||
if (state.pending.empty())
|
if (state.pending.empty())
|
||||||
return;
|
return;
|
||||||
// a few chunks a frame, those whose model is in
|
// 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());
|
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.pending.empty())
|
||||||
{
|
{
|
||||||
if (state.shape)
|
if (state.shape && false == state.grown)
|
||||||
{
|
{
|
||||||
nmt_shape_tracks();
|
nmt_shape_tracks();
|
||||||
state.status += format(STR_P("; the formation of %zu path shaped", "; the formation of %zu paths shaped", state.shaped), state.shaped);
|
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);
|
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()
|
void editor_mode::render_nmt_ui()
|
||||||
{
|
{
|
||||||
auto &state{m_nmt_state};
|
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")};
|
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"));
|
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
|
// how far it got
|
||||||
if (state.stage == nmt_state::automatic::fetching || state.fitting)
|
if (state.stage == nmt_state::automatic::fetching || state.fitting)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9943,3 +9943,9 @@ msgstr "równolegle do %s"
|
|||||||
|
|
||||||
msgid "%.0f deg to %s"
|
msgid "%.0f deg to %s"
|
||||||
msgstr "%.0f° do %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"
|
||||||
|
|||||||
Reference in New Issue
Block a user