Skip to content

Commit 2696120

Browse files
authored
Replace BroadPhaseMethod enum with shared_ptr<BroadPhase> (#152)
* Replace BroadPhaseMethod phase enum with shared_ptr<BroadPhase> * Update docs * Fix GENERATE std::shared_ptr<BroadPhase> for CUDA * Add includes for Sweep and Prune, and Sweep and Tiniest Queue in GPU CCD tests * Fix default broad phase in python
1 parent b30785d commit 2696120

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+302
-268
lines changed

docs/source/cpp-api/broad_phase.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
Broad Phase
22
===========
33

4-
.. doxygenenum:: ipc::BroadPhaseMethod
5-
6-
.. doxygenvariable:: ipc::DEFAULT_BROAD_PHASE_METHOD
7-
84
Broad Phase
95
-----------
106

docs/source/python-api/broad_phase.rst

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
Broad Phase
22
===========
33

4-
.. autoclass:: ipctk.BroadPhaseMethod
5-
6-
.. autoclasstoc::
7-
8-
.. .. autovariable:: ipctk.DEFAULT_BROAD_PHASE_METHOD
9-
104
Broad Phase
115
-----------
126

docs/source/tutorial/getting_started.rst

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -508,21 +508,19 @@ The ``Candidates`` class represents the culled set of candidate pairs and is bui
508508

509509
ipc::Candidates candidates;
510510
candidates.build(
511-
mesh, vertices_t0, vertices_t1,
512-
/*inflation_radius=*/0.0,
513-
/*broad_phase_method=*/ipc::BroadPhaseMethod::HASH_GRID);
511+
mesh, vertices_t0, vertices_t1, /*inflation_radius=*/0.0,
512+
/*broad_phase=*/std::make_shared<ipc::HashGrid>());
514513

515514
.. md-tab-item:: Python
516515

517516
.. code-block:: python
518517
519518
candidates = ipctk.Candidates()
520519
candidates.build(
521-
mesh, vertices_t0, vertices_t1,
522-
broad_phase_method=ipctk.BroadPhaseMethod.HASH_GRID)
520+
mesh, vertices_t0, vertices_t1, broad_phase=ipctk.HashGrid())
523521
524-
Possible values for ``broad_phase_method`` are: ``BRUTE_FORCE`` (parallel brute force culling), ``HASH_GRID`` (default), ``SPATIAL_HASH`` (implementation from the original IPC codebase),
525-
``BVH`` (`SimpleBVH <https://github.com/geometryprocessing/SimpleBVH>`_), ``SWEEP_AND_PRUNE`` (method of :cite:t:`Belgrod2023Time`), or ``SWEEP_AND_TINIEST_QUEUE`` (requires CUDA).
522+
Possible values for ``broad_phase`` are: ``BruteForce`` (parallel brute force culling), ``HashGrid`` (default), ``SpatialHash`` (implementation from the original IPC codebase),
523+
``BVH`` (`SimpleBVH <https://github.com/geometryprocessing/SimpleBVH>`_), ``SweepAndPrune`` (method of :cite:t:`Belgrod2023Time`), or ``SweepAndTiniestQueue`` (requires CUDA).
526524

527525
Narrow-Phase
528526
^^^^^^^^^^^^
@@ -628,17 +626,12 @@ To do this, we need to set the ``min_distance`` parameter when calling ``is_step
628626
.. code-block:: c++
629627

630628
double max_step_size = ipc::compute_collision_free_stepsize(
631-
collision_mesh, vertices_t0, vertices_t1,
632-
/*broad_phase_method=*/ipc::DEFAULT_BROAD_PHASE_METHOD,
633-
/*min_distance=*/1e-4);
629+
collision_mesh, vertices_t0, vertices_t1, /*min_distance=*/1e-4);
634630

635631
Eigen::MatrixXd collision_free_vertices =
636632
(vertices_t1 - vertices_t0) * max_step_size + vertices_t0;
637633
assert(ipc::is_step_collision_free(
638-
mesh, vertices_t0, collision_free_vertices,
639-
/*broad_phase_method=*/ipc::DEFAULT_BROAD_PHASE_METHOD,
640-
/*min_distance=*/1e-4
641-
));
634+
mesh, vertices_t0, collision_free_vertices, /*min_distance=*/1e-4));
642635

643636
.. md-tab-item:: Python
644637

python/src/broad_phase/broad_phase.cpp

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,8 @@ using namespace ipc;
88

