mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-23 18:25:15 +02:00
merge feat/rail-crossings: the split rail code, mitred wide crossings, guard rail treads, check rail spacers and frogs for every rail profile, with the geometric switch blades moved into RailCrossings, their shape in track_rails::switch_blade and the lowering of the head in loft_span
This commit is contained in:
124
world/Track.cpp
124
world/Track.cpp
@@ -1460,20 +1460,20 @@ void TTrack::rebuild_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
|
||||
void TTrack::share_joints() {
|
||||
|
||||
for( int path = 0; path < ( eType == tt_Switch ? 2 : 1 ); ++path ) {
|
||||
for( int path = 0; path < track_rails::path_count( *this ); ++path ) {
|
||||
auto *segment { eType == tt_Switch ? SwitchExtension->Segments[ path ].get() : Segment.get() };
|
||||
if( segment == nullptr ) {
|
||||
continue;
|
||||
}
|
||||
for( int end = 0; end < 2; ++end ) {
|
||||
std::optional<std::pair<glm::dvec3, glm::dvec3>> joint;
|
||||
auto *neighbour { eType == tt_Switch ? ( end ? SwitchExtension->pNexts[ path ] : SwitchExtension->pPrevs[ path ] ) : ( end ? trNext : trPrev ) };
|
||||
auto *neighbour { track_rails::path_neighbour( *this, path, end ) };
|
||||
if( neighbour != nullptr && neighbour != this && ( neighbour->iCategoryFlag & 15 ) == ( iCategoryFlag & 15 ) ) {
|
||||
glm::dvec3 point;
|
||||
glm::dvec3 across;
|
||||
segment->plan_frame( end ? segment->GetLength() : 0.0, point, across );
|
||||
auto closest { 0.2 };
|
||||
for( int theirpath = 0; theirpath < ( neighbour->eType == tt_Switch ? 2 : 1 ); ++theirpath ) {
|
||||
for( int theirpath = 0; theirpath < track_rails::path_count( *neighbour ); ++theirpath ) {
|
||||
auto const *theirs { neighbour->eType == tt_Switch ? neighbour->SwitchExtension->Segments[ theirpath ].get() : neighbour->Segment.get() };
|
||||
if( theirs == nullptr ) {
|
||||
continue;
|
||||
@@ -1601,7 +1601,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
if( false == lay_rail( Path, Profile, Side, Texturelength, track_rails::blade_length( *this, Path ), false, false, Geometry, Cuts ) ) {
|
||||
gfx::vertex_array vertices;
|
||||
if( auto const &shape { blade( Path ) }; shape.valid ) {
|
||||
SwitchExtension->Segments[ Path ]->RenderLoftSpan( vertices, m_origin, Profile, Side, 0.5f * std::abs( fTrackWidth ), Texturelength, shape.heel, SwitchExtension->Segments[ Path ]->GetLength(), {} );
|
||||
SwitchExtension->Segments[ Path ]->RenderLoftSpan( vertices, m_origin, Profile, { .side = Side, .halfwidth = 0.5f * std::abs( fTrackWidth ), .texturelength = Texturelength, .from = shape.heel, .to = SwitchExtension->Segments[ Path ]->GetLength() } );
|
||||
}
|
||||
else {
|
||||
SwitchExtension->Segments[ Path ]->RenderLoft( vertices, m_origin, Profile, false, Texturelength, 1.0, track_rails::blade_steps( *this, Path ) );
|
||||
@@ -2157,7 +2157,7 @@ void TTrack::loft_blade( int const Path, gfx::vertex_array const &Rail, gfx::ver
|
||||
offsets.emplace_back( bend.x, -thrown * bend.y );
|
||||
}
|
||||
auto const size { rail_dimensions() };
|
||||
SwitchExtension->Segments[ Path ]->RenderLoftSpan( Vertices, m_origin, Rail, blade_side( Path ), 0.5f * std::abs( fTrackWidth ), Texturelength, shape.tip, shape.heel, offsets, shape.extents, 0.f, {}, nullptr, {}, 0.0, true, -1.f, glm::dvec2 { 0.0 }, shape.drops, { size.neck, size.crest } );
|
||||
SwitchExtension->Segments[ Path ]->RenderLoftSpan( Vertices, m_origin, Rail, { .side = blade_side( Path ), .halfwidth = 0.5f * std::abs( fTrackWidth ), .texturelength = Texturelength, .from = shape.tip, .to = shape.heel, .offsets = offsets, .extents = shape.extents, .walls = true, .drops = shape.drops, .head = { size.neck, size.crest } } );
|
||||
return;
|
||||
}
|
||||
auto const bladelength { track_rails::blade_steps( *this, Path ) };
|
||||
@@ -2730,121 +2730,13 @@ TTrack::track_rail_profile( int const Profile ) {
|
||||
return m_profiles[ Profile ];
|
||||
}
|
||||
|
||||
TTrack::rail_size
|
||||
track_rails::rail_size
|
||||
TTrack::rail_dimensions() const {
|
||||
|
||||
rail_size result;
|
||||
if( m_profiles.empty() ) {
|
||||
return result;
|
||||
return {};
|
||||
}
|
||||
auto const &profile { track_rail_profile( m_profile1.second ) };
|
||||
auto const count { profile.size() / 2 };
|
||||
if( count < 2 ) {
|
||||
return result;
|
||||
}
|
||||
auto top { -1e9 };
|
||||
auto bottom { 1e9 };
|
||||
result.low = 1e9;
|
||||
result.high = -1e9;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
top = std::max( top, static_cast<double>( point.y ) );
|
||||
bottom = std::min( bottom, static_cast<double>( point.y ) );
|
||||
result.low = std::min( result.low, static_cast<double>( point.x ) );
|
||||
result.high = std::max( result.high, static_cast<double>( point.x ) );
|
||||
}
|
||||
result.height = top - bottom;
|
||||
result.crest = top;
|
||||
auto const middle { top - 0.5 * result.height };
|
||||
auto webfrom { 1e9 };
|
||||
auto webto { -1e9 };
|
||||
for( std::size_t i = 0; i + 1 < count; ++i ) {
|
||||
auto const &a { profile[ i ].position };
|
||||
auto const &b { profile[ i + 1 ].position };
|
||||
if( a.y != b.y && ( a.y - middle ) * ( b.y - middle ) <= 0.0 ) {
|
||||
auto const x { a.x + ( b.x - a.x ) * ( middle - a.y ) / ( b.y - a.y ) };
|
||||
webfrom = std::min( webfrom, x );
|
||||
webto = std::max( webto, x );
|
||||
}
|
||||
}
|
||||
if( webfrom < webto ) {
|
||||
result.web = 0.5 * ( webfrom + webto );
|
||||
result.neck = top;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > middle && ( point.x < webfrom - 0.0005 || point.x > webto + 0.0005 ) ) {
|
||||
result.neck = std::min( result.neck, static_cast<double>( point.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
result.head = 0.0;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > top - 0.3 * result.height ) {
|
||||
result.head = std::max( result.head, static_cast<double>( point.x ) );
|
||||
}
|
||||
}
|
||||
result.tread = result.head;
|
||||
std::vector<std::size_t> heads, lips;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > top - 0.015 ) {
|
||||
( point.x < -0.02 ? lips : heads ).push_back( i );
|
||||
}
|
||||
}
|
||||
if( heads.empty() || lips.empty() ) {
|
||||
return result;
|
||||
}
|
||||
auto const first { heads.back() < lips.front() ? heads.back() : lips.back() };
|
||||
auto const last { heads.back() < lips.front() ? lips.front() : heads.front() };
|
||||
if( first >= last || ( heads.back() > lips.front() && lips.back() > heads.front() ) ) {
|
||||
return result;
|
||||
}
|
||||
auto groove { 1e9 };
|
||||
for( auto i { first + 1 }; i < last; ++i ) {
|
||||
groove = std::min( groove, static_cast<double>( profile[ i ].position.y ) );
|
||||
}
|
||||
if( groove > top ) {
|
||||
return result;
|
||||
}
|
||||
result.grooved = true;
|
||||
result.groove = groove;
|
||||
result.lip = -1e9;
|
||||
result.liptop = -1e9;
|
||||
for( auto const i : lips ) {
|
||||
result.lip = std::max( result.lip, static_cast<double>( profile[ i ].position.x ) );
|
||||
result.liptop = std::max( result.liptop, static_cast<double>( profile[ i ].position.y ) );
|
||||
}
|
||||
result.tread = -1e9;
|
||||
for( auto const i : heads ) {
|
||||
if( profile[ i ].position.y > top - 0.0005 ) {
|
||||
result.tread = std::max( result.tread, static_cast<double>( profile[ i ].position.x ) );
|
||||
}
|
||||
}
|
||||
result.ledge = 1e9;
|
||||
for( auto const i : lips ) {
|
||||
if( profile[ i ].position.y > result.liptop - 0.0005 ) {
|
||||
result.ledge = std::min( result.ledge, static_cast<double>( profile[ i ].position.x ) );
|
||||
}
|
||||
}
|
||||
result.rim = 1e9;
|
||||
result.crown = -1e9;
|
||||
auto const reach = [&]( double const X ) {
|
||||
result.rim = std::min( result.rim, X );
|
||||
result.crown = std::max( result.crown, X ); };
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > groove + 1e-4 ) {
|
||||
reach( point.x );
|
||||
}
|
||||
if( i + 1 < count ) {
|
||||
auto const &next { profile[ i + 1 ].position };
|
||||
if( ( point.y - groove ) * ( next.y - groove ) < 0.0 ) {
|
||||
reach( point.x + ( next.x - point.x ) * ( groove - point.y ) / ( next.y - point.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return track_rails::measure_rail( track_rail_profile( m_profile1.second ) );
|
||||
}
|
||||
|
||||
float
|
||||
|
||||
Reference in New Issue
Block a user