IPC Contact¶
Overview¶
NovaPhy integrates libuipc to provide GPU-accelerated Incremental Potential Contact (IPC) with mathematically guaranteed penetration-free contact.
Optional Feature
IPC is built from the external/libuipc submodule and must be
enabled with NOVAPHY_WITH_IPC=ON. Select the GPU path with
NOVAPHY_GPU_PLATFORM=NVIDIA or NOVAPHY_GPU_PLATFORM=COREX.
How It Works¶
The IPC pipeline:
- Shape Conversion — NovaPhy shapes are converted to tetrahedral meshes
- GPU Newton Solver — libuipc solves the barrier-based contact problem on GPU
- Barrier Contact — Log-barrier potential guarantees no interpenetration
Build with IPC¶
# NVIDIA CUDA path
CMAKE_ARGS="-DNOVAPHY_WITH_IPC=ON -DNOVAPHY_GPU_PLATFORM=NVIDIA" pip install -e .
# NVIDIA RTX 50-series / compute_120 path
CMAKE_ARGS="-DNOVAPHY_WITH_IPC=ON -DNOVAPHY_GPU_PLATFORM=NVIDIA -DCMAKE_CUDA_COMPILER=/usr/local/cuda-12.8/bin/nvcc" pip install -e .
# CoreX compatibility path
CMAKE_ARGS="-DNOVAPHY_WITH_IPC=ON -DNOVAPHY_GPU_PLATFORM=COREX" pip install -e .
Usage¶
SolverIPC is a Newton-aligned SolverBase adapter; drive it through
the standard solver.step(...) contract. dt and gravity are
validated against the libuipc scene built at construction:
import novaphy
if novaphy.has_ipc():
builder = novaphy.ModelBuilder()
# ... add bodies and shapes ...
model = builder.finalize()
config = novaphy.solvers.SolverIPC.Config()
config.dt = 1.0 / 60.0
solver = novaphy.solvers.SolverIPC(model, config)
state = model.state()
control = model.control()
contacts = novaphy.CollisionPipeline(model).contacts()
for _ in range(100):
solver.step(state, state, control, contacts, config.dt)
novaphy.solvers.SolverIPC is the public IPC entry point. libuipc's
scene/world/engine are kept as private solver implementation details.
The contacts argument is accepted to preserve the shared SolverBase
call shape; libuipc performs IPC collision detection and contact solving
internally and does not consume NovaPhy's CollisionPipeline output yet.
The current adapter supports rigid free bodies with plane, box, sphere,
cylinder, convex hull, triangle mesh, and heightfield shapes. Box, sphere,
cylinder, and convex hull shapes are converted to libuipc affine-body
tetrahedral meshes. Triangle mesh and heightfield shapes are mapped as
codimensional libuipc shell affine bodies; tune their half-thickness with
IPCConfig.shell_thickness or a positive per-shape margin. Multiple shell
shapes can share one body and are merged into one libuipc shell object; a body
cannot mix shell and volumetric IPC shapes yet. SdfGrid shapes remain
unsupported for IPC and should be converted to a triangle mesh or heightfield
first.
NovaPhy shape flags, collision groups, disabled collision pairs, per-shape friction, and free-body kinematic flags are mirrored into libuipc's contact element table and affine-body external-kinetic attributes. Articulated joints, particles/deformables, multi-world batching, SDF grids, and mixed shell plus volumetric bodies are rejected with clear errors until those mappings are implemented.
When to Use IPC¶
| Scenario | Recommended Solver |
|---|---|
| Real-time simulation | SolverSemiImplicit / SolverFeatherstone |
| Guaranteed no-penetration | SolverIPC |
| Deformable objects (future) | SolverIPC |
| Large-scale contact | SolverIPC |
Demo¶
Requirements¶
- NVIDIA CUDA path: CUDA 12.4+.
- NVIDIA RTX 50-series /
compute_120: CUDA 12.8+ and an explicitCMAKE_CUDA_COMPILER, for example/usr/local/cuda-12.8/bin/nvcc, if the system defaultnvccis older. - CoreX path: CoreX CUDA compatibility toolchain and
ivcore11architecture. - Compatible C++ compiler (see Build Documentation)
- The libuipc submodule is initialized at
external/libuipc.