99
void define_broad_phase(py::module_& m)
1010
{
11-
py::enum_<BroadPhaseMethod>(
12-
m, "BroadPhaseMethod",
13-
"Enumeration of implemented broad phase methods.")
14-
.value("BRUTE_FORCE", BroadPhaseMethod::BRUTE_FORCE, "Brute force")
15-
.value("HASH_GRID", BroadPhaseMethod::HASH_GRID, "Hash grid")
16-
.value("SPATIAL_HASH", BroadPhaseMethod::SPATIAL_HASH, "Spatial hash")
17-
.value(
18-
"BOUNDING_VOLUME_HIERARCHY", BroadPhaseMethod::BVH,
19-
"Bounding volume hierarchy")
20-
.value(
21-
"SWEEP_AND_PRUNE", BroadPhaseMethod::SWEEP_AND_PRUNE,
22-
"Sweep and prune")
23-
.value(
24-
"SWEEP_AND_TINIEST_QUEUE",
25-
BroadPhaseMethod::SWEEP_AND_TINIEST_QUEUE,
26-
"Sweep and tiniest queue (GPU)")
27-
.export_values();
28-
29-
py::class_<BroadPhase>(m, "BroadPhase")
30-
.def_static(
31-
"make_broad_phase", &BroadPhase::make_broad_phase,
32-
R"ipc_Qu8mg5v7(
33-
Construct a registered broad phase object.
34-
35-
Parameters:
36-
method: The broad phase method to use.
37-
38-
Returns:
39-
The constructed broad phase object.
40-
)ipc_Qu8mg5v7",
41-
py::arg("method"))
11+
py::class_<BroadPhase, std::shared_ptr<BroadPhase>>(m, "BroadPhase")
12+
.def("name", &BroadPhase::name, "Get the name of the broad phase.")
4213
.def(
4314
"build",
4415
py::overload_cast<

python/src/broad_phase/brute_force.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ using namespace ipc;
77

88
void define_brute_force(py::module_& m)
99
{
10-
py::class_<BruteForce, BroadPhase>(m, "BruteForce").def(py::init());
10+
py::class_<BruteForce, BroadPhase, std::shared_ptr<BruteForce>>(
11+
m, "BruteForce")
12+
.def(py::init());
1113
}

python/src/broad_phase/bvh.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ using namespace ipc;
77

88
void define_bvh(py::module_& m)
99
{
10-
py::class_<BVH, BroadPhase>(m, "BVH").def(py::init());
10+
py::class_<BVH, BroadPhase, std::shared_ptr<BVH>>(m, "BVH").def(py::init());
1111
}

python/src/broad_phase/hash_grid.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ void define_hash_grid(py::module_& m)
1818
.def_readwrite("key", &HashItem::key, "The key of the item.")
1919
.def_readwrite("id", &HashItem::id, "The value of the item.");
2020

21-
py::class_<HashGrid, BroadPhase>(m, "HashGrid")
21+
py::class_<HashGrid, BroadPhase, std::shared_ptr<HashGrid>>(m, "HashGrid")
2222
.def(py::init())
2323
.def_property_readonly("cell_size", &HashGrid::cell_size)
2424
.def_property_readonly(

python/src/broad_phase/spatial_hash.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ using namespace ipc;
77

88
void define_spatial_hash(py::module_& m)
99
{
10-
py::class_<SpatialHash, BroadPhase>(m, "SpatialHash")
10+
py::class_<SpatialHash, BroadPhase, std::shared_ptr<SpatialHash>>(
11+
m, "SpatialHash")
1112
.def(py::init())
1213
.def(
1314
py::init<

python/src/broad_phase/sweep_and_prune.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ using namespace ipc;
77

88
void define_sweep_and_prune(py::module_& m)
99
{
10-
py::class_<SweepAndPrune, BroadPhase>(m, "SweepAndPrune").def(py::init());
10+
py::class_<SweepAndPrune, BroadPhase, std::shared_ptr<SweepAndPrune>>(
11+
m, "SweepAndPrune")
12+
.def(py::init());
1113
}

python/src/broad_phase/sweep_and_tiniest_queue.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ using namespace ipc; // not defined if IPC_TOOLKIT_WITH_CUDA is not defined
1010
void define_sweep_and_tiniest_queue(py::module_& m)
1111
{
1212
#ifdef IPC_TOOLKIT_WITH_CUDA
13-
py::class_<SweepAndTiniestQueue, BroadPhase>(m, "SweepAndTiniestQueue")
13+
py::class_<
14+
SweepAndTiniestQueue, BroadPhase,
15+
std::shared_ptr<SweepAndTiniestQueue>>(m, "SweepAndTiniestQueue")
1416
.def(py::init());
1517
#endif
1618
}

python/src/candidates/candidates.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@ void define_candidates(py::module_& m)
1313
"build",
1414
py::overload_cast<
1515
const CollisionMesh&, const Eigen::MatrixXd&, const double,
16-
const BroadPhaseMethod>(&Candidates::build),
16+
std::shared_ptr<BroadPhase>>(&Candidates::build),
1717
R"ipc_Qu8mg5v7(
1818
Initialize the set of discrete collision detection candidates.
1919
2020
Parameters:
2121
mesh: The surface of the collision mesh.
2222
vertices: Surface vertex positions (rowwise).
2323
inflation_radius: Amount to inflate the bounding boxes.
24-
broad_phase_method: Broad phase method to use.
24+
broad_phase: Broad phase to use.
2525
)ipc_Qu8mg5v7",
2626
py::arg("mesh"), py::arg("vertices"),
2727
py::arg("inflation_radius") = 0,
28-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD)
28+
py::arg("broad_phase") = make_default_broad_phase())
2929
.def(
3030
"build",
3131
py::overload_cast<
3232
const CollisionMesh&, const Eigen::MatrixXd&,
33-
const Eigen::MatrixXd&, const double, const BroadPhaseMethod>(
34-
&Candidates::build),
33+
const Eigen::MatrixXd&, const double,
34+
std::shared_ptr<BroadPhase>>(&Candidates::build),
3535
R"ipc_Qu8mg5v7(
3636
Initialize the set of continuous collision detection candidates.
3737
@@ -43,11 +43,11 @@ void define_candidates(py::module_& m)
4343
vertices_t0: Surface vertex starting positions (rowwise).
4444
vertices_t1: Surface vertex ending positions (rowwise).
4545
inflation_radius: Amount to inflate the bounding boxes.
46-
broad_phase_method: Broad phase method to use.
46+
broad_phase: Broad phase to use.
4747
)ipc_Qu8mg5v7",
4848
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
4949
py::arg("inflation_radius") = 0,
50-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD)
50+
py::arg("broad_phase") = make_default_broad_phase())
5151
.def("__len__", &Candidates::size)
5252
.def("empty", &Candidates::empty)
5353
.def("clear", &Candidates::clear)
@@ -122,13 +122,13 @@ void define_candidates(py::module_& m)
122122
vertices_t0: Surface vertex starting positions (rowwise).
123123
vertices_t1: Surface vertex ending positions (rowwise).
124124
dhat: Barrier activation distance.
125-
min_distance: The minimum distance allowable between any two elements.
126-
narrow_phase_ccd: The narrow phase CCD algorithm to use.
125+
min_distance: Minimum distance allowable between any two elements.
126+
broad_phase: Broad phase algorithm to use.
127+
narrow_phase_ccd: Narrow phase CCD algorithm to use.
127128
)ipc_Qu8mg5v7",
128129
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
129-
py::arg("dhat"),
130-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD,
131-
py::arg("min_distance") = 0.0,
130+
py::arg("dhat"), py::arg("min_distance") = 0.0,
131+
py::arg("broad_phase") = make_default_broad_phase(),
132132
py::arg("narrow_phase_ccd") = DEFAULT_NARROW_PHASE_CCD)
133133
.def(
134134
"save_obj", &Candidates::save_obj, py::arg("filename"),

python/src/collisions/normal/normal_collisions.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ void define_normal_collisions(py::module_& m)
1313
"build",
1414
py::overload_cast<
1515
const CollisionMesh&, const Eigen::MatrixXd&, const double,
16-
const double, const BroadPhaseMethod>(&NormalCollisions::build),
16+
const double, std::shared_ptr<BroadPhase>>(
17+
&NormalCollisions::build),
1718
R"ipc_Qu8mg5v7(
1819
Initialize the set of collisions used to compute the barrier potential.
1920
@@ -22,11 +23,11 @@ void define_normal_collisions(py::module_& m)
2223
vertices: Vertices of the collision mesh.
2324
dhat: The activation distance of the barrier.
2425
dmin: Minimum distance.
25-
broad_phase_method: Broad-phase method to use.
26+
broad_phase: Broad-phase to use.
2627
)ipc_Qu8mg5v7",
2728
py::arg("mesh"), py::arg("vertices"), py::arg("dhat"),
2829
py::arg("dmin") = 0,
29-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD)
30+
py::arg("broad_phase") = make_default_broad_phase())
3031
.def(
3132
"build",
3233
py::overload_cast<

python/src/ipc.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <ipc/ipc.hpp>
44
#include <ipc/config.hpp>
5+
56
#include <igl/edges.h>
67

78
namespace py = pybind11;
@@ -24,15 +25,15 @@ void define_ipc(py::module_& m)
2425
vertices_t0: Surface vertex vertices at start as rows of a matrix.
2526
vertices_t1: Surface vertex vertices at end as rows of a matrix.
2627
min_distance: The minimum distance allowable between any two elements.
27-
broad_phase_method: The broad phase method to use.
28+
broad_phase: Broad phase to use.
2829
narrow_phase_ccd: The narrow phase CCD algorithm to use.
2930
3031
Returns:
3132
True if <b>any</b> collisions occur.
3233
)ipc_Qu8mg5v7",
3334
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
3435
py::arg("min_distance") = 0.0,
35-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD,
36+
py::arg("broad_phase") = make_default_broad_phase(),
3637
py::arg("narrow_phase_ccd") = DEFAULT_NARROW_PHASE_CCD);
3738

