Expand description
Canonical vertex type and the binary serialisation format shared between the build step (build_mesh.rs writes) and GraphicsSystem (reads).
The layout asserts below stay hand-written. A vertex payload reaches a shader
through a vertex descriptor or a raw pointer, never as a declared buffer
block, so slangc’s reflection reports it as an attribute index with no byte
offset – the reflection-driven check in concinnity-device’s shader_layout
has nothing to compare against here.
Format (little-endian): u32 vertex_count vertex_count * 56 bytes float3 pos + float3 normal + float3 tangent + float3 color + float2 uv (14 x f32) u32 index_count // LOD0 indices index_count * 2 bytes u16 indices optional LOD trailer 4 bytes ascii “LODS” magic (absent for legacy / single-LOD payloads) u32 alt_count // number of additional LODs beyond LOD0 alt_count × { f32 switch_distance // camera-distance threshold (LOD i+1 applies at d >= switch_distance) u32 index_count index_count * 2 bytes u16 indices }
deserialise reads only the LOD0 indices and ignores any trailer, so old
readers keep working unchanged. deserialise_with_lods reads the trailer
when present and returns the additional LODs alongside LOD0.
Structs§
- Heightfield
Grid - A baked heightfield collider grid:
rowsxcolsworld-space heights in row-major order (row index increases along +Z, column index along +X), matching the vertex order the heightfield mesh generator emits. - Morph
Delta - One morph-target vertex delta in dense form: position and normal offsets added to the bind pose before skinning, scaled by the target’s weight.
- Morph
Entry - One sparse morph entry as the GPU consumes it: the target it belongs to plus the position and normal offsets. Plain tightly packed 4-byte fields; the shader-side struct uses packed types so the 28-byte stride matches.
- Payload
Joint - One joint of a skinned mesh’s bind-pose skeleton, as stored in the
compiled payload. Mirrors
assets::skinned_mesh::SkeletonJointbut lives ingfxso the payload format stays self-contained: the build/runtime boundaries convert between the two. Parents must appear before their children, so the runtime can walk the array once when building theSkeleton. - Payload
Morphs - Morph-target block of a skinned payload: target names plus the sparse vertex-major entries.
- Skinned
Payload - A fully deserialised skinned payload, including the optional morph and LOD blocks (empty when the payload carries none).
- Skinned
Vertex - Vertex layout for skeletally animated meshes. A superset of
Vertex: the same 56-byte static attributes plus four joint indices and four blend weights.repr(C), 80 bytes, so it casts directly to a GPU buffer. - Vertex
- Vertex layout shared by all mesh producers and both GPU backends. Repr(C) so it can be cast directly to GPU buffer memory.
Constants§
- MORPH_
DELTA_ EPSILON - Deltas whose every component is at or below this magnitude are dropped when a dense target is sparsified: a micron of position or a 1e-6 normal tilt is invisible, and imported targets carry that much float noise.
Functions§
- deserialise_
heightfield - Decode the baked-heightfield trailer from a static mesh payload, if present.
The trailer rides at the very end, so this walks past the vertex, LOD0
index, and optional LOD blocks positionally before reading the
"HFLD"block. ReturnsOk(None)for any payload without the trailer (i.e. every non-heightfield mesh) so callers can treat absence as “no baked collider”. - deserialise_
skinned - Deserialise a packed skinned-mesh payload produced by
serialise_skinned. The returned skeleton lives in the payload; the args JSON no longer needs to carry it. The optional LOD trailer is parsed and discarded; callers who need LOD alternates should usedeserialise_skinned_with_lods. - deserialise_
skinned_ with_ lods - Deserialise a packed skinned-mesh payload, also returning any optional
LOD trailer. Mirrors
deserialise_with_lodsfor static meshes: legacy single-LOD payloads have no trailer and produce an empty alternates vec. - deserialise_
with_ lods - Deserialise a packed payload, also returning any optional LOD trailer.
Legacy single-LOD payloads have no trailer and produce an empty
alternates vec; multi-LOD payloads parse the
"LODS"block after the LOD0 indices and return one entry per additional level. The order is preserved:alternates[i]is LODi + 1and applies at camera distance ≥alternates[i].0. - serialise
- Serialise vertex and index slices into the packed binary payload format. Each vertex tuple is (pos, normal, tangent, color, uv).
- serialise_
heightfield_ trailer - Serialise a baked-heightfield collider trailer:
"HFLD"magic,u32 rows,u32 cols, thenrows * colslittle-endian f32 heights in row-major order. Appended to a heightfield ProceduralMesh payload after the optional LOD trailer. - serialise_
skinned_ with_ lods - Serialise a multi-LOD skinned mesh. Two optional blocks ride after the
joint block, each announced by a magic:
"MRPS"(u32 target_count, per targetu32 name_byte_len+ name UTF-8 bytes, thenu32 entry_count,(vertex_count + 1) * 4bytes of u32 entry offsets andentry_count * 28bytes of sparseMorphEntrys, seePayloadMorphs) and"LODS"(u32 alt_count, then per alternatef32 switch_distance,u32 index_count,index_count * 2bytes of u16 indices). Empty morphs and alternates match the legacy single-LOD payload byte-for-byte. - serialise_
with_ lods - Serialise a multi-LOD mesh payload.
indicesis LOD0;lod_alternatesis the list of additional LODs (LOD1..N), each paired with the camera-distance threshold that triggers a switch to it. Whenlod_alternatesis empty this is byte-identical to the single-LODserialiseoutput, so the build can call this unconditionally.