@forgeax/engine-geometry 0.1.7 → 0.1.20

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.mjs CHANGED
@@ -1936,6 +1936,1912 @@ function create2dRingGeometry(shape, thickness, resolutionOverride) {
1936
1936
  return invalid(`ring thickness=${thickness} exceeds shape extent=${extent}`);
1937
1937
  return ok(ring(outer, scaleAround(outer, factor)));
1938
1938
  }
1939
+ var WELD_EPSILON = 1e-4;
1940
+ var DEFAULT_THRESHOLD_DEGREES = 1;
1941
+ function parseFailure(field, value, reason) {
1942
+ return new AssetError({
1943
+ code: "asset-parse-failed",
1944
+ expected: `a valid triangle-list MeshAsset: ${reason}`,
1945
+ hint: ASSET_ERROR_HINTS["asset-parse-failed"],
1946
+ detail: { field, value, reason }
1947
+ });
1948
+ }
1949
+ function f32Bits(value) {
1950
+ const buffer = new ArrayBuffer(4);
1951
+ new Float32Array(buffer)[0] = value;
1952
+ return new Uint32Array(buffer)[0];
1953
+ }
1954
+ function normalizedValue(value) {
1955
+ return value === 0 ? 0 : value;
1956
+ }
1957
+ function exactKey(value) {
1958
+ return value.map((component) => f32Bits(normalizedValue(component)).toString(16).padStart(8, "0")).join(":");
1959
+ }
1960
+ function weldComponent(value) {
1961
+ const scaled = normalizedValue(value) / WELD_EPSILON;
1962
+ return String(Math.round(scaled));
1963
+ }
1964
+ function weldKey(value) {
1965
+ return value.map(weldComponent).join(":");
1966
+ }
1967
+ function endpoint(position) {
1968
+ const value = [
1969
+ normalizedValue(position[0]),
1970
+ normalizedValue(position[1]),
1971
+ normalizedValue(position[2])
1972
+ ];
1973
+ return { value, exactKey: exactKey(value), weldKey: weldKey(value) };
1974
+ }
1975
+ function compareText(left, right) {
1976
+ return left < right ? -1 : left > right ? 1 : 0;
1977
+ }
1978
+ function compareEndpoint(left, right) {
1979
+ return compareText(left.exactKey, right.exactKey);
1980
+ }
1981
+ function compareWireEdge(left, right) {
1982
+ return compareEndpoint(left.a, right.a) || compareEndpoint(left.b, right.b);
1983
+ }
1984
+ function compareSurfaceEdge(left, right) {
1985
+ return compareText(left.aWeldKey, right.aWeldKey) || compareText(left.bWeldKey, right.bWeldKey);
1986
+ }
1987
+ function readPosition(raw) {
1988
+ return raw instanceof Float32Array ? raw : new Float32Array(raw);
1989
+ }
1990
+ function validatePosition(source) {
1991
+ if (source === null || typeof source !== "object" || source.kind !== "mesh") {
1992
+ return err(parseFailure("kind", source?.kind, "kind must be mesh"));
1993
+ }
1994
+ const attributes = source.attributes;
1995
+ const raw = attributes?.position;
1996
+ if (raw === void 0) {
1997
+ return err(parseFailure("attributes.position", void 0, "position is required"));
1998
+ }
1999
+ if (raw instanceof ArrayBuffer) {
2000
+ if (raw.byteLength % 4 !== 0) {
2001
+ return err(
2002
+ parseFailure(
2003
+ "attributes.position",
2004
+ raw.byteLength,
2005
+ "ArrayBuffer byte length must align to f32"
2006
+ )
2007
+ );
2008
+ }
2009
+ } else if (!(raw instanceof Float32Array)) {
2010
+ return err(
2011
+ parseFailure(
2012
+ "attributes.position",
2013
+ raw === null ? null : typeof raw,
2014
+ "position storage must be Float32Array or ArrayBuffer"
2015
+ )
2016
+ );
2017
+ }
2018
+ const position = readPosition(raw);
2019
+ if (position.length % 3 !== 0) {
2020
+ return err(
2021
+ parseFailure(
2022
+ "attributes.position",
2023
+ position.length,
2024
+ "position length must be divisible by 3"
2025
+ )
2026
+ );
2027
+ }
2028
+ for (let index = 0; index < position.length; index += 1) {
2029
+ const value = position[index];
2030
+ if (!Number.isFinite(value)) {
2031
+ return err(parseFailure("attributes.position", value, `position[${index}] must be finite`));
2032
+ }
2033
+ }
2034
+ return ok(position);
2035
+ }
2036
+ function validateThreshold(threshold) {
2037
+ if (!Number.isFinite(threshold) || threshold < 0 || threshold > 180) {
2038
+ return err(
2039
+ parseFailure("thresholdAngleDegrees", threshold, "threshold must be finite and in [0, 180]")
2040
+ );
2041
+ }
2042
+ return ok(threshold);
2043
+ }
2044
+ function validateSubmeshShape(source, positionCount) {
2045
+ if (!Array.isArray(source.submeshes) || source.submeshes.length === 0) {
2046
+ return err(parseFailure("submeshes", source.submeshes, "at least one submesh is required"));
2047
+ }
2048
+ const indexed = source.indices !== void 0;
2049
+ if (!indexed && source.submeshes.length !== 1) {
2050
+ return err(
2051
+ parseFailure("submeshes", source.submeshes.length, "non-indexed meshes require one submesh")
2052
+ );
2053
+ }
2054
+ if (!indexed && positionCount % 3 !== 0) {
2055
+ return err(
2056
+ parseFailure(
2057
+ "attributes.position",
2058
+ positionCount,
2059
+ "non-indexed positions require triangle cardinality"
2060
+ )
2061
+ );
2062
+ }
2063
+ for (let index = 0; index < source.submeshes.length; index += 1) {
2064
+ const submesh = source.submeshes[index];
2065
+ if (submesh === void 0 || submesh === null || submesh.topology !== "triangle-list") {
2066
+ return err(
2067
+ parseFailure(
2068
+ `submeshes[${index}].topology`,
2069
+ submesh?.topology,
2070
+ "topology must be triangle-list"
2071
+ )
2072
+ );
2073
+ }
2074
+ if (!Number.isInteger(submesh.indexOffset) || submesh.indexOffset < 0) {
2075
+ return err(
2076
+ parseFailure(
2077
+ `submeshes[${index}].indexOffset`,
2078
+ submesh.indexOffset,
2079
+ "index offset must be a non-negative integer"
2080
+ )
2081
+ );
2082
+ }
2083
+ if (!Number.isInteger(submesh.indexCount) || submesh.indexCount < 0) {
2084
+ return err(
2085
+ parseFailure(
2086
+ `submeshes[${index}].indexCount`,
2087
+ submesh.indexCount,
2088
+ "index count must be a non-negative integer"
2089
+ )
2090
+ );
2091
+ }
2092
+ if (!Number.isInteger(submesh.vertexCount) || submesh.vertexCount < 0 || submesh.vertexCount > positionCount) {
2093
+ return err(
2094
+ parseFailure(
2095
+ `submeshes[${index}].vertexCount`,
2096
+ submesh.vertexCount,
2097
+ "vertex count must be an integer within position count"
2098
+ )
2099
+ );
2100
+ }
2101
+ if (submesh.indexCount % 3 !== 0) {
2102
+ return err(
2103
+ parseFailure(
2104
+ `submeshes[${index}].indexCount`,
2105
+ submesh.indexCount,
2106
+ "index count must be divisible by 3"
2107
+ )
2108
+ );
2109
+ }
2110
+ if (!indexed && submesh.indexOffset !== 0) {
2111
+ return err(
2112
+ parseFailure(
2113
+ `submeshes[${index}].indexOffset`,
2114
+ submesh.indexOffset,
2115
+ "non-indexed submesh index offset must be zero"
2116
+ )
2117
+ );
2118
+ }
2119
+ if (!indexed && submesh.indexCount !== 0) {
2120
+ return err(
2121
+ parseFailure(
2122
+ `submeshes[${index}].indexCount`,
2123
+ submesh.indexCount,
2124
+ "non-indexed submesh index count must be zero"
2125
+ )
2126
+ );
2127
+ }
2128
+ if (!indexed && submesh.vertexCount !== positionCount) {
2129
+ return err(
2130
+ parseFailure(
2131
+ `submeshes[${index}].vertexCount`,
2132
+ submesh.vertexCount,
2133
+ "non-indexed submesh must span all positions"
2134
+ )
2135
+ );
2136
+ }
2137
+ }
2138
+ return ok(void 0);
2139
+ }
2140
+ function validateIndices(source, positionCount) {
2141
+ const indices = source.indices;
2142
+ if (indices === void 0) return ok(void 0);
2143
+ if (!(indices instanceof Uint16Array) && !(indices instanceof Uint32Array)) {
2144
+ return err(
2145
+ parseFailure("indices", indices, "indices storage must be Uint16Array or Uint32Array")
2146
+ );
2147
+ }
2148
+ for (let index = 0; index < source.submeshes.length; index += 1) {
2149
+ const submesh = source.submeshes[index];
2150
+ if (submesh === void 0) continue;
2151
+ if (submesh.indexOffset + submesh.indexCount > indices.length) {
2152
+ return err(
2153
+ parseFailure(`submeshes[${index}]`, submesh, "submesh index range exceeds indices length")
2154
+ );
2155
+ }
2156
+ for (let offset = submesh.indexOffset; offset < submesh.indexOffset + submesh.indexCount; offset += 1) {
2157
+ const value = indices[offset];
2158
+ if (!Number.isInteger(value) || value < 0 || value >= positionCount) {
2159
+ return err(
2160
+ parseFailure(`indices[${offset}]`, value, "index must address a position vertex")
2161
+ );
2162
+ }
2163
+ }
2164
+ }
2165
+ return ok(void 0);
2166
+ }
2167
+ function cross(a, b) {
2168
+ return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
2169
+ }
2170
+ function subtract(a, b) {
2171
+ return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
2172
+ }
2173
+ function triangleNormal(a, b, c) {
2174
+ const normal = cross(subtract(b, a), subtract(c, a));
2175
+ const length = Math.hypot(normal[0], normal[1], normal[2]);
2176
+ if (!Number.isFinite(length) || length === 0) return void 0;
2177
+ return [normal[0] / length, normal[1] / length, normal[2] / length];
2178
+ }
2179
+ function positionAt(position, index) {
2180
+ const base = index * 3;
2181
+ return [position[base], position[base + 1], position[base + 2]];
2182
+ }
2183
+ function makeTriangle(position, indices) {
2184
+ const a = endpoint(positionAt(position, indices[0]));
2185
+ const b = endpoint(positionAt(position, indices[1]));
2186
+ const c = endpoint(positionAt(position, indices[2]));
2187
+ const normal = triangleNormal(a.value, b.value, c.value);
2188
+ return normal === void 0 ? void 0 : { a, b, c, normal };
2189
+ }
2190
+ function collectTriangles(source, position) {
2191
+ const triangles = [];
2192
+ for (const submesh of source.submeshes) {
2193
+ if (source.indices === void 0) {
2194
+ for (let offset = 0; offset < submesh.vertexCount; offset += 3) {
2195
+ const triangle = makeTriangle(position, [offset, offset + 1, offset + 2]);
2196
+ if (triangle !== void 0) triangles.push(triangle);
2197
+ }
2198
+ continue;
2199
+ }
2200
+ for (let offset = submesh.indexOffset; offset < submesh.indexOffset + submesh.indexCount; offset += 3) {
2201
+ const a = source.indices[offset];
2202
+ const b = source.indices[offset + 1];
2203
+ const c = source.indices[offset + 2];
2204
+ const triangle = makeTriangle(position, [a, b, c]);
2205
+ if (triangle !== void 0) triangles.push(triangle);
2206
+ }
2207
+ }
2208
+ return triangles;
2209
+ }
2210
+ function prepare(source, threshold) {
2211
+ const positionResult = validatePosition(source);
2212
+ if (!positionResult.ok) return positionResult;
2213
+ if (threshold !== void 0) {
2214
+ const thresholdResult = validateThreshold(threshold);
2215
+ if (!thresholdResult.ok) return thresholdResult;
2216
+ }
2217
+ const submeshResult = validateSubmeshShape(source, positionResult.value.length / 3);
2218
+ if (!submeshResult.ok) return submeshResult;
2219
+ const indexResult = validateIndices(source, positionResult.value.length / 3);
2220
+ if (!indexResult.ok) return indexResult;
2221
+ return ok({ triangles: collectTriangles(source, positionResult.value) });
2222
+ }
2223
+ function addWireEdge(edges, left, right) {
2224
+ if (left.exactKey === right.exactKey) return;
2225
+ const [a, b] = compareEndpoint(left, right) < 0 ? [left, right] : [right, left];
2226
+ const key = `${a.exactKey}|${b.exactKey}`;
2227
+ if (!edges.has(key)) edges.set(key, { a, b });
2228
+ }
2229
+ function collectWireEdges(triangles) {
2230
+ const edges = /* @__PURE__ */ new Map();
2231
+ for (const triangle of triangles) {
2232
+ addWireEdge(edges, triangle.a, triangle.b);
2233
+ addWireEdge(edges, triangle.b, triangle.c);
2234
+ addWireEdge(edges, triangle.c, triangle.a);
2235
+ }
2236
+ return Array.from(edges.values()).sort(compareWireEdge);
2237
+ }
2238
+ function updateRepresentative(current, candidate) {
2239
+ return compareEndpoint(candidate, current) < 0 ? candidate : current;
2240
+ }
2241
+ function addSurfaceEdge(edges, left, right, normal) {
2242
+ if (left.weldKey === right.weldKey) return;
2243
+ const leftFirst = compareText(left.weldKey, right.weldKey) < 0;
2244
+ const a = leftFirst ? left : right;
2245
+ const b = leftFirst ? right : left;
2246
+ const key = `${a.weldKey}|${b.weldKey}`;
2247
+ const current = edges.get(key);
2248
+ if (current === void 0) {
2249
+ edges.set(key, {
2250
+ aWeldKey: a.weldKey,
2251
+ bWeldKey: b.weldKey,
2252
+ a,
2253
+ b,
2254
+ normals: [normal]
2255
+ });
2256
+ return;
2257
+ }
2258
+ current.a = updateRepresentative(current.a, a);
2259
+ current.b = updateRepresentative(current.b, b);
2260
+ current.normals.push(normal);
2261
+ }
2262
+ function collectSurfaceEdges(triangles) {
2263
+ const edges = /* @__PURE__ */ new Map();
2264
+ for (const triangle of triangles) {
2265
+ addSurfaceEdge(edges, triangle.a, triangle.b, triangle.normal);
2266
+ addSurfaceEdge(edges, triangle.b, triangle.c, triangle.normal);
2267
+ addSurfaceEdge(edges, triangle.c, triangle.a, triangle.normal);
2268
+ }
2269
+ return Array.from(edges.values()).sort(compareSurfaceEdge);
2270
+ }
2271
+ function keepSurfaceEdge(edge, thresholdDegrees) {
2272
+ if (edge.normals.length !== 2) return true;
2273
+ const first = edge.normals[0];
2274
+ const second = edge.normals[1];
2275
+ if (first === void 0 || second === void 0) return true;
2276
+ const dot = Math.min(
2277
+ 1,
2278
+ Math.max(-1, first[0] * second[0] + first[1] * second[1] + first[2] * second[2])
2279
+ );
2280
+ return dot <= Math.cos(thresholdDegrees * Math.PI / 180);
2281
+ }
2282
+ function lineMesh(edges) {
2283
+ const positions = new Float32Array(edges.length * 6);
2284
+ for (let edgeIndex = 0; edgeIndex < edges.length; edgeIndex += 1) {
2285
+ const edge = edges[edgeIndex];
2286
+ positions.set(edge.a.value, edgeIndex * 6);
2287
+ positions.set(edge.b.value, edgeIndex * 6 + 3);
2288
+ }
2289
+ const vertexCount = positions.length / 3;
2290
+ const attributes = {
2291
+ position: positions,
2292
+ normal: new Float32Array(vertexCount * 3),
2293
+ uv: new Float32Array(vertexCount * 2),
2294
+ tangent: new Float32Array(vertexCount * 4)
2295
+ };
2296
+ const packed = packInterleavedVertexAttributes(attributes, vertexCount);
2297
+ if (!packed.ok) return err(packed.error);
2298
+ return ok({
2299
+ kind: "mesh",
2300
+ vertices: packed.value.vertices,
2301
+ attributes,
2302
+ submeshes: [
2303
+ {
2304
+ indexOffset: 0,
2305
+ indexCount: 0,
2306
+ vertexCount,
2307
+ topology: "line-list",
2308
+ materialSlot: 0
2309
+ }
2310
+ ],
2311
+ materialSlots: [{ slotName: "Default" }],
2312
+ aabb: box3.fromPositions(box3.create(), positions)
2313
+ });
2314
+ }
2315
+ function createWireframeGeometry(source) {
2316
+ const prepared = prepare(source);
2317
+ if (!prepared.ok) return prepared;
2318
+ return lineMesh(collectWireEdges(prepared.value.triangles));
2319
+ }
2320
+ function createEdgesGeometry(source, thresholdAngleDegrees = DEFAULT_THRESHOLD_DEGREES) {
2321
+ const prepared = prepare(source, thresholdAngleDegrees);
2322
+ if (!prepared.ok) return prepared;
2323
+ const edges = collectSurfaceEdges(prepared.value.triangles).filter(
2324
+ (edge) => keepSurfaceEdge(edge, thresholdAngleDegrees)
2325
+ );
2326
+ return lineMesh(edges.map(({ a, b }) => ({ a, b })));
2327
+ }
2328
+ var PATCHES = new Uint16Array([
2329
+ 0,
2330
+ 1,
2331
+ 2,
2332
+ 3,
2333
+ 4,
2334
+ 5,
2335
+ 6,
2336
+ 7,
2337
+ 8,
2338
+ 9,
2339
+ 10,
2340
+ 11,
2341
+ 12,
2342
+ 13,
2343
+ 14,
2344
+ 15,
2345
+ 3,
2346
+ 16,
2347
+ 17,
2348
+ 18,
2349
+ 7,
2350
+ 19,
2351
+ 20,
2352
+ 21,
2353
+ 11,
2354
+ 22,
2355
+ 23,
2356
+ 24,
2357
+ 15,
2358
+ 25,
2359
+ 26,
2360
+ 27,
2361
+ 18,
2362
+ 28,
2363
+ 29,
2364
+ 30,
2365
+ 21,
2366
+ 31,
2367
+ 32,
2368
+ 33,
2369
+ 24,
2370
+ 34,
2371
+ 35,
2372
+ 36,
2373
+ 27,
2374
+ 37,
2375
+ 38,
2376
+ 39,
2377
+ 30,
2378
+ 40,
2379
+ 41,
2380
+ 0,
2381
+ 33,
2382
+ 42,
2383
+ 43,
2384
+ 4,
2385
+ 36,
2386
+ 44,
2387
+ 45,
2388
+ 8,
2389
+ 39,
2390
+ 46,
2391
+ 47,
2392
+ 12,
2393
+ 12,
2394
+ 13,
2395
+ 14,
2396
+ 15,
2397
+ 48,
2398
+ 49,
2399
+ 50,
2400
+ 51,
2401
+ 52,
2402
+ 53,
2403
+ 54,
2404
+ 55,
2405
+ 56,
2406
+ 57,
2407
+ 58,
2408
+ 59,
2409
+ 15,
2410
+ 25,
2411
+ 26,
2412
+ 27,
2413
+ 51,
2414
+ 60,
2415
+ 61,
2416
+ 62,
2417
+ 55,
2418
+ 63,
2419
+ 64,
2420
+ 65,
2421
+ 59,
2422
+ 66,
2423
+ 67,
2424
+ 68,
2425
+ 27,
2426
+ 37,
2427
+ 38,
2428
+ 39,
2429
+ 62,
2430
+ 69,
2431
+ 70,
2432
+ 71,
2433
+ 65,
2434
+ 72,
2435
+ 73,
2436
+ 74,
2437
+ 68,
2438
+ 75,
2439
+ 76,
2440
+ 77,
2441
+ 39,
2442
+ 46,
2443
+ 47,
2444
+ 12,
2445
+ 71,
2446
+ 78,
2447
+ 79,
2448
+ 48,
2449
+ 74,
2450
+ 80,
2451
+ 81,
2452
+ 52,
2453
+ 77,
2454
+ 82,
2455
+ 83,
2456
+ 56,
2457
+ 56,
2458
+ 57,
2459
+ 58,
2460
+ 59,
2461
+ 84,
2462
+ 85,
2463
+ 86,
2464
+ 87,
2465
+ 88,
2466
+ 89,
2467
+ 90,
2468
+ 91,
2469
+ 92,
2470
+ 93,
2471
+ 94,
2472
+ 95,
2473
+ 59,
2474
+ 66,
2475
+ 67,
2476
+ 68,
2477
+ 87,
2478
+ 96,
2479
+ 97,
2480
+ 98,
2481
+ 91,
2482
+ 99,
2483
+ 100,
2484
+ 101,
2485
+ 95,
2486
+ 102,
2487
+ 103,
2488
+ 104,
2489
+ 68,
2490
+ 75,
2491
+ 76,
2492
+ 77,
2493
+ 98,
2494
+ 105,
2495
+ 106,
2496
+ 107,
2497
+ 101,
2498
+ 108,
2499
+ 109,
2500
+ 110,
2501
+ 104,
2502
+ 111,
2503
+ 112,
2504
+ 113,
2505
+ 77,
2506
+ 82,
2507
+ 83,
2508
+ 56,
2509
+ 107,
2510
+ 114,
2511
+ 115,
2512
+ 84,
2513
+ 110,
2514
+ 116,
2515
+ 117,
2516
+ 88,
2517
+ 113,
2518
+ 118,
2519
+ 119,
2520
+ 92,
2521
+ 120,
2522
+ 121,
2523
+ 122,
2524
+ 123,
2525
+ 124,
2526
+ 125,
2527
+ 126,
2528
+ 127,
2529
+ 128,
2530
+ 129,
2531
+ 130,
2532
+ 131,
2533
+ 132,
2534
+ 133,
2535
+ 134,
2536
+ 135,
2537
+ 123,
2538
+ 136,
2539
+ 137,
2540
+ 120,
2541
+ 127,
2542
+ 138,
2543
+ 139,
2544
+ 124,
2545
+ 131,
2546
+ 140,
2547
+ 141,
2548
+ 128,
2549
+ 135,
2550
+ 142,
2551
+ 143,
2552
+ 132,
2553
+ 132,
2554
+ 133,
2555
+ 134,
2556
+ 135,
2557
+ 144,
2558
+ 145,
2559
+ 146,
2560
+ 147,
2561
+ 148,
2562
+ 149,
2563
+ 150,
2564
+ 151,
2565
+ 68,
2566
+ 152,
2567
+ 153,
2568
+ 154,
2569
+ 135,
2570
+ 142,
2571
+ 143,
2572
+ 132,
2573
+ 147,
2574
+ 155,
2575
+ 156,
2576
+ 144,
2577
+ 151,
2578
+ 157,
2579
+ 158,
2580
+ 148,
2581
+ 154,
2582
+ 159,
2583
+ 160,
2584
+ 68,
2585
+ 161,
2586
+ 162,
2587
+ 163,
2588
+ 164,
2589
+ 165,
2590
+ 166,
2591
+ 167,
2592
+ 168,
2593
+ 169,
2594
+ 170,
2595
+ 171,
2596
+ 172,
2597
+ 173,
2598
+ 174,
2599
+ 175,
2600
+ 176,
2601
+ 164,
2602
+ 177,
2603
+ 178,
2604
+ 161,
2605
+ 168,
2606
+ 179,
2607
+ 180,
2608
+ 165,
2609
+ 172,
2610
+ 181,
2611
+ 182,
2612
+ 169,
2613
+ 176,
2614
+ 183,
2615
+ 184,
2616
+ 173,
2617
+ 173,
2618
+ 174,
2619
+ 175,
2620
+ 176,
2621
+ 185,
2622
+ 186,
2623
+ 187,
2624
+ 188,
2625
+ 189,
2626
+ 190,
2627
+ 191,
2628
+ 192,
2629
+ 193,
2630
+ 194,
2631
+ 195,
2632
+ 196,
2633
+ 176,
2634
+ 183,
2635
+ 184,
2636
+ 173,
2637
+ 188,
2638
+ 197,
2639
+ 198,
2640
+ 185,
2641
+ 192,
2642
+ 199,
2643
+ 200,
2644
+ 189,
2645
+ 196,
2646
+ 201,
2647
+ 202,
2648
+ 193,
2649
+ 203,
2650
+ 203,
2651
+ 203,
2652
+ 203,
2653
+ 204,
2654
+ 205,
2655
+ 206,
2656
+ 207,
2657
+ 208,
2658
+ 208,
2659
+ 208,
2660
+ 208,
2661
+ 209,
2662
+ 210,
2663
+ 211,
2664
+ 212,
2665
+ 203,
2666
+ 203,
2667
+ 203,
2668
+ 203,
2669
+ 207,
2670
+ 213,
2671
+ 214,
2672
+ 215,
2673
+ 208,
2674
+ 208,
2675
+ 208,
2676
+ 208,
2677
+ 212,
2678
+ 216,
2679
+ 217,
2680
+ 218,
2681
+ 203,
2682
+ 203,
2683
+ 203,
2684
+ 203,
2685
+ 215,
2686
+ 219,
2687
+ 220,
2688
+ 221,
2689
+ 208,
2690
+ 208,
2691
+ 208,
2692
+ 208,
2693
+ 218,
2694
+ 222,
2695
+ 223,
2696
+ 224,
2697
+ 203,
2698
+ 203,
2699
+ 203,
2700
+ 203,
2701
+ 221,
2702
+ 225,
2703
+ 226,
2704
+ 204,
2705
+ 208,
2706
+ 208,
2707
+ 208,
2708
+ 208,
2709
+ 224,
2710
+ 227,
2711
+ 228,
2712
+ 209,
2713
+ 209,
2714
+ 210,
2715
+ 211,
2716
+ 212,
2717
+ 229,
2718
+ 230,
2719
+ 231,
2720
+ 232,
2721
+ 233,
2722
+ 234,
2723
+ 235,
2724
+ 236,
2725
+ 237,
2726
+ 238,
2727
+ 239,
2728
+ 240,
2729
+ 212,
2730
+ 216,
2731
+ 217,
2732
+ 218,
2733
+ 232,
2734
+ 241,
2735
+ 242,
2736
+ 243,
2737
+ 236,
2738
+ 244,
2739
+ 245,
2740
+ 246,
2741
+ 240,
2742
+ 247,
2743
+ 248,
2744
+ 249,
2745
+ 218,
2746
+ 222,
2747
+ 223,
2748
+ 224,
2749
+ 243,
2750
+ 250,
2751
+ 251,
2752
+ 252,
2753
+ 246,
2754
+ 253,
2755
+ 254,
2756
+ 255,
2757
+ 249,
2758
+ 256,
2759
+ 257,
2760
+ 258,
2761
+ 224,
2762
+ 227,
2763
+ 228,
2764
+ 209,
2765
+ 252,
2766
+ 259,
2767
+ 260,
2768
+ 229,
2769
+ 255,
2770
+ 261,
2771
+ 262,
2772
+ 233,
2773
+ 258,
2774
+ 263,
2775
+ 264,
2776
+ 237,
2777
+ 265,
2778
+ 265,
2779
+ 265,
2780
+ 265,
2781
+ 266,
2782
+ 267,
2783
+ 268,
2784
+ 269,
2785
+ 270,
2786
+ 271,
2787
+ 272,
2788
+ 273,
2789
+ 92,
2790
+ 119,
2791
+ 118,
2792
+ 113,
2793
+ 265,
2794
+ 265,
2795
+ 265,
2796
+ 265,
2797
+ 269,
2798
+ 274,
2799
+ 275,
2800
+ 276,
2801
+ 273,
2802
+ 277,
2803
+ 278,
2804
+ 279,
2805
+ 113,
2806
+ 112,
2807
+ 111,
2808
+ 104,
2809
+ 265,
2810
+ 265,
2811
+ 265,
2812
+ 265,
2813
+ 276,
2814
+ 280,
2815
+ 281,
2816
+ 282,
2817
+ 279,
2818
+ 283,
2819
+ 284,
2820
+ 285,
2821
+ 104,
2822
+ 103,
2823
+ 102,
2824
+ 95,
2825
+ 265,
2826
+ 265,
2827
+ 265,
2828
+ 265,
2829
+ 282,
2830
+ 286,
2831
+ 287,
2832
+ 266,
2833
+ 285,
2834
+ 288,
2835
+ 289,
2836
+ 270,
2837
+ 95,
2838
+ 94,
2839
+ 93,
2840
+ 92
2841
+ ]);
2842
+ var CONTROL_POINTS = new Float32Array([
2843
+ 1.4,
2844
+ 0,
2845
+ 2.4,
2846
+ 1.4,
2847
+ -0.784,
2848
+ 2.4,
2849
+ 0.784,
2850
+ -1.4,
2851
+ 2.4,
2852
+ 0,
2853
+ -1.4,
2854
+ 2.4,
2855
+ 1.3375,
2856
+ 0,
2857
+ 2.53125,
2858
+ 1.3375,
2859
+ -0.749,
2860
+ 2.53125,
2861
+ 0.749,
2862
+ -1.3375,
2863
+ 2.53125,
2864
+ 0,
2865
+ -1.3375,
2866
+ 2.53125,
2867
+ 1.4375,
2868
+ 0,
2869
+ 2.53125,
2870
+ 1.4375,
2871
+ -0.805,
2872
+ 2.53125,
2873
+ 0.805,
2874
+ -1.4375,
2875
+ 2.53125,
2876
+ 0,
2877
+ -1.4375,
2878
+ 2.53125,
2879
+ 1.5,
2880
+ 0,
2881
+ 2.4,
2882
+ 1.5,
2883
+ -0.84,
2884
+ 2.4,
2885
+ 0.84,
2886
+ -1.5,
2887
+ 2.4,
2888
+ 0,
2889
+ -1.5,
2890
+ 2.4,
2891
+ -0.784,
2892
+ -1.4,
2893
+ 2.4,
2894
+ -1.4,
2895
+ -0.784,
2896
+ 2.4,
2897
+ -1.4,
2898
+ 0,
2899
+ 2.4,
2900
+ -0.749,
2901
+ -1.3375,
2902
+ 2.53125,
2903
+ -1.3375,
2904
+ -0.749,
2905
+ 2.53125,
2906
+ -1.3375,
2907
+ 0,
2908
+ 2.53125,
2909
+ -0.805,
2910
+ -1.4375,
2911
+ 2.53125,
2912
+ -1.4375,
2913
+ -0.805,
2914
+ 2.53125,
2915
+ -1.4375,
2916
+ 0,
2917
+ 2.53125,
2918
+ -0.84,
2919
+ -1.5,
2920
+ 2.4,
2921
+ -1.5,
2922
+ -0.84,
2923
+ 2.4,
2924
+ -1.5,
2925
+ 0,
2926
+ 2.4,
2927
+ -1.4,
2928
+ 0.784,
2929
+ 2.4,
2930
+ -0.784,
2931
+ 1.4,
2932
+ 2.4,
2933
+ 0,
2934
+ 1.4,
2935
+ 2.4,
2936
+ -1.3375,
2937
+ 0.749,
2938
+ 2.53125,
2939
+ -0.749,
2940
+ 1.3375,
2941
+ 2.53125,
2942
+ 0,
2943
+ 1.3375,
2944
+ 2.53125,
2945
+ -1.4375,
2946
+ 0.805,
2947
+ 2.53125,
2948
+ -0.805,
2949
+ 1.4375,
2950
+ 2.53125,
2951
+ 0,
2952
+ 1.4375,
2953
+ 2.53125,
2954
+ -1.5,
2955
+ 0.84,
2956
+ 2.4,
2957
+ -0.84,
2958
+ 1.5,
2959
+ 2.4,
2960
+ 0,
2961
+ 1.5,
2962
+ 2.4,
2963
+ 0.784,
2964
+ 1.4,
2965
+ 2.4,
2966
+ 1.4,
2967
+ 0.784,
2968
+ 2.4,
2969
+ 0.749,
2970
+ 1.3375,
2971
+ 2.53125,
2972
+ 1.3375,
2973
+ 0.749,
2974
+ 2.53125,
2975
+ 0.805,
2976
+ 1.4375,
2977
+ 2.53125,
2978
+ 1.4375,
2979
+ 0.805,
2980
+ 2.53125,
2981
+ 0.84,
2982
+ 1.5,
2983
+ 2.4,
2984
+ 1.5,
2985
+ 0.84,
2986
+ 2.4,
2987
+ 1.75,
2988
+ 0,
2989
+ 1.875,
2990
+ 1.75,
2991
+ -0.98,
2992
+ 1.875,
2993
+ 0.98,
2994
+ -1.75,
2995
+ 1.875,
2996
+ 0,
2997
+ -1.75,
2998
+ 1.875,
2999
+ 2,
3000
+ 0,
3001
+ 1.35,
3002
+ 2,
3003
+ -1.12,
3004
+ 1.35,
3005
+ 1.12,
3006
+ -2,
3007
+ 1.35,
3008
+ 0,
3009
+ -2,
3010
+ 1.35,
3011
+ 2,
3012
+ 0,
3013
+ 0.9,
3014
+ 2,
3015
+ -1.12,
3016
+ 0.9,
3017
+ 1.12,
3018
+ -2,
3019
+ 0.9,
3020
+ 0,
3021
+ -2,
3022
+ 0.9,
3023
+ -0.98,
3024
+ -1.75,
3025
+ 1.875,
3026
+ -1.75,
3027
+ -0.98,
3028
+ 1.875,
3029
+ -1.75,
3030
+ 0,
3031
+ 1.875,
3032
+ -1.12,
3033
+ -2,
3034
+ 1.35,
3035
+ -2,
3036
+ -1.12,
3037
+ 1.35,
3038
+ -2,
3039
+ 0,
3040
+ 1.35,
3041
+ -1.12,
3042
+ -2,
3043
+ 0.9,
3044
+ -2,
3045
+ -1.12,
3046
+ 0.9,
3047
+ -2,
3048
+ 0,
3049
+ 0.9,
3050
+ -1.75,
3051
+ 0.98,
3052
+ 1.875,
3053
+ -0.98,
3054
+ 1.75,
3055
+ 1.875,
3056
+ 0,
3057
+ 1.75,
3058
+ 1.875,
3059
+ -2,
3060
+ 1.12,
3061
+ 1.35,
3062
+ -1.12,
3063
+ 2,
3064
+ 1.35,
3065
+ 0,
3066
+ 2,
3067
+ 1.35,
3068
+ -2,
3069
+ 1.12,
3070
+ 0.9,
3071
+ -1.12,
3072
+ 2,
3073
+ 0.9,
3074
+ 0,
3075
+ 2,
3076
+ 0.9,
3077
+ 0.98,
3078
+ 1.75,
3079
+ 1.875,
3080
+ 1.75,
3081
+ 0.98,
3082
+ 1.875,
3083
+ 1.12,
3084
+ 2,
3085
+ 1.35,
3086
+ 2,
3087
+ 1.12,
3088
+ 1.35,
3089
+ 1.12,
3090
+ 2,
3091
+ 0.9,
3092
+ 2,
3093
+ 1.12,
3094
+ 0.9,
3095
+ 2,
3096
+ 0,
3097
+ 0.45,
3098
+ 2,
3099
+ -1.12,
3100
+ 0.45,
3101
+ 1.12,
3102
+ -2,
3103
+ 0.45,
3104
+ 0,
3105
+ -2,
3106
+ 0.45,
3107
+ 1.5,
3108
+ 0,
3109
+ 0.225,
3110
+ 1.5,
3111
+ -0.84,
3112
+ 0.225,
3113
+ 0.84,
3114
+ -1.5,
3115
+ 0.225,
3116
+ 0,
3117
+ -1.5,
3118
+ 0.225,
3119
+ 1.5,
3120
+ 0,
3121
+ 0.15,
3122
+ 1.5,
3123
+ -0.84,
3124
+ 0.15,
3125
+ 0.84,
3126
+ -1.5,
3127
+ 0.15,
3128
+ 0,
3129
+ -1.5,
3130
+ 0.15,
3131
+ -1.12,
3132
+ -2,
3133
+ 0.45,
3134
+ -2,
3135
+ -1.12,
3136
+ 0.45,
3137
+ -2,
3138
+ 0,
3139
+ 0.45,
3140
+ -0.84,
3141
+ -1.5,
3142
+ 0.225,
3143
+ -1.5,
3144
+ -0.84,
3145
+ 0.225,
3146
+ -1.5,
3147
+ 0,
3148
+ 0.225,
3149
+ -0.84,
3150
+ -1.5,
3151
+ 0.15,
3152
+ -1.5,
3153
+ -0.84,
3154
+ 0.15,
3155
+ -1.5,
3156
+ 0,
3157
+ 0.15,
3158
+ -2,
3159
+ 1.12,
3160
+ 0.45,
3161
+ -1.12,
3162
+ 2,
3163
+ 0.45,
3164
+ 0,
3165
+ 2,
3166
+ 0.45,
3167
+ -1.5,
3168
+ 0.84,
3169
+ 0.225,
3170
+ -0.84,
3171
+ 1.5,
3172
+ 0.225,
3173
+ 0,
3174
+ 1.5,
3175
+ 0.225,
3176
+ -1.5,
3177
+ 0.84,
3178
+ 0.15,
3179
+ -0.84,
3180
+ 1.5,
3181
+ 0.15,
3182
+ 0,
3183
+ 1.5,
3184
+ 0.15,
3185
+ 1.12,
3186
+ 2,
3187
+ 0.45,
3188
+ 2,
3189
+ 1.12,
3190
+ 0.45,
3191
+ 0.84,
3192
+ 1.5,
3193
+ 0.225,
3194
+ 1.5,
3195
+ 0.84,
3196
+ 0.225,
3197
+ 0.84,
3198
+ 1.5,
3199
+ 0.15,
3200
+ 1.5,
3201
+ 0.84,
3202
+ 0.15,
3203
+ -1.6,
3204
+ 0,
3205
+ 2.025,
3206
+ -1.6,
3207
+ -0.3,
3208
+ 2.025,
3209
+ -1.5,
3210
+ -0.3,
3211
+ 2.25,
3212
+ -1.5,
3213
+ 0,
3214
+ 2.25,
3215
+ -2.3,
3216
+ 0,
3217
+ 2.025,
3218
+ -2.3,
3219
+ -0.3,
3220
+ 2.025,
3221
+ -2.5,
3222
+ -0.3,
3223
+ 2.25,
3224
+ -2.5,
3225
+ 0,
3226
+ 2.25,
3227
+ -2.7,
3228
+ 0,
3229
+ 2.025,
3230
+ -2.7,
3231
+ -0.3,
3232
+ 2.025,
3233
+ -3,
3234
+ -0.3,
3235
+ 2.25,
3236
+ -3,
3237
+ 0,
3238
+ 2.25,
3239
+ -2.7,
3240
+ 0,
3241
+ 1.8,
3242
+ -2.7,
3243
+ -0.3,
3244
+ 1.8,
3245
+ -3,
3246
+ -0.3,
3247
+ 1.8,
3248
+ -3,
3249
+ 0,
3250
+ 1.8,
3251
+ -1.5,
3252
+ 0.3,
3253
+ 2.25,
3254
+ -1.6,
3255
+ 0.3,
3256
+ 2.025,
3257
+ -2.5,
3258
+ 0.3,
3259
+ 2.25,
3260
+ -2.3,
3261
+ 0.3,
3262
+ 2.025,
3263
+ -3,
3264
+ 0.3,
3265
+ 2.25,
3266
+ -2.7,
3267
+ 0.3,
3268
+ 2.025,
3269
+ -3,
3270
+ 0.3,
3271
+ 1.8,
3272
+ -2.7,
3273
+ 0.3,
3274
+ 1.8,
3275
+ -2.7,
3276
+ 0,
3277
+ 1.575,
3278
+ -2.7,
3279
+ -0.3,
3280
+ 1.575,
3281
+ -3,
3282
+ -0.3,
3283
+ 1.35,
3284
+ -3,
3285
+ 0,
3286
+ 1.35,
3287
+ -2.5,
3288
+ 0,
3289
+ 1.125,
3290
+ -2.5,
3291
+ -0.3,
3292
+ 1.125,
3293
+ -2.65,
3294
+ -0.3,
3295
+ 0.9375,
3296
+ -2.65,
3297
+ 0,
3298
+ 0.9375,
3299
+ -2,
3300
+ -0.3,
3301
+ 0.9,
3302
+ -1.9,
3303
+ -0.3,
3304
+ 0.6,
3305
+ -1.9,
3306
+ 0,
3307
+ 0.6,
3308
+ -3,
3309
+ 0.3,
3310
+ 1.35,
3311
+ -2.7,
3312
+ 0.3,
3313
+ 1.575,
3314
+ -2.65,
3315
+ 0.3,
3316
+ 0.9375,
3317
+ -2.5,
3318
+ 0.3,
3319
+ 1.125,
3320
+ -1.9,
3321
+ 0.3,
3322
+ 0.6,
3323
+ -2,
3324
+ 0.3,
3325
+ 0.9,
3326
+ 1.7,
3327
+ 0,
3328
+ 1.425,
3329
+ 1.7,
3330
+ -0.66,
3331
+ 1.425,
3332
+ 1.7,
3333
+ -0.66,
3334
+ 0.6,
3335
+ 1.7,
3336
+ 0,
3337
+ 0.6,
3338
+ 2.6,
3339
+ 0,
3340
+ 1.425,
3341
+ 2.6,
3342
+ -0.66,
3343
+ 1.425,
3344
+ 3.1,
3345
+ -0.66,
3346
+ 0.825,
3347
+ 3.1,
3348
+ 0,
3349
+ 0.825,
3350
+ 2.3,
3351
+ 0,
3352
+ 2.1,
3353
+ 2.3,
3354
+ -0.25,
3355
+ 2.1,
3356
+ 2.4,
3357
+ -0.25,
3358
+ 2.025,
3359
+ 2.4,
3360
+ 0,
3361
+ 2.025,
3362
+ 2.7,
3363
+ 0,
3364
+ 2.4,
3365
+ 2.7,
3366
+ -0.25,
3367
+ 2.4,
3368
+ 3.3,
3369
+ -0.25,
3370
+ 2.4,
3371
+ 3.3,
3372
+ 0,
3373
+ 2.4,
3374
+ 1.7,
3375
+ 0.66,
3376
+ 0.6,
3377
+ 1.7,
3378
+ 0.66,
3379
+ 1.425,
3380
+ 3.1,
3381
+ 0.66,
3382
+ 0.825,
3383
+ 2.6,
3384
+ 0.66,
3385
+ 1.425,
3386
+ 2.4,
3387
+ 0.25,
3388
+ 2.025,
3389
+ 2.3,
3390
+ 0.25,
3391
+ 2.1,
3392
+ 3.3,
3393
+ 0.25,
3394
+ 2.4,
3395
+ 2.7,
3396
+ 0.25,
3397
+ 2.4,
3398
+ 2.8,
3399
+ 0,
3400
+ 2.475,
3401
+ 2.8,
3402
+ -0.25,
3403
+ 2.475,
3404
+ 3.525,
3405
+ -0.25,
3406
+ 2.49375,
3407
+ 3.525,
3408
+ 0,
3409
+ 2.49375,
3410
+ 2.9,
3411
+ 0,
3412
+ 2.475,
3413
+ 2.9,
3414
+ -0.15,
3415
+ 2.475,
3416
+ 3.45,
3417
+ -0.15,
3418
+ 2.5125,
3419
+ 3.45,
3420
+ 0,
3421
+ 2.5125,
3422
+ 2.8,
3423
+ 0,
3424
+ 2.4,
3425
+ 2.8,
3426
+ -0.15,
3427
+ 2.4,
3428
+ 3.2,
3429
+ -0.15,
3430
+ 2.4,
3431
+ 3.2,
3432
+ 0,
3433
+ 2.4,
3434
+ 3.525,
3435
+ 0.25,
3436
+ 2.49375,
3437
+ 2.8,
3438
+ 0.25,
3439
+ 2.475,
3440
+ 3.45,
3441
+ 0.15,
3442
+ 2.5125,
3443
+ 2.9,
3444
+ 0.15,
3445
+ 2.475,
3446
+ 3.2,
3447
+ 0.15,
3448
+ 2.4,
3449
+ 2.8,
3450
+ 0.15,
3451
+ 2.4,
3452
+ 0,
3453
+ 0,
3454
+ 3.15,
3455
+ 0.8,
3456
+ 0,
3457
+ 3.15,
3458
+ 0.8,
3459
+ -0.45,
3460
+ 3.15,
3461
+ 0.45,
3462
+ -0.8,
3463
+ 3.15,
3464
+ 0,
3465
+ -0.8,
3466
+ 3.15,
3467
+ 0,
3468
+ 0,
3469
+ 2.85,
3470
+ 0.2,
3471
+ 0,
3472
+ 2.7,
3473
+ 0.2,
3474
+ -0.112,
3475
+ 2.7,
3476
+ 0.112,
3477
+ -0.2,
3478
+ 2.7,
3479
+ 0,
3480
+ -0.2,
3481
+ 2.7,
3482
+ -0.45,
3483
+ -0.8,
3484
+ 3.15,
3485
+ -0.8,
3486
+ -0.45,
3487
+ 3.15,
3488
+ -0.8,
3489
+ 0,
3490
+ 3.15,
3491
+ -0.112,
3492
+ -0.2,
3493
+ 2.7,
3494
+ -0.2,
3495
+ -0.112,
3496
+ 2.7,
3497
+ -0.2,
3498
+ 0,
3499
+ 2.7,
3500
+ -0.8,
3501
+ 0.45,
3502
+ 3.15,
3503
+ -0.45,
3504
+ 0.8,
3505
+ 3.15,
3506
+ 0,
3507
+ 0.8,
3508
+ 3.15,
3509
+ -0.2,
3510
+ 0.112,
3511
+ 2.7,
3512
+ -0.112,
3513
+ 0.2,
3514
+ 2.7,
3515
+ 0,
3516
+ 0.2,
3517
+ 2.7,
3518
+ 0.45,
3519
+ 0.8,
3520
+ 3.15,
3521
+ 0.8,
3522
+ 0.45,
3523
+ 3.15,
3524
+ 0.112,
3525
+ 0.2,
3526
+ 2.7,
3527
+ 0.2,
3528
+ 0.112,
3529
+ 2.7,
3530
+ 0.4,
3531
+ 0,
3532
+ 2.55,
3533
+ 0.4,
3534
+ -0.224,
3535
+ 2.55,
3536
+ 0.224,
3537
+ -0.4,
3538
+ 2.55,
3539
+ 0,
3540
+ -0.4,
3541
+ 2.55,
3542
+ 1.3,
3543
+ 0,
3544
+ 2.55,
3545
+ 1.3,
3546
+ -0.728,
3547
+ 2.55,
3548
+ 0.728,
3549
+ -1.3,
3550
+ 2.55,
3551
+ 0,
3552
+ -1.3,
3553
+ 2.55,
3554
+ 1.3,
3555
+ 0,
3556
+ 2.4,
3557
+ 1.3,
3558
+ -0.728,
3559
+ 2.4,
3560
+ 0.728,
3561
+ -1.3,
3562
+ 2.4,
3563
+ 0,
3564
+ -1.3,
3565
+ 2.4,
3566
+ -0.224,
3567
+ -0.4,
3568
+ 2.55,
3569
+ -0.4,
3570
+ -0.224,
3571
+ 2.55,
3572
+ -0.4,
3573
+ 0,
3574
+ 2.55,
3575
+ -0.728,
3576
+ -1.3,
3577
+ 2.55,
3578
+ -1.3,
3579
+ -0.728,
3580
+ 2.55,
3581
+ -1.3,
3582
+ 0,
3583
+ 2.55,
3584
+ -0.728,
3585
+ -1.3,
3586
+ 2.4,
3587
+ -1.3,
3588
+ -0.728,
3589
+ 2.4,
3590
+ -1.3,
3591
+ 0,
3592
+ 2.4,
3593
+ -0.4,
3594
+ 0.224,
3595
+ 2.55,
3596
+ -0.224,
3597
+ 0.4,
3598
+ 2.55,
3599
+ 0,
3600
+ 0.4,
3601
+ 2.55,
3602
+ -1.3,
3603
+ 0.728,
3604
+ 2.55,
3605
+ -0.728,
3606
+ 1.3,
3607
+ 2.55,
3608
+ 0,
3609
+ 1.3,
3610
+ 2.55,
3611
+ -1.3,
3612
+ 0.728,
3613
+ 2.4,
3614
+ -0.728,
3615
+ 1.3,
3616
+ 2.4,
3617
+ 0,
3618
+ 1.3,
3619
+ 2.4,
3620
+ 0.224,
3621
+ 0.4,
3622
+ 2.55,
3623
+ 0.4,
3624
+ 0.224,
3625
+ 2.55,
3626
+ 0.728,
3627
+ 1.3,
3628
+ 2.55,
3629
+ 1.3,
3630
+ 0.728,
3631
+ 2.55,
3632
+ 0.728,
3633
+ 1.3,
3634
+ 2.4,
3635
+ 1.3,
3636
+ 0.728,
3637
+ 2.4,
3638
+ 0,
3639
+ 0,
3640
+ 0,
3641
+ 1.425,
3642
+ 0,
3643
+ 0,
3644
+ 1.425,
3645
+ 0.798,
3646
+ 0,
3647
+ 0.798,
3648
+ 1.425,
3649
+ 0,
3650
+ 0,
3651
+ 1.425,
3652
+ 0,
3653
+ 1.5,
3654
+ 0,
3655
+ 0.075,
3656
+ 1.5,
3657
+ 0.84,
3658
+ 0.075,
3659
+ 0.84,
3660
+ 1.5,
3661
+ 0.075,
3662
+ 0,
3663
+ 1.5,
3664
+ 0.075,
3665
+ -0.798,
3666
+ 1.425,
3667
+ 0,
3668
+ -1.425,
3669
+ 0.798,
3670
+ 0,
3671
+ -1.425,
3672
+ 0,
3673
+ 0,
3674
+ -0.84,
3675
+ 1.5,
3676
+ 0.075,
3677
+ -1.5,
3678
+ 0.84,
3679
+ 0.075,
3680
+ -1.5,
3681
+ 0,
3682
+ 0.075,
3683
+ -1.425,
3684
+ -0.798,
3685
+ 0,
3686
+ -0.798,
3687
+ -1.425,
3688
+ 0,
3689
+ 0,
3690
+ -1.425,
3691
+ 0,
3692
+ -1.5,
3693
+ -0.84,
3694
+ 0.075,
3695
+ -0.84,
3696
+ -1.5,
3697
+ 0.075,
3698
+ 0,
3699
+ -1.5,
3700
+ 0.075,
3701
+ 0.798,
3702
+ -1.425,
3703
+ 0,
3704
+ 1.425,
3705
+ -0.798,
3706
+ 0,
3707
+ 0.84,
3708
+ -1.5,
3709
+ 0.075,
3710
+ 1.5,
3711
+ -0.84,
3712
+ 0.075
3713
+ ]);
3714
+ function basis(value) {
3715
+ const inverse = 1 - value;
3716
+ return [
3717
+ inverse * inverse * inverse,
3718
+ 3 * value * inverse * inverse,
3719
+ 3 * value * value * inverse,
3720
+ value * value * value
3721
+ ];
3722
+ }
3723
+ function derivativeBasis(value) {
3724
+ const inverse = 1 - value;
3725
+ return [
3726
+ -3 * inverse * inverse,
3727
+ 3 * inverse * inverse - 6 * value * inverse,
3728
+ 6 * value * inverse - 3 * value * value,
3729
+ 3 * value * value
3730
+ ];
3731
+ }
3732
+ function evaluatePatch(surface, s, t, fitLid, blinn) {
3733
+ const sb = basis(s);
3734
+ const tb = basis(t);
3735
+ const dsb = derivativeBasis(s);
3736
+ const dtb = derivativeBasis(t);
3737
+ const point = [0, 0, 0];
3738
+ const ds = [0, 0, 0];
3739
+ const dt = [0, 0, 0];
3740
+ for (let row = 0; row < 4; row++) {
3741
+ for (let column = 0; column < 4; column++) {
3742
+ const control = PATCHES[surface * 16 + row * 4 + column] ?? 0;
3743
+ const source = control * 3;
3744
+ for (let axis = 0; axis < 3; axis++) {
3745
+ const lidScale = fitLid && surface >= 20 && surface < 28 && axis !== 2 ? 1.077 : 1;
3746
+ let value = (CONTROL_POINTS[source + axis] ?? 0) * lidScale;
3747
+ if (!blinn && axis === 2) value *= 1.3;
3748
+ const pointWeight = value * (sb[row] ?? 0) * (tb[column] ?? 0);
3749
+ const dsWeight = value * (dsb[row] ?? 0) * (tb[column] ?? 0);
3750
+ const dtWeight = value * (sb[row] ?? 0) * (dtb[column] ?? 0);
3751
+ point[axis] = (point[axis] ?? 0) + pointWeight;
3752
+ ds[axis] = (ds[axis] ?? 0) + dsWeight;
3753
+ dt[axis] = (dt[axis] ?? 0) + dtWeight;
3754
+ }
3755
+ }
3756
+ }
3757
+ return { point, ds, dt };
3758
+ }
3759
+ function cross2(a, b) {
3760
+ return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
3761
+ }
3762
+ function normalize(value) {
3763
+ const length = Math.hypot(value[0], value[1], value[2]);
3764
+ return length > 0 ? [value[0] / length, value[1] / length, value[2] / length] : [0, 1, 0];
3765
+ }
3766
+ function createTeapotGeometry(size = 0.8, segments = 18, bottom = true, lid = true, body = true, fitLid = true, blinn = true) {
3767
+ if (!Number.isFinite(size) || size <= 0 || !Number.isFinite(segments) || segments < 2) {
3768
+ return err(
3769
+ new AssetError({
3770
+ code: "asset-parse-failed",
3771
+ expected: "finite positive size and segments >= 2",
3772
+ hint: ASSET_ERROR_HINTS["asset-parse-failed"],
3773
+ detail: { field: "parameters", value: size, reason: `segments=${segments}` }
3774
+ })
3775
+ );
3776
+ }
3777
+ const steps = Math.max(2, Math.floor(segments));
3778
+ const maxHeight = 3.15 * (blinn ? 1 : 1.3);
3779
+ const maxHeight2 = maxHeight / 2;
3780
+ const trueSize = size / maxHeight2;
3781
+ const firstSurface = body ? 0 : 20;
3782
+ const lastSurface = bottom ? 32 : 28;
3783
+ const activeSurfaces = [];
3784
+ for (let surface = firstSurface; surface < lastSurface; surface++) {
3785
+ if (lid || surface < 20 || surface >= 28) activeSurfaces.push(surface);
3786
+ }
3787
+ const vertices = new Float32Array(
3788
+ activeSurfaces.length * (steps + 1) * (steps + 1) * FACTORY_FLOATS_PER_VERTEX
3789
+ );
3790
+ const indices = [];
3791
+ const stride = steps + 1;
3792
+ let vertex = 0;
3793
+ const positions = [];
3794
+ for (const surface of activeSurfaces) {
3795
+ const surfaceStart = vertex;
3796
+ for (let sStep = 0; sStep <= steps; sStep++) {
3797
+ const s = sStep / steps;
3798
+ for (let tStep = 0; tStep <= steps; tStep++) {
3799
+ const t = tStep / steps;
3800
+ const evaluated = evaluatePatch(surface, s, t, fitLid, blinn);
3801
+ const normalRaw = cross2(evaluated.dt, evaluated.ds);
3802
+ const normal = evaluated.point[0] === 0 && evaluated.point[1] === 0 ? [0, evaluated.point[2] > maxHeight2 ? 1 : -1, 0] : normalize([normalRaw[0], normalRaw[2], -normalRaw[1]]);
3803
+ const position = [
3804
+ Math.fround(trueSize * evaluated.point[0]),
3805
+ Math.fround(trueSize * (evaluated.point[2] - maxHeight2)),
3806
+ Math.fround(-trueSize * evaluated.point[1])
3807
+ ];
3808
+ const base = vertex * FACTORY_FLOATS_PER_VERTEX;
3809
+ vertices[base] = position[0];
3810
+ vertices[base + 1] = position[1];
3811
+ vertices[base + 2] = position[2];
3812
+ vertices[base + 3] = normal[0];
3813
+ vertices[base + 4] = normal[1];
3814
+ vertices[base + 5] = normal[2];
3815
+ vertices[base + 6] = 1 - t;
3816
+ vertices[base + 7] = 1 - s;
3817
+ positions.push(position);
3818
+ vertex++;
3819
+ }
3820
+ }
3821
+ for (let sStep = 0; sStep < steps; sStep++) {
3822
+ for (let tStep = 0; tStep < steps; tStep++) {
3823
+ const v1 = surfaceStart + sStep * stride + tStep;
3824
+ const v2 = v1 + 1;
3825
+ const v3 = v2 + stride;
3826
+ const v4 = v1 + stride;
3827
+ const same = (a, b) => positions[a]?.[0] === positions[b]?.[0] && positions[a]?.[1] === positions[b]?.[1] && positions[a]?.[2] === positions[b]?.[2];
3828
+ if (!same(v1, v2) && !same(v1, v3) && !same(v2, v3)) indices.push(v1, v2, v3);
3829
+ if (!same(v1, v3) && !same(v1, v4) && !same(v3, v4)) indices.push(v1, v3, v4);
3830
+ }
3831
+ }
3832
+ }
3833
+ const mesh = meshFromInterleaved(vertices, new Uint32Array(indices));
3834
+ if (!mesh.ok) return mesh;
3835
+ return ok({
3836
+ ...mesh.value,
3837
+ provenance: {
3838
+ source: "three.js",
3839
+ commit: "ad005397bbd15b0a9fcd5159c782eba56e1cba2a",
3840
+ path: "examples/jsm/geometries/TeapotGeometry.js",
3841
+ license: "MIT"
3842
+ }
3843
+ });
3844
+ }
1939
3845
  function createTorusGeometry(radius, tube, radialSegments = 8, tubularSegments = 24) {
1940
3846
  if (radius <= 0) return err(degenerate(`radius=${radius}`));
1941
3847
  if (tube <= 0) return err(degenerate(`tube=${tube}`));
@@ -1995,6 +3901,6 @@ function createTorusGeometry(radius, tube, radialSegments = 8, tubularSegments =
1995
3901
  return meshFromInterleaved(vertices, indices);
1996
3902
  }
1997
3903
 
1998
- export { PROCEDURAL_FLOATS_PER_VERTEX, VertexAttributePackError, buildMeshAttributeMapForUvSets, compute2dBounds, computeTangentVec4, create2dGeometry, create2dRingGeometry, createBoxGeometry, createCapsuleGeometry, createConeGeometry, createCylinderGeometry, createPlaneGeometry, createPrimitiveMesh, createSphereGeometry, createTorusGeometry, deriveVertexBufferLayout, deriveVertexBufferLayoutFromProjection, deriveVertexLayoutProjection, deriveVertexLayoutProjectionFromMask, meshAssetContribution, meshAssetDecoder, meshAssetKind, meshFromInterleaved, packInterleavedVertexAttributes };
3904
+ export { PROCEDURAL_FLOATS_PER_VERTEX, VertexAttributePackError, buildMeshAttributeMapForUvSets, compute2dBounds, computeTangentVec4, create2dGeometry, create2dRingGeometry, createBoxGeometry, createCapsuleGeometry, createConeGeometry, createCylinderGeometry, createEdgesGeometry, createPlaneGeometry, createPrimitiveMesh, createSphereGeometry, createTeapotGeometry, createTorusGeometry, createWireframeGeometry, deriveVertexBufferLayout, deriveVertexBufferLayoutFromProjection, deriveVertexLayoutProjection, deriveVertexLayoutProjectionFromMask, meshAssetContribution, meshAssetDecoder, meshAssetKind, meshFromInterleaved, packInterleavedVertexAttributes };
1999
3905
  //# sourceMappingURL=index.mjs.map
2000
3906
  //# sourceMappingURL=index.mjs.map