Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions docs/source/cpp-api/broad_phase.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
Broad Phase
===========

.. doxygenenum:: ipc::BroadPhaseMethod

.. doxygenvariable:: ipc::DEFAULT_BROAD_PHASE_METHOD

Broad Phase
-----------

Expand Down
6 changes: 0 additions & 6 deletions docs/source/python-api/broad_phase.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
Broad Phase
===========

.. autoclass:: ipctk.BroadPhaseMethod

.. autoclasstoc::

.. .. autovariable:: ipctk.DEFAULT_BROAD_PHASE_METHOD

Broad Phase
-----------

Expand Down
21 changes: 7 additions & 14 deletions docs/source/tutorial/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -508,21 +508,19 @@ The ``Candidates`` class represents the culled set of candidate pairs and is bui

ipc::Candidates candidates;
candidates.build(
mesh, vertices_t0, vertices_t1,
/*inflation_radius=*/0.0,
/*broad_phase_method=*/ipc::BroadPhaseMethod::HASH_GRID);
mesh, vertices_t0, vertices_t1, /*inflation_radius=*/0.0,
/*broad_phase=*/std::make_shared<ipc::HashGrid>());

.. md-tab-item:: Python

.. code-block:: python

candidates = ipctk.Candidates()
candidates.build(
mesh, vertices_t0, vertices_t1,
broad_phase_method=ipctk.BroadPhaseMethod.HASH_GRID)
mesh, vertices_t0, vertices_t1, broad_phase=ipctk.HashGrid())

Possible values for ``broad_phase_method`` are: ``BRUTE_FORCE`` (parallel brute force culling), ``HASH_GRID`` (default), ``SPATIAL_HASH`` (implementation from the original IPC codebase),
``BVH`` (`SimpleBVH <https://github.com/geometryprocessing/SimpleBVH>`_), ``SWEEP_AND_PRUNE`` (method of :cite:t:`Belgrod2023Time`), or ``SWEEP_AND_TINIEST_QUEUE`` (requires CUDA).
Possible values for ``broad_phase`` are: ``BruteForce`` (parallel brute force culling), ``HashGrid`` (default), ``SpatialHash`` (implementation from the original IPC codebase),
``BVH`` (`SimpleBVH <https://github.com/geometryprocessing/SimpleBVH>`_), ``SweepAndPrune`` (method of :cite:t:`Belgrod2023Time`), or ``SweepAndTiniestQueue`` (requires CUDA).

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

double max_step_size = ipc::compute_collision_free_stepsize(
collision_mesh, vertices_t0, vertices_t1,
/*broad_phase_method=*/ipc::DEFAULT_BROAD_PHASE_METHOD,
/*min_distance=*/1e-4);
collision_mesh, vertices_t0, vertices_t1, /*min_distance=*/1e-4);

Eigen::MatrixXd collision_free_vertices =
(vertices_t1 - vertices_t0) * max_step_size + vertices_t0;
assert(ipc::is_step_collision_free(
mesh, vertices_t0, collision_free_vertices,
/*broad_phase_method=*/ipc::DEFAULT_BROAD_PHASE_METHOD,
/*min_distance=*/1e-4
));
mesh, vertices_t0, collision_free_vertices, /*min_distance=*/1e-4));

.. md-tab-item:: Python

Expand Down
33 changes: 2 additions & 31 deletions python/src/broad_phase/broad_phase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,8 @@ using namespace ipc;

