| 633 | } |
| 634 | |
| 635 | static Expected<Mesh> fromPly( std::istream& in, const MeshLoadSettings& settings, const std::filesystem::path& dir ) |
| 636 | { |
| 637 | MR_TIMER; |
| 638 | |
| 639 | std::optional<Triangulation> tris; |
| 640 | TriCornerUVCoords triCornerUvCoords; |
| 641 | PlyLoadParams params = |
| 642 | { |
| 643 | .tris = &tris, |
| 644 | .edges = settings.edges, |
| 645 | .colors = settings.colors, |
| 646 | .faceColors = settings.faceColors, |
| 647 | .uvCoords = settings.uvCoords, |
| 648 | .triCornerUvCoords = ( settings.texture && settings.colors ) ? &triCornerUvCoords : nullptr, |
| 649 | .normals = settings.normals, |
| 650 | .texture = settings.texture, |
| 651 | .dir = dir, |
| 652 | // suppose that reading is 10% of progress and building mesh is 90% of progress |
| 653 | .callback = subprogress( settings.callback, 0.0f, 0.1f ), |
| 654 | .telemetrySignal = settings.telemetrySignal |
| 655 | }; |
| 656 | auto maybePoints = loadPly( in, params ); |
| 657 | if ( !maybePoints ) |
| 658 | return unexpected( std::move( maybePoints.error() ) ); |
| 659 | |
| 660 | Mesh res; |
| 661 | res.points = std::move( *maybePoints ); |
| 662 | |
| 663 | if ( tris ) |
| 664 | { |
| 665 | int mySkippedFaceCount = 0; |
| 666 | res.topology = MeshBuilder::fromTriangles( *tris, |
| 667 | { .skippedFaceCount = settings.skippedFaceCount ? &mySkippedFaceCount : nullptr }, |
| 668 | subprogress( settings.callback, 0.9f, 1.0f ) ); |
| 669 | if ( res.topology.lastValidVert() + 1 > res.points.size() ) |
| 670 | return unexpected( "vertex id is larger than total point coordinates" ); |
| 671 | if ( settings.skippedFaceCount ) |
| 672 | *settings.skippedFaceCount += mySkippedFaceCount; |
| 673 | } |
| 674 | |
| 675 | // try converting per-corner UVs into per-vertex UVs |
| 676 | if ( settings.uvCoords && tris && !tris->empty() && !triCornerUvCoords.empty() ) |
| 677 | { |
| 678 | if ( auto vertUVs = findVertexUVs( res.topology, triCornerUvCoords ) ) |
| 679 | { |
| 680 | *settings.uvCoords = std::move( *vertUVs ); |
| 681 | triCornerUvCoords.clear(); // not to sample colors from UVs below |
| 682 | } |
| 683 | } |
| 684 | // convert per-corner UVs into per-vertex colors by averaging the value |
| 685 | if ( settings.texture && !settings.texture->pixels.empty() && settings.colors && tris && !tris->empty() && !triCornerUvCoords.empty() ) |
| 686 | { |
| 687 | *settings.colors = sampleVertexColors( res, *settings.texture, triCornerUvCoords ); |
| 688 | if ( !settings.uvCoords || settings.uvCoords->empty() ) |
| 689 | *settings.texture = {}; // texture will not be used outside of this function |
| 690 | } |
| 691 | |
| 692 | if ( !reportProgress( settings.callback, 1.0f ) ) |
no test coverage detected