17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-08 05:10:41 +01:00

feat(track): 3D sleepers and switch timbers, blade heel and throw from templates, one rail carving pass

- sleepers3d / sleepers3dplain / sleepers3dbed in eu07.ini: timbers put together from the begin, main and end parts of a model
  and stretched to their length, plain sleepers of their own model; tracks whose plain sleepers would touch are laid as one
  cluster, lines of timbers led by priority and turned to the bisectors of frogs and crossings at a limited rate, whole timbers
  under crossings, split ones between tracks with room to part them, gaps filled per rail and overlaps shortened or dropped;
  clusters worked out in a background thread while driving, on demand in the editor
- the ballast can be left out under the beams (sleepers3dbed no)
- blades get their heel and throw from the switch template or blades <heel> <throw> in the scenery; blades of double switches
  run on into the track linking them to the next switch
- rail cutting at frogs, wing rails, movable noses and switch crossings done by one carving pass (RailCarve)
- tint of the rail treads applied to the colour only, without the matte band at the frog
- a switch trailed through with a movable nose set the other way derails the vehicle
- self-tests: sleepercheck, sharedzones, beamsnear, throw, sleepersbg
This commit is contained in:
maj00r
2026-10-17 23:28:36 +02:00
parent 21eca4d9a6
commit d25f20a56c
49 changed files with 9802 additions and 848 deletions

View File

@@ -35,12 +35,13 @@ inline double sample( line const &Line, double const Position, double const Defa
if( Position <= Line.front().x ) {
return Line.front().y;
}
for( std::size_t i = 1; i < Line.size(); ++i ) {
if( Position <= Line[ i ].x ) {
return glm::mix( Line[ i - 1 ].y, Line[ i ].y, ( Position - Line[ i - 1 ].x ) / std::max( Line[ i ].x - Line[ i - 1 ].x, 1e-6 ) );
}
// the first knot at or past the position, after the first one
auto const next { std::lower_bound( Line.begin() + 1, Line.end(), Position, []( glm::dvec2 const &Knot, double const At ) { return Knot.x < At; } ) };
if( next == Line.end() ) {
return Line.back().y;
}
return Line.back().y;
auto const &before { *( next - 1 ) };
return glm::mix( before.y, next->y, ( Position - before.x ) / std::max( next->x - before.x, 1e-6 ) );
}
inline line shifted( line Line, double const Value ) {
@@ -107,4 +108,44 @@ inline line middle( line const &A, line const &B ) {
return result;
}
// both lines added up, each going on flat past its ends
inline line sum( line const &A, line const &B ) {
if( A.empty() || B.empty() ) {
return ( A.empty() ? B : A );
}
line result;
for( auto const position : stations( A, B ) ) {
if( false == result.empty() && position - result.back().x < 1e-9 ) {
continue;
}
result.emplace_back( position, sample( A, position, 0.0 ) + sample( B, position, 0.0 ) );
}
return result;
}
// the line without the knots lying on the straight between the knots kept around them, within Tolerance
inline line simplified( line const &Line, double const Tolerance ) {
if( Line.size() < 3 ) {
return Line;
}
line result { Line.front() };
std::size_t kept { 0 };
for( std::size_t i = 2; i < Line.size(); ++i ) {
auto const &a { Line[ kept ] };
auto const &b { Line[ i ] };
for( std::size_t j = kept + 1; j < i; ++j ) {
auto const t { ( Line[ j ].x - a.x ) / std::max( b.x - a.x, 1e-9 ) };
if( std::abs( glm::mix( a.y, b.y, t ) - Line[ j ].y ) > Tolerance ) {
kept = i - 1;
result.push_back( Line[ kept ] );
break;
}
}
}
result.push_back( Line.back() );
return result;
}
} // namespace knots