17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-24 09:16:25 +02:00

feat(track): frogs and crossings for every rail profile; grooved rails share the floor of their grooves where they cross and need no check rails, the V beside the rail going through is one block where the lofts of the rails overlap; the nose of an acute frog of flat rails is filled between its legs as far as their lofts overlap, like a cast insert

This commit is contained in:
maj00r
2026-10-13 21:03:17 +02:00
parent 59f1a5a144
commit 9343ebcb13
5 changed files with 387 additions and 56 deletions

View File

@@ -580,7 +580,7 @@ void TSegment::plan_frame( double const Distance, glm::dvec3 &Point, glm::dvec3
Across = glm::normalize( Across );
}
bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Origin, gfx::vertex_array const &ShapePoints, int const Side, float const Halfwidth, double const fTextureLength, double const From, double const To, std::vector<glm::dvec2> const &Offsets, std::vector<glm::dvec2> const &Extents, float const Lift, std::vector<glm::dvec2> const &Inner, gfx::userdata_array *Userdata, std::vector<glm::dvec2> const &Ramp, double const Rampwidth ) const {
bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Origin, gfx::vertex_array const &ShapePoints, int const Side, float const Halfwidth, double const fTextureLength, double const From, double const To, std::vector<glm::dvec2> const &Offsets, std::vector<glm::dvec2> const &Extents, float const Lift, std::vector<glm::dvec2> const &Inner, gfx::userdata_array *Userdata, std::vector<glm::dvec2> const &Ramp, double const Rampwidth, bool const Walls ) const {
if( fTsBuffer.empty() || To - From < 0.001 || ShapePoints.empty() )
return false;
@@ -642,6 +642,20 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
auto const offset { sample( Offsets, Distance, 0.0 ) };
auto const extent { sample( Extents, Distance, 1e6 ) };
auto const innerextent { sample( Inner, Distance, -1e6 ) };
glm::vec3 outerwall { 0.f }, innerwall { 0.f };
if( Walls ) {
auto const delta { 0.001 };
glm::dvec3 ahead, behind, unused;
plan_frame( std::min( Distance + delta, static_cast<double>( fLength ) ), ahead, unused );
plan_frame( std::max( Distance - delta, 0.0 ), behind, unused );
auto tangent { glm::dvec3{ ahead.x - behind.x, 0.0, ahead.z - behind.z } };
tangent = ( glm::length2( tangent ) > 0.0 ? glm::normalize( tangent ) : glm::dvec3{ 0.0 } );
auto const outward { glm::dvec3{ across } * static_cast<double>( Side ) };
auto const slope = [&]( std::vector<glm::dvec2> const &Knots, double const Default ) {
return ( sample( Knots, Distance + delta, Default ) - sample( Knots, Distance - delta, Default ) + sample( Offsets, Distance + delta, 0.0 ) - sample( Offsets, Distance - delta, 0.0 ) ) / ( 2.0 * delta ); };
outerwall = glm::vec3{ glm::normalize( outward - tangent * slope( Extents, 1e6 ) ) };
innerwall = glm::vec3{ glm::normalize( tangent * slope( Inner, -1e6 ) - outward ) };
}
auto const worn { sample( Ramp, Distance, -1e6 ) };
Ring.clear();
Wear.clear();
@@ -651,7 +665,9 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
for( std::size_t j = 0; j < count; ++j ) {
auto shape { ShapePoints[ j ] };
auto outside { reach( j ) };
auto wall { glm::vec3{ 0.f } };
if( outside > extent ) {
wall = outerwall;
for( auto const neighbour : { j - 1, j + 1 } ) {
if( neighbour >= count || reach( neighbour ) > extent ) {
continue;
@@ -661,11 +677,13 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
shape.position.y = glm::mix( inner.position.y, shape.position.y, t );
shape.texture.x = glm::mix( inner.texture.x, shape.texture.x, t );
shape.normal = inner.normal;
wall = glm::vec3{ 0.f };
break;
}
outside = extent;
}
else if( outside < innerextent ) {
wall = innerwall;
for( auto const neighbour : { j - 1, j + 1 } ) {
if( neighbour >= count || reach( neighbour ) < innerextent ) {
continue;
@@ -675,6 +693,7 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
shape.position.y = glm::mix( other.position.y, shape.position.y, t );
shape.texture.x = glm::mix( other.texture.x, shape.texture.x, t );
shape.normal = other.normal;
wall = glm::vec3{ 0.f };
break;
}
outside = innerextent;
@@ -683,6 +702,9 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
pt.y += shape.position.y + Lift;
auto norm { shape.normal.x * parallel };
norm.y += shape.normal.y;
if( glm::length2( wall ) > 0.f ) {
norm = wall;
}
Ring.emplace_back( pt, glm::normalize( norm ), glm::vec2{ shape.texture.x, 0.f } );
Wear.push_back( Rampwidth > 0.0 ? static_cast<float>( std::clamp( ( outside - worn + Rampwidth ) / Rampwidth, 0.0, 1.0 ) ) : 1.f );
}