@aura3d/rendering 4.0.3 → 4.0.4

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.
Files changed (240) hide show
  1. package/dist/EnvironmentPlatform.d.ts.map +1 -1
  2. package/dist/EnvironmentPlatform.js +6 -2
  3. package/dist/EnvironmentPlatform.js.map +1 -1
  4. package/dist/ForwardPass.d.ts +2 -0
  5. package/dist/ForwardPass.d.ts.map +1 -1
  6. package/dist/ForwardPass.js +70 -5
  7. package/dist/ForwardPass.js.map +1 -1
  8. package/dist/Geometry.d.ts +40 -0
  9. package/dist/Geometry.d.ts.map +1 -1
  10. package/dist/Geometry.js +39 -2
  11. package/dist/Geometry.js.map +1 -1
  12. package/dist/IndexBuffer.d.ts +16 -1
  13. package/dist/IndexBuffer.d.ts.map +1 -1
  14. package/dist/IndexBuffer.js +46 -1
  15. package/dist/IndexBuffer.js.map +1 -1
  16. package/dist/InstancedPBRMaterial.d.ts +2 -0
  17. package/dist/InstancedPBRMaterial.d.ts.map +1 -1
  18. package/dist/InstancedPBRMaterial.js +1 -0
  19. package/dist/InstancedPBRMaterial.js.map +1 -1
  20. package/dist/Material.d.ts +9 -0
  21. package/dist/Material.d.ts.map +1 -1
  22. package/dist/Material.js +3 -0
  23. package/dist/Material.js.map +1 -1
  24. package/dist/PBRMaterial.d.ts +2 -0
  25. package/dist/PBRMaterial.d.ts.map +1 -1
  26. package/dist/PBRMaterial.js +1 -0
  27. package/dist/PBRMaterial.js.map +1 -1
  28. package/dist/PortableShaderMaterial.d.ts +13 -3
  29. package/dist/PortableShaderMaterial.d.ts.map +1 -1
  30. package/dist/PortableShaderMaterial.js +24 -12
  31. package/dist/PortableShaderMaterial.js.map +1 -1
  32. package/dist/RenderDevice.d.ts +98 -0
  33. package/dist/RenderDevice.d.ts.map +1 -1
  34. package/dist/RenderDevice.js +129 -0
  35. package/dist/RenderDevice.js.map +1 -1
  36. package/dist/Renderer.d.ts +94 -0
  37. package/dist/Renderer.d.ts.map +1 -1
  38. package/dist/Renderer.js +321 -26
  39. package/dist/Renderer.js.map +1 -1
  40. package/dist/Sampler.d.ts +35 -0
  41. package/dist/Sampler.d.ts.map +1 -1
  42. package/dist/Sampler.js +96 -0
  43. package/dist/Sampler.js.map +1 -1
  44. package/dist/ShaderLibraryCore.d.ts +14 -0
  45. package/dist/ShaderLibraryCore.d.ts.map +1 -1
  46. package/dist/ShaderLibraryCore.js +94 -4
  47. package/dist/ShaderLibraryCore.js.map +1 -1
  48. package/dist/Texture.d.ts +53 -1
  49. package/dist/Texture.d.ts.map +1 -1
  50. package/dist/Texture.js +53 -2
  51. package/dist/Texture.js.map +1 -1
  52. package/dist/UnlitMaterial.d.ts +46 -0
  53. package/dist/UnlitMaterial.d.ts.map +1 -1
  54. package/dist/UnlitMaterial.js +32 -3
  55. package/dist/UnlitMaterial.js.map +1 -1
  56. package/dist/VertexFormat.d.ts +19 -1
  57. package/dist/VertexFormat.d.ts.map +1 -1
  58. package/dist/VertexFormat.js +40 -1
  59. package/dist/VertexFormat.js.map +1 -1
  60. package/dist/WebGL2Device.d.ts +16 -0
  61. package/dist/WebGL2Device.d.ts.map +1 -1
  62. package/dist/WebGL2Device.js +31 -6
  63. package/dist/WebGL2Device.js.map +1 -1
  64. package/dist/WebGPUDevice.d.ts +92 -1
  65. package/dist/WebGPUDevice.d.ts.map +1 -1
  66. package/dist/WebGPUDevice.js +417 -44
  67. package/dist/WebGPUDevice.js.map +1 -1
  68. package/dist/batching/BatchedGeometryPool.d.ts +22 -1
  69. package/dist/batching/BatchedGeometryPool.d.ts.map +1 -1
  70. package/dist/batching/BatchedGeometryPool.js +50 -2
  71. package/dist/batching/BatchedGeometryPool.js.map +1 -1
  72. package/dist/batching/DrawDataTexture.d.ts +21 -1
  73. package/dist/batching/DrawDataTexture.d.ts.map +1 -1
  74. package/dist/batching/DrawDataTexture.js +30 -4
  75. package/dist/batching/DrawDataTexture.js.map +1 -1
  76. package/dist/batching/MultiDrawBatch.d.ts +26 -0
  77. package/dist/batching/MultiDrawBatch.d.ts.map +1 -1
  78. package/dist/batching/MultiDrawBatch.js +64 -2
  79. package/dist/batching/MultiDrawBatch.js.map +1 -1
  80. package/dist/batching/index.d.ts +2 -2
  81. package/dist/batching/index.d.ts.map +1 -1
  82. package/dist/batching/index.js +2 -2
  83. package/dist/batching/index.js.map +1 -1
  84. package/dist/compute/ComputeContext.d.ts +84 -0
  85. package/dist/compute/ComputeContext.d.ts.map +1 -0
  86. package/dist/compute/ComputeContext.js +371 -0
  87. package/dist/compute/ComputeContext.js.map +1 -0
  88. package/dist/compute/index.d.ts +4 -0
  89. package/dist/compute/index.d.ts.map +1 -0
  90. package/dist/compute/index.js +3 -0
  91. package/dist/compute/index.js.map +1 -0
  92. package/dist/compute/types.d.ts +108 -0
  93. package/dist/compute/types.d.ts.map +1 -0
  94. package/dist/compute/types.js +25 -0
  95. package/dist/compute/types.js.map +1 -0
  96. package/dist/contracts/core.d.ts +1 -1
  97. package/dist/contracts/core.d.ts.map +1 -1
  98. package/dist/contracts/core.js.map +1 -1
  99. package/dist/contracts/flags.state.d.ts.map +1 -1
  100. package/dist/contracts/flags.state.js +20 -1
  101. package/dist/contracts/flags.state.js.map +1 -1
  102. package/dist/contracts/output.d.ts +1 -1
  103. package/dist/contracts/output.d.ts.map +1 -1
  104. package/dist/contracts/output.js.map +1 -1
  105. package/dist/contracts/post.d.ts +7 -0
  106. package/dist/contracts/post.d.ts.map +1 -1
  107. package/dist/contracts/post.js.map +1 -1
  108. package/dist/contracts/renderItem.d.ts +15 -0
  109. package/dist/contracts/renderItem.d.ts.map +1 -1
  110. package/dist/contracts/renderSource.d.ts +3 -1
  111. package/dist/contracts/renderSource.d.ts.map +1 -1
  112. package/dist/contracts/sampling.d.ts +23 -0
  113. package/dist/contracts/sampling.d.ts.map +1 -1
  114. package/dist/contracts/sampling.js.map +1 -1
  115. package/dist/environment/EnvironmentCache.d.ts.map +1 -1
  116. package/dist/environment/EnvironmentCache.js +7 -3
  117. package/dist/environment/EnvironmentCache.js.map +1 -1
  118. package/dist/environment/RoomEnvironmentScene.d.ts +2 -2
  119. package/dist/environment/RoomEnvironmentScene.d.ts.map +1 -1
  120. package/dist/environment/RoomEnvironmentScene.js.map +1 -1
  121. package/dist/geometry/Circle.d.ts +14 -0
  122. package/dist/geometry/Circle.d.ts.map +1 -0
  123. package/dist/geometry/Circle.js +31 -0
  124. package/dist/geometry/Circle.js.map +1 -0
  125. package/dist/geometry/Cone.d.ts +37 -0
  126. package/dist/geometry/Cone.d.ts.map +1 -0
  127. package/dist/geometry/Cone.js +129 -0
  128. package/dist/geometry/Cone.js.map +1 -0
  129. package/dist/geometry/Convex.d.ts +19 -0
  130. package/dist/geometry/Convex.d.ts.map +1 -0
  131. package/dist/geometry/Convex.js +27 -0
  132. package/dist/geometry/Convex.js.map +1 -0
  133. package/dist/geometry/Edges.d.ts +15 -0
  134. package/dist/geometry/Edges.d.ts.map +1 -0
  135. package/dist/geometry/Edges.js +98 -0
  136. package/dist/geometry/Edges.js.map +1 -0
  137. package/dist/geometry/Extrude.d.ts +29 -0
  138. package/dist/geometry/Extrude.d.ts.map +1 -0
  139. package/dist/geometry/Extrude.js +403 -0
  140. package/dist/geometry/Extrude.js.map +1 -0
  141. package/dist/geometry/Lathe.d.ts +20 -0
  142. package/dist/geometry/Lathe.d.ts.map +1 -0
  143. package/dist/geometry/Lathe.js +94 -0
  144. package/dist/geometry/Lathe.js.map +1 -0
  145. package/dist/geometry/Polyhedron.d.ts +21 -0
  146. package/dist/geometry/Polyhedron.d.ts.map +1 -0
  147. package/dist/geometry/Polyhedron.js +201 -0
  148. package/dist/geometry/Polyhedron.js.map +1 -0
  149. package/dist/geometry/Primitives.d.ts +38 -2
  150. package/dist/geometry/Primitives.d.ts.map +1 -1
  151. package/dist/geometry/Primitives.js +114 -0
  152. package/dist/geometry/Primitives.js.map +1 -1
  153. package/dist/geometry/Ring.d.ts +16 -0
  154. package/dist/geometry/Ring.d.ts.map +1 -0
  155. package/dist/geometry/Ring.js +44 -0
  156. package/dist/geometry/Ring.js.map +1 -0
  157. package/dist/geometry/RoundedBox.d.ts +22 -0
  158. package/dist/geometry/RoundedBox.d.ts.map +1 -0
  159. package/dist/geometry/RoundedBox.js +191 -0
  160. package/dist/geometry/RoundedBox.js.map +1 -0
  161. package/dist/geometry/Shape.d.ts +15 -0
  162. package/dist/geometry/Shape.d.ts.map +1 -0
  163. package/dist/geometry/Shape.js +44 -0
  164. package/dist/geometry/Shape.js.map +1 -0
  165. package/dist/geometry/Support.d.ts +137 -0
  166. package/dist/geometry/Support.d.ts.map +1 -0
  167. package/dist/geometry/Support.js +1066 -0
  168. package/dist/geometry/Support.js.map +1 -0
  169. package/dist/geometry/TorusKnot.d.ts +18 -0
  170. package/dist/geometry/TorusKnot.d.ts.map +1 -0
  171. package/dist/geometry/TorusKnot.js +83 -0
  172. package/dist/geometry/TorusKnot.js.map +1 -0
  173. package/dist/geometry/Tube.d.ts +19 -0
  174. package/dist/geometry/Tube.d.ts.map +1 -0
  175. package/dist/geometry/Tube.js +70 -0
  176. package/dist/geometry/Tube.js.map +1 -0
  177. package/dist/geometry/Wireframe.d.ts +19 -0
  178. package/dist/geometry/Wireframe.d.ts.map +1 -0
  179. package/dist/geometry/Wireframe.js +63 -0
  180. package/dist/geometry/Wireframe.js.map +1 -0
  181. package/dist/index.d.ts +38 -7
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js +25 -3
  184. package/dist/index.js.map +1 -1
  185. package/dist/lanes/prd11.js +1 -1
  186. package/dist/lanes/prd11.js.map +1 -1
  187. package/dist/output/ToneMappingOperators.glsl.d.ts +1 -1
  188. package/dist/output/ToneMappingOperators.glsl.d.ts.map +1 -1
  189. package/dist/output/ToneMappingOperators.glsl.js +9 -1
  190. package/dist/output/ToneMappingOperators.glsl.js.map +1 -1
  191. package/dist/post/v2Entry.d.ts +1 -0
  192. package/dist/post/v2Entry.d.ts.map +1 -1
  193. package/dist/post/v2Entry.js.map +1 -1
  194. package/dist/post/v2Stages.d.ts +30 -1
  195. package/dist/post/v2Stages.d.ts.map +1 -1
  196. package/dist/post/v2Stages.js +87 -21
  197. package/dist/post/v2Stages.js.map +1 -1
  198. package/dist/program/ProgramCache.d.ts.map +1 -1
  199. package/dist/program/ProgramCache.js +12 -0
  200. package/dist/program/ProgramCache.js.map +1 -1
  201. package/dist/program/ProgramGenerator.d.ts.map +1 -1
  202. package/dist/program/ProgramGenerator.js +3 -0
  203. package/dist/program/ProgramGenerator.js.map +1 -1
  204. package/dist/reference/PostProcessPass.d.ts +1 -1
  205. package/dist/reference/PostProcessPass.d.ts.map +1 -1
  206. package/dist/reference/PostProcessPass.js +8 -1
  207. package/dist/reference/PostProcessPass.js.map +1 -1
  208. package/dist/renderer/CullingBatching.d.ts +44 -2
  209. package/dist/renderer/CullingBatching.d.ts.map +1 -1
  210. package/dist/renderer/CullingBatching.js +66 -11
  211. package/dist/renderer/CullingBatching.js.map +1 -1
  212. package/dist/shaders/chunks/lighting_mirrors.d.ts +2 -2
  213. package/dist/shaders/chunks/lighting_mirrors.d.ts.map +1 -1
  214. package/dist/shaders/chunks/lighting_mirrors.js.map +1 -1
  215. package/dist/shadows/DirectionalCascadeFitter.d.ts +8 -8
  216. package/dist/shadows/DirectionalCascadeFitter.d.ts.map +1 -1
  217. package/dist/shadows/DirectionalCascadeFitter.js.map +1 -1
  218. package/dist/shadows/ShadowAtlas.d.ts +5 -5
  219. package/dist/shadows/ShadowAtlas.d.ts.map +1 -1
  220. package/dist/shadows/ShadowAtlas.js.map +1 -1
  221. package/dist/vfx/ProceduralVolumeEmitter.d.ts +11 -0
  222. package/dist/vfx/ProceduralVolumeEmitter.d.ts.map +1 -1
  223. package/dist/vfx/ProceduralVolumeEmitter.js +20 -6
  224. package/dist/vfx/ProceduralVolumeEmitter.js.map +1 -1
  225. package/dist/webgl2/ContextLifecycle.d.ts +36 -0
  226. package/dist/webgl2/ContextLifecycle.d.ts.map +1 -1
  227. package/dist/webgl2/ContextLifecycle.js +110 -2
  228. package/dist/webgl2/ContextLifecycle.js.map +1 -1
  229. package/dist/webgl2/LegacyPost.d.ts +16 -1
  230. package/dist/webgl2/LegacyPost.d.ts.map +1 -1
  231. package/dist/webgl2/LegacyPost.js +49 -16
  232. package/dist/webgl2/LegacyPost.js.map +1 -1
  233. package/dist/webgl2/MultiDraw.d.ts.map +1 -1
  234. package/dist/webgl2/MultiDraw.js +42 -2
  235. package/dist/webgl2/MultiDraw.js.map +1 -1
  236. package/dist/webgl2/TextureUpload.d.ts +7 -0
  237. package/dist/webgl2/TextureUpload.d.ts.map +1 -1
  238. package/dist/webgl2/TextureUpload.js +54 -10
  239. package/dist/webgl2/TextureUpload.js.map +1 -1
  240. package/package.json +3 -3
