Add ramp-friendly vehicle collision, throttle engine audio and Mixamo SDK guide

This commit is contained in:
chazmm committed 2026-09-08 22:21:17 +01:00
1 parent fb0dd98e83
commit a97c9157e6
16 files changed
+421 -21

No files matched your search

+122
View File
@@ -0,0 +1,122 @@
# Mixamo to native vehicle animations
This is the workflow used for the working Mario Kart rider. The game plays a native
Skate skeleton pose on the currently selected compatible character. It does not swap
the rider to the mesh bundled in the Mixamo download. Other characters must first be
converted to the supported native render rig; arbitrary skeletons are not interchangeable.
Different proportions may still need contact adjustments to reach a wheel or pedals.
## 1. Keep a matched calibration pair
Use your owned stock `assets/private/skater.glb` as the native reference. Upload the
same stock character mesh to Mixamo, rig it there, and retain its returned rest/T-pose
with skin and skeleton. Convert that returned reference FBX to GLB without altering
its bind pose (Blender import FBX, export glTF/GLB with skin). This paired stock return
is the calibration source, not a Mario mesh or a posed entry/exit frame.
The converter's `--calibrate` path accepts a GLB. It verifies mesh bounds and records
the reference hash, source hash, scale and Mixamo bind transforms. Example:
```powershell
python tools/mixamo_to_skate/main.py returned-stock.glb --reference assets/private/skater.glb --profile calibration.json --calibrate --noninteractive
```
Keep calibration.json with that exact stock reference. For this local kart, the matched
profile is `C:/Users/Daddy/Documents/Mixamo-to-Skate/calibration.json`. Do not replace it
with a profile built from another character. Calibration transfers the change from a
Mixamo bind pose into the original native bind basis; copying raw rotations ignores
bone axes and is what produced the forward shoulders in the earlier attempt.
## 2. Download the animations from the same Mixamo character
Select Entering Car and Exiting Car on that same uploaded stock character. Download FBX
**with skin** for this pipeline, retaining its skeleton. The skin is useful for verifying
the reference and is not used as the in-game rider. Use consistent frame rate and no
keyframe reduction. Preserve root motion; these clips need to move between standing
and seated positions. Keep the original downloads untouched.
The accepted local inputs were `Entering Car (2).fbx` and `Exiting Car (2).fbx` in Downloads.
The earlier `(1)` files used another character and are not the calibrated source.
## 3. Verify the raw transfer before fitting a vehicle
Run Blender in background mode with the stock GLB and matched profile. Use fresh output
directories: the tools refuse to overwrite existing preview folders.
```powershell
& $blender -b --python tools/preview_mixamo_animation.py -- --source 'Entering Car (2).fbx' --reference assets/private/skater.glb --profile calibration.json --output .local/raw-enter
& $blender -b --python tools/preview_mixamo_animation.py -- --source 'Exiting Car (2).fbx' --reference assets/private/skater.glb --profile calibration.json --output .local/raw-exit
```
`$blender` is the path to your Blender executable. Open each `Raw-Skate-Animation.blend`.
Check the first, middle and final frames, especially shoulders, wrists, hips and feet.
The tool checks the calibration hash and source bind compatibility. Do not bypass a
mismatch by forcing rotation offsets into the native rest skeleton. Native rest bones
and skin inverse-bind matrices must remain unchanged. Fix the calibration/source first.
## 4. Fit the approved poses to the kart
```powershell
& $blender -b --python tools/fit_kart_animation_preview.py -- --raw .local/raw-enter/Raw-Skate-Animation.blend --kart mods/mario-kart/kart.glb --mode enter --output .local/fit-enter
& $blender -b --python tools/fit_kart_animation_preview.py -- --raw .local/raw-exit/Raw-Skate-Animation.blend --kart mods/mario-kart/kart.glb --mode exit --output .local/fit-exit
```
This example script aligns the seated hips, eases torso lean and solves arms/legs to
wheel and footwell targets. It bakes a separate fitted action, retains the raw action,
checks unchanged rest bones and writes a fit report. Review both .blend files before
export. Feet need clearance over the side pod, hands need a reachable wheel position,
and the last entry pose should match the first exit pose. The seated pose is also
used for the driving loop. Fingers are limited by the native character's hand rig.
Targets in this script use Blender Z-up: seat `(0, .20, .73)`, wheel grips
`(+/-.19, -.36, .90)`, feet `(+/-.17, -.55, .33)`; the preview kart is raised `.55`.
These are **kart example values**. For another vehicle adjust alignment, contact targets,
clearance and torso lean in the authoring script or bake equivalent edits in Blender.
Do not change rest bones, and keep the fitted armature object transform identity.
## 5. Export in the game's exact skeleton order
Obtain the order from the installed native bank (or `sdk.animation.info().bone_names`).
Do not use the larger reference list in the vendor importer: this build's bank has 36
bones, including reparented helpers. Generate the JSON list with the provided utility:
```powershell
cargo run --locked -p skate-data --example vehicle_bone_names -- assets/private/stock/data/anim/OnBoard.abin .local/bone-names.json
& $blender -b --python tools/export_kart_rider.py -- --enter .local/fit-enter/Kart-enter.blend --exit .local/fit-exit/Kart-exit.blend --reference assets/private/skater.glb --bone-names .local/bone-names.json --output mods/mario-kart/rider.json
```
The exporter preserves the glTF skin bind basis while converting Blender poses into
column-major native matrices. It subtracts the preview seat, exports enter/exit clips,
uses the final entry pose as drive, and generates left/right steering endpoints with
length-preserving arm reach. It renders both endpoints for inspection. The host blends
between them continuously with steering input. For another cockpit, change the exporter
seat, steering-wheel centre/axis and steering angle alongside the fitted scene targets.
The example's game seat is `[0, .18, -.20]`: convert the Blender seat to Y-up and subtract
the preview kart's .55 m lift. Model fitting offsets are not an excuse to alter native
bone axes. Export fps comes from each scene; retain its timing instead of relabelling
frames with a different rate. The output is a full native pose, not additive rotations.
## 6. Package, validate and playtest
Put `rider.json`, the embedded `kart.glb`, `vehicle.json`, `mod.json` and `main.lua` in the
executable-adjacent mod folder. Set animations.file to rider.json, enter/exit to their
names, idle/drive/reverse/brake to drive for this example, and steer_left/steer_right to
the corresponding endpoints. See vehicle-sdk.md for limits, schema and lifecycle.
The host validates names, frame counts, finite rigid transforms and clip references at
load. The source loader tests cover malformed inputs; local validation also checked the
export against the actual stock bank and matched the final entry pose to drive. The
runtime applies the same native pose to whichever compatible character is selected.
`Build-VehicleSDK.ps1` stages a build and documentation. It preserves differing local
mod files; copy your approved changed files into the playable mod directory explicitly
when it reports them. Reload/disable-enable the mod to load changed animation files.
Use PLAY-MARIO-KART.bat for a manual session. Check entry/exit from multiple vanilla
stances, steering in both directions, ramps, braking, reset, Escape, and mod disable.
Also try characters with different proportions; native-rig compatibility does not
promise exact contact for every body size. Gameplay is never launched by these tools.
Source code and authoring scripts are reusable. Proprietary FBX, GLB, .blend and exported
rider data remain local and ignored by Git. Distribute only assets you have permission
to redistribute; the SDK source itself does not include the stock mesh or these clips.
+55 -8
View File
@@ -65,7 +65,7 @@ Do not pass the full input table to `control`; copy only its four control fields
and a parking brake is applied. Controls are ignored during enter/exit animations.
`tune` supports optional engine_force (0..100000 N), max_speed (1..100 m/s),
brake_impulse (0..10000), steering_angle (0.01..1.2 radians), tire_grip (0.1..20).
engine_volume (0..1), brake_impulse (0..10000), steering_angle (0.01..1.2 radians), tire_grip (0.1..20).
Maximum speed limits engine application; it is not an absolute downhill speed cap.
Events passed to `on_event`: `vehicle_spawned`, `vehicle_entering`, `vehicle_entered`,
@@ -77,8 +77,8 @@ mod errors; they retire the mod's vehicles instead of crashing the game.
## Vehicle definition
See `mods/mario-kart/vehicle.json` for a complete working definition. Coordinates
are metres, +Y up, +Z forward, +X right, with heading in radians around +Y.
`half_extents` describes the chassis cuboid. `mass` is kilograms. `model_scale`,
are metres, +Y up, +Z forward, +X driver-left, with heading in radians around +Y.
`half_extents` describes the outer chassis collision bounds. `mass` is kilograms. `model_scale`,
`model_offset` and `model_yaw` affect the model only, not its collider.
Each wheel defines a chassis-local suspension mounting `position`, radius,
@@ -96,7 +96,7 @@ A package may total 64 MiB; a model is limited to 32 MiB and an animation file t
## Rider animation support
No animations are supplied. All animation slots default to null. Without a matching
The local kart package supplies fitted clips. Other definitions default their animation slots to null. Without a matching
clip, the skater is hidden and entering/exiting completes immediately. This avoids
showing an unrelated standing/skating pose on the kart.
@@ -143,9 +143,10 @@ when exiting. Files with a mismatched skeleton, invalid matrices or missing name
clips are rejected. Maximum 32 clips, 3600 frames per clip, 1..120 fps.
Enter/exit clips play once and their frame count/fps determines transition duration.
Driving slots loop; brake, reverse and steering states select their respective clips,
with drive as fallback. Missing optional driving slots use the drive clip when
available. Slot switching currently cuts between clips; cross-fades are not included.
Driving slots loop; brake and reverse select their respective base clips, with drive
as fallback. Steering continuously blends that base towards the left/right pose.
Vehicle phase changes blend with native bone-local interpolation; brake/reverse
base-clip changes currently cut, so author compatible seated poses.
Edit vehicle.json or rider.json and reload the mod to install new clips.
## Current boundaries
@@ -156,7 +157,7 @@ and session-marker controls are blocked while driving. Vehicle motion is not
recorded in skating replays. Native skater-versus-vehicle impact forces are not
bridged yet: vehicles collide with the map and one another, but parked vehicles
are not native skating obstacles. This API does not include weapons, damage,
network synchronization, engine audio or a racing ruleset.
network synchronization or a racing ruleset.
Verification uses headless Rapier tests and window-free Lua tests. The game is
not launched automatically; rendering, entry/exit and handling need manual playtesting.
@@ -172,3 +173,49 @@ jitter from separate camera damping. Resets discard the old motion sample.
The board root is scaled away during vehicle playback and restored by the vanilla blend.
The local Mario Kart package supplies fitted entry/exit, seated and steering clips;
its proprietary rider.json is generated locally and is not included in source control.
## Ramp clearance and mass distribution
These are shared definition fields, available to any mod, not Mario-specific code:
| Field | Meaning | Default |
| --- | --- | --- |
| `collider_offset` | Chassis-local collision centre, metres | `[0,0,0]` |
| `collider_rounding` | Rounded edge radius; below 95% of smallest half extent | `0` |
| `chassis_friction` | Body contact friction, 0..2 | `0.3` |
| `center_of_mass` | Chassis-local mass centre, metres | `[0,0,0]` |
| `inertia_half_extents` | Box dimensions used for mass distribution, independent of contact shape | null: use half_extents |
Rounding stays inside half_extents. Shorten low front/rear overhangs so wheel contact
can lift the chassis before the body catches the ramp. Keep the collider large enough
to protect the cockpit; the visual model does not define collision. Inertia dimensions
let a shorter collision shape retain stable pitching/rolling behaviour. A lower centre
of mass helps resist nose-diving under braking. These fields require respawning.
The example passes headless 20/30/40-degree incline tests plus braking and steering tests;
this does not guarantee every map seam or vertical ledge is traversable. Wheels remain
raycasts, and vertical walls remain obstacles. No teleporting or artificial ramp boost is used.
## Engine sound
Opt in per definition:
```json
"engine_audio": { "enabled": true, "volume": 0.45, "idle_pitch": 0.7, "max_pitch": 2.8 }
```
The host synthesizes an original layered exhaust pulse with filtered noise. No downloaded
sound asset or extra file is required. It plays for the occupied vehicle; parked engines
are silent. Pitch follows speed and absolute throttle, including reverse and free revving
while stopped. Full throttle increases volume; releasing it smoothly drops the engine back
towards idle. Pitch/volume changes are smoothed, Escape/replay fades it silent, and exiting
or disabling the mod fades/removes the voice. This is a driver-focused mono sound, not a
spatial multi-car mixer or a simulated gearbox. There is currently no custom sample slot.
Volume is 0..1, idle_pitch 0.25..2, max_pitch idle_pitch..5 (multipliers of the 80 Hz
synth fundamental). All are validated. `sdk.vehicle.tune(key,{engine_volume=0.5})`
changes volume live; use zero to mute. Mario Kart exposes this in its mod settings.
## Authoring and reuse
See [Mixamo vehicle animation workflow](mixamo-vehicle-workflow.md) for the full sequence,
calibration, Blender fitting, native export and packaging commands. The host's animation
slots, steering blend, stance hand-offs, board hiding and shared motion interpolation
apply automatically to every vehicle definition. The example fitting scripts contain
kart geometry targets; adjust those targets for another vehicle without changing the host.