@woosh/meep-engine 2.33.22 → 2.33.23

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 (42) hide show
  1. package/core/bvh2/traversal/__detailed_box_volume_intersection.js +10 -7
  2. package/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +9 -1
  3. package/core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js +13 -14
  4. package/core/geom/3d/voxel/DenseBitVolume3D.js +87 -0
  5. package/core/geom/3d/voxel/buildVolumeFromProjectedGeometry.js +23 -0
  6. package/core/geom/Plane.js +14 -9
  7. package/core/primitives/array/computeIntegerArrayHash.js +1 -1
  8. package/engine/asset/loaders/material/computeImageBitmapEquality.js +11 -0
  9. package/engine/asset/loaders/material/computeImageBitmapHash.js +22 -28
  10. package/engine/ecs/util/hideEntityGracefully.js +18 -0
  11. package/engine/graphics/GraphicsEngine.js +0 -17
  12. package/engine/graphics/camera/testClippingPlaneComputation.js +2 -2
  13. package/engine/graphics/ecs/path/testPathDisplaySystem.js +98 -98
  14. package/engine/graphics/ecs/trail2d/Trail2D.js +17 -4
  15. package/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts +2 -3
  16. package/engine/graphics/ecs/trail2d/Trail2DSystem.js +34 -118
  17. package/engine/graphics/particles/particular/engine/ParticularEngine.js +4 -2
  18. package/engine/graphics/particles/particular/engine/emitter/PARTICULAR_PARTICLE_SPECIFICATION.js +20 -0
  19. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +40 -97
  20. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +12 -2
  21. package/engine/graphics/particles/particular/engine/emitter/computeEmissionFunction.js +37 -0
  22. package/engine/graphics/particles/particular/engine/emitter/distance_to_camera.js +25 -0
  23. package/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +2 -2
  24. package/engine/graphics/render/forward_plus/LightManager.js +10 -2
  25. package/engine/graphics/render/forward_plus/computeFrustumCorners.js +14 -32
  26. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
  27. package/engine/graphics/render/forward_plus/prototypeLightManager.js +96 -95
  28. package/engine/graphics/render/forward_plus/queryBVH_Frustum.js +17 -5
  29. package/engine/graphics/render/layers/RenderLayerUtils.js +7 -4
  30. package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +1 -1
  31. package/engine/graphics/texture/atlas/AtlasPatch.js +7 -2
  32. package/engine/graphics/texture/atlas/TextureAtlas.js +2 -2
  33. package/engine/graphics/texture/sampler/Sampler2D.js +8 -7
  34. package/engine/graphics/texture/sampler/scaleSampler2D.js +7 -10
  35. package/engine/graphics/trail/x/RibbonMaterialX.js +3 -3
  36. package/engine/graphics/trail/x/RibbonX.js +17 -2
  37. package/engine/graphics/trail/x/RibbonXPlugin.js +51 -1
  38. package/engine/grid/components/GridObstacle.js +2 -9
  39. package/engine/reference/v2/Reference.js +6 -0
  40. package/generation/theme/ThemeEngine.js +1 -1
  41. package/package.json +3 -3
  42. package/view/View.js +4 -2
@@ -98,10 +98,10 @@ function getFPStandard() {
98
98
  }
99
99
 
100
100
  const material_fp_standard = new FPlusStandardMaterial({
101
- color: 0xFFFF00,
102
- polygonOffset: true,
103
- depthWrite: false
104
- });
101
+ color: 0xFFFF00,
102
+ polygonOffset: true,
103
+ depthWrite: false
104
+ });
105
105
 
106
106
  fp_materials.push(material_fp_standard);
107
107
 
@@ -200,14 +200,14 @@ function addPointLight(position, radius, color, intensity = 1) {
200
200
  lm.addLight(light);
201
201
 
202
202
  const sphere_material = new LineBasicMaterial({
203
- depthTest: true,
204
- depthWrite: false,
205
- transparent: true,
206
- linewidth: 1,
207
- fog: false,
208
- color: light.color.toUint(),
209
- opacity: min2(intensity, 1)
210
- });
203
+ depthTest: true,
204
+ depthWrite: false,
205
+ transparent: true,
206
+ linewidth: 1,
207
+ fog: false,
208
+ color: light.color.toUint(),
209
+ opacity: min2(intensity, 1)
210
+ });
211
211
 
