Creating Shapes
This guide covers building Polygon[] arrays by hand, using the built-in
geometry helpers from @glyphcss/core, and generating procedural meshes from math
functions. All examples are self-contained — copy any block and it will run.
From scratch: a tetrahedron
Section titled “From scratch: a tetrahedron”A tetrahedron has 4 vertices and 4 triangular faces. The simplest approach: write
the vertices as a Vec3[] and the face indices by hand, then map to polygons.
import { createGlyphCamera, createGlyphScene } from "glyphcss";import type { Polygon, Vec3 } from "@glyphcss/core";
// 4 vertices of a regular tetrahedron (circumradius ≈ 1).const s = 1 / Math.sqrt(3);const verts: Vec3[] = [ [ s, s, s], // 0 [-s, -s, s], // 1 [-s, s, -s], // 2 [ s, -s, -s], // 3];
// 4 CCW-from-outside triangular faces.const faceIndices: [number, number, number][] = [ [0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3],];
const polygons: Polygon[] = faceIndices.map(([a, b, c]) => ({ vertices: [verts[a], verts[b], verts[c]], color: "#aaffcc",}));
// Render it.const host = document.querySelector<HTMLElement>("#scene")!;const camera = createGlyphCamera({ rotX: 25 });const scene = createGlyphScene(host, { camera, mode: "solid", cols: 80, rows: 24 });scene.add(polygons);The resulting Polygon[] is a flat array — no scene graph, no hierarchy.
Each element has vertices: Vec3[] and an optional color hex string.
The rasterizer fan-triangulates N-gons internally.
Built-in helpers
Section titled “Built-in helpers”@glyphcss/core ships geometry generators for all common shapes. Each returns
Polygon[] — pass directly to scene.add() or to the GlyphMesh polygons prop.
Platonic solids
Section titled “Platonic solids”tetrahedronPolygons
Section titled “tetrahedronPolygons”4 triangular faces. size is the circumradius.
import { tetrahedronPolygons } from "@glyphcss/core";
const polys = tetrahedronPolygons({ center: [0, 0, 0], size: 1, color: "#ff6644",});// Returns Polygon[] — 4 triangular polygons.cubePolygons
Section titled “cubePolygons”6 square faces. size is the edge length.
import { cubePolygons } from "@glyphcss/core";
const polys = cubePolygons({ center: [0, 0, 0], size: 1, color: "#4488ff",});// Returns Polygon[] — 6 quad polygons.octahedronPolygons
Section titled “octahedronPolygons”8 triangular faces. size is the half-extent (distance from center to each pole).
import { octahedronPolygons } from "@glyphcss/core";
const polys = octahedronPolygons({ center: [0, 0, 0], size: 1, color: "#ffcc44",});// Returns Polygon[] — 8 triangular polygons.dodecahedronPolygons
Section titled “dodecahedronPolygons”12 pentagonal faces. size is the circumradius. Vertices follow the golden-ratio
form; winding is CCW from outside, same as three.js DodecahedronGeometry.
import { dodecahedronPolygons } from "@glyphcss/core";
const polys = dodecahedronPolygons({ center: [0, 0, 0], size: 1, color: "#cc44ff",});// Returns Polygon[] — 12 pentagonal polygons.icosahedronPolygons
Section titled “icosahedronPolygons”20 triangular faces. size is the circumradius.
import { icosahedronPolygons } from "@glyphcss/core";
const polys = icosahedronPolygons({ center: [0, 0, 0], size: 1, color: "#44ffcc",});// Returns Polygon[] — 20 triangular polygons.Utility shapes
Section titled “Utility shapes”planePolygons
Section titled “planePolygons”A single axis-aligned quad. axis picks the perpendicular direction (0=YZ, 1=XZ,
2=XY); size is the half-extent of the quad.
import { planePolygons } from "@glyphcss/core";
const polys = planePolygons({ axis: 1, // quad lies in the XZ plane size: 0.4, color: "#ffffff",});// Returns Polygon[] — 1 quad polygon.ringPolygons
Section titled “ringPolygons”A flat annulus (ring) perpendicular to a chosen axis. Made of segments quads
around the circle.
import { ringPolygons } from "@glyphcss/core";
const polys = ringPolygons({ axis: 1, // ring perpendicular to Y axis radius: 1.2, halfThickness: 0.05, segments: 32, color: "#ff4488",});// Returns Polygon[] — 32 quad segments forming the annulus.axesHelperPolygons
Section titled “axesHelperPolygons”Three thin colored cuboids along world X (red), Y (green), Z (blue). Mirrors the
three.js AxesHelper gizmo.
import { axesHelperPolygons } from "@glyphcss/core";
const polys = axesHelperPolygons({ size: 2, thickness: 0.02, negative: false, // only positive halves xColor: "#ff3a3a", yColor: "#3aff3a", zColor: "#3a8aff",});// Returns Polygon[] — 18 quads (6 per axis bar × 3 axes).Combining shapes
Section titled “Combining shapes”Stack multiple meshes in one scene by calling scene.add() for each, or by
composing multiple framework components.
import { GlyphCamera, GlyphScene, GlyphMesh, GlyphOrbitControls,} from "@glyphcss/react";import { cubePolygons, octahedronPolygons, axesHelperPolygons } from "@glyphcss/core";
// Build each shape once (outside render).const cube = cubePolygons({ center: [-1.5, 0, 0], size: 0.8, color: "#4488ff" });const octa = octahedronPolygons({ center: [0, 0, 0], size: 0.8, color: "#ffcc44" });const axes = axesHelperPolygons({ size: 1.5 });
export function App() { return ( <GlyphCamera rotX={25}> <GlyphScene mode="solid" cols={120} rows={36}> <GlyphOrbitControls /> <GlyphMesh polygons={cube} /> <GlyphMesh polygons={octa} /> <GlyphMesh polygons={axes} /> </GlyphScene> </GlyphCamera> );}<template> <GlyphCamera :rot-x="25"> <GlyphScene mode="solid" :cols="120" :rows="36"> <GlyphOrbitControls /> <GlyphMesh :polygons="cube" /> <GlyphMesh :polygons="octa" /> <GlyphMesh :polygons="axes" /> </GlyphScene> </GlyphCamera></template>
<script setup lang="ts">import { GlyphCamera, GlyphScene, GlyphMesh, GlyphOrbitControls,} from "@glyphcss/vue";import { cubePolygons, octahedronPolygons, axesHelperPolygons } from "@glyphcss/core";
const cube = cubePolygons({ center: [-1.5, 0, 0], size: 0.8, color: "#4488ff" });const octa = octahedronPolygons({ center: [0, 0, 0], size: 0.8, color: "#ffcc44" });const axes = axesHelperPolygons({ size: 1.5 });</script>import { createGlyphCamera, createGlyphScene } from "glyphcss";import { cubePolygons, octahedronPolygons, axesHelperPolygons } from "@glyphcss/core";
const host = document.querySelector<HTMLElement>("#scene")!;const camera = createGlyphCamera({ rotX: 25 });const scene = createGlyphScene(host, { camera, mode: "solid", cols: 120, rows: 36 });
scene.add(cubePolygons({ center: [-1.5, 0, 0], size: 0.8, color: "#4488ff" }));scene.add(octahedronPolygons({ center: [0, 0, 0], size: 0.8, color: "#ffcc44" }));scene.add(axesHelperPolygons({ size: 1.5 }));Mesh from a math function
Section titled “Mesh from a math function”Generate arbitrary surfaces with a for loop. This example builds a wavy plane
by pushing two triangles per grid cell. You can also push quads (4 vertices) —
the rasterizer fan-triangulates them automatically.
import { createGlyphCamera, createGlyphScene } from "glyphcss";import type { Polygon, Vec3 } from "@glyphcss/core";
const COLS = 20;const ROWS = 20;const SIZE = 2;
function waveY(x: number, z: number, t = 0): number { return Math.sin(x * 3 + t) * 0.15 + Math.cos(z * 2.5 + t) * 0.1;}
function makeGrid(): Polygon[] { const polygons: Polygon[] = [];
for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c++) { const x0 = (c / COLS - 0.5) * SIZE; const x1 = ((c + 1) / COLS - 0.5) * SIZE; const z0 = (r / ROWS - 0.5) * SIZE; const z1 = ((r + 1) / ROWS - 0.5) * SIZE;
const v00: Vec3 = [x0, waveY(x0, z0), z0]; const v10: Vec3 = [x1, waveY(x1, z0), z0]; const v01: Vec3 = [x0, waveY(x0, z1), z1]; const v11: Vec3 = [x1, waveY(x1, z1), z1];
polygons.push({ vertices: [v00, v10, v11], color: "#33aaff" }); polygons.push({ vertices: [v00, v11, v01], color: "#2299ee" }); } } return polygons;}
const host = document.querySelector<HTMLElement>("#scene")!;const camera = createGlyphCamera({ rotX: 25 });const scene = createGlyphScene(host, { camera, mode: "solid", cols: 100, rows: 30 });scene.add(makeGrid());Each cell produces two triangular polygons sharing the quad diagonal v00→v11.
To animate the wave, call handle.dispose() and scene.add(makeGrid(newTime))
after each camera-end event — do not call it every frame.