mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-02 12:49:13 +01:00
refactor(track): the cap of a lofted rail end takes its texture from cap_texture and its triangles from ear_clip instead of computing both inside cap_loft
This commit is contained in:
@@ -14,7 +14,90 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
namespace track_rails {
|
namespace track_rails {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// in the colour of the top of the rail foot
|
// in the colour of the top of the rail foot
|
||||||
|
glm::vec2 cap_texture( std::vector<gfx::basic_vertex> const &Ring, std::vector<glm::dvec2> const &Plan ) {
|
||||||
|
|
||||||
|
auto bottom { 0.0 }, top { 0.0 };
|
||||||
|
for( auto const &point : Plan ) {
|
||||||
|
bottom = std::min( bottom, point.y );
|
||||||
|
top = std::max( top, point.y );
|
||||||
|
}
|
||||||
|
auto web { Ring[ 0 ].texture };
|
||||||
|
auto nearest { std::numeric_limits<double>::max() };
|
||||||
|
for( std::size_t j = 0; j < Ring.size() / 2; ++j ) {
|
||||||
|
auto const distance { std::abs( Plan[ j ].y - 0.5 * ( bottom + top ) ) };
|
||||||
|
if( distance < nearest ) {
|
||||||
|
nearest = distance;
|
||||||
|
web = Ring[ j ].texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto lowest { std::numeric_limits<double>::max() };
|
||||||
|
for( std::size_t j = 0; j < Ring.size() / 2; ++j ) {
|
||||||
|
if( Ring[ j ].normal.y > 0.5f && Plan[ j ].y < lowest ) {
|
||||||
|
lowest = Plan[ j ].y;
|
||||||
|
web = Ring[ j ].texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return web;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::array<std::size_t, 3>> ear_clip( std::vector<glm::dvec2> const &Polygon ) {
|
||||||
|
|
||||||
|
auto const cross = []( glm::dvec2 const &A, glm::dvec2 const &B, glm::dvec2 const &C ) {
|
||||||
|
return ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ); };
|
||||||
|
double area { 0.0 };
|
||||||
|
for( std::size_t j = 0; j < Polygon.size(); ++j ) {
|
||||||
|
auto const &a { Polygon[ j ] };
|
||||||
|
auto const &b { Polygon[ ( j + 1 ) % Polygon.size() ] };
|
||||||
|
area += a.x * b.y - b.x * a.y;
|
||||||
|
}
|
||||||
|
auto const orientation { area < 0.0 ? -1.0 : 1.0 };
|
||||||
|
std::vector<std::size_t> left( Polygon.size() );
|
||||||
|
for( std::size_t j = 0; j < Polygon.size(); ++j ) {
|
||||||
|
left[ j ] = j;
|
||||||
|
}
|
||||||
|
std::vector<std::array<std::size_t, 3>> triangles;
|
||||||
|
while( left.size() > 3 ) {
|
||||||
|
auto ear { left.size() };
|
||||||
|
for( std::size_t j = 0; j < left.size() && ear == left.size(); ++j ) {
|
||||||
|
auto const &a { Polygon[ left[ ( j + left.size() - 1 ) % left.size() ] ] };
|
||||||
|
auto const &b { Polygon[ left[ j ] ] };
|
||||||
|
auto const &c { Polygon[ left[ ( j + 1 ) % left.size() ] ] };
|
||||||
|
auto const turn { cross( a, b, c ) * orientation };
|
||||||
|
if( turn < -1e-12 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto inside { false };
|
||||||
|
if( turn > 1e-12 ) {
|
||||||
|
for( auto const k : left ) {
|
||||||
|
auto const &p { Polygon[ k ] };
|
||||||
|
if( p == a || p == b || p == c ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( cross( a, b, p ) * orientation > 1e-12 && cross( b, c, p ) * orientation > 1e-12 && cross( c, a, p ) * orientation > 1e-12 ) {
|
||||||
|
inside = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( false == inside ) {
|
||||||
|
ear = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ear == left.size() ) {
|
||||||
|
ear = 0;
|
||||||
|
}
|
||||||
|
triangles.push_back( { left[ ( ear + left.size() - 1 ) % left.size() ], left[ ear ], left[ ( ear + 1 ) % left.size() ] } );
|
||||||
|
left.erase( left.begin() + ear );
|
||||||
|
}
|
||||||
|
triangles.push_back( { left[ 0 ], left[ 1 ], left[ 2 ] } );
|
||||||
|
return triangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void cap_loft( gfx::vertex_array const &Strip, std::size_t const Ring, bool const Start, bool const End, gfx::vertex_array &Triangles ) {
|
void cap_loft( gfx::vertex_array const &Strip, std::size_t const Ring, bool const Start, bool const End, gfx::vertex_array &Triangles ) {
|
||||||
|
|
||||||
if( Ring < 3 || Strip.size() < 2 * Ring ) {
|
if( Ring < 3 || Strip.size() < 2 * Ring ) {
|
||||||
@@ -48,77 +131,12 @@ void cap_loft( gfx::vertex_array const &Strip, std::size_t const Ring, bool cons
|
|||||||
}
|
}
|
||||||
across = glm::normalize( across );
|
across = glm::normalize( across );
|
||||||
std::vector<glm::dvec2> plan;
|
std::vector<glm::dvec2> plan;
|
||||||
auto bottom { 0.0 }, top { 0.0 };
|
|
||||||
for( auto const &vertex : ring ) {
|
for( auto const &vertex : ring ) {
|
||||||
auto const offset { vertex.position - ring[ 0 ].position };
|
auto const offset { vertex.position - ring[ 0 ].position };
|
||||||
plan.emplace_back( glm::dot( offset, across ), offset.y );
|
plan.emplace_back( glm::dot( offset, across ), offset.y );
|
||||||
bottom = std::min<double>( bottom, offset.y );
|
|
||||||
top = std::max<double>( top, offset.y );
|
|
||||||
}
|
}
|
||||||
auto web { ring[ 0 ].texture };
|
auto const web { cap_texture( ring, plan ) };
|
||||||
auto nearest { std::numeric_limits<double>::max() };
|
auto const triangles { ear_clip( plan ) };
|
||||||
for( std::size_t j = 0; j < Ring / 2; ++j ) {
|
|
||||||
auto const distance { std::abs( plan[ j ].y - 0.5 * ( bottom + top ) ) };
|
|
||||||
if( distance < nearest ) {
|
|
||||||
nearest = distance;
|
|
||||||
web = ring[ j ].texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto lowest { std::numeric_limits<double>::max() };
|
|
||||||
for( std::size_t j = 0; j < Ring / 2; ++j ) {
|
|
||||||
if( ring[ j ].normal.y > 0.5f && plan[ j ].y < lowest ) {
|
|
||||||
lowest = plan[ j ].y;
|
|
||||||
web = ring[ j ].texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto const cross = []( glm::dvec2 const &A, glm::dvec2 const &B, glm::dvec2 const &C ) {
|
|
||||||
return ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ); };
|
|
||||||
double area { 0.0 };
|
|
||||||
for( std::size_t j = 0; j < plan.size(); ++j ) {
|
|
||||||
auto const &a { plan[ j ] };
|
|
||||||
auto const &b { plan[ ( j + 1 ) % plan.size() ] };
|
|
||||||
area += a.x * b.y - b.x * a.y;
|
|
||||||
}
|
|
||||||
auto const orientation { area < 0.0 ? -1.0 : 1.0 };
|
|
||||||
std::vector<std::size_t> left( Ring );
|
|
||||||
for( std::size_t j = 0; j < Ring; ++j ) {
|
|
||||||
left[ j ] = j;
|
|
||||||
}
|
|
||||||
std::vector<std::array<std::size_t, 3>> triangles;
|
|
||||||
while( left.size() > 3 ) {
|
|
||||||
auto ear { left.size() };
|
|
||||||
for( std::size_t j = 0; j < left.size() && ear == left.size(); ++j ) {
|
|
||||||
auto const &a { plan[ left[ ( j + left.size() - 1 ) % left.size() ] ] };
|
|
||||||
auto const &b { plan[ left[ j ] ] };
|
|
||||||
auto const &c { plan[ left[ ( j + 1 ) % left.size() ] ] };
|
|
||||||
auto const turn { cross( a, b, c ) * orientation };
|
|
||||||
if( turn < -1e-12 ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto inside { false };
|
|
||||||
if( turn > 1e-12 ) {
|
|
||||||
for( auto const k : left ) {
|
|
||||||
auto const &p { plan[ k ] };
|
|
||||||
if( p == a || p == b || p == c ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( cross( a, b, p ) * orientation > 1e-12 && cross( b, c, p ) * orientation > 1e-12 && cross( c, a, p ) * orientation > 1e-12 ) {
|
|
||||||
inside = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( false == inside ) {
|
|
||||||
ear = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( ear == left.size() ) {
|
|
||||||
ear = 0;
|
|
||||||
}
|
|
||||||
triangles.push_back( { left[ ( ear + left.size() - 1 ) % left.size() ], left[ ear ], left[ ( ear + 1 ) % left.size() ] } );
|
|
||||||
left.erase( left.begin() + ear );
|
|
||||||
}
|
|
||||||
triangles.push_back( { left[ 0 ], left[ 1 ], left[ 2 ] } );
|
|
||||||
for( auto const &triangle : triangles ) {
|
for( auto const &triangle : triangles ) {
|
||||||
for( auto const &order : { std::array<int, 3>{ 0, 1, 2 }, std::array<int, 3>{ 0, 2, 1 } } ) {
|
for( auto const &order : { std::array<int, 3>{ 0, 1, 2 }, std::array<int, 3>{ 0, 2, 1 } } ) {
|
||||||
for( auto const k : order ) {
|
for( auto const k : order ) {
|
||||||
|
|||||||
Reference in New Issue
Block a user