@layoutit/polycss-core 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -102
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +1635 -177
- package/dist/index.d.ts +1635 -177
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,135 +1,202 @@
|
|
|
1
|
-
|
|
1
|
+
# PolyCSS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A CSS polygon mesh library. A 3D engine for the DOM. Renders OBJ/MTL, STL, glTF/GLB, and VOX as real HTML elements transformed with CSS `matrix3d(...)`. Supports colors, textures, lighting, shadows, shapes and animations. Works with React, Vue or plain JavaScript.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Visit [polycss.com](https://polycss.com) for docs and model examples.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<img width="1600" height="300" alt="PolyCSS primitives banner" src="https://github.com/user-attachments/assets/b05e2204-9323-4f83-8d1b-01ea0dd000db" />
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Installation
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
```bash
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# Vanilla
|
|
14
|
+
npm install @layoutit/polycss
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# React
|
|
17
|
+
npm install @layoutit/polycss-react
|
|
18
|
+
|
|
19
|
+
# Vue
|
|
20
|
+
npm install @layoutit/polycss-vue
|
|
18
21
|
|
|
19
|
-
```bash
|
|
20
|
-
npm install @layoutit/polycss-core
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
## Public surface
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
You can also load PolyCSS directly from a CDN. Here is a minimal custom-element scene:
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| `Vec2` | `[number, number]`: 2D point or UV coordinate |
|
|
30
|
-
| `Vec3` | `[number, number, number]`: 3D point or direction |
|
|
31
|
-
| `Polygon` | Single renderable polygon: `vertices`, optional `color`, `texture`, `uvs`, `data` |
|
|
32
|
-
| `PolyDirectionalLight` | Directional light: `direction`, optional `color`, optional `intensity` |
|
|
33
|
-
| `PolyAmbientLight` | Ambient fill light: optional `color`, optional `intensity` |
|
|
34
|
-
| `ParseResult` | Unified parser return: `polygons`, `objectUrls`, `dispose()`, `warnings` |
|
|
35
|
-
| `ObjParseOptions` | Options for `parseObj` |
|
|
36
|
-
| `GltfParseOptions` | Options for `parseGltf` |
|
|
37
|
-
| `VoxParseOptions` | Options for `parseVox` |
|
|
38
|
-
| `MtlParseResult` | `{ colors, textures }` from `parseMtl` |
|
|
39
|
-
| `NormalizeResult` | `{ polygons, warnings }` from `normalizePolygons` |
|
|
40
|
-
| `CameraState` | Camera target, angles, zoom, and dolly distance |
|
|
41
|
-
| `CameraHandle` | Mutable camera object from `createIsometricCamera` |
|
|
42
|
-
| `AutoRotateOption` | `boolean | number | { axis, speed, pauseOnInteraction }` |
|
|
43
|
-
| `BoxPolygonsOptions` | Options for `boxPolygons`: size/center or min/max bounds, materials, face overrides |
|
|
44
|
-
|
|
45
|
-
### Functions
|
|
46
|
-
|
|
47
|
-
| Function | Description |
|
|
48
|
-
|---|---|
|
|
49
|
-
| `normalizePolygons(input)` | Validates polygons. Drops degenerate ones, auto-triangulates non-coplanar N-gons, strips mismatched UVs. Returns `{ polygons, warnings }`. |
|
|
50
|
-
| `mergePolygons(polygons)` | Coplanar same-material adjacent merge. Reduces DOM element count on flat surfaces. |
|
|
51
|
-
| `optimizeMeshPolygons(polygons, options?)` | Applies lossless or lossy mesh-resolution optimization and chooses the smallest accepted candidate; defaults to `meshResolution: "lossy"`. |
|
|
52
|
-
| `computeSceneBbox(polygons)` | Computes min/max bounds across all polygon vertices. |
|
|
53
|
-
| `createIsometricCamera(initial?)` | Creates a mutable camera handle with `state`, `update(partial)`, and `getStyle()`. |
|
|
54
|
-
| `boxPolygons(options?)` | Creates six quad `Polygon`s for an axis-aligned box/cuboid. Supports per-face material/data overrides and omitted faces. |
|
|
55
|
-
| `parseObj(text, options?)` | Parses OBJ text into `ParseResult`. Supports UV (`vt`), materials, `map_Kd` textures. |
|
|
56
|
-
| `parseMtl(text)` | Parses MTL text into `{ colors, textures }`. |
|
|
57
|
-
| `parseGltf(buffer, options?)` | Parses GLB or glTF `ArrayBuffer` into `ParseResult`. Extracts embedded textures as blob URLs. |
|
|
58
|
-
| `parseVox(buffer, options?)` | Parses MagicaVoxel `.vox` `ArrayBuffer` into `ParseResult`. Face-culls interior voxel faces and emits exposed quads. `targetSize` snaps to integer voxel CSS cells for the fast-path renderer. |
|
|
59
|
-
| `loadMesh(url, options?)` | Fetches a URL, dispatches to the right parser by extension (`.obj`, `.glb`, `.gltf`, `.vox`). Returns `Promise<ParseResult>` and defaults to `meshResolution: "lossy"`. |
|
|
60
|
-
| `parseColor(input)` | Parse any CSS color string to `{ r, g, b, a }`. |
|
|
61
|
-
| `shadeColor(input, lambert, ...)` | Apply Lambert shading factor to a color. |
|
|
62
|
-
| `computeShapeLighting(normal, baseColor, light?)` | Compute shaded color for a polygon face given a directional light and surface normal. |
|
|
63
|
-
|
|
64
|
-
## Examples
|
|
65
|
-
|
|
66
|
-
### Parse an OBJ file
|
|
27
|
+
```html
|
|
28
|
+
<script type="module" src="https://esm.sh/@layoutit/polycss/elements"></script>
|
|
67
29
|
|
|
68
|
-
|
|
69
|
-
|
|
30
|
+
<poly-camera rot-x="65" rot-y="45">
|
|
31
|
+
<poly-scene>
|
|
32
|
+
<poly-orbit-controls drag wheel></poly-orbit-controls>
|
|
33
|
+
<poly-box size="100" color="#ffd166"></poly-box>
|
|
34
|
+
</poly-scene>
|
|
35
|
+
</poly-camera>
|
|
36
|
+
```
|
|
70
37
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
38
|
+
<img width="2500" height="1145" alt="PolyCSS intro" src="https://github.com/user-attachments/assets/0e5df0d8-04a8-4e50-8e3a-1097a96ce42f" />
|
|
39
|
+
|
|
40
|
+
## Framework Components
|
|
41
|
+
|
|
42
|
+
React and Vue expose the same component model. `<PolyCamera>` owns the viewpoint, `<PolyScene>` owns lighting and atlas options, and `<PolyMesh>` loads or receives polygon data.
|
|
76
43
|
|
|
77
|
-
|
|
78
|
-
|
|
44
|
+
```tsx
|
|
45
|
+
import { PolyCamera, PolyScene, PolyOrbitControls, PolyMesh } from "@layoutit/polycss-react";
|
|
79
46
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
47
|
+
export default function App() {
|
|
48
|
+
return (
|
|
49
|
+
<PolyCamera rotX={65} rotY={45}>
|
|
50
|
+
<PolyScene textureLighting="dynamic">
|
|
51
|
+
<PolyOrbitControls drag wheel />
|
|
52
|
+
<PolyMesh src="/gallery/obj/cottage.obj" mtl="/gallery/obj/cottage.mtl" />
|
|
53
|
+
</PolyScene>
|
|
54
|
+
</PolyCamera>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
83
57
|
```
|
|
84
58
|
|
|
85
|
-
|
|
59
|
+
## API Reference
|
|
86
60
|
|
|
87
|
-
|
|
88
|
-
import { normalizePolygons } from "@layoutit/polycss-core";
|
|
89
|
-
import type { Polygon } from "@layoutit/polycss-core";
|
|
61
|
+
### PolyCamera
|
|
90
62
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
- `rotX`, `rotY` control the orbit angle in degrees.
|
|
64
|
+
- `zoom` scales the projected scene.
|
|
65
|
+
- `target` pans the camera target in world coordinates.
|
|
66
|
+
- `distance` adds dolly pull-back.
|
|
67
|
+
- `PolyCamera` is the orthographic default. Use `PolyPerspectiveCamera` when you want perspective depth.
|
|
96
68
|
|
|
97
|
-
|
|
98
|
-
console.log(polygons.length); // 2 (degenerate dropped; quad fan-triangulated into 2)
|
|
99
|
-
warnings.forEach(w => console.warn(w));
|
|
100
|
-
```
|
|
69
|
+
### PolyScene
|
|
101
70
|
|
|
102
|
-
|
|
71
|
+
- `polygons` renders a static `Polygon[]` directly.
|
|
72
|
+
- `directionalLight` and `ambientLight` control scene lighting.
|
|
73
|
+
- `textureLighting` chooses `"baked"` or `"dynamic"`.
|
|
74
|
+
- `textureQuality` controls atlas raster budget.
|
|
75
|
+
- `strategies` can disable selected render strategies for diagnostics.
|
|
76
|
+
- `autoCenter` rotates around the rendered mesh bounds instead of world origin.
|
|
103
77
|
|
|
104
|
-
|
|
105
|
-
|
|
78
|
+
### PolyMesh
|
|
79
|
+
|
|
80
|
+
- `src` loads `.obj`, `.gltf`, `.glb`, or `.vox` files.
|
|
81
|
+
- `mtl` loads companion OBJ materials.
|
|
82
|
+
- `polygons` accepts pre-parsed geometry.
|
|
83
|
+
- `position`, `scale`, and `rotation` transform the mesh wrapper.
|
|
84
|
+
- `autoCenter` shifts the mesh bbox center to local origin.
|
|
85
|
+
- `meshResolution` chooses `"lossy"` (default) or `"lossless"` optimization. STL imports use the conservative lossless path in both modes.
|
|
86
|
+
- `castShadow` emits CSS-projected shadows in dynamic lighting mode.
|
|
87
|
+
|
|
88
|
+
### Controls
|
|
106
89
|
|
|
107
|
-
|
|
108
|
-
|
|
90
|
+
- `<PolyOrbitControls>` adds drag orbit, shift-drag pan, wheel zoom, and optional auto-rotate.
|
|
91
|
+
- `<PolyMapControls>` uses pan-first map-style input.
|
|
92
|
+
- `<PolyFirstPersonControls>` provides keyboard and pointer-look navigation.
|
|
93
|
+
- `<PolyTransformControls>` adds translate/rotate gizmos for selected mesh handles.
|
|
109
94
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
### Snapshot Export
|
|
96
|
+
|
|
97
|
+
The vanilla package exports `exportPolySceneSnapshot(target)`. It clones the current rendered `.polycss-camera` / `.polycss-scene` DOM, injects only the PolyCSS CSS needed by that snapshot, inlines CSS `url(...)` image assets as `data:image/...;base64,...`, strips scripts and inline event handlers, and returns a standalone HTML document string with no PolyCSS runtime import. It works with rendered React/Vue scenes too; import it from `@layoutit/polycss` and pass the rendered camera or scene element.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { exportPolySceneSnapshot } from "@layoutit/polycss";
|
|
113
101
|
|
|
114
|
-
|
|
102
|
+
const html = await exportPolySceneSnapshot(scene.host);
|
|
115
103
|
```
|
|
116
104
|
|
|
117
|
-
|
|
105
|
+
If any referenced asset cannot be inlined, the function throws `PolySceneSnapshotError` with `code: "ASSET_INLINE_FAILED"`.
|
|
106
|
+
|
|
107
|
+
### Polygon Data Model
|
|
108
|
+
|
|
109
|
+
Each polygon describes one renderable face:
|
|
118
110
|
|
|
119
111
|
```ts
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
texture: "/tile.png",
|
|
130
|
-
data: { face: "top" },
|
|
131
|
-
},
|
|
132
|
-
bottom: false,
|
|
112
|
+
const polygons = [
|
|
113
|
+
{
|
|
114
|
+
vertices: [[0, 0, 0], [60, 0, 0], [0, 60, 0]],
|
|
115
|
+
color: "#f97316",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
vertices: [[0, 0, 0], [60, 0, 0], [60, 60, 0], [0, 60, 0]],
|
|
119
|
+
texture: "/texture.png",
|
|
120
|
+
uvs: [[0, 0], [1, 0], [1, 1], [0, 1]],
|
|
133
121
|
},
|
|
122
|
+
];
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Render polygons directly when you need per-face DOM events or custom styling:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
<PolyCamera>
|
|
129
|
+
<PolyScene>
|
|
130
|
+
{polygons.map((polygon, index) => (
|
|
131
|
+
<Poly
|
|
132
|
+
key={index}
|
|
133
|
+
{...polygon}
|
|
134
|
+
onClick={() => console.log("clicked polygon", index)}
|
|
135
|
+
className="my-polygon"
|
|
136
|
+
/>
|
|
137
|
+
))}
|
|
138
|
+
</PolyScene>
|
|
139
|
+
</PolyCamera>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Loading Mesh Files
|
|
143
|
+
|
|
144
|
+
Use `loadMesh()` to parse supported model formats:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { createPolyCamera, createPolyScene, loadMesh } from "@layoutit/polycss";
|
|
148
|
+
|
|
149
|
+
const host = document.getElementById("polycss")!;
|
|
150
|
+
const camera = createPolyCamera({ rotX: 65, rotY: 45 });
|
|
151
|
+
const scene = createPolyScene(host, { camera });
|
|
152
|
+
|
|
153
|
+
const mesh = await loadMesh("https://polycss.com/gallery/obj/cottage.obj", {
|
|
154
|
+
mtlUrl: "https://polycss.com/gallery/obj/cottage.mtl",
|
|
134
155
|
});
|
|
156
|
+
|
|
157
|
+
scene.add(mesh);
|
|
135
158
|
```
|
|
159
|
+
|
|
160
|
+
Supported formats:
|
|
161
|
+
|
|
162
|
+
- OBJ + MTL, including `map_Kd` textures and UV coordinates.
|
|
163
|
+
- STL triangle meshes, including binary Magics face colors. STL has no standard units, textures, UVs, or hierarchy, so imports skip lossy simplification and ray-based interior culling.
|
|
164
|
+
- glTF / GLB, including embedded images and `TEXCOORD_0`.
|
|
165
|
+
- MagicaVoxel `.vox`, with direct voxel fast paths when eligible.
|
|
166
|
+
- Generated primitives: box, plane, ring, sphere, torus, cylinder, cone, and Platonic solids.
|
|
167
|
+
|
|
168
|
+
## Performance
|
|
169
|
+
|
|
170
|
+
PolyCSS renders through the DOM, so performance is mostly shaped by two things: the number of mounted leaves, and the amount of texture atlas area the browser has to paint. The renderer tries to keep the common cases cheap. Simple surfaces stay as solid CSS elements, while textured, irregular, or high-detail geometry falls back to atlas-backed slices only when needed.
|
|
171
|
+
|
|
172
|
+
Each visible polygon is emitted as one leaf element; the renderer chooses the least expensive CSS primitive that can represent the polygon, then uses `matrix3d(...)` to place that primitive in 3D space.
|
|
173
|
+
|
|
174
|
+
- `<b>` uses `background: currentColor` on a fixed box for solid rectangles and stable quads.
|
|
175
|
+
- `<u>` uses `corner-shape` for stable triangles and beveled-corner solids, with a `border-width` triangle fallback when needed.
|
|
176
|
+
- `<i>` clips solid polygons with `border-shape: polygon(...)` when the browser supports it.
|
|
177
|
+
- `<s>` maps a packed texture-atlas slice with `background-image`, and is the fallback for textured or unsupported shapes.
|
|
178
|
+
|
|
179
|
+
## Packages
|
|
180
|
+
|
|
181
|
+
| Package | Description |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `@layoutit/polycss-core` | Pure math, parsers, lighting, camera helpers, mesh optimization. Zero browser globals. |
|
|
184
|
+
| `@layoutit/polycss` | Vanilla custom elements and imperative `createPolyScene` API. |
|
|
185
|
+
| `@layoutit/polycss-react` | React components, hooks, controls, and core re-exports. |
|
|
186
|
+
| `@layoutit/polycss-vue` | Vue 3 components, composables, controls, and core re-exports. |
|
|
187
|
+
|
|
188
|
+
## Made with PolyCSS
|
|
189
|
+
|
|
190
|
+
[Layoutit Voxels](https://voxels.layoutit.com)
|
|
191
|
+
-> A CSS Voxel editor
|
|
192
|
+
|
|
193
|
+
<img width="1000" height="600" alt="layoutit-voxels" src="https://polycss.com/layoutit-voxels.png" />
|
|
194
|
+
|
|
195
|
+
[Layoutit Terra](https://terra.layoutit.com)
|
|
196
|
+
-> A CSS Terrain Generator
|
|
197
|
+
|
|
198
|
+
<img width="1000" height="601" alt="layoutit-terra" src="https://polycss.com/layoutit-terra.png" />
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT.
|