212
212
  const mesh = new Line(sphere_geometry, sphere_material);
213
213
 
@@ -233,39 +233,41 @@ function prepare_scene_0() {
233
233
 
234
234
  controls.minDistance = 2;
235
235
 
236
- for (let i = 0; i < 500; i++) {
237
- const radius = randomFloatBetween(random, 4, 4);
236
+ const bounds_size = 15;
237
+
238
+ for (let i = 0; i < 5000; i++) {
239
+ const radius = randomFloatBetween(random, 2, 2);
238
240
  const intensity = randomFloatBetween(random, 2, 2);
239
241
  addPointLight([
240
- randomFloatBetween(random, -20, 20),
241
- randomFloatBetween(random, -20, 20),
242
- randomFloatBetween(random, -20, 20),
243
- ],
244
- radius,
245
- `hsv(${random().toFixed(4)}, 0.8, 1)`,
246
- intensity
242
+ randomFloatBetween(random, -bounds_size, bounds_size),
243
+ randomFloatBetween(random, -bounds_size, bounds_size),
244
+ randomFloatBetween(random, -bounds_size, bounds_size),
245
+ ],
246
+ radius,
247
+ `hsv(${random().toFixed(4)}, 0.8, 1)`,
248
+ intensity
247
249
  );
248
250
  }
249
251
 
250
252
  for (let i = 0; i < 500; i++) {
251
253
 
252
254
  addKnot([
253
- randomFloatBetween(random, -20, 20),
254
- randomFloatBetween(random, -20, 20),
255
- randomFloatBetween(random, -20, 20)
256
- ], 0.5, [
257
- randomFloatBetween(random, 0, Math.PI),
258
- randomFloatBetween(random, 0, Math.PI),
259
- randomFloatBetween(random, 0, Math.PI)
260
- ]);
255
+ randomFloatBetween(random, -bounds_size, bounds_size),
256
+ randomFloatBetween(random, -bounds_size, bounds_size),
257
+ randomFloatBetween(random, -bounds_size, bounds_size)
258
+ ], 0.5, [
259
+ randomFloatBetween(random, 0, Math.PI),
260
+ randomFloatBetween(random, 0, Math.PI),
261
+ randomFloatBetween(random, 0, Math.PI)
262
+ ]);
261
263
  }
262
264
  }
263
265
 
264
266
  function prepare_scene_1() {
265
267
  addPointLight([
266
- 0, 0, -3
267
- ], 1,
268
- 0xFF0000
268
+ 0, 0, -3
269
+ ], 1,
270
+ 0xFF0000
269
271
  );
270
272
 
271
273
  // tight planes around the light
@@ -278,9 +280,9 @@ function prepare_scene_1() {
278
280
 
279
281
  function prepare_scene_3() {
280
282
  addPointLight([
281
- 0, 0, -4
282
- ], 1,
283
- 0xFF0000
283
+ 0, 0, -4
284
+ ], 1,
285
+ 0xFF0000
284
286
  );
285
287
 
286
288
  // tight planes around the light
@@ -288,8 +290,8 @@ function prepare_scene_3() {
288
290
  camera.far = 7;
289
291
 
290
292
  addKnot([
291
- 0, 0, -4
292
- ], 1, [0, 0, 0]);
293
+ 0, 0, -4
294
+ ], 1, [0, 0, 0]);
293
295
 
294
296
  // camera.position.set(0, 0, 0);
295
297
  camera.lookAt(0, 0, -5);
