Sprites.Scene
A small three dimensional engine, built on the same reactive model as Sprites.Image. A point starts in the local space of the transform around it; Translate and the three Rotate commands nest to build that transform. A command maps its points to world space, the camera projects them to the drawing plane, and the shape draws through the Sprites.Image commands, so a scene is just lines and polygons projected onto an image. Draw inside a Sprites.Ui.Scene.Vector.
- Sprites.Scene.Line
- Sprites.Scene.Square
- Sprites.Scene.LineStyle
- Sprites.Scene.FillStyle
- Sprites.Scene.Translate
- Sprites.Scene.RotateX
- Sprites.Scene.RotateY
- Sprites.Scene.RotateZ
- Sprites.Scene.RotateAndZoom
Sprites.Scene.Line Void
Sprites.Scene.Line(x1, y1, z1, x2, y2, z2)
Draw a line between two points, in the current line style. The points are in the space of the transform around the command; each coordinate may be a constant or a reactive value. The example is a hollow cube, twelve edges drawn with lines from -1 to 1 and no transforms at all.
| Input | Type | Description |
|---|---|---|
x1, y1, z1 | Number or Sprites.Reactive.Value | The first point. |
x2, y2, z2 | Number or Sprites.Reactive.Value | The second point. |
Returns nothing.
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#0f172a', () => {
Sprites.Scene.Line(-1, -1, -1, 1, -1, -1);
Sprites.Scene.Line(1, -1, -1, 1, -1, 1);
Sprites.Scene.Line(1, -1, 1, -1, -1, 1);
Sprites.Scene.Line(-1, -1, 1, -1, -1, -1);
Sprites.Scene.Line(-1, 1, -1, 1, 1, -1);
Sprites.Scene.Line(1, 1, -1, 1, 1, 1);
Sprites.Scene.Line(1, 1, 1, -1, 1, 1);
Sprites.Scene.Line(-1, 1, 1, -1, 1, -1);
Sprites.Scene.Line(-1, -1, -1, -1, 1, -1);
Sprites.Scene.Line(1, -1, -1, 1, 1, -1);
Sprites.Scene.Line(1, -1, 1, 1, 1, 1);
Sprites.Scene.Line(-1, -1, 1, -1, 1, 1);
});
});
});
Sprites.Scene.Square Void
Sprites.Scene.Square(x1, y1, x2, y2)
Draw a filled square in the Z = 0 plane of the current transform, its corners at (x1, y1), (x2, y1), (x2, y2) and (x1, y2). It is filled when a FillStyle is in scope and stroked when a LineStyle is. Its local normal is +Z; when the transform turns that away from the camera the square is culled, so only faces turned toward you draw. The example is a cube: six squares, each moved and turned into place by a small tree of transforms, and each a different colour.
| Input | Type | Description |
|---|---|---|
x1, y1 | Number or Sprites.Reactive.Value | One corner in the Z = 0 plane. |
x2, y2 | Number or Sprites.Reactive.Value | The opposite corner. |
Returns nothing.
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#0f172a', () => {
Sprites.Scene.FillStyle('#ef4444', () => {
Sprites.Scene.Translate(0, 0, 1, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
Sprites.Scene.FillStyle('#f97316', () => {
Sprites.Scene.Translate(0, 0, -1, () => {
Sprites.Scene.RotateY(Math.PI, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
Sprites.Scene.FillStyle('#22c55e', () => {
Sprites.Scene.Translate(1, 0, 0, () => {
Sprites.Scene.RotateY(Math.PI / 2, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
Sprites.Scene.FillStyle('#3b82f6', () => {
Sprites.Scene.Translate(-1, 0, 0, () => {
Sprites.Scene.RotateY(-Math.PI / 2, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
Sprites.Scene.FillStyle('#eab308', () => {
Sprites.Scene.Translate(0, 1, 0, () => {
Sprites.Scene.RotateX(-Math.PI / 2, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
Sprites.Scene.FillStyle('#a855f7', () => {
Sprites.Scene.Translate(0, -1, 0, () => {
Sprites.Scene.RotateX(Math.PI / 2, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
});
});
});
Sprites.Scene.LineStyle Void
Sprites.Scene.LineStyle(thickness, colour, build)
Set the line style for the build subtree. A scene draws through the image commands, so this is Sprites.Image.LineStyle: everything drawn inside strokes with this thickness and colour until a nearer LineStyle overrides it. The example draws the three axes as lines, each in its own style.
| Input | Type | Description |
|---|---|---|
thickness | Number or Sprites.Reactive.Value | The stroke width, in drawing units. |
colour | String or Sprites.Reactive.Value | The stroke colour. |
build | Function | The scene subtree that draws in this style. |
Returns nothing.
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.05, '#dc2626', () => {
Sprites.Scene.Line(-1.4, 0, 0, 1.4, 0, 0);
});
Sprites.Scene.LineStyle(0.025, '#2563eb', () => {
Sprites.Scene.Line(0, -1.4, 0, 0, 1.4, 0);
});
Sprites.Scene.LineStyle(0.01, '#16a34a', () => {
Sprites.Scene.Line(0, 0, -1.4, 0, 0, 1.4);
});
});
});
Sprites.Scene.FillStyle Void
Sprites.Scene.FillStyle(colour, build)
Set the fill colour for the build subtree. A scene draws through the image commands, so this is Sprites.Image.FillStyle: a Square drawn inside fills with this colour until a nearer FillStyle overrides it. The example draws two squares, one in each fill.
| Input | Type | Description |
|---|---|---|
colour | String or Sprites.Reactive.Value | The fill colour. |
build | Function | The scene subtree that fills in this colour. |
Returns nothing.
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#1e293b', () => {
Sprites.Scene.FillStyle('#f472b6', () => {
Sprites.Scene.Translate(-0.55, 0, 0.35, () => {
Sprites.Scene.Square(-0.7, -0.7, 0.7, 0.7);
});
});
Sprites.Scene.FillStyle('#38bdf8', () => {
Sprites.Scene.Translate(0.55, 0, -0.35, () => {
Sprites.Scene.Square(-0.7, -0.7, 0.7, 0.7);
});
});
});
});
});
Sprites.Scene.Translate Void
Sprites.Scene.Translate(x, y, z, build)
Move the build subtree by (x, y, z) in the directions of the current transform, then draw it. Translates and Rotates nest to place a shape. The offsets may be reactive, so a slider moves the subtree live. The example is a square you slide along each axis.
| Input | Type | Description |
|---|---|---|
x, y, z | Number or Sprites.Reactive.Value | The offset, in the current transform. |
build | Function | The scene subtree that is moved. |
Returns nothing.
const tx = Sprites.Reactive.Value(0);
const ty = Sprites.Reactive.Value(0.5);
const tz = Sprites.Reactive.Value(0);
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#065f46', () => {
Sprites.Scene.FillStyle('#34d399', () => {
Sprites.Scene.Translate(tx, ty, tz, () => {
Sprites.Scene.Square(-0.7, -0.7, 0.7, 0.7);
});
});
});
});
});
Sprites.Ui.Layout.Row(() => {
Sprites.Ui.Content.Text('x');
Sprites.Ui.Input.Slider(tx, -2, 2, 0.05);
Sprites.Ui.Content.Text('y');
Sprites.Ui.Input.Slider(ty, -2, 2, 0.05);
Sprites.Ui.Content.Text('z');
Sprites.Ui.Input.Slider(tz, -2, 2, 0.05);
});
Sprites.Scene.RotateX Void
Sprites.Scene.RotateX(angle, build)
Turn the build subtree by angle radians about the X axis of the current transform, then draw it. The angle may be reactive, so a slider turns the subtree live. The example is a square you tilt about X; turn it past edge-on and its back face is culled until it comes round to face you again.
| Input | Type | Description |
|---|---|---|
angle | Number or Sprites.Reactive.Value | The turn about X, in radians. |
build | Function | The scene subtree that is turned. |
Returns nothing.
const angle = Sprites.Reactive.Value(0.6);
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#7c2d12', () => {
Sprites.Scene.FillStyle('#fb923c', () => {
Sprites.Scene.RotateX(angle, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
});
});
Sprites.Ui.Layout.Row(() => {
Sprites.Ui.Content.Text('angle');
Sprites.Ui.Input.Slider(angle, -3.14, 3.14, 0.01);
});
Sprites.Scene.RotateY Void
Sprites.Scene.RotateY(angle, build)
Turn the build subtree by angle radians about the Y axis of the current transform, then draw it. The angle may be reactive. The example is a square you swing about Y.
| Input | Type | Description |
|---|---|---|
angle | Number or Sprites.Reactive.Value | The turn about Y, in radians. |
build | Function | The scene subtree that is turned. |
Returns nothing.
const angle = Sprites.Reactive.Value(0.6);
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#155e75', () => {
Sprites.Scene.FillStyle('#22d3ee', () => {
Sprites.Scene.RotateY(angle, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
});
});
Sprites.Ui.Layout.Row(() => {
Sprites.Ui.Content.Text('angle');
Sprites.Ui.Input.Slider(angle, -3.14, 3.14, 0.01);
});
Sprites.Scene.RotateZ Void
Sprites.Scene.RotateZ(angle, build)
Turn the build subtree by angle radians about the Z axis of the current transform, then draw it. The angle may be reactive. The example is a square you spin about Z. Because Z is the square’s own normal, it spins in place and never turns away, so it is never culled.
| Input | Type | Description |
|---|---|---|
angle | Number or Sprites.Reactive.Value | The turn about Z, in radians. |
build | Function | The scene subtree that is turned. |
Returns nothing.
const angle = Sprites.Reactive.Value(0.6);
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#4c1d95', () => {
Sprites.Scene.FillStyle('#a78bfa', () => {
Sprites.Scene.RotateZ(angle, () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
});
});
Sprites.Ui.Layout.Row(() => {
Sprites.Ui.Content.Text('angle');
Sprites.Ui.Input.Slider(angle, -3.14, 3.14, 0.01);
});
Sprites.Scene.RotateAndZoom Void
Sprites.Scene.RotateAndZoom()
Capture the pointer over the surface: a drag orbits the camera about the origin, and the wheel moves it in and out. It reads the camera from the scene in scope and writes it, so a look-around tool is just this one command placed in the scene. The example is a single square you can orbit; being in the Z = 0 plane, it turns edge-on and culls as you go round the back.
Takes no arguments.
Returns nothing.
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('image-frame');
Sprites.Ui.Dom.Style('width', '100%');
Sprites.Ui.Dom.Style('height', '220px');
Sprites.Ui.Scene.Vector(() => {
Sprites.Scene.RotateAndZoom();
Sprites.Scene.LineStyle(0.02, '#0f172a', () => {
Sprites.Scene.FillStyle('#38bdf8', () => {
Sprites.Scene.Square(-1, -1, 1, 1);
});
});
});
});