Architecture¶
Core Pipeline¶
NovaPhy follows a three-stage pipeline:
graph LR
A[ModelBuilder<br/>mutable] --> B[Model<br/>immutable]
B --> C[World<br/>simulation]
C --> D[step dt]
D --> C
- ModelBuilder — Mutable scene description. Add bodies, shapes, joints, articulations.
- Model — Immutable, baked data. Created by
builder.build(). Can be shared across multiple worlds. - World — Simulation state and stepping. Owns the solver, manages contacts and integration.
World Variants¶
| World | Solver(s) | Use Case |
|---|---|---|
World |
SolverSemiImplicit, SolverFeatherstone, SolverXPBD | Standard rigid body simulation |
FluidWorld |
PBFSolver + Akinci | Fluid and rigid-fluid coupling |
IPCWorld |
libuipc GPU Newton | Penetration-free contact (CUDA) |
VBDWorld |
VbdSolver (CPU/CUDA) | AVBD primal-dual |
Solver Pipelines¶
Free Bodies (SolverSemiImplicit)¶
graph LR
A[Broadphase<br/>SAP] --> B[Narrowphase]
B --> C[Sequential Impulse<br/>PGS]
C --> D[Integrate]
- Sweep and Prune broadphase filters candidate pairs
- Narrowphase generates contact points with normals and penetration depths
- Sequential Impulse solver resolves contacts with warm starting and Coulomb friction
- Semi-implicit Euler integration updates positions and velocities
Articulated Bodies (SolverFeatherstone)¶
graph LR
A[FK] --> B[RNEA<br/>bias forces]
B --> C[CRBA<br/>mass matrix]
C --> D[Cholesky<br/>solve]
D --> E[Integrate]
- Forward Kinematics computes body transforms from joint coordinates
- RNEA computes bias forces (Coriolis, centrifugal, gravity)
- CRBA computes the joint-space mass matrix
- Cholesky factorization solves for joint accelerations
- Semi-implicit Euler integrates joint coordinates
PBF Fluids¶
graph LR
A[Predict] --> B[Neighbor Search<br/>spatial hash]
B --> C[Density Constraint<br/>iterative]
C --> D[XSPH + Vorticity]
D --> E[Update]
Collision System¶
Broadphase¶
Multiple broadphase implementations behind the IBroadphase interface:
- SweepAndPrune — Default, O(n log n) sort-based
- BVH — Bounding Volume Hierarchy tree
- AllPairs — Brute-force O(n^2), for testing
Narrowphase¶
Dispatches to specialized collision pair algorithms:
- Sphere-Sphere, Sphere-Plane, Sphere-Box
- Box-Plane, Box-Box (SAT)
- GJK/EPA for general convex shapes
- Cylinder collision pairs
Contact Convention¶
- Normal direction: body_a → body_b (positive impulse separates)
- Plane shapes use
body_index = -1(world-owned, always static)
Data Types¶
NovaPhy uses float32 exclusively — never double.
| Type | Definition |
|---|---|
Scalar |
float |
Vec3f |
Eigen::Vector3f |
Mat3f |
Eigen::Matrix3f |
Quatf |
Eigen::Quaternionf |
VecXf |
Eigen::VectorXf |
MatXf |
Eigen::MatrixXf |
Spatial algebra uses the Featherstone convention: [angular; linear] for 6D vectors.
File Organization¶
NovaPhy/
├── include/novaphy/
│ ├── math/ # Vec3f, Mat3f, Quatf, spatial algebra
│ ├── core/ # Body, Shape, Joint, Model, ModelBuilder, Contact
│ ├── collision/ # SAP, BVH, Narrowphase, GJK/EPA
│ ├── dynamics/ # SolverBase, integrator
│ │ ├── semi_implicit/ # SolverSemiImplicit
│ │ ├── featherstone/ # SolverFeatherstone, FK, RNEA, CRBA
│ │ ├── xpbd/ # SolverXPBD
│ │ ├── vbd/ # VBDWorld, VbdSolver
│ │ └── ipc/ # IPCWorld, IPCConfig
│ ├── fluid/ # PBF, SPH kernels, Akinci boundary
│ ├── io/ # URDF, OpenUSD, scene builder
│ └── sim/ # World, SimState, PerformanceMonitor
├── src/ # C++ implementations (mirrors include/)
├── python/
│ ├── novaphy/ # Python package
│ └── bindings/ # pybind11 binding files
├── tests/
│ ├── python/ # pytest files
│ └── cpp/ # C++ unit tests
└── demos/ # Polyscope demo scripts