Skip to content

Commit 5370866

Browse files
authored
Nonlinear CCD (#72)
* Implement nonlinear CCD of linear geometry * Optional filib
1 parent 7d04a5f commit 5370866

27 files changed

+1074
-133
lines changed

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ project(IPCToolkit
6363

6464
option(IPC_TOOLKIT_BUILD_TESTS "Build unit-tests" ${IPC_TOOLKIT_TOPLEVEL_PROJECT})
6565
option(IPC_TOOLKIT_BUILD_PYTHON "Build Python bindings" OFF)
66-
option(IPC_TOOLKIT_WITH_CORRECT_CCD "Use the TightInclusion CCD" ON)
66+
option(IPC_TOOLKIT_WITH_CORRECT_CCD "Use Tight Inclusion CCD" ON)
6767
option(IPC_TOOLKIT_WITH_SIMD "Enable SIMD" OFF)
6868
option(IPC_TOOLKIT_WITH_CUDA "Enable CUDA CCD" OFF)
6969
option(IPC_TOOLKIT_WITH_RATIONAL_INTERSECTION "Use rational edge-triangle intersection check" OFF)
7070
option(IPC_TOOLKIT_WITH_ROBIN_MAP "Use Tessil's robin-map rather than std maps" ON)
7171
option(IPC_TOOLKIT_WITH_ABSEIL "Use Abseil's hash functions" ON)
72+
option(IPC_TOOLKIT_WITH_FILIB "Use filib for interval arithmetic" ON)
7273
option(IPC_TOOLKIT_WITH_CODE_COVERAGE "Enable coverage reporting" OFF)
7374
mark_as_advanced(IPC_TOOLKIT_WITH_CODE_COVERAGE)
7475

@@ -181,6 +182,12 @@ if(IPC_TOOLKIT_WITH_ABSEIL)
181182
target_link_libraries(ipc_toolkit PUBLIC absl::hash)
182183
endif()
183184

185+
# Intervals
186+
if(IPC_TOOLKIT_WITH_FILIB)
187+
include(filib)
188+
target_link_libraries(ipc_toolkit PUBLIC filib::filib)
189+
endif()
190+
184191
# Extra warnings (link last for highest priority)
185192
include(ipc_toolkit_warnings)
186193
target_link_libraries(ipc_toolkit PRIVATE ipc::toolkit::warnings)

IPCToolkitOptions.cmake.sample

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,14 @@
3030

3131
# option(IPC_TOOLKIT_BUILD_TESTS "Build unit-tests" ON)
3232
# option(IPC_TOOLKIT_BUILD_PYTHON "Build Python bindings" OFF)
33-
# option(IPC_TOOLKIT_WITH_CORRECT_CCD "Use the TightInclusion CCD" ON)
33+
# option(IPC_TOOLKIT_WITH_CORRECT_CCD "Use Tight Inclusion CCD" ON)
3434
# option(IPC_TOOLKIT_WITH_SIMD "Enable SIMD" OFF)
3535
# option(IPC_TOOLKIT_WITH_CUDA "Enable CUDA CCD" OFF)
3636
# option(IPC_TOOLKIT_WITH_RATIONAL_INTERSECTION "Use rational edge-triangle intersection check" OFF)
37-
# option(IPC_TOOLKIT_WITH_ROBIN_MAP "Use Tessil's robin-map rather than std maps" ON)
37+
# option(IPC_TOOLKIT_WITH_ROBIN_MAP "Use Tessil's robin-map rather than std maps" ON)
38+
# option(IPC_TOOLKIT_WITH_ABSEIL "Use Abseil's hash functions" ON)
39+
# option(IPC_TOOLKIT_WITH_FILIB "Use filib for interval arithmetic" ON)
40+
# option(IPC_TOOLKIT_WITH_CODE_COVERAGE "Enable coverage reporting" OFF)
41+
# option(IPC_TOOLKIT_TESTS_CCD_BENCHMARK "Enable CCD benchmark test" ON)
42+
# set(IPC_TOOLKIT_TESTS_CCD_BENCHMARK_DIR "" CACHE PATH "Path to the CCD benchmark directory")
43+
# set(IPC_TOOLKIT_TESTS_NEW_CCD_BENCHMARK_DIR "" CACHE PATH "Path to the new CCD benchmark directory")

cmake/ipc_toolkit/ipc_toolkit_warnings.cmake

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ set(IPC_TOOLKIT_WARNING_FLAGS
1313
-pedantic
1414

1515
# -Wconversion
16-
#-Wunsafe-loop-optimizations # broken with C++11 loops
16+
# -Wunsafe-loop-optimizations # broken with C++11 loops
1717
-Wunused
1818

1919
-Wno-long-long
@@ -39,14 +39,13 @@ set(IPC_TOOLKIT_WARNING_FLAGS
3939
-Werror=int-to-pointer-cast
4040
-Werror=pointer-to-int-cast
4141

42-
-Wno-unused-variable
42+
-Wunused-variable
4343
-Wunused-but-set-variable
4444
-Wno-unused-parameter
4545

4646
#-Weffc++
47-
-Wno-old-style-cast
48-
# -Wno-sign-conversion
49-
#-Wsign-conversion
47+
-Wold-style-cast
48+
# -Wsign-conversion
5049

5150
# -Wshadow
5251

@@ -69,7 +68,7 @@ set(IPC_TOOLKIT_WARNING_FLAGS
6968

7069
-Wcast-align
7170
-Wdisabled-optimization
72-
#-Winline # produces warning on default implicit destructor
71+
# -Winline # produces warning on default implicit destructor
7372
-Winvalid-pch
7473
# -Wmissing-include-dirs
7574
-Wpacked

cmake/recipes/filib.cmake

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# filib (https://github.com/zfergus/filib.git)
2+
# License: LGPL
3+
if(TARGET filib::filib)
4+
return()
5+
endif()
6+
7+
message(STATUS "Third-party: creating target 'filib::filib'")
8+
9+
include(CPM)
10+
CPMAddPackage("gh:zfergus/filib#63acb1f78dcdf7667ca2d214f7a3fa3505fdf339")

src/ipc/broad_phase/voxel_size_heuristic.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
namespace ipc {
88

9+
namespace {
10+
// Avoid unused variable warnings
11+
inline void check_success(bool success) { assert(success); }
12+
} // namespace
13+
914
double suggest_good_voxel_size(
1015
const Eigen::MatrixXd& vertices,
1116
const Eigen::MatrixXi& edges,
@@ -129,16 +134,14 @@ double median_edge_length(
129134
}
130135

131136
double median = -1;
132-
const bool success = igl::median(lengths, median);
133-
assert(success);
137+
check_success(igl::median(lengths, median));
134138
return median;
135139
}
136140

137141
double median_displacement_length(const Eigen::MatrixXd& displacements)
138142
{
139143
double median = -1;
140-
const bool success = igl::median(displacements.rowwise().norm(), median);
141-
assert(success);
144+
check_success(igl::median(displacements.rowwise().norm(), median));
142145
return median;
143146
}
144147

src/ipc/ccd/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ set(SOURCES
77
ccd.hpp
88
inexact_point_edge.cpp
99
inexact_point_edge.hpp
10+
nonlinear_ccd.cpp
11+
nonlinear_ccd.hpp
1012
point_static_plane.cpp
1113
point_static_plane.hpp
1214
)

src/ipc/ccd/ccd.cpp

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#ifdef IPC_TOOLKIT_WITH_CORRECT_CCD
1111
#include <tight_inclusion/ccd.hpp>
12-
#include <tight_inclusion/interval_root_finder.hpp>
1312
#else
1413
#include <ipc/ccd/inexact_point_edge.hpp>
1514
#include <CTCD.h>
@@ -20,39 +19,14 @@
2019

2120
namespace ipc {
2221

23-
namespace {
24-
inline Eigen::Vector3d to_3D(const VectorMax3d& v)
25-
{
26-
assert(v.size() == 2 || v.size() == 3);
27-
return v.size() == 2 ? Eigen::Vector3d(v.x(), v.y(), 0) : v.head<3>();
28-
}
29-
30-
inline bool check_initial_distance(
31-
const double initial_distance, const double min_distance, double& toi)
32-
{
33-
if (initial_distance > min_distance) {
34-
return false;
35-
}
36-
37-
logger().warn(
38-
"Initial distance {} ≤ d_min={}, returning toi=0!",
39-
initial_distance, min_distance);
40-
41-
toi = 0; // Initially touching
42-
43-
return true;
44-
}
45-
} // namespace
46-
47-
/// @brief Scale the distance tolerance to be at most this fraction of the initial distance.
22+
/// Scale the distance tolerance to be at most this fraction of the initial
23+
/// distance.
4824
static constexpr double INITIAL_DISTANCE_TOLERANCE_SCALE = 0.5;
4925

50-
/// @brief Special value for max_iterations to run tight inclusion without a maximum number of iterations.
26+
/// Special value for max_iterations to run tight inclusion without a maximum
27+
/// number of iterations.
5128
static constexpr long TIGHT_INCLUSION_UNLIMITED_ITERATIONS = -1;
5229

53-
/// @brief Tolerance for small time of impact which triggers rerunning CCD without a minimum separation.
54-
static constexpr double SMALL_TOI = 1e-6;
55-
5630
bool ccd_strategy(
5731
const std::function<bool(
5832
long /*max_iterations*/,
@@ -87,15 +61,15 @@ bool ccd_strategy(
8761
// #ifdef IPC_TOOLKIT_WITH_CORRECT_CCD
8862
// // Tight inclusion will have higher accuracy and better performance
8963
// // if we shrink the minimum distance. The value 1e-10 is arbitrary.
90-
// while (is_impacting && toi < SMALL_TOI && min_distance > 1e-10) {
64+
// while (is_impacting && toi < CCD_SMALL_TOI && min_distance > 1e-10) {
9165
// min_distance /= 10;
9266
// is_impacting =
9367
// ccd(max_iterations, min_distance, /*no_zero_toi=*/false,
9468
// toi);
9569
// }
9670
// #endif
9771

98-
if (is_impacting && toi < SMALL_TOI) {
72+
if (is_impacting && toi < CCD_SMALL_TOI) {
9973
is_impacting = ccd(
10074
/*max_iterations=*/TIGHT_INCLUSION_UNLIMITED_ITERATIONS,
10175
/*min_distance=*/min_distance, /*no_zero_toi=*/true, toi);
@@ -219,7 +193,7 @@ bool point_edge_ccd_3D(
219193
max_iterations, // maximum number of iterations
220194
output_tolerance, // delta_actual
221195
no_zero_toi);
222-
if (adjusted_tolerance < output_tolerance && toi < SMALL_TOI) {
196+
if (adjusted_tolerance < output_tolerance && toi < CCD_SMALL_TOI) {
223197
logger().trace(
224198
"ticcd::edgeEdgeCCD exceeded iteration limit (min_dist={:g} "
225199
"max_iterations={:d} input_tol={:g} output_tol={:g} toi={:g})",
@@ -252,10 +226,9 @@ bool point_edge_ccd(
252226
const long max_iterations,
253227
const double conservative_rescaling)
254228
{
255-
int dim = p_t0.size();
256-
assert(p_t1.size() == dim);
257-
assert(e0_t0.size() == dim && e1_t0.size() == dim);
258-
assert(e0_t1.size() == dim && e1_t1.size() == dim);
229+
assert(p_t1.size() == p_t0.size());
230+
assert(e0_t0.size() == p_t0.size() && e1_t0.size() == p_t0.size());
231+
assert(e0_t1.size() == p_t0.size() && e1_t1.size() == p_t0.size());
259232
return point_edge_ccd_3D(
260233
to_3D(p_t0), to_3D(e0_t0), to_3D(e1_t0), to_3D(p_t1), to_3D(e0_t1),
261234
to_3D(e1_t1), toi, min_distance, tmax, tolerance, max_iterations,
@@ -305,7 +278,7 @@ bool edge_edge_ccd(
305278
max_iterations, // maximum number of iterations
306279
output_tolerance, // delta_actual
307280
no_zero_toi);
308-
if (adjusted_tolerance < output_tolerance && toi < SMALL_TOI) {
281+
if (adjusted_tolerance < output_tolerance && toi < CCD_SMALL_TOI) {
309282
logger().trace(
310283
"ticcd::edgeEdgeCCD exceeded iteration limit (min_dist={:g} "
311284
"max_iterations={:d} input_tol={:g} output_tol={:g} toi={:g})",
@@ -368,7 +341,7 @@ bool point_triangle_ccd(
368341
max_iterations, // maximum number of iterations
369342
output_tolerance, // delta_actual
370343
no_zero_toi);
371-
if (adjusted_tolerance < output_tolerance && toi < SMALL_TOI) {
344+
if (adjusted_tolerance < output_tolerance && toi < CCD_SMALL_TOI) {
372345
logger().trace(
373346
"ticcd::vertexFaceCCD exceeded iteration limit (min_dist={:g} "
374347
"max_iterations={:d} input_tol={:g} output_tol={:g} toi={:g})",
@@ -388,4 +361,22 @@ bool point_triangle_ccd(
388361
conservative_rescaling, toi);
389362
}
390363

364+
// -----------------------------------------------------------------------------
365+
366+
bool check_initial_distance(
367+
const double initial_distance, const double min_distance, double& toi)
368+
{
369+
if (initial_distance > min_distance) {
370+
return false;
371+
}
372+
373+
logger().warn(
374+
"Initial distance {} ≤ d_min={}, returning toi=0!", initial_distance,
375+
min_distance);
376+
377+
toi = 0; // Initially touching
378+
379+
return true;
380+
}
381+
391382
} // namespace ipc

0 commit comments

Comments
 (0)