@@ -297,16 +299,16 @@ function prepare_scene_3() {
297
299
 
298
300
  function prepare_scene_2() {
299
301
  addPointLight([
300
- 1.5, 0, -4
301
- ], 1.5,
302
- 0xFF0000,
303
- 1
302
+ 1.5, 0, -4
303
+ ], 1.5,
304
+ 0xFF0000,
305
+ 1
304
306
  );
305
307
  addPointLight([
306
- -1.5, 0, -4
307
- ], 1.5,
308
- 0x00FF00,
309
- 1
308
+ -1.5, 0, -4
309
+ ], 1.5,
310
+ 0x00FF00,
311
+ 1
310
312
  );
311
313
 
312
314
  addKnot([0, 0, -5], 1, [0, 0, 0]);
@@ -324,16 +326,16 @@ function prepare_scene_5() {
324
326
 
325
327
 
326
328
  addPointLight([
327
- 1.5 + offset.x, 0 + offset.y, -4 + offset.z
328
- ], 1.5,
329
- 0xFF0000,
330
- 10
329
+ 1.5 + offset.x, 0 + offset.y, -4 + offset.z
330
+ ], 1.5,
331
+ 0xFF0000,
332
+ 10
331
333
  );
332
334
  addPointLight([
333
- -1.5 + offset.x, 0 + offset.y, -4 + offset.z
334
- ], 1.5,
335
- 0x00FF00,
336
- 10
335
+ -1.5 + offset.x, 0 + offset.y, -4 + offset.z
336
+ ], 1.5,
337
+ 0x00FF00,
338
+ 10
337
339
  );
338
340
 
339
341
  addKnot(
@@ -355,7 +357,6 @@ function prepare_scene_5() {
355
357
  }
356
358
 
357
359
 
358
-
359
360
  function addSponza() {
360
361
  const loader = new GLTFLoader();
361
362
 
@@ -420,13 +421,13 @@ function prepare_scene_4() {
420
421
  for (let i = 0; i < 2000; i++) {
421
422
  const radius = randomFloatBetween(random, 2, 2);
422
423
  addPointLight([
423
- randomFloatBetween(random, -18, 18),
424
- randomFloatBetween(random, -3, 16),
425
- randomFloatBetween(random, -11, 11),
426
- ],
427
- radius,
428
- `hsv(${random().toFixed(4)}, 0.8, 1)`,
429
- randomFloatBetween(random, 3, 3)
424
+ randomFloatBetween(random, -18, 18),
425
+ randomFloatBetween(random, -3, 16),
426
+ randomFloatBetween(random, -11, 11),
427
+ ],
428
+ radius,
429
+ `hsv(${random().toFixed(4)}, 0.8, 1)`,
430
+ randomFloatBetween(random, 3, 3)
430
431
  );
431
432
  }
432
433
 
@@ -460,13 +461,13 @@ function prepare_scene_6() {
460
461
 
461
462
 
462
463
  addPointLight([
463
- 11,
464
- 1,
465
- 0,
466
- ],
467
- 2,
468
- `hsv(0.5, 0.8, 1)`,
469
- 3
464
+ 11,
465
+ 1,
466
+ 0,
467
+ ],
468
+ 2,
469
+ `hsv(0.5, 0.8, 1)`,
470
+ 3
470
471
  );
471
472
 
472
473
  //
@@ -488,9 +489,9 @@ function prepare_scene_6() {
488
489
 
489
490
  function prepare_scene_7() {
490
491
  addSpotLight([
491
- 0, 0, -3
492
- ], [0, 0, 1],
493
- 0xFF0000
492
+ 0, 0, -3
493
+ ], [0, 0, 1],
494
+ 0xFF0000
494
495
  );
495
496
 
496
497
  // tight planes around the light
@@ -513,8 +514,8 @@ console.log("done");
513
514
 
514
515
 
515
516
  const renderer = new WebGLRenderer({
516
- antialias: true
517
- });
517
+ antialias: true
518
+ });
518
519
  // renderer.shadowMap.type = VSMShadowMap;
519
520
  // renderer.shadowMap.enabled = true;
520
521
  renderer.sortObjects = false;
@@ -679,32 +680,32 @@ renderer.domElement.addEventListener(MouseEvents.DoubleClick, () => {
679
680
  });
680
681
 
681
682
  domify(lightClusterWidget.domElement).css({
682
- position: "absolute",
683
- zIndex: 2,
684
- bottom: 0,
685
- right: 0
686
- });
683
+ position: "absolute",
684
+ zIndex: 2,
685
+ bottom: 0,
686
+ right: 0
687
+ });
687
688
 
