| 506 | } |
| 507 | |
| 508 | AtlasLayout PackAtlas(const std::vector<RegionProjection>& projections, |
| 509 | const std::vector<FaceRegion>& regions, |
| 510 | const int padding) { |
| 511 | AtlasLayout layout; |
| 512 | |
| 513 | if (projections.empty()) { |
| 514 | return layout; |
| 515 | } |
| 516 | |
| 517 | struct RectEntry { |
| 518 | int width; |
| 519 | int height; |
| 520 | size_t region_idx; |
| 521 | }; |
| 522 | std::vector<RectEntry> rects(projections.size()); |
| 523 | int64_t total_area = 0; |
| 524 | int max_rect_width = 0; |
| 525 | |
| 526 | for (size_t i = 0; i < projections.size(); ++i) { |
| 527 | rects[i].width = projections[i].bbox_width + 2 * padding; |
| 528 | rects[i].height = projections[i].bbox_height + 2 * padding; |
| 529 | rects[i].region_idx = i; |
| 530 | total_area += static_cast<int64_t>(rects[i].width) * rects[i].height; |
| 531 | max_rect_width = std::max(max_rect_width, rects[i].width); |
| 532 | } |
| 533 | |
| 534 | std::sort( |
| 535 | rects.begin(), rects.end(), [](const RectEntry& a, const RectEntry& b) { |
| 536 | return a.height > b.height; |
| 537 | }); |
| 538 | |
| 539 | const int atlas_side = std::max( |
| 540 | static_cast<int>(std::ceil(std::sqrt(total_area * 1.3))), max_rect_width); |
| 541 | int atlas_width = 1; |
| 542 | while (atlas_width < atlas_side) atlas_width *= 2; |
| 543 | int atlas_height = atlas_width; |
| 544 | |
| 545 | // Shelf packing. |
| 546 | const auto TryPack = [&](const int aw, |
| 547 | const int ah, |
| 548 | std::vector<PackRect>& placements_out) -> bool { |
| 549 | placements_out.resize(rects.size()); |
| 550 | int shelf_x = 0; |
| 551 | int shelf_y = 0; |
| 552 | int shelf_height = 0; |
| 553 | |
| 554 | for (size_t i = 0; i < rects.size(); ++i) { |
| 555 | if (shelf_x + rects[i].width > aw) { |
| 556 | shelf_y += shelf_height; |
| 557 | shelf_x = 0; |
| 558 | shelf_height = 0; |
| 559 | } |
| 560 | if (shelf_y + rects[i].height > ah) { |
| 561 | return false; |
| 562 | } |
| 563 | placements_out[i].x = shelf_x + padding; |
| 564 | placements_out[i].y = shelf_y + padding; |
| 565 | placements_out[i].width = projections[rects[i].region_idx].bbox_width; |
no test coverage detected