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
3 changes: 0 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 0 additions & 14 deletions cmake/recipes/simple_bvh.cmake

This file was deleted.

5 changes: 0 additions & 5 deletions docs/source/_static/graphviz/dependencies.dot
Original file line number Diff line number Diff line change
Expand Up @@ -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";];
Expand Down
249 changes: 115 additions & 134 deletions docs/source/_static/graphviz/dependencies.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions docs/source/about/dependencies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ These dependencies are all `permissively licensed <license.html>`_, and we list
- Provably conservative CCD
- MIT
- `github.com/Continuous-Collision-Detection/Tight-Inclusion <https://github.com/Continuous-Collision-Detection/Tight-Inclusion>`_
* - SimpleBVH
- Simple bounding volume hierarchy data structure
- MIT
- `github.com/geometryprocessing/SimpleBVH <https://github.com/geometryprocessing/SimpleBVH>`_
* - Scalable-CCD
- Scalable (GPU) CCD
- Apache-2.0
Expand Down
6 changes: 0 additions & 6 deletions docs/source/cpp-api/broad_phase.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ Spatial Hash
.. doxygenclass:: ipc::SpatialHash
:allow-dot-graphs:

BVH
---

.. doxygenclass:: ipc::BVH
:allow-dot-graphs:

LBVH
---

Expand Down
7 changes: 0 additions & 7 deletions docs/source/python-api/broad_phase.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@ Spatial Hash

.. autoclasstoc::

BVH
---

.. autoclass:: ipctk.BVH

.. autoclasstoc::

LBVH
----

Expand Down
2 changes: 1 addition & 1 deletion docs/source/tutorials/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/geometryprocessing/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
^^^^^^^^^^^^
Expand Down
82 changes: 48 additions & 34 deletions notebooks/ogc.py
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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
Expand All @@ -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()

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -120,43 +121,56 @@ 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()
ps_mesh.add_scalar_quantity("force", np.linalg.norm(f, axis=1))
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)
Expand Down
21 changes: 8 additions & 13 deletions python/examples/profiler.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)

Expand Down
1 change: 0 additions & 1 deletion python/src/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions python/src/broad_phase/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ set(SOURCES
aabb.cpp
broad_phase.cpp
brute_force.cpp
bvh.cpp
hash_grid.cpp
lbvh.cpp
spatial_hash.cpp
Expand All @@ -11,4 +10,4 @@ set(SOURCES
voxel_size_heuristic.cpp
)

target_sources(ipctk PRIVATE ${SOURCES})
target_sources(ipctk PRIVATE ${SOURCES})
1 change: 0 additions & 1 deletion python/src/broad_phase/bindings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 0 additions & 10 deletions python/src/broad_phase/bvh.cpp

This file was deleted.

28 changes: 19 additions & 9 deletions python/tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pathlib
import numpy as np
import meshio

import meshio
import numpy as np
from find_ipctk import ipctk


Expand All @@ -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()


Expand Down
Loading