Release NotesΒΆ

v2.0.0 (alpha)ΒΆ

Warning

This is an in-development alpha release. The API is not yet stable.

HighlightsΒΆ

  • Contact Hessian assembly is now block-accelerated. Local per-collision Hessians scatter straight into MeshFEMSparse [Mohammadian et al., 2026] block-CSC storage, and the full-mesh DOF map is folded into that scatter instead of being applied afterwards. Callers do not have to change anything to benefit: on Puffer-Ball (512k collisions) assembling a Hessian goes from 918 ms to 46 ms (#246).

  • Templated distance, barrier, normal, tangent-basis, closest-point, relative-velocity, and area functions on the scalar type and dimension. This adds float support alongside double (and autodiff scalars where already supported). This is 1.5–4.8Γ— faster for select functons; see Performance below (#249).

  • Update Tight Inclusion to 1.1.0, which adds a bucket depth-first-search root finder and makes it the default (#248).

  • Update the tutorials to match the current API, and fill the gaps in the Python bindings they depend on (#247).

New Features πŸš€ΒΆ

  • Expose the intersection coordinates of an edge–triangle intersection through a new ipc::edge_triangle_intersection() overload, which reports the barycentric coordinates \((u, v)\) on the triangle and the parameter \(t\) along the edge (#245).

  • Add ipc::CollisionMesh::face_normals(), computing the unit normal of each face for a given set of vertex positions (3D only) (#245).

API Changes πŸ”§ΒΆ

  • Update Tight Inclusion from 1.0.6 to 1.1.0 (#248).

    • Adds a BUCKET_DEPTH_FIRST_SEARCH root-finding method, which upstream makes the default for edgeEdgeCCD and vertexFaceCCD.

    • The method is exposed in the Python CCDRootFindingMethod enum, and ipctk.tight_inclusion.edge_edge_ccd and point_triangle_ccd now default to it so the bindings match the C++ default.

  • Potential::gradient and Potential::hessian take a new in_full_dof flag, folding the full-mesh DOF map into assembly (#246). Non-selection DOF maps fall back internally, so the flag is always safe to pass.

  • Add a HessianAssembler interface separating local derivative evaluation from global matrix construction (#246).

    • The previous triplet path lives on unchanged as TripletHessianAssembler and remains the fallback when the option is off.

    • Hold a MeshFEMHessianAssembler across Potential::hessian calls to get sparsity-pattern reuse, or call block_matrix() for the native block-CSC matrix if your solver can consume it.

  • Move gradient assembly into a shared ipc::assemble_gradient (ipc/utils/gradient_assembler.hpp) that all five gradient-producing potentials route through (#246).

  • Templatize the distance, tangent, friction, adhesion, and geometry functions on the scalar type.

    • Functions now take a scalar template parameter T and are instantiated for float, double, xsimd::batch<float>, and xsimd::batch<double> types.

    • πŸ’₯ [Breaking] Mixed-precision calls no longer deduce: barrier(float_d, 0.001) must become barrier(float_d, 0.001f).

    • πŸ’₯ [Breaking] The gradients/Hessians of the point-point, point-line, and point-edge distances and the normalization_* functions now return fixed-size Eigen types (e.g. Eigen::Vector<T, 3 * dim>) when the argument type knows its dimension at compile time, and the previous VectorMax/MatrixMax types otherwise.

    • The functions are now a two-layer API.

      • The concrete kernels moved into ipc::detail and are templated on the scalar and the dimension (template <typename T, int dim>, or just <typename T> for the 3D-only).

      • The public names in ipc are thin front ends templated on the argument expression types. They deduce T, dispatch on the compile-time dimension when the arguments know it, and fall back to a single runtime branch on size() otherwise. Existing calls are unaffected.

    • Autodiff scalars are supported for the value functions only; passing one to a *_gradient/*_hessian or to a *_distance_type predicate is a compile-time or AUTO-dispatch error rather than silently wrong output.

    • AUTO and the *_distance_type predicates are not available for batch scalars and throw std::invalid_argument. The distance type is a per-lane property but the predicates return a single enum, so two lanes cannot report different closest features. Resolve the distance types scalar-side and group problems by type before batching.

    • edge_edge_closest_point and point_triangle_closest_point solve their 2Γ—2 symmetric positive-definite system in closed form instead of with A.ldlt().solve(), whose pivot is scalar control flow a batch cannot take per-lane.

      • Solve using Cramer’s rule, which is a closed form for 2Γ—2 systems. The determinant is computed in Kahan’s fused multiply-add form to recover the rounding error of one product, so the solution stays accurate even when the two products cancel badly.

      • The pivot in LDLT loses the same digits as the naive determinant, so it is no more accurate than the closed form.

      • Measured against the exact solution of the same double inputs, the closed form and LDLT stay within about 2Γ— of each other on well-conditioned systems, but at 1e-4 rad the closed form is accurate to 4e-17 relative where LDLT reaches only 2e-9.

  • Templatize the barrier classes on the scalar type.

    • ipc::Barrier is now an alias for the class template ipc::BarrierBase<T> (defaulting to double).

    • πŸ’₯ [Breaking] The concrete barriers are now class templates and must be spelled with explicit template arguments (e.g., ipc::ClampedLogBarrier<>).

    • The free functions ipc::barrier, ipc::barrier_first_derivative, and ipc::barrier_second_derivative are now templates defaulting to double.

    • Replace if/else` branches in the barrier functions with select_lazy cascades, so a batch may carry lanes on either side of dhat. Single scalar inputs still only evaluate the active branch.

  • Add ipc::numext namespace containing an override for sqrt, abs, log, fma, and atan2. For float and double they call std::; for xsimd::batch<T> they call the corresponding xsimd function. This allows the templated distance and barrier functions to call numext::sqrt and friends without knowing whether they are operating on scalars or batches.

  • πŸ’₯ [Breaking] xsimd and SIMD_CXX_FLAGS are now linked/applied PUBLIC rather than PRIVATE. xsimd::default_arch is selected from each translation unit’s own compiler flags, so a consumer built without the library’s SIMD flags would name a different batch type than the one instantiated and fail to link. This means consumers are now compiled with the detected SIMD flags (typically -march=native); disable IPC_TOOLKIT_WITH_SIMD if that is not wanted.

Performance ⚑¢

  • Assemble the contact Hessian into MeshFEMSparse [Mohammadian et al., 2026] block-CSC storage rather than triplets, and fold the mesh’s DOF map into that scatter (#246).

    Evaluating the local per-collision Hessians was only 2–8% of Potential::hessian across the eight benchmark scenes; the rest was building triplets, sorting them inside setFromTriplets, and multiplying by the selection matrix twice in to_full_dof.

    https://github.com/user-attachments/assets/fdfb0d8f-e3ad-459f-88ae-bd2fea9b64a8

    Hessian assembly by stage. to_full_dof is absent from every MeshFEM bar because it is folded into the scatter, and local evaluation grows from a sliver to roughly half the bar β€” on the largest scenes the arithmetic is now the majority of the cost. Benchmarked on Apple Silicon, AppleClang 21, Release; median of three runs.ΒΆ

  • The speed-up comes from four independent steps, each measured against the triplet baseline in the same run (#246).

    https://github.com/user-attachments/assets/32709ba8-4365-4826-a8e8-17d4abf7d71d

    Ablation of the four steps, applied successively. Benchmarked on Apple Silicon, AppleClang 21, Release; median of three runs.ΒΆ

    1. Fold to_full_dof into assembly (1.2–1.8Γ—). When the DOF map is a plain selection matrix β€” which holds unless a custom displacement map was supplied β€” stencil vertex IDs are remapped during assembly and the two sparse products disappear. Non-selection maps fall back internally, so passing the new in_full_dof flag is always safe.

    2. Assemble into block-CSC rather than triplets (2.6–15.3Γ—). A block sparsity pattern is built from the collision stencils, then local Hessians scatter into the value array through a sorted column-merge with per-column locks β€” no triplet construction and no setFromTriplets sort.

    3. Reuse the pattern across assemblies (3.2–24.8Γ—). One assembler held across a Newton solve detects contact-set changes and rebuilds only when it must.

    4. Skip change detection when the caller asserts the set is unchanged (3.8–30.9Γ—).

    Most of the win lands before any reuse. Reuse pays where pattern construction dominates and adds almost nothing on Rod-Twist, where detection costs about what a rebuild does β€” which is what the opt-in fast path in step 4 exists for.

  • Share one gradient-assembly routine across all vector-assembly paths, picking its strategy per call from the problem shape (#246).

    Sparse contact buffers the local gradients in parallel and scatters them serially, costing one add per stencil slot; dense contact keeps per-thread accumulators and reduces them in parallel over DOF blocks. The crossover sits at roughly out_ndof > 4 Γ— collisions.

    https://github.com/user-attachments/assets/aceb3cb7-367f-4266-8493-7b6a4685ed01

    Gradient assembly, before and after, with the strategy selected per scene. Benchmarked on Apple Silicon, AppleClang 21, Release; median of three runs.ΒΆ

  • Replace the three 2Γ—2 LDLT solves in ipc::point_triangle_distance_type with a closed form (#249).

    • Each edge lies in the triangle’s plane, so the 2Γ—2 Gram matrix is diagonal and the solve collapses to two guarded divisions.

    • Measured 10–13Γ— faster standalone (104 β†’ 8.6 ns) and 7.3Γ— on the full AUTO distance query (93 β†’ 12.8 ns).

    • An error study over 10.8 million configurations (uniform, needle, cap, near-collinear, degenerate, in-plane, and coordinate scales from 1e-50 to 1e+50) found zero classification changes outside triangles collinear to within 1e-11 of their own edge length.

  • Dim-templated fixed-size kernels behind expression-templated front ends for the point-point, point-line, and point-edge distance functions and their gradients/Hessians, and for the normalization_* family (#249).

    • point_line_distance 8.2 β†’ 2.3 ns (3.5Γ—), point_edge_distance 18.1 β†’ 5.2 ns (3.5Γ—), point_point_distance_hessian up to 5Γ—, normalization_and_jacobian 3.4Γ—.

    • Mark small functions inline in the the header.

  • Recovering the compile-time dimension in the tangent, closest-point, relative-velocity, and area kernels is worth 1.5–4.8Γ— on the call site that dominates in practice (#249):

    Benchmark

    Before

    After

    Speedup

    point_edge_closest_point

    8.7 ns

    1.8 ns

    4.8x

    point_edge_closest_point, Vector3d

    4.7 ns

    1.7 ns

    2.8x

    point_edge_closest_point_jacobian

    14.9 ns

    6.2 ns

    2.4x

    point_point_relative_velocity

    5.5 ns

    1.4 ns

    3.9x

    point_point_relative_velocity_jacobian

    6.8 ns

    1.8 ns

    3.9x

    edge_length

    4.1 ns

    1.3 ns

    3.1x

    point_edge_tangent_basis

    7.1 ns

    4.2 ns

    1.7x

    point_triangle_tangent_basis

    7.7 ns

    5.0 ns

    1.5x

  • Branch once on the dimension in EdgeVertexCandidate::compute_distance_gradient/_hessian so the statically sized kernels are selected (3.1Γ— on the gradient).

  • Move all cold throw bodies in the distance dispatch functions out of line behind [[noreturn]] helpers; constructing the exception inline consumed the caller’s inlining budget (the single largest lever found: up to 2Γ— by itself).

Bug Fixes πŸ›ΒΆ

  • PSD-project the mollified Hessian block when the mollifier is zero (#244).

    • NormalPotential::hessian() early-returned the block \((\text{weight} \cdot f)\nabla^2 m\) for exactly parallel edges (\(m = 0\)) without projection, while every other path projects.

    • Positive weights leave the block PSD, so this was harmless until IMPROVED_MAX_APPROX introduced negative-weight collisions, which made the block negative-(semi)definite and the assembled β€œPSD-projected” Hessian non-PSD.

    • Because \(m = 0\) is a global minimum of the mollifier, \(\nabla^2 m\) is PSD and \(f(d) > 0\), so projecting the scalar weight is sufficient β€” no eigendecomposition needed.

Python 🐍¢

  • πŸ’₯ [Breaking] Rename the SmoothPotential class to SmoothContactPotential to match the C++ name (#247).

  • Fill gaps that made the GCP and convergent-formulation tutorials impossible to follow from Python (#247):

    • Add SmoothCollisions.compute_adaptive_dhat. Without it, adaptive dhat was unreachable even though build() accepts use_adaptive_dhat=True and requires this to be called first.

    • Add the SmoothContactParameters.adaptive_dhat_ratio property.

    • Add the BarrierPotential.stiffness and .use_physical_barrier properties, mirroring the C++ setters.

  • Validate preconditions in the bindings instead of relying on the C++ asserts, which are compiled out under NDEBUG and would let a release build silently accept a bad value (#247). BarrierPotential now raises ValueError for a non-positive or NaN dhat/stiffness and for a null barrier.

  • Bind edge_triangle_intersection(), returning an (intersects, u, v, t) tuple since Python has no out-parameters, and CollisionMesh.face_normals(), returning an (#F Γ— 3) array to match the other per-element accessors (#245). face_normals() raises ValueError on a 2D mesh rather than invoking undefined behavior.

DocumentationΒΆ

  • Update the tutorials to match the current API (#247). Every snippet is now verified: the C++ is extracted into a compile harness checked against the real headers, and the Python is run against a built ipctk.

    • ipc::point_triangle_ccd and the other free narrow-phase functions are now methods on ipc::NarrowPhaseCCD subclasses; <ipc/ccd/ccd.hpp> no longer exists.

    • The four *_nonlinear_ccd free functions are now ipc::NonlinearCCD methods.

    • CollisionStencil::ccd takes stencil vertices rather than (vertices, edges, faces); use dof() to gather them.

    • TangentialCollisions::build no longer takes barrier_stiffness β€” stiffness now comes from the normal potential. The stale call still compiled in C++, silently binding barrier_stiffness to mu_s and mu to mu_k.

  • Correct the note on conservative CCD (#247). ipc::TightInclusionCCD does not scale the returned time of impact in the normal path; it inflates the minimum separation the query stops at, capped at 1e-4, and only scales the TOI in the fallback taken when that query returns a TOI below SMALL_TOI. Because the cap usually binds, changing conservative_rescaling often has no effect at all.

  • Describe the narrow-phase alternatives accurately (#247).

    • InexactCCD is behind IPC_TOOLKIT_WITH_INEXACT_CCD, which is off by default, so it is now marked opt-in.

    • All three methods compute their margin as \(d_\min + (1 - r)(d_0 - d_\min)\); only ipc::TightInclusionCCD caps the second term, which is why it reports a time of impact closer to the exact one.

    • ipc::AdditiveCCD is over 100Γ— faster and reliable in practice; it does not account for rounding error in its distance computations, but the default 10% margin is large enough to avoid false negatives, at the cost of a less accurate time of impact and more false positives.

  • Add MeshFEM [Mohammadian et al., 2026] to the gallery.

RefactorΒΆ

  • Replace the duplicate squared-distance implementations in ipc/smooth_contact/distance/ (point_point_sqr_distance, point_line_sqr_distance, line_line_sqr_distance, edge_edge_sqr_distance, point_plane_sqr_distance, point_triangle_sqr_distance) with the now-templated functions from ipc/distance/.

MiscellaneousΒΆ

  • Add MeshFEMCore and MeshFEMSparse [Mohammadian et al., 2026] as dependencies, fetched with CPM (#246). Both are MIT licensed and build as small static targets β€” matrix data structures and assembly routines, without sparse direct solvers.

  • Take the distance_squared functor of the private AdditiveCCD::additive_ccd helper as a template parameter rather than a std::function (#247).

  • 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 (#248).

v1.6.0 (July 14, 2026)ΒΆ

HighlightsΒΆ

  • LBVH is now the default broad phase, replacing HashGrid. Combined with this release’s LBVH optimizations, it is roughly 2Γ— faster than the (now-removed) SimpleBVH and, because HashGrid scales poorly, several-fold faster (β‰ˆ6–8Γ— on large benchmark scenes) than the previous default (#212).

  • Add analytic plane-vertex collisions (#216).

  • Add anisotropic friction by @antoinebou12 (#210).

  • Add barrier stiffness (\(\kappa\)) to ipc::BarrierPotential and simplify the tangential API (#215).

  • Add composable collision filters (#235).

Broad PhaseΒΆ

  • Set the default broad phase to ipc::LBVH (#212).

    • LBVH outperforms the previous default (HashGrid) and all other methods across a range of scenes. On the benchmark scenes below it is ~1.5Γ— faster than SimpleBVH (the fastest existing method) at baseline; with this release’s pruning and bottom-up-build optimizations that grows to roughly 2Γ— faster than SimpleBVH and ~6–8Γ— faster than HashGrid.

    https://github.com/user-attachments/assets/7a15bef6-24cd-4b79-9fbd-079f4dd8e431

    Total broad-phase performance across methods; LBVH is roughly 1.5Γ— faster than the fastest existing method. Benchmarked on an Apple M2 Max (12 cores).ΒΆ

  • Remove the SimpleBVH dependency and the deprecated BVH broad phase (#213).

    https://github.com/user-attachments/assets/71cd90ce-4097-4a2d-a48a-11672029396e

    LBVH construction is more than 3Γ— faster than the removed BVH method. Benchmarked on an Apple M2 Max (12 cores).ΒΆ

  • Add rightmost-leaf pruning to LBVH self-collision traversal, skipping subtrees fully left of the query. 39% average speed-up in edge-edge traversal across benchmark scenes (#222).

    • Also fixes three bugs in the OGC edge-edge feasibility check.

  • Optimize LBVH construction with a single bottom-up pass [Apetrei, 2014], building the hierarchy and bounding boxes simultaneously instead of the two-pass build of Karras [2012]. Up to 10% faster to build (#230).

    https://github.com/user-attachments/assets/3f447f8f-210c-4873-8b32-965250b3ffa6

    Bottom-up [Apetrei, 2014] vs. two-pass [Karras, 2012] LBVH construction, benchmarked on an Apple M3 Pro (11 cores).ΒΆ

  • Refactor the AABB, HashGrid, and LBVH parallel loops to use tbb::parallel_for with index ranges directly (#228).

New Features πŸš€ΒΆ

  • πŸ’₯ [Breaking] Add barrier stiffness and simplify the tangential API in #215

    • Add a barrier stiffness \(\kappa\) to ipc::BarrierPotential: new constructors, member, and getter/setter, scaling the potential, gradient, and Hessian by \(\kappa\).

    • Remove the redundant normal_stiffness parameter from the tangential collision constructors and ipc::TangentialPotential interfaces, updating all call sites and Python bindings.

  • Add analytic plane-vertex collision support in #216

    • Add ipc::PlaneVertexCandidate and normal and tangential plane-vertex collisions, integrated into the collision builders.

    • Add ipc::CollisionMesh::planes (a list of Eigen::Hyperplane<double, 3>) to represent infinite analytic planes such as a ground plane, with Python bindings.

    • Remove the old implicits module.

  • Add anisotropic friction by @antoinebou12 in #210

    • Per-contact tangent-space velocity scaling and optional Erleben et al. [2019] β€œmatchstick” direction-dependent static/kinetic coefficients.

    • Direction-dependent coefficients are lagged: refresh with ipc::TangentialCollisions::update_lagged_anisotropic_friction_coefficients() after build and whenever the lagged state changes.

    • Default behavior remains isotropic. The directional model is active only in the 2D tangent space of 3D simulations.

    • Tutorial available here.

  • Implement the Gauss-Newton preconditioner from Shen et al. [2024] in #221

    • Add ipc::CollisionStencil distance-vector utilities (compute_distance_vector, compute_distance_vector_jacobian, and diagonal/Jacobian-contraction helpers).

    • Add cumulative ipc::NormalPotential Gauss-Newton routines (diagonal and quadratic form), parallelized with TBB.

    • Exposed in the Python bindings with unit tests.

  • Add the Planar Divide-and-Truncate (Planar-DAT) trust-region filter for OGC Chen et al. [2026] in #228

    • ipc::ogc::TrustRegion::planar_filter_step() is a direction-aware alternative to isotropic filtering: it computes a division plane per collision pair and truncates only motion toward the opposing primitive, reducing artificial damping and deadlock in dense-contact scenarios.

    • Available in both C++ and Python.

    • Tutorial available here.

  • Add composable collision filters in #235

    • New ipc::CollisionFilter (C++ and Python) wraps any bool(int, int) callable and composes via | (union), & (intersection), and ! (negation).

    • Factory functions for common cases: make_vertex_patches_filter, make_static_obstacle_filter, make_codim_cross_filter, and make_connected_components_filter.

    • The FAQ is rewritten to document the new system with C++ and Python examples.

  • Add support for nonmanifold smooth edges in #223

    • Generalize the Edge3 primitive and smooth_edge3_term (and its derivatives) to an arbitrary number of adjacent faces.

    • Change edges_to_faces from a fixed-size matrix to a vector of vectors and increase N_EDGE_NEIGHBORS_3D from 4 to 6.

API Changes πŸ”§ΒΆ

  • Configurable derivative layout in #217

    • Add a VERTEX_DERIVATIVE_LAYOUT constant to ipc/config.hpp and parameterize the gradient, sparse-gradient, Hessian-triplet, and Jacobian-triplet assembly helpers with an optional row- or column-major global ordering (defaulting to VERTEX_DERIVATIVE_LAYOUT).

  • πŸ’₯ [Breaking] Update the local 3rd-order tensor Jacobian layout in #219

    • Store 3rd-order tensors as matrices following the convention in β€œDynamic Deformables” [Kim and Eberle, 2022], easing tensor contractions in the chain rule.

    • Rename the relative-velocity API from *_matrix/*_matrix_jacobian to *_jacobian/*_dx_dbeta across C++, Python, and documentation.

  • πŸ’₯ [Breaking] Refactor the nonlinear CCD into a ipc::NonlinearCCD class in #218

    • Encapsulate the point-point, point-edge, edge-edge, and point-triangle nonlinear CCD methods, replacing the previous free-function API.

    • Update signatures to take Eigen::ConstRef and adjust the conservative-rescaling parameter handling.

Bug Fixes πŸ›ΒΆ

  • Use a relative PARALLEL_THRESHOLD in edge_edge_distance_type to correctly classify nearly-collinear coplanar edges, and add defensive guards for mollified collisions at \(d=0\); adds a regression test (#225).

  • Fix a 2D GCP bug caused by a trivially loose Edge2 active check by @udaykusupati in #227.

  • Skip the edge-edge planar filter for nearly-parallel edges with negligible approach velocity to avoid spurious truncation (#232).

  • Fix MSVC duplicate-symbol errors for PrimitiveDistance by adding explicit specialization declarations (#237).

  • Fix two bugs in the mollified edge-edge shape derivative (a wrong gradient factor and a missing outer-product term) by @Huangzizhou in #239.

Profiling ⏱️¢

  • Add fine-grained profiling instrumentation throughout, recording only on the main thread (#233).

  • Add an optional Tracy frame profiler via the IPC_TOOLKIT_WITH_TRACY CMake option (#234).

  • Record profiler data on the TBB arena coordinator thread rather than by main-thread ID (#236).

Python 🐍¢

  • Allow the thread limit to be set globally via the TBB_NUM_THREADS environment variable, applied on import of ipctk (#242).

  • Add the IPCTK_WITH_SIMD environment variable to disable SIMD in Python builds (#231).

MiscellaneousΒΆ

  • Replace the maybe_parallel_for wrapper with direct tbb::parallel_for and tbb::enumerable_thread_specific (#214).

  • Clean up the closest-point auto-generated code (#220).

  • Update GitHub Actions to the latest major versions (#224).

  • Disable pedantic and unneeded MSVC compiler warnings.

  • Strip notebook outputs and add an nbstripout pre-commit hook (#240).

  • Updated dependencies:

    • Bump finite-diff from v1.0.3 to v1.0.4

v1.5.0 (Febuary 5, 2026)ΒΆ

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.

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::ogc to encapsulate OGC-specific functionality.

    • Trust Region Implementation:

      • Added TrustRegion class (trust_region.hpp, trust_region.cpp) to manage per-vertex conservative bounds.

      • Implemented warm_start_time_step to initialize the trust region and handle initial predictions.

      • Implemented filter_step to scale optimization steps ensuring vertices stay within safe bounds.

      • Implemented update and update_if_needed to dynamically resize trust regions based on motion.

    • Feasible Region Logic:

      • Added feasible_region.hpp and feasible_region.cpp containing 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 NormalCollisions class to filter out invalid collision candidates. Enabled via set_collision_set_type(NormalCollisions::CollisionSetType::OGC).

    • Step Scaling: Unlike the original paper’s projection method, TrustRegion::filter_step scales 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 LBVH class in src/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.

      • Added python/examples/lbvh.py to demonstrate usage and visualization.

    • ⚑ Enhancements

      • Performance Optimizations:

        • Added DefaultInitAllocator to reduce overhead when allocating large arrays of POD types.

        • Replaced std::vector<AABB> with std::vector<AABB, DefaultInitAllocator<AABB>>.

        • Memory Optimization:

          • Switched AABB::min and AABB::max from ArrayMax3d to Eigen::Array3d.

          • Result: Reduces sizeof(AABB) from 76 to 64 bytes, allowing AABB to fit into a single cache line (assuming 64-byte lines).

        • Replaced hardware rounding in AABB::conservative_inflation with software rounding using std::nextafter.

    • πŸ’₯ Breaking Changes

      • API & Structural Changes:

        • Moved dimension variable: Removed dim from AABB and moved it to BroadPhase to handle 2D/3D data more cleanly. dim is now set in BroadPhase::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_3D in ipc/utils/eigen_ext.hpp to operate on Eigen::Array types instead of Eigen::Vector.

        • Deprecated BVH class in favor of the new LBVH class for better performance on large scenes.

  • Refactor BroadPhase to Build from Vertex Boxes Directly in #187

  • Rename sweep_and_tiniest_queue.cpp to .cu file by @iiiian in #203

  • Fix vertex id assignment by @iiiian in #204

    • Fix vertex id assignment logic in SweepAndTiniestQueue.

  • Replace optional const shared_ptr<BroadPhase>& parameters with BroadPhase* in #205

    • Change make_default_broad_phase to return a unique_ptr

  • Pass parameters to Scalable CCD Narrow-Phase by @antoinebou12 in #208

    • Replace hardcoded TightInclusionCCD::DEFAULT_TOLERANCE and TightInclusionCCD::DEFAULT_MAX_ITERATION with narrow_phase.tolerance and narrow_phase.tolerance if passed a TightInclusionCCD object.

    • If narrow_phase_ccd is not a TightInclusionCCD instance, we fall back to default values to preserve backward compatibility.

  • Add SIMD support via xsimd library in #207

    • Cross-platform SIMD (Single Instruction, Multiple Data) support using the xsimd library in the LBVH code.

    • Update the IPC_TOOLKIT_WITH_SIMD to 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.

Math and Geometry UtilitiesΒΆ

  • Add normal computation and Jacobian methods for collision candidates in #182

  • Collect normal utilities into geometry/normal files in #197

  • Organize geometry and math utilities into geometry and math folders 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.1 to 20260107.0

    • Bump Catch2 from v3.8.1 to v3.12.0

    • Bump Eigen from 3.4.0 to 5.0.1

    • Bump JSON from v3.11.2 to v3.12.0

    • Bump libigl from 89267b4a80b1904de3f6f2812a2053e5e9332b7e to v2.6.0

    • Bump TBB from v2022.1.0 to v2022.3.0

    • Bump Pybind11 from v2.13.1 to v3.0.1

    • Bump robin-map from v1.4.0 to v1.4.1

    • Bump spdlog from v1.15.3 to v1.17.0

  • Make most dependencies private

    • Added a figure for default dependencies of the ipc::toolkit library: https://ipctk.xyz/about/dependencies.html

    • Refactored BVH class to use unique_ptr to hide SimpleBVH

    • Updated Sweep and Prune and Sweep and Tiniest Queue classes to use a Pimpl pattern for encapsulation.

    • Mark tsl::robin_map and absl::hash as private dependencies in CMake. Update the dependency documentation accordingly.

    • Convert SpatialHash to PImpl idiom to hide tsl::robin_map and absl::hash from the public API.

  • Add Clang Tidy check

    • Added a .clang-tidy configuration 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.

  • Simplify CMake CUDA setup by @iiiian in #201 - Disable CUDA builds by default. - Bump CMake minimum version to 3.24 to support CMAKE_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_PROFILER CMake option to enable/disable profiling.

  • Refactor to use Eigen::ConstRef for vertices in #200

v1.4.0 (July 22, 2025)ΒΆ

HighlightsΒΆ

  • Add adhesion potentials for sticky interactions, allowing for more realistic simulations of contact between objects.

    • Based on the paper β€œAugmented Incremental Potential Contact for Sticky Interactions” by Fang et al. [2024]

  • Implement new barrier functions from the literature.

  • Add support for separate static and kinetic coefficients in tangential collisions.

What’s ChangedΒΆ

Python SpecificΒΆ

MiscellaneousΒΆ

  • Add /Wall and /MP compiler flags for MSVC in #134

  • Enable CUDA by default if CUDA is detected by CMake in #134

  • Devcontainer by @antoinebou12 in #136

  • Update dependencies for CMake 4.0 in #158

  • Organize folder structure for generated Xcode project in #159

    • Refactor CMake configurations and improve project structure

    • Updated CMake recipes for third-party libraries to set appropriate folder properties for IDE organization.

    • Changed the CPMAddPackage references for scalable-ccd to a more recent commit.

    • Enhanced logging functionality by adding a new log_and_throw_error function to improve error handling.

    • Improved documentation in the style guide for naming conventions.

    • Move generated config.hpp file from src/ipc to build/include/src/ipc

    • Update CUDA builds in CMakePresets.json

    • Remove virtual tag from ipc::BroadPhase::detect_collision_candidates()

  • Index typedef in #161

    • Add a index_t typedef for vertex/edge/face ids. Changes default from long to int32_t.

  • Update Tight Inclusion package version to 1.0.6 in #165

  • Fix cmake for non-top-level inclusion by @sin3point14 in #167

  • Improve and clean up documentation:

    • Fix Error in Docs in #169

    • Update docs in #173

    • Update docs.yml in #174

    • Refactor and clean-up C++ API docs in #175

v1.3.1 (Nov 08, 2024)ΒΆ

  • Move test data to an external repository in #113

    • Download test data at compile time as needed using CMake

  • Individual convergent formulation flags in #120

    • Replace the use_convergent_formulation flag in Collisions with two flags: use_area_weighting and use_improved_max_approximator.

    • Move the physical barrier rescaling from collision weights into the BarrierPotential using a flag use_physcial_barrier.

  • Replace scalar tbb::enumerable_thread_specific with tbb::parallel_reduce in #121

  • Fix missing max_iterations and tolerance variables in compute_collision_free_stepsize when using SWEEP_AND_TINIEST_QUEUE by @antoinebou12 in #123

  • Add cuda.yml to test if the code compile with CUDA enabled in #125

  • Update filib to allow shared library build in #122

  • Fix friction_collisions.build tutorial (Issue #126) in #127

  • Sort includes using clang-format in #129

  • Add frequently asked questions page to the tutorial documentation

  • Fix barrier API documentation

  • On Apple, link Eigen against Accelerate as a BLAS/LAPACK backend

    • Requires brew install lapack to install LAPACKE headers

v1.3.0 (Aug 03, 2024)ΒΆ

  • Separated the collision set and potential computations. This allows us to more easily add new potentials in the future. This will require updating calls to compute_potential_*. See the tutorial for details.

  • Add a Barrier class to enable dynamic selection of barrier function.

  • Add a NarrowPhaseCCD class to enable dynamic selection of narrow-phase CCD method.

DetailsΒΆ

  • Refactor potentials in #83

    • Replace β€œconstraint” and β€œcontact” names with β€œcollision”

    • Removed compute_potential_* from Collision and Collisions

    • Add a new class hierarchy Potential which represents computing the sum of individual potentials per collision

      • Implement the barrier potential and friction dissipative potential as Potentials: BarrierPotential and FrictionPotential

    • Now, Collisions serve solely as the set of active collisions

    • Add the distance mollifier to all collisions with a is_mollified() function

      • The default mollifier is $m(x) = 1$, and only EdgeEdgeCollision overrides this

    • Remove versions of compute_distance and ccd from CollisionStencil which take the full mesh as input

      • Instead, expose the versions that take the collision stencil’s vertex positions directly

  • Polymorphic barrier in #84

    • Make the barrier function an object so it can be changed at runtime

    • Add a virtual class Barrier as an interface for generic barriers

    • Add ClampedLogBarrier class which implements the smoothly clamped log barrier functions from [Li et al. 2020]

    • barrier_gradient and barrier_hessian renamed to barrier_first_derivative and barrier_second_derivative respectively

    • Co-authored by @arvigj

  • Update compiler warnings in #88

    • Add -Werror=enum-conversion and -Wfloat-conversion

  • Fix πŸ› hash when not using Abseil in #90

  • Clean-up SpatialHash Broad Phase in #91

    • Replace IPC_TOOLKIT_WITH_CORRECT_CCD with IPC_TOOLKIT_WITH_INEXACT_CCD

      • Always include Tight Inclusion CCD because it is used by Nonlinear CCD

    • Add support for face-face collision (not used anywhere but for completeness and future-proof nonlinear face-face)

    • Add and use generic functions to SpatialHash

    • Replace camelCase with snake_case in SpatialHash and HashGrid

  • Update Scalable CCD in #92

    • Updated Scalable CCD (i.e., Sweep and Tiniest Queue and CUDA Tight Inclusion CCD) to the unified repository with support for generic collision pairs.

    • Renamed SWEEP_AND_TINIEST_QUEUE to SWEEP_AND_PRUNE to reflect that it is a standard implementation of the sweep and prune algorithm (see, e.g., β€œReal-Time Collision Detection” [Ericson 2004])

    • Renamed SWEEP_AND_TINIEST_QUEUE_GPU to SWEEP_AND_TINIEST_QUEUE to reflect that it is the only existing implementation of the sweep and tiniest queue algorithm

  • Mark single argument constructors explicit in #93

    • Mark BarrierPotential(double) and FrictionPotential(double) as explicit constructors to avoid implicit conversions from double

  • Fix compatibility with the latest Eigen by @teseoch in #94

  • Add clang-format check action in #96

  • Add new project PSD option by @Huangzizhou in #95

    • Instead of clamping the negative eigenvalues to zero, add the option to flips the sign of negative eigenvalues according to [Chen et al. 2024]

  • Fix πŸ› Python bindings for Numpy 2 in #100

  • Make faces an optional parameter to CollisionMesh in #105

  • Fix Python documentation by @rc in #108

  • Polymorphic CCD in #110

    • Add narrow phase CCD parent class; pass CCD object to choose method

    • Replace tolerance and max_iterations parameters with const NarrowPhaseCCD& narrow_phase_ccd parameter

    • NarrowPhaseCCD is a virtual class containing the CCD methods for point-point, point-edge, edge-edge, and point-triangle CCD

    • NarrowPhaseCCD is implemented by InexactCCD, TightInclusionCCD, and AdditiveCCD classes

    • [Breaking] The optional parameter order to is_step_collision_free and compute_collision_free_stepsize is changed from

      const BroadPhaseMethod broad_phase_method = DEFAULT_BROAD_PHASE_METHOD,
      const double min_distance = 0.0,
      const double tolerance = DEFAULT_CCD_TOLERANCE,
      const long max_iterations = DEFAULT_CCD_MAX_ITERATIONS);
      

      to

      const double min_distance = 0.0,
      const BroadPhaseMethod broad_phase_method = DEFAULT_BROAD_PHASE_METHOD,
      const NarrowPhaseCCD& narrow_phase_ccd = DEFAULT_NARROW_PHASE_CCD);
      
    • The inexact floating-point CCD can be enabled beside the Tight Inclusion CCD rather than replacing it

v1.2.1 (Jul 12, 2024)ΒΆ

Bug fixes πŸ› :

  • Update Pybind11 to support Numpy 2.0. Fixes segmentation fault as described in #102.

v1.2.0 (Dec 11, 2023)ΒΆ

Various new features πŸš€ and some bug fixes πŸ›.

  • Implement the improved max approximator as described in [Li et al. 2023]

  • Add a port of the Additive CCD method from [Li et al. 2021]

  • Add a generic implementation of the nonlinear CCD (of linear geometry) algorithm from [Ferguson et al. 2021]

  • Add missing codimensional collision support (point-point and point-edge)

DetailsΒΆ

  • Update website URL to ipctk.xyz in #54

  • Simplify tangential basis Jacobian calculation thanks to @halehOssadat and @jpanetta in #56

  • Update FindSIMD.cmake to now add support for Neon (Arm/Apple Silicon SIMD instruction set) in #58

  • Improve the max approximator used (i.e., sum over constraints) as described in [Li et al. 2023] in #55

    • Add a dtype to EE collisions to keep track of the distance type for mollified constraints

    • Initialize mesh adjacencies by default

    • Use edge length as the area weighting for codimensional edges

  • Improve documentation and tutorials in #61

    • Add documentation describing the convergent formulation

    • Add documentation describing the constraint offset/minimum distance

    • Add documentation for broad- and narrow-phase CCD

    • Add documentation for High-Order IPC

    • Also, renames CollisionConstraint::minimum_distance to CollisionConstraint::dmin

  • Add a port of the Additive CCD method from [Li et al. 2021] in #62

    • This is a modified version of the original open-source implementation which is under the Appache-2.0 License.

    • Modifications: remove broad phase functions, refactor code to use a single implementation of the additive_ccd algorithm, utilize our distance function rather than porting the Codim-IPC versions, return true if the initial distance is less than the minimum distance, and add an explicit tmax parameter rather than relying on the initial value of toi.

    • This is mostly for reference comparison and it is not integrated into the full code. This also includes the ability to pull the sample CCD queries and run them in a unit-test (requires GMP).

    • This adds missing feature mentioned in #63

  • Add Codecov to get a report of unit test code coverage in #64

    • Add more tests to improve code coverage and fix small bugs in #65

  • Fix the symmetric matrix assertion in project_to_psd and project_to_pd in #67

  • Handle codim. point-point collisions in #66

    • This adds missing feature as discussed in #63

  • Add tests of Python bindings using nose2 in #69

  • In CCD, check the initial distance when no motion occurs in #71

  • Add a generic implementation of the nonlinear CCD (of linear geometry) algorithm from [Ferguson et al. 2021] in #72

    • Generic nonlinear trajectories are specified through a NonlinearTrajectory virtual class. By default the maximum distance between the trajectory and a linearized version is computed using interval arithmetic. That is

      \[\begin{split}\max_{t \in [0, 1]} \Vert p(\mathrm{lerp}(t_0, t_1, t)) - \mathrm{lerp}(p(t_0), p(t_1), t) \Vert_2 \\ \leq \sup(\Vert p([t_0, t_1]) - \mathrm{lerp}(p(t_0), p(t_1), [0, 1]) \Vert_2)\end{split}\]

      where \(p\) is the point’s position over time, \(\mathrm{lerp}(a, b, t) := (b - a) t + a\) and \(\sup([a,b]):=b\). Because this can be an overly conservative approximation, users can override the NonlinearTrajectory::max_distance_from_linear function to compute the max directly in closed form, if known.

    • We perform interval arithmetic using filib which has been shown to be β€œthe only library that is correct, consistent, portable, and efficient” [Tang et al. 2022].

    • Add a nonlinear CCD tutorial to the docs in #78

  • Add additional compiler warnings and resolve them to be warning-free in #73

  • Add Python bindings for igl::predicate::segment_segment_intersect in #74

  • Integrate SimpleBVH as a broad-phase method in #75

  • Fix the shape derivative of mollified edge-edge contact in #76

    • Additionally, this makes the shape derivative computation object-oriented.

  • Update Python bindings with recent changes and unified comments in #77

  • Add support for collision between codimensional edges and points in 3D in #79

    • Implements missing features discussed in #63.

v1.1.1 (Aug 18, 2023)ΒΆ

  • Logo by @zfergus in #52

  • Fix vertex-vertex == and < functions to be order independent

    • This allows vertex-vertex constraints merge correctly

  • Update Tight Inclusion CCD

v1.1.0 (Jul 25, 2023)ΒΆ

Large refactoring to make the code more object-oriented rather than passing objects to functions. Other changes include the friction potential now being a function of velocity, bug fixes, and a new tutorial.

DetailsΒΆ

  • Large Refactor in #25

    • construct_collision_candidates(..., candidates) β†’ candidates.build(...)

    • is_step_collision_free(candidates, ...) β†’ candidates.is_step_collision_free(...)

    • compute_collision_free_stepsize(candidates, ...) β†’ candidates.compute_collision_free_stepsize(...)

    • compute_barrier_potential*(constraints, ...) β†’ constraints.compute_potential*(...)

    • compute_shape_derivative(constraints, ...) β†’ constraints.compute_shape_derivative(...)

    • compute_minimum_distance(constraints, ...) β†’ constraints.compute_minimum_distance(...)

    • construct_friction_constraint_set(..., friction_constraints) β†’ friction_constraints.build(...)

    • compute_friction_*(..., friction_constraints, ...) β†’ friction_constraints.compute_*(...)

    • Generic CollisionStencil parent class to Candidates, CollisionConstraints, and FrictionConstraints.

    • Renamed Constraints to CollisionConstraints

    • Replaced single letter variable names V, E, F with vertices/positions, edges, faces

    • Renamed *_index β†’ *_id

    • Replaced inflation_radius = min_distance / 1.99 with inflation_radius = min_distance / 2 and use rounding mode to conservativly inflate AABBs

    • CollisionConstraints::use_convergent_formulation and are_shape_derivatives_enabled must now be accessed through getter and setter functions

    • Friction potentials are now functions of velocity. Previously V0 and V1 were passed and U = V1-V0. This limited the integration scheme to implicit Euler. Upstream this means you need to multiply the potential by \(1/(dv/dx)\) to get the correct friction force.

      • Change input \(\epsilon_vh\) to \(\epsilon_v\) in #37 to reflect the fact that friction is defined in terms of velocity instead of displacement now.

  • Changed default project_hessian_to_psd to false in #30

  • Update website with a tutorial (#31) and version dropdown list (#34)

  • Switch from templates to using Eigen::Ref in #28

  • Speed up the CCD by limiting the maximum minimum distance to 1e-4 in #43

  • Fix the bug pointed out in #41 in #42. Namely, to get units of distance in the barrier we should divide the original function by \(\hat{d}\cdot(\hat{d} + 2d_{\min})^2\) when using distance squared. Before it was being divided by \(2d_{\min} \hat{d} + \hat{d}^2\).

  • Fix build for IPC_TOOLKIT_WITH_CORRECT_CCD=OFF in #44

  • Switched from FetchContent to CPM in #48. This provides better caching between builds. Additionally, made robin-map and Abseil optional dependencies.

  • Add the CFL-Inspired Culling of CCD as described in Section 3 of the Technical Supplement to IPC in #50

v1.0.0 (Feb 21, 2023)ΒΆ

This is the first official release. πŸš€

This is a stable release of the toolkit prior to refactoring the code and making updates to the API.

DetailsΒΆ

  • Added a minimum distance optional parameter to all CCD functions (const double min_distance = 0.0) in #22. This is placed as the first optional argument which can break calling code if optional parameters were previously used.

  • Added CollisionMesh in #7 to wrap up face and edges into a single data structure.

    • Removes Support for ignoring internal vertices. Instead, users should use the CollisionMesh to map from the full mesh to the surface mesh.

    • This also includes a to_full_dof function that can map the reduced gradient/hessian to the full mesh’s DOF.

Pre-v1.0.0ΒΆ

2021-10-05 (9e2cc2a)ΒΆ

AddedΒΆ

  • Added implicits source folder to organize point-plane collisions

2021-09-05 (9e2cc2a)ΒΆ

AddedΒΆ

  • Added support for point vs. (static) analytical plane contact

2021-08-21 (acf2a80)ΒΆ

ChangedΒΆ

  • Changed CMake target name to ipc::toolkit

2021-07-26 (1479aae)ΒΆ

ChangedΒΆ

  • Updated the CMake system to use modern FetchContent to download externals

2021-07-22 (e24c76d)ΒΆ

FixedΒΆ

  • Updated CCD strategy when using Tight Inclusion to only perform no_zero_toi=true when there is no minimum distance

2021-07-17 (a20f7a2)ΒΆ

AddedΒΆ

  • Added detect_edge_face_collision_candidates_brute_force for 3D intersection broad-phase

  • Added ability to save an obj of collision candidates

  • Added tests for has_intersection (all pass after fixes)

FixedΒΆ

  • Fixed possible numerical rounding problems in HashGrid AABB::are_overlapping

  • Fixed HashGrid’s function for getting edge-face intersection candidates

2021-07-15 (7301b42)ΒΆ

FixedΒΆ

  • Use ignore_codimensional_vertices in the brute force broad-phase method

  • Fixed AABB inflation in brute force and SpatialHash methods

2021-07-08 (86ae4e5)ΒΆ

ChangedΒΆ

  • Replaced vertex group ids with more powerful can_collide function. By default everything can collide with everything (same as before)

  • Reordered parameters in construct_constraint_set(), is_collision_free(), and compute_collision_free_stepsize()

  • update_barrier_stiffness now requires the constraint_set rather than building it

  • update_barrier_stiffness dropped dhat parameter

FixedΒΆ

  • SpatialHash for 2D

RemovedΒΆ

  • Verison of initial_barrier_stiffness that computes the constraint set and barrier gradient because there are a lot of parameters to these functions

2021-07-05 (4d16954)ΒΆ

ChangedΒΆ

  • Renamed directory src/spatial_hash/ β†’ src/broad_phase/

  • Renamed files src/ccd/broad_phase.* β†’ src/ccd/aabb.*

2021-07-05 (b3808e1)ΒΆ

AddedΒΆ

  • Select the broad-phase method for CCD and distance constraints

    • Methods: HASH_GRID, SPATIAL_HASH, BRUTE_FORCE

  • CCD parameters for Tight Inclusion’s tolerance and maximum iterations

ChangedΒΆ

  • ignore_codimensional_vertices to false by default

  • CMake option TIGHT_INCLUSION_WITH_NO_ZERO_TOI=ON as default

2021-06-18 (aa59aeb)ΒΆ

ChangedΒΆ

  • construct_friction_constraint_set now clears the given friction_constraint_set

2021-05-18 (245b13b)ΒΆ

ChangedΒΆ

  • Use TightInclusion degenerate edge-edge for point-point and point-edge CCD

2021-05-11 (5c34dcd)ΒΆ

ChangedΒΆ

  • char* exceptions to std::exceptions

2021-05-06 (24056cc)ΒΆ

ChangedΒΆ

  • Gave dhat_epsilon_scale a default value of 1e-9 in update_barrier_stiffness

  • warning:

    Changed order of parameters to update_barrier_stiffness

    • Flipped bbox_diagonal and dhat_epsilon_scale

2021-05-06 (81d65f3)ΒΆ

FixedΒΆ

  • Bug in output min distance of update_barrier_stiffness

2021-05-04 (59ec167)ΒΆ

ChangedΒΆ

  • Moved eigen_ext functions into ipc namespace

  • Renamed max size matrices with Max

    • Eigen::VectorX([0-9]) β†’ ipc::VectorMax$1

    • Eigen::MatrixXX([0-9]) β†’ ipc::VectorMax$1

    • Eigen::ArrayMax([0-9]) β†’ ipc::ArrayMax$1

2021-05-03 (664d65f)ΒΆ

AddedΒΆ

  • Added utility function to check for edge-edge intersection in 2D and edge-triangle intersection in 3D.

  • Optionally: use GMP for exact edge-triangle intersection checks

2021-05-03 (9b4ebfc)ΒΆ

AddedΒΆ

  • voxel_size_heuristic.cpp which suggests a good voxel size for the SpatialHash and HashGrid

ChangedΒΆ

  • Changed HashGrid voxel size to be the average edge length not considering displacement length. This results in better performance, but can result in large memory usage.

2021-04-29 (293d0ad)ΒΆ

AddedΒΆ

  • Added TBB parallel loops to the main function (compute_potential, compute_friction_potential, compute_collision_free_stepsize, etc.)

  • Added function addVerticesFromEdges that adds the vertices connected to edges in parallel and avoids duplicates

ChangedΒΆ

  • Changed the HashGrid to use ArrayMax3 over VectorX3 to simplify the code

FixedΒΆ

  • Fixed some parameters that were not by reference

2021-04-21 (c8a6d5)ΒΆ

AddedΒΆ

  • Added the SpatialHash from the original IPC code base with some modification to get all candidates in parallel

    • Benchmark results indicate this SpatialHash is faster than the HashGrid with multithreading

    • TODO: Improve HashGrid or fully integrate SpatialHash into ipc.hpp

2021-02-11 (9c7493)ΒΆ

ChangedΒΆ

  • Switched to the correct (conservative) CCD of Wang et al. [2021]

    • Can select Etienne Vouga’s CCD in the CMake (see README.md)

2021-02-01 (b510253)ΒΆ

AddedΒΆ

  • Added minimum seperation distance (thickness) to distance constraints

    • Based on β€œCodimensional Incremental Potential Contact” [Li et al., 2021]

2021-02-01 (a395175)ΒΆ

AddedΒΆ

  • Added 2D friction model based on the 3D formulation.

    • TODO: Test this further

2021-01-12 (deee6d0)ΒΆ

AddedΒΆ

  • Added and optional parameter F2E to construct_constraint_set(). This is similar to F (which maps faces to vertices), but maps faces to edges. This is optional, but recommended for better performance. If not provided a simple linear search will be done per face edge!

    • TODO: Add a function to compute this mapping.

2021-01-09 (deee6d0)ΒΆ

ChangedΒΆ

  • Replaced VectorXd and MatrixXd with static size versions for local gradient and hessians

ChangedΒΆ

  • Removed TBB parallelization form the hash grid because we get better performance without it.

    • TODO: Improve parallelization in the hash grid or switch to the original IPC spatial hash

2020-11-06 (4553509)ΒΆ

FixedΒΆ

  • Fixed multiplicity for point-triangle distance computation to avoid duplicate point-point and point-edge pairs.

2020-10-22 (51f4903)ΒΆ

FixedΒΆ

  • Projection of the hessian to PSD. This was completely broken as the projected matrix was never used.

2020-10-22 (9be6c0f)ΒΆ

FixedΒΆ

  • Mollification of EE constraints that have a distance type of PP or PE

  • If there is no mollification needed then the PP and PE constraints are stored with multiplicity

  • Set the parallel EE friction constraint threshold to eps_x like in IPC

    • This avoid needing the mollification for the normal force and these forces are small anyways

2020-10-10 (cb8b53f)ΒΆ

FixedΒΆ

  • Assertions in compute_collision_free_stepsize

2020-10-10 (4a5f84f)ΒΆ

FixedΒΆ

  • Point-triangle distance type by replacing it with the one used in the original IPC code

2020-10-10 (1d51a61)ΒΆ

AddedΒΆ

  • Boolean parameter in compute_friction_potential_hessian that controls if the hessian is projected to PSD

2020-10-09 (b737fb0)ΒΆ

AddedΒΆ

  • Parameter for vertex group IDs to exclude some collisions (e.g., self collisions)

2020-10-08 (6ee60ae)ΒΆ

AddedΒΆ

  • Second version of update_barrier_stiffness() that takes an already computed minimum distance and world bounding box diagonal

2020-10-08 (cc3947d)ΒΆ

AddedΒΆ

  • Second version of initial_barrier_stiffness() that takes an already computed barrier gradient

  • Assertions on initial_barrier_stiffness() input

    • average_mass > 0 && min_barrier_stiffness_scale > 0

ChangedΒΆ

  • Fixed typo in initial_barrier_stiffness() name (was intial_barrier_stiffness())

2020-10-07 (5582582)ΒΆ

AddedΒΆ

  • FrictionConstraint structures to store friction information (i.e., tangent basis, normal force magnitude, closest points, and coefficient of friction)

  • Unit test that compares the original IPC code’s friction components with the toolkit’s

ChangedΒΆ

  • compute_friction_bases() is now construct_friction_constraint_set()

    • It now takes the coefficient of friction (mu)

    • It now puts all information inside of the FrictionConstraints (friction_constraint_set)

2020-10-06 (b48ba0e)ΒΆ

ChangedΒΆ

  • During construct_constraint_set() the constraints are added based on distance type

    • Duplicate vertex-vertex and edge-vertex constraints are handled by a multiplicity multiplier

    • Edge-edge constraints are always line-line distances

    • Point-triangle constraints are always point-plane distances

2020-10-05 (9a4576b)ΒΆ

FixedΒΆ

  • Fixed a bug in the point-triangle closest points and tangent basis computed in compute_friction_bases()

  • Fixed a bug in edge_edge_tangent_basis() used to compute the tangent basis for friction

2020-09-19 (31a37e0)ΒΆ

AddedΒΆ

  • spdlog for logging information

2020-09-19 (acb7664)ΒΆ

ChangedΒΆ

  • Headers are now include with the prefix ipc/

    • E.g., #include <ipc.hpp> β†’ #include <ipc/ipc.hpp>

2020-09-04 (7dd2ab7)ΒΆ

AddedΒΆ

  • Collision constraint to store distance constraint pairs

    • EdgeEdgeConstraint stores the edge-edge mollifier threshold (eps_x)

ChangedΒΆ

  • Input parameter dhat_squared is now dhat (i.e., non-squared value)

  • Input parameter epsv_times_h_squared is now epsv_times_h (i.e., non-squared value)

  • Constraints replaced Candidates

  • construct_constraint_set() now takes the rest vertex position (V_rest)

  • compute_barrier_potential*() no longer take the rest vertex position