Collision, physics pools and grinds
Stock collision streams with the world; render readiness does not imply that ground collision has arrived. StaticModelGroups can share one PhysicsAsset per group, while render-only members are legal. Observed
Studio 20261012 generally places collision in resident level-root layers such as default_1. Below roughly
4,003 geometries it writes per-object .physics assets. Above that threshold it merges collision into 100-metre
areas named collision_area_<x>_<z>; when merged geometry still exceeds the budget it can stream collision
with WorldPartition cells. A measured 6.4-km cube-grid example streams up to 27,648 geometry slots in game.
Observed
The 4,003 threshold is a compiler budget, distinct from the stock geometry pool of 5,000 and ReSkate’s raised 40,000-geometry pool. Studio warns when geometries across active WorldPartition ancestry exceed its native resident budget. Observed
Studio’s Blender add-on turns curves flagged sk8_grind_curve into invisible, open-ended, eight-sided collision
prisms. These are collision geometry rather than runtime grind splines. Observed
Capacity assertions
Section titled “Capacity assertions”The executable contains FatalAssert failed: Exceeded <X> capacity of PhysicsWorld checks for twenty pools,
for example FixedShapeCount at Skate+0x26b122c. config/DisabledAsserts.cfg disables them at every launch.
Disabling does not make an overflow safe: each check reports through +0x7138370 and then executes
mov dword [0],0 at its report site (for example +0x265af98, +0x266eedb), so an overflowing pool faults
there and the dump names that site. Observed
ReSkate caps fixed shapes and hull/mesh pools at 1<<20. Sourced · ReSkate Per-level capacity selection
appears related to the level’s FBPhysicsWorldData, else the Physics.DefaultClientWorldCapacity.* settings,
going by the executable’s assertion strings; that selection path is not exercised by the available evidence.
Inferred
PhysicsResource
Section titled “PhysicsResource”A PhysicsResource (resource type 0x41759364) is the collision a PhysicsAsset or EcsPhysicsAsset names. It is
little-endian, and every offset in it is self-relative: the field’s own position plus its value. Observed
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 4 | u32 = 2 | version | Observed | |
| 0x4 | 4 | u32 = 0x69af7015 | magic | Observed | |
| 0x8 | 4 | u32 | unknown | Unknown | 0 in the game's own resources, 1 in ReSkate Studio's |
| 0xC | 4 | u32 | part count | Observed | |
| 0x10 | 4 | u32 | count of 24-byte entries after the parts | Observed | |
| 0x14 | 4 | u32 | unknown | Unknown | Zero. |
| 0x18 | 4 | u32 | shape count | Observed | |
| 0x1C | 4 | u32 | count of 44-byte entries | Observed | |
| 0x20 | 4 | u32 | unknown | Unknown | Zero. |
| 0x24 | 4 | u32 | body offset | Observed | Always 0x38 |
| 0x28 | 4 | u32 | shape table offset | Observed | |
| 0x2C | 4 | u32 | 44-byte entry table offset | Observed | |
| 0x30 | 4 | u32 | part table offset | Observed | |
| 0x34 | 4 | u32 | end of the part table | Observed |
The body at 0x38 is empty in the game’s own resources and 0x4c bytes in ReSkate Studio’s, copied from its
template. The 24- and 44-byte entry tables occur in dynamic props; their layout is not decoded. Observed
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 12 | f32[3] | bounds minimum | Observed | |
| 0xC | 12 | f32[3] | bounds maximum | Observed | |
| 0x18 | 2 | u16 | vertex count | Observed | |
| 0x1A | 2 | u16 | corner count | Observed | |
| 0x1C | 2 | u16 | face count | Observed | |
| 0x1E | 2 | u16 | tree node count | Observed | |
| 0x20 | 4 | u32 | unknown | Unknown | Zero. |
| 0x24 | 48 | u32[12] | array offsets | Observed | Vertices (f32x3), vertex-to-corner offsets, corner ids by vertex, corner vertices (u16), corner edge values (f32), concave bits, flat bits, face offsets, two unused (zero), face planes, bounding-volume tree |
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 16 | f32[4] | rotation | Observed | |
| 0x10 | 12 | f32[3] | position | Observed | |
| 0x1C | 4 | f32 = 1.0 | unknown | Unknown | |
| 0x20 | 4 | u32 | unknown | Unknown | |
| 0x24 | 4 | u32 | shape kind | Observed | 2 box with face planes, 3 convex polyhedron, 5 triangle mesh |
| 0x28 | 12 | u32[3] | part ids | Observed | |
| 0x34 | 4 | u32 | unknown | Unknown | |
| 0x38 | 4 | u32 | shape index | Observed | |
| 0x3C | 4 | u32 | unknown | Unknown | |
| 0x40 | 4 | u32 | packed material | Observed | |
| 0x44 | 4 | u32 | flags | Observed | 0x800 in measured parts |
The kind is stored in the part, not the shape. The game’s own small parts are convex polyhedra (kind 3: polygon faces, no edge data, no tree, zero bounds) and boxes with face planes (kind 2). A face plane is eight bytes: the normal octahedrally encoded as two snorm16 values, then the offset as f32. Zero bytes follow the last plane to at least 56 bytes past it. Observed
Shape arrays follow the tables by kind across all shapes in shape order: vertices, vertex offsets, corner ids, corner vertices; then, four-aligned, each shape’s edge values, concave bits and flat bits; face offsets; four-aligned face planes; and, where a shape has a tree, eight-aligned trees followed by eight zero bytes. Observed
Every PhysicsResource of every TOC of the base data reads and writes back byte for byte under this layout, except those holding the undecoded 24- and 44-byte tables, which the reader refuses. The box, convex and mesh part kinds all occur. Proven · every resource read; dynamic props with the two undecoded tables refused
Triangle-mesh shapes
Section titled “Triangle-mesh shapes”Kind 5 shapes are triangle meshes with edge data and a tree; ReSkate Studio writes only this kind. A shape holds
at most 65,535 vertices and 21,845 faces, the capacity of its u16 counts. Its vertices are recentred on the
box centre, the part position. Observed
Each face corner’s edge runs to the next corner. When exactly one other corner holds the opposite directed edge,
the two face normals give d = n1·n2: the flat bit is set when d >= cos(0.1°); otherwise, when the neighbour’s
centroid lies on or above this face’s plane, the concave bit is set if d > 0; otherwise the edge is convex and
stores f32 cos(acos(d)/2). Every other edge value is 1.0 with neither bit. Observed
The tree is a complete bounding-volume hierarchy in heap layout with faces - 1 u64 nodes. An inner node packs
its children’s minimum planes in 10/10/10 bits, rounded down, with owner bits 30 and 31, and its maximum planes in
10/9/10 bits with owner bits 61–63. The left child keeps the parent’s planes by default. Every face of a
2,048-triangle test grid lies inside the box of the leaf it reaches when the boxes are followed from the root.
Observed
Studio’s writer orders faces by their centroid on the axis of largest centroid extent, then face-box minimum x, then index, and takes the left count from the heap shape. These ordering rules reproduce Studio’s output byte for byte on eight test meshes up to 8,192 triangles; they are the writer’s rules, not a requirement the game is known to check. Observed
The 24- and 44-byte entry tables, the header word at 8, and several part words are stored but not decoded;
contact materials and grind-edge analysis are therefore not established from this layout. Unknown