3839
m.def(
@@ -48,15 +49,15 @@ void define_ipc(py::module_& m)
4849
vertices_t0: Vertex vertices at start as rows of a matrix. Assumes vertices_t0 is intersection free.
4950
vertices_t1: Surface vertex vertices at end as rows of a matrix.
5051
min_distance: The minimum distance allowable between any two elements.
51-
broad_phase_method: The broad phase method to use.
52+
broad_phase: Broad phase to use.
5253
narrow_phase_ccd: The narrow phase CCD algorithm to use.
5354
5455
Returns:
5556
A step-size :math:`\in [0, 1]` that is collision free. A value of 1.0 if a full step and 0.0 is no step.
5657
)ipc_Qu8mg5v7",
5758
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
5859
py::arg("min_distance") = 0.0,
59-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD,
60+
py::arg("broad_phase") = make_default_broad_phase(),
6061
py::arg("narrow_phase_ccd") = DEFAULT_NARROW_PHASE_CCD);
6162

6263
m.def(
@@ -67,13 +68,13 @@ void define_ipc(py::module_& m)
6768
Parameters:
6869
mesh: The collision mesh.
6970
vertices: Vertices of the collision mesh.
70-
broad_phase_method: The broad phase method to use.
71+
broad_phase: Broad phase to use.
7172
7273
Returns:
7374
A boolean for if the mesh has intersections.
7475
)ipc_Qu8mg5v7",
7576
py::arg("mesh"), py::arg("vertices"),
76-
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD);
77+
py::arg("broad_phase") = make_default_broad_phase());
7778

