@woosh/meep-engine 2.35.8 → 2.35.12

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 (28) hide show
  1. package/core/binary/BinaryBuffer.js +65 -18
  2. package/engine/graphics/ecs/camera/Camera.d.ts +3 -0
  3. package/engine/graphics/ecs/camera/Camera.js +39 -1
  4. package/engine/graphics/ecs/camera/CameraSystem.js +25 -6
  5. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +8 -2
  6. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +19 -4
  7. package/engine/graphics/ecs/path/PathDisplaySystem.js +1 -1
  8. package/engine/graphics/ecs/path/testPathDisplaySystem.js +13 -12
  9. package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +2 -0
  10. package/engine/graphics/ecs/path/tube/TubePathStyle.js +43 -1
  11. package/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +138 -0
  12. package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +32 -0
  13. package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +16 -0
  14. package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +153 -0
  15. package/engine/graphics/ecs/path/tube/build/estimatePathLength.js +17 -0
  16. package/engine/graphics/ecs/path/tube/build/estimatePathViaIterativeIntegral.js +37 -0
  17. package/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +156 -0
  18. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -1
  19. package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +45 -76
  20. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +19 -24
  21. package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -1
  22. package/engine/graphics/micron/render/v1/MaterialContext.js +1 -11
  23. package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +55 -2
  24. package/engine/graphics/micron/render/v1/MicronRenderContext.js +151 -0
  25. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +24 -117
  26. package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +1 -0
  27. package/package.json +1 -1
  28. package/engine/graphics/ecs/path/tube/TubePathBuilder.js +0 -522
