17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-19 08:29:18 +02:00

fix(track): a crossing of grooved rails is one flat block where their lofts overlap; the rail cut by the other covers the roundings of the rail going through, the tops in the block are flat in one texture, the plates of the V reach up to the rail top, the walls of the cuts are lit and textured as walls, and the nose between two flangeways starts blunt at the width of a nose tip instead of a thin sliver standing in the groove

This commit is contained in:
maj00r
2026-10-13 22:03:36 +02:00
parent 18c01ceb72
commit 2ece18cc4a
5 changed files with 198 additions and 48 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, bool const Walls ) 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, float const Wallu ) const {
if( fTsBuffer.empty() || To - From < 0.001 || ShapePoints.empty() )
return false;
@@ -662,41 +662,53 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
auto const count { ShapePoints.size() };
auto const reach = [&]( std::size_t const Index ) {
return static_cast<double>( Side * ShapePoints[ Index ].position.x - Halfwidth ); };
auto const twin = [&]( std::size_t const A, std::size_t const B ) {
return ShapePoints[ A ].position.x == ShapePoints[ B ].position.x && ShapePoints[ A ].position.y == ShapePoints[ B ].position.y; };
auto const clamped = [&]( std::size_t const Index ) {
auto const outside { reach( Index ) };
return ( outside > extent ? 1 : outside < innerextent ? -1 : 0 ); };
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;
auto const side { clamped( j ) };
if( side != 0 ) {
auto const limit { side > 0 ? extent : innerextent };
auto const open = [&]( std::size_t const Index ) {
return Index < count && ( side > 0 ? reach( Index ) <= extent : reach( Index ) >= innerextent ); };
auto first { j };
auto last { j };
if( Walls ) {
while( first > 0 && twin( first - 1, j ) ) {
--first;
}
while( last + 1 < count && twin( last + 1, j ) ) {
++last;
}
auto const &inner { ShapePoints[ neighbour ] };
auto const t { static_cast<float>( ( extent - reach( neighbour ) ) / std::max( outside - reach( neighbour ), 1e-6 ) ) };
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 ) {
auto const paired { last > first && first > 0 && last + 1 < count };
auto const before { paired ? first - 1 : j - 1 };
auto const after { paired ? last + 1 : j + 1 };
auto const partner { j == last ? after : before };
auto moved { count };
for( auto const neighbour : { paired ? partner : before, paired ? ( partner == before ? after : before ) : after } ) {
if( false == open( neighbour ) ) {
continue;
}
auto const &other { ShapePoints[ neighbour ] };
auto const t { static_cast<float>( ( innerextent - reach( neighbour ) ) / std::min( outside - reach( neighbour ), -1e-6 ) ) };
auto const t { static_cast<float>( ( limit - reach( neighbour ) ) / ( side > 0 ? std::max( outside - reach( neighbour ), 1e-6 ) : std::min( outside - reach( neighbour ), -1e-6 ) ) ) };
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 };
auto const blend { glm::mix( other.normal, shape.normal, t ) };
shape.normal = ( glm::length2( blend ) > 1e-6f ? blend : other.normal );
moved = neighbour;
break;
}
outside = innerextent;
outside = limit;
auto const onwall { paired ? ( false == open( partner ) && clamped( partner ) == side ) : moved == count };
if( onwall ) {
wall = ( side > 0 ? outerwall : innerwall );
}
}
auto pt { parallel * static_cast<float>( Side * ( Halfwidth + outside + offset ) ) + position };
pt.y += shape.position.y + Lift;
@@ -704,6 +716,9 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
norm.y += shape.normal.y;
if( glm::length2( wall ) > 0.f ) {
norm = wall;
if( Wallu >= 0.f ) {
shape.texture.x = Wallu;
}
}
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 );