688
689
  document.body.appendChild(lightClusterWidget.domElement);
689
690
 
690
691
  const debugger_button = new ButtonView({
691
- action() {
692
- if (screenGrid.domElement.parentNode !== null) {
693
- document.body.removeChild(screenGrid.domElement);
694
- } else {
695
- document.body.appendChild(screenGrid.domElement);
696
- }
697
- },
698
- name: "debugger",
699
- css: {
700
- position: "absolute",
701
- color: "white",
702
- background: "rgba(0,0,0,0.5)",
703
- zIndex: 2,
704
- top: 0,
705
- left: 0
706
- }
707
- });
692
+ action() {
693
+ if (screenGrid.domElement.parentNode !== null) {
694
+ document.body.removeChild(screenGrid.domElement);
695
+ } else {
696
+ document.body.appendChild(screenGrid.domElement);
697
+ }
698
+ },
699
+ name: "debugger",
700
+ css: {
701
+ position: "absolute",
702
+ color: "white",
703
+ background: "rgba(0,0,0,0.5)",
704
+ zIndex: 2,
705
+ top: 0,
706
+ left: 0
707
+ }
708
+ });
708
709
 
709
710
  debugger_button.link();
710
711
 
@@ -67,7 +67,11 @@ biplanar_edge_mapping[0b100010] = 5 | (7 << 3);
67
67
  * @param {number[]} points
68
68
  * @return {boolean}
69
69
  */
