From 1ceaa6fd2f0d98cae79290b3b68d4647b65bf8ac Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Thu, 6 Aug 2026 11:27:50 -0500 Subject: [PATCH 1/3] Update Tight Inclusion to 1.1.0 (bucket DFS root finding) Tight Inclusion 1.1.0 adds a BUCKET_DEPTH_FIRST_SEARCH root-finding method and makes it the default for edgeEdgeCCD/vertexFaceCCD. * Expose BUCKET_DEPTH_FIRST_SEARCH in the Python CCDRootFindingMethod enum and default ipctk.tight_inclusion.edge_edge_ccd and point_triangle_ccd to it, so the bindings match the C++ default. * Fix the CCD benchmark test case: the dataset SECTIONs inside run_benchmark() were siblings of the CCD-selection SECTIONs, so Catch2 never entered both in a single run and the benchmark loop was dead code. Call run_benchmark() from inside each section instead. * Add the [Belgrod et al. 2023] scenes to the earliest-toi benchmark and report which meshes failed to load when skipping. * Fix stale IPC_TOOLKIT_CCD_BENCHMARK_DIR and IPC_TOOLKIT_CCD_NEW_BENCHMARK_DIR references in the CMake status messages; the cache variables are IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR and IPC_TOOLKIT_TESTS_NEW_CCD_BENCHMARK_DIR. Co-Authored-By: Claude Opus 5 --- cmake/recipes/tight_inclusion.cmake | 2 +- python/src/ccd/tight_inclusion_ccd.cpp | 15 +++++++++---- tests/CMakeLists.txt | 8 +++---- tests/src/tests/ccd/benchmark_ccd.cpp | 26 +++++++++++++++++++++- tests/src/tests/ccd/test_ccd_benchmark.cpp | 10 +++------ 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/cmake/recipes/tight_inclusion.cmake b/cmake/recipes/tight_inclusion.cmake index ad08111ff..1fdf52785 100644 --- a/cmake/recipes/tight_inclusion.cmake +++ b/cmake/recipes/tight_inclusion.cmake @@ -7,7 +7,7 @@ endif() message(STATUS "Third-party: creating target 'tight_inclusion::tight_inclusion'") include(CPM) -CPMAddPackage("gh:Continuous-Collision-Detection/Tight-Inclusion@1.0.6") +CPMAddPackage("gh:Continuous-Collision-Detection/Tight-Inclusion@1.1.0") # Folder name for IDE set_target_properties(tight_inclusion PROPERTIES FOLDER "ThirdParty") \ No newline at end of file diff --git a/python/src/ccd/tight_inclusion_ccd.cpp b/python/src/ccd/tight_inclusion_ccd.cpp index dc23f3f4d..011bd2ea3 100644 --- a/python/src/ccd/tight_inclusion_ccd.cpp +++ b/python/src/ccd/tight_inclusion_ccd.cpp @@ -23,6 +23,11 @@ void define_tight_inclusion_ccd(py::module_& m) "BREADTH_FIRST_SEARCH", ticcd::CCDRootFindingMethod::BREADTH_FIRST_SEARCH, "Breadth first search") + .value( + "BUCKET_DEPTH_FIRST_SEARCH", + ticcd::CCDRootFindingMethod::BUCKET_DEPTH_FIRST_SEARCH, + "Depth first search with a dedicated traversal stack per time " + "lower bound") .export_values(); m_ti.def( @@ -61,7 +66,7 @@ void define_tight_inclusion_ccd(py::module_& m) max_iterations: Maximum number of solver iterations (default: 1e7). If negative, solver will run until convergence. filter: Filters calculated using get_numerical_error (default: (-1,-1,-1)). Use (-1,-1,-1) if checking a single query. no_zero_toi: Refine further if a zero TOI is produced (assuming not initially in contact). - ccd_method: Root finding method (default: BREADTH_FIRST_SEARCH). + ccd_method: Root finding method (default: BUCKET_DEPTH_FIRST_SEARCH). Returns: Tuple of: @@ -75,7 +80,8 @@ void define_tight_inclusion_ccd(py::module_& m) "max_iterations"_a = TightInclusionCCD::DEFAULT_MAX_ITERATIONS, "filter"_a = ticcd::Array3::Constant(-1), "no_zero_toi"_a = ticcd::DEFAULT_NO_ZERO_TOI, - "ccd_method"_a = ticcd::CCDRootFindingMethod::BREADTH_FIRST_SEARCH); + "ccd_method"_a = + ticcd::CCDRootFindingMethod::BUCKET_DEPTH_FIRST_SEARCH); m_ti.def( "point_triangle_ccd", @@ -113,7 +119,7 @@ void define_tight_inclusion_ccd(py::module_& m) max_iterations: Maximum number of solver iterations (default: 1e7). If negative, solver will run until convergence. filter: Filters calculated using get_numerical_error (default: (-1,-1,-1)). Use (-1,-1,-1) if checking a single query. no_zero_toi: Refine further if a zero TOI is produced (assuming not initially in contact). - ccd_method: Root finding method (default: BREADTH_FIRST_SEARCH). + ccd_method: Root finding method (default: BUCKET_DEPTH_FIRST_SEARCH). Returns: Tuple of: @@ -127,7 +133,8 @@ void define_tight_inclusion_ccd(py::module_& m) "max_iterations"_a = TightInclusionCCD::DEFAULT_MAX_ITERATIONS, "filter"_a = ticcd::Array3::Constant(-1), "no_zero_toi"_a = ticcd::DEFAULT_NO_ZERO_TOI, - "ccd_method"_a = ticcd::CCDRootFindingMethod::BREADTH_FIRST_SEARCH); + "ccd_method"_a = + ticcd::CCDRootFindingMethod::BUCKET_DEPTH_FIRST_SEARCH); m_ti.def( "compute_ccd_filters", diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b534803f8..7fc0bdcd1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -79,11 +79,11 @@ endif() if (IPC_TOOLKIT_TESTS_CCD_BENCHMARK) include(ccd_query_io) target_link_libraries(ipc_toolkit_tests PRIVATE ccd_io::ccd_io) - if(NOT (IPC_TOOLKIT_CCD_BENCHMARK_DIR STREQUAL "")) - message(STATUS "Using CCD benchmark directory: ${IPC_TOOLKIT_CCD_BENCHMARK_DIR}") + if(NOT (IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR STREQUAL "")) + message(STATUS "Using CCD benchmark directory: ${IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR}") endif() - if(NOT (IPC_TOOLKIT_CCD_NEW_BENCHMARK_DIR STREQUAL "")) - message(STATUS "Using new CCD benchmark directory: ${IPC_TOOLKIT_CCD_NEW_BENCHMARK_DIR}") + if(NOT (IPC_TOOLKIT_TESTS_NEW_CCD_BENCHMARK_DIR STREQUAL "")) + message(STATUS "Using new CCD benchmark directory: ${IPC_TOOLKIT_TESTS_NEW_CCD_BENCHMARK_DIR}") endif() endif() diff --git a/tests/src/tests/ccd/benchmark_ccd.cpp b/tests/src/tests/ccd/benchmark_ccd.cpp index bec93481a..7e709b04c 100644 --- a/tests/src/tests/ccd/benchmark_ccd.cpp +++ b/tests/src/tests/ccd/benchmark_ccd.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace ipc; @@ -26,11 +27,31 @@ TEST_CASE("Benchmark earliest toi", "[!benchmark][ccd][earliest_toi]") mesh_name_t0 = "private/slow-broadphase-ccd/s0.ply"; mesh_name_t1 = "private/slow-broadphase-ccd/s1.ply"; } + SECTION("Cloth-Funnel") + { + mesh_name_t0 = "cloth-funnel/227.ply"; + mesh_name_t1 = "cloth-funnel/228.ply"; + } SECTION("Cloth-ball") { mesh_name_t0 = "cloth_ball92.ply"; mesh_name_t1 = "cloth_ball93.ply"; } + SECTION("Armadillo-Rollers") + { + mesh_name_t0 = "armadillo-rollers/326.ply"; + mesh_name_t1 = "armadillo-rollers/327.ply"; + } + SECTION("N-Body-Simulation") + { + mesh_name_t0 = "n-body-simulation/balls16_18.ply"; + mesh_name_t1 = "n-body-simulation/balls16_19.ply"; + } + SECTION("Rod-Twist") + { + mesh_name_t0 = "rod-twist/3036.ply"; + mesh_name_t1 = "rod-twist/3037.ply"; + } SECTION("Puffer-Ball") { mesh_name_t0 = "puffer-ball/20.ply"; @@ -39,7 +60,10 @@ TEST_CASE("Benchmark earliest toi", "[!benchmark][ccd][earliest_toi]") if (!tests::load_mesh(mesh_name_t0, V0, E, F) || !tests::load_mesh(mesh_name_t1, V1, E, F)) { - SKIP("Slow broadphase CCD meshes are private"); + SKIP( + fmt::format( + "Unable to load {} and/or {} (some meshes are private)", + mesh_name_t0, mesh_name_t1)); } CollisionMesh mesh = CollisionMesh::build_from_full_mesh(V0, E, F); diff --git a/tests/src/tests/ccd/test_ccd_benchmark.cpp b/tests/src/tests/ccd/test_ccd_benchmark.cpp index 1ec4757af..b19afee71 100644 --- a/tests/src/tests/ccd/test_ccd_benchmark.cpp +++ b/tests/src/tests/ccd/test_ccd_benchmark.cpp @@ -187,27 +187,23 @@ static const std::string BENCHMARK_TAGS = TEST_CASE("Run CCD Benchmark", BENCHMARK_TAGS) { - std::shared_ptr ccd; - #ifdef IPC_TOOLKIT_WITH_INEXACT_CCD SECTION("Floating-Point CCD") { fmt::print("Floating-Point CCD:\n\n"); - ccd = std::make_shared(); + run_benchmark(std::make_shared()); } #endif SECTION("Tight Inclusion CCD") { fmt::print("Tight Inclusion CCD:\n\n"); - ccd = std::make_shared(); + run_benchmark(std::make_shared()); } SECTION("Additive CCD") { fmt::print("Additive CCD:\n\n"); - ccd = std::make_shared(); + run_benchmark(std::make_shared()); } - - run_benchmark(ccd); } // TEST_CASE("Failing Benchmark Cases", "[ccd]") From 74aa83db498366ca08ffc6fa58dccf9e3112b59f Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Thu, 6 Aug 2026 11:42:37 -0500 Subject: [PATCH 2/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/src/tests/ccd/benchmark_ccd.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/tests/ccd/benchmark_ccd.cpp b/tests/src/tests/ccd/benchmark_ccd.cpp index 7e709b04c..cc4a55b64 100644 --- a/tests/src/tests/ccd/benchmark_ccd.cpp +++ b/tests/src/tests/ccd/benchmark_ccd.cpp @@ -7,7 +7,6 @@ #include #include #include -#include using namespace ipc; From 9423d1764e90d0465017001030fd6158da7a6f8b Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Thu, 6 Aug 2026 11:44:30 -0500 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7fc0bdcd1..d26c8cd98 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -79,7 +79,7 @@ endif() if (IPC_TOOLKIT_TESTS_CCD_BENCHMARK) include(ccd_query_io) target_link_libraries(ipc_toolkit_tests PRIVATE ccd_io::ccd_io) - if(NOT (IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR STREQUAL "")) + if(NOT "${IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR}" STREQUAL "") message(STATUS "Using CCD benchmark directory: ${IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR}") endif() if(NOT (IPC_TOOLKIT_TESTS_NEW_CCD_BENCHMARK_DIR STREQUAL ""))