finds if given mesh has enough sharp edges (>25 degrees) to recommend flat shading
| 37 | |
| 38 | /// finds if given mesh has enough sharp edges (>25 degrees) to recommend flat shading |
| 39 | bool detectFlatShading( const Mesh& mesh ) |
| 40 | { |
| 41 | MR_TIMER; |
| 42 | |
| 43 | constexpr float sharpAngle = 25 * PI_F / 180; // Critical angle from planar, degrees |
| 44 | const float sharpAngleCos = std::cos( sharpAngle ); |
| 45 | |
| 46 | struct Data |
| 47 | { |
| 48 | double sumDblArea = 0; |
| 49 | double sumSharpDblArea = 0; |
| 50 | Data operator + ( const Data & b ) const |
| 51 | { |
| 52 | return { sumDblArea + b.sumDblArea, sumSharpDblArea + b.sumSharpDblArea }; |
| 53 | } |
| 54 | }; |
| 55 | |
| 56 | auto total = parallel_deterministic_reduce( |
| 57 | tbb::blocked_range( 0_ue, UndirectedEdgeId{ mesh.topology.undirectedEdgeSize() } ), |
| 58 | Data(), |
| 59 | [&mesh, sharpAngleCos] ( const auto& range, Data current ) |
| 60 | { |
| 61 | for ( UndirectedEdgeId ue = range.begin(); ue < range.end(); ++ue ) |
| 62 | { |
| 63 | const EdgeId e = ue; |
| 64 | const auto l = mesh.topology.left( e ); |
| 65 | const auto r = mesh.topology.right( e ); |
| 66 | if ( !l || !r ) |
| 67 | continue; |
| 68 | const auto da = mesh.dblArea( l ) + mesh.dblArea( r ); |
| 69 | current.sumDblArea += da; |
| 70 | auto dihedralCos = mesh.dihedralAngleCos( ue ); |
| 71 | if ( dihedralCos <= sharpAngleCos ) |
| 72 | current.sumSharpDblArea += da; |
| 73 | } |
| 74 | return current; |
| 75 | }, |
| 76 | std::plus<Data>() ); |
| 77 | |
| 78 | // triangles' area near sharp edges is more than 5% of total area |
| 79 | return total.sumSharpDblArea > 0.05 * total.sumDblArea; |
| 80 | } |
| 81 | |
| 82 | // Prepare object after it has been imported from external format (not .mru) |
| 83 | void postImportObject( const std::shared_ptr<Object> &o, const std::filesystem::path &filename ) |
no test coverage detected