Mesh is a packed local surface: positions and normals are Tensor[f32] values,
and indices are Tensor[u32] triangles. Its procedural dimensions and
Vec3 transforms are Number values (the language’s f64 representation), then
Rust checks the conversion into the packed f32 buffers. Rust owns construction,
validation, normal generation and retained-allocation limits. A browser or
native adapter receives the resulting geometry and frame; it does not implement
another mesh language.
Make a mesh
Procedural methods start with Mesh {} and return Res[Mesh, DataError].
Dimensions are metres; resolution arguments must be valid integers. Use ? to
propagate a rejected shape, or use match when the program can recover.
| Method | Arguments | Result |
|---|---|---|
sphere(radius, rings, segments) | positive radius, two resolutions | UV sphere |
torus(major, minor, rings, sides) | positive radii, two resolutions | Y-axis torus |
cone(radius, height, segments) | positive dimensions and resolution | capped cone |
grid(width, depth, columns, rows) | positive XZ dimensions and resolution | upward-facing grid |
lathe(profile, segments) | Tensor[f32] shaped [N, 2] of radius/height points | revolved profile |
suzanne() | none | supplied Suzanne mesh |
decode_json(chunks) | List[Str] containing SDK Mesh JSON | checked imported mesh |
// First scene: move the cyan sphere by editing one number.
let floor = spawn(Mesh {}.grid(3, 3, 6, 6)?);
add(floor, Material {
color: "#17152a",
roughness: 0.9
});
let orb = spawn(
Mesh {}.sphere(0.35, 12, 16)?.translated(Vec3 {
x: 0.6,
y: 0.35
})?
);
add(orb, Material {
color: "#7ee7ff",
roughness: 0.18,
emissive: 0.25
});
let ring = spawn(
Mesh {}.torus(0.65, 0.06, 20, 8)?.rotated(Vec3 {
x: 1.5707963267948966
})?
);
add(ring, Material {
color: "#ffcb72",
roughness: 0.28
});
The Kreate examples use these exact methods. A mesh never bypasses its data
contract: malformed dimensions, topology and over-budget allocations return a
DataError rather than panicking or retaining a partial scene. One mesh is
limited to 16,384 vertices and 98,304 indices; the spatial adapter also bounds
the aggregate scene geometry.
Blender imports keep transforms, materials and hierarchy in main.kj, with
mesh data in separate geometry_N modules. Those modules use decode_json to
load positions, normals and indices as data. Each string chunk is limited to
16 KiB, and the combined JSON to 8 MiB; the same mesh and runtime limits still
apply. The decoder does not read files, fetch URLs or execute source.
Transform or map it
Meshes are values. translated(Vec3), scaled(Vec3) and rotated(Vec3) each
return a new checked mesh. Their vector is respectively metres, per-axis scale,
and XYZ radians. Transformed normals are recomputed correctly; negative scale
reverses winding.
mapped(func(Vec3) -> Res[Vec3, DataError]) calls a typed mapper once for every
vertex, derives smooth normals after the mapping, and rejects the whole result
if the mapper returns Err. This is a geometry operation with a bounded work
cost, not a renderer shader hook.
// Wave pavilion: change the sine amplitude below to reshape the roof.
func wave(point: Vec3) -> Res[Vec3, DataError] {
ret Ok(Vec3 {
x: point.x,
y: (point.x.sin()? * 0.28)?,
z: point.z
});
}
let roof = spawn(
Mesh {}.grid(5, 3, 20, 12)?
.mapped(wave)?
.translated(Vec3 { y: 1.5 })?
);
add(roof, Material {
color: "#7ee7ff",
roughness: 0.25,
emissive: 0.15
});
for x in [-2, -1, 0, 1, 2] {
let post = spawn(
Mesh {}.cone(0.08, 1.5, 10)?.translated(Vec3 {
x: x,
y: 0.75,
z: -1.2
})?
);
add(post, Material {
color: "#27233e",
roughness: 0.75
});
}
let floor = spawn(Mesh {}.grid(5.5, 3.5, 8, 6)?);
add(floor, Material {
color: "#17152a",
roughness: 0.95
});
Compose local transforms
Attach Parent { entity: root } to make an entity’s Transform local to a
parent. Rust resolves the entity reference; the spatial adapter rejects missing
targets, self-parenting, cycles and excessive depth before producing the scene
frame. An entity with no visible mesh can remain as a group when the hierarchy
needs it.
let root = spawn(Transform { position: Vec3 { y: 1 } });
let child = spawn(Mesh {}.sphere(0.2, 8, 12)?);
add(child, Parent { entity: root });
add(child, Transform { position: Vec3 { x: -0.7 } });The child’s authored transform remains local; the SDK composes it with the parent when evaluating the frame. See Spatial applications for materials, controls and physics, and open these scenes from Examples to change them in Kreate.