Core Concepts
This page covers the mental model behind polycss. Each section describes a building block and how it composes with the others.
A single block
Section titled “A single block”Where voxcss used to render a single voxel cube, polycss renders any regular polyhedron the same way: each face becomes one DOM element. The dodecahedron below is 12 native pentagons (not 36 triangles) — flip the shape selector to see how the same renderer handles every Platonic solid.
Three building blocks
Section titled “Three building blocks”polycss exposes three composable concepts. Each one ships as a custom element (vanilla) and as a React / Vue component:
- Scene (
<poly-scene>/PolyScene) — the 3D viewport. Sets up perspective, camera angle, and lighting. Fills its parent element. - Mesh (
<poly-mesh>/PolyMesh) — loads a mesh from a URL (OBJ / glTF / GLB). Internally expands to one polygon child per face. Convenience wrapper around the parser + renderer. - Polygon (
<poly-polygon>/Poly) — one polygon. The atomic primitive. Renders one atlas-backed<i>withtransform: matrix3d(...). Accepts standard DOM event handlers, classes, and styles — this is what makes polycss “DOM-native 3D” rather than “3D inside a black-box canvas”.
A mesh element is internally polygons.map(p => <poly-polygon …>), so any rendered mesh can be inspected, styled, or handled per-polygon.
Camera
Section titled “Camera”The scene element accepts camera attributes / props directly: rot-x / rotX, rot-y / rotY, perspective, and directional-light / directionalLight. There is also a PolyCamera React / Vue wrapper for separating camera state from scene layout — vanilla users set the same fields directly on <poly-scene>.
<!-- Vanilla --><poly-scene perspective="1000" rot-x="65" rot-y="45" directional-light='{"direction":[0.5,-0.7,0.6],"color":"#ffe4a8","ambient":0.4}'> <poly-mesh src="/cottage.glb"></poly-mesh></poly-scene>// React<PolyScene perspective={1000} rotX={65} rotY={45} directionalLight={{ direction: [0.5, -0.7, 0.6], color: "#ffe4a8", ambient: 0.4, }}> <PolyMesh src="/cottage.glb" /></PolyScene>See PolyCamera for the full prop table, defaults, and usage patterns.
Polygon Data Model
Section titled “Polygon Data Model”Each polygon is a plain object. The only required field is vertices (three or more [x, y, z] points in world space):
interface Polygon { vertices: [number, number, number][]; // Required — 3+ [x, y, z] points in world space color?: string; // CSS color ("#f97316", "tomato") texture?: string; // Image URL for UV-mapped face uvs?: [number, number][]; // UV coordinates (one per vertex) data?: Record<string, string | number | boolean>; // Reflected as data-* DOM attributes}Because polygons are plain objects, you can generate them from loops, load them from parsers, or compute them from any data source.
World coordinate convention
Section titled “World coordinate convention”Polycss world space: +X right, +Y forward (into screen), +Z up. The camera’s default rotX=65, rotY=45 gives a classic isometric angle. Parsers (parseObj, parseGltf) normalize imported coordinates to this convention.
(0,0,0) origin and autoCenter
Section titled “(0,0,0) origin and autoCenter”Scene content renders relative to the (0,0,0) origin. Most mesh files are authored with the model at an arbitrary offset. Use autoCenter (vanilla: auto-center) on the mesh element to shift the mesh’s bounding-box center to the origin before applying your position offset:
<!-- Vanilla --><poly-mesh src="/cottage.glb" auto-center position="[0,0,0]"></poly-mesh>// React<PolyMesh src="/cottage.glb" autoCenter position={[0, 0, 0]} />Rendering Pipeline
Section titled “Rendering Pipeline”polycss is structured in three layers:
- Core (
@polycss/core) — Pure math and parsing. Handles OBJ / glTF / GLB parsing, UV decoding, lighting math, and polygon normalization. No DOM dependency. - Triangle Renderer — Takes parsed polygons and produces DOM elements. It runs a one-time off-DOM canvas atlas pass for both textured and flat-color polygons (UV affine transform when available → clip → drawImage or fill → atlas Blob URL → CSS background-position).
- Entry points — The vanilla
polycsspackage exposes custom elements (<poly-scene>,<poly-mesh>,<poly-polygon>) plus an imperativecreatePolySceneAPI; this is the default surface and what the rest of these docs use first. Thin React (@polycss/react) and Vue (@polycss/vue) bindings (PolyScene,PolyMesh,Poly,PolyCamera) wrap the same renderer with framework-native reactivity, lifecycle, and prop updates.
Merge Modes
Section titled “Merge Modes”The merge attribute / prop on the scene controls whether coplanar same-material polygons are merged before rendering:
"off"(default) — No merging. Every parsed polygon is its own DOM element. Full per-polygon control."auto"— Merge coplanar adjacent polygons with identical material. Reduces DOM element count for dense flat surfaces without changing visual output.
See the Performance guide for guidance on choosing a mode.
Related
Section titled “Related”- Quickstart — Install + first scene walkthrough.
- PolyCamera — Camera props reference.
- PolyScene — Scene props and polygon data reference.
- Performance — Merge modes and DOM tuning.