| 270 | #endif // COLMAP_CGAL_ENABLED |
| 271 | |
| 272 | std::vector<int> SelectViews(const PlyMesh& mesh, |
| 273 | const std::vector<Eigen::Vector3f>& face_normals, |
| 274 | const std::vector<Image>& images, |
| 275 | const FaceAdjacencyMap& adjacency, |
| 276 | const MeshTextureMappingOptions& options) { |
| 277 | const size_t num_faces = mesh.faces.size(); |
| 278 | const size_t num_images = images.size(); |
| 279 | |
| 280 | if (num_faces == 0 || num_images == 0) { |
| 281 | return std::vector<int>(num_faces, -1); |
| 282 | } |
| 283 | |
| 284 | #if defined(COLMAP_CGAL_ENABLED) |
| 285 | OcclusionTester occlusion_tester; |
| 286 | occlusion_tester.Build(mesh); |
| 287 | #endif |
| 288 | |
| 289 | // Flat score buffer: scores[fi * num_images + ii]. |
| 290 | std::vector<double> scores(num_faces * num_images, -1.0); |
| 291 | |
| 292 | #ifdef _OPENMP |
| 293 | [[maybe_unused]] const int num_threads = |
| 294 | options.num_threads > 0 |
| 295 | ? options.num_threads |
| 296 | : std::max(1, static_cast<int>(omp_get_max_threads())); |
| 297 | #pragma omp parallel for schedule(dynamic) num_threads(num_threads) |
| 298 | #endif |
| 299 | for (int64_t fi = 0; fi < static_cast<int64_t>(num_faces); ++fi) { |
| 300 | const Eigen::Vector3f& normal = face_normals[fi]; |
| 301 | if (normal.squaredNorm() < 1e-10f) continue; |
| 302 | |
| 303 | const std::array<size_t, 3> idx = GetFaceIndices(mesh.faces[fi]); |
| 304 | const Eigen::Vector3f v0 = GetVertex(mesh, idx[0]); |
| 305 | const Eigen::Vector3f v1 = GetVertex(mesh, idx[1]); |
| 306 | const Eigen::Vector3f v2 = GetVertex(mesh, idx[2]); |
| 307 | const Eigen::Vector3f centroid = (v0 + v1 + v2) / 3.0f; |
| 308 | const std::array<Eigen::Vector3f, 3> verts = {v0, v1, v2}; |
| 309 | |
| 310 | for (size_t ii = 0; ii < num_images; ++ii) { |
| 311 | const Image& img = images[ii]; |
| 312 | const Eigen::Vector3f cam_center = |
| 313 | ComputeCameraCenter(img.GetR(), img.GetT()); |
| 314 | |
| 315 | const Eigen::Vector3f view_dir = (cam_center - centroid).normalized(); |
| 316 | const float cos_angle = normal.dot(view_dir); |
| 317 | if (cos_angle < static_cast<float>(options.min_cos_normal_angle)) { |
| 318 | continue; |
| 319 | } |
| 320 | |
| 321 | int visible_count = 0; |
| 322 | std::array<Eigen::Vector2f, 3> proj; |
| 323 | bool behind_camera = false; |
| 324 | for (int vi = 0; vi < 3; ++vi) { |
| 325 | const float depth = ProjectPointDepth(img.GetP(), verts[vi]); |
| 326 | if (depth <= 0) { |
| 327 | behind_camera = true; |
| 328 | break; |
| 329 | } |
no test coverage detected