17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-01 23:59:12 +01:00

perf(sleepers): the rails of each track for the fastenings worked out once and kept until its geometry is made again, it goes far or the crossings change, not again for every track laid around it; the fastenings laid only out to 30 m past where they're drawn, the tracks further out keeping their beams to lay them on as they come near; out past 50 m the tracks laid while the laying in a frame took under 2 ms, the rest in the frames after

This commit is contained in:
maj00r
2026-10-24 00:23:50 +02:00
parent 2e00619d7f
commit f155956669
8 changed files with 225 additions and 114 deletions

View File

@@ -123,29 +123,22 @@ std::pair<double, double> shared_zone( TTrack const &Track, int const Path ) {
return { zones.front().first, zones.back().second };
}
void lay( TTrack &Track ) {
namespace {
// the beams as instances of the parts of the model of the track: those of the fastenings with them, or left for later and the beams
// kept for them meanwhile
void instance( TTrack &Track, std::vector<beam> &&Beams, bool const Fastened ) {
auto &laid { Track.m_sleepers3d };
std::vector<beam> placed;
if( laid.active && in_background() && timber_model( Track ) != nullptr ) {
// worked out in the background; till then the track keeps what it has, and tries again
auto beams { laid_out( Track ) };
if( false == beams.has_value() ) {
ask_layout( Track );
return;
}
placed = std::move( *beams );
}
laid.dirty = false;
for( auto &instances : laid.instances ) {
instances.clear();
}
laid.whole.clear();
laid.plain.clear();
laid.chunks.clear();
laid.timbers = timber_model( Track );
laid.plains = plain_model( Track );
if( false == laid.active || laid.timbers == nullptr ) {
laid.fastened = true;
std::vector<beam> {}.swap( laid.beams );
if( laid.timbers == nullptr ) {
return;
}
// the sleepers of the model of the track itself (sleepermodel) at the height they're drawn at without the 3D sleepers: the
@@ -153,16 +146,6 @@ void lay( TTrack &Track ) {
auto const ownplains { laid.plains != nullptr && Track.m_sleeper_enabled && laid.plains != plain_model() };
auto const plainlift { ownplains ? Track.rail_height() + Track.m_sleeper_offset.z : 0.f };
auto const &parts { *laid.timbers };
if( auto const panel { panel_off_plane( Track ) }; panel.first > coplanar_tolerance ) {
WriteLog(
"sleepers3d: switch \"" + Track.name() + "\" has its paths " + to_string( panel.first * 1000.0, 1 ) + " mm off one plane "
+ to_string( panel.second, 2 ) + " m along, where they share the timbers of its panel" );
}
laid.laying = true;
auto const beams { in_background() ? std::move( placed ) : place( Track ) };
laid.laying = false;
// the layout of the cluster isn't needed by this track any more, the instances below are what's drawn
forget_layout( Track );
// the rails around, where they lie on the timbers, for the fastenings of the model; found at the first timber, none for plain sleepers
std::optional<fastened_rails> rails;
@@ -199,7 +182,7 @@ void lay( TTrack &Track ) {
runbeams.clear();
};
for( auto const &beam : beams ) {
for( auto const &beam : Beams ) {
if( runbeams.empty() ) {
for( int part = 0; part < part_count; ++part ) {
run.first[ part ] = static_cast<std::uint32_t>( laid.instances[ part ].size() );
@@ -265,7 +248,7 @@ void lay( TTrack &Track ) {
put( part_end, scale, parts.spans[ part_end ].x, -half );
put( part_begin, scale, parts.spans[ part_begin ].y, half );
}
if( parts.fastened() && false == ( beam.plain && laid.plains != nullptr ) ) {
if( Fastened && parts.fastened() && false == ( beam.plain && laid.plains != nullptr ) ) {
if( false == rails.has_value() ) {
rails.emplace( Track );
}
@@ -296,6 +279,55 @@ void lay( TTrack &Track ) {
laid.whole.shrink_to_fit();
laid.plain.shrink_to_fit();
laid.chunks.shrink_to_fit();
if( false == Fastened && parts.fastened() ) {
laid.fastened = false;
laid.beams = std::move( Beams );
}
}
} // namespace
void lay( TTrack &Track, bool const Fastened ) {
auto &laid { Track.m_sleepers3d };
std::vector<beam> placed;
if( laid.active && in_background() && timber_model( Track ) != nullptr ) {
// worked out in the background; till then the track keeps what it has, and tries again
auto beams { laid_out( Track ) };
if( false == beams.has_value() ) {
ask_layout( Track );
return;
}
placed = std::move( *beams );
}
laid.dirty = false;
laid.timbers = timber_model( Track );
laid.plains = plain_model( Track );
if( false == laid.active || laid.timbers == nullptr ) {
instance( Track, {}, true );
return;
}
if( auto const panel { panel_off_plane( Track ) }; panel.first > coplanar_tolerance ) {
WriteLog(
"sleepers3d: switch \"" + Track.name() + "\" has its paths " + to_string( panel.first * 1000.0, 1 ) + " mm off one plane "
+ to_string( panel.second, 2 ) + " m along, where they share the timbers of its panel" );
}
laid.laying = true;
auto beams { in_background() ? std::move( placed ) : place( Track ) };
laid.laying = false;
// the layout of the cluster isn't needed by this track any more, the instances below are what's drawn
forget_layout( Track );
instance( Track, std::move( beams ), Fastened );
}
void fasten( TTrack &Track ) {
auto &laid { Track.m_sleepers3d };
if( laid.fastened || laid.dirty ) {
return;
}
auto beams { std::move( laid.beams ) };
instance( Track, std::move( beams ), true );
}
void release_far( glm::dvec3 const &Camera, double const Range ) {
@@ -309,15 +341,19 @@ void release_far( glm::dvec3 const &Camera, double const Range ) {
next = 0;
}
auto *track { tracks[ next++ ] };
if( track == nullptr || false == track->m_sleepers3d.active || track->m_sleepers3d.laying ) {
if( track == nullptr || track->m_sleepers3d.laying ) {
continue;
}
if( glm::length( track->location() - Camera ) - track->radius() <= Range ) {
continue;
}
forget_rails( *track );
if( false == track->m_sleepers3d.active ) {
continue;
}
auto &laid { track->m_sleepers3d };
forget_layout( *track );
auto const holds { laid.chunks.capacity() > 0 || laid.whole.capacity() > 0 || laid.plain.capacity() > 0
auto const holds { laid.chunks.capacity() > 0 || laid.whole.capacity() > 0 || laid.plain.capacity() > 0 || laid.beams.capacity() > 0
|| std::any_of( laid.instances.begin(), laid.instances.end(), []( std::vector<glm::mat4> const &Instances ) { return Instances.capacity() > 0; } ) };
if( false == holds ) {
continue;
@@ -328,6 +364,7 @@ void release_far( glm::dvec3 const &Camera, double const Range ) {
std::vector<glm::mat4> {}.swap( laid.whole );
std::vector<glm::mat4> {}.swap( laid.plain );
std::vector<chunk> {}.swap( laid.chunks );
std::vector<beam> {}.swap( laid.beams );
laid.dirty = true;
}
}