Highlights
- Implement "Geometric Contact Potential" [Huang et al. 2025] by @Huangzizhou in #191
- Implement "Offset Geometric Contact" [Chen et al. 2025] by @zfergus in #192
- Implement fully parallel LBVH Broad Phase by @zfergus in #188
- Add geometry utilities for collision normals, signed distances, and dihedral angles with gradients and Hessians.
What's Changed
New Formulations
-
Geometric Contact Potential (GCP) by @Huangzizhou in #191
- The implementation includes the collision and friction potential with gradients and Hessians.
- Tutorial available here.
-
Offset Geometric Contact (OGC) by @zfergus in #192
- OGC is a penetration-free contact model that replaces continuous collision detection (CCD) with a trust-region-based approach.
-
New Namespace: Introduced
ipc::ogcto encapsulate OGC-specific functionality. -
Trust Region Implementation:
- Added
TrustRegionclass (trust_region.hpp,trust_region.cpp) to manage per-vertex conservative bounds. - Implemented
warm_start_time_stepto initialize the trust region and handle initial predictions. - Implemented
filter_stepto scale optimization steps ensuring vertices stay within safe bounds. - Implemented
updateandupdate_if_neededto dynamically resize trust regions based on motion.
- Added
-
Feasible Region Logic:
- Added
feasible_region.hppandfeasible_region.cppcontaining geometric predicates (e.g.,check_vertex_feasible_region,is_edge_edge_feasible) to verify if primitives are within valid non-penetrating regions. - Integrated feasible region checks into the
NormalCollisionsclass to filter out invalid collision candidates. Enabled viaset_collision_set_type(NormalCollisions::CollisionSetType::OGC).
- Added
-
Step Scaling: Unlike the original paper's projection method,
TrustRegion::filter_stepscales the descent direction$\beta$ to keep vertices on the trust region boundary. This preserves the descent direction, ensuring compatibility with line-search-based solvers. - Tutorial available here.
Broad Phase
- Parallel CPU LBVH implementation by @zfergus in #188
- New broad phase collision detection method with memory optimizations on the AABB structure.
- LBVH Broad Phase:
- Implemented
LBVHclass insrc/ipc/broad_phase/lbvh.hpp, providing a Linear Bounding Volume Hierarchy method for broad phase collision detection. - Fully parallel build and traversal routines using Intel TBB.
- SIMD optimizations for AABB overlap tests.
- Faster than the existing BVH method and all other broad phase methods in IPC Toolkit for large scenes.
- More than 3x faster to build.
- Up to 1.5x faster for candidate detection.
- Detailed performance charts available below.
- Added
python/examples/lbvh.pyto demonstrate usage and visualization.
- Implemented
- ⚡ Enhancements
- Performance Optimizations:
- Added
DefaultInitAllocatorto reduce overhead when allocating large arrays of POD types. - Replaced
std::vector<AABB>withstd::vector<AABB, DefaultInitAllocator<AABB>>.
- Added
- Memory Optimization:
- Switched
AABB::minandAABB::maxfromArrayMax3dtoEigen::Array3d. - Result: Reduces
sizeof(AABB)from 76 to 64 bytes, allowing AABB to fit into a single cache line (assuming 64-byte lines).
- Switched
- Replaced hardware rounding in
AABB::conservative_inflationwith software rounding usingstd::nextafter.
- Performance Optimizations:
- 💥 Breaking Changes
- API & Structural Changes:
- Moved dimension variable: Removed dim from
AABBand moved it toBroadPhaseto handle 2D/3D data more cleanly.dimis now set inBroadPhase::build. - Handle 2D data by setting AABB's z-components to zero.
- Constructor Removal: Removed the AABB default constructor and the initialization of
AABB::vertex_ids. - Type Change: Changed
to_3Dinipc/utils/eigen_ext.hppto operate onEigen::Arraytypes instead ofEigen::Vector.
- Moved dimension variable: Removed dim from
- Deprecated
BVHclass in favor of the newLBVHclass for better performance on large scenes.
- API & Structural Changes:
- Refactor BroadPhase to Build from Vertex Boxes Directly in #187
- Rename
sweep_and_tiniest_queue.cppto.cufile by @iiiian in #203 - Fix vertex id assignment by @iiiian in #204
- Fix vertex id assignment logic in
SweepAndTiniestQueue.
- Fix vertex id assignment logic in
- Replace optional
const shared_ptr<BroadPhase>¶meters withBroadPhase*in #205- Change
make_default_broad_phaseto return aunique_ptr
- Change
- Pass parameters to Scalable CCD Narrow-Phase by @antoinebou12 in #208
- Replace hardcoded
TightInclusionCCD::DEFAULT_TOLERANCEandTightInclusionCCD::DEFAULT_MAX_ITERATIONwithnarrow_phase.toleranceandnarrow_phase.toleranceif passed aTightInclusionCCDobject. - If
narrow_phase_ccdis not aTightInclusionCCDinstance, we fall back to default values to preserve backward compatibility.
- Replace hardcoded
- Add SIMD support via
xsimdlibrary in #207- Cross-platform SIMD (Single Instruction, Multiple Data) support using the
xsimdlibrary in the LBVH code. - Update the
IPC_TOOLKIT_WITH_SIMDto be enabled by default, and improve CMake logic to detect SIMD capabilities and configure the build accordingly. - Disable Eigen's internal vectorization to avoid crashes on Linux.
- Cross-platform SIMD (Single Instruction, Multiple Data) support using the
Math and Geometry Utilities
- Add normal computation and Jacobian methods for collision candidates in #182
- Collect normal utilities into
geometry/normalfiles in #197 - Organize geometry and math utilities into
geometryandmathfolders in #198 - Add signed distance computations for point-plane, point-line, and line-line geometries in #206
- Optimized edge_edge_mollifier.cpp with FMA operator in gradient calculations.
Miscellaneous
- Updated dependencies:
- Bump Abseil from
20250512.1to20260107.0 - Bump Catch2 from
v3.8.1tov3.12.0 - Bump Eigen from
3.4.0to5.0.1 - Bump JSON from
v3.11.2tov3.12.0 - Bump libigl from
89267b4a80b1904de3f6f2812a2053e5e9332b7etov2.6.0 - Bump TBB from
v2022.1.0tov2022.3.0 - Bump Pybind11 from
v2.13.1tov3.0.1 - Bump robin-map from
v1.4.0tov1.4.1 - Bump spdlog from
v1.15.3tov1.17.0
- Bump Abseil from
- Make most dependencies private
- Added a figure for default dependencies of the
ipc::toolkitlibrary: https://ipctk.xyz/about/dependencies.html - Refactored
BVHclass to use unique_ptr to hideSimpleBVH - Updated Sweep and Prune and Sweep and Tiniest Queue classes to use a Pimpl pattern for encapsulation.
- Mark
tsl::robin_mapandabsl::hashas private dependencies in CMake. Update the dependency documentation accordingly. - Convert
SpatialHashto PImpl idiom to hidetsl::robin_mapandabsl::hashfrom the public API.
- Added a figure for default dependencies of the
- Add Clang Tidy check
- Added a
.clang-tidyconfiguration file with a comprehensive set of checks, exclusions, naming conventions, and options to enforce modern C++ practices and treat all warnings as errors. - Introduced a GitHub Actions workflow (
.github/workflows/clang-tidy-check.yml) to automatically run Clang-Tidy on relevant files for every push and pull request, improving code quality and review automation.
- Added a
- Simplify CMake CUDA setup by @iiiian in #201
- Disable CUDA builds by default.
- Bump CMake minimum version to
3.24to supportCMAKE_CUDA_ARCHITECTURES="native"
- Add performance profiling utilities in #188
- Added a (optional) profiler utility (
src/ipc/utils/profiler.hpp) to measure/record metrics with CSV output support. - Added Nlohmann JSON as a dependency for profiler storage.
- Use
IPC_TOOLKIT_WITH_PROFILERCMake option to enable/disable profiling.
- Added a (optional) profiler utility (
- Refactor to use
Eigen::ConstReffor vertices in #200
New Contributors
Full Changelog: v1.4.0...v1.5.0