void define_broad_phase(py::module_& m)
{
py::enum_<BroadPhaseMethod>(
m, "BroadPhaseMethod",
"Enumeration of implemented broad phase methods.")
.value("BRUTE_FORCE", BroadPhaseMethod::BRUTE_FORCE, "Brute force")
.value("HASH_GRID", BroadPhaseMethod::HASH_GRID, "Hash grid")
.value("SPATIAL_HASH", BroadPhaseMethod::SPATIAL_HASH, "Spatial hash")
.value(
"BOUNDING_VOLUME_HIERARCHY", BroadPhaseMethod::BVH,
"Bounding volume hierarchy")
.value(
"SWEEP_AND_PRUNE", BroadPhaseMethod::SWEEP_AND_PRUNE,
"Sweep and prune")
.value(
"SWEEP_AND_TINIEST_QUEUE",
BroadPhaseMethod::SWEEP_AND_TINIEST_QUEUE,
"Sweep and tiniest queue (GPU)")
.export_values();

py::class_<BroadPhase>(m, "BroadPhase")
.def_static(
"make_broad_phase", &BroadPhase::make_broad_phase,
R"ipc_Qu8mg5v7(
Construct a registered broad phase object.

Parameters:
method: The broad phase method to use.

Returns:
The constructed broad phase object.
)ipc_Qu8mg5v7",
py::arg("method"))
py::class_<BroadPhase, std::shared_ptr<BroadPhase>>(m, "BroadPhase")
.def("name", &BroadPhase::name, "Get the name of the broad phase.")
.def(
"build",
py::overload_cast<
Expand Down
4 changes: 3 additions & 1 deletion python/src/broad_phase/brute_force.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ using namespace ipc;

void define_brute_force(py::module_& m)
{
py::class_<BruteForce, BroadPhase>(m, "BruteForce").def(py::init());
py::class_<BruteForce, BroadPhase, std::shared_ptr<BruteForce>>(
m, "BruteForce")
.def(py::init());
}
2 changes: 1 addition & 1 deletion python/src/broad_phase/bvh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ using namespace ipc;

void define_bvh(py::module_& m)
{
py::class_<BVH, BroadPhase>(m, "BVH").def(py::init());
py::class_<BVH, BroadPhase, std::shared_ptr<BVH>>(m, "BVH").def(py::init());
}
2 changes: 1 addition & 1 deletion python/src/broad_phase/hash_grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void define_hash_grid(py::module_& m)
.def_readwrite("key", &HashItem::key, "The key of the item.")
.def_readwrite("id", &HashItem::id, "The value of the item.");

py::class_<HashGrid, BroadPhase>(m, "HashGrid")
py::class_<HashGrid, BroadPhase, std::shared_ptr<HashGrid>>(m, "HashGrid")
.def(py::init())
.def_property_readonly("cell_size", &HashGrid::cell_size)
.def_property_readonly(
Expand Down
3 changes: 2 additions & 1 deletion python/src/broad_phase/spatial_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ using namespace ipc;

void define_spatial_hash(py::module_& m)
{
py::class_<SpatialHash, BroadPhase>(m, "SpatialHash")
py::class_<SpatialHash, BroadPhase, std::shared_ptr<SpatialHash>>(
m, "SpatialHash")
.def(py::init())
.def(
py::init<
Expand Down
4 changes: 3 additions & 1 deletion python/src/broad_phase/sweep_and_prune.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ using namespace ipc;

void define_sweep_and_prune(py::module_& m)
{
py::class_<SweepAndPrune, BroadPhase>(m, "SweepAndPrune").def(py::init());
py::class_<SweepAndPrune, BroadPhase, std::shared_ptr<SweepAndPrune>>(
m, "SweepAndPrune")
.def(py::init());
}
4 changes: 3 additions & 1 deletion python/src/broad_phase/sweep_and_tiniest_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ using namespace ipc; // not defined if IPC_TOOLKIT_WITH_CUDA is not defined
void define_sweep_and_tiniest_queue(py::module_& m)
{
#ifdef IPC_TOOLKIT_WITH_CUDA
py::class_<SweepAndTiniestQueue, BroadPhase>(m, "SweepAndTiniestQueue")
py::class_<
SweepAndTiniestQueue, BroadPhase,
std::shared_ptr<SweepAndTiniestQueue>>(m, "SweepAndTiniestQueue")
.def(py::init());
#endif
}
24 changes: 12 additions & 12 deletions python/src/candidates/candidates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,25 @@ void define_candidates(py::module_& m)
"build",
py::overload_cast<
const CollisionMesh&, const Eigen::MatrixXd&, const double,
const BroadPhaseMethod>(&Candidates::build),
std::shared_ptr<BroadPhase>>(&Candidates::build),
R"ipc_Qu8mg5v7(
Initialize the set of discrete collision detection candidates.

Parameters:
mesh: The surface of the collision mesh.
vertices: Surface vertex positions (rowwise).
inflation_radius: Amount to inflate the bounding boxes.
broad_phase_method: Broad phase method to use.
broad_phase: Broad phase to use.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices"),
py::arg("inflation_radius") = 0,
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD)
py::arg("broad_phase") = make_default_broad_phase())
.def(
"build",
py::overload_cast<
const CollisionMesh&, const Eigen::MatrixXd&,
const Eigen::MatrixXd&, const double, const BroadPhaseMethod>(
&Candidates::build),
const Eigen::MatrixXd&, const double,
std::shared_ptr<BroadPhase>>(&Candidates::build),
R"ipc_Qu8mg5v7(
Initialize the set of continuous collision detection candidates.

Expand All @@ -43,11 +43,11 @@ void define_candidates(py::module_& m)
vertices_t0: Surface vertex starting positions (rowwise).
vertices_t1: Surface vertex ending positions (rowwise).
inflation_radius: Amount to inflate the bounding boxes.
broad_phase_method: Broad phase method to use.
broad_phase: Broad phase to use.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
py::arg("inflation_radius") = 0,
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD)
py::arg("broad_phase") = make_default_broad_phase())
.def("__len__", &Candidates::size)
.def("empty", &Candidates::empty)
.def("clear", &Candidates::clear)
Expand Down Expand Up @@ -122,13 +122,13 @@ void define_candidates(py::module_& m)
vertices_t0: Surface vertex starting positions (rowwise).
vertices_t1: Surface vertex ending positions (rowwise).
dhat: Barrier activation distance.
min_distance: The minimum distance allowable between any two elements.
narrow_phase_ccd: The narrow phase CCD algorithm to use.
min_distance: Minimum distance allowable between any two elements.
broad_phase: Broad phase algorithm to use.
narrow_phase_ccd: Narrow phase CCD algorithm to use.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
py::arg("dhat"),
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD,
py::arg("min_distance") = 0.0,
py::arg("dhat"), py::arg("min_distance") = 0.0,
py::arg("broad_phase") = make_default_broad_phase(),
py::arg("narrow_phase_ccd") = DEFAULT_NARROW_PHASE_CCD)
.def(
"save_obj", &Candidates::save_obj, py::arg("filename"),
Expand Down
7 changes: 4 additions & 3 deletions python/src/collisions/normal/normal_collisions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ void define_normal_collisions(py::module_& m)
"build",
py::overload_cast<
const CollisionMesh&, const Eigen::MatrixXd&, const double,
const double, const BroadPhaseMethod>(&NormalCollisions::build),
const double, std::shared_ptr<BroadPhase>>(
&NormalCollisions::build),
R"ipc_Qu8mg5v7(
Initialize the set of collisions used to compute the barrier potential.

Expand All @@ -22,11 +23,11 @@ void define_normal_collisions(py::module_& m)
vertices: Vertices of the collision mesh.
dhat: The activation distance of the barrier.
dmin: Minimum distance.
broad_phase_method: Broad-phase method to use.
broad_phase: Broad-phase to use.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices"), py::arg("dhat"),
py::arg("dmin") = 0,
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD)
py::arg("broad_phase") = make_default_broad_phase())
.def(
"build",
py::overload_cast<
Expand Down
13 changes: 7 additions & 6 deletions python/src/ipc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <ipc/ipc.hpp>
#include <ipc/config.hpp>

#include <igl/edges.h>

namespace py = pybind11;
Expand All @@ -24,15 +25,15 @@ void define_ipc(py::module_& m)
vertices_t0: Surface vertex vertices at start as rows of a matrix.
vertices_t1: Surface vertex vertices at end as rows of a matrix.
min_distance: The minimum distance allowable between any two elements.
broad_phase_method: The broad phase method to use.
broad_phase: Broad phase to use.
narrow_phase_ccd: The narrow phase CCD algorithm to use.

Returns:
True if <b>any</b> collisions occur.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
py::arg("min_distance") = 0.0,
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD,
py::arg("broad_phase") = make_default_broad_phase(),
py::arg("narrow_phase_ccd") = DEFAULT_NARROW_PHASE_CCD);

