Skip to content

Models & media

The five examples the gallery lists under Models & media. Each block is what the gallery’s code panel shows beside that example, copied from the example itself: the lines that do it rather than the whole file, so it isn’t compiled here the way the guides’ code is. The file it came from is linked under each one.

A glTF file, loaded once and instanced, with failures reported back.

// A path, on as many objects as want it.
OrblitObject(
key: 600,
transform: placement,
colour: Vector3(0.72, 0.13, 0.08), // used only if the file will not load
mesh: '/Users/you/models/crate.glb',
)
// Parsed once and kept, however many objects name it: a scene arrives on
// every frame of a drag, and re-reading a glTF at that rate is unusable.
// The second object using a file gets another instance of it rather than
// another copy.
// What could not be loaded comes back from the publish rather than going to
// a log, so a host can name the asset it is missing.
OrblitView(
scene: scene,
onSceneNotes: (notes) => setState(() => note = notes.values.first),
)

From meshes.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='meshes' flutter run -d macos

Clips, material variants and lights out of glTF files, named by the files themselves.

// What a file holds comes back from the renderer as it is loaded.
OrblitView(
scene: scene,
onAssetInfo: (info) => setState(() => models[info.path] = info),
)
// A clip by the file's own name, fading in from the one before.
final info = models['orblit:resource/fox.glb']!;
OrblitObject(
key: 1,
transform: placement,
colour: grey,
mesh: 'orblit:resource/fox.glb',
animation: OrblitAnimation(
clip: info.clipNamed('Run')!,
seconds: seconds,
speed: 1,
from: OrblitAnimation(clip: info.clipNamed('Walk')!, seconds: seconds),
fade: 0.5,
),
)
// A look the file comes in, by its name.
OrblitObject(..., variant: info.variants.indexOf('beach'))
// The file's lights, as ordinary lights that shadow like any other.
lights: [...info.lightsFor(placement, keyOf: (i) => 100 + i)],

From imported.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='imported models' flutter run -d macos

A cloud of 3D Gaussians, drawn as ellipses, sorted back to front off the render thread and held to what the device can carry.

// What this device can carry, asked of the view once its renderer is up.
final device = await OrblitView.profileOf(viewport);
// A capture from a file: the reference trainer's .ply, or a compact .splat.
OrblitSplats(
key: 1,
path: 'garden.ply',
// Structure-from-motion puts y down. Turned the right way up here.
transform: Matrix4.rotationX(math.pi),
// How much of the capture's view-dependent colour to read: 16 bytes a splat
// for each degree, so a small device reads less of it.
harmonics: device.harmonicDegree,
// Keeps the most opaque and largest splats, and never sends the rest to the
// GPU at all.
limit: device.splatBudget,
// Sixteen bits of depth where a full sort would lag a turning camera.
coarseOrder: device.coarseSplatOrder,
)
// Or a cloud made in Dart, packed into the same 32-byte layout.
final data = OrblitSplats.pack(
positions: positions, // three floats a splat, metres
scales: scales, // three standard deviations a splat, metres
colours: colours, // RGBA, nought to one; alpha is peak opacity
rotations: rotations, // quaternions, (w, x, y, z)
);
OrblitSplats(key: 1, data: data, revision: revision)
// Sorted back to front whenever the camera moves — on a thread of the
// renderer's own, or a Web Worker in a browser — leaving out what the camera
// cannot see. Drawn after the solid scene, tested against its depth, never
// writing any.

From splats.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='gaussian splats' flutter run -d macos

Pixel art in layers: one draw a layer, drawn in order, and a backdrop that scrolls without resending a tile.

// The sheet, as bytes: from an asset, a download or, here, painted in code.
await OrblitResources.provide('orblit:resource/sheet.png', png);
final atlas = Atlas.grid(image: 'sheet', imageWidth: 64, imageHeight: 64,
cellWidth: 16, cellHeight: 16);
// A layer is one image and any number of rectangles of it: one draw.
final uv = atlas['frame_0']!.uv(64, 64);
OrblitSprites(
key: 2,
image: const OrblitTexture('orblit:resource/sheet.png'),
sprites: OrblitSprites.pack([
OrblitSprite(x: 0, y: 0, u0: uv.u0, v0: uv.v0, u1: uv.u1, v1: uv.v1),
]),
revision: revision, // bump when the sprites change
)
// A backdrop scrolls by its layer's transform, and sends no tiles to do it.
OrblitSprites(key: 1, sprites: tiles, order: -10,
transform: Matrix4.translationValues(scroll, 0, 0))
// Seen through an orthographic camera, graded straight through.
OrblitCamera(position: Vector3(0, 0, 20), target: Vector3.zero(),
orthographic: true, viewHeight: 18)

From sprites.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='sprites' flutter run -d macos

A film on four screens from one decoder, tinted, faded and played backwards — set ORBLIT_VIDEO or paste a path.

// The film is on the scene, not on the material. One decoder, however many
// screens are showing it.
OrblitScene(
videos: [
OrblitVideo(key: 1, path: '/path/to/a.mp4', playing: true, loop: true),
],
materials: [
// A screen: unlit, because it makes its own light, and the base colour
// tints the frame rather than replacing it.
OrblitMaterial(
key: 10,
shading: OrblitShading.video,
video: 1,
baseColour: Vector4(1, 1, 1, 1),
),
],
objects: [OrblitObject(key: 10, material: 10, transform: ..., colour: ...)],
camera: camera,
);
// Seeking is an event and the scene is a description, so a token reconciles
// them: the renderer jumps when the token moves, not when the target does.
OrblitVideo(key: 1, path: ..., seekTo: 12.0, seekToken: ++token);

From video.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='video' flutter run -d macos