70
- function detailed_sphere_frustum_intersection_test(radius, light_x, light_y, light_z, outside_plane_count, outside_plane_bitfield, points) {
70
+ function detailed_sphere_frustum_intersection_test(
71
+ radius, light_x, light_y, light_z,
72
+ outside_plane_count, outside_plane_bitfield,
73
+ points
74
+ ) {
71
75
 
72
76
  const radius_sqr = radius * radius;
73
77
 
@@ -201,7 +205,11 @@ function point_light_inside_volume(light, points, planes) {
201
205
  if (outside_plane_count < 2) {
202
206
  return true;
203
207
  } else {
204
- return detailed_sphere_frustum_intersection_test(radius, light_x, light_y, light_z, outside_plane_count, outside_plane_bitfield, points);
208
+ return detailed_sphere_frustum_intersection_test(
209
+ radius, light_x, light_y, light_z,
210
+ outside_plane_count, outside_plane_bitfield,
211
+ points
212
+ );
205
213
  }
206
214
  }
207
215
 
@@ -246,7 +254,11 @@ function spot_light_inside_volume(light, points, planes) {
246
254
  * @param {number[]|Float32Array|Float64Array} points
247
255
  * @returns {number} number of items added to the destination, non-negative integer
248
256
  */
249
- export function queryBVH_Frustum(destination, destination_offset, root, planes, points) {
257
+ export function queryBVH_Frustum(
258
+ destination,
259
+ destination_offset,
260
+ root, planes, points
261
+ ) {
250
262
  let i = 0;
251
263
  let j = 0;
252
264
  // read out points
@@ -258,7 +270,7 @@ export function queryBVH_Frustum(destination, destination_offset, root, planes,
258
270
 
259
271
  stack_loop:while (stackPointer-- > stackOffset) {
260
272
 
261
- queryBVH_Frustum.iteration_count++;
273
+ // queryBVH_Frustum.iteration_count++;
262
274
 
263
275
  const n = stack[stackPointer];
264
276
 
@@ -282,7 +294,7 @@ export function queryBVH_Frustum(destination, destination_offset, root, planes,
282
294
  if (distanceAbovePlane < 0) {
283
295
  // node is below the plane
284
296
 
285
- queryBVH_Frustum.rejection_count++;
297
+ // queryBVH_Frustum.rejection_count++;
286
298
 
287
299
  continue stack_loop;
288
300
  }
@@ -1,4 +1,3 @@
1
- import Vector3 from "../../../../core/geom/Vector3.js";
2
1
  import { computePointDistanceToPlane } from "../../../../core/geom/Plane.js";
3
2
  import { plane_three_computeConvex3PlaneIntersection } from "../../../../core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js";
4
3
 
@@ -10,7 +9,11 @@ import { plane_three_computeConvex3PlaneIntersection } from "../../../../core/ge
10
9
  */
11
10
  export function buildPlanarRenderLayerClipPlaneComputationMethod(traversePlanes, bias = 0) {
12
11
 
13
- const p = new Vector3();
12
+ /**
13
+ *
14
+ * @type {number[]}
15
+ */
16
+ const p = [];
14
17
 
15
18
  const adjacentPlanePairs = [
16
19
  [],
@@ -38,7 +41,7 @@ export function buildPlanarRenderLayerClipPlaneComputationMethod(traversePlanes,
38
41
  const p0 = pair[0];
39
42
  const p1 = pair[1];
40
43
 
41
- const planeIntersection = plane_three_computeConvex3PlaneIntersection(p, p0, p1, objectPlane);
44
+ const planeIntersection = plane_three_computeConvex3PlaneIntersection(p, 0, p0, p1, objectPlane);
42
45
 
43
46
  if (!planeIntersection) {
44
47
  //no intersection
@@ -48,7 +51,7 @@ export function buildPlanarRenderLayerClipPlaneComputationMethod(traversePlanes,
48
51
 
49
52
  const plane_normal = nearPlane.normal;
50
53
 
51
- const distanceToNearPlane = computePointDistanceToPlane(p.x, p.y, p.z, plane_normal.x, plane_normal.y, plane_normal.z, nearPlane.constant);
54
+ const distanceToNearPlane = computePointDistanceToPlane(p[0], p[1], p[2], plane_normal.x, plane_normal.y, plane_normal.z, nearPlane.constant);
52
55
 
53
56
  //update near and far plane distances
54
57
  if (distanceToNearPlane > 0 && distanceToNearPlane < range.near) {
@@ -112,7 +112,7 @@ function makeConfig(engine) {
112
112
  new ClingToTerrainSystem(),
113
113
  new TerrainSystem(graphics, assetManager),
114
114
  new WaterSystem(graphics),
115
- new Trail2DSystem(graphics, assetManager),
115
+ new Trail2DSystem(engine),
116
116
  new Foliage2System(assetManager, graphics),
117
117
  new ViewportPositionSystem(graphics.viewport.size),
118
118
  new GridPosition2TransformSystem(),
@@ -5,12 +5,15 @@ import AABB2 from "../../../../core/geom/AABB2.js";
5
5
  export class AtlasPatch {
6
6
  constructor() {
7
7
  /**
8
- *
8
+ * Position in the atlas where the raw patch data is found, excludes padding
9
+ * @readonly
9
10
  * @type {Vector2}
10
11
  */
11
12
  this.position = new Vector2(0, 0);
13
+
12
14
  /**
13
- *
15
+ * Size in pixels of the patch, excludes padding
16
+ * @readonly
14
17
  * @type {Vector2}
15
18
  */
16
19
  this.size = new Vector2(0, 0);
@@ -34,11 +37,13 @@ export class AtlasPatch {
34
37
  this.sampler = null;
35
38
 
36
39
  /**
40
+ * @readonly
37
41
  * @type {Rectangle}
38
42
  */
39
43
  this.uv = new Rectangle(0, 0, 0, 0);
40
44
 
41
45
  /**
46
+ * Area in the atlas where patch along with the padding is packed into
42
47
  * Used for packing inside TextureAtlas. Do not modify manually
43
48
  * @readonly
44
49
  * @protected
@@ -82,8 +82,8 @@ export class TextureAtlas {
82
82
  * @returns {boolean}
83
83
  */
84
84
  contains(patch) {
85
- assert.notEqual(patch, null, 'patch is null');
86
- assert.notEqual(patch, undefined, 'patch is undefined');
85
+ assert.notNull(patch, 'patch');
86
+ assert.defined(patch, 'patch');
87
87
  assert.ok(patch.isAtlasPatch, 'patch argument is not an AtlasPatch');
88
88
 
89
89
  return this.patches.includes(patch);
@@ -493,7 +493,7 @@ Sampler2D.prototype.get = function (x, y, result) {
493
493
 
494
494
  const t = [];
495
495
 
496
- this.sampleBilinear(x, y, t);
496
+ this.sampleBilinear(x, y, t, 0);
497
497
 
498
498
  if (result !== undefined) {
499
499
  result.readFromArray(t, 0);
@@ -655,14 +655,15 @@ Sampler2D.prototype.sampleChannelBicubic = function (x, y, channel) {
655
655
  * @param {number} x
656
656
  * @param {number} y
657
657
  * @param {number[]} result
658
+ * @param {number} result_offset
658
659
  */
659
- Sampler2D.prototype.sampleBilinear = function (x, y, result) {
660
+ Sampler2D.prototype.sampleBilinear = function (x, y, result, result_offset) {
660
661
 
661
662
  const itemSize = this.itemSize;
662
663
 
663
664
  for (let i = 0; i < itemSize; i++) {
664
665
  //TODO this can be optimized greatly
665
- result[i] = this.sampleChannelBilinear(x, y, i);
666
+ result[i + result_offset] = this.sampleChannelBilinear(x, y, i);
666
667
 
667
668
  }
668
669
  };
@@ -809,7 +810,7 @@ Sampler2D.prototype.sample = function (u, v, result) {
809
810
 
810
811
  const temp = [];
811
812
 
812
- this.sampleBilinear(u * (this.width - 1), v * (this.height - 1), temp);
813
+ this.sampleBilinear(u * (this.width - 1), v * (this.height - 1), temp, 0);
813
814
 
814
815
  result.readFromArray(temp);
815
816
 
@@ -888,7 +889,7 @@ Sampler2D.prototype.makeArrayFiller = function (scale, offset) {
888
889
  }
889
890
 
890
891
  function fillDD2(index, array, x, y) {
891
- sampler.sampleBilinear(x, y, v4);
892
+ sampler.sampleBilinear(x, y, v4, 0);
892
893
  const val = (v4[0] + offset) * scale | 0;
893
894
  array.fill(val, index, index + 3);
894
895
  array[index + 3] = (v4[1] + offset) * scale | 0;
@@ -896,7 +897,7 @@ Sampler2D.prototype.makeArrayFiller = function (scale, offset) {
896
897
 
897
898
  function fillDD3(index, array, x, y) {
898
899
 
899
- sampler.sampleBilinear(x, y, v4);
900
+ sampler.sampleBilinear(x, y, v4, 0);
900
901
 
901
902
  array[index] = (v4[0] + offset) * scale | 0;
902
903
  array[index + 1] = (v4[1] + offset) * scale | 0;
@@ -905,7 +906,7 @@ Sampler2D.prototype.makeArrayFiller = function (scale, offset) {
905
906
  }
906
907
 
907
908
  function fillDD4(index, array, x, y) {
908
- sampler.sampleBilinear(x, y, v4);
909
+ sampler.sampleBilinear(x, y, v4, 0);
909
910
  array[index] = (v4[0] + offset) * scale | 0;
910
911
  array[index + 1] = (v4[1] + offset) * scale | 0;
911
912
  array[index + 2] = (v4[2] + offset) * scale | 0;
@@ -7,6 +7,7 @@ import { assert } from "../../../../core/assert.js";
7
7
  */
8
8
  export function scaleSampler2D(source, target) {
9
9
  const targetItemSize = target.itemSize;
10
+
10
11
  assert.equal(source.itemSize, targetItemSize, 'both source and target must have the same number of channels');
11
12
 
12
13
  const targetWidth = target.width;
@@ -18,32 +19,28 @@ export function scaleSampler2D(source, target) {
18
19
  const target_data = target.data;
19
20
 
20
21
  if (sourceWidth === targetWidth && sourceHeight === targetHeight) {
21
- // exact size match
22
+ // exact size match, nothing to do
22
23
  target_data.set(source.data);
23
24
  return;
24
25
  }
25
26
 
26
- const sample = [];
27
-
28
27
  const targetRowSize = targetItemSize * targetWidth;
29
28
 
29
+ const source_scale_x = sourceWidth / targetWidth;
30
+ const source_scale_y = sourceHeight / targetHeight;
31
+
30
32
  for (let y = 0; y < targetHeight; y++) {
31
33
 
32
- const v = y / targetHeight;
33
34
 
35
+ const sample_y = y * source_scale_y;
34
36
  const target_row_address = y * targetRowSize;
35
37
 
36
38
  for (let x = 0; x < targetWidth; x++) {
37
39
 
38
- const u = x / targetWidth;
39
-
40
- source.sampleBilinear(u * sourceWidth, v * sourceHeight, sample);
41
40
 
42
41
  const target_offset = target_row_address + x * targetItemSize;
43
42
 
44
- for (let i = 0; i < targetItemSize; i++) {
45
- target_data[target_offset + i] = sample[i];
46
- }
43
+ source.sampleBilinear(x * source_scale_x, sample_y, target_data, target_offset);
47
44
 
48
45
  }
49
46
  }
@@ -106,11 +106,11 @@ export class RibbonMaterialX extends ShaderMaterial {
106
106
  uDiffuse: {
107
107
  type: 't',
108
108
  value: null
109
- },
110
- defines: {
111
- USE_TEXTURE: false
112
109
  }
113
110
  },
111
+ defines: {
112
+ USE_TEXTURE: false
113
+ },
114
114
  blending: NormalBlending,
115
115
  transparent: true,
116
116
  depthWrite: false,
@@ -36,7 +36,6 @@ export class RibbonX {
36
36
  */
37
37
  this.__data = new RowFirstTable(ribbon_attributes_spec);
38
38
 
39
-
40
39
  /**
41
40
  * Index into current geometry segment that is at the END of the ribbon
42
41
  * @type {number}
@@ -66,6 +65,10 @@ export class RibbonX {
66
65
  this.__count = 0;
67
66
  }
68
67
 
68
+ dispose() {
69
+ this.__geometry.dispose();
70
+ }
71
+
69
72
  /**
70
73
  *
71
74
  * @returns {BufferGeometry}
@@ -350,6 +353,11 @@ export class RibbonX {
350
353
  this.setPointAttribute_Vector3(index, RIBBON_ATTRIBUTE_ADDRESS_COLOR, r, g, b);
351
354
  }
352
355
 
356
+ /**
357
+ *
358
+ * @param {number} index
359
+ * @param {number} value
360
+ */
353
361
  setPointAlpha(index, value) {
354
362
  const i2 = index * 2;
355
363
 
@@ -359,7 +367,11 @@ export class RibbonX {
359
367
  this.__ib_float32.needsUpdate = true;
360
368
  }
361
369
 
362
-
370
+ /**
371
+ *
372
+ * @param {number} index
373
+ * @param {number} value
374
+ */
363
375
  setPointThickness(index, value) {
364
376
  const i2 = index * 2;
365
377
 
@@ -377,6 +389,9 @@ export class RibbonX {
377
389
  assert.greaterThanOrEqual(count, 2, 'number of points in the ribbon must be at least 2 (to produce at least a single quad)');
378
390
  assert.isNonNegativeInteger(count, 'count');
379
391
 
392
+ // dispose of existing geometry
393
+ this.__geometry.dispose();
394
+
380
395
  const point_count = count * 2;
381
396
 
382
397
  if (this.__data.length > point_count) {