Skip to content

Collision models, ledges and physics materials

MonoGame / XNACollision and physicsApplies toSTUNTBOOST

For each level part the game’s content pipeline derives a collision model from the glTF and stores it as Level_<Name>_<N>Collision.xnb (reader SE.Pipeline.CollisionModelReader). It holds what the game collides with, how the board grips, and the grind ledges the board can lock onto. A custom map has no such file: the game compiles collision from the glTF itself. Observed · STUNTBOOST

Every node whose name parses as solid (<) or transmissive (#, a trigger) gets a collision mesh from its mesh and its global transform (node names). Grind ledges are computed per solid node unless its name contains no_grind (=OnlyGrindUpright() is respected); ledges that are obstructed or short are omitted and nearby corners linked. Observed · STUNTBOOST

Over all 159 parts the game’s own loader reads 3,022,926 collision triangles and 293,944 ledges: 287,956 Edge, 5,346 RailBoost and 642 RailNoBoost. Proven · STUNTBOOST A reader of the file layout below gives, for every part, the same nodes with collision, the same triangles (corners to the bit, load order, grippable bits, ramps), the same ledges (type, corners, normal, tangent, binormal, angles, lengths, group) and the same corner counts as the game’s own code. Proven · STUNTBOOST

After the primary object’s reader index, little-endian, a vector being three f32:

Collision model (CollisionModelReader object)variableSTUNTBOOST100% known

Read as a stream: sizes depend on the counts.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x012vec3solid cell sizeProventhe lookup grid's cell size for solid triangles
0xC12vec3trigger cell sizeProven
0x184i32mesh countProvenone per glTF node
after the countsper meshmesh[]meshesProvena byte 1 (present), the aggregate (byte: 0 solid, 1 trigger, 2 none), a part count (i32), then the parts
after the meshesvariableledgesledge graphProvencorner count and corners, ledge count and ledges, then each corner's ledge directions

A part of a mesh: its triangle count (i32); per triangle three corners (vectors) and, for a solid mesh only, the grippable-edge bits (a byte) and a ramp id (i32, −1 none); then the part’s lookup grid cells (an i32 count; each cell three i32 indices, a triangle count and that many triangle indices). The grid is derived from the triangles and is the game’s lookup structure. Proven · STUNTBOOST

The ledge graph: the corner count (i32), each corner’s position (vector) and its near corners (an i32 count and indices); the ledge count (i32), each ledge a minimum and a maximum angle (f32), a normal and a tangent (vectors), two corner indices (i32), a length, the recursive lengths in each direction, a group id (i32), two lerp cut-offs (f32) and a type byte (0 edge, 1 rail without boost, 2 rail with boost); then each corner’s ledge directions (an i32 count, each a ledge index and a bool, forward). The binormal is not stored: the game derives it as normalize(cross(tangent, normal)). Proven · STUNTBOOST

The shortcuts file Level_<Name>_<N>Cuts.xnb is a reflective SE.Pipeline.ShortcutContent whose one property is a Dictionary<uint, int[]>: the reader index, the entry count (i32), then per entry the key (u32) and the value (reader index, an i32 count and the integers; a null array is possible). Observed · STUNTBOOST

The file stores grippable-edge bits and ramp ids for solid triangles only. The game’s loader (SE.CollisionModel.Load) defaults them to 0 for transmissive (trigger) triangles, so a dump through the game’s loader shows zeros there, for 518 parts, that the file does not hold. Proven · STUNTBOOST

The game’s physics materials are glTF materials whose names begin C_, assigned to collision geometry (_<, not visual meshes): C_<behaviour>[_<substance>][_no_grind], a Blender .NNN suffix dropped. Sourced · StuntboostTools documentation The 28 distinct names in the 159 parts: Observed · STUNTBOOST

Behaviour Meaning Names (uses) Confidence
Default an ordinary solid surface C_Default (126), _Cardboard (113), _Wood (97), _PlasticHard (95), _Metal (94), _Fabric (69), _MetalHollow (62), _PlasticSoft (60), _PlasticHard_no_grind (36) Sourced · StuntboostTools documentation
Ramp ramp handling C_Ramp (18), _Cardboard (63), _MetalHollow (30), _Metal (16), _PlasticHard (7), _PlasticSoft (3), _Wood (2) Sourced · StuntboostTools documentation
RampV, RampVExtension vertical-ramp variants C_RampV_Cardboard (34), _Cardboard_no_grind (25), C_RampVExtension_Cardboard (31), C_RampV (2), _PlasticSoft (1) Inferred
Kill a deadly surface C_Kill (70) Sourced · StuntboostTools documentation
RailBoost, RailNoBoost rails with and without a boost C_RailBoost (13), C_RailNoBoost (4), _MetalHollow (1) Sourced · StuntboostTools documentation
Ice C_Ice (14) Inferred
SlowSkate C_SlowSkate_PlasticHard (13) Inferred

Substances (Wood, Metal, MetalHollow, Cardboard, Fabric, PlasticHard, PlasticSoft) name a surface sound or feel. Inferred The material of a collection can be swapped by a collection named swap_collision_materials=C_Kill. Sourced · StuntboostTools documentation