| 428 | using MtlLibrary = HashMap<std::string, MtlMaterial>; |
| 429 | |
| 430 | Expected<MtlLibrary> loadMtlLibrary( const std::filesystem::path& path ) |
| 431 | { |
| 432 | std::ifstream mtlIn( path, std::ios::binary ); |
| 433 | if ( !mtlIn.is_open() ) |
| 434 | return unexpected( "unable to open MTL file" ); |
| 435 | |
| 436 | const auto mtlContent = readCharBuffer( mtlIn ); |
| 437 | if ( !mtlContent ) |
| 438 | return unexpected( "Unable to open MTL file: " + mtlContent.error() ); |
| 439 | auto data = mtlContent->data(); |
| 440 | auto mtlSize = mtlContent->size(); |
| 441 | if ( hasBom( data ) ) |
| 442 | { |
| 443 | data += 3; |
| 444 | mtlSize -= 3; |
| 445 | } |
| 446 | |
| 447 | if ( mtlSize == 0 ) |
| 448 | return unexpected( "empty MTL file" ); |
| 449 | |
| 450 | const auto newlines = splitByLines( data, mtlSize ); |
| 451 | |
| 452 | const auto groups = groupLines<MtlElement>( data, mtlSize, newlines ); |
| 453 | |
| 454 | MtlLibrary result; |
| 455 | std::string currentMaterialName; |
| 456 | MtlMaterial currentMaterial; |
| 457 | |
| 458 | for ( const auto& group : groups ) |
| 459 | { |
| 460 | std::string parseError; |
| 461 | switch ( group.element ) |
| 462 | { |
| 463 | case MtlElement::Unknown: |
| 464 | break; |
| 465 | case MtlElement::MaterialName: |
| 466 | { |
| 467 | const auto li = group.end - 1; |
| 468 | std::string_view line( data + newlines[li], newlines[li + 1] - newlines[li + 0] ); |
| 469 | |
| 470 | if ( !currentMaterialName.empty() ) |
| 471 | { |
| 472 | result.emplace( std::move( currentMaterialName ), std::move( currentMaterial ) ); |
| 473 | currentMaterial = {}; |
| 474 | } |
| 475 | currentMaterialName = line.substr( 6, std::string_view::npos ); |
| 476 | boost::trim( currentMaterialName ); |
| 477 | } |
| 478 | break; |
| 479 | case MtlElement::DiffuseColor: |
| 480 | { |
| 481 | const auto li = group.end - 1; |
| 482 | std::string_view line( data + newlines[li], newlines[li + 1] - newlines[li + 0] ); |
| 483 | |
| 484 | auto res = parseMtlColor( line, currentMaterial.diffuseColor ); |
| 485 | if ( !res.has_value() ) |
| 486 | parseError = std::move( res.error() ); |
| 487 | } |
no test coverage detected