Repository navigation
Conversation
- Added InertialTerm class for computing energy, gradient, and Hessian of rigid bodies. - Implemented mass properties computation for 2D and 3D meshes, including point clouds. - Created pose representation with rotation vector and matrix conversions. - Developed RigidBodies class to manage multiple rigid bodies from mesh data. - Implemented ImplicitEuler time integrator for updating positions and velocities. - Added unit tests for mass properties and pose transformations using Catch2 framework.
- Updated finite-diff package from version 1.0.1 to 1.0.3 in CMake configuration. - Remove template from Pose. - Modified RigidBody and related classes to use the updated Pose structure. - Added unit tests for RigidBody construction and transformations.
- Update CPM to 0.42.0 - Add TinyGLTF dependency - Rename save_obj to write_candidates_obj - Add write_gltf
…_throw_error for consistency
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #184 +/- ##
==========================================
- Coverage 96.97% 96.25% -0.73%
==========================================
Files 221 264 +43
Lines 22426 25883 +3457
Branches 1540 1976 +436
==========================================
+ Hits 21748 24913 +3165
- Misses 678 970 +292
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…in normal collisions test (#185)
- Introduce new overloads for build methods across various classes, allowing for the use of precomputed AABBs. - Update related documentation and ensure consistent handling of vertex boxes and edges. - Improve voxel size suggestion logic based on bounding box dimensions.
… function signatures
…ment collision detection methods
…eCCD Replace the direct Tight-Inclusion calls in the piecewise-linear driver with calls through a stored NarrowPhaseCCD (set_narrow_phase_ccd; default TightInclusionCCD). A new NarrowPhaseCCD::component_mode flag, set by NonlinearCCD, tells the narrow phase it is a component of the piecewise driver, which supplies its own conservative margins: - TightInclusionCCD bypasses its standalone ccd_strategy (no minimum- separation inflation, small-TOI rerun, or rescaling) and forwards the driver's per-piece cm_no_zero_toi hint (true on the first piece), a new trailing parameter on the NarrowPhaseCCD interface - AdditiveCCD uses COMPONENT_CONSERVATIVE_RESCALING = 0.99 (a raw TOI never terminates since its advancement gap is (1-cr) x initial gap), honors cm_no_zero_toi by halving the minimum separation until the initial distance clears it, and logs expected within-separation returns at trace level - NonlinearCCD's tolerance/max_iterations move to the TightInclusionCCD component; conservative_rescaling stays (used by the driver and the plane-vertex CCD) - demo: rigid mode uses AdditiveCCD per piece (bolt scene: 0.50 s vs 0.65 s with Tight Inclusion vs 8.45 s original Rigid IPC, 20 steps; identical trajectories, intersection-free) - python: NarrowPhaseCCD hierarchy switches to shared_ptr holders; NonlinearCCD.narrow_phase_ccd is a property whose setter enforces component_mode Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add IPC_TOOLKIT_BUILD_DEMO using main's unforced option pattern - Keep the dynamics/demo Python bindings alongside the deprecated GCP-name __getattr__ - Keep AdditiveCCD::handle_initial_proximity with the templated additive_ccd - Take main's MSVC warning variable and newer tests-data commit - Drop unordered_map_and_set.cpp (header-only on main) and save_obj (replaced by write_candidates_obj on dynamics) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Project each contact's rigid-DOF Hessian block to PSD, as in Rigid IPC - Add fixed-size single-vertex Pose Jacobian and Hessian - Restore position-rotation coupling in RigidToAffine::apply_hessian - Add Simulator minimum_separation_distance; default use_area_weighting to false - Skip candidates between bodies that are both non-dynamic - Add unique rigid body names with name lookup - Expose num_contacts, last_momentum_balance, and a writable external_force in Python Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Trim read_gltf/write_gltf to geometry and node names - Take per-body DOF masks in read_gltf, keyed by unique body name - Add RigidBody::set_density and RigidBodies::make_unique_names - Load a settings .py with configure(scene) in rigid.py - Enable glTF and CUDA in the python preset and find its module Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Use a double pi in Pose::clamp_rotation_to_pi (-Werror=float-conversion) - Cast glTF buffer values to float explicitly - Keep polysolve's unused CuSolverDN.cu and bare /utf-8 away from nvcc - Raise the CTest per-test timeout for the slow ESP test on Windows Debug Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Set the second moment of bodies with two rotation DOFs fixed - Apply external torques as the world torque at any orientation - Pass the CCD component mode per call instead of mutating the shared narrow phase - Keep the old NonlinearCCD constructor and save_obj as deprecated overloads, and old Python CCD overrides working - Read glTF node hierarchies, matrix transforms, and multiple or unindexed primitives; write faceless bodies as lines or points - Make the joint reduction sparse and reject invalid or late joints - Fix the BDF::dvdx history index and the FILIB-off sinc build - Add a shared ipc::PI and rename getters to lower_case - Fix the CPM OPTIONS syntax in the polysolve recipe Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zfergus
marked this pull request as ready for review
October 25, 2026 16:18
polysolve's grad_norm_tol is absolute, so at the old 1e-6 default it accepted the spolling coin's unconverged steps after one Newton iteration. It now defaults to 0 while velocity_conv_tol > 0, and to 1e-6 otherwise; an explicit setting still wins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Simulator::step() built the friction set after re-seeding the barrier stiffness, so the lagged normal forces were scaled by κ_new/κ_prev (0.01x to 42x per step on the card house). Building it first, as Rigid IPC does, removes the card house's iteration-limit failures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add LBVH::Leaves so RigidCandidates::build no longer builds a temporary tree per body pair - Replace the LBVH-vs-LBVH queries with LBVH-vs-Leaves overloads - Test the leaves queries against a brute-force box-overlap reference - Fill in missing Doxygen parameter docs in dynamics and ESP headers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # src/ipc/esp/collisions/esp_collision_dict.hpp # src/ipc/esp/esp_collisions_builder.hpp # src/ipc/esp/esp_parameters.hpp # src/ipc/esp/quadrature_potential.cpp # src/ipc/esp/quadrature_potential.hpp
- Add Settings::momentum_balance_tol, defaulting to the old fixed 1e-2 - Expose it in the Python bindings and document it in the README Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Targets were built from the velocity reached last step, so every step that fell short of its target slowed the body down for good. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Weigh the penalty against inertia and scale only the multipliers by (βΔt)², so λ is the constraint's reaction force - Keep the multipliers across steps (torque part only for λ_A) and reset them when a body's driver changes or it stops being kinematic - Double the penalty when progress stagnates short of the target - Snap affine rotations to SO(3) before converting to rigid poses Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AL updates fold any unbalanced force into the multipliers, so they need an iterate near equilibrium; on stiff contact the velocity criterion stops well short of that - The kinematic body then overshoots, the penalty escalates, and tight mechanisms (e.g., 02-piston's crank pin) wedge shut - Scale the Δx criterion by 0.1 until every target is met Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- RigidBody, RigidBodies, and read_gltf take an optional prescribed center of mass; the body's pose and rotation then refer to that point - The inertia moves there by the parallel axis theorem, which is exact for static and kinematic bodies - read_gltf takes the centers in world coordinates, keyed by body name - rigid.py reads `center_of_mass` from a scene's settings script Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A stale reaction from the previous step can push a kinematic body the wrong way (e.g., a crank at dead center) and wedge a tight mechanism; Rigid IPC also starts every step from zero multipliers - Remove the carry-over, its torque projection, the fold on satisfaction, and reset_multipliers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Tightening the whole solve cost about 3x Rigid IPC's Newton iterations on the piston, since its pins spin freely and the last digits come slowly - Matches Rigid IPC, whose convergence test also requires the kinematic targets to be met Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The early exit tested the distance at the already-accepted ti0, so the first Newton steps could close ~90% of a gap and wedge kinematic scenes (piston, bike chain). Each piece's linear CCD now stops at min_distance + (1 - s)(d0 - min_distance), inflated by the linearization error, matching standalone Additive CCD. - Subdivide while the linearization error swallows the slack above the target - Update tests that assumed the CCD stops near contact Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Average mass over free DOFs so heavy static or DOF-locked bodies don't inflate κ - Keep κ across augmented Lagrangian updates; re-seed only for a friction re-lag - Tighten the 2D friction slide's velocity tolerance to 1e-4 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds rigid and affine body dynamics as reusable library components (
src/ipc/dynamics/), glTF scene I/O (src/ipc/io/), and a demo simulator (demo/) that assembles them, touching CCD, the LBVH broad phase, and the Python bindings along the way.Mechanism
ipc::rigid—Pose,RigidBody, andRigidBodies(aCollisionMeshof all bodies, built from per-body meshes). Each body is re-centered on its center of mass and expressed in its principal frame. This follows Rigid IPC (Ferguson et al. 2021).ipc::rigid::RigidCandidates— finds body pairs with a bounding-sphere broad phase, then queries each pair with two-tree LBVH queries in one body's rest frame. Narrow-phase CCD follows the curved rigid trajectories throughNonlinearCCD, with a conservative bound on how far each piece strays from its chord.ipc::affine— the body terms are written once in affine coordinates y = [p; vec(A)]:InertialTerm,BodyForces,OrthogonalityPotential, anAugmentedLagrangianthat drives kinematic bodies, and linearJointConstraints. This follows ABD (Lan et al. 2022), with joints as in Chen et al. 2022, §4.1.ipc::dynamics— aToAffinechange of variables lets the same terms serve both models.RigidToAffinemaps [p; θ] to A = R(θ);AffineToAffineis the identity.BodyPotentialssums the terms and applies the chain rule once, andBDFprovides orders 1–6.demo/(ipc_toolkit_demo, not part of the library) — a polysolve-basedSimulatorwith adaptive barrier stiffness, lagged friction, and static/kinematic bodies. It is exposed in Python asipctk.demo.Impact
NonlinearCCDcan now use anyNarrowPhaseCCDfor its per-piece linear CCD; the demo usesAdditiveCCD.IPC_TOOLKIT_WITH_GLTF=ON.API changes
IPC_TOOLKIT_BUILD_DEMO(ON at top level, OFF as a subproject) andIPC_TOOLKIT_WITH_GLTF(OFF).NarrowPhaseCCD: every query takes a trailingNarrowPhaseCCDMode mode = STANDALONE.COMPONENTandCOMPONENT_NO_ZERO_TOItell a method it is the per-piece CCD inside a piecewise driver, so it returns the raw time of impact. The mode is passed per call, so a shared narrow-phase object is never modified.NonlinearCCD: the constructor is nowNonlinearCCD(narrow_phase_ccd = nullptr, conservative_rescaling); null selects aTightInclusionCCD. Also new:set_narrow_phase_ccd()andnarrow_phase_ccd().LBVH: new two-tree queriesdetect_*_candidates(const LBVH& other, can_collide, candidates)between two separately built trees.CollisionMesh: the destructor andvertices(full_positions)are now virtual, soRigidBodiescan map poses to vertices.nearest_rotation,sinc(scalar and interval),ipc::PI(<ipc/math/constants.hpp>), and a 2Dcross_product_matrix(double).ipctklogger is no longer registered in spdlog's global registry. Previously, two Python modules that each embed the toolkit failed on the duplicate name.RigidBodies,RigidBody,Pose/Poses,AffinePose,JointConstraints,read_gltf/write_gltf, andNarrowPhaseCCDMode.std::shared_ptr.NarrowPhaseCCDsubclasses written without amodeparameter keep working.💥 Breaking changes
NarrowPhaseCCDmust add themodeparameter to their four overrides.NonlinearCCD::toleranceandNonlinearCCD::max_iterationsare removed. Configure theTightInclusionCCDyou pass in instead.NonlinearCCD(tolerance, max_iterations, conservative_rescaling)in C++ and Python. It builds the equivalentTightInclusionCCD.Candidates::save_obj, renamed towrite_obj, in C++ and Python.<ipc/utils/save_obj.hpp>, which forwards to<ipc/io/write_candidates_obj.hpp>.New dependencies
ipc_toolkit_demo, never byipc_toolkit.PRIVATE.IPC_TOOLKIT_WITH_GLTF=ON.Type of change
How Has This Been Tested?
ipc_toolkit_tests "~[!benchmark]": all 518 test cases pass. This includes 86 new cases intests/src/tests/{dynamics,demo,io}:ToAffinechain rule, and rigid pose derivatives.python -m nose2inpython/tests: all 106 tests pass. These include the newNarrowPhaseCCDModeand backward-compatibility tests.src/ipc/math/sinc.cppwithIPC_TOOLKIT_WITH_FILIBoff.Test Configuration:
Checklist