DOCUMENTATION / examples/kart3d/assets/README.md
Sunline Sprint original assets
These small, original meshes were authored for this example. The red kart,
purple-haired driver, folded cape, leafy trees and hilltop keep follow the
grassland art direction in generated/concepts/bytorio_kart/. No third-party
model, texture or character data is included.
The editable workshop source is ../tools/assets.mjs.
It exports generateAssets() for the example's mise build/generation tasks.
The checked .gltf files are standard glTF 2.0 artist inputs and may also be
edited in a glTF-capable modeling tool. Regeneration replaces those edits, so
either keep changes in the workshop source or intentionally adopt the edited
glTF as the new source. The asset generator does not write SDK modules.
Import the checked model using the regular SDK pipeline:
mise run byt -- import examples/kart3d/assets/kart-lod.gltf --output examples/kart3d/build/imported/kart
The other .gltf files use the same command with a dedicated output directory.
kart-low.gltf and kart-high.gltf are complete standalone artist models with
identical named nodes and pivots. kart-lod.gltf stores their shared parts once
for runtime selection. Load one of these three inputs, according to the game’s
needs; the combined asset does not require loading the standalone variants.
Each source references the adjacent atlas.png, a 16×16 opaque RGBA8 texture.
It uses nearest sampling and clamp addressing. There are no extensions, skins,
animation tracks or lighting dependencies. All assets require the existing
SDK 0.4.0 textured-3d-preview-1 profile or a compatible later profile.
Scale and animation
After import, +Y is up, +Z is forward and X spans the axle. The root sits on the road plane at Y=0. Source glTF Z is reflected by the workshop writer because the importer restores the console coordinate convention. The wheel radius is 0.390625 units; the chassis is roughly 2.4 units long and the driver reaches 2.4375 units high. The cape trails to Z=-1.796875. No global rescaling is needed for the existing course.
| Node | Parent | Imported local translation | Purpose |
|---|---|---|---|
body |
root | 0, 0, 0 | Chassis, seat, engine, hood, exhausts and bumpers |
driver |
body |
0, 0, 0 | Torso, arms, steering bar, head and sculpted hair |
cape |
driver |
0, 1.34375, -0.4375 | Neck pivot for rigid cape motion |
wheel_front_left |
body |
-0.890625, 0.390625, 0.71875 | Steering and axle rotation |
wheel_front_right |
body |
0.890625, 0.390625, 0.71875 | Steering and axle rotation |
wheel_rear_left |
body |
-0.9375, 0.390625, -0.765625 | Axle rotation |
wheel_rear_right |
body |
0.9375, 0.390625, -0.765625 | Axle rotation |
All four wheel nodes share one mesh. Multiply each bind transform by a local rotation to retain its pivot. Rotate the wheels around X to roll and the front wheels around Y to steer. The cape is a separate five-triangle folded surface; a small Y rotation adds motion without rebuilding geometry. Driver geometry uses the kart origin, so a small Y rotation turns its silhouette around the seat; the cape inherits that rotation.
Runtime quality selection
The high model adds cooling fins, a seat hoop, side rails, bumper guards, an open steering rim, gloves, eyes, extra hair locks and sixteen-sided wheels. The low model keeps the same silhouette and uses eight-sided wheels. This is a geometry choice independent of CPU/GPU rendering; either host can draw either version.
The combined asset contains the seven animation nodes above plus three detached
resource nodes: body_detail, driver_detail and wheel_high. The detached
nodes identify additional mesh resources; their identity matrices do not define
where those details should be drawn. The game draws them using the animated
body, driver and wheel transforms already calculated for the corresponding
base parts. Use the generated instance's meshes and material with
draw_textured to select the required parts; calling the generic model draw
function would render every node, including the detached alternatives.
| Primitive index (Odin / Luau) | Geometry | Low quality | High quality |
|---|---|---|---|
| 0 / 1 | Body | once at body transform | once at body transform |
| 1 / 2 | Driver | once at driver transform | once at driver transform |
| 2 / 3 | Cape | once at cape transform | once at cape transform |
| 3 / 4 | Eight-sided wheel | once at each wheel transform | omitted |
| 4 / 5 | Body details | omitted | once at body transform |
| 5 / 6 | Driver details | omitted | once at driver transform |
| 6 / 7 | Sixteen-sided wheel | omitted | once at each wheel transform |
All primitives use material index 0 in Odin or 1 in Luau. The low selection is seven draws and 314 triangles; the high selection is nine draws and 600 triangles. A distance rule, host preference or player option can select quality without creating resources again. Keep cape/steering/rolling transforms common to both selections so switching quality does not move animated parts.
Create one resource instance per imported asset and reuse it for repeated
draws. Independent transforms do not require independent resource instances.
The one-node scenery assets have their base at Y=0: tree is about 4.23 units
tall, castle is 15.2 units tall and 11.3 units wide, and roadside is a
0.95-unit rock and wildflower cluster.
Resource costs
Counts below are measured through the existing importer, including its normalized vertex/index representation and the atlas upload. Generated source sizes include the standard formatters. These are asset costs, not a scene triangle cap or a performance measurement.
| Asset | Unique vertices | Unique triangles | Triangles per draw of the complete model | Meshes / draws | Upload bytes | Luau / Odin source bytes |
|---|---|---|---|---|---|---|
| Kart low | 259 | 218 | 314 | 4 / 7 | 9,888 | 39,344 / 43,175 |
| Kart high | 445 | 408 | 600 | 4 / 7 | 16,632 | 61,952 / 64,063 |
| Kart LOD collection | 495 | 440 | 314 or 600 selected | 7 / 7 or 9 selected | 18,216 | 66,932 / 69,260 |
| Tree | 41 | 44 | 44 | 1 / 1 | 2,568 | 15,265 / 19,732 |
| Castle | 155 | 88 | 88 | 1 / 1 | 5,832 | 24,990 / 29,272 |
| Roadside | 42 | 22 | 22 | 1 / 1 | 2,328 | 14,272 / 19,005 |
Each imported module owns one texture and one material. Loading several modules duplicates the 1,024-byte atlas, while repeated draws of the same instance share it. All generated modules remain below the importer source-size bound. The game still needs to fit its complete SDK, source, commands and resources within its selected profile.
The atlas tiles, in row order, are red paint, shaded red, charcoal, steel, tire tread, purple, shaded purple, skin, ivory, gold, light foliage, dark foliage, bark, masonry, wheel hub and asphalt. Tiles are 4×4 texels; UVs stay inside each tile to prevent nearest-sampling seams. Painted solid faces sample a tile's center and share indexed vertices; tire, hub, stone, bark and asphalt surfaces use UV patterns. The base-color/flat-normal import path provides the final runtime lighting.
Get started