3D
import * as ThreeD from "tts/3d"
Perspective projection plus pen-drawn 3D: wireframes, filled triangles with back-face culling, and sprites placed in 3D space.
See examples/3d-demo: WASD / arrows to walk and turn, Q/E to look up and down.

import * as ThreeD from "tts/3d";
import * as Input from "tts/input";
whenFlag(() => {
me.visible = false; // the pen draws even while the sprite is hidden
ThreeD.setCamera(0, 60, -400, 0, -10);
forever(() => {
ThreeD.cam3d.yaw += Input.axisX() * 3;
ThreeD.moveForward(Input.axisY() * 8);
penClear();
setPenColor("#4C97FF");
ThreeD.grid(0, 80, 12);
setPenColor("#FFFFFF");
ThreeD.cube(0, 40, 200, 80);
});
});
World axes: x right, y up, z forward. Angles are in degrees; positive yaw turns right and positive pitch looks up.
Camera​
setCamera(x, y, z, yaw, pitch) | position and orientation |
moveForward(d) / strafe(d) | walk relative to the yaw |
setFov(scale) | projection scale (300 by default; larger zooms in) |
cam3d.camX, camY, camZ, yaw, pitch, fov | the shared camera; change it directly |
Drawing​
Set the pen colour first; each primitive draws with the current pen.
line3d(x1, y1, z1, x2, y2, z2) | a line (skipped if an end is behind the camera) |
box(x, y, z, w, h, d) / cube(x, y, z, size) | wireframe boxes |
grid(height, cell, count) | a floor grid |
triangle3d(...9 numbers) | a filled triangle |
setCulling(true) | skip triangles facing away (wind faces counter-clockwise as seen from outside) |
line2d(x0, y0, x1, y1) / fillTriangle(...) | screen-space versions, clipped to the stage |
Projection and sprites​
project(x, y, z) | returns false if the point is behind the camera; otherwise sets sx, sy, depth |
placeSprite(x, y, z, baseSize) | show this sprite at a 3D point, scaled by distance |
rotate(x, z, angle) | rotate around the y axis; sets rx, rz |
Tips​
- Draw 3D with one hidden sprite that has a tiny costume, and call
penClear()at the start of each frame. - Put the drawing in a
/** @warp */function, or use the engine functions (already warped), so each frame draws all at once. - There's no depth buffer: draw far objects first, and use culling for closed shapes.
- Pen drawing costs time per line, so keep scenes to a few hundred lines per frame.