Files
suaveplan/openspec/changes/enterprise-gaming-vehicle-physics/proposal.md
2026-05-27 23:29:53 +01:00

174 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenSpec Change: enterprise-gaming-vehicle-physics
- **Change ID**: enterprise-gaming-vehicle-physics
- **Package**: `@suaveplan/vehicle-physics`
- **Category**: gaming/rigs
- **Target path**: `gaming/rigs/vehicle-physics`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/vehicle-physics.md`
---
## Summary
Deliver `@suaveplan/vehicle-physics` on the genesis branch from scratch at enterprise quality. The package provides engine-agnostic vehicle physics using Pacejka Magic Formula tire model, spring-damper suspension per wheel, multi-wheel drivetrain (FWD/RWD/AWD), differential, braking, and aerodynamic drag. All math is pure TypeScript with no runtime deps — physics backends plug in via interface. Genesis adds Zod config schemas, structured errors, injectable clock, OTel telemetry, and property tests verifying tire force symmetry and suspension convergence.
---
## Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | `VehiclePhysicsError`; `VEHICLE.*` codes |
| `@suaveplan/types` (`workspace:^`) | `Clock` |
| `@suaveplan/events` (`workspace:^`) | `vehicle:collision`, `vehicle:flip`, `vehicle:stall` events |
| `zod` (`catalog:forms`) | `VehicleConfig` schema |
| `@opentelemetry/api` (`catalog:observability`) | Step duration histogram |
---
## Public API surface
```ts
function createVehicle(config: VehicleConfig): Vehicle
interface VehicleConfig {
mass: number
wheelBase: number
trackWidth: number
centerOfMassY: number
engine: EngineConfig
transmission: TransmissionConfig
wheels: WheelConfig[]
aerodynamics?: AeroConfig
backend?: VehiclePhysicsBackend
clock?: Clock
}
interface EngineConfig {
maxTorque: number // Nm
maxRpm: number
torqueCurve?: [rpm: number, torque: number][]
idleRpm?: number
}
interface TransmissionConfig {
type: 'FWD' | 'RWD' | 'AWD'
gearRatios: number[]
finalDrive: number
differentialSlip?: number
}
interface WheelConfig {
position: Vec3
radius: number
suspensionRestLength: number
suspensionStiffness: number
suspensionDamping: number
tireGripLateral: number
tireGripLongitudinal: number
}
interface Vehicle {
update(dt: number, input: VehicleInput): void
teleport(position: Vec3, rotation: Quat): void
applyImpulse(impulse: Vec3): void
flip(): void
readonly position: Vec3
readonly rotation: Quat
readonly velocity: Vec3
readonly speed: number // m/s
readonly rpm: number
readonly gear: number
readonly wheelsGrounded: boolean[]
}
interface VehicleInput {
throttle: number // 0–1
brake: number // 0–1
steering: number // -1 to 1
handbrake: boolean
clutch?: number
}
```
### Error codes
```ts
type VehicleErrorCode =
| 'VEHICLE_INVALID_CONFIG'
| 'VEHICLE_BACKEND_NOT_SET'
| 'VEHICLE_UPDATE_FAILED'
| 'VEHICLE_INVALID_GEAR'
```
---
## New additions for genesis
1. **Pacejka tire model** — lateral and longitudinal force from slip angle / slip ratio; configurable B/C/D/E coefficients.
2. **Automatic gear shifting** — RPM-based shift logic with configurable up/down thresholds.
3. **Aerodynamic drag + downforce** — `0.5 * rho * Cd * A * v²` drag; downforce scales with speed².
4. **Suspension raycast** — `VehiclePhysicsBackend.castRay()` for each wheel per tick; ground contact from hit distance.
---
## File layout
```text
gaming/rigs/vehicle-physics/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/common.ts
types/common.md
core/
vehicle/
vehicle.ts
vehicle.md
vehicle.types.ts
vehicle.test.ts
index.ts
models/
pacejka/
pacejka.ts
pacejka.md
pacejka.test.ts
index.ts
suspension/
suspension.ts
suspension.md
suspension.test.ts
index.ts
drivetrain/
drivetrain.ts
drivetrain.md
drivetrain.test.ts
index.ts
backends/
null-backend/
null-backend.ts
null-backend.md
null-backend.test.ts
index.ts
tests/
property.test.ts
```
---
## Impact
**Downstream**: `@suaveplan/r3f-vehicle` wires this to Rapier. Prerequisites: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`.