m.def(
Expand All @@ -48,15 +49,15 @@ void define_ipc(py::module_& m)
vertices_t0: Vertex vertices at start as rows of a matrix. Assumes vertices_t0 is intersection free.
vertices_t1: Surface vertex vertices at end as rows of a matrix.
min_distance: The minimum distance allowable between any two elements.
broad_phase_method: The broad phase method to use.
broad_phase: Broad phase to use.
narrow_phase_ccd: The narrow phase CCD algorithm to use.

Returns:
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.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices_t0"), py::arg("vertices_t1"),
py::arg("min_distance") = 0.0,
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD,
py::arg("broad_phase") = make_default_broad_phase(),
py::arg("narrow_phase_ccd") = DEFAULT_NARROW_PHASE_CCD);

m.def(
Expand All @@ -67,13 +68,13 @@ void define_ipc(py::module_& m)
Parameters:
mesh: The collision mesh.
vertices: Vertices of the collision mesh.
broad_phase_method: The broad phase method to use.
broad_phase: Broad phase to use.

Returns:
A boolean for if the mesh has intersections.
)ipc_Qu8mg5v7",
py::arg("mesh"), py::arg("vertices"),
py::arg("broad_phase_method") = DEFAULT_BROAD_PHASE_METHOD);
py::arg("broad_phase") = make_default_broad_phase());

m.def(
"edges",
Expand Down
7 changes: 3 additions & 4 deletions python/tests/test_ipc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import utils


def check_ipc_derivatives(broad_phase_method, use_convergent_formulation, mesh_name, dhat, all_vertices_on_surface):
def check_ipc_derivatives(broad_phase, use_convergent_formulation, mesh_name, dhat, all_vertices_on_surface):
vertices, edges, faces = utils.load_mesh(mesh_name)

if all_vertices_on_surface:
Expand All @@ -17,8 +17,7 @@ def check_ipc_derivatives(broad_phase_method, use_convergent_formulation, mesh_n
collisions = ipctk.NormalCollisions()
collisions.use_area_weighting = use_convergent_formulation
collisions.use_improved_max_approximator = use_convergent_formulation
collisions.build(mesh, vertices, dhat,
broad_phase_method=broad_phase_method)
collisions.build(mesh, vertices, dhat, broad_phase=broad_phase)
assert len(collisions) > 0

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


def test_ipc():
for method in utils.broad_phase_methods():
for method in utils.broad_phases():
for use_convergent_formulation in (True, False):
yield check_ipc_derivatives, method, use_convergent_formulation, "cube.ply", np.sqrt(2.0), True
yield check_ipc_derivatives, method, use_convergent_formulation, "two-cubes-far.ply", 1e-1, False
Expand Down
12 changes: 6 additions & 6 deletions python/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ def load_mesh(mesh_name):
return mesh.points, ipctk.edges(mesh.cells_dict['triangle']), mesh.cells_dict['triangle']


def broad_phase_methods():
yield ipctk.BroadPhaseMethod.BRUTE_FORCE
yield ipctk.BroadPhaseMethod.HASH_GRID
yield ipctk.BroadPhaseMethod.SPATIAL_HASH
yield ipctk.BroadPhaseMethod.BOUNDING_VOLUME_HIERARCHY
yield ipctk.BroadPhaseMethod.SWEEP_AND_PRUNE
def broad_phases():
yield ipctk.BruteForce()
yield ipctk.HashGrid()
yield ipctk.SpatialHash()
yield ipctk.BVH()
yield ipctk.SweepAndPrune()


def finite_jacobian(x, f, h=1e-8):
Expand Down
1 change: 1 addition & 0 deletions src/ipc/broad_phase/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(SOURCES
brute_force.hpp
bvh.cpp
bvh.hpp
default_broad_phase.hpp
hash_grid.cpp
hash_grid.hpp
spatial_hash.cpp
Expand Down
Loading