poppygl 0.0.35 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -3
- package/dist/index.d.ts +18 -2
- package/dist/index.js +228 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ const png = await renderGLTFToPNGFromGLB(glb, {
|
|
|
136
136
|
- `showEdges`: draw visible boundary and crease edges on all triangle meshes (default `false`).
|
|
137
137
|
- `showHiddenEdges`: draw visible edges plus faint dashed occluded edges on all meshes. Omit it or use `null` to preserve each model's flag; `false` disables those flags.
|
|
138
138
|
- `edgeWidth`: width of both visible and hidden mesh edges in output pixels (default `1`).
|
|
139
|
-
- `lineWidth`: width of glTF `LINES
|
|
139
|
+
- `lineWidth`: width of glTF `LINES`, finite grid lines, and explosion guides in output pixels (default `1`).
|
|
140
140
|
- `hiddenEdgeOpacity`: opacity of dashed occluded mesh edges, from `0` to `1` (default `0.35`).
|
|
141
141
|
- `fetchImpl`: optional override for resource loading (must match the `fetch` signature).
|
|
142
142
|
|
|
@@ -167,8 +167,9 @@ finite fractional widths are supported; invalid widths fall back to one pixel.
|
|
|
167
167
|
Wider strokes use antialiased screen-space coverage with round caps in the
|
|
168
168
|
software renderer. They are clipped before the perspective divide and remain
|
|
169
169
|
depth tested across their full width. No GPU or shader runtime is required.
|
|
170
|
-
`lineWidth` also applies to ordinary glTF line primitives
|
|
171
|
-
|
|
170
|
+
`lineWidth` also applies to ordinary glTF line primitives, finite grid lines,
|
|
171
|
+
and explosion guides, including arrowhead strokes. The procedural infinite grid
|
|
172
|
+
keeps its existing independent styling.
|
|
172
173
|
|
|
173
174
|
### Hidden edges for selected sub-models
|
|
174
175
|
|
|
@@ -238,6 +239,53 @@ const png = await encodePNG(bitmap)
|
|
|
238
239
|
|
|
239
240
|
The only contract is that `buffers` is an array of `Uint8Array` instances and `images` is an array of `BitmapLike` textures (PNG and JPEG are supported out of the box via `decodeImageFromBuffer`).
|
|
240
241
|
|
|
242
|
+
## Explosion guide lines
|
|
243
|
+
|
|
244
|
+
Pass `explosionLines` to any render entrypoint to draw polylines between assembled
|
|
245
|
+
and displaced part positions. The caller moves the geometry and supplies the
|
|
246
|
+
points in the same glTF scene frame and units (normally right-handed, +Y up).
|
|
247
|
+
|
|
248
|
+
This lamp is adapted from [core's reference-surface lamp](https://github.com/tscircuit/core/blob/81bef4337570e3ac4d7dd6d30ab63481304e8147/tests/assembly/fixtures/reference-surface-lamp.tsx).
|
|
249
|
+
Its base, hollow blue stem, and bulb stay in place while the hollow shade,
|
|
250
|
+
mounting collar, and three spokes move together by **+60 mm on scene Y**. The
|
|
251
|
+
shade mount moves from Y=92 to Y=152. Two dashed guides join corresponding points
|
|
252
|
+
on its lower rim, from Y=68 to Y=128. Arrowheads at the displaced endpoints show
|
|
253
|
+
the upward movement:
|
|
254
|
+
|
|
255
|
+

|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
// explodedLampGlb already contains the shade translated +60 mm on scene Y.
|
|
259
|
+
const rimPoints = [[-36 / Math.SQRT2, 36 / Math.SQRT2], [36, 0]] as const
|
|
260
|
+
const png = await renderGLTFToPNGFromGLB(explodedLampGlb, {
|
|
261
|
+
explosionLines: rimPoints.map(([x, z]) => ({
|
|
262
|
+
points: [[x, 68, z], [x, 128, z]],
|
|
263
|
+
color: [0.015, 0.04, 0.08], // Linear RGB, 0..1; optional.
|
|
264
|
+
dashed: true, // Default; false gives a solid guide.
|
|
265
|
+
arrow: true, // Optional; false by default.
|
|
266
|
+
})),
|
|
267
|
+
})
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The deterministic [lamp fixture](tests/fixtures/reference-lamp.ts) and
|
|
271
|
+
[visual test](tests/render/explosion-lamp.test.ts) generate the comparison without
|
|
272
|
+
network assets. Open the `explosion-lamp` Cosmos example to toggle shade movement,
|
|
273
|
+
guides, and arrows interactively. The separate synthetic explosion-lines snapshot
|
|
274
|
+
exercises elbows, geometry occlusion, and camera clipping.
|
|
275
|
+
|
|
276
|
+
Guides respect scene depth, do not write to the depth buffer, and render after
|
|
277
|
+
geometry denoising. Their points contribute to automatic camera framing. Lines
|
|
278
|
+
are clipped to the camera frustum before rasterization; dash length scales with
|
|
279
|
+
supersampling. Omitting the option or passing an empty list preserves the existing
|
|
280
|
+
rendering behavior. Each guide needs at least two finite XYZ points.
|
|
281
|
+
|
|
282
|
+
Set `arrow: true` to draw a solid open arrowhead at the final authored point,
|
|
283
|
+
following the final nonzero-length segment's direction. Arrowheads are at most
|
|
284
|
+
10 output pixels long, capped for short segments, and scale with supersampling.
|
|
285
|
+
They respect scene depth and remain solid when the shaft is dashed. `lineWidth`
|
|
286
|
+
controls both the shaft and arrowhead stroke width. Omit `arrow` or set it to
|
|
287
|
+
`false` for a guide without an arrow.
|
|
288
|
+
|
|
241
289
|
## Additional utilities
|
|
242
290
|
|
|
243
291
|
- `loadGLTFWithResourcesFromURL` returns `{ gltf, resources }` if you prefer to inspect or cache the parsed data before rendering.
|
package/dist/index.d.ts
CHANGED
|
@@ -69,6 +69,21 @@ interface DebugPoint {
|
|
|
69
69
|
z: number;
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
+
/** Guide polyline in right-handed glTF scene coordinates (normally +Y up),
|
|
73
|
+
* using the model's scene units. Each vertex is a point, not a displacement.
|
|
74
|
+
*/
|
|
75
|
+
interface ExplosionLine {
|
|
76
|
+
points: readonly (readonly [number, number, number])[];
|
|
77
|
+
/** Linear RGB, 0..1; defaults to a muted blue. */
|
|
78
|
+
color?: readonly [number, number, number];
|
|
79
|
+
/** Defaults to true. Visible segments respect scene depth. */
|
|
80
|
+
dashed?: boolean;
|
|
81
|
+
/** Add a solid arrowhead at the last point, following the final segment.
|
|
82
|
+
* Defaults to false. The arrowhead is 10 output pixels long (or shorter for
|
|
83
|
+
* short segments), independent of camera distance and supersampling.
|
|
84
|
+
*/
|
|
85
|
+
arrow?: boolean;
|
|
86
|
+
}
|
|
72
87
|
type CameraUp = "y+" | "y-" | "x+" | "x-" | "z+" | "z-";
|
|
73
88
|
interface CameraRotation {
|
|
74
89
|
x: number;
|
|
@@ -102,13 +117,14 @@ interface RenderOptions {
|
|
|
102
117
|
debugFontSize?: number | null;
|
|
103
118
|
debugPointColor?: readonly [number, number, number] | null;
|
|
104
119
|
debugLabelColor?: readonly [number, number, number] | null;
|
|
120
|
+
explosionLines?: readonly ExplosionLine[] | null;
|
|
105
121
|
/** Draw visible boundary and crease edges on every triangle mesh. */
|
|
106
122
|
showEdges: boolean;
|
|
107
123
|
/** Override model showHiddenEdges flags; null preserves each model's flag. */
|
|
108
124
|
showHiddenEdges: boolean | null;
|
|
109
125
|
/** Width of visible and hidden mesh edges in output pixels. */
|
|
110
126
|
edgeWidth: number;
|
|
111
|
-
/** Width of glTF LINES
|
|
127
|
+
/** Width of glTF LINES, finite grid lines, and explosion guides in output pixels. */
|
|
112
128
|
lineWidth: number;
|
|
113
129
|
/** Opacity of dashed, occluded mesh edges, from 0 to 1. */
|
|
114
130
|
hiddenEdgeOpacity: number;
|
|
@@ -263,4 +279,4 @@ declare function renderGLTFToPNGFromGLB(glb: ArrayBuffer | Uint8Array, options?:
|
|
|
263
279
|
|
|
264
280
|
declare function renderSceneFromGLTF(scene: GLTFScene, options?: RenderOptionsInput, imageFactory?: ImageFactory): RenderResult;
|
|
265
281
|
|
|
266
|
-
export { type BitmapLike, type Camera, type CameraRotation, type CameraUp, DEFAULT_LIGHT_DIR, DEFAULT_RENDER_OPTIONS, type DebugPoint, type DrawCall, type FetchLike, type GLTFResources, type GLTFScene, type GridOptions, type ImageFactory, type LightSettings, type LineRenderOptions, type LoadGLTFWithResourcesFromURLOptions, type Material, type MutableRGBA, type RGBA, type RenderGLTFToPNGFromGLBOptions, type RenderGLTFToPNGFromURLOptions, type RenderOptions, type RenderOptionsInput, type RenderResult, SoftwareRenderer, bufferFromDataURI, buildCamera, computeSmoothNormals, computeWorldAABB, createEdgeDrawCall, createGrid, createInfiniteGrid, createSceneFromGLTF, createUint8Bitmap, decodeImageFromBuffer, drawInfiniteGrid, encodePNG, getDefaultRenderOptions, hexToRgb, isJPG, isPNG, loadGLTFWithResourcesFromURL, renderDrawCalls, renderGLTFToPNGFromGLB, renderGLTFToPNGFromURL, renderSceneFromGLTF, resolveRenderOptions };
|
|
282
|
+
export { type BitmapLike, type Camera, type CameraRotation, type CameraUp, DEFAULT_LIGHT_DIR, DEFAULT_RENDER_OPTIONS, type DebugPoint, type DrawCall, type ExplosionLine, type FetchLike, type GLTFResources, type GLTFScene, type GridOptions, type ImageFactory, type LightSettings, type LineRenderOptions, type LoadGLTFWithResourcesFromURLOptions, type Material, type MutableRGBA, type RGBA, type RenderGLTFToPNGFromGLBOptions, type RenderGLTFToPNGFromURLOptions, type RenderOptions, type RenderOptionsInput, type RenderResult, SoftwareRenderer, bufferFromDataURI, buildCamera, computeSmoothNormals, computeWorldAABB, createEdgeDrawCall, createGrid, createInfiniteGrid, createSceneFromGLTF, createUint8Bitmap, decodeImageFromBuffer, drawInfiniteGrid, encodePNG, getDefaultRenderOptions, hexToRgb, isJPG, isPNG, loadGLTFWithResourcesFromURL, renderDrawCalls, renderGLTFToPNGFromGLB, renderGLTFToPNGFromURL, renderSceneFromGLTF, resolveRenderOptions };
|
package/dist/index.js
CHANGED
|
@@ -499,6 +499,7 @@ var DEFAULT_RENDER_OPTIONS = {
|
|
|
499
499
|
debugFontSize: null,
|
|
500
500
|
debugPointColor: null,
|
|
501
501
|
debugLabelColor: null,
|
|
502
|
+
explosionLines: null,
|
|
502
503
|
showEdges: false,
|
|
503
504
|
showHiddenEdges: null,
|
|
504
505
|
edgeWidth: 1,
|
|
@@ -2369,13 +2370,190 @@ var StudioLighting = class {
|
|
|
2369
2370
|
}
|
|
2370
2371
|
};
|
|
2371
2372
|
|
|
2373
|
+
// lib/render/createExplosionLineDrawCall.ts
|
|
2374
|
+
import { mat4 as mat47, vec4 as vec45 } from "gl-matrix";
|
|
2375
|
+
function createExplosionLineDrawCall(line) {
|
|
2376
|
+
if (line.points.length < 2 || line.points.some(
|
|
2377
|
+
(point) => point.length !== 3 || !point.every(Number.isFinite)
|
|
2378
|
+
)) {
|
|
2379
|
+
throw new Error("Explosion lines need at least two finite XYZ points");
|
|
2380
|
+
}
|
|
2381
|
+
const color = line.color ?? [0.08, 0.2, 0.35];
|
|
2382
|
+
if (color.length !== 3 || color.some(
|
|
2383
|
+
(channel) => !Number.isFinite(channel) || channel < 0 || channel > 1
|
|
2384
|
+
)) {
|
|
2385
|
+
throw new Error(
|
|
2386
|
+
"Explosion line colors must be linear RGB values from 0 to 1"
|
|
2387
|
+
);
|
|
2388
|
+
}
|
|
2389
|
+
const indices = [];
|
|
2390
|
+
for (let vertex = 1; vertex < line.points.length; vertex++) {
|
|
2391
|
+
indices.push(vertex - 1, vertex);
|
|
2392
|
+
}
|
|
2393
|
+
return {
|
|
2394
|
+
positions: new Float32Array(line.points.flatMap((point) => [...point])),
|
|
2395
|
+
indices: new Uint32Array(indices),
|
|
2396
|
+
normals: null,
|
|
2397
|
+
uvs: null,
|
|
2398
|
+
model: mat47.create(),
|
|
2399
|
+
material: { baseColorFactor: [...color, 1], baseColorTexture: null },
|
|
2400
|
+
mode: 1
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
function clipExplosionLineDrawCall(drawCall, camera) {
|
|
2404
|
+
const viewProjection = mat47.multiply(mat47.create(), camera.proj, camera.view);
|
|
2405
|
+
const positions = [];
|
|
2406
|
+
const indices = [];
|
|
2407
|
+
const distances = (point) => [
|
|
2408
|
+
point[3] + point[0],
|
|
2409
|
+
point[3] - point[0],
|
|
2410
|
+
point[3] + point[1],
|
|
2411
|
+
point[3] - point[1],
|
|
2412
|
+
point[3] + point[2],
|
|
2413
|
+
point[3] - point[2]
|
|
2414
|
+
];
|
|
2415
|
+
for (let segment = 0; segment < drawCall.indices.length; segment += 2) {
|
|
2416
|
+
const startIndex = drawCall.indices[segment] * 3;
|
|
2417
|
+
const endIndex = drawCall.indices[segment + 1] * 3;
|
|
2418
|
+
const start = vec45.fromValues(
|
|
2419
|
+
drawCall.positions[startIndex],
|
|
2420
|
+
drawCall.positions[startIndex + 1],
|
|
2421
|
+
drawCall.positions[startIndex + 2],
|
|
2422
|
+
1
|
|
2423
|
+
);
|
|
2424
|
+
const end = vec45.fromValues(
|
|
2425
|
+
drawCall.positions[endIndex],
|
|
2426
|
+
drawCall.positions[endIndex + 1],
|
|
2427
|
+
drawCall.positions[endIndex + 2],
|
|
2428
|
+
1
|
|
2429
|
+
);
|
|
2430
|
+
const startDistances = distances(
|
|
2431
|
+
vec45.transformMat4(vec45.create(), start, viewProjection)
|
|
2432
|
+
);
|
|
2433
|
+
const endDistances = distances(
|
|
2434
|
+
vec45.transformMat4(vec45.create(), end, viewProjection)
|
|
2435
|
+
);
|
|
2436
|
+
let from = 0;
|
|
2437
|
+
let to = 1;
|
|
2438
|
+
for (let plane = 0; plane < 6; plane++) {
|
|
2439
|
+
const a = startDistances[plane];
|
|
2440
|
+
const b = endDistances[plane];
|
|
2441
|
+
if (a < 0 && b < 0) {
|
|
2442
|
+
to = -1;
|
|
2443
|
+
break;
|
|
2444
|
+
}
|
|
2445
|
+
if (a < 0 !== b < 0) {
|
|
2446
|
+
const intersection = a / (a - b);
|
|
2447
|
+
if (a < 0) from = Math.max(from, intersection);
|
|
2448
|
+
else to = Math.min(to, intersection);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
if (from > to) continue;
|
|
2452
|
+
const vertex = positions.length / 3;
|
|
2453
|
+
for (const progress of [from, to]) {
|
|
2454
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
2455
|
+
positions.push(start[axis] + progress * (end[axis] - start[axis]));
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
indices.push(vertex, vertex + 1);
|
|
2459
|
+
}
|
|
2460
|
+
return {
|
|
2461
|
+
...drawCall,
|
|
2462
|
+
positions: new Float32Array(positions),
|
|
2463
|
+
indices: new Uint32Array(indices)
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
// lib/render/createExplosionArrowDrawCall.ts
|
|
2468
|
+
import { mat4 as mat48, vec4 as vec46 } from "gl-matrix";
|
|
2469
|
+
function createExplosionArrowDrawCall(drawCall, camera, width, height, supersampling) {
|
|
2470
|
+
if (width <= 1 || height <= 1) return null;
|
|
2471
|
+
const points = drawCall.positions;
|
|
2472
|
+
const end = points.length - 3;
|
|
2473
|
+
let start = end - 3;
|
|
2474
|
+
while (start >= 0 && points[start] === points[end] && points[start + 1] === points[end + 1] && points[start + 2] === points[end + 2]) {
|
|
2475
|
+
start -= 3;
|
|
2476
|
+
}
|
|
2477
|
+
if (start < 0) return null;
|
|
2478
|
+
const viewProjection = mat48.multiply(mat48.create(), camera.proj, camera.view);
|
|
2479
|
+
const tip = vec46.transformMat4(
|
|
2480
|
+
vec46.create(),
|
|
2481
|
+
vec46.fromValues(points[end], points[end + 1], points[end + 2], 1),
|
|
2482
|
+
viewProjection
|
|
2483
|
+
);
|
|
2484
|
+
if (!Array.from(tip).every(Number.isFinite) || tip[3] <= 0 || Math.abs(tip[0]) > tip[3] || Math.abs(tip[1]) > tip[3] || Math.abs(tip[2]) > tip[3]) {
|
|
2485
|
+
return null;
|
|
2486
|
+
}
|
|
2487
|
+
const clipped = clipExplosionLineDrawCall(
|
|
2488
|
+
{
|
|
2489
|
+
...drawCall,
|
|
2490
|
+
positions: new Float32Array([
|
|
2491
|
+
points[start],
|
|
2492
|
+
points[start + 1],
|
|
2493
|
+
points[start + 2],
|
|
2494
|
+
points[end],
|
|
2495
|
+
points[end + 1],
|
|
2496
|
+
points[end + 2]
|
|
2497
|
+
]),
|
|
2498
|
+
indices: new Uint32Array([0, 1])
|
|
2499
|
+
},
|
|
2500
|
+
camera
|
|
2501
|
+
);
|
|
2502
|
+
if (!clipped.indices?.length) return null;
|
|
2503
|
+
const tail = vec46.transformMat4(
|
|
2504
|
+
vec46.create(),
|
|
2505
|
+
vec46.fromValues(
|
|
2506
|
+
clipped.positions[0],
|
|
2507
|
+
clipped.positions[1],
|
|
2508
|
+
clipped.positions[2],
|
|
2509
|
+
1
|
|
2510
|
+
),
|
|
2511
|
+
viewProjection
|
|
2512
|
+
);
|
|
2513
|
+
if (tail[3] <= 0) return null;
|
|
2514
|
+
const dx = (tip[0] / tip[3] - tail[0] / tail[3]) * (width - 1) / 2;
|
|
2515
|
+
const dy = (tip[1] / tip[3] - tail[1] / tail[3]) * (height - 1) / 2;
|
|
2516
|
+
const length = Math.hypot(dx, dy);
|
|
2517
|
+
if (!Number.isFinite(length) || length < 1e-3) return null;
|
|
2518
|
+
const arrowLength = Math.min(10 * supersampling, length / 2);
|
|
2519
|
+
const ux = dx / length;
|
|
2520
|
+
const uy = dy / length;
|
|
2521
|
+
const inverse = mat48.invert(mat48.create(), viewProjection);
|
|
2522
|
+
if (!inverse) return null;
|
|
2523
|
+
const positions = [points[end], points[end + 1], points[end + 2]];
|
|
2524
|
+
for (const side of [-1, 1]) {
|
|
2525
|
+
const offsetX = -ux * arrowLength - side * uy * arrowLength * 0.45;
|
|
2526
|
+
const offsetY = -uy * arrowLength + side * ux * arrowLength * 0.45;
|
|
2527
|
+
const wing = vec46.transformMat4(
|
|
2528
|
+
vec46.create(),
|
|
2529
|
+
vec46.fromValues(
|
|
2530
|
+
tip[0] / tip[3] + 2 * offsetX / (width - 1),
|
|
2531
|
+
tip[1] / tip[3] + 2 * offsetY / (height - 1),
|
|
2532
|
+
tip[2] / tip[3],
|
|
2533
|
+
1
|
|
2534
|
+
),
|
|
2535
|
+
inverse
|
|
2536
|
+
);
|
|
2537
|
+
if (!Array.from(wing).every(Number.isFinite) || wing[3] === 0) return null;
|
|
2538
|
+
positions.push(wing[0] / wing[3], wing[1] / wing[3], wing[2] / wing[3]);
|
|
2539
|
+
}
|
|
2540
|
+
return {
|
|
2541
|
+
...drawCall,
|
|
2542
|
+
positions: new Float32Array(positions),
|
|
2543
|
+
indices: new Uint32Array([0, 1, 0, 2])
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2372
2547
|
// lib/render/renderDrawCalls.ts
|
|
2373
2548
|
function renderDrawCalls(drawCalls, optionsInput = {}, imageFactory = createUint8Bitmap) {
|
|
2374
2549
|
const options = resolveRenderOptions(optionsInput);
|
|
2375
2550
|
const renderWidth = options.width * options.supersampling;
|
|
2376
2551
|
const renderHeight = options.height * options.supersampling;
|
|
2552
|
+
const explosionDrawCalls = (options.explosionLines ?? []).map(
|
|
2553
|
+
createExplosionLineDrawCall
|
|
2554
|
+
);
|
|
2377
2555
|
const camera = buildCamera(
|
|
2378
|
-
drawCalls,
|
|
2556
|
+
[...drawCalls, ...explosionDrawCalls],
|
|
2379
2557
|
renderWidth,
|
|
2380
2558
|
renderHeight,
|
|
2381
2559
|
options.fov,
|
|
@@ -2534,6 +2712,43 @@ function renderDrawCalls(drawCalls, optionsInput = {}, imageFactory = createUint
|
|
|
2534
2712
|
width: options.edgeWidth * options.supersampling
|
|
2535
2713
|
});
|
|
2536
2714
|
}
|
|
2715
|
+
for (const [index, drawCall] of explosionDrawCalls.entries()) {
|
|
2716
|
+
renderer.drawLines(
|
|
2717
|
+
clipExplosionLineDrawCall(drawCall, camera),
|
|
2718
|
+
camera,
|
|
2719
|
+
options.gamma,
|
|
2720
|
+
{
|
|
2721
|
+
depthCompare: "less-equal",
|
|
2722
|
+
depthWrite: false,
|
|
2723
|
+
depthBias: 1e-4,
|
|
2724
|
+
dashed: options.explosionLines[index].dashed ?? true,
|
|
2725
|
+
dashLength: 4 * options.supersampling,
|
|
2726
|
+
width: options.lineWidth * options.supersampling
|
|
2727
|
+
}
|
|
2728
|
+
);
|
|
2729
|
+
if (options.explosionLines[index].arrow) {
|
|
2730
|
+
const arrow = createExplosionArrowDrawCall(
|
|
2731
|
+
drawCall,
|
|
2732
|
+
camera,
|
|
2733
|
+
renderWidth,
|
|
2734
|
+
renderHeight,
|
|
2735
|
+
options.supersampling
|
|
2736
|
+
);
|
|
2737
|
+
if (arrow) {
|
|
2738
|
+
renderer.drawLines(
|
|
2739
|
+
clipExplosionLineDrawCall(arrow, camera),
|
|
2740
|
+
camera,
|
|
2741
|
+
options.gamma,
|
|
2742
|
+
{
|
|
2743
|
+
depthCompare: "less-equal",
|
|
2744
|
+
depthWrite: false,
|
|
2745
|
+
depthBias: 1e-4,
|
|
2746
|
+
width: options.lineWidth * options.supersampling
|
|
2747
|
+
}
|
|
2748
|
+
);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2537
2752
|
if (options.debugPoints?.length) {
|
|
2538
2753
|
drawDebugPoints(
|
|
2539
2754
|
renderer,
|
|
@@ -2554,7 +2769,7 @@ function renderDrawCalls(drawCalls, optionsInput = {}, imageFactory = createUint
|
|
|
2554
2769
|
}
|
|
2555
2770
|
|
|
2556
2771
|
// lib/gltf/createInfiniteGrid.ts
|
|
2557
|
-
import { mat4 as
|
|
2772
|
+
import { mat4 as mat49 } from "gl-matrix";
|
|
2558
2773
|
function createInfiniteGrid(options = {}) {
|
|
2559
2774
|
const cellSize = options.cellSize ?? 1;
|
|
2560
2775
|
const sectionSize = options.sectionSize ?? 10;
|
|
@@ -2578,9 +2793,9 @@ function createInfiniteGrid(options = {}) {
|
|
|
2578
2793
|
size
|
|
2579
2794
|
]);
|
|
2580
2795
|
const indices = new Uint32Array([0, 1, 2, 0, 2, 3]);
|
|
2581
|
-
const model =
|
|
2796
|
+
const model = mat49.create();
|
|
2582
2797
|
const offset = options.offset ?? {};
|
|
2583
|
-
|
|
2798
|
+
mat49.fromTranslation(model, [offset.x ?? 0, offset.y ?? 0, offset.z ?? 0]);
|
|
2584
2799
|
return {
|
|
2585
2800
|
positions,
|
|
2586
2801
|
indices,
|
|
@@ -2605,7 +2820,7 @@ function createInfiniteGrid(options = {}) {
|
|
|
2605
2820
|
}
|
|
2606
2821
|
|
|
2607
2822
|
// lib/gltf/createSceneFromGLTF.ts
|
|
2608
|
-
import { mat4 as
|
|
2823
|
+
import { mat4 as mat410 } from "gl-matrix";
|
|
2609
2824
|
var COMPONENT_INFO = {
|
|
2610
2825
|
5120: {
|
|
2611
2826
|
name: "BYTE",
|
|
@@ -2812,17 +3027,17 @@ function readIndices(ctx, accessorIndex) {
|
|
|
2812
3027
|
}
|
|
2813
3028
|
function nodeLocalMatrix(node) {
|
|
2814
3029
|
if (node.matrix) {
|
|
2815
|
-
const m2 =
|
|
3030
|
+
const m2 = mat410.create();
|
|
2816
3031
|
for (let i = 0; i < 16; i++) m2[i] = node.matrix[i];
|
|
2817
3032
|
return m2;
|
|
2818
3033
|
}
|
|
2819
3034
|
const translation = node.translation || [0, 0, 0];
|
|
2820
3035
|
const rotation = node.rotation || [0, 0, 0, 1];
|
|
2821
3036
|
const scale = node.scale || [1, 1, 1];
|
|
2822
|
-
const m =
|
|
2823
|
-
const tmp =
|
|
2824
|
-
|
|
2825
|
-
|
|
3037
|
+
const m = mat410.create();
|
|
3038
|
+
const tmp = mat410.create();
|
|
3039
|
+
mat410.fromRotationTranslationScale(tmp, rotation, translation, scale);
|
|
3040
|
+
mat410.copy(m, tmp);
|
|
2826
3041
|
return m;
|
|
2827
3042
|
}
|
|
2828
3043
|
function getMaterial(gltf, textures, images, materialIndex) {
|
|
@@ -2865,8 +3080,8 @@ function createSceneFromGLTF(gltf, resources) {
|
|
|
2865
3080
|
const node = nodes[nodeIndex];
|
|
2866
3081
|
if (!node) return;
|
|
2867
3082
|
const local = nodeLocalMatrix(node);
|
|
2868
|
-
const world =
|
|
2869
|
-
|
|
3083
|
+
const world = mat410.create();
|
|
3084
|
+
mat410.multiply(world, parentMatrix, local);
|
|
2870
3085
|
if (Number.isInteger(node.mesh)) {
|
|
2871
3086
|
const mesh = meshes[node.mesh];
|
|
2872
3087
|
if (mesh) {
|
|
@@ -2905,7 +3120,7 @@ function createSceneFromGLTF(gltf, resources) {
|
|
|
2905
3120
|
traverse(childIndex, world);
|
|
2906
3121
|
}
|
|
2907
3122
|
}
|
|
2908
|
-
const identity =
|
|
3123
|
+
const identity = mat410.create();
|
|
2909
3124
|
for (const rootIndex of scene.nodes || []) {
|
|
2910
3125
|
traverse(rootIndex, identity);
|
|
2911
3126
|
}
|