diff --git a/CMakeLists.txt b/CMakeLists.txt index 945269d08..fe7e932c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,9 +200,6 @@ target_link_libraries(ipc_toolkit PRIVATE tight_inclusion::tight_inclusion) include(scalable_ccd) target_link_libraries(ipc_toolkit PRIVATE scalable_ccd::scalable_ccd) -# SimpleBVH -include(simple_bvh) -target_link_libraries(ipc_toolkit PRIVATE simple_bvh::simple_bvh) # Logger include(spdlog) diff --git a/cmake/recipes/simple_bvh.cmake b/cmake/recipes/simple_bvh.cmake deleted file mode 100644 index c86439352..000000000 --- a/cmake/recipes/simple_bvh.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# BVH (https://github.com/geometryprocessing/SimpleBVH) -# License: MIT - -if(TARGET simple_bvh::simple_bvh) - return() -endif() - -message(STATUS "Third-party: creating target 'simple_bvh::simple_bvh'") - -include(CPM) -CPMAddPackage("gh:geometryprocessing/SimpleBVH#e1a931337a9e07e8bd2d2e8bbdfd7e54bc850df5") - -# Folder name for IDE -set_target_properties(simple_bvh PROPERTIES FOLDER "ThirdParty") \ No newline at end of file diff --git a/docs/source/_static/graphviz/dependencies.dot b/docs/source/_static/graphviz/dependencies.dot index 60c06a42c..a2ae83709 100644 --- a/docs/source/_static/graphviz/dependencies.dot +++ b/docs/source/_static/graphviz/dependencies.dot @@ -63,11 +63,6 @@ digraph "IPC Toolkit Dependencies" { // scalable_ccd -> tbb "node5" -> "node7" [color = "#BE6562";]; // ipc_toolkit -> scalable_ccd - "node10" [label = "simple_bvh\n(simple_bvh::simple_bvh)";shape = box;style = "rounded,filled";fillcolor = "#D5E8D4";color = "#8FB976";]; - "node10" -> "node0" [color = "#8FB976";]; - // simple_bvh -> Eigen3_Eigen - "node5" -> "node10" [color = "#BE6562";]; - // ipc_toolkit -> simple_bvh "node5" -> "node8" [color = "#8FB976";]; // ipc_toolkit -> spdlog "node5" -> "node9" [color = "#BE6562";]; diff --git a/docs/source/_static/graphviz/dependencies.svg b/docs/source/_static/graphviz/dependencies.svg index ecdbe6fe2..0802bd436 100644 --- a/docs/source/_static/graphviz/dependencies.svg +++ b/docs/source/_static/graphviz/dependencies.svg @@ -1,318 +1,299 @@ - - + IPC Toolkit Dependencies clusterLegend -Legend +Legend legendNode0 -Static Library +Static Library legendNode1 -Shared Library +Shared Library legendNode0->legendNode1 -Public +Public legendNode2 -Interface Library +Interface Library legendNode1->legendNode2 -Private +Private legendNode2->legendNode0 -Interface +Interface node5 - -ipc_toolkit -(ipc::toolkit) + +ipc_toolkit +(ipc::toolkit) node0 - -Eigen3_Eigen -(Eigen3::Eigen) + +Eigen3_Eigen +(Eigen3::Eigen) node5->node0 - - + + node1 - -filib -(filib::filib) + +filib +(filib::filib) node5->node1 - - + + node2 - -igl_core -(igl::core) + +igl_core +(igl::core) node5->node2 - - + + node3 - -igl_predicates -(igl::predicates) + +igl_predicates +(igl::predicates) node5->node3 - - + + node15 - -xsimd -(xsimd::xsimd) + +xsimd +(xsimd::xsimd) node5->node15 - - + + node6 - -robin_map -(tsl::robin_map) + +robin_map +(tsl::robin_map) node5->node6 - - + + node7 - -scalable_ccd -(scalable_ccd::scalable_ccd) + +scalable_ccd +(scalable_ccd::scalable_ccd) node5->node7 - - + + node8 - -spdlog -(spdlog::spdlog) + +spdlog +(spdlog::spdlog) - + node5->node8 - - + + node9 - -tbb -(TBB::tbb) + +tbb +(TBB::tbb) - -node5->node9 - - - - - -node10 - -simple_bvh -(simple_bvh::simple_bvh) - - -node5->node10 - - +node5->node9 + + - + node11 - -tight_inclusion -(tight_inclusion::tight_inclusion) + +tight_inclusion +(tight_inclusion::tight_inclusion) - + node5->node11 - - + + - + node12 - -absl_hash -(absl::hash) + +absl_hash +(absl::hash) - + node5->node12 - - + + - + node13 - -TinyAD -(TinyAD::TinyAD) + +TinyAD +(TinyAD::TinyAD) - + node5->node13 - - + + - + node14 - -nlohmann_json -(nlohmann_json::nlohmann_json) + +nlohmann_json +(nlohmann_json::nlohmann_json) - + node5->node14 - - + + node2->node0 - - + + node3->node2 - - + + node4 - -predicates -(predicates::predicates) + +predicates +(predicates::predicates) node3->node4 - - + + node7->node0 - - + + node7->node8 - - + + node7->node9 - - - - - -node10->node0 - - + + - + node11->node0 - - + + - + node11->node8 - - + + - + node13->node0 - - + + - + node13->node9 - - + + diff --git a/docs/source/about/dependencies.rst b/docs/source/about/dependencies.rst index 19327b8df..dce384b85 100644 --- a/docs/source/about/dependencies.rst +++ b/docs/source/about/dependencies.rst @@ -36,10 +36,6 @@ These dependencies are all `permissively licensed `_, and we list - Provably conservative CCD - MIT - `github.com/Continuous-Collision-Detection/Tight-Inclusion `_ - * - SimpleBVH - - Simple bounding volume hierarchy data structure - - MIT - - `github.com/geometryprocessing/SimpleBVH `_ * - Scalable-CCD - Scalable (GPU) CCD - Apache-2.0 diff --git a/docs/source/cpp-api/broad_phase.rst b/docs/source/cpp-api/broad_phase.rst index 766f08116..70c4f5278 100644 --- a/docs/source/cpp-api/broad_phase.rst +++ b/docs/source/cpp-api/broad_phase.rst @@ -25,12 +25,6 @@ Spatial Hash .. doxygenclass:: ipc::SpatialHash :allow-dot-graphs: -BVH ---- - -.. doxygenclass:: ipc::BVH - :allow-dot-graphs: - LBVH --- diff --git a/docs/source/python-api/broad_phase.rst b/docs/source/python-api/broad_phase.rst index 807387e2b..022a01668 100644 --- a/docs/source/python-api/broad_phase.rst +++ b/docs/source/python-api/broad_phase.rst @@ -29,13 +29,6 @@ Spatial Hash .. autoclasstoc:: -BVH ---- - -.. autoclass:: ipctk.BVH - - .. autoclasstoc:: - LBVH ---- diff --git a/docs/source/tutorials/getting_started.rst b/docs/source/tutorials/getting_started.rst index 90a41b8dd..e4af4538f 100644 --- a/docs/source/tutorials/getting_started.rst +++ b/docs/source/tutorials/getting_started.rst @@ -531,7 +531,7 @@ The ``Candidates`` class represents the culled set of candidate pairs and is bui candidates.build( mesh, vertices_t0, vertices_t1, broad_phase=ipctk.HashGrid()) -Possible values for ``broad_phase`` are: ``BruteForce`` (parallel brute force culling), ``HashGrid`` (default), ``SpatialHash`` (implementation from the original IPC codebase), ``BVH`` (`SimpleBVH `_), ``LBVH`` (CPU implementation of :cite:t:`Karras2012HPG` using TBB), ``SweepAndPrune`` (a.k.a. Sort-and-Sweep from :cite:t:`Baraff1992PhD`), or ``SweepAndTiniestQueue`` (method of :cite:t:`Belgrod2023Time`; requires CUDA). +Possible values for ``broad_phase`` are: ``BruteForce`` (parallel brute force culling), ``HashGrid`` (default), ``SpatialHash`` (implementation from the original IPC codebase), ``LBVH`` (CPU implementation of :cite:t:`Karras2012HPG` using TBB), ``SweepAndPrune`` (a.k.a. Sort-and-Sweep from :cite:t:`Baraff1992PhD`), or ``SweepAndTiniestQueue`` (method of :cite:t:`Belgrod2023Time`; requires CUDA). Narrow-Phase ^^^^^^^^^^^^ diff --git a/notebooks/ogc.py b/notebooks/ogc.py index ca2e37d90..9cb3d94f9 100644 --- a/notebooks/ogc.py +++ b/notebooks/ogc.py @@ -1,26 +1,22 @@ +import argparse import pathlib -from find_ipctk import ipctk -import polyscope as ps -from polyscope import imgui + import meshio import numpy as np - -import argparse +import polyscope as ps +from find_ipctk import ipctk +from polyscope import imgui parser = argparse.ArgumentParser() parser.add_argument( - "mesh", - type=pathlib.Path, - help="Path to the mesh file (e.g., .ply)" + "mesh", type=pathlib.Path, help="Path to the mesh file (e.g., .ply)" ) args = parser.parse_args() mesh = meshio.read(args.mesh) # Rotate 90 degrees around the x-axis -R = np.array([[1, 0, 0], - [0, 0, -1], - [0, 1, 0]]) +R = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]]) cmesh = ipctk.CollisionMesh( # mesh.points @ R.T, @@ -30,8 +26,12 @@ ) min_edge_length = np.min( - np.linalg.norm(cmesh.rest_positions[cmesh.edges[:, 0]] - - cmesh.rest_positions[cmesh.edges[:, 1]], axis=1)) + np.linalg.norm( + cmesh.rest_positions[cmesh.edges[:, 0]] + - cmesh.rest_positions[cmesh.edges[:, 1]], + axis=1, + ) +) max_dhat = 2e-1 dhat = 2e-3 # 0.5 * min_edge_length @@ -40,8 +40,7 @@ # Prebuild the candidates since dhat is the max it will ever be candidates = ipctk.Candidates() -candidates.build(cmesh, cmesh.rest_positions, - max_dhat, broad_phase=ipctk.BVH()) +candidates.build(cmesh, cmesh.rest_positions, max_dhat, broad_phase=ipctk.LBVH()) collisions = ipctk.NormalCollisions() @@ -50,13 +49,15 @@ def contact_force(): global collisions collisions.clear() collisions.collision_set_type = ( - ipctk.NormalCollisions.CollisionSetType.OGC if use_ogc else ipctk.NormalCollisions.CollisionSetType.IPC) + ipctk.NormalCollisions.CollisionSetType.OGC + if use_ogc + else ipctk.NormalCollisions.CollisionSetType.IPC + ) collisions.use_area_weighting = use_area_weighting collisions.build(candidates, cmesh, cmesh.rest_positions, dhat) B = ipctk.BarrierPotential(dhat) - f = -B.gradient(collisions, cmesh, - cmesh.rest_positions).reshape(-1, 3, order="C") + f = -B.gradient(collisions, cmesh, cmesh.rest_positions).reshape(-1, 3, order="C") f *= 1e5 return f @@ -107,7 +108,7 @@ def contact_force(): np.array([[0, 1], [2, 3]]), enabled=True, ) -ps_ee.set_radius(dhat/2, relative=False) +ps_ee.set_radius(dhat / 2, relative=False) ps_ee_closest_points = ps.register_point_cloud( "edge-edge-closest-points", cmesh.rest_positions[0:2], # Temporarily use first 2 vertices @@ -120,8 +121,9 @@ def callback(): changed0, dhat = imgui.SliderFloat("dhat", dhat, 1e-3, max_dhat, "%.5f") if changed0 and dhat > max_dhat: max_dhat = dhat - candidates.build(cmesh, cmesh.rest_positions, max_dhat, - broad_phase=ipctk.BVH()) + candidates.build( + cmesh, cmesh.rest_positions, max_dhat, broad_phase=ipctk.LBVH() + ) changed1, use_ogc = imgui.Checkbox("use_ogc", use_ogc) if changed0 or changed1: f = contact_force() @@ -129,34 +131,46 @@ def callback(): ps_mesh.add_vector_quantity("force_vector", f) imgui.Text( f"Number of collisions: {len(collisions.vv_collisions)} VV, {len(collisions.ev_collisions)} EV," - f" {len(collisions.ee_collisions)} EE, {len(collisions.fv_collisions)} FV") + f" {len(collisions.ee_collisions)} EE, {len(collisions.fv_collisions)} FV" + ) if len(collisions.ev_collisions) > 0: ev_i = min(ev_i, len(collisions.ev_collisions) - 1) - _, ev_i = imgui.SliderInt("Edge-Vertex Index", ev_i, - 0, len(collisions.ev_collisions) - 1) - ps_ev.update_node_positions(cmesh.rest_positions[ - collisions.ev_collisions[ev_i].vertex_ids(cmesh.edges, cmesh.faces)[:3]]) + _, ev_i = imgui.SliderInt( + "Edge-Vertex Index", ev_i, 0, len(collisions.ev_collisions) - 1 + ) + ps_ev.update_node_positions( + cmesh.rest_positions[ + collisions.ev_collisions[ev_i].vertex_ids(cmesh.edges, cmesh.faces)[:3] + ] + ) else: ps_ev.set_enabled(False) if len(collisions.ee_collisions) > 0: ee_i = min(ee_i, len(collisions.ee_collisions) - 1) - changed2, ee_i = imgui.SliderInt("Edge-Edge Index", ee_i, - 0, len(collisions.ee_collisions) - 1) + changed2, ee_i = imgui.SliderInt( + "Edge-Edge Index", ee_i, 0, len(collisions.ee_collisions) - 1 + ) coeffs = collisions.ee_collisions[ee_i].compute_coefficients( - cmesh.rest_positions, cmesh.edges, cmesh.faces) + cmesh.rest_positions, cmesh.edges, cmesh.faces + ) imgui.Text("Coeffs: {}".format(coeffs)) if changed0 or changed1 or changed2: V_ee = cmesh.rest_positions[ - collisions.ee_collisions[ee_i].vertex_ids(cmesh.edges, cmesh.faces)] + collisions.ee_collisions[ee_i].vertex_ids(cmesh.edges, cmesh.faces) + ] ps_ee.update_node_positions(V_ee) if changed0: - ps_ee.set_radius(dhat/2, relative=False) + ps_ee.set_radius(dhat / 2, relative=False) ps_ee_closest_points.update_point_positions( - np.vstack([ - coeffs[0] * V_ee[0] + coeffs[1] * V_ee[1], - -coeffs[2] * V_ee[2] - coeffs[3] * V_ee[3]])) + np.vstack( + [ + coeffs[0] * V_ee[0] + coeffs[1] * V_ee[1], + -coeffs[2] * V_ee[2] - coeffs[3] * V_ee[3], + ] + ) + ) else: ps_ee.set_enabled(False) ps_ee_closest_points.set_enabled(False) diff --git a/python/examples/profiler.py b/python/examples/profiler.py index 6d44b169b..5ac55683b 100644 --- a/python/examples/profiler.py +++ b/python/examples/profiler.py @@ -1,10 +1,11 @@ -import pandas as pd -import plotly.express as px import pathlib from io import StringIO +import pandas as pd +import plotly.express as px from find_ipctk import ipctk + def plot_profiler(title=None): df = pd.read_csv(StringIO(ipctk.profiler().csv), na_filter=False) # df["Time (s)"] = df["Time (ms)"] / 1000.0 @@ -41,22 +42,19 @@ def plot_profiler(title=None): fig.show() return fig + if __name__ == "__main__": - # plot(pathlib.Path(__file__).parent / "lbvh_profile.csv") + import argparse import meshio - import argparse import numpy as np parser = argparse.ArgumentParser() parser.add_argument( "--mesh", type=pathlib.Path, - default=(pathlib.Path(__file__).parents[2] / "tests/data/puffer-ball/20.ply")) - parser.add_argument( - "--method", - type=str, - default="lvbh") + default=(pathlib.Path(__file__).parents[2] / "tests/data/puffer-ball/20.ply"), + ) args = parser.parse_args() mesh = meshio.read(args.mesh) @@ -69,10 +67,7 @@ def plot_profiler(title=None): # indices = np.lexsort((faces[:, 2], faces[:, 1], faces[:, 0])) # faces = faces[indices] - if args.method.lower() == "bvh": - bp = ipctk.BVH() - elif args.method.lower() == "lbvh": - bp = ipctk.LBVH() + bp = ipctk.LBVH() bp.build(mesh.points, edges, faces) diff --git a/python/src/bindings.cpp b/python/src/bindings.cpp index 597b69656..0a31510ae 100644 --- a/python/src/bindings.cpp +++ b/python/src/bindings.cpp @@ -25,7 +25,6 @@ PYBIND11_MODULE(ipctk, m) define_aabb(m); define_broad_phase(m); define_brute_force(m); - define_bvh(m); define_hash_grid(m); define_lbvh(m); define_spatial_hash(m); diff --git a/python/src/broad_phase/CMakeLists.txt b/python/src/broad_phase/CMakeLists.txt index 71ac7f03c..dd0db17f2 100644 --- a/python/src/broad_phase/CMakeLists.txt +++ b/python/src/broad_phase/CMakeLists.txt @@ -2,7 +2,6 @@ set(SOURCES aabb.cpp broad_phase.cpp brute_force.cpp - bvh.cpp hash_grid.cpp lbvh.cpp spatial_hash.cpp @@ -11,4 +10,4 @@ set(SOURCES voxel_size_heuristic.cpp ) -target_sources(ipctk PRIVATE ${SOURCES}) \ No newline at end of file +target_sources(ipctk PRIVATE ${SOURCES}) diff --git a/python/src/broad_phase/bindings.hpp b/python/src/broad_phase/bindings.hpp index fccc9c315..13edeeeb5 100644 --- a/python/src/broad_phase/bindings.hpp +++ b/python/src/broad_phase/bindings.hpp @@ -5,7 +5,6 @@ void define_aabb(py::module_& m); void define_broad_phase(py::module_& m); void define_brute_force(py::module_& m); -void define_bvh(py::module_& m); void define_hash_grid(py::module_& m); void define_lbvh(py::module_& m); void define_spatial_hash(py::module_& m); diff --git a/python/src/broad_phase/bvh.cpp b/python/src/broad_phase/bvh.cpp deleted file mode 100644 index d2467f135..000000000 --- a/python/src/broad_phase/bvh.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include - -#include - -using namespace ipc; - -void define_bvh(py::module_& m) -{ - py::class_>(m, "BVH").def(py::init()); -} diff --git a/python/tests/utils.py b/python/tests/utils.py index d303dbfce..10d89fb8d 100644 --- a/python/tests/utils.py +++ b/python/tests/utils.py @@ -1,7 +1,7 @@ import pathlib -import numpy as np -import meshio +import meshio +import numpy as np from find_ipctk import ipctk @@ -12,28 +12,38 @@ def download_test_data_if_needed(directory): # Clone the test data repository print(f"Downloading test data to {directory}") import subprocess - subprocess.run([ - 'git', 'clone', 'https://github.com/ipc-sim/ipc-toolkit-tests-data', - str(directory) - ]) + + subprocess.run( + [ + "git", + "clone", + "https://github.com/ipc-sim/ipc-toolkit-tests-data", + str(directory), + ], + check=True, + ) def test_data_dir(): - _test_data_dir = pathlib.Path(__file__).parents[2] / 'tests' / 'data' + _test_data_dir = pathlib.Path(__file__).parents[2] / "tests" / "data" download_test_data_if_needed(_test_data_dir) return _test_data_dir def load_mesh(mesh_name): mesh = meshio.read(test_data_dir() / mesh_name) - return mesh.points, ipctk.edges(mesh.cells_dict['triangle']), mesh.cells_dict['triangle'] + return ( + mesh.points, + ipctk.edges(mesh.cells_dict["triangle"]), + mesh.cells_dict["triangle"], + ) def broad_phases(): yield ipctk.BruteForce() yield ipctk.HashGrid() yield ipctk.SpatialHash() - yield ipctk.BVH() + yield ipctk.LBVH() yield ipctk.SweepAndPrune() diff --git a/src/ipc/broad_phase/CMakeLists.txt b/src/ipc/broad_phase/CMakeLists.txt index c536957f5..e0613ebcf 100644 --- a/src/ipc/broad_phase/CMakeLists.txt +++ b/src/ipc/broad_phase/CMakeLists.txt @@ -5,8 +5,6 @@ set(SOURCES broad_phase.hpp brute_force.cpp brute_force.hpp - bvh.cpp - bvh.hpp create_broad_phase.cpp create_broad_phase.hpp default_broad_phase.hpp diff --git a/src/ipc/broad_phase/bvh.cpp b/src/ipc/broad_phase/bvh.cpp deleted file mode 100644 index 72cb552bf..000000000 --- a/src/ipc/broad_phase/bvh.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include "bvh.hpp" - -#include -#include - -#include -#include -#include -#include - -using namespace std::placeholders; - -namespace ipc { - -BVH::BVH() - : BroadPhase() - , vertex_bvh(std::make_unique()) - , edge_bvh(std::make_unique()) - , face_bvh(std::make_unique()) -{ -} - -BVH::~BVH() = default; - -void BVH::build( - Eigen::ConstRef edges, - Eigen::ConstRef faces) -{ - IPC_TOOLKIT_PROFILE_BLOCK("BVH::build"); - BroadPhase::build(edges, faces); // Build edge_boxes and face_boxes - init_bvh(vertex_boxes, *vertex_bvh); - init_bvh(edge_boxes, *edge_bvh); - init_bvh(face_boxes, *face_bvh); -} - -void BVH::init_bvh(const AABBs& boxes, SimpleBVH::BVH& bvh) -{ - if (boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::init_bvh"); - - // Convert AABBs to the format expected by SimpleBVH - std::vector> vector_boxes(boxes.size()); - for (int i = 0; i < boxes.size(); i++) { - vector_boxes[i] = { { boxes[i].min, boxes[i].max } }; - } - - bvh.init(vector_boxes); -} - -void BVH::clear() -{ - BroadPhase::clear(); - vertex_bvh->clear(); - edge_bvh->clear(); - face_bvh->clear(); -} - -template -void BVH::detect_candidates( - const AABBs& boxes, - const SimpleBVH::BVH& bvh, - const std::function& can_collide, - std::vector& candidates) -{ - // O(n) or O(n⋅log(n)) to build - // O(k⋅log(n)) to do a single look up - // O(k⋅n⋅log(n)) to do all look ups - - tbb::enumerable_thread_specific> storage; - - tbb::parallel_for( - tbb::blocked_range(size_t(0), boxes.size()), - [&](const tbb::blocked_range& r) { - auto& local_candidates = storage.local(); - - for (size_t i = r.begin(); i < r.end(); i++) { - std::vector js; - bvh.intersect_box(boxes[i].min, boxes[i].max, js); - - for (const unsigned int j : js) { - size_t ai = i, bi = j; - if constexpr (swap_order) { - std::swap(ai, bi); - } - - if constexpr (triangular) { - if (ai >= bi) { - continue; - } - } - - if (!can_collide(ai, bi)) { - continue; - } - - local_candidates.emplace_back(ai, bi); - } - } - }); - - merge_thread_local_vectors(storage, candidates); -} - -void BVH::detect_vertex_vertex_candidates( - std::vector& candidates) const -{ - if (vertex_boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::detect_vertex_vertex_candidates"); - - detect_candidates< - VertexVertexCandidate, /*swap_order=*/false, /*triangular=*/true>( - vertex_boxes, *vertex_bvh, can_vertices_collide, candidates); -} - -void BVH::detect_edge_vertex_candidates( - std::vector& candidates) const -{ - if (edge_boxes.empty() || vertex_boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::detect_edge_vertex_candidates"); - - // In 2D and for codimensional edge-vertex collisions, there are more - // vertices than edges, so we want to iterate over the edges. - detect_candidates( - edge_boxes, *vertex_bvh, - std::bind(&BVH::can_edge_vertex_collide, this, _1, _2), candidates); -} - -void BVH::detect_edge_edge_candidates( - std::vector& candidates) const -{ - if (edge_boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::detect_edge_edge_candidates"); - - detect_candidates< - EdgeEdgeCandidate, /*swap_order=*/false, /*triangular=*/true>( - edge_boxes, *edge_bvh, std::bind(&BVH::can_edges_collide, this, _1, _2), - candidates); -} - -void BVH::detect_face_vertex_candidates( - std::vector& candidates) const -{ - if (face_boxes.empty() || vertex_boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::detect_face_vertex_candidates"); - - // The ratio vertices:faces is 1:2, so we want to iterate over the vertices. - detect_candidates( - vertex_boxes, *face_bvh, - std::bind(&BVH::can_face_vertex_collide, this, _1, _2), candidates); -} - -void BVH::detect_edge_face_candidates( - std::vector& candidates) const -{ - if (edge_boxes.empty() || face_boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::detect_edge_face_candidates"); - - // The ratio edges:faces is 3:2, so we want to iterate over the faces. - detect_candidates( - face_boxes, *edge_bvh, - std::bind(&BVH::can_edge_face_collide, this, _1, _2), candidates); -} - -void BVH::detect_face_face_candidates( - std::vector& candidates) const -{ - if (face_boxes.empty()) { - return; - } - - IPC_TOOLKIT_PROFILE_BLOCK("BVH::detect_face_face_candidates"); - - detect_candidates< - FaceFaceCandidate, /*swap_order=*/false, /*triangular=*/true>( - face_boxes, *face_bvh, std::bind(&BVH::can_faces_collide, this, _1, _2), - candidates); -} -} // namespace ipc \ No newline at end of file diff --git a/src/ipc/broad_phase/bvh.hpp b/src/ipc/broad_phase/bvh.hpp deleted file mode 100644 index 4afa77388..000000000 --- a/src/ipc/broad_phase/bvh.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include - -#include - -namespace SimpleBVH { -class BVH; -} - -namespace ipc { - -/// @brief Bounding Volume Hierarchy (BVH) broad phase collision detection. -class [[deprecated("Use LBVH instead.")]] BVH : public BroadPhase { -public: - BVH(); - ~BVH(); - - /// @brief Get the name of the broad phase method. - /// @return The name of the broad phase method. - std::string name() const override { return "BVH"; } - - using BroadPhase::build; - - /// @brief Clear any built data. - void clear() override; - - /// @brief Find the candidate vertex-vertex collisions. - /// @param[out] candidates The candidate vertex-vertex collisions. - void detect_vertex_vertex_candidates( - std::vector& candidates) const override; - - /// @brief Find the candidate edge-vertex collisions. - /// @param[out] candidates The candidate edge-vertex collisions. - void detect_edge_vertex_candidates( - std::vector& candidates) const override; - - /// @brief Find the candidate edge-edge collisions. - /// @param[out] candidates The candidate edge-edge collisions. - void detect_edge_edge_candidates( - std::vector& candidates) const override; - - /// @brief Find the candidate face-vertex collisions. - /// @param[out] candidates The candidate face-vertex collisions. - void detect_face_vertex_candidates( - std::vector& candidates) const override; - - /// @brief Find the candidate edge-face intersections. - /// @param[out] candidates The candidate edge-face intersections. - void detect_edge_face_candidates( - std::vector& candidates) const override; - - /// @brief Find the candidate face-face collisions. - /// @param[out] candidates The candidate face-face collisions. - void detect_face_face_candidates( - std::vector& candidates) const override; - -protected: - /// @brief Build the broad phase for collision detection. - /// @note Assumes the vertex_boxes have been built. - /// @param edges Collision mesh edges - /// @param faces Collision mesh faces - void build( - Eigen::ConstRef edges, - Eigen::ConstRef faces) override; - - /// @brief Initialize a BVH from a set of boxes. - /// @param[in] boxes Set of boxes to initialize the BVH with. - /// @param[out] bvh The BVH to initialize. - static void init_bvh(const AABBs& boxes, SimpleBVH::BVH& bvh); - - /// @brief Detect candidate collisions between a BVH and a sets of boxes. - /// @tparam Candidate Type of candidate collision. - /// @tparam swap_order Whether to swap the order of box id with the BVH id when adding to the candidates. - /// @tparam triangular Whether to consider (i, j) and (j, i) as the same. - /// @param[in] boxes The boxes to detect collisions with. - /// @param[in] bvh The BVH to detect collisions with. - /// @param[in] can_collide Function to determine if two primitives can collide given their ids. - /// @param[out] candidates The candidate collisions. - template < - typename Candidate, - bool swap_order = false, - bool triangular = false> - static void detect_candidates( - const AABBs& boxes, - const SimpleBVH::BVH& bvh, - const std::function& can_collide, - std::vector& candidates); - - /// @brief BVH containing the vertices. - std::unique_ptr vertex_bvh; - /// @brief BVH containing the edges. - std::unique_ptr edge_bvh; - /// @brief BVH containing the faces. - std::unique_ptr face_bvh; -}; - -} // namespace ipc \ No newline at end of file diff --git a/src/ipc/broad_phase/create_broad_phase.cpp b/src/ipc/broad_phase/create_broad_phase.cpp index 938be137e..c812a1170 100644 --- a/src/ipc/broad_phase/create_broad_phase.cpp +++ b/src/ipc/broad_phase/create_broad_phase.cpp @@ -1,7 +1,6 @@ #include "create_broad_phase.hpp" #include -#include #include #include #include @@ -20,8 +19,6 @@ create_broad_phase(const BroadPhaseMethod& broad_phase_method) return std::make_shared(); case BroadPhaseMethod::SPATIAL_HASH: return std::make_shared(); - case BroadPhaseMethod::BVH: - return std::make_shared(); case BroadPhaseMethod::LBVH: return std::make_shared(); case BroadPhaseMethod::SWEEP_AND_PRUNE: diff --git a/src/ipc/broad_phase/create_broad_phase.hpp b/src/ipc/broad_phase/create_broad_phase.hpp index e68d34964..ef6b2ee89 100644 --- a/src/ipc/broad_phase/create_broad_phase.hpp +++ b/src/ipc/broad_phase/create_broad_phase.hpp @@ -9,7 +9,6 @@ enum class BroadPhaseMethod : uint8_t { BRUTE_FORCE, HASH_GRID, SPATIAL_HASH, - BVH [[deprecated("Use LBVH instead.")]], LBVH, SWEEP_AND_PRUNE, SWEEP_AND_TINIEST_QUEUE diff --git a/tests/src/tests/broad_phase/test_lbvh.cpp b/tests/src/tests/broad_phase/test_lbvh.cpp index 0625a8aab..6e71d4f03 100644 --- a/tests/src/tests/broad_phase/test_lbvh.cpp +++ b/tests/src/tests/broad_phase/test_lbvh.cpp @@ -3,9 +3,8 @@ #include #include -#include +#include #include -// #include #include #include @@ -14,8 +13,6 @@ #include -#include - using namespace ipc; namespace { @@ -208,8 +205,10 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") const std::shared_ptr lbvh = std::make_shared(); lbvh->build(vertices_t0, vertices_t1, edges, faces, inflation_radius); - const std::shared_ptr bvh = std::make_shared(); - bvh->build(vertices_t0, vertices_t1, edges, faces, inflation_radius); + const std::shared_ptr spatial_hash = + std::make_shared(); + spatial_hash->build( + vertices_t0, vertices_t1, edges, faces, inflation_radius); // detect_vertex_vertex_candidates { @@ -217,7 +216,7 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") lbvh->detect_vertex_vertex_candidates(vv_candidates); std::vector expected_vv_candidates; - bvh->detect_vertex_vertex_candidates(expected_vv_candidates); + spatial_hash->detect_vertex_vertex_candidates(expected_vv_candidates); CHECK(vv_candidates.size() >= expected_vv_candidates.size()); CHECK(contains_all_candidates(vv_candidates, expected_vv_candidates)); @@ -228,7 +227,7 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") lbvh->detect_edge_vertex_candidates(ev_candidates); std::vector expected_ev_candidates; - bvh->detect_edge_vertex_candidates(expected_ev_candidates); + spatial_hash->detect_edge_vertex_candidates(expected_ev_candidates); CHECK(ev_candidates.size() >= expected_ev_candidates.size()); CHECK(contains_all_candidates(ev_candidates, expected_ev_candidates)); @@ -239,7 +238,7 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") lbvh->detect_edge_edge_candidates(ee_candidates); std::vector expected_ee_candidates; - bvh->detect_edge_edge_candidates(expected_ee_candidates); + spatial_hash->detect_edge_edge_candidates(expected_ee_candidates); CHECK(ee_candidates.size() >= expected_ee_candidates.size()); CHECK(contains_all_candidates(ee_candidates, expected_ee_candidates)); @@ -250,7 +249,7 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") lbvh->detect_face_vertex_candidates(fv_candidates); std::vector expected_fv_candidates; - bvh->detect_face_vertex_candidates(expected_fv_candidates); + spatial_hash->detect_face_vertex_candidates(expected_fv_candidates); CHECK(fv_candidates.size() >= expected_fv_candidates.size()); CHECK(contains_all_candidates(fv_candidates, expected_fv_candidates)); @@ -261,7 +260,7 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") lbvh->detect_edge_face_candidates(ef_candidates); std::vector expected_ef_candidates; - bvh->detect_edge_face_candidates(expected_ef_candidates); + spatial_hash->detect_edge_face_candidates(expected_ef_candidates); CHECK(ef_candidates.size() >= expected_ef_candidates.size()); CHECK(contains_all_candidates(ef_candidates, expected_ef_candidates)); @@ -272,7 +271,7 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") lbvh->detect_face_face_candidates(ff_candidates); std::vector expected_ff_candidates; - bvh->detect_face_face_candidates(expected_ff_candidates); + spatial_hash->detect_face_face_candidates(expected_ff_candidates); CHECK(ff_candidates.size() >= expected_ff_candidates.size()); CHECK(contains_all_candidates(ff_candidates, expected_ff_candidates)); @@ -282,4 +281,4 @@ TEST_CASE("LBVH::detect_*_candidates", "[broad_phase][lbvh]") ipc::profiler().print(); ipc::profiler().clear(); #endif -} +} \ No newline at end of file diff --git a/tests/src/tests/broad_phase/test_stq.cpp b/tests/src/tests/broad_phase/test_stq.cpp index 3dbf9c3a9..f893dbebd 100644 --- a/tests/src/tests/broad_phase/test_stq.cpp +++ b/tests/src/tests/broad_phase/test_stq.cpp @@ -5,7 +5,6 @@ #include #include -#include using namespace ipc; diff --git a/tests/src/tests/utils.cpp b/tests/src/tests/utils.cpp index 2e1f8dc4b..a5a360c77 100644 --- a/tests/src/tests/utils.cpp +++ b/tests/src/tests/utils.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #ifdef IPC_TOOLKIT_WITH_CUDA @@ -27,7 +26,6 @@ std::vector> broad_phases() std::make_shared(), std::make_shared(), std::make_shared(), - std::make_shared(), std::make_shared(), std::make_shared(), #ifdef IPC_TOOLKIT_WITH_CUDA