Skip to content

Headless API

The glyphcss vanilla package exposes a glyph-shaped imperative API plus the raw glyph-core math primitives.

The main entry point. Creates and mounts a scene into a host element and returns a GlyphSceneHandle with methods to add meshes, hotspots, and update options. Always construct a camera first and pass it in.

import { createGlyphCamera, createGlyphScene } from "glyphcss";
const host = document.querySelector<HTMLElement>("#scene")!;
const camera = createGlyphCamera({ rotX: 25, zoom: 50 });
const scene = createGlyphScene(host, {
camera,
mode: "solid", // "wireframe" | "solid" | "voxel"
cols: 100, // grid width in character columns
rows: 30, // grid height in character rows
cellAspect: 2.0, // cell height ÷ width (typical monospace: ~2.0)
glyphPalette: "default", // named glyph palette
useColors: true, // emit color <span>s in output
directionalLight: { direction: [0.5, 0.7, 0.5], intensity: 1 },
ambientLight: { intensity: 0.4 },
});

Register a Polygon[] as a mesh. Returns a GlyphMeshHandle.

import { cubePolygons } from "@glyphcss/core";
const meshHandle = scene.add(
cubePolygons({ center: [0, 0, 0], size: 1, color: "#4488ff" }),
{
position: [1, 0, 0], // translate in world space
scale: 0.8, // uniform scale (or [sx, sy, sz])
rotation: [0, 45, 0], // XYZ Euler angles in degrees
}
);
// Later, update the transform and re-render:
meshHandle.setTransform({ position: [2, 0, 0] });
scene.rerender();
// Remove the mesh:
meshHandle.dispose();

Update any scene option. Triggers an automatic re-render.

scene.setOptions({
mode: "wireframe",
cols: 120,
rows: 36,
directionalLight: { direction: [1, 0.5, 0.2], intensity: 1.2 },
});

Remove the scene DOM and clear all registered meshes and hotspots.

scene.destroy();

The following snippet covers add, setOptions, addHotspot, and destroy in one runnable block:

import {
createGlyphCamera,
createGlyphScene,
createGlyphOrbitControls,
} from "glyphcss";
import { cubePolygons, octahedronPolygons, axesHelperPolygons } from "@glyphcss/core";
const host = document.querySelector<HTMLElement>("#scene")!;
// 1. Create the camera first.
const camera = createGlyphCamera({ rotX: 25, zoom: 50 });
// 2. Create the scene with the camera.
const scene = createGlyphScene(host, { camera, mode: "solid", cols: 100, rows: 30 });
// 3. Add meshes. Each call returns a handle.
const cubeHandle = scene.add(
cubePolygons({ center: [-1, 0, 0], size: 0.8, color: "#4488ff" })
);
const octaHandle = scene.add(
octahedronPolygons({ center: [1, 0, 0], size: 0.8, color: "#ffcc44" })
);
scene.add(axesHelperPolygons({ size: 1.5 }));
// 4. Add a hotspot.
const hotspot = scene.addHotspot(
{ id: "octa-top", at: [1, 0.8, 0], size: [4, 2] },
() => alert("octahedron top"),
);
// 5. Attach orbit controls.
const controls = createGlyphOrbitControls(scene, { drag: true, wheel: true });
// 6. Update options at any time.
scene.setOptions({ mode: "wireframe" });
// 7. Move a mesh.
cubeHandle.setTransform({ position: [-2, 0, 0] });
scene.rerender();
// 8. Cleanup everything.
hotspot.remove();
controls.destroy();
octaHandle.dispose();
cubeHandle.dispose();
scene.destroy();

Two cameras: orthographic (default, createGlyphCamera) and perspective. First-person view is createGlyphPerspectiveCamera + createGlyphFirstPersonControls.

import {
createGlyphCamera,
createGlyphPerspectiveCamera,
createGlyphOrthographicCamera,
} from "glyphcss";
// Orthographic — default alias, best for voxel/iso scenes
const camera = createGlyphCamera({ rotX: 25, zoom: 50 });
// Orthographic — explicit form
const ortho = createGlyphOrthographicCamera({ rotX: 25, zoom: 50 });
// Perspective — foreshortened; required for first-person controls
const perspective = createGlyphPerspectiveCamera({
rotX: 25, rotY: 0,
distance: 3, zoom: 50, stretch: 0.95,
});
// All camera properties are mutable after creation:
perspective.rotY = 45;
perspective.distance = 4;
// Swap the camera on a running scene:
scene.setOptions({ camera: ortho });

glyph-core is browser-agnostic (no DOM globals) and can run in Node or a web worker.

import {
buildSceneContext,
rasterize,
projectHotspots,
icosahedronPolygons,
} from "glyph-core";
import { createGlyphPerspectiveCamera } from "glyphcss";
const triangles = icosahedronPolygons({ center: [0, 0, 0], size: 1, color: "#44ffcc" });
const camera = createGlyphPerspectiveCamera({ rotX: 25, zoom: 50 });
const grid = { cols: 160, rows: 48, cellAspect: 2.0 };
const ctx = buildSceneContext({ camera, grid, triangles, mode: "solid" });
// Rasterize one frame to a string:
const text = rasterize(ctx);
// Project hotspots to grid cells:
const cells = projectHotspots(
[{ id: "top", at: [0, 1, 0] }],
camera, 160, 48, 2.0,
);
// cells is { id, col, row, depth, visible }[]