feat(physics): wire CTransition sphere-sweep into player movement
Replace simple Z-snap PhysicsEngine.Resolve with ResolveWithTransition that uses the ported CTransition sphere-sweep pipeline. Movement is subdivided into sphere-radius steps, terrain collision tested at each step with step-down for ground contact maintenance. Falls back to simple Resolve if transition fails. Player controller now passes pre/post integration positions to the transition system. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6523c7199b
commit
246713e2cc
2 changed files with 66 additions and 22 deletions
|
|
@ -287,35 +287,35 @@ public sealed class PlayerMovementController
|
|||
}
|
||||
|
||||
// ── 4. Integrate physics (gravity, friction, sub-stepping) ────────────
|
||||
// Drive the integration directly rather than via update_object's wall-clock
|
||||
// path — update_object silently skips frames shorter than MinQuantum (~33ms),
|
||||
// which would drop 60fps frames entirely. Calling calc_acceleration +
|
||||
// UpdatePhysicsInternal(dt) directly gives us the same Euler integration
|
||||
// and friction with a caller-controlled dt, which is what we want.
|
||||
var preIntegratePos = _body.Position;
|
||||
_body.calc_acceleration();
|
||||
_body.UpdatePhysicsInternal(dt);
|
||||
var postIntegratePos = _body.Position;
|
||||
|
||||
// ── 5. Terrain/cell Z snap and ground-contact detection ───────────────
|
||||
// Use PhysicsEngine.Resolve to find the ground surface Z under the player.
|
||||
// We pass a zero delta because PhysicsBody already moved the position.
|
||||
var resolveResult = _physics.Resolve(
|
||||
_body.Position, CellId, Vector3.Zero, StepUpHeight);
|
||||
// ── 5. Collision resolution via CTransition sphere-sweep ─────────────
|
||||
// The Transition system subdivides the movement from pre→post into
|
||||
// sphere-radius steps, testing terrain collision at each step.
|
||||
// Falls back to simple Z-snap if transition fails.
|
||||
var resolveResult = _physics.ResolveWithTransition(
|
||||
preIntegratePos, postIntegratePos, CellId,
|
||||
sphereRadius: 0.48f, // human player radius from Setup
|
||||
sphereHeight: 1.2f, // human player height from Setup
|
||||
stepUpHeight: StepUpHeight,
|
||||
stepDownHeight: 0.04f, // retail default
|
||||
isOnGround: _body.OnWalkable);
|
||||
|
||||
// Apply resolved position.
|
||||
_body.Position = resolveResult.Position;
|
||||
|
||||
if (resolveResult.IsOnGround)
|
||||
{
|
||||
float groundZ = resolveResult.Position.Z;
|
||||
float bodyZ = _body.Position.Z;
|
||||
|
||||
if (bodyZ <= groundZ + 0.05f && _body.Velocity.Z <= 0f)
|
||||
if (_body.Velocity.Z <= 0f)
|
||||
{
|
||||
// Player is at or below the ground AND not jumping upward — snap to surface.
|
||||
_body.Position = new Vector3(_body.Position.X, _body.Position.Y, groundZ);
|
||||
|
||||
// Grounded — snap to resolved position and land.
|
||||
bool wasAirborne = !_body.OnWalkable;
|
||||
_body.TransientState |= TransientStateFlags.Contact | TransientStateFlags.OnWalkable;
|
||||
_body.calc_acceleration(); // re-zero gravity acceleration now grounded
|
||||
_body.calc_acceleration();
|
||||
|
||||
// Zero out downward velocity so we don't keep integrating through terrain.
|
||||
if (_body.Velocity.Z < 0f)
|
||||
_body.Velocity = new Vector3(_body.Velocity.X, _body.Velocity.Y, 0f);
|
||||
|
||||
|
|
@ -324,13 +324,18 @@ public sealed class PlayerMovementController
|
|||
}
|
||||
else
|
||||
{
|
||||
// Player is above the ground — airborne.
|
||||
// Moving upward (jump) — stay airborne even though terrain is below.
|
||||
_body.TransientState &= ~(TransientStateFlags.Contact | TransientStateFlags.OnWalkable);
|
||||
_body.calc_acceleration(); // re-enable gravity
|
||||
_body.calc_acceleration();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No ground found — airborne.
|
||||
_body.TransientState &= ~(TransientStateFlags.Contact | TransientStateFlags.OnWalkable);
|
||||
_body.calc_acceleration();
|
||||
}
|
||||
|
||||
// Update CellId from the resolve result.
|
||||
CellId = resolveResult.CellId;
|
||||
|
||||
// ── 6. Determine outbound motion commands ─────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue