-
-
Notifications
You must be signed in to change notification settings - Fork 0
CONTINUOUS_COLLISION_DETECTION
Continuous collision detection (CCD) prevents fast motion from skipping relevant contacts. Gravitas keeps CCD deterministic by using fixed-point sweep reducers, stable candidate ordering, bounded time-of-impact work, and service-owned handoff queues.
- CCD resolves from body, hierarchy, then context defaults.
- Bodyless colliders, explicit static bodies, and stationary kinematic bodies use static-style sweeps.
- Moving dynamic and kinematic targets use frame-prepared candidate indexing.
- Kinematic bodies can act as active swept sources from frame-start pose to host target pose.
- Translation and rotation compete in one normalized-time arbiter whenever either participant has rotational motion.
- Mixed CCD runs only in
PhysicsRuntimeMode.Mixed. - Service-level handoff queues handle dense same-frame contact chains.
- Public query APIs remain query APIs; CCD uses internal target filters where needed.
| Concern | API |
|---|---|
| Context default | PhysicsSettings.DefaultContinuousCollisionMode |
| 3D body override | SolidBody.ContinuousCollisionMode |
| 2D body override | SolidBody2D.ContinuousCollisionMode |
| Body-owned TOI counters |
LastContinuousCollisionToiIterationCount, LastContinuousCollisionToiIterationLimitReached
|
| 3D service counters |
GravitasPhysicsService.LastContinuousCollisionIslandCount, LastContinuousCollisionIslandIterationCount, LastContinuousCollisionIslandLimitReached
|
| 2D service counters |
GravitasPhysics2DService.LastContinuousCollisionIslandCount, LastContinuousCollisionIslandIterationCount, LastContinuousCollisionIslandLimitReached
|
Both body types expose body-owned TOI counters, and both physics services expose service-level island counters for the last late step.
Inherit, Discrete, Continuous, and Auto are the only valid
ContinuousCollisionMode values. The context default deliberately accepts
Inherit; if no body or hierarchy override supplies a concrete mode, that
context value resolves to Discrete. Public settings/body assignment and
settings or replay population reject undefined byte-cast values with
ArgumentOutOfRangeException before publishing them. Invalid authored or
serialized state therefore cannot silently change tunneling policy.
| Path | Target set | Reducer policy |
|---|---|---|
| Stationary 3D | bodyless, static-role, and stationary kinematic 3D colliders | Source collider proxy sphere, then shape-exact validation where supported. |
| Moving 3D | dynamic and moving kinematic 3D bodies | Prepared pair trajectories, exact validation for supported source families, conservative proxy behavior where no exact source reducer exists. |
| Mixed stationary 2D | bodyless, static-role, and stationary kinematic 2D slabs | Same reducer policy as public QueryMixed.SweepSphereAgainst2D. |
| Mixed moving 2D | dynamic and moving kinematic 2D bodies | Prepared pair trajectories, conservative mixed proxy candidate, then bounded handoff. |
| Kinematic active source | static-style blockers and dynamic 3D/2D targets before first blocker | Frame-start pose to host target pose, using the underlying dimension-local or mixed reducer. |
| Path | Target set | Reducer policy |
|---|---|---|
| Stationary 2D | bodyless, static-role, and stationary kinematic 2D colliders | Source circle sweep, refined by mover shape where needed. |
| Moving 2D | dynamic and moving kinematic 2D bodies | Prepared pair trajectories, then exact mover-shape validation for circle, capsule, AABB, convex polygon, and compound families. |
| Mixed stationary 3D | bodyless, static-role, and stationary kinematic 3D colliders | Same reducer policy as public QueryMixed.SweepCircleAgainst3D. |
| Mixed moving 3D | dynamic and moving kinematic 3D bodies | Prepared pair trajectories, conservative mixed proxy candidate, then bounded handoff. |
| Kinematic active source | static-style blockers and dynamic 2D/3D targets before first blocker | Frame-start pose to host target pose, using the underlying dimension-local or mixed reducer. |
Static-style CCD targets include bodyless colliders, explicit static bodies, and
stationary kinematic bodies. Freeze axes do not change a body's CCD role.
Translational source admission follows CanTranslate; rotational source and
target admission follows independent CanRotate, so a position-frozen dynamic
body can still sweep changing rotational bounds. Fully locked dynamic bodies
remain indexed for deterministic counterpart access but do not start CCD work.
Moving kinematic targets are captured in the same frame-prepared candidate index and piecewise trajectory model as moving dynamic targets, so their sampled pose does not depend on body registration or service order. Public sweep queries can report dynamic, kinematic, static, and bodyless targets according to normal query filters. Final CCD target admission uses the owning collision service's physical-pair gate, including collider lifecycle, authored filters, hierarchy rules, and linked-joint collision suppression.
For kinematic active-source CCD, hosts write deterministic target transforms
before context.LateSimulate(). Gravitas captures the frame-start pose, reads
the host transform as the requested target pose, sweeps between those poses, and
clips the first static-style blocker. Dynamic targets crossed before the first
blocker are woken and position-corrected through service-owned handoff queues.
Discrete contact response samples the same prepared kinematic end velocity, so
authored same-frame linear and angular motion contributes consistently even when
the kinematic body was processed earlier in service order.
Moving-pair CCD uses immutable frame-start candidate indices plus bounded dirty overlays for bodies whose same-frame handoff changes their remaining swept bounds. A dirty body shadows its immutable entry; stale prepared bounds are not unioned back into admission. Each body exposes a canonical piecewise position, rotation, and velocity trajectory. Later sources therefore sample the exact pre-impact and post-impact history instead of whichever pose happened to be published most recently. Translational moving-pair reducers traverse only the target segments that overlap the source's remaining interval, clip the source sweep to each segment, and map segment-local hits back to the source's global time of impact. Handoff boundaries are right-continuous: when a target reverses exactly at a shared boundary, the successor segment owns that instant. Because canonical segments are chronological and non-overlapping, the first admitted non-boundary hit is the global earliest hit. This contract is shared by dynamic and kinematic 2D, 3D, and mixed CCD.
Relative circle and sphere reducers keep motion as an endpoint-free direction plus physical distance. They compare the exact hit distance with the active overlap boundary, reconstruct both bodies from their authored trajectory segments, and only then materialize normalized time for arbitration. This avoids constructing an unrepresentable relative endpoint or collapsing distinct spatial contacts during early Q32.32 time conversion.
Mixed moving-pair admission encloses an embedded 2D shape with the ceiling-safe Euclidean combination of its planar pivot radius and slab half-thickness. That radial interval is geometry-only: exact reducers or sampled contact normals own closing-direction admission and candidate-speed ranking. A conservative proxy therefore cannot reject a real slab-closing contact merely because the proxy normal is separating, and it cannot promote an enclosing-proxy-only hit after an exact reducer certifies a miss.
Candidate results use stable ordering:
- time of impact.
- target dimension, with 2D before 3D for an exact-time tie.
- stable collider ID or dimension-tagged mixed key.
- bounded iteration counts.
The ordering is deterministic across repeated runs. Service-level queues own same-frame handoff processing so dense contact chains do not depend on traversal side effects. Queue admission deduplicates a body only while that body owns an unread entry. Dequeue releases that ownership before consumption, allowing a later same-frame relay to append the body again under the same deterministic iteration budget. Requeued work that exceeds the budget is explicitly discarded rather than left as stale continuation state. A later terminal handoff update (no remaining time or no resulting motion) likewise cancels any older pending continuation for that body; latest-state-wins includes the absence of further work.
Mixed CCD uses explicit mixed query reducers only in PhysicsRuntimeMode.Mixed.
PhysicsRuntimeMode.Both advances 2D and 3D services side by side without
cross-dimensional CCD.
3D swept-sphere mixed CCD routes through QueryMixed.SweepSphereAgainst2D.
Circle slabs use the exact spherical dilation of their finite vertical cylinder,
including rounded cap rims. Capsule slabs use an exact union of their expanded
planar side and cap cores, four sphere-dilated straight rims, and two
sphere-dilated vertical endpoint cylinders. Both reducers retain full-domain
finite-axis arithmetic through the final distance and report Exact. AABB,
convex polygon, and supported compound slab hits use their exact finite-slab
reducers.
2D swept-circle mixed CCD routes through QueryMixed.SweepCircleAgainst3D.
Supported primitive, mesh, and compound target families use exact reducers for
the public mixed query contract. Rotated finite cones use the same
support-mapped convex advancement kernel as 3D swept source queries with a
query-owned circle-slab source.
PhysicsMixedHit.ReducerKind labels exact hits separately from conservative
proxy candidates used by dynamic CCD paths.
Rotational CCD is bounded and deterministic across same-dimensional and mixed pairs. When either participant has rotational motion, source translation, source rotation, target translation, and target rotation compete in one normalized-time arbiter. It traverses intervals earliest-first for each candidate and samples both prepared poses at each midpoint. Shape-specific closest-feature separation, with a conservative AABB fallback where no tighter proof exists, certifies an interval only when its gap exceeds an outward-rounded bound on both participants' linear and pivot-centered angular travel. The bound also scales fixed-point pose uncertainty by pivot radius.
An unresolved interval is subdivided until a fixed depth or per-candidate work
budget. A witnessed contact can apply the contact-point response and bounded
handoffs atomically. If the search cannot prove separation or witness contact,
it clamps at the unresolved interval's lower time without inventing an impulse.
Only the immediate prior pair is excluded from continuation, so a deterministic
A -> B -> A same-frame chain remains admissible. Candidate results are ordered
by normalized time, target dimension, and stable collider identity.
Trajectory mutation and dirty-overlay admission share a deterministic frame budget. If either participant cannot reserve all state required for an atomic pair update, Gravitas conservatively clamps before mutating either body and reports the CCD iteration limit. Linear-only handoffs preserve unrelated angular acceleration, and angular-only handoffs preserve unrelated linear acceleration.
Rotational broad-phase radii are measured from each body's actual rotation
pivot, not merely from the collider center, so local offsets and remote compound
parts remain inside the candidate volume. Unsupported collision pairs are
skipped explicitly. If the required pivot radius exceeds the scalar domain,
candidate admission scans the bounded context registry instead of issuing an
effectively unbounded GridForge query. Dynamic and kinematic moving targets use
their prepared piecewise trajectories; mixed candidates are admitted only in
PhysicsRuntimeMode.Mixed, never in Both.
Body-owned bounded TOI counters are deterministic frame-local state for tuning, tests, and host diagnostics. Service counters describe CCD island/handoff behavior without adding event-buffer traffic to the hot path.
Active cross-frame CCD handoff state is included in the authoritative replay hash because it can affect the next fixed step. Rebuildable per-frame CCD snapshots are excluded from ordinary authoritative hashes and are available only through solver-cache hash mode when useful for drift RCA.
- Keep CCD target filters separate from public query filters.
- Keep exact reducers and conservative proxy behavior explicit.
- Bound TOI iterations and handoff processing.
- Preserve stable candidate ordering.
- Use mixed CCD only through the mixed runtime path.
- Add replay tests for any CCD state that affects continuation.
- Add benchmarks for dense dynamic, mixed, rotational, or kinematic-source CCD changes.