Assign points to spatial blocks and reconstruct each block independently.
| 706 | |
| 707 | // Assign points to spatial blocks and reconstruct each block independently. |
| 708 | colmap::PlyMesh ReconstructBlocks( |
| 709 | const std::vector<colmap::PlyPoint>& points, |
| 710 | const VisibilityData& vis_data, |
| 711 | const colmap::mvs::AdvancingFrontMeshingOptions& options) { |
| 712 | const auto grid = |
| 713 | ComputeBlockGrid(points, options.block_size, options.block_overlap); |
| 714 | |
| 715 | LOG(INFO) << "Block-wise processing: " << grid.nx << "x" << grid.ny << "x" |
| 716 | << grid.nz << " = " << grid.NumBlocks() |
| 717 | << " blocks (size=" << grid.block_size |
| 718 | << ", overlap=" << grid.overlap << ")."; |
| 719 | |
| 720 | const auto block_point_indices = AssignPointsToBlocks(points, grid); |
| 721 | |
| 722 | // Build all visibility rays and pre-assign to blocks by AABB intersection. |
| 723 | const bool use_vis = |
| 724 | options.visibility_filtering && !vis_data.cam_positions.empty(); |
| 725 | std::vector<K::Segment_3> all_rays; |
| 726 | std::vector<std::vector<size_t>> block_ray_indices(grid.NumBlocks()); |
| 727 | |
| 728 | if (use_vis) { |
| 729 | all_rays = BuildVisibilityRays(points, |
| 730 | vis_data.cam_positions, |
| 731 | vis_data.point_visibility, |
| 732 | {}, |
| 733 | options.visibility_ray_trim_offset); |
| 734 | LOG(INFO) << "Built " << all_rays.size() |
| 735 | << " visibility rays. Assigning to blocks..."; |
| 736 | block_ray_indices = AssignRaysToBlocks(all_rays, block_point_indices, grid); |
| 737 | } |
| 738 | |
| 739 | colmap::PlyMesh merged_mesh; |
| 740 | std::mutex merge_mutex; |
| 741 | std::atomic<int> blocks_completed{0}; |
| 742 | int num_active_blocks = 0; |
| 743 | for (int i = 0; i < grid.NumBlocks(); ++i) { |
| 744 | if (!block_point_indices[i].empty()) { |
| 745 | ++num_active_blocks; |
| 746 | } |
| 747 | } |
| 748 | |
| 749 | const int num_threads = colmap::GetEffectiveNumThreads(options.num_threads); |
| 750 | colmap::ThreadPool thread_pool(num_threads); |
| 751 | |
| 752 | for (int block_idx = 0; block_idx < grid.NumBlocks(); ++block_idx) { |
| 753 | if (block_point_indices[block_idx].empty()) { |
| 754 | continue; |
| 755 | } |
| 756 | |
| 757 | thread_pool.AddTask([&, block_idx]() { |
| 758 | // Disable OMP parallelism within each block task to avoid |
| 759 | // oversubscription since ThreadPool handles inter-block parallelism. |
| 760 | omp_set_num_threads(1); |
| 761 | #ifdef _MSC_VER |
| 762 | omp_set_nested(0); |
| 763 | #else |
| 764 | omp_set_max_active_levels(1); |
| 765 | #endif |
no test coverage detected