mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-08 17:26:22 +01:00
feat(track): track unevenness declared in the track entry
Usage, optional attributes of a track entry, before endtrack:
uneven <mm> peak deviation of a rail on a 10 m chord, 0-100; normal and switch
unevenup <mm> up and down alone, instead of uneven; normal and switch
unevenside <mm> sideways alone, instead of uneven; normal and switch
unevencross <mm> cross level alone, instead of uneven; normal only
jointdip <mm> depth of the dip at rail joints, every sound distance; normal only,
default 0.4 of the up and down component
Values of uneven follow PLK Id-14 appendix 1: 6 mm is the limit at 160 km/h, 10 at 120,
18 at 80, 35 at 40; half of it for a track in a good state. Example:
uneven 18
unevencross 25
jointdip 6
endtrack
The same fields are in the editor, track panel, section Ride and sound. See
track_uneven_doc.md.
The unevenness is a displacement field over the plan of the scenery, with no random
numbers: one place strays the same every time, and joined tracks, the paths of a switch,
sleepermodel and axles at one place move together. Tracks meet at a joint at the lower of
their values. Joined switches take the lowest of theirs, the tracks joined to them come to
it, and a track with none of a component keeps the switch to its design in it. The clatter
comes from the dipping joints. Curve radius and grade for the physics stay as designed.
Tracks with it get geometry every 2 m on straights: 4x the vertices on Baltyk with all
tracks flagged, 0.2 ms more per frame on td.scn.
This commit is contained in:
@@ -118,6 +118,10 @@ bool TSegment::Init(glm::dvec3 &NewPoint1, glm::dvec3 NewCPointOut, glm::dvec3 N
|
||||
fStoop = std::atan2(Point2.y - Point1.y, fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
||||
|
||||
fStep = fNewStep;
|
||||
if( m_uneven && pOwner->eType != tt_Switch ) {
|
||||
// dense enough for the waves; a switch keeps its division, the blades depend on it
|
||||
fStep = std::min( fStep, 2.0 );
|
||||
}
|
||||
// NOTE: optionally replace this part with the commented version, after solving geometry issues with double switches
|
||||
if( pOwner->eType == tt_Switch
|
||||
&& fStep * (3.0 * Global.SplineFidelity) > fLength ) {
|
||||
@@ -366,6 +370,52 @@ Math3D::vector3 TSegment::GetPoint(double const fDistance) const
|
||||
*/
|
||||
|
||||
void TSegment::RaPositionGet(double const fDistance, glm::dvec3 &position, glm::vec3 &rotation) const {
|
||||
design_position( fDistance, position, rotation );
|
||||
if( false == m_uneven ) {
|
||||
return;
|
||||
}
|
||||
// direction and slope stay as designed: the physics takes the curve radius and the grade from them
|
||||
auto const gauge { std::max( std::abs( pOwner->fTrackWidth ), 0.1f ) };
|
||||
glm::dvec3 const across { -std::cos( rotation.z ), 0.0, -std::sin( rotation.z ) };
|
||||
auto const amount { pOwner->uneven_at( fDistance ) };
|
||||
rotation.x += static_cast<float>( track_uneven::stray_per_mm * (
|
||||
amount.up * track_uneven::roll( position, across, gauge )
|
||||
+ amount.cross * track_uneven::level( position ) / gauge ) );
|
||||
position += stray( position, fDistance );
|
||||
}
|
||||
|
||||
glm::dvec3 TSegment::stray( glm::dvec3 const &Point, double const Distance ) const {
|
||||
auto const amount { pOwner->uneven_at( Distance ) };
|
||||
auto const field { track_uneven::field( Point ) };
|
||||
glm::dvec3 result { field.x * amount.side, field.y * amount.up, field.z * amount.side };
|
||||
result *= track_uneven::stray_per_mm;
|
||||
result.y -= pOwner->joint_dip( Distance );
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::dvec3 TSegment::uneven_bend( double const Distance ) const {
|
||||
if( false == m_uneven ) {
|
||||
return glm::dvec3 { 0.0 };
|
||||
}
|
||||
// over about a bogie; FastGetTFromS extrapolates past the ends of the path
|
||||
auto const reach { 1.5 };
|
||||
auto const strayed = [&]( double const At ) {
|
||||
return stray( FastGetPoint( FastGetTFromS( At ) ), At ); };
|
||||
return ( strayed( Distance + reach ) - 2.0 * strayed( Distance ) + strayed( Distance - reach ) ) / ( reach * reach );
|
||||
}
|
||||
|
||||
void TSegment::settle_vertex( gfx::basic_vertex &Vertex, glm::dvec3 const &Origin, glm::vec3 const &Position, glm::vec3 const &Parallel, double const Distance ) const {
|
||||
if( false == m_uneven ) {
|
||||
return;
|
||||
}
|
||||
// the rails settling apart turn about the middle of the track, what's outside them follows the rail
|
||||
auto const gauge { std::max( std::abs( pOwner->fTrackWidth ), 0.1f ) };
|
||||
auto const across { std::clamp( glm::dot( Vertex.position - Position, Parallel ), -0.5f * gauge, 0.5f * gauge ) };
|
||||
Vertex.position.y -= static_cast<float>( track_uneven::stray_per_mm * pOwner->uneven_at( Distance ).cross * track_uneven::level( Origin + glm::dvec3 { Position } ) * across / gauge );
|
||||
Vertex.position += glm::vec3 { stray( Origin + glm::dvec3 { Vertex.position }, Distance ) };
|
||||
}
|
||||
|
||||
void TSegment::design_position(double const fDistance, glm::dvec3 &position, glm::vec3 &rotation) const {
|
||||
if (bCurve) {
|
||||
// można by wprowadzić uproszczony wzór dla okręgów płaskich
|
||||
auto const t = FastGetTFromS(fDistance); // aproksymacja dystansu na krzywej Beziera na parametr (t)
|
||||
@@ -500,6 +550,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ( jmm1 * ShapePoints[ j ].texture.x + m1 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv1 } );
|
||||
settle_vertex( Output.back(), Origin, pos1, parallel1, s - step );
|
||||
}
|
||||
// jeśli jest wskaźnik do tablicy
|
||||
if (p && *p && !j) // to dla pierwszego punktu
|
||||
@@ -518,6 +569,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ( jmm2 * ShapePoints[ j ].texture.x + m2 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv2 } );
|
||||
settle_vertex( Output.back(), Origin, pos2, parallel2, s );
|
||||
}
|
||||
// jeśli jest wskaźnik do tablicy
|
||||
// to dla pierwszego punktu
|
||||
@@ -540,6 +592,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv1 } );
|
||||
settle_vertex( Output.back(), Origin, pos1, parallel1, s - step );
|
||||
|
||||
pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].position.x - fOffsetX.first ) + m2 * ( ShapePoints[ j ].position.x - fOffsetX.second ) ) + pos2;
|
||||
pt.y += ShapePoints[ j ].position.y;
|
||||
@@ -550,6 +603,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv2 } );
|
||||
settle_vertex( Output.back(), Origin, pos2, parallel2, s );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user