@@ -1,522 +0,0 @@
1
- import {
2
- BufferGeometry,
3
- CatmullRomCurve3,
4
- Float32BufferAttribute,
5
- MeshMatcapMaterial,
6
- MeshStandardMaterial,
7
- TubeGeometry,
8
- Vector3
9
- } from "three";
10
- import { InterpolationType } from "../../../../navigation/ecs/components/InterpolationType.js";
11
- import EntityBuilder from "../../../../ecs/EntityBuilder.js";
12
- import { Transform } from "../../../../ecs/transform/Transform.js";
13
- import Renderable from "../../../../ecs/components/Renderable.js";
14
- import ThreeFactory from "../../../three/ThreeFactory.js";
15
- import { TubeMaterialType } from "./TubeMaterialType.js";
16
- import { GameAssetType } from "../../../../asset/GameAssetType.js";
17
- import { Matrix4 } from "three/src/math/Matrix4.js";
18
- import * as MathUtils from "three/src/math/MathUtils.js";
19
- import { max2 } from "../../../../../core/math/max2.js";
20
- import { min2 } from "../../../../../core/math/min2.js";
21
-
22
- /**
23
- * some useful references:
24
- * https://stackoverflow.com/questions/29438398/cheap-way-of-calculating-cubic-bezier-length
25
- * https://stackoverflow.com/questions/1147249/connecting-catmull-rom-splines-together-and-calculating-its-length
26
- * @param {Path} path
27
- * @param {number} epsilon
28
- */
29
- function estimatePathViaIterativeIntegral(path, epsilon) {
30
- let sum = 0;
31
-
32
- let p0 = new Vector3();
33
- let p1 = new Vector3();
34
-
35
- if (!path.sample(p0, 0)) {
36
- // path has 0 length
37
- return 0;
38
- }
39
-
40
- for (let p = epsilon; ; i += epsilon) {
41
- const ended = path.sample(p1, p);
42
-
43
- if (ended) {
44
- break;
45
- }
46
-
47
- sum += p0.distanceTo(p1);
48
-
49
- const swap = p1;
50
-
51
- p1 = p0;
52
- p0 = swap;
53
- }
54
-
55
- return sum;
56
- }
57
-
58
- /**
59
- * @see https://github.com/mrdoob/three.js/blob/c12c9a166a1369cdd58622fff2aff7e3a84305d7/src/extras/core/Curve.js#L260
60
- * @param {Vector3[]} points
61
- * @param {boolean} [closed]
62
- */
63
- function computeFrenetFrames(points, closed = false) {
64
- // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
65
-
66
- const normal = new Vector3();
67
-
68
- const tangents = [];
69
- const normals = [];
70
- const binormals = [];
71
-
72
- const vec = new Vector3();
73
- const mat = new Matrix4();
74
-
75
- const segments = points.length - 1;
76
-
77
- const v3_0 = new Vector3();
78
- const v3_1 = new Vector3();
79
-
80
- /**
81
- *
82
- * @param {number} i
83
- * @param {Vector3} destination
84
- */
85
- function getTangent(i, destination) {
86
- // get points on either side
87
- const i0 = max2(i - 1, 0);
88
- const i1 = min2(i + 1, segments);
89
-
90
- const p0 = points[i0];
91
- const pR = points[i];
92
- const p1 = points[i1];
93
-
94
- // get points along the lines close to the reference
95
- v3_0.subVectors(p0, pR);
96
- v3_0.normalize();
97
-
98
- v3_1.subVectors(p1, pR);
99
- v3_1.normalize();
100
-
101
- destination.subVectors(v3_1, v3_0);
102
- destination.normalize();
103
- }
104
-
105
- // compute the tangent vectors for each segment on the curve
106
-
107
- for (let i = 0; i <= segments; i++) {
108
-
109
- const tangent = new Vector3();
110
- getTangent(i, tangent);
111
-
112
- tangents[i] = tangent;
113
-
114
- }
115
-
116
- // select an initial normal vector perpendicular to the first tangent vector,
117
- // and in the direction of the minimum tangent xyz component
118
-
119
- normals[0] = new Vector3();
120
- binormals[0] = new Vector3();
121
- let min = Number.MAX_VALUE;
122
- const tx = Math.abs(tangents[0].x);
123
- const ty = Math.abs(tangents[0].y);
124
- const tz = Math.abs(tangents[0].z);
125
-
126
- if (tx <= min) {
127
-
128
- min = tx;
129
- normal.set(1, 0, 0);
130
-
131
- }
132
-
133
- if (ty <= min) {
134
-
135
- min = ty;
136
- normal.set(0, 1, 0);
137
-
138
- }
139
-
140
- if (tz <= min) {
141
-
142
- normal.set(0, 0, 1);
143
-
144
- }
145
-
146
- vec.crossVectors(tangents[0], normal).normalize();
147
-
148
- normals[0].crossVectors(tangents[0], vec);
149
- binormals[0].crossVectors(tangents[0], normals[0]);
150
-
151
-
152
- // compute the slowly-varying normal and binormal vectors for each segment on the curve
153
-
154
- for (let i = 1; i <= segments; i++) {
155
-
156
- normals[i] = normals[i - 1].clone();
157
-
158
- binormals[i] = binormals[i - 1].clone();
159
-
160
- vec.crossVectors(tangents[i - 1], tangents[i]);
161
-
162
- if (vec.length() > Number.EPSILON) {
163
-
164
- vec.normalize();
165
-
166
- const theta = Math.acos(MathUtils.clamp(tangents[i - 1].dot(tangents[i]), -1, 1)); // clamp for floating pt errors
167
-
168
- normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
169
-
170
- }
171
-
172
- binormals[i].crossVectors(tangents[i], normals[i]);
173
-
174
- }
175
-
176
- // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
177
-
178
- if (closed === true) {
179
-
180
- let theta = Math.acos(MathUtils.clamp(normals[0].dot(normals[segments]), -1, 1));
181
- theta /= segments;
182
-
183
- if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
184
-
185
- theta = -theta;
186
-
187
- }
188
-
189
- for (let i = 1; i <= segments; i++) {
190
-
191
- // twist a little...
192
- normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
193
- binormals[i].crossVectors(tangents[i], normals[i]);
194
-
195
- }
196
-
197
- }
198
-
199
- return {
200
- tangents: tangents,
201
- normals: normals,
202
- binormals: binormals
203
- };
204
- }
205
-
206
- /**
207
- * @see https://github.com/mrdoob/three.js/blob/master/src/geometries/TubeGeometry.js
208
- * @param {Vector3[]} points
209
- * @param {Vector3[]} _normals
210
- * @param {Vector3[]} binormals
211
- * @param {number} radius
212
- * @param {number} radialSegments
213
- * @param {boolean} [closed]
214
- * @returns {BufferGeometry}
215
- */
216
- function makeTubeGeometry(points, _normals, binormals, radius, radialSegments, closed = false) {
217
- const geometry = new BufferGeometry();
218
- // helper variables
219
-
220
- const vertex = new Vector3();
221
- const normal = new Vector3();
222
-
223
- // buffer
224
-
225
- const vertices = [];
226
- const normals = [];
227
- const uvs = [];
228
- const indices = [];
229
-
230
- const tubularSegments = points.length - 1;
231
-
232
- // create buffer data
233
-
234
- generateBufferData();
235
-
236
- // build geometry
237
-
238
- geometry.setIndex(indices);
239
- geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
240
- geometry.setAttribute('normal', new Float32BufferAttribute(normals, 3));
241
- geometry.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
242
-
243
- // functions
244
-
245
- function generateBufferData() {
246
-
247
- for (let i = 0; i < tubularSegments; i++) {
248
-
249
- generateSegment(i);
250
-
251
- }
252
-
253
- // if the geometry is not closed, generate the last row of vertices and normals
254
- // at the regular position on the given path
255
- //
256
- // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
257
-
258
- generateSegment((closed === false) ? tubularSegments : 0);
259
-
260
- // uvs are generated in a separate function.
261
- // this makes it easy compute correct values for closed geometries
262
-
263
- generateUVs();
264
-
265
- // finally create faces
266
-
267
- generateIndices();
268
-
269
- }
270
-
271
- function generateSegment(i) {
272
-
273
- // we use getPointAt to sample evenly distributed points from the given path
274
-
275
- const P = points[i];
276
-
277
- // retrieve corresponding normal and binormal
278
-
279
- const N = _normals[i];
280
- const B = binormals[i];
281
-
282
- // generate normals and vertices for the current segment
283
-
284
- for (let j = 0; j <= radialSegments; j++) {
285
-
286
- const v = j / radialSegments * Math.PI * 2;
287
-
288
- const sin = Math.sin(v);
289
- const cos = -Math.cos(v);
290
-
291
- // normal
292
-
293
- normal.x = (cos * N.x + sin * B.x);
294
- normal.y = (cos * N.y + sin * B.y);
295
- normal.z = (cos * N.z + sin * B.z);
296
- normal.normalize();
297
-
298
- normals.push(normal.x, normal.y, normal.z);
299
-
300
- // vertex
301
-
302
- vertex.x = P.x + radius * normal.x;
303
- vertex.y = P.y + radius * normal.y;
304
- vertex.z = P.z + radius * normal.z;
305
-
306
- vertices.push(vertex.x, vertex.y, vertex.z);
307
-
308
- }
309
-
310
- }
311
-
312
- function generateIndices() {
313
- let i = 0, j = 0;
314
-
315
- for (j = 1; j <= tubularSegments; j++) {
316
-
317
- for (i = 1; i <= radialSegments; i++) {
318
-
319
- const a = (radialSegments + 1) * (j - 1) + (i - 1);
320
- const b = (radialSegments + 1) * j + (i - 1);
321
- const c = (radialSegments + 1) * j + i;
322
- const d = (radialSegments + 1) * (j - 1) + i;
323
-
324
- // faces
325
-
326
- indices.push(a, b, d);
327
- indices.push(b, c, d);
328
-
329
- }
330
-
331
- }
332
-
333
- }
334
-
335
- function generateUVs() {
336
- let i = 0, j = 0;
337
-
338
- for (i = 0; i <= tubularSegments; i++) {
339
-
340
- const u = i / tubularSegments;
341
-
342
- for (j = 0; j <= radialSegments; j++) {
343
-
344
- const v = j / radialSegments;
345
-
346
- uvs.push(u, v);
347
-
348
- }
349
-
350
- }
351
-
352
- }
353
-
354
-
355
- return geometry;
356
- }
357
-
358
- /**
359
- *
360
- * @param {Path} path
361
- * @returns {number}
362
- */
363
- function estimatePathLength(path) {
364
-
365
- if (path.interpolation === InterpolationType.Linear) {
366
- return path.getLength();
367
- } else {
368
- return estimatePathViaIterativeIntegral(path, 0.01);
369
- }
370
-
371
- }
372
-
373
- /**
374
- *
375
- * @param {THREE.Vector3[]} points
376
- * @param {number} point_count
377
- * @param {TubePathStyle} style
378
- * @return {BufferGeometry}
379
- */
380
- function build_geometry_linear(points, point_count, style) {
381
-
382
- const frames = computeFrenetFrames(points, false);
383
-
384
- return makeTubeGeometry(points, frames.normals, frames.binormals, style.width, style.radial_resolution, false);
385
- }
386
-
387
- /**
388
- *
389
- * @param {THREE.Vector3[]} points
390
- * @param {number} point_count
391
- * @param {TubePathStyle} style
392
- * @return {BufferGeometry}
393
- */
394
- function build_geometry_catmullrom(points, point_count, style) {
395
-
396
- const path = new CatmullRomCurve3(points, false, "centripetal");
397
-
398
- return new TubeGeometry(path, style.resolution * point_count, style.width, style.radial_resolution, false);
399
-
400
- }
401
-
402
- export class TubePathBuilder {
403
- constructor() {
404
- /**
405
- *
406
- * @type {TubePathStyle|null}
407
- */
408
- this.style = null;
409
-
410
- /**
411
- *
412
- * @type {Path|null}
413
- */
414
- this.path = null;
415
-
416
- /**
417
- *
418
- * @type {MaterialManager|null}
419
- */
420
- this.materials = null;
421
-
422
- /**
423
- *
424
- * @type {AssetManager|null}
425
- */
426
- this.assetManager = null;
427
- }
428
-
429
- setPath(path) {
430
- this.path = path;
431
- }
432
-
433
- setStyle(style) {
434
- this.style = style;
435
- }
436
-
437
- setMaterials(m) {
438
- this.materials = m;
439
- }
440
-
441
- setAssetManager(assetManager) {
442
- this.assetManager = assetManager;
443
- }
444
-
445
- /**
446
- *
447
- * @param {EntityBuilder[]} destination
448
- */
449
- build(destination) {
450
- const style = this.style;
451
-
452
- // generate three.js curve from path
453
- const path_component = this.path;
454
-
455
- const three_points = [];
456
-
457
- const pointCount = path_component.getPointCount();
458
-
459
- if (pointCount < 2) {
460
- // no curve possible without at least 2 points
461
- return;
462
- }
463
-
464
- for (let i = 0; i < pointCount; i++) {
465
- const v3 = new Vector3();
466
-
467
- path_component.getPosition(i, v3);
468
-
469
- three_points.push(v3);
470
- }
471
-
472
-
473
- /**
474
- * @type {THREE.BufferGeometry}
475
- */
476
- let geometry;
477
-
478
- if (path_component.interpolation === InterpolationType.Linear) {
479
- geometry = build_geometry_linear(three_points, pointCount, style);
480
- } else if (path_component.interpolation === InterpolationType.CatmullRom) {
481
- geometry = build_geometry_catmullrom(three_points, pointCount, style);
482
- } else {
483
- throw new Error(`Unsupported interpolation type '${path_component.interpolation}'`);
484
- }
485
-
486
-
487
- let material_def;
488
-
489
- if (style.material_type === TubeMaterialType.Standard) {
490
- material_def = new MeshStandardMaterial({
491
- metalness: style.material.metalness,
492
- roughness: style.material.roughness
493
- });
494
- } else if (style.material_type === TubeMaterialType.Matcap) {
495
-
496
- material_def = new MeshMatcapMaterial();
497
-
498
- this.assetManager.get(style.material.texture, GameAssetType.Texture, asset => {
499
- material_def.matcap = asset.create();
500
-
501
- material_def.needsUpdate = true;
502
- }, console.error);
503
-
504
- } else {
505
- throw new Error(`Unsupported material type '${style.material_type}'`);
506
- }
507
-
508
- material_def.color.set(style.color.toUint());
509
-
510
- if (style.opacity < 1) {
511
- material_def.transparent = true;
512
- material_def.opacity = style.opacity;
513
- }
514
-
515
- const entityBuilder = new EntityBuilder();
516
-
517
- entityBuilder.add(new Transform());
518
- entityBuilder.add(new Renderable(ThreeFactory.createMesh(geometry, material_def)));
519
-
520
- destination.push(entityBuilder);
521
- }
522
- }