@layoutit/polycss-core 0.2.7 → 0.2.8
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 +53 -5
- package/dist/camera-VU-yix11.d.cts +304 -0
- package/dist/camera-VU-yix11.d.ts +304 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -304
- package/dist/index.d.ts +4 -304
- package/dist/index.js +1 -1
- package/dist/three.cjs +1 -0
- package/dist/three.d.cts +108 -0
- package/dist/three.d.ts +108 -0
- package/dist/three.js +1 -0
- package/package.json +13 -1
package/README.md
CHANGED
|
@@ -21,7 +21,6 @@ npm install @layoutit/polycss-vue
|
|
|
21
21
|
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
You can also load PolyCSS directly from a CDN. Here is a minimal custom-element scene:
|
|
26
25
|
|
|
27
26
|
```html
|
|
@@ -39,7 +38,7 @@ You can also load PolyCSS directly from a CDN. Here is a minimal custom-element
|
|
|
39
38
|
|
|
40
39
|
## Framework Components
|
|
41
40
|
|
|
42
|
-
React and Vue expose the same component model. `<PolyCamera>` owns the viewpoint, `<PolyScene>` owns lighting and
|
|
41
|
+
React and Vue expose the same component model. `<PolyCamera>` owns the viewpoint, `<PolyScene>` owns lighting and options, and `<PolyMesh>` loads or receives polygon data.
|
|
43
42
|
|
|
44
43
|
```tsx
|
|
45
44
|
import { PolyCamera, PolyScene, PolyOrbitControls, PolyMesh } from "@layoutit/polycss-react";
|
|
@@ -56,6 +55,54 @@ export default function App() {
|
|
|
56
55
|
}
|
|
57
56
|
```
|
|
58
57
|
|
|
58
|
+
## Three.js Parity API
|
|
59
|
+
|
|
60
|
+
When porting Three.js scenes or generating code with an agent, use the explicit
|
|
61
|
+
`*/three` subpaths:
|
|
62
|
+
|
|
63
|
+
- `@layoutit/polycss-core/three`
|
|
64
|
+
- `@layoutit/polycss/three`
|
|
65
|
+
- `@layoutit/polycss-react/three`
|
|
66
|
+
- `@layoutit/polycss-vue/three`
|
|
67
|
+
|
|
68
|
+
They expose Three-like `PerspectiveCamera`, `OrthographicCamera`, `Object3D`,
|
|
69
|
+
`Vector3`, `DirectionalLight`, `PointLight`, `AmbientLight`, radians for object
|
|
70
|
+
rotations, Y-up authoring coordinates, and `camera.position` + `camera.lookAt(...)`
|
|
71
|
+
framing. The adapters convert into native PolyCSS coordinates with a right-handed
|
|
72
|
+
axis map, so the apparent object size, projection, orientation, depth ordering,
|
|
73
|
+
and light direction line up with Three.js scene math while still rendering
|
|
74
|
+
through the DOM.
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { PolyScene } from "@layoutit/polycss-react";
|
|
78
|
+
import {
|
|
79
|
+
DirectionalLight,
|
|
80
|
+
PolyThreeMesh,
|
|
81
|
+
PolyThreePerspectiveCamera,
|
|
82
|
+
} from "@layoutit/polycss-react/three";
|
|
83
|
+
|
|
84
|
+
const sun = new DirectionalLight("#ffffff", 1);
|
|
85
|
+
sun.position.set(3, 5, 4);
|
|
86
|
+
sun.target.position.set(0, 0, 0);
|
|
87
|
+
|
|
88
|
+
export function App() {
|
|
89
|
+
return (
|
|
90
|
+
<PolyThreePerspectiveCamera
|
|
91
|
+
fov={50}
|
|
92
|
+
aspect={16 / 9}
|
|
93
|
+
position={[3, 2, 5]}
|
|
94
|
+
lookAt={[0, 0, 0]}
|
|
95
|
+
>
|
|
96
|
+
<PolyScene directionalLight={sun.toPolyDirectionalLight()}>
|
|
97
|
+
<PolyThreeMesh src="/models/cube.glb" rotation={[0, Math.PI / 4, 0]} />
|
|
98
|
+
</PolyScene>
|
|
99
|
+
</PolyThreePerspectiveCamera>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Full reference: [polycss.com/api/three-parity](https://polycss.com/api/three-parity).
|
|
105
|
+
|
|
59
106
|
## API Reference
|
|
60
107
|
|
|
61
108
|
### PolyCamera
|
|
@@ -187,10 +234,11 @@ Each visible polygon is emitted as one leaf element; the renderer chooses the le
|
|
|
187
234
|
|
|
188
235
|
## Made with PolyCSS
|
|
189
236
|
|
|
190
|
-
[
|
|
191
|
-
-> A CSS
|
|
237
|
+
[cssQuake](https://cssquake.com)
|
|
238
|
+
-> A CSS port of Quake (1996)
|
|
239
|
+
|
|
240
|
+
<img width="1280" height="720" alt="quake" src="https://github.com/user-attachments/assets/6d9d809c-857a-4a39-b5cf-733ead2661ec" />
|
|
192
241
|
|
|
193
|
-
<img width="1000" height="600" alt="layoutit-voxels" src="https://polycss.com/layoutit-voxels.png" />
|
|
194
242
|
|
|
195
243
|
[Layoutit Terra](https://terra.layoutit.com)
|
|
196
244
|
-> A CSS Terrain Generator
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
declare const DEFAULT_PROJECTION: "cubic";
|
|
2
|
+
/**
|
|
3
|
+
* How polygon lighting is applied by DOM renderers.
|
|
4
|
+
* - "baked": multiply the light tint into the off-DOM canvas before the
|
|
5
|
+
* polygon becomes an atlas sprite. Best fidelity (full RGB tint) but
|
|
6
|
+
* the atlas re-rasterizes whenever the light changes.
|
|
7
|
+
* - "dynamic": lighting computed entirely in CSS via per-polygon normals
|
|
8
|
+
* embedded in calc() and scene-root light vars (background-color +
|
|
9
|
+
* background-blend-mode multiply, masked by the atlas alpha). Atlas
|
|
10
|
+
* stays light-independent — sliding the light only writes a few CSS
|
|
11
|
+
* variables, no JS work, no atlas re-rasterization.
|
|
12
|
+
*/
|
|
13
|
+
type PolyTextureLightingMode = "baked" | "dynamic";
|
|
14
|
+
type PolyTextureLeafSizing = "canonical" | "local" | "raster";
|
|
15
|
+
type PolyTextureBackend = "auto" | "atlas" | "image";
|
|
16
|
+
type PolyTextureImageRendering = "auto" | "pixelated";
|
|
17
|
+
type PolyTextureImageLighting = "scene" | "source";
|
|
18
|
+
type PolyTextureProjection = "affine" | "projective";
|
|
19
|
+
interface PolyTextureImageSource {
|
|
20
|
+
url: string;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
sourceRect?: {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
};
|
|
29
|
+
imageRendering?: PolyTextureImageRendering;
|
|
30
|
+
}
|
|
31
|
+
interface PolyTexturePresentation {
|
|
32
|
+
imageRendering?: PolyTextureImageRendering;
|
|
33
|
+
backend?: PolyTextureBackend;
|
|
34
|
+
lighting?: PolyTextureImageLighting;
|
|
35
|
+
projection?: PolyTextureProjection;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Mesh post-processing intent.
|
|
39
|
+
* - "lossless": preserve the authored surface while applying exact
|
|
40
|
+
* reductions such as interior culling and coplanar merge.
|
|
41
|
+
* - "lossy": allow bounded geometric approximation when it reduces the
|
|
42
|
+
* rendered polygon/DOM count.
|
|
43
|
+
*/
|
|
44
|
+
type MeshResolution = "lossless" | "lossy";
|
|
45
|
+
/**
|
|
46
|
+
* 3D point/vector, stored as a `[x, y, z]` tuple. Tuple (rather than
|
|
47
|
+
* `{x, y, z}`) for compact JSON: meshes serialize to thousands of vertices
|
|
48
|
+
* and the difference adds up. Destructure with `const [x, y, z] = v` when
|
|
49
|
+
* you need named axes.
|
|
50
|
+
*
|
|
51
|
+
* PolyCSS world space convention: +X right, +Y forward, +Z up.
|
|
52
|
+
*/
|
|
53
|
+
type Vec3 = [number, number, number];
|
|
54
|
+
/**
|
|
55
|
+
* 2D point/vector — `[u, v]`. Used for texture-atlas UV coordinates on
|
|
56
|
+
* polygons. Convention follows OBJ: u is horizontal (0=left, 1=right),
|
|
57
|
+
* v is vertical (0=bottom, 1=top). Renderers flip v when binding to raster
|
|
58
|
+
* image space whose Y-axis points down.
|
|
59
|
+
*/
|
|
60
|
+
type Vec2 = [number, number];
|
|
61
|
+
interface TextureTriangle {
|
|
62
|
+
vertices: [Vec3, Vec3, Vec3];
|
|
63
|
+
uvs: [Vec2, Vec2, Vec2];
|
|
64
|
+
}
|
|
65
|
+
type PolyTextureWrapMode = "repeat" | "clamp-to-edge" | "mirrored-repeat";
|
|
66
|
+
interface PolyTextureWrap {
|
|
67
|
+
s: PolyTextureWrapMode;
|
|
68
|
+
t: PolyTextureWrapMode;
|
|
69
|
+
}
|
|
70
|
+
type PolyTextureAlphaMode = "opaque" | "mask" | "blend";
|
|
71
|
+
/**
|
|
72
|
+
* Directional light — simulates a single distant source (sun, key light).
|
|
73
|
+
* Contributes Lambert shading scaled by `intensity`. `direction` is in
|
|
74
|
+
* scene-local CSS-pixel coords and does not need to be pre-normalized.
|
|
75
|
+
* Mirrors three.js's `DirectionalLight`.
|
|
76
|
+
*/
|
|
77
|
+
interface PolyDirectionalLight {
|
|
78
|
+
/** Unit direction from the surface toward the distant light source. */
|
|
79
|
+
direction: Vec3;
|
|
80
|
+
/** Light tint, hex string. White by default. */
|
|
81
|
+
color?: string;
|
|
82
|
+
/** Scalar multiplier on the directional contribution. Default 1. */
|
|
83
|
+
intensity?: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Point light — radiates from a world-space position. Contributes per-face
|
|
87
|
+
* Lambert like a directional light, but the light direction is computed
|
|
88
|
+
* per polygon (face centroid → light position) rather than being global.
|
|
89
|
+
*
|
|
90
|
+
* DIRECTION-ONLY by design: there is no distance falloff (no `decay`/
|
|
91
|
+
* `distance`). A point light differs from a directional light only in that
|
|
92
|
+
* its direction varies per face. To emulate in three.js for parity, use
|
|
93
|
+
* `new THREE.PointLight(color, intensity, 0, 0)` (distance 0, decay 0 →
|
|
94
|
+
* no attenuation). Shading is flat per face (the centroid direction), so it
|
|
95
|
+
* approximates three.js's per-fragment gradient — exact for small faces /
|
|
96
|
+
* distant lights, never a CSS gradient.
|
|
97
|
+
*/
|
|
98
|
+
interface PolyPointLight {
|
|
99
|
+
/** World-space position the light radiates from. */
|
|
100
|
+
position: Vec3;
|
|
101
|
+
/** Light tint, hex string. White by default. */
|
|
102
|
+
color?: string;
|
|
103
|
+
/** Scalar multiplier on the contribution. Default 1. */
|
|
104
|
+
intensity?: number;
|
|
105
|
+
/** When true, this light casts shadows (radial projection). Default false. */
|
|
106
|
+
castShadow?: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ambient light — uniform fill that adds to every polygon regardless of
|
|
110
|
+
* orientation. Mirrors three.js's `AmbientLight`. Decoupled from the
|
|
111
|
+
* directional contribution: the two add independently rather than
|
|
112
|
+
* splitting a fixed energy budget.
|
|
113
|
+
*/
|
|
114
|
+
interface PolyAmbientLight {
|
|
115
|
+
/** Tint, hex string. White by default. */
|
|
116
|
+
color?: string;
|
|
117
|
+
/** Scalar multiplier on the ambient contribution. Default 0.4. */
|
|
118
|
+
intensity?: number;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Material — paint configuration shareable across many polygons.
|
|
122
|
+
*
|
|
123
|
+
* In CSS terms, a material bundles the `background-image` source plus paint
|
|
124
|
+
* config. When a polygon references a material AND its UVs form an
|
|
125
|
+
* axis-aligned rectangle, PolyCSS renders the polygon as an <i> with
|
|
126
|
+
* `background-image: url(material.texture)` directly — no per-polygon canvas
|
|
127
|
+
* rasterization, browser-cached texture, mounting / unmounting one polygon
|
|
128
|
+
* does not affect any other.
|
|
129
|
+
*
|
|
130
|
+
* Three.js parallel: combines THREE.Texture + a basic Material in one. CSS
|
|
131
|
+
* has no shader/sampler concerns, so the texture/material split from
|
|
132
|
+
* Three.js doesn't pay rent here.
|
|
133
|
+
*/
|
|
134
|
+
interface PolyMaterial {
|
|
135
|
+
/** Image source. Anything `background-image: url(...)` can use. */
|
|
136
|
+
texture: string;
|
|
137
|
+
/** Optional unique key (used by PolyCSS to dedupe / cache). Caller can
|
|
138
|
+
* pass a stable string; if omitted, the material's identity is its object
|
|
139
|
+
* reference. */
|
|
140
|
+
key?: string;
|
|
141
|
+
imageSource?: PolyTextureImageSource;
|
|
142
|
+
presentation?: PolyTexturePresentation;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The single polygon type for polycss. N coplanar vertices in 3D space,
|
|
146
|
+
* CCW winding from outside. No bbox field, no shape discriminator, no
|
|
147
|
+
* input/output distinction — one type, used by parsers, by the merge
|
|
148
|
+
* pass, and by the renderer.
|
|
149
|
+
*/
|
|
150
|
+
interface Polygon {
|
|
151
|
+
/** N coplanar vertices in 3D space, CCW winding from outside. */
|
|
152
|
+
vertices: Vec3[];
|
|
153
|
+
/**
|
|
154
|
+
* Solid base color. Falls back to "#cccccc" when neither color nor
|
|
155
|
+
* texture is set.
|
|
156
|
+
*/
|
|
157
|
+
color?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Texture URL. When set with `uvs`, UV-mapped via affine; without
|
|
160
|
+
* `uvs`, single-tile fill. If the load fails, renderer falls back to
|
|
161
|
+
* `color` (or default gray).
|
|
162
|
+
*/
|
|
163
|
+
texture?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Texture sampler wrap mode for UVs outside [0, 1]. glTF imports preserve
|
|
166
|
+
* sampler.wrapS / wrapT here so the atlas rasterizer can tile repeated UVs.
|
|
167
|
+
* When unset, renderers keep the historical single-image behavior.
|
|
168
|
+
* @internal
|
|
169
|
+
*/
|
|
170
|
+
textureWrap?: PolyTextureWrap;
|
|
171
|
+
/**
|
|
172
|
+
* Texture alpha interpretation imported from glTF `material.alphaMode`.
|
|
173
|
+
* Opaque textures can use transparent PNG padding without cutting holes in
|
|
174
|
+
* the rendered polygon.
|
|
175
|
+
* @internal
|
|
176
|
+
*/
|
|
177
|
+
textureAlphaMode?: PolyTextureAlphaMode;
|
|
178
|
+
/**
|
|
179
|
+
* Shared material. When set, `material.texture` takes precedence over the
|
|
180
|
+
* inline `texture` field. If the polygon's UVs form an axis-aligned
|
|
181
|
+
* rectangle, PolyCSS uses the direct CSS background-image path (no per-
|
|
182
|
+
* polygon canvas rasterization). Falls back to the atlas path otherwise.
|
|
183
|
+
*/
|
|
184
|
+
material?: PolyMaterial;
|
|
185
|
+
textureImageSource?: PolyTextureImageSource;
|
|
186
|
+
texturePresentation?: PolyTexturePresentation;
|
|
187
|
+
/**
|
|
188
|
+
* Per-vertex UV coords (0..1, OBJ convention with v=0 at bottom).
|
|
189
|
+
* Length MUST equal vertices.length when set; mismatched UVs are
|
|
190
|
+
* stripped by `normalizePolygons`.
|
|
191
|
+
*/
|
|
192
|
+
uvs?: Vec2[];
|
|
193
|
+
/**
|
|
194
|
+
* Renderer-internal source triangles for UV textures. Merge passes use this
|
|
195
|
+
* to reduce DOM planes while preserving per-triangle texture mapping in the
|
|
196
|
+
* generated atlas.
|
|
197
|
+
* @internal
|
|
198
|
+
*/
|
|
199
|
+
textureTriangles?: TextureTriangle[];
|
|
200
|
+
/**
|
|
201
|
+
* Import-time simplifier seam keys retained after solid texture baking.
|
|
202
|
+
* Renderers ignore this; mesh optimization uses it to avoid welding vertices
|
|
203
|
+
* that shared a position but came from different texture/attribute seams.
|
|
204
|
+
* @internal
|
|
205
|
+
*/
|
|
206
|
+
simplifyVertexKeys?: string[];
|
|
207
|
+
/**
|
|
208
|
+
* Stricter import-time simplifier keys that preserve source vertex identity.
|
|
209
|
+
* Renderers ignore this; candidate simplification uses it only for fallback
|
|
210
|
+
* passes where relaxed seam welding loses after render-cost optimization.
|
|
211
|
+
* @internal
|
|
212
|
+
*/
|
|
213
|
+
simplifySourceVertexKeys?: string[];
|
|
214
|
+
/**
|
|
215
|
+
* Source material requested two-sided rendering. Importers use this so
|
|
216
|
+
* optimization passes do not collapse intentional reverse-wound faces.
|
|
217
|
+
* @internal
|
|
218
|
+
*/
|
|
219
|
+
doubleSided?: boolean;
|
|
220
|
+
/**
|
|
221
|
+
* User-controlled metadata. Reflected to DOM as `data-*` attributes via
|
|
222
|
+
* stringification by the framework wrappers. Only string|number|boolean
|
|
223
|
+
* values are kept; other shapes are dropped by `normalizePolygons`.
|
|
224
|
+
*/
|
|
225
|
+
data?: Record<string, string | number | boolean>;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Base tile size in CSS pixels. One PolyCSS world unit = BASE_TILE CSS
|
|
230
|
+
* pixels (pre-scale). Used to convert world-coordinate target values to
|
|
231
|
+
* CSS translations in the transform string.
|
|
232
|
+
*/
|
|
233
|
+
declare const BASE_TILE = 50;
|
|
234
|
+
interface AutoRotateConfig {
|
|
235
|
+
axis?: "x" | "y";
|
|
236
|
+
speed?: number;
|
|
237
|
+
pauseOnInteraction?: boolean;
|
|
238
|
+
}
|
|
239
|
+
type AutoRotateOption = boolean | number | AutoRotateConfig;
|
|
240
|
+
/**
|
|
241
|
+
* World-coordinate camera state (Three.js-style).
|
|
242
|
+
*
|
|
243
|
+
* `target` is the world point that should appear at the viewport centre.
|
|
244
|
+
* PolyCSS world axes: [0]=X (rows/south), [1]=Y (cols/east), [2]=Z (up).
|
|
245
|
+
*
|
|
246
|
+
* `pan`, `tilt`, and `depthOffset` are gone. Translations now live inside
|
|
247
|
+
* `target` so they happen BEFORE rotations — enabling correct world-space
|
|
248
|
+
* pan at any tilt angle.
|
|
249
|
+
*
|
|
250
|
+
* `distance` is the camera's pull-back from the target in CSS pixels.
|
|
251
|
+
* Increasing distance moves the camera farther from the target along the
|
|
252
|
+
* view axis (dolly out) — analogous to three.js's spherical radius.
|
|
253
|
+
* Default 0 keeps orthographic/isometric scenes flat.
|
|
254
|
+
*/
|
|
255
|
+
interface CameraState {
|
|
256
|
+
target: Vec3;
|
|
257
|
+
rotX: number;
|
|
258
|
+
rotY: number;
|
|
259
|
+
zoom: number;
|
|
260
|
+
/** Camera pull-back from target in CSS pixels. Default 0. */
|
|
261
|
+
distance: number;
|
|
262
|
+
}
|
|
263
|
+
interface CameraStyleInput {
|
|
264
|
+
rows?: number;
|
|
265
|
+
cols?: number;
|
|
266
|
+
}
|
|
267
|
+
interface CameraHandle {
|
|
268
|
+
state: CameraState;
|
|
269
|
+
update(next: Partial<CameraState>): void;
|
|
270
|
+
getStyle(input?: CameraStyleInput): {
|
|
271
|
+
transform: string;
|
|
272
|
+
width: string;
|
|
273
|
+
height: string;
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
interface PolyCameraSceneTransformOptions {
|
|
277
|
+
autoCenterOffset?: Vec3;
|
|
278
|
+
layoutScale?: number;
|
|
279
|
+
tileSize?: number;
|
|
280
|
+
}
|
|
281
|
+
type PolyCameraProjection = "orthographic" | "perspective";
|
|
282
|
+
interface PolyCameraSnapshot {
|
|
283
|
+
projection: PolyCameraProjection;
|
|
284
|
+
perspectiveStyle: string;
|
|
285
|
+
appliedPerspectiveStyle: string;
|
|
286
|
+
state: CameraState;
|
|
287
|
+
}
|
|
288
|
+
interface PolyCameraSnapshotOptions {
|
|
289
|
+
projection?: PolyCameraProjection;
|
|
290
|
+
perspectiveStyle?: string;
|
|
291
|
+
}
|
|
292
|
+
type PolyCameraSnapshotSource = CameraHandle & {
|
|
293
|
+
readonly type?: PolyCameraProjection;
|
|
294
|
+
readonly perspectiveStyle?: string;
|
|
295
|
+
};
|
|
296
|
+
declare function normalizeInvertMultiplier(value: number | boolean | undefined): number | undefined;
|
|
297
|
+
declare const DEFAULT_CAMERA_STATE: CameraState;
|
|
298
|
+
declare function polyCameraTargetToCss(target?: Vec3, autoCenterOffset?: Vec3, tileSize?: number): Vec3;
|
|
299
|
+
declare function buildPolyCameraSceneTransform(state?: Partial<CameraState>, options?: PolyCameraSceneTransformOptions): string;
|
|
300
|
+
declare function resolvePolyCameraAppliedPerspectiveStyle(perspectiveStyle?: string): string;
|
|
301
|
+
declare function capturePolyCameraSnapshot(camera: PolyCameraSnapshotSource, options?: PolyCameraSnapshotOptions): PolyCameraSnapshot;
|
|
302
|
+
declare function createIsometricCamera(initial?: Partial<CameraState>): CameraHandle;
|
|
303
|
+
|
|
304
|
+
export { type AutoRotateConfig as A, BASE_TILE as B, type CameraState as C, DEFAULT_CAMERA_STATE as D, capturePolyCameraSnapshot as E, createIsometricCamera as F, normalizeInvertMultiplier as G, polyCameraTargetToCss as H, resolvePolyCameraAppliedPerspectiveStyle as I, type MeshResolution as M, type Polygon as P, type TextureTriangle as T, type Vec3 as V, type PolyDirectionalLight as a, type PolyAmbientLight as b, type PolyPointLight as c, type PolyTextureLightingMode as d, type Vec2 as e, type PolyTextureLeafSizing as f, type PolyTextureImageSource as g, type PolyTextureImageRendering as h, type PolyTextureImageLighting as i, type PolyTextureProjection as j, type PolyTextureBackend as k, type PolyTexturePresentation as l, type AutoRotateOption as m, type CameraHandle as n, type CameraStyleInput as o, DEFAULT_PROJECTION as p, type PolyCameraProjection as q, type PolyCameraSceneTransformOptions as r, type PolyCameraSnapshot as s, type PolyCameraSnapshotOptions as t, type PolyCameraSnapshotSource as u, type PolyMaterial as v, type PolyTextureAlphaMode as w, type PolyTextureWrap as x, type PolyTextureWrapMode as y, buildPolyCameraSceneTransform as z };
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
declare const DEFAULT_PROJECTION: "cubic";
|
|
2
|
+
/**
|
|
3
|
+
* How polygon lighting is applied by DOM renderers.
|
|
4
|
+
* - "baked": multiply the light tint into the off-DOM canvas before the
|
|
5
|
+
* polygon becomes an atlas sprite. Best fidelity (full RGB tint) but
|
|
6
|
+
* the atlas re-rasterizes whenever the light changes.
|
|
7
|
+
* - "dynamic": lighting computed entirely in CSS via per-polygon normals
|
|
8
|
+
* embedded in calc() and scene-root light vars (background-color +
|
|
9
|
+
* background-blend-mode multiply, masked by the atlas alpha). Atlas
|
|
10
|
+
* stays light-independent — sliding the light only writes a few CSS
|
|
11
|
+
* variables, no JS work, no atlas re-rasterization.
|
|
12
|
+
*/
|
|
13
|
+
type PolyTextureLightingMode = "baked" | "dynamic";
|
|
14
|
+
type PolyTextureLeafSizing = "canonical" | "local" | "raster";
|
|
15
|
+
type PolyTextureBackend = "auto" | "atlas" | "image";
|
|
16
|
+
type PolyTextureImageRendering = "auto" | "pixelated";
|
|
17
|
+
type PolyTextureImageLighting = "scene" | "source";
|
|
18
|
+
type PolyTextureProjection = "affine" | "projective";
|
|
19
|
+
interface PolyTextureImageSource {
|
|
20
|
+
url: string;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
sourceRect?: {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
};
|
|
29
|
+
imageRendering?: PolyTextureImageRendering;
|
|
30
|
+
}
|
|
31
|
+
interface PolyTexturePresentation {
|
|
32
|
+
imageRendering?: PolyTextureImageRendering;
|
|
33
|
+
backend?: PolyTextureBackend;
|
|
34
|
+
lighting?: PolyTextureImageLighting;
|
|
35
|
+
projection?: PolyTextureProjection;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Mesh post-processing intent.
|
|
39
|
+
* - "lossless": preserve the authored surface while applying exact
|
|
40
|
+
* reductions such as interior culling and coplanar merge.
|
|
41
|
+
* - "lossy": allow bounded geometric approximation when it reduces the
|
|
42
|
+
* rendered polygon/DOM count.
|
|
43
|
+
*/
|
|
44
|
+
type MeshResolution = "lossless" | "lossy";
|
|
45
|
+
/**
|
|
46
|
+
* 3D point/vector, stored as a `[x, y, z]` tuple. Tuple (rather than
|
|
47
|
+
* `{x, y, z}`) for compact JSON: meshes serialize to thousands of vertices
|
|
48
|
+
* and the difference adds up. Destructure with `const [x, y, z] = v` when
|
|
49
|
+
* you need named axes.
|
|
50
|
+
*
|
|
51
|
+
* PolyCSS world space convention: +X right, +Y forward, +Z up.
|
|
52
|
+
*/
|
|
53
|
+
type Vec3 = [number, number, number];
|
|
54
|
+
/**
|
|
55
|
+
* 2D point/vector — `[u, v]`. Used for texture-atlas UV coordinates on
|
|
56
|
+
* polygons. Convention follows OBJ: u is horizontal (0=left, 1=right),
|
|
57
|
+
* v is vertical (0=bottom, 1=top). Renderers flip v when binding to raster
|
|
58
|
+
* image space whose Y-axis points down.
|
|
59
|
+
*/
|
|
60
|
+
type Vec2 = [number, number];
|
|
61
|
+
interface TextureTriangle {
|
|
62
|
+
vertices: [Vec3, Vec3, Vec3];
|
|
63
|
+
uvs: [Vec2, Vec2, Vec2];
|
|
64
|
+
}
|
|
65
|
+
type PolyTextureWrapMode = "repeat" | "clamp-to-edge" | "mirrored-repeat";
|
|
66
|
+
interface PolyTextureWrap {
|
|
67
|
+
s: PolyTextureWrapMode;
|
|
68
|
+
t: PolyTextureWrapMode;
|
|
69
|
+
}
|
|
70
|
+
type PolyTextureAlphaMode = "opaque" | "mask" | "blend";
|
|
71
|
+
/**
|
|
72
|
+
* Directional light — simulates a single distant source (sun, key light).
|
|
73
|
+
* Contributes Lambert shading scaled by `intensity`. `direction` is in
|
|
74
|
+
* scene-local CSS-pixel coords and does not need to be pre-normalized.
|
|
75
|
+
* Mirrors three.js's `DirectionalLight`.
|
|
76
|
+
*/
|
|
77
|
+
interface PolyDirectionalLight {
|
|
78
|
+
/** Unit direction from the surface toward the distant light source. */
|
|
79
|
+
direction: Vec3;
|
|
80
|
+
/** Light tint, hex string. White by default. */
|
|
81
|
+
color?: string;
|
|
82
|
+
/** Scalar multiplier on the directional contribution. Default 1. */
|
|
83
|
+
intensity?: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Point light — radiates from a world-space position. Contributes per-face
|
|
87
|
+
* Lambert like a directional light, but the light direction is computed
|
|
88
|
+
* per polygon (face centroid → light position) rather than being global.
|
|
89
|
+
*
|
|
90
|
+
* DIRECTION-ONLY by design: there is no distance falloff (no `decay`/
|
|
91
|
+
* `distance`). A point light differs from a directional light only in that
|
|
92
|
+
* its direction varies per face. To emulate in three.js for parity, use
|
|
93
|
+
* `new THREE.PointLight(color, intensity, 0, 0)` (distance 0, decay 0 →
|
|
94
|
+
* no attenuation). Shading is flat per face (the centroid direction), so it
|
|
95
|
+
* approximates three.js's per-fragment gradient — exact for small faces /
|
|
96
|
+
* distant lights, never a CSS gradient.
|
|
97
|
+
*/
|
|
98
|
+
interface PolyPointLight {
|
|
99
|
+
/** World-space position the light radiates from. */
|
|
100
|
+
position: Vec3;
|
|
101
|
+
/** Light tint, hex string. White by default. */
|
|
102
|
+
color?: string;
|
|
103
|
+
/** Scalar multiplier on the contribution. Default 1. */
|
|
104
|
+
intensity?: number;
|
|
105
|
+
/** When true, this light casts shadows (radial projection). Default false. */
|
|
106
|
+
castShadow?: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ambient light — uniform fill that adds to every polygon regardless of
|
|
110
|
+
* orientation. Mirrors three.js's `AmbientLight`. Decoupled from the
|
|
111
|
+
* directional contribution: the two add independently rather than
|
|
112
|
+
* splitting a fixed energy budget.
|
|
113
|
+
*/
|
|
114
|
+
interface PolyAmbientLight {
|
|
115
|
+
/** Tint, hex string. White by default. */
|
|
116
|
+
color?: string;
|
|
117
|
+
/** Scalar multiplier on the ambient contribution. Default 0.4. */
|
|
118
|
+
intensity?: number;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Material — paint configuration shareable across many polygons.
|
|
122
|
+
*
|
|
123
|
+
* In CSS terms, a material bundles the `background-image` source plus paint
|
|
124
|
+
* config. When a polygon references a material AND its UVs form an
|
|
125
|
+
* axis-aligned rectangle, PolyCSS renders the polygon as an <i> with
|
|
126
|
+
* `background-image: url(material.texture)` directly — no per-polygon canvas
|
|
127
|
+
* rasterization, browser-cached texture, mounting / unmounting one polygon
|
|
128
|
+
* does not affect any other.
|
|
129
|
+
*
|
|
130
|
+
* Three.js parallel: combines THREE.Texture + a basic Material in one. CSS
|
|
131
|
+
* has no shader/sampler concerns, so the texture/material split from
|
|
132
|
+
* Three.js doesn't pay rent here.
|
|
133
|
+
*/
|
|
134
|
+
interface PolyMaterial {
|
|
135
|
+
/** Image source. Anything `background-image: url(...)` can use. */
|
|
136
|
+
texture: string;
|
|
137
|
+
/** Optional unique key (used by PolyCSS to dedupe / cache). Caller can
|
|
138
|
+
* pass a stable string; if omitted, the material's identity is its object
|
|
139
|
+
* reference. */
|
|
140
|
+
key?: string;
|
|
141
|
+
imageSource?: PolyTextureImageSource;
|
|
142
|
+
presentation?: PolyTexturePresentation;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The single polygon type for polycss. N coplanar vertices in 3D space,
|
|
146
|
+
* CCW winding from outside. No bbox field, no shape discriminator, no
|
|
147
|
+
* input/output distinction — one type, used by parsers, by the merge
|
|
148
|
+
* pass, and by the renderer.
|
|
149
|
+
*/
|
|
150
|
+
interface Polygon {
|
|
151
|
+
/** N coplanar vertices in 3D space, CCW winding from outside. */
|
|
152
|
+
vertices: Vec3[];
|
|
153
|
+
/**
|
|
154
|
+
* Solid base color. Falls back to "#cccccc" when neither color nor
|
|
155
|
+
* texture is set.
|
|
156
|
+
*/
|
|
157
|
+
color?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Texture URL. When set with `uvs`, UV-mapped via affine; without
|
|
160
|
+
* `uvs`, single-tile fill. If the load fails, renderer falls back to
|
|
161
|
+
* `color` (or default gray).
|
|
162
|
+
*/
|
|
163
|
+
texture?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Texture sampler wrap mode for UVs outside [0, 1]. glTF imports preserve
|
|
166
|
+
* sampler.wrapS / wrapT here so the atlas rasterizer can tile repeated UVs.
|
|
167
|
+
* When unset, renderers keep the historical single-image behavior.
|
|
168
|
+
* @internal
|
|
169
|
+
*/
|
|
170
|
+
textureWrap?: PolyTextureWrap;
|
|
171
|
+
/**
|
|
172
|
+
* Texture alpha interpretation imported from glTF `material.alphaMode`.
|
|
173
|
+
* Opaque textures can use transparent PNG padding without cutting holes in
|
|
174
|
+
* the rendered polygon.
|
|
175
|
+
* @internal
|
|
176
|
+
*/
|
|
177
|
+
textureAlphaMode?: PolyTextureAlphaMode;
|
|
178
|
+
/**
|
|
179
|
+
* Shared material. When set, `material.texture` takes precedence over the
|
|
180
|
+
* inline `texture` field. If the polygon's UVs form an axis-aligned
|
|
181
|
+
* rectangle, PolyCSS uses the direct CSS background-image path (no per-
|
|
182
|
+
* polygon canvas rasterization). Falls back to the atlas path otherwise.
|
|
183
|
+
*/
|
|
184
|
+
material?: PolyMaterial;
|
|
185
|
+
textureImageSource?: PolyTextureImageSource;
|
|
186
|
+
texturePresentation?: PolyTexturePresentation;
|
|
187
|
+
/**
|
|
188
|
+
* Per-vertex UV coords (0..1, OBJ convention with v=0 at bottom).
|
|
189
|
+
* Length MUST equal vertices.length when set; mismatched UVs are
|
|
190
|
+
* stripped by `normalizePolygons`.
|
|
191
|
+
*/
|
|
192
|
+
uvs?: Vec2[];
|
|
193
|
+
/**
|
|
194
|
+
* Renderer-internal source triangles for UV textures. Merge passes use this
|
|
195
|
+
* to reduce DOM planes while preserving per-triangle texture mapping in the
|
|
196
|
+
* generated atlas.
|
|
197
|
+
* @internal
|
|
198
|
+
*/
|
|
199
|
+
textureTriangles?: TextureTriangle[];
|
|
200
|
+
/**
|
|
201
|
+
* Import-time simplifier seam keys retained after solid texture baking.
|
|
202
|
+
* Renderers ignore this; mesh optimization uses it to avoid welding vertices
|
|
203
|
+
* that shared a position but came from different texture/attribute seams.
|
|
204
|
+
* @internal
|
|
205
|
+
*/
|
|
206
|
+
simplifyVertexKeys?: string[];
|
|
207
|
+
/**
|
|
208
|
+
* Stricter import-time simplifier keys that preserve source vertex identity.
|
|
209
|
+
* Renderers ignore this; candidate simplification uses it only for fallback
|
|
210
|
+
* passes where relaxed seam welding loses after render-cost optimization.
|
|
211
|
+
* @internal
|
|
212
|
+
*/
|
|
213
|
+
simplifySourceVertexKeys?: string[];
|
|
214
|
+
/**
|
|
215
|
+
* Source material requested two-sided rendering. Importers use this so
|
|
216
|
+
* optimization passes do not collapse intentional reverse-wound faces.
|
|
217
|
+
* @internal
|
|
218
|
+
*/
|
|
219
|
+
doubleSided?: boolean;
|
|
220
|
+
/**
|
|
221
|
+
* User-controlled metadata. Reflected to DOM as `data-*` attributes via
|
|
222
|
+
* stringification by the framework wrappers. Only string|number|boolean
|
|
223
|
+
* values are kept; other shapes are dropped by `normalizePolygons`.
|
|
224
|
+
*/
|
|
225
|
+
data?: Record<string, string | number | boolean>;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Base tile size in CSS pixels. One PolyCSS world unit = BASE_TILE CSS
|
|
230
|
+
* pixels (pre-scale). Used to convert world-coordinate target values to
|
|
231
|
+
* CSS translations in the transform string.
|
|
232
|
+
*/
|
|
233
|
+
declare const BASE_TILE = 50;
|
|
234
|
+
interface AutoRotateConfig {
|
|
235
|
+
axis?: "x" | "y";
|
|
236
|
+
speed?: number;
|
|
237
|
+
pauseOnInteraction?: boolean;
|
|
238
|
+
}
|
|
239
|
+
type AutoRotateOption = boolean | number | AutoRotateConfig;
|
|
240
|
+
/**
|
|
241
|
+
* World-coordinate camera state (Three.js-style).
|
|
242
|
+
*
|
|
243
|
+
* `target` is the world point that should appear at the viewport centre.
|
|
244
|
+
* PolyCSS world axes: [0]=X (rows/south), [1]=Y (cols/east), [2]=Z (up).
|
|
245
|
+
*
|
|
246
|
+
* `pan`, `tilt`, and `depthOffset` are gone. Translations now live inside
|
|
247
|
+
* `target` so they happen BEFORE rotations — enabling correct world-space
|
|
248
|
+
* pan at any tilt angle.
|
|
249
|
+
*
|
|
250
|
+
* `distance` is the camera's pull-back from the target in CSS pixels.
|
|
251
|
+
* Increasing distance moves the camera farther from the target along the
|
|
252
|
+
* view axis (dolly out) — analogous to three.js's spherical radius.
|
|
253
|
+
* Default 0 keeps orthographic/isometric scenes flat.
|
|
254
|
+
*/
|
|
255
|
+
interface CameraState {
|
|
256
|
+
target: Vec3;
|
|
257
|
+
rotX: number;
|
|
258
|
+
rotY: number;
|
|
259
|
+
zoom: number;
|
|
260
|
+
/** Camera pull-back from target in CSS pixels. Default 0. */
|
|
261
|
+
distance: number;
|
|
262
|
+
}
|
|
263
|
+
interface CameraStyleInput {
|
|
264
|
+
rows?: number;
|
|
265
|
+
cols?: number;
|
|
266
|
+
}
|
|
267
|
+
interface CameraHandle {
|
|
268
|
+
state: CameraState;
|
|
269
|
+
update(next: Partial<CameraState>): void;
|
|
270
|
+
getStyle(input?: CameraStyleInput): {
|
|
271
|
+
transform: string;
|
|
272
|
+
width: string;
|
|
273
|
+
height: string;
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
interface PolyCameraSceneTransformOptions {
|
|
277
|
+
autoCenterOffset?: Vec3;
|
|
278
|
+
layoutScale?: number;
|
|
279
|
+
tileSize?: number;
|
|
280
|
+
}
|
|
281
|
+
type PolyCameraProjection = "orthographic" | "perspective";
|
|
282
|
+
interface PolyCameraSnapshot {
|
|
283
|
+
projection: PolyCameraProjection;
|
|
284
|
+
perspectiveStyle: string;
|
|
285
|
+
appliedPerspectiveStyle: string;
|
|
286
|
+
state: CameraState;
|
|
287
|
+
}
|
|
288
|
+
interface PolyCameraSnapshotOptions {
|
|
289
|
+
projection?: PolyCameraProjection;
|
|
290
|
+
perspectiveStyle?: string;
|
|
291
|
+
}
|
|
292
|
+
type PolyCameraSnapshotSource = CameraHandle & {
|
|
293
|
+
readonly type?: PolyCameraProjection;
|
|
294
|
+
readonly perspectiveStyle?: string;
|
|
295
|
+
};
|
|
296
|
+
declare function normalizeInvertMultiplier(value: number | boolean | undefined): number | undefined;
|
|
297
|
+
declare const DEFAULT_CAMERA_STATE: CameraState;
|
|
298
|
+
declare function polyCameraTargetToCss(target?: Vec3, autoCenterOffset?: Vec3, tileSize?: number): Vec3;
|
|
299
|
+
declare function buildPolyCameraSceneTransform(state?: Partial<CameraState>, options?: PolyCameraSceneTransformOptions): string;
|
|
300
|
+
declare function resolvePolyCameraAppliedPerspectiveStyle(perspectiveStyle?: string): string;
|
|
301
|
+
declare function capturePolyCameraSnapshot(camera: PolyCameraSnapshotSource, options?: PolyCameraSnapshotOptions): PolyCameraSnapshot;
|
|
302
|
+
declare function createIsometricCamera(initial?: Partial<CameraState>): CameraHandle;
|
|
303
|
+
|
|
304
|
+
export { type AutoRotateConfig as A, BASE_TILE as B, type CameraState as C, DEFAULT_CAMERA_STATE as D, capturePolyCameraSnapshot as E, createIsometricCamera as F, normalizeInvertMultiplier as G, polyCameraTargetToCss as H, resolvePolyCameraAppliedPerspectiveStyle as I, type MeshResolution as M, type Polygon as P, type TextureTriangle as T, type Vec3 as V, type PolyDirectionalLight as a, type PolyAmbientLight as b, type PolyPointLight as c, type PolyTextureLightingMode as d, type Vec2 as e, type PolyTextureLeafSizing as f, type PolyTextureImageSource as g, type PolyTextureImageRendering as h, type PolyTextureImageLighting as i, type PolyTextureProjection as j, type PolyTextureBackend as k, type PolyTexturePresentation as l, type AutoRotateOption as m, type CameraHandle as n, type CameraStyleInput as o, DEFAULT_PROJECTION as p, type PolyCameraProjection as q, type PolyCameraSceneTransformOptions as r, type PolyCameraSnapshot as s, type PolyCameraSnapshotOptions as t, type PolyCameraSnapshotSource as u, type PolyMaterial as v, type PolyTextureAlphaMode as w, type PolyTextureWrap as x, type PolyTextureWrapMode as y, buildPolyCameraSceneTransform as z };
|