@@ -0,0 +1,1066 @@
1
+ /**
2
+ * threejs-parity (docs/workflows/threejs-parity-gaps.md §5.2, lane L2) —
3
+ * shared plumbing for the new primitive generators.
4
+ *
5
+ * Every generator emits a `ParityMesh`: raw `number[]` buffers in the exact
6
+ * vertex order, index order and UV layout three.js 0.185.1 produces for the
7
+ * same parameters, so the parity fixtures can diff buffers element-by-element.
8
+ * `parityMeshToGeometry` packs the buffers into the engine `Geometry`
9
+ * (P3N3T4T2 when UVs exist — tangents are computed for the textured material
10
+ * contract — otherwise P3N3 / P3).
11
+ *
12
+ * Also hosts the two things L3 has not landed yet, coded against the frozen
13
+ * contracts instead:
14
+ * - `Curve3Adapter` implements the frozen `Curve<Vector3>` interface
15
+ * (`M/Curves.ts`) over any `getPoint(t)` sampler, porting three's
16
+ * arc-length table + `computeFrenetFrames` parallel transport exactly.
17
+ * `resolveCurve3` accepts a frozen `Curve`, a `{ getPoint }` sampler, an
18
+ * M/CatmullRomCurve3/CubicBezierCurve3, or a plain point list.
19
+ * - `resolveShape2D` normalizes `params.shape` inputs (point lists,
20
+ * `{points,holes}`, `{extractPoints}` L3 `Shape` objects) into contour +
21
+ * holes; `triangulateShape` is a verbatim port of three's ShapeUtils over
22
+ * a verbatim port of the vendored mapbox earcut 3.0.2 (same indices).
23
+ */
24
+ import { Geometry } from "../Geometry.js";
25
+ import { IndexBuffer } from "../IndexBuffer.js";
26
+ import { VertexBuffer } from "../VertexBuffer.js";
27
+ import { VertexFormat } from "../VertexFormat.js";
28
+ import { CatmullRomCurve3 } from "@aura3d/math";
29
+ import { Matrix4 } from "@aura3d/math";
30
+ import { Vector2 } from "@aura3d/math";
31
+ import { Vector3 } from "@aura3d/math";
32
+ export function computeParityBounds(positions) {
33
+ const min = [Infinity, Infinity, Infinity];
34
+ const max = [-Infinity, -Infinity, -Infinity];
35
+ for (let i = 0; i < positions.length; i += 3) {
36
+ const x = positions[i];
37
+ const y = positions[i + 1];
38
+ const z = positions[i + 2];
39
+ if (x < min[0])
40
+ min[0] = x;
41
+ if (x > max[0])
42
+ max[0] = x;
43
+ if (y < min[1])
44
+ min[1] = y;
45
+ if (y > max[1])
46
+ max[1] = y;
47
+ if (z < min[2])
48
+ min[2] = z;
49
+ if (z > max[2])
50
+ max[2] = z;
51
+ }
52
+ return { min, max };
53
+ }
54
+ /**
55
+ * Per-vertex averaged UV-derivative tangents (vec4, w = +1). three does not
56
+ * emit tangents; these exist solely so parity meshes ride the engine's
57
+ * textured P3N3T4T2 format — they are never compared in the fixtures.
58
+ */
59
+ export function computeParityTangents(positions, uvs, indices) {
60
+ const count = positions.length / 3;
61
+ const t = new Float32Array(count * 4);
62
+ const tx = new Float32Array(count);
63
+ const ty = new Float32Array(count);
64
+ const tz = new Float32Array(count);
65
+ for (let f = 0; f + 2 < indices.length; f += 3) {
66
+ const ia = indices[f];
67
+ const ib = indices[f + 1];
68
+ const ic = indices[f + 2];
69
+ const ax = positions[ia * 3];
70
+ const ay = positions[ia * 3 + 1];
71
+ const az = positions[ia * 3 + 2];
72
+ const bx = positions[ib * 3];
73
+ const by = positions[ib * 3 + 1];
74
+ const bz = positions[ib * 3 + 2];
75
+ const cx = positions[ic * 3];
76
+ const cy = positions[ic * 3 + 1];
77
+ const cz = positions[ic * 3 + 2];
78
+ const e1x = bx - ax;
79
+ const e1y = by - ay;
80
+ const e1z = bz - az;
81
+ const e2x = cx - ax;
82
+ const e2y = cy - ay;
83
+ const e2z = cz - az;
84
+ const du1 = uvs[ib * 2] - uvs[ia * 2];
85
+ const dv1 = uvs[ib * 2 + 1] - uvs[ia * 2 + 1];
86
+ const du2 = uvs[ic * 2] - uvs[ia * 2];
87
+ const dv2 = uvs[ic * 2 + 1] - uvs[ia * 2 + 1];
88
+ const det = du1 * dv2 - du2 * dv1;
89
+ if (Math.abs(det) < 1e-12)
90
+ continue;
91
+ const r = 1 / det;
92
+ const sx = (e1x * dv2 - e2x * dv1) * r;
93
+ const sy = (e1y * dv2 - e2y * dv1) * r;
94
+ const sz = (e1z * dv2 - e2z * dv1) * r;
95
+ for (const i of [ia, ib, ic]) {
96
+ tx[i] = tx[i] + sx;
97
+ ty[i] = ty[i] + sy;
98
+ tz[i] = tz[i] + sz;
99
+ }
100
+ }
101
+ for (let i = 0; i < count; i += 1) {
102
+ const len = Math.hypot(tx[i], ty[i], tz[i]);
103
+ if (len < 1e-12) {
104
+ t[i * 4] = 1;
105
+ t[i * 4 + 3] = 1;
106
+ continue;
107
+ }
108
+ t[i * 4] = tx[i] / len;
109
+ t[i * 4 + 1] = ty[i] / len;
110
+ t[i * 4 + 2] = tz[i] / len;
111
+ t[i * 4 + 3] = 1;
112
+ }
113
+ return t;
114
+ }
115
+ /**
116
+ * three's `BufferGeometry.computeVertexNormals`: indexed input accumulates
117
+ * face normals per vertex then normalizes; non-indexed input writes the flat
118
+ * face normal to all three vertices (ExtrudeGeometry / detail=0 Polyhedron).
119
+ */
120
+ export function computeVertexNormals(positions, indices) {
121
+ const count = positions.length / 3;
122
+ const normals = new Array(positions.length).fill(0);
123
+ const va = { x: 0, y: 0, z: 0 };
124
+ const vb = { x: 0, y: 0, z: 0 };
125
+ const vc = { x: 0, y: 0, z: 0 };
126
+ const face = (a, b, c) => {
127
+ // three: cb = c - b; ab = a - b; cb × ab, normalized.
128
+ const cbx = c.x - b.x;
129
+ const cby = c.y - b.y;
130
+ const cbz = c.z - b.z;
131
+ const abx = a.x - b.x;
132
+ const aby = a.y - b.y;
133
+ const abz = a.z - b.z;
134
+ let nx = cby * abz - cbz * aby;
135
+ let ny = cbz * abx - cbx * abz;
136
+ let nz = cbx * aby - cby * abx;
137
+ const len = Math.hypot(nx, ny, nz);
138
+ if (len > 0) {
139
+ nx /= len;
140
+ ny /= len;
141
+ nz /= len;
142
+ }
143
+ return [nx, ny, nz];
144
+ };
145
+ const read = (i, out) => {
146
+ out.x = positions[i * 3];
147
+ out.y = positions[i * 3 + 1];
148
+ out.z = positions[i * 3 + 2];
149
+ };
150
+ if (indices && indices.length > 0) {
151
+ for (let i = 0; i + 2 < indices.length; i += 3) {
152
+ const ia = indices[i];
153
+ const ib = indices[i + 1];
154
+ const ic = indices[i + 2];
155
+ read(ia, va);
156
+ read(ib, vb);
157
+ read(ic, vc);
158
+ const n = face(va, vb, vc);
159
+ for (const t of [ia, ib, ic]) {
160
+ normals[t * 3] = normals[t * 3] + n[0];
161
+ normals[t * 3 + 1] = normals[t * 3 + 1] + n[1];
162
+ normals[t * 3 + 2] = normals[t * 3 + 2] + n[2];
163
+ }
164
+ }
165
+ for (let i = 0; i < count; i += 1) {
166
+ const nx = normals[i * 3];
167
+ const ny = normals[i * 3 + 1];
168
+ const nz = normals[i * 3 + 2];
169
+ const len = Math.hypot(nx, ny, nz);
170
+ if (len > 0) {
171
+ normals[i * 3] = nx / len;
172
+ normals[i * 3 + 1] = ny / len;
173
+ normals[i * 3 + 2] = nz / len;
174
+ }
175
+ }
176
+ }
177
+ else {
178
+ for (let i = 0; i < count; i += 3) {
179
+ read(i, va);
180
+ read(i + 1, vb);
181
+ read(i + 2, vc);
182
+ const n = face(va, vb, vc);
183
+ for (const t of [i, i + 1, i + 2]) {
184
+ normals[t * 3] = n[0];
185
+ normals[t * 3 + 1] = n[1];
186
+ normals[t * 3 + 2] = n[2];
187
+ }
188
+ }
189
+ }
190
+ return normals;
191
+ }
192
+ /** Pack a `ParityMesh` into the engine `Geometry` (normals computed when absent). */
193
+ export function parityMeshToGeometry(mesh, topology = "triangles") {
194
+ const vertexCount = mesh.positions.length / 3;
195
+ if (vertexCount === 0) {
196
+ const empty = new VertexBuffer(VertexFormat.P3, 1);
197
+ empty.setAttribute(0, "position", [0, 0, 0]);
198
+ return new Geometry(empty, null, topology, { min: [0, 0, 0], max: [0, 0, 0] });
199
+ }
200
+ const normals = mesh.normals ?? computeVertexNormals(mesh.positions, mesh.indices);
201
+ const textured = mesh.uvs !== undefined && mesh.uvs.length === vertexCount * 2;
202
+ const format = textured ? VertexFormat.P3N3T4T2 : VertexFormat.P3N3;
203
+ const vertices = new VertexBuffer(format, vertexCount);
204
+ const indexList = mesh.indices ?? Array.from({ length: vertexCount }, (_, i) => i);
205
+ const tangents = textured ? computeParityTangents(mesh.positions, mesh.uvs ?? [], indexList) : undefined;
206
+ for (let i = 0; i < vertexCount; i += 1) {
207
+ vertices.setAttribute(i, "position", [mesh.positions[i * 3], mesh.positions[i * 3 + 1], mesh.positions[i * 3 + 2]]);
208
+ vertices.setAttribute(i, "normal", [normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]]);
209
+ if (textured) {
210
+ vertices.setAttribute(i, "uv", [mesh.uvs[i * 2], mesh.uvs[i * 2 + 1]]);
211
+ vertices.setAttribute(i, "tangent", [tangents[i * 4], tangents[i * 4 + 1], tangents[i * 4 + 2], tangents[i * 4 + 3]]);
212
+ }
213
+ }
214
+ const bounds = computeParityBounds(mesh.positions);
215
+ const indexBuffer = indexList.length > 0 ? new IndexBuffer(indexList, vertexCount) : null;
216
+ return new Geometry(vertices, indexBuffer, topology, bounds);
217
+ }
218
+ function toVector2(value) {
219
+ if (value instanceof Vector2)
220
+ return value;
221
+ if (Array.isArray(value)) {
222
+ const arr = value;
223
+ return new Vector2(arr[0], arr[1]);
224
+ }
225
+ const obj = value;
226
+ return new Vector2(obj.x, obj.y);
227
+ }
228
+ function isVec2Like(value) {
229
+ if (value instanceof Vector2)
230
+ return true;
231
+ if (Array.isArray(value))
232
+ return value.length >= 2 && typeof value[0] === "number" && typeof value[1] === "number";
233
+ return typeof value === "object" && value !== null
234
+ && typeof value.x === "number"
235
+ && typeof value.y === "number";
236
+ }
237
+ function vec2Array(value) {
238
+ if (!Array.isArray(value) || value.length === 0)
239
+ return undefined;
240
+ if (!isVec2Like(value[0]))
241
+ return undefined;
242
+ return value.map((entry) => toVector2(entry));
243
+ }
244
+ /**
245
+ * Normalize `params.shape` / `params.points` into contour + holes. Accepts:
246
+ * - `[x,y][]`, `Vector2[]`, `{x,y}[]` (contour only)
247
+ * - `{ points }`, `{ contour }`, `{ shape }` with optional `holes`
248
+ * - L3 `Shape`: `{ extractPoints(curveSegments) -> {shape, holes} }`
249
+ * - Path-like `{ getPoints() }` (single contour)
250
+ */
251
+ export function resolveShape2D(input, curveSegments = 12) {
252
+ const direct = vec2Array(input);
253
+ if (direct)
254
+ return { shape: direct, holes: [] };
255
+ if (typeof input === "object" && input !== null) {
256
+ const record = input;
257
+ if (typeof record.extractPoints === "function") {
258
+ const extracted = record.extractPoints(curveSegments);
259
+ const shape = vec2Array(extracted?.shape) ?? [];
260
+ const holes = (extracted?.holes ?? []).map((hole) => vec2Array(hole) ?? []);
261
+ return { shape, holes };
262
+ }
263
+ for (const key of ["shape", "contour", "points", "outline"]) {
264
+ const contour = vec2Array(record[key]);
265
+ if (contour) {
266
+ const holes = Array.isArray(record.holes)
267
+ ? record.holes.map((hole) => vec2Array(hole) ?? [])
268
+ : [];
269
+ return { shape: contour, holes };
270
+ }
271
+ }
272
+ if (typeof record.getPoints === "function") {
273
+ const points = record.getPoints();
274
+ return { shape: vec2Array(points) ?? [], holes: [] };
275
+ }
276
+ }
277
+ throw new Error("Aura3D shape/extrude requires a shape outline (point list, {points,holes}, or a Shape with extractPoints).");
278
+ }
279
+ /** three's `ShapeUtils.area` (signed, shoelace). */
280
+ export function shapeArea(contour) {
281
+ const n = contour.length;
282
+ let a = 0;
283
+ for (let p = n - 1, q = 0; q < n; p = q++) {
284
+ a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
285
+ }
286
+ return a * 0.5;
287
+ }
288
+ /** three's `ShapeUtils.isClockWise` — sign of the shoelace area. */
289
+ export function isClockWise(pts) {
290
+ return shapeArea(pts) < 0;
291
+ }
292
+ function removeDupEndPts(points) {
293
+ const l = points.length;
294
+ // three uses Vector2.equals — exact coordinate equality.
295
+ if (l > 2 && points[l - 1].x === points[0].x && points[l - 1].y === points[0].y) {
296
+ points.pop();
297
+ }
298
+ }
299
+ /**
300
+ * three's `ShapeUtils.triangulateShape` over the vendored earcut below — same
301
+ * vertex feeding order, so the emitted faces are index-for-index identical.
302
+ */
303
+ export function triangulateShape(contour, holes) {
304
+ const vertices = [];
305
+ const holeIndices = [];
306
+ const faces = [];
307
+ const c = [...contour];
308
+ removeDupEndPts(c);
309
+ for (const p of c)
310
+ vertices.push(p.x, p.y);
311
+ let holeIndex = contour.length;
312
+ const hs = holes.map((hole) => [...hole]);
313
+ hs.forEach(removeDupEndPts);
314
+ for (const hole of hs) {
315
+ holeIndices.push(holeIndex);
316
+ holeIndex += hole.length;
317
+ for (const p of hole)
318
+ vertices.push(p.x, p.y);
319
+ }
320
+ const triangles = earcut(vertices, holeIndices);
321
+ for (let i = 0; i < triangles.length; i += 3) {
322
+ faces.push([triangles[i], triangles[i + 1], triangles[i + 2]]);
323
+ }
324
+ return faces;
325
+ }
326
+ // ─────────────────────────────────────────────────────────────────────────────
327
+ // Curve inputs — frozen `Curve<Vector3>` adapter (B-06) until L3 lands
328
+ // ─────────────────────────────────────────────────────────────────────────────
329
+ function clampNumber(value, min, max) {
330
+ return Math.max(min, Math.min(max, value));
331
+ }
332
+ /**
333
+ * Matrix4.makeRotationAxis(axis, angle) — column-major elements for a rotation
334
+ * of `angle` about a *unit* axis (three's formula verbatim).
335
+ */
336
+ export function rotationAxisMatrix(axis, angle) {
337
+ const c = Math.cos(angle);
338
+ const s = Math.sin(angle);
339
+ const t = 1 - c;
340
+ const x = axis.x;
341
+ const y = axis.y;
342
+ const z = axis.z;
343
+ const tx = t * x;
344
+ const ty = t * y;
345
+ // three's Matrix4.set row-major args → column-major elements
346
+ return new Matrix4([
347
+ tx * x + c, tx * y + z * s, tx * z - y * s, 0,
348
+ tx * y - z * s, ty * y + c, ty * z + x * s, 0,
349
+ tx * z + y * s, ty * z - x * s, t * z * z + c, 0,
350
+ 0, 0, 0, 1
351
+ ]);
352
+ }
353
+ /**
354
+ * Implements the frozen `Curve<Vector3>` interface over any `getPoint(t)`
355
+ * sampler, using three's exact base-class algorithms: 200-division arc-length
356
+ * cache, binary-search `getUtoTmapping`, finite-difference `getTangent`, and
357
+ * the TR425 parallel-transport `computeFrenetFrames`. When L3's real family
358
+ * lands, those objects satisfy `Curve` directly and never reach this adapter.
359
+ */
360
+ export class Curve3Adapter {
361
+ sampler;
362
+ cacheArcLengths;
363
+ needsUpdate = true;
364
+ arcLengthDivisions = 200;
365
+ /** Consulted by Extrude (three's `extrudePath.isCatmullRomCurve3 && closed`). */
366
+ closed = false;
367
+ /** Mirrors three's class flag — `extrudePath.isCatmullRomCurve3` gate. */
368
+ isCatmullRomCurve3 = false;
369
+ constructor(sampler) {
370
+ this.sampler = sampler;
371
+ }
372
+ getPoint(t) {
373
+ return this.sampler(Math.min(1, Math.max(0, t)));
374
+ }
375
+ getPointAt(u) {
376
+ return this.getPoint(this.getUtoTmapping(u));
377
+ }
378
+ getTangent(t) {
379
+ const delta = 0.0001;
380
+ let t1 = t - delta;
381
+ let t2 = t + delta;
382
+ if (t1 < 0)
383
+ t1 = 0;
384
+ if (t2 > 1)
385
+ t2 = 1;
386
+ const pt1 = this.getPoint(t1);
387
+ const pt2 = this.getPoint(t2);
388
+ return pt2.subtract(pt1).normalize();
389
+ }
390
+ getTangentAt(u) {
391
+ return this.getTangent(this.getUtoTmapping(u));
392
+ }
393
+ getLength() {
394
+ const lengths = this.getLengths();
395
+ return lengths[lengths.length - 1];
396
+ }
397
+ getLengths(divisions = this.arcLengthDivisions) {
398
+ if (this.cacheArcLengths && this.cacheArcLengths.length === divisions + 1 && !this.needsUpdate) {
399
+ return this.cacheArcLengths;
400
+ }
401
+ this.needsUpdate = false;
402
+ const cache = [0];
403
+ let last = this.getPoint(0);
404
+ let sum = 0;
405
+ for (let p = 1; p <= divisions; p += 1) {
406
+ const current = this.getPoint(p / divisions);
407
+ sum += current.distanceTo(last);
408
+ cache.push(sum);
409
+ last = current;
410
+ }
411
+ this.cacheArcLengths = cache;
412
+ return cache;
413
+ }
414
+ updateArcLengths() {
415
+ this.needsUpdate = true;
416
+ this.getLengths();
417
+ }
418
+ getUtoTmapping(u) {
419
+ const arcLengths = this.getLengths();
420
+ const il = arcLengths.length;
421
+ const targetArcLength = u * arcLengths[il - 1];
422
+ let low = 0;
423
+ let high = il - 1;
424
+ let i = 0;
425
+ while (low <= high) {
426
+ i = Math.floor(low + (high - low) / 2);
427
+ const comparison = arcLengths[i] - targetArcLength;
428
+ if (comparison < 0) {
429
+ low = i + 1;
430
+ }
431
+ else if (comparison > 0) {
432
+ high = i - 1;
433
+ }
434
+ else {
435
+ high = i;
436
+ break;
437
+ }
438
+ }
439
+ i = high;
440
+ if (arcLengths[i] === targetArcLength) {
441
+ return i / (il - 1);
442
+ }
443
+ const lengthBefore = arcLengths[i];
444
+ const lengthAfter = arcLengths[i + 1];
445
+ const segmentLength = lengthAfter - lengthBefore;
446
+ if (segmentLength === 0) {
447
+ return i / (il - 1);
448
+ }
449
+ const segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
450
+ return (i + segmentFraction) / (il - 1);
451
+ }
452
+ getSpacedPoints(divisions = 5) {
453
+ const points = [];
454
+ for (let i = 0; i <= divisions; i += 1) {
455
+ points.push(this.getPointAt(i / divisions));
456
+ }
457
+ return points;
458
+ }
459
+ getPoints(divisions = 5) {
460
+ const points = [];
461
+ for (let i = 0; i <= divisions; i += 1) {
462
+ points.push(this.getPoint(i / divisions));
463
+ }
464
+ return points;
465
+ }
466
+ computeFrenetFrames(segments, closed = false) {
467
+ // three's Curve.computeFrenetFrames — TR425 parallel transport with the
468
+ // initial normal perpendicular to the first tangent's smallest component.
469
+ const tangents = [];
470
+ const normals = [];
471
+ const binormals = [];
472
+ for (let i = 0; i <= segments; i += 1) {
473
+ tangents[i] = this.getTangentAt(i / segments);
474
+ }
475
+ let normal = new Vector3();
476
+ let min = Number.MAX_VALUE;
477
+ const tx = Math.abs(tangents[0].x);
478
+ const ty = Math.abs(tangents[0].y);
479
+ const tz = Math.abs(tangents[0].z);
480
+ if (tx <= min) {
481
+ min = tx;
482
+ normal = new Vector3(1, 0, 0);
483
+ }
484
+ if (ty <= min) {
485
+ min = ty;
486
+ normal = new Vector3(0, 1, 0);
487
+ }
488
+ if (tz <= min) {
489
+ normal = new Vector3(0, 0, 1);
490
+ }
491
+ const vec = tangents[0].cross(normal).normalize();
492
+ normals[0] = tangents[0].cross(vec);
493
+ binormals[0] = tangents[0].cross(normals[0]);
494
+ for (let i = 1; i <= segments; i += 1) {
495
+ normals[i] = normals[i - 1].clone();
496
+ binormals[i] = binormals[i - 1].clone();
497
+ const cross = tangents[i - 1].cross(tangents[i]);
498
+ if (cross.length() > Number.EPSILON) {
499
+ const axis = cross.normalize();
500
+ const theta = Math.acos(clampNumber(tangents[i - 1].dot(tangents[i]), -1, 1));
501
+ normals[i] = normals[i].transformMatrix4(rotationAxisMatrix(axis, theta));
502
+ }
503
+ binormals[i] = tangents[i].cross(normals[i]);
504
+ }
505
+ if (closed === true) {
506
+ let theta = Math.acos(clampNumber(normals[0].dot(normals[segments]), -1, 1));
507
+ theta /= segments;
508
+ if (tangents[0].dot(normals[0].cross(normals[segments])) > 0) {
509
+ theta = -theta;
510
+ }
511
+ for (let i = 1; i <= segments; i += 1) {
512
+ normals[i] = normals[i].transformMatrix4(rotationAxisMatrix(tangents[i], theta * i));
513
+ binormals[i] = tangents[i].cross(normals[i]);
514
+ }
515
+ }
516
+ return { tangents, normals, binormals };
517
+ }
518
+ }
519
+ function isFrozenCurve(value) {
520
+ const candidate = value;
521
+ return typeof candidate === "object" && candidate !== null
522
+ && typeof candidate.getPoint === "function"
523
+ && typeof candidate.getPointAt === "function"
524
+ && typeof candidate.getUtoTmapping === "function"
525
+ && typeof candidate.computeFrenetFrames === "function";
526
+ }
527
+ function toVector3(value) {
528
+ if (value instanceof Vector3)
529
+ return value;
530
+ if (Array.isArray(value)) {
531
+ const arr = value;
532
+ return new Vector3(arr[0], arr[1], arr[2]);
533
+ }
534
+ const obj = value;
535
+ return new Vector3(obj.x, obj.y, obj.z);
536
+ }
537
+ /**
538
+ * Resolve `params.path` / `params.extrudePath` into a frozen `Curve<Vector3>`:
539
+ * - an object already satisfying the frozen interface (L3's family) — used as-is;
540
+ * - `{ getPoint(t) }` samplers (incl. `CatmullRomCurve3`/`CubicBezierCurve3`) — wrapped in `Curve3Adapter`;
541
+ * - a point list → Catmull-Rom through the points (the same interpolation
542
+ * `M/CatmullRomCurve3` already implements).
543
+ */
544
+ export function resolveCurve3(input) {
545
+ if (isFrozenCurve(input))
546
+ return input;
547
+ if (typeof input === "object" && input !== null && typeof input.getPoint === "function") {
548
+ const sampler = input;
549
+ const adapter = new Curve3Adapter((t) => {
550
+ const p = sampler.getPoint(t);
551
+ return p instanceof Vector3 ? p : new Vector3(p[0], p[1], p[2]);
552
+ });
553
+ adapter.closed = sampler.closed === true;
554
+ adapter.isCatmullRomCurve3 = sampler.isCatmullRomCurve3 === true || input instanceof CatmullRomCurve3;
555
+ return adapter;
556
+ }
557
+ if (Array.isArray(input) && input.length >= 2) {
558
+ const points = input.map((value) => toVector3(value));
559
+ const cr = new CatmullRomCurve3(points);
560
+ const adapter = new Curve3Adapter((t) => cr.getPoint(t));
561
+ adapter.isCatmullRomCurve3 = true;
562
+ return adapter;
563
+ }
564
+ throw new Error("Aura3D path input must be a Curve, a { getPoint(t) } sampler, or a list of at least two points.");
565
+ }
566
+ export function earcut(data, holeIndices, dim = 2) {
567
+ const hasHoles = holeIndices !== undefined && holeIndices.length > 0;
568
+ const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
569
+ let outerNode = linkedList(data, 0, outerLen, dim, true);
570
+ const triangles = [];
571
+ if (!outerNode || outerNode.next === outerNode.prev)
572
+ return triangles;
573
+ let minX = 0;
574
+ let minY = 0;
575
+ let invSize = 0;
576
+ if (hasHoles)
577
+ outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
578
+ if (data.length > 80 * dim) {
579
+ minX = data[0];
580
+ minY = data[1];
581
+ let maxX = minX;
582
+ let maxY = minY;
583
+ for (let i = dim; i < outerLen; i += dim) {
584
+ const x = data[i];
585
+ const y = data[i + 1];
586
+ if (x < minX)
587
+ minX = x;
588
+ if (y < minY)
589
+ minY = y;
590
+ if (x > maxX)
591
+ maxX = x;
592
+ if (y > maxY)
593
+ maxY = y;
594
+ }
595
+ invSize = Math.max(maxX - minX, maxY - minY);
596
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
597
+ }
598
+ earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
599
+ return triangles;
600
+ }
601
+ function createNode(i, x, y) {
602
+ return {
603
+ i,
604
+ x,
605
+ y,
606
+ prev: null,
607
+ next: null,
608
+ z: 0,
609
+ prevZ: null,
610
+ nextZ: null,
611
+ steiner: false
612
+ };
613
+ }
614
+ function linkedList(data, start, end, dim, clockwise) {
615
+ let last;
616
+ if (clockwise === (signedArea(data, start, end, dim) > 0)) {
617
+ for (let i = start; i < end; i += dim)
618
+ last = insertNode(Math.floor(i / dim), data[i], data[i + 1], last);
619
+ }
620
+ else {
621
+ for (let i = end - dim; i >= start; i -= dim)
622
+ last = insertNode(Math.floor(i / dim), data[i], data[i + 1], last);
623
+ }
624
+ if (last && equals(last, last.next)) {
625
+ removeNode(last);
626
+ last = last.next;
627
+ }
628
+ return last;
629
+ }
630
+ function filterPoints(start, end) {
631
+ if (!start)
632
+ return start;
633
+ let e = end ?? start;
634
+ let p = start;
635
+ let again;
636
+ do {
637
+ again = false;
638
+ if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
639
+ removeNode(p);
640
+ p = e = p.prev;
641
+ if (p === p.next)
642
+ break;
643
+ again = true;
644
+ }
645
+ else {
646
+ p = p.next;
647
+ }
648
+ } while (again || p !== e);
649
+ return e;
650
+ }
651
+ function earcutLinked(earIn, triangles, dim, minX, minY, invSize, pass) {
652
+ if (!earIn)
653
+ return;
654
+ let ear = earIn;
655
+ if (pass === 0 && invSize !== 0)
656
+ indexCurve(ear, minX, minY, invSize);
657
+ let stop = ear;
658
+ while (ear.prev !== ear.next) {
659
+ const prev = ear.prev;
660
+ const next = ear.next;
661
+ if (invSize !== 0 ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
662
+ triangles.push(prev.i, ear.i, next.i);
663
+ removeNode(ear);
664
+ ear = next.next;
665
+ stop = next.next;
666
+ continue;
667
+ }
668
+ ear = next;
669
+ if (ear === stop) {
670
+ if (pass === 0) {
671
+ earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
672
+ }
673
+ else if (pass === 1) {
674
+ ear = cureLocalIntersections(filterPoints(ear), triangles);
675
+ earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
676
+ }
677
+ else if (pass === 2) {
678
+ splitEarcut(ear, triangles, dim, minX, minY, invSize);
679
+ }
680
+ break;
681
+ }
682
+ }
683
+ }
684
+ function isEar(ear) {
685
+ const a = ear.prev;
686
+ const b = ear;
687
+ const c = ear.next;
688
+ if (area(a, b, c) >= 0)
689
+ return false;
690
+ const ax = a.x;
691
+ const bx = b.x;
692
+ const cx = c.x;
693
+ const ay = a.y;
694
+ const by = b.y;
695
+ const cy = c.y;
696
+ const x0 = Math.min(ax, bx, cx);
697
+ const y0 = Math.min(ay, by, cy);
698
+ const x1 = Math.max(ax, bx, cx);
699
+ const y1 = Math.max(ay, by, cy);
700
+ let p = c.next;
701
+ while (p !== a) {
702
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1
703
+ && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y)
704
+ && area(p.prev, p, p.next) >= 0)
705
+ return false;
706
+ p = p.next;
707
+ }
708
+ return true;
709
+ }
710
+ function isEarHashed(ear, minX, minY, invSize) {
711
+ const a = ear.prev;
712
+ const b = ear;
713
+ const c = ear.next;
714
+ if (area(a, b, c) >= 0)
715
+ return false;
716
+ const ax = a.x;
717
+ const bx = b.x;
718
+ const cx = c.x;
719
+ const ay = a.y;
720
+ const by = b.y;
721
+ const cy = c.y;
722
+ const x0 = Math.min(ax, bx, cx);
723
+ const y0 = Math.min(ay, by, cy);
724
+ const x1 = Math.max(ax, bx, cx);
725
+ const y1 = Math.max(ay, by, cy);
726
+ const minZ = zOrder(x0, y0, minX, minY, invSize);
727
+ const maxZ = zOrder(x1, y1, minX, minY, invSize);
728
+ let p = ear.prevZ;
729
+ let n = ear.nextZ;
730
+ while (p && p.z >= minZ && n && n.z <= maxZ) {
731
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c
732
+ && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
733
+ return false;
734
+ p = p.prevZ;
735
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c
736
+ && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
737
+ return false;
738
+ n = n.nextZ;
739
+ }
740
+ while (p && p.z >= minZ) {
741
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c
742
+ && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
743
+ return false;
744
+ p = p.prevZ;
745
+ }
746
+ while (n && n.z <= maxZ) {
747
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c
748
+ && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
749
+ return false;
750
+ n = n.nextZ;
751
+ }
752
+ return true;
753
+ }
754
+ function cureLocalIntersections(start, triangles) {
755
+ let p = start;
756
+ do {
757
+ const a = p.prev;
758
+ const b = p.next.next;
759
+ if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
760
+ triangles.push(a.i, p.i, b.i);
761
+ removeNode(p);
762
+ removeNode(p.next);
763
+ p = start = b;
764
+ }
765
+ p = p.next;
766
+ } while (p !== start);
767
+ return filterPoints(p);
768
+ }
769
+ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
770
+ let a = start;
771
+ do {
772
+ let b = a.next.next;
773
+ while (b !== a.prev) {
774
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
775
+ let c = splitPolygon(a, b);
776
+ a = filterPoints(a, a.next);
777
+ c = filterPoints(c, c.next);
778
+ earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
779
+ earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
780
+ return;
781
+ }
782
+ b = b.next;
783
+ }
784
+ a = a.next;
785
+ } while (a !== start);
786
+ }
787
+ function eliminateHoles(data, holeIndices, outerNode, dim) {
788
+ const queue = [];
789
+ for (let i = 0, len = holeIndices.length; i < len; i += 1) {
790
+ const start = holeIndices[i] * dim;
791
+ const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
792
+ const list = linkedList(data, start, end, dim, false);
793
+ if (list === list.next)
794
+ list.steiner = true;
795
+ queue.push(getLeftmost(list));
796
+ }
797
+ queue.sort(compareXYSlope);
798
+ for (let i = 0; i < queue.length; i += 1) {
799
+ outerNode = eliminateHole(queue[i], outerNode);
800
+ }
801
+ return outerNode;
802
+ }
803
+ function compareXYSlope(a, b) {
804
+ let result = a.x - b.x;
805
+ if (result === 0) {
806
+ result = a.y - b.y;
807
+ if (result === 0) {
808
+ const aSlope = (a.next.y - a.y) / (a.next.x - a.x);
809
+ const bSlope = (b.next.y - b.y) / (b.next.x - b.x);
810
+ result = aSlope - bSlope;
811
+ }
812
+ }
813
+ return result;
814
+ }
815
+ function eliminateHole(hole, outerNode) {
816
+ const bridge = findHoleBridge(hole, outerNode);
817
+ if (!bridge)
818
+ return outerNode;
819
+ const bridgeReverse = splitPolygon(bridge, hole);
820
+ filterPoints(bridgeReverse, bridgeReverse.next);
821
+ return filterPoints(bridge, bridge.next);
822
+ }
823
+ function findHoleBridge(hole, outerNode) {
824
+ let p = outerNode;
825
+ const hx = hole.x;
826
+ const hy = hole.y;
827
+ let qx = -Infinity;
828
+ let m;
829
+ if (equals(hole, p))
830
+ return p;
831
+ do {
832
+ if (equals(hole, p.next))
833
+ return p.next;
834
+ else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
835
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
836
+ if (x <= hx && x > qx) {
837
+ qx = x;
838
+ m = p.x < p.next.x ? p : p.next;
839
+ if (x === hx)
840
+ return m;
841
+ }
842
+ }
843
+ p = p.next;
844
+ } while (p !== outerNode);
845
+ if (!m)
846
+ return undefined;
847
+ const stop = m;
848
+ const mx = m.x;
849
+ const my = m.y;
850
+ let tanMin = Infinity;
851
+ p = m;
852
+ do {
853
+ if (hx >= p.x && p.x >= mx && hx !== p.x
854
+ && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
855
+ const tan = Math.abs(hy - p.y) / (hx - p.x);
856
+ if (locallyInside(p, hole)
857
+ && (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
858
+ m = p;
859
+ tanMin = tan;
860
+ }
861
+ }
862
+ p = p.next;
863
+ } while (p !== stop);
864
+ return m;
865
+ }
866
+ function sectorContainsSector(m, p) {
867
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
868
+ }
869
+ function indexCurve(start, minX, minY, invSize) {
870
+ let p = start;
871
+ do {
872
+ if (p.z === 0)
873
+ p.z = zOrder(p.x, p.y, minX, minY, invSize);
874
+ p.prevZ = p.prev;
875
+ p.nextZ = p.next;
876
+ p = p.next;
877
+ } while (p !== start);
878
+ p.prevZ.nextZ = null;
879
+ p.prevZ = null;
880
+ sortLinked(p);
881
+ }
882
+ function sortLinked(list) {
883
+ let numMerges = 0;
884
+ let inSize = 1;
885
+ do {
886
+ let p = list;
887
+ let e;
888
+ list = null;
889
+ let tail = null;
890
+ numMerges = 0;
891
+ while (p) {
892
+ numMerges += 1;
893
+ let q = p;
894
+ let pSize = 0;
895
+ for (let i = 0; i < inSize; i += 1) {
896
+ pSize += 1;
897
+ q = q.nextZ;
898
+ if (!q)
899
+ break;
900
+ }
901
+ let qSize = inSize;
902
+ while (pSize > 0 || (qSize > 0 && q)) {
903
+ if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
904
+ e = p;
905
+ p = p.nextZ;
906
+ pSize -= 1;
907
+ }
908
+ else {
909
+ e = q;
910
+ q = q.nextZ;
911
+ qSize -= 1;
912
+ }
913
+ if (tail)
914
+ tail.nextZ = e ?? null;
915
+ else
916
+ list = e ?? null;
917
+ e.prevZ = tail;
918
+ tail = e;
919
+ }
920
+ p = q;
921
+ }
922
+ tail.nextZ = null;
923
+ inSize *= 2;
924
+ } while (numMerges > 1);
925
+ return list;
926
+ }
927
+ function zOrder(xIn, yIn, minX, minY, invSize) {
928
+ let x = Math.floor((xIn - minX) * invSize);
929
+ let y = Math.floor((yIn - minY) * invSize);
930
+ x = (x | (x << 8)) & 0x00ff00ff;
931
+ x = (x | (x << 4)) & 0x0f0f0f0f;
932
+ x = (x | (x << 2)) & 0x33333333;
933
+ x = (x | (x << 1)) & 0x55555555;
934
+ y = (y | (y << 8)) & 0x00ff00ff;
935
+ y = (y | (y << 4)) & 0x0f0f0f0f;
936
+ y = (y | (y << 2)) & 0x33333333;
937
+ y = (y | (y << 1)) & 0x55555555;
938
+ return x | (y << 1);
939
+ }
940
+ function getLeftmost(start) {
941
+ let p = start;
942
+ let leftmost = start;
943
+ do {
944
+ if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y))
945
+ leftmost = p;
946
+ p = p.next;
947
+ } while (p !== start);
948
+ return leftmost;
949
+ }
950
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
951
+ return (cx - px) * (ay - py) >= (ax - px) * (cy - py)
952
+ && (ax - px) * (by - py) >= (bx - px) * (ay - py)
953
+ && (bx - px) * (cy - py) >= (cx - px) * (by - py);
954
+ }
955
+ function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
956
+ return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);
957
+ }
958
+ function isValidDiagonal(a, b) {
959
+ return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b)
960
+ && (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b)
961
+ && (area(a.prev, a, b.prev) !== 0 || area(a, b.prev, b) !== 0)
962
+ || equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
963
+ }
964
+ function area(p, q, r) {
965
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
966
+ }
967
+ function equals(p1, p2) {
968
+ return p1.x === p2.x && p1.y === p2.y;
969
+ }
970
+ function intersects(p1, q1, p2, q2) {
971
+ const o1 = signNum(area(p1, q1, p2));
972
+ const o2 = signNum(area(p1, q1, q2));
973
+ const o3 = signNum(area(p2, q2, p1));
974
+ const o4 = signNum(area(p2, q2, q1));
975
+ if (o1 !== o2 && o3 !== o4)
976
+ return true;
977
+ if (o1 === 0 && onSegment(p1, p2, q1))
978
+ return true;
979
+ if (o2 === 0 && onSegment(p1, q2, q1))
980
+ return true;
981
+ if (o3 === 0 && onSegment(p2, p1, q2))
982
+ return true;
983
+ if (o4 === 0 && onSegment(p2, q1, q2))
984
+ return true;
985
+ return false;
986
+ }
987
+ function onSegment(p, q, r) {
988
+ return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
989
+ }
990
+ function signNum(num) {
991
+ return num > 0 ? 1 : num < 0 ? -1 : 0;
992
+ }
993
+ function intersectsPolygon(a, b) {
994
+ let p = a;
995
+ do {
996
+ if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i
997
+ && intersects(p, p.next, a, b))
998
+ return true;
999
+ p = p.next;
1000
+ } while (p !== a);
1001
+ return false;
1002
+ }
1003
+ function locallyInside(a, b) {
1004
+ return area(a.prev, a, a.next) < 0
1005
+ ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0
1006
+ : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
1007
+ }
1008
+ function middleInside(a, b) {
1009
+ let p = a;
1010
+ let inside = false;
1011
+ const px = (a.x + b.x) / 2;
1012
+ const py = (a.y + b.y) / 2;
1013
+ do {
1014
+ if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y
1015
+ && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
1016
+ inside = !inside;
1017
+ p = p.next;
1018
+ } while (p !== a);
1019
+ return inside;
1020
+ }
1021
+ function splitPolygon(a, b) {
1022
+ const a2 = createNode(a.i, a.x, a.y);
1023
+ const b2 = createNode(b.i, b.x, b.y);
1024
+ const an = a.next;
1025
+ const bp = b.prev;
1026
+ a.next = b;
1027
+ b.prev = a;
1028
+ a2.next = an;
1029
+ an.prev = a2;
1030
+ b2.next = a2;
1031
+ a2.prev = b2;
1032
+ bp.next = b2;
1033
+ b2.prev = bp;
1034
+ return b2;
1035
+ }
1036
+ function insertNode(i, x, y, last) {
1037
+ const p = createNode(i, x, y);
1038
+ if (!last) {
1039
+ p.prev = p;
1040
+ p.next = p;
1041
+ }
1042
+ else {
1043
+ p.next = last.next;
1044
+ p.prev = last;
1045
+ last.next.prev = p;
1046
+ last.next = p;
1047
+ }
1048
+ return p;
1049
+ }
1050
+ function removeNode(p) {
1051
+ p.next.prev = p.prev;
1052
+ p.prev.next = p.next;
1053
+ if (p.prevZ)
1054
+ p.prevZ.nextZ = p.nextZ;
1055
+ if (p.nextZ)
1056
+ p.nextZ.prevZ = p.prevZ;
1057
+ }
1058
+ function signedArea(data, start, end, dim) {
1059
+ let sum = 0;
1060
+ for (let i = start, j = end - dim; i < end; i += dim) {
1061
+ sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
1062
+ j = i;
1063
+ }
1064
+ return sum;
1065
+ }
1066
+ //# sourceMappingURL=Support.js.map