7879
m.def(
7980
"edges",

python/tests/test_ipc.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import utils
66

77

8-
def check_ipc_derivatives(broad_phase_method, use_convergent_formulation, mesh_name, dhat, all_vertices_on_surface):
8+
def check_ipc_derivatives(broad_phase, use_convergent_formulation, mesh_name, dhat, all_vertices_on_surface):
99
vertices, edges, faces = utils.load_mesh(mesh_name)
1010

1111
if all_vertices_on_surface:
@@ -17,8 +17,7 @@ def check_ipc_derivatives(broad_phase_method, use_convergent_formulation, mesh_n
1717
collisions = ipctk.NormalCollisions()
1818
collisions.use_area_weighting = use_convergent_formulation
1919
collisions.use_improved_max_approximator = use_convergent_formulation
20-
collisions.build(mesh, vertices, dhat,
21-
broad_phase_method=broad_phase_method)
20+
collisions.build(mesh, vertices, dhat, broad_phase=broad_phase)
2221
assert len(collisions) > 0
2322

2423
B = ipctk.BarrierPotential(
@@ -40,7 +39,7 @@ def check_ipc_derivatives(broad_phase_method, use_convergent_formulation, mesh_n
4039

4140

4241
def test_ipc():
43-
for method in utils.broad_phase_methods():
42+
for method in utils.broad_phases():
4443
for use_convergent_formulation in (True, False):
4544
yield check_ipc_derivatives, method, use_convergent_formulation, "cube.ply", np.sqrt(2.0), True
4645
yield check_ipc_derivatives, method, use_convergent_formulation, "two-cubes-far.ply", 1e-1, False

python/tests/utils.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ def load_mesh(mesh_name):
2929
return mesh.points, ipctk.edges(mesh.cells_dict['triangle']), mesh.cells_dict['triangle']
3030

3131

32-
def broad_phase_methods():
33-
yield ipctk.BroadPhaseMethod.BRUTE_FORCE
34-
yield ipctk.BroadPhaseMethod.HASH_GRID
35-
yield ipctk.BroadPhaseMethod.SPATIAL_HASH
36-
yield ipctk.BroadPhaseMethod.BOUNDING_VOLUME_HIERARCHY
37-
yield ipctk.BroadPhaseMethod.SWEEP_AND_PRUNE
32+
def broad_phases():
33+
yield ipctk.BruteForce()
34+
yield ipctk.HashGrid()
35+
yield ipctk.SpatialHash()
36+
yield ipctk.BVH()
37+
yield ipctk.SweepAndPrune()
3838

3939

4040
def finite_jacobian(x, f, h=1e-8):

src/ipc/broad_phase/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(SOURCES
77
brute_force.hpp
88
bvh.cpp
99
bvh.hpp
10+
default_broad_phase.hpp
1011
hash_grid.cpp
1112
hash_grid.hpp
1213
spatial_hash.cpp

0 commit comments

Comments
 (0)