Loading Meshes
polycss loads 3D mesh files (OBJ, GLB, glTF) and renders them as DOM elements. UV textures are extracted from the file and packed into generated atlas pages; each textured polygon is an atlas-backed <i> that uses CSS background positioning.
Live demo — UV-textured GLB
Section titled “Live demo — UV-textured GLB”The tree below uses tree.glb, which has embedded UV textures. Each textured triangle is a DOM sprite whose background is a generated atlas page.
Declarative loading — the mesh element
Section titled “Declarative loading — the mesh element”The simplest way to render a mesh is the mesh element with a src. It fetches the file, parses it, and renders one polygon element per polygon automatically.
<script type="module" src="https://esm.sh/polycss/elements"></script>
<poly-scene rot-x="65" rot-y="45"> <poly-mesh src="/cottage.glb"></poly-mesh></poly-scene>import { PolyScene, PolyMesh } from "@polycss/react";
export function App() { return ( <PolyScene rotX={65} rotY={45}> <PolyMesh src="/cottage.glb" /> </PolyScene> );}<template> <PolyScene :rot-x="65" :rot-y="45"> <PolyMesh src="/cottage.glb" /> </PolyScene></template>
<script setup lang="ts">import { PolyScene, PolyMesh } from "@polycss/vue";</script>Supported formats
Section titled “Supported formats”| Format | Extension | Notes |
|---|---|---|
| OBJ + MTL | .obj + .mtl | Text format. UV maps via vt. Material textures from map_Kd. |
| glTF | .gltf | JSON format. Embedded or external buffers. TEXCOORD_0 UVs. |
| GLB | .glb | Binary glTF. Embedded textures extracted as blob URLs. |
OBJ with MTL
Section titled “OBJ with MTL”When your OBJ has a companion MTL file with textures, polycss reads map_Kd entries and applies them as UV-mapped textures. Pass mtlUrl (vanilla attribute) or mtlUrl prop:
<!-- Vanilla --><poly-mesh src="/rock.obj" mtl-url="/rock.mtl" target-size="40"></poly-mesh>// React / Vue<PolyMesh src="/rock.obj" mtlUrl="/rock.mtl" options={{ targetSize: 40 }}/>Material overrides
Section titled “Material overrides”Override material colors or textures without modifying the source files (React / Vue prop form):
<PolyMesh src="/character.obj" options={{ materialColors: { Skin: "#f4c2a1" }, materialTextures: { Body: "/body-diffuse.png" }, includeObjects: ["Body", "Head"], // only these objects }}/>Imperative loading
Section titled “Imperative loading”For programmatic loading with explicit lifecycle, use loadMesh from the core parser. This is the universal vanilla path; React adds a useMesh hook on top:
// Vanilla — works anywhere, no frameworkimport { loadMesh, createPolyScene } from "polycss";
const result = await loadMesh("/cottage.glb", { targetSize: 60 });const scene = createPolyScene(document.getElementById("host")!);scene.add(result);// later:result.dispose(); // revoke blob URLsscene.remove();// React — useMesh wraps loadMesh + dispose() on unmountimport { PolyScene, Poly, useMesh } from "@polycss/react";
function Viewer() { const { polygons, loading, error } = useMesh("/cottage.glb");
if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error}</div>;
return ( <PolyScene> {polygons.map((p, i) => <Poly key={i} {...p} />)} </PolyScene> );}Atlas pipeline
Section titled “Atlas pipeline”For both textured and flat-color polygons, polycss runs a one-time atlas canvas pass at mount:
- Extract the texture image from the file (or fetch it by URL) when the polygon has a texture.
- Solve a 6-DOF affine transform from the polygon’s UV coordinates to its 2D screen footprint when UVs are available.
- Pack polygon footprints into one or more atlas pages.
- Clip, draw texture pixels or shaded color fills, and export atlas pages to blob URLs via
canvas.toBlob().atlasScalecan rasterize these pages below full CSS resolution to reduce memory. - Render each polygon as an
<i>withbackground-image,background-size, andbackground-position.
Generated atlas blob URLs are revoked on unmount (call dispose() or let PolyMesh / useMesh handle it).
targetSize— scale the model so its longest axis fits this many world units (default: no scaling). Set it to roughly match the scale of your other scene content.atlasScale— lower the generated atlas bitmap scale for dense or distant textured assets.0.5uses about one quarter of the atlas bitmap memory of1.baseUrl— for OBJ/glTF files with external texture paths, pass the file’s URL so relative paths resolve correctly.- For large meshes: blob URLs for embedded textures and generated atlases are revoked when
dispose()is called. Always let polycss manage this — don’t hold references to blob URLs across remounts.
Related
Section titled “Related”- PolyScene — Scene props.
- Per-polygon Interaction — Click handlers and hover states on individual polygons.
- Performance — Merge modes and DOM tuning.
- Headless API —
loadMesh,parseObj,parseGltfsignatures.