@layoutit/polycss-core 0.0.1 → 0.2.0

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/dist/index.d.cts CHANGED
@@ -11,6 +11,14 @@ declare const DEFAULT_PROJECTION: "cubic";
11
11
  * variables, no JS work, no atlas re-rasterization.
12
12
  */
13
13
  type PolyTextureLightingMode = "baked" | "dynamic";
14
+ /**
15
+ * Mesh post-processing intent.
16
+ * - "lossless": preserve the authored surface while applying exact
17
+ * reductions such as interior culling and coplanar merge.
18
+ * - "lossy": allow bounded geometric approximation when it reduces the
19
+ * rendered polygon/DOM count.
20
+ */
21
+ type MeshResolution = "lossless" | "lossy";
14
22
  /**
15
23
  * 3D point/vector, stored as a `[x, y, z]` tuple. Tuple (rather than
16
24
  * `{x, y, z}`) for compact JSON: meshes serialize to thousands of vertices
@@ -280,6 +288,51 @@ declare function rotateVec3(v: Vec3, rxDeg: number, ryDeg: number, rzDeg: number
280
288
  */
281
289
  declare function inverseRotateVec3(v: Vec3, rot: Vec3): Vec3;
282
290
 
291
+ /**
292
+ * Minimal quaternion helpers for composing rotations.
293
+ *
294
+ * Why we need quaternions: the public PolyMesh API exposes rotation as a
295
+ * Euler triple `[rx, ry, rz]` in degrees (drives CSS `rotateX rotateY
296
+ * rotateZ`, applied right-to-left). Euler triples don't compose by
297
+ * component addition — rotating Y after X must happen around the mesh's
298
+ * NEW local-Y axis, not world-Y. The transform-controls ring drag handler
299
+ * uses these helpers to compose around the mesh's local axis correctly:
300
+ *
301
+ * q_start = quatFromEulerXYZ(currentRotationDeg)
302
+ * q_delta = quatFromAxisAngle(localAxis, deltaRadians)
303
+ * q_new = quatMultiply(q_start, q_delta) // RIGHT-multiply = local frame
304
+ * next = eulerXYZFromQuat(q_new)
305
+ *
306
+ * Convention: "XYZ" Euler means the composed rotation matrix is
307
+ * `Rx(rx) · Ry(ry) · Rz(rz)`, which matches CSS `rotateX rotateY rotateZ`
308
+ * (right-to-left application to a point ⇒ Z first, then Y, then X).
309
+ *
310
+ * Quaternion format: `[w, x, y, z]` (real-first, like three.js's internal
311
+ * `_x/_y/_z/_w` reordered). Stored as plain tuples — no constructor or
312
+ * runtime allocations per drag.
313
+ */
314
+
315
+ /** Quaternion `[w, x, y, z]`, real component first. Unit-length is not
316
+ * enforced by the type — callers normalize when needed. */
317
+ type Quat = [number, number, number, number];
318
+ /** Identity quaternion. */
319
+ declare const QUAT_IDENTITY: Quat;
320
+ /** Hamilton product `q1 * q2`. Apply to a vector as `q v q⁻¹`. Right-
321
+ * multiplication composes the second rotation in the LOCAL frame of the
322
+ * first — that's the property the gizmo relies on for local-axis drag. */
323
+ declare function quatMultiply(q1: Quat, q2: Quat): Quat;
324
+ /** Quaternion from axis-angle. `axis` must be unit length (caller's
325
+ * responsibility — typically a CSS basis vector). `angleRad` in radians. */
326
+ declare function quatFromAxisAngle(axis: Vec3, angleRad: number): Quat;
327
+ /** Quaternion from Euler XYZ degrees — the order CSS `rotateX rotateY
328
+ * rotateZ` applies. Matches the composed matrix `Rx(rx)·Ry(ry)·Rz(rz)`. */
329
+ declare function quatFromEulerXYZ(eulerDeg: Vec3): Quat;
330
+ /** Euler XYZ degrees from a quaternion — inverse of `quatFromEulerXYZ`.
331
+ * Handles gimbal lock (|ry| → 90°) by collapsing rz onto rx. The output
332
+ * matches the convention used by CSS `rotateX rotateY rotateZ` so it can
333
+ * be written straight back into a PolyMesh rotation prop. */
334
+ declare function eulerXYZFromQuat(q: Quat): Vec3;
335
+
283
336
  /**
284
337
  * Base tile size in CSS pixels. One polycss world unit = BASE_TILE CSS
285
338
  * pixels (pre-scale). Used to convert world-coordinate target values to
@@ -394,6 +447,82 @@ declare function computeShapeLighting(normal: Vec3, baseColor: string, direction
394
447
 
395
448
  declare function mergePolygons(input: Polygon[]): Polygon[];
396
449
 
450
+ /**
451
+ * dedupeOverlappingPolygons — drop polygons whose 3D footprint coincides
452
+ * with another polygon's, within an epsilon tolerance.
453
+ *
454
+ * Why this exists: modelers (and importers) often emit redundant geometry
455
+ * for the same visible surface — a doubled face on a wall, an inner shell
456
+ * coincident with an outer shell, or two N-gons that fan-triangulate the
457
+ * same region. Each duplicate is a real `<i>` element at render time:
458
+ * it costs DOM, Lambert math, atlas budget, AND it produces stacked
459
+ * shadow leaves that visibly multiply on the receiver (overlapping dark
460
+ * patches on the ground).
461
+ *
462
+ * This is a separate concern from `cullInteriorPolygons` (which removes
463
+ * polygons fully *enclosed* by other geometry, conservative against
464
+ * false positives) and from `mergePolygons` (which joins same-color
465
+ * coplanar polygons that share an edge). A polygon's exact twin
466
+ * doesn't share an edge with itself and isn't enclosed by anything —
467
+ * it slips through both passes.
468
+ *
469
+ * Algorithm:
470
+ * 1. Compute each polygon's plane (normal + signed offset along
471
+ * normal) and centroid.
472
+ * 2. Bucket polygons by quantized plane key (rounded normal direction
473
+ * with sign-folding so anti-parallel faces share a bucket, and
474
+ * rounded distance from origin along the unsigned normal axis).
475
+ * Polygons in different buckets cannot overlap.
476
+ * 3. Within each bucket, do an O(K²) pairwise check on at most K
477
+ * polygons. Two polygons overlap if their 2D projections onto
478
+ * the shared plane share a significant area fraction.
479
+ * 4. When a pair overlaps, drop one: prefer keeping the one whose
480
+ * normal points *away* from the mesh centroid (the "outward"
481
+ * face). For ties (truly identical orientation), keep the one
482
+ * with greater 2D area.
483
+ *
484
+ * Runs once at parse time in the same pipeline as mergePolygons. Zero
485
+ * cost at runtime — once it returns the polygon array is final and the
486
+ * dedup logic never executes again.
487
+ */
488
+
489
+ /** Tunable thresholds. Default values are conservative — only catch
490
+ * duplicates that are visually identical surfaces (exact twins,
491
+ * back-to-back winding flips, nested polys on the same plane).
492
+ * Looser values are appropriate for shadow-casting purposes, where
493
+ * any polygons whose projections land in the same place can share a
494
+ * shadow without affecting the rendered model. */
495
+ interface DedupeOverlappingPolygonsOptions {
496
+ /** Maximum 1 - |dot(n_a, n_b)| for normals to count as "parallel".
497
+ * Default 1e-3 (strict — must be near-identical orientation).
498
+ * Looser values (~5e-2 ≈ 18° off) treat near-parallel normals as
499
+ * duplicates, useful for shadow dedup where small orientation
500
+ * differences project to nearly the same shadow shape. */
501
+ normalTolerance?: number;
502
+ /** Maximum signed-distance difference between two polygons' plane
503
+ * offsets (along their shared normal) to count as coplanar.
504
+ * Default 0.05 (world units). Looser values treat distinct
505
+ * parallel shells (e.g. an inner cavity wall behind an outer
506
+ * wall) as shadow-duplicates. */
507
+ distanceTolerance?: number;
508
+ /** Minimum overlap fraction (max of A-in-B and B-in-A vertex
509
+ * containment ratios) for a pair to count as a duplicate.
510
+ * Default 0.7. Lower (~0.4) is liberal; higher (~0.9) is strict. */
511
+ overlapFraction?: number;
512
+ }
513
+ /** Identify polygons that are duplicates within tolerance. Returns the
514
+ * set of indices into the input array that should be dropped (the
515
+ * losers of duplicate pairs). The "winner" of a pair is the polygon
516
+ * whose normal faces away from the mesh centroid (outward), with
517
+ * larger area as a tiebreaker.
518
+ *
519
+ * Exposed for callers that want to act on the index set directly —
520
+ * e.g. shadow casting can use a looser tolerance to skip shadow leaves
521
+ * for redundant casters without removing them from the renderable
522
+ * polygon set. */
523
+ declare function findOverlappingPolygonDuplicates(input: Polygon[], options?: DedupeOverlappingPolygonsOptions): Set<number>;
524
+ declare function dedupeOverlappingPolygons(input: Polygon[], options?: DedupeOverlappingPolygonsOptions): Polygon[];
525
+
397
526
  interface CoverPlanarPolygonsOptions {
398
527
  /** Smallest connected coplanar group worth attempting. Default 4. */
399
528
  minGroupPolygons?: number;
@@ -413,6 +542,30 @@ interface CoverPlanarPolygonsOptions {
413
542
  */
414
543
  declare function coverPlanarPolygons(input: Polygon[], options?: CoverPlanarPolygonsOptions): Polygon[];
415
544
 
545
+ interface ApproximateMergeOptions {
546
+ maxAngleDeg?: number;
547
+ maxPlaneDisplacement?: number;
548
+ maxBoundaryDisplacement?: number;
549
+ isolatedPairs?: boolean;
550
+ }
551
+ interface OptimizeMeshPolygonsOptions {
552
+ /** Public quality/resolution intent. Defaults to "lossy". */
553
+ meshResolution?: MeshResolution;
554
+ /**
555
+ * Run the planar cover pass as an exact candidate for untextured coplanar
556
+ * regions. Defaults to true.
557
+ */
558
+ rectCover?: boolean | CoverPlanarPolygonsOptions;
559
+ /**
560
+ * Lossy approximate merge settings. Ignored for lossless resolution.
561
+ * When omitted, lossy evaluates isolated-pair and small plane-group
562
+ * strategies, then chooses the lowest render-cost result with a near-cost
563
+ * preference for candidates that reduce detected internal gaps.
564
+ */
565
+ approximateMerge?: boolean | ApproximateMergeOptions;
566
+ }
567
+ declare function optimizeMeshPolygons(polygons: Polygon[], options?: OptimizeMeshPolygonsOptions): Polygon[];
568
+
416
569
  /**
417
570
  * cullInteriorPolygons — remove polygons that are fully enclosed by other
418
571
  * polygons of the same mesh and therefore never visible from any external
@@ -440,6 +593,29 @@ interface CullInteriorOptions {
440
593
  }
441
594
  declare function cullInteriorPolygons(polygons: Polygon[], options?: CullInteriorOptions): Polygon[];
442
595
 
596
+ declare const CAMERA_BACKFACE_CULL_EPS = 0.00001;
597
+ declare const VOXEL_CAMERA_CULL_AXIS_EPS = 0.001;
598
+ declare const VOXEL_CAMERA_CULL_NORMAL_LIMIT = 6;
599
+ interface CameraCullRotation {
600
+ rotX: number;
601
+ rotY: number;
602
+ meshRotation?: Vec3;
603
+ }
604
+ interface CameraCullNormalGroup {
605
+ key: string;
606
+ normal: Vec3;
607
+ }
608
+ declare function polygonCssSurfaceNormal(polygon: Polygon): Vec3 | null;
609
+ declare function cameraFacingDepth(normal: Vec3, rotation: CameraCullRotation): number;
610
+ declare function normalFacesCamera(normal: Vec3, rotation: CameraCullRotation, depthThreshold?: number): boolean;
611
+ declare function polygonFacesCamera(polygon: Polygon, rotation: CameraCullRotation, depthThreshold?: number): boolean;
612
+ declare function cameraCullNormalKey(normal: Vec3): string;
613
+ declare function cameraCullNormalGroups(normals: Iterable<Vec3 | null | undefined>): CameraCullNormalGroup[];
614
+ declare function cameraCullNormalGroupsFromPolygons(polygons: readonly Polygon[]): CameraCullNormalGroup[];
615
+ declare function isAxisAlignedSurfaceNormal(normal: Vec3, axisEpsilon?: number): boolean;
616
+ declare function isVoxelCameraCullableNormalGroups(groups: readonly CameraCullNormalGroup[]): boolean;
617
+ declare function cameraCullVisibleSignature(groups: readonly CameraCullNormalGroup[], rotation: CameraCullRotation, depthThreshold?: number): string;
618
+
443
619
  /**
444
620
  * Geometry for the three.js-style debug axes gizmo: three thin colored
445
621
  * cuboids stretching along world-X, world-Y and world-Z. Mirrors the
@@ -471,6 +647,30 @@ interface AxesHelperOptions {
471
647
  */
472
648
  declare function axesHelperPolygons(options?: AxesHelperOptions): Polygon[];
473
649
 
650
+ /**
651
+ * Axis-aligned box/cuboid geometry as six quad polygons.
652
+ *
653
+ * Returned polygons are in standard polycss world space:
654
+ * +X = right, +Y = front/forward, +Z = top/up.
655
+ */
656
+
657
+ type BoxFace = "right" | "left" | "front" | "back" | "top" | "bottom";
658
+ type BoxFaceOptions = Pick<Polygon, "color" | "texture" | "material" | "uvs" | "data">;
659
+ interface BoxPolygonsOptions extends BoxFaceOptions {
660
+ /** Size along the world X/Y/Z axes. Defaults to a 1×1×1 cube. */
661
+ size?: number | Vec3;
662
+ /** Center used with `size`. Defaults to the origin. */
663
+ center?: Vec3;
664
+ /** Explicit minimum world-space corner. When set with `max`, bounds win over size/center. */
665
+ min?: Vec3;
666
+ /** Explicit maximum world-space corner. When set with `min`, bounds win over size/center. */
667
+ max?: Vec3;
668
+ /** Per-face material/data overrides. Set a face to `false` to omit it. */
669
+ faces?: Partial<Record<BoxFace, BoxFaceOptions | false>>;
670
+ }
671
+ /** Build the polygons for one axis-aligned box/cuboid. */
672
+ declare function boxPolygons(options?: BoxPolygonsOptions): Polygon[];
673
+
474
674
  /**
475
675
  * Geometry for a single 3D arrow: a thin axis-aligned cuboid shaft
476
676
  * stretching from the origin along one signed axis, capped with a
@@ -497,6 +697,11 @@ interface ArrowPolygonsOptions {
497
697
  headHalfThickness?: number;
498
698
  /** Fill color. */
499
699
  color?: string;
700
+ /** Emit the rectangular shaft polygons. Default `true`. Set `false` to
701
+ * render just the pyramid head — used by transform-control gizmos to
702
+ * declutter back-facing axes (only the head still identifies direction
703
+ * while the shaft would visually overlap the front-facing arrow). */
704
+ shaft?: boolean;
500
705
  }
501
706
  /** Build the polygons for one signed-axis arrow. */
502
707
  declare function arrowPolygons(options: ArrowPolygonsOptions): Polygon[];
@@ -534,6 +739,66 @@ interface RingPolygonsOptions {
534
739
  /** Build the polygons for a flat ring (annulus). */
535
740
  declare function ringPolygons(options: RingPolygonsOptions): Polygon[];
536
741
 
742
+ /**
743
+ * One square quad covering the bounding box of a ring (annulus) in the
744
+ * plane perpendicular to a chosen axis. Used by `<PolyTransformControls
745
+ * mode="rotate">` together with a CSS `mask: radial-gradient(...)` to
746
+ * render the visible donut, replacing the segmented quad-strip approach
747
+ * of `ringPolygons` with a single DOM element per ring.
748
+ *
749
+ * The caller is responsible for applying the mask CSS and using a donut-
750
+ * shaped hit-test (the quad's bounding rect alone would over-hit the
751
+ * inner hole). The recommended setup is to set the CSS custom property
752
+ * `--ring-inner-ratio` on the mesh element so the mask scales with the
753
+ * caller's chosen thickness ratio.
754
+ */
755
+
756
+ interface RingQuadPolygonsOptions {
757
+ /** World axis the ring is perpendicular to: 0=X, 1=Y, 2=Z. The quad
758
+ * lies in the plane spanned by the other two axes. */
759
+ axis: 0 | 1 | 2;
760
+ /** Outer radius of the ring. The quad spans ±outerRadius in both
761
+ * in-plane axes. */
762
+ outerRadius: number;
763
+ /** Fill color. */
764
+ color?: string;
765
+ }
766
+ /** Build a single 4-vertex polygon (a square) bounding the ring's outer
767
+ * circle. CSS `mask` is expected to clip this to the donut shape at
768
+ * render time. */
769
+ declare function ringQuadPolygons(options: RingQuadPolygonsOptions): Polygon[];
770
+
771
+ /**
772
+ * A flat quad on one of the three axis-aligned planes, offset diagonally
773
+ * along the two in-plane axes. Used as a planar drag handle in
774
+ * `<PolyTransformControls>` — clicking and dragging this handle moves the
775
+ * attached mesh along two axes simultaneously (XY, XZ, or YZ), instead of
776
+ * the single-axis motion the arrow shafts provide.
777
+ *
778
+ * The polygon lives in standard polycss world space; wrap it in the
779
+ * framework's PolyMesh equivalent for rendering.
780
+ */
781
+
782
+ interface PlanePolygonsOptions {
783
+ /** Axis perpendicular to the plane: 0 = YZ plane, 1 = XZ plane,
784
+ * 2 = XY plane. The quad lies on the OTHER two axes. */
785
+ axis: 0 | 1 | 2;
786
+ /** Half-extent of the quad along each in-plane axis. Default `0.4`. */
787
+ size?: number;
788
+ /** Center of the quad along the two in-plane axes. Pass a single number
789
+ * to use the same offset on both (positive places the handle in the
790
+ * +A/+B corner). Pass `[offsetA, offsetB]` to control each
791
+ * independently — sign flips move the handle to a different octant.
792
+ * `A = (axis+1)%3`, `B = (axis+2)%3`. Default `size * 2`. */
793
+ offset?: number | [number, number];
794
+ /** Position along the perpendicular axis. Default `0` (on the plane). */
795
+ along?: number;
796
+ /** Fill color. */
797
+ color?: string;
798
+ }
799
+ /** Build the polygons for one axis-aligned planar drag handle. */
800
+ declare function planePolygons(options: PlanePolygonsOptions): Polygon[];
801
+
537
802
  /**
538
803
  * Geometry for a small solid-color octahedron — the marker shape used by
539
804
  * `PolyDirectionalLightHelper` to indicate where a directional light is
@@ -563,6 +828,22 @@ declare function octahedronPolygons(options: OctahedronPolygonsOptions): Polygon
563
828
  * is empty (e.g. `parseObj`, where it's a no-op).
564
829
  */
565
830
 
831
+ interface PolyVoxelCell {
832
+ x: number;
833
+ y: number;
834
+ z: number;
835
+ color: string;
836
+ }
837
+ interface PolyVoxelSource {
838
+ kind: "magica-vox";
839
+ cells: PolyVoxelCell[];
840
+ rows: number;
841
+ cols: number;
842
+ depth: number;
843
+ scale: number;
844
+ gridShift: number;
845
+ sourceBytes: number;
846
+ }
566
847
  interface ParseAnimationClip {
567
848
  /** Stable numeric index in the source file's animation array. */
568
849
  index: number;
@@ -585,6 +866,8 @@ interface ParseAnimationController {
585
866
  interface ParseResult {
586
867
  /** The mesh, as a flat polygon list. Already vertex-permuted to polycss space. */
587
868
  polygons: Polygon[];
869
+ /** Optional raw voxel source for `.vox` fast paths; polygon fallback remains authoritative. */
870
+ voxelSource?: PolyVoxelSource;
588
871
  /** Optional animation sampler for formats that carry timeline data. */
589
872
  animation?: ParseAnimationController;
590
873
  /**
@@ -616,6 +899,8 @@ interface ParseResult {
616
899
  animations?: ParseAnimationClip[];
617
900
  /** Source file size in bytes (for diagnostics). */
618
901
  sourceBytes?: number;
902
+ /** Voxel count for `.vox` sources. */
903
+ voxelCount?: number;
619
904
  };
620
905
  }
621
906
 
@@ -851,8 +1136,9 @@ declare function bakeSolidTextureSamples(result: ParseResult, options?: SolidTex
851
1136
 
852
1137
  interface VoxParseOptions {
853
1138
  /**
854
- * Largest mesh extent (in scene-space units). The mesh is uniformly
855
- * scaled so its longest bbox dimension equals this. Default: 60.
1139
+ * Largest mesh extent (in scene-space units). For `.vox`, the requested
1140
+ * extent is snapped to the nearest integer CSS cell size to keep voxel
1141
+ * fast-path coordinates integral. Default: 60.
856
1142
  */
857
1143
  targetSize?: number;
858
1144
  /**
@@ -864,6 +1150,51 @@ interface VoxParseOptions {
864
1150
  }
865
1151
  declare function parseVox(buffer: ArrayBuffer, options?: VoxParseOptions): ParseResult;
866
1152
 
1153
+ type PlaneAxis = "x" | "y" | "z";
1154
+ type PolyVoxelFace = "t" | "b" | "bl" | "br" | "fr" | "fl";
1155
+ interface PolyVoxelWallsMask {
1156
+ t: boolean;
1157
+ b: boolean;
1158
+ bl: boolean;
1159
+ br: boolean;
1160
+ fl: boolean;
1161
+ fr: boolean;
1162
+ }
1163
+ interface FaceKey {
1164
+ axis: PlaneAxis;
1165
+ plane: number;
1166
+ face: PolyVoxelFace;
1167
+ }
1168
+ interface FaceBuffer {
1169
+ width: number;
1170
+ height: number;
1171
+ minRow: number;
1172
+ minCol: number;
1173
+ ids: Uint32Array;
1174
+ mask: Uint8Array;
1175
+ filledCount: number;
1176
+ palette: string[];
1177
+ }
1178
+ interface FaceData {
1179
+ key: FaceKey;
1180
+ buffer: FaceBuffer;
1181
+ }
1182
+ type Brush = {
1183
+ r0: number;
1184
+ c0: number;
1185
+ r1: number;
1186
+ c1: number;
1187
+ baseColor: string;
1188
+ };
1189
+ type SlicePlan = {
1190
+ key: FaceKey;
1191
+ buffer: FaceBuffer;
1192
+ brushes: Brush[];
1193
+ };
1194
+ declare const NEXT_LAYER_STEP: Record<PolyVoxelFace, number>;
1195
+ declare const buildSlicePlan: (faceData: FaceData, nextLayer: FaceBuffer | null) => SlicePlan;
1196
+ declare const buildFaceDataFromVoxelSource: (source: PolyVoxelSource) => FaceData[];
1197
+
867
1198
  /**
868
1199
  * loadMesh — high-level fetch+parse dispatcher. Picks the parser by file
869
1200
  * extension, fetches the URL, runs the parser, returns the unified
@@ -908,7 +1239,12 @@ interface LoadMeshOptions {
908
1239
  * low-poly models that use texture atlases as color swatches.
909
1240
  */
910
1241
  solidTextureSamples?: boolean | SolidTextureSampleOptions;
1242
+ /**
1243
+ * Mesh optimization intent. Defaults to "lossy"; set "lossless" to keep
1244
+ * exact planar candidates only.
1245
+ */
1246
+ meshResolution?: MeshResolution;
911
1247
  }
912
1248
  declare function loadMesh(url: string, options?: LoadMeshOptions): Promise<ParseResult>;
913
1249
 
914
- export { type ArrowPolygonsOptions, type AutoRotateConfig, type AutoRotateOption, type AxesHelperOptions, BASE_TILE, type CameraHandle, type CameraState, type CameraStyleInput, type CoverPlanarPolygonsOptions, type CullInteriorOptions, DEFAULT_CAMERA_STATE, DEFAULT_PROJECTION, type GltfParseOptions, type LoadMeshOptions, type LoopMode, LoopOnce, LoopPingPong, LoopRepeat, type MtlParseResult, type NormalizeResult, type ObjParseOptions, type OctahedronPolygonsOptions, type ParseAnimationClip, type ParseAnimationController, type ParseResult, type ParsedColor, type PolyAmbientLight, type PolyAnimationAction, type ParseAnimationClip as PolyAnimationClip, type PolyAnimationMixer, type PolyAnimationTarget, type PolyDirectionalLight, type PolyMaterial, type PolyTextureLightingMode, type Polygon, type PolygonFace, type RingPolygonsOptions, type SceneBbox, type SceneContext, type SceneContextBuildArgs, type SceneContextBuildResult, type SolidTextureSampleOptions, type TexturePaintMetrics, type TexturePaintMetricsOptions, type TextureTriangle, type Vec2, type Vec3, type VoxParseOptions, arrowPolygons, axesHelperPolygons, bakeSolidTextureSampledPolygons, bakeSolidTextureSamples, buildSceneContext, clampChannel, computeSceneBbox, computeShapeLighting, computeTexturePaintMetrics, coverPlanarPolygons, createIsometricCamera, createPolyAnimationMixer, cullInteriorPolygons, formatColor, inverseRotateVec3, loadMesh, mergePolygons, normalizeInvertMultiplier, normalizePolygons, octahedronPolygons, parseColor, parseGltf, parseHexColor, parseMtl, parseObj, parsePureColor, parseRgbColor, parseVox, polygonFaces, ringPolygons, rotateVec3, shadeColor };
1250
+ export { type ApproximateMergeOptions, type ArrowPolygonsOptions, type AutoRotateConfig, type AutoRotateOption, type AxesHelperOptions, BASE_TILE, type BoxFace, type BoxFaceOptions, type BoxPolygonsOptions, CAMERA_BACKFACE_CULL_EPS, type CameraCullNormalGroup, type CameraCullRotation, type CameraHandle, type CameraState, type CameraStyleInput, type CoverPlanarPolygonsOptions, type CullInteriorOptions, DEFAULT_CAMERA_STATE, DEFAULT_PROJECTION, type DedupeOverlappingPolygonsOptions, type GltfParseOptions, type LoadMeshOptions, type LoopMode, LoopOnce, LoopPingPong, LoopRepeat, type MeshResolution, type MtlParseResult, type NormalizeResult, type ObjParseOptions, type OctahedronPolygonsOptions, type OptimizeMeshPolygonsOptions, NEXT_LAYER_STEP as POLY_VOXEL_NEXT_LAYER_STEP, type ParseAnimationClip, type ParseAnimationController, type ParseResult, type ParsedColor, type PlanePolygonsOptions, type PolyAmbientLight, type PolyAnimationAction, type ParseAnimationClip as PolyAnimationClip, type PolyAnimationMixer, type PolyAnimationTarget, type PolyDirectionalLight, type PolyMaterial, type PolyTextureLightingMode, type Brush as PolyVoxelBrush, type PolyVoxelCell, type PolyVoxelFace, type FaceBuffer as PolyVoxelFaceBuffer, type FaceData as PolyVoxelFaceData, type FaceKey as PolyVoxelFaceKey, type PlaneAxis as PolyVoxelPlaneAxis, type SlicePlan as PolyVoxelSlicePlan, type PolyVoxelSource, type PolyVoxelWallsMask, type Polygon, type PolygonFace, QUAT_IDENTITY, type Quat, type RingPolygonsOptions, type RingQuadPolygonsOptions, type SceneBbox, type SceneContext, type SceneContextBuildArgs, type SceneContextBuildResult, type SolidTextureSampleOptions, type TexturePaintMetrics, type TexturePaintMetricsOptions, type TextureTriangle, VOXEL_CAMERA_CULL_AXIS_EPS, VOXEL_CAMERA_CULL_NORMAL_LIMIT, type Vec2, type Vec3, type VoxParseOptions, arrowPolygons, axesHelperPolygons, bakeSolidTextureSampledPolygons, bakeSolidTextureSamples, boxPolygons, buildFaceDataFromVoxelSource as buildPolyVoxelFaceData, buildSlicePlan as buildPolyVoxelSlicePlan, buildSceneContext, cameraCullNormalGroups, cameraCullNormalGroupsFromPolygons, cameraCullNormalKey, cameraCullVisibleSignature, cameraFacingDepth, clampChannel, computeSceneBbox, computeShapeLighting, computeTexturePaintMetrics, coverPlanarPolygons, createIsometricCamera, createPolyAnimationMixer, cullInteriorPolygons, dedupeOverlappingPolygons, eulerXYZFromQuat, findOverlappingPolygonDuplicates, formatColor, inverseRotateVec3, isAxisAlignedSurfaceNormal, isVoxelCameraCullableNormalGroups, loadMesh, mergePolygons, normalFacesCamera, normalizeInvertMultiplier, normalizePolygons, octahedronPolygons, optimizeMeshPolygons, parseColor, parseGltf, parseHexColor, parseMtl, parseObj, parsePureColor, parseRgbColor, parseVox, planePolygons, polygonCssSurfaceNormal, polygonFaces, polygonFacesCamera, quatFromAxisAngle, quatFromEulerXYZ, quatMultiply, ringPolygons, ringQuadPolygons, rotateVec3, shadeColor };