@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
@@ -3,6 +3,7 @@
3
3
  * @enum {boolean}
4
4
  */
5
5
  import { assert } from "../assert.js";
6
+ import { array_copy } from "../collection/array/copyArray.js";
6
7
 
7
8
  /**
8
9
  *
@@ -30,17 +31,50 @@ function BinaryBuffer() {
30
31
  */
31
32
  this.endianness = EndianType.BigEndian;
32
33
 
34
+ /**
35
+ *
36
+ * @type {number}
37
+ */
33
38
  this.position = 0;
39
+
40
+ /**
41
+ *
42
+ * @type {number}
43
+ */
34
44
  this.length = 0;
45
+
46
+ /**
47
+ *
48
+ * @type {number}
49
+ */
35
50
  this.capacity = 0;
36
51
 
37
52
  /**
38
53
  *
39
54
  * @type {ArrayBuffer}
55
+ * @private
40
56
  */
41
57
  this.data = new ArrayBuffer(0);
58
+
59
+ /**
60
+ *
61
+ * @type {DataView}
62
+ * @private
63
+ */
42
64
  this.dataView = new DataView(this.data);
43
65
 
66
+ /**
67
+ *
68
+ * @type {Uint8Array}
69
+ * @private
70
+ */
71
+ this.__data_uint8 = new Uint8Array(0);
72
+
73
+ /**
74
+ *
75
+ * @type {number}
76
+ * @private
77
+ */
44
78
  this.__growFactor = 1.1;
45
79
  }
46
80
 
@@ -50,6 +84,7 @@ function BinaryBuffer() {
50
84
  BinaryBuffer.prototype.fromArrayBuffer = function (arrayBuffer) {
51
85
  this.data = arrayBuffer;
52
86
  this.dataView = new DataView(arrayBuffer);
87
+ this.__data_uint8 = new Uint8Array(arrayBuffer);
53
88
 
54
89
  this.capacity = arrayBuffer.byteLength;
55
90
  //assume that all the data is useful
@@ -85,7 +120,7 @@ BinaryBuffer.prototype.trim = function () {
85
120
  * @param {number} capacity
86
121
  */
87
122
  BinaryBuffer.prototype.setCapacity = function (capacity) {
88
- const oldData = new Uint8Array(this.data);
123
+ const oldData = this.__data_uint8;
89
124
  const newData = new Uint8Array(capacity);
90
125
 
91
126
  //copy old data
@@ -93,7 +128,7 @@ BinaryBuffer.prototype.setCapacity = function (capacity) {
93
128
  newData.set(oldData.subarray(0, copyLength), 0);
94
129
 
95
130
  this.data = newData.buffer;
96
-
131
+ this.__data_uint8 = newData;
97
132
  this.dataView = new DataView(this.data);
98
133
 
99
134
  this.capacity = capacity;
@@ -680,11 +715,11 @@ BinaryBuffer.prototype.writeUint32LE = function (value) {
680
715
  /**
681
716
  *
682
717
  * @param {Uint8Array|Uint8ClampedArray} array
683
- * @param {number} sourceOffset
718
+ * @param {number} source_offset
684
719
  * @param {number} length
685
720
  */
686
- BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
687
- const source_end = sourceOffset + length;
721
+ BinaryBuffer.prototype.writeBytes = function (array, source_offset, length) {
722
+ const source_end = source_offset + length;
688
723
  assert.greaterThanOrEqual(array.length, source_end, 'source array underflow');
689
724
 
690
725
  const targetAddress = this.position;
@@ -693,18 +728,21 @@ BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
693
728
 
694
729
  this.ensureCapacity(end);
695
730
 
696
- const destination = new Uint8Array(this.data, targetAddress, length);
731
+ if (source_offset === 0 && array.length === length) {
732
+ // copying entire source array
697
733
 
698
- if (typeof array.subarray === "function") {
734
+ this.__data_uint8.set(array, targetAddress);
735
+
736
+ } else if (typeof array.subarray === "function") {
699
737
  // typed array, use "subarray" method
700
738
 
701
- destination.set(array.subarray(sourceOffset, source_end));
739
+ this.__data_uint8.set(array.subarray(source_offset, source_end), targetAddress);
702
740
 
703
741
  } else {
704
742
  // not a typed array, copy byte by byte manually
705
743
 
706
744
  for (let i = 0; i < length; i++) {
707
- destination[i] = array[sourceOffset + i];
745
+ this.__data_uint8[targetAddress + i] = array[source_offset + i];
708
746
  }
709
747
 
710
748
  }
@@ -714,14 +752,23 @@ BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
714
752
 
715
753
  /**
716
754
  *
717
- * @param {Uint8Array} target
718
- * @param {number} targetOffset
755
+ * @param {Uint8Array} destination
756
+ * @param {number} destination_offset
719
757
  * @param {number} length
720
758
  */
721
- BinaryBuffer.prototype.readBytes = function (target, targetOffset, length) {
722
- const end = this.position + length;
723
- const uint8Array = new Uint8Array(this.data);
724
- target.set(uint8Array.subarray(this.position, end), targetOffset);
759
+ BinaryBuffer.prototype.readBytes = function (destination, destination_offset, length) {
760
+ const source_position = this.position;
761
+
762
+ const end = source_position + length;
763
+
764
+ const uint8 = this.__data_uint8;
765
+
766
+ if (length < 128) {
767
+ // small copy
768
+ array_copy(uint8, source_position, destination, destination_offset, length);
769
+ } else {
770
+ destination.set(uint8.subarray(source_position, end), destination_offset);
771
+ }
725
772
 
726
773
  this.position = end;
727
774
  };
@@ -764,7 +811,7 @@ BinaryBuffer.prototype.writeUTF8String = function (string) {
764
811
 
765
812
  this.ensureCapacity(tlen + at);
766
813
 
767
- let target = new Uint8Array(this.data); // ... but at 8 byte offset
814
+ let target = this.__data_uint8; // ... but at 8 byte offset
768
815
 
769
816
 
770
817
  while (pos < len) {
@@ -791,7 +838,7 @@ BinaryBuffer.prototype.writeUTF8String = function (string) {
791
838
 
792
839
  this.ensureCapacity(tlen + startPosition);
793
840
 
794
- target = new Uint8Array(this.data);
841
+ target = this.__data_uint8;
795
842
  }
796
843
 
797
844
  if ((value & 0xffffff80) === 0) { // 1-byte
@@ -851,7 +898,7 @@ BinaryBuffer.prototype.readUTF8String = function () {
851
898
  return undefined;
852
899
  }
853
900
 
854
- const bytes = new Uint8Array(this.data);
901
+ const bytes = this.__data_uint8;
855
902
 
856
903
 
857
904
  let result = "";
@@ -9,6 +9,9 @@ export class Camera {
9
9
 
10
10
  autoClip: boolean
11
11
 
12
+ clip_near: number
13
+ clip_far: number
14
+
12
15
  computeProjectionMatrix(result: Matrix4): boolean
13
16
 
14
17
  projectWorldPointOntoNearPlane(x: number, y: number, z: number, result: Vector3): void
@@ -26,7 +26,7 @@ export const ProjectionType = {
26
26
  export class Camera {
27
27
  constructor() {
28
28
  /**
29
- *
29
+ * Whether clipping planes should be automatically calculated or not
30
30
  * @type {boolean}
31
31
  */
32
32
  this.autoClip = true;
@@ -56,6 +56,44 @@ export class Camera {
56
56
  * @type {ObservedBoolean}
57
57
  */
58
58
  this.active = new ObservedBoolean(false);
59
+
60
+ /**
61
+ * Near clipping plane
62
+ * @type {number}
63
+ * @private
64
+ */
65
+ this.__clip_far = 100;
66
+
67
+ /**
68
+ * Far clipping plane
69
+ * @type {number}
70
+ * @private
71
+ */
72
+ this.__clip_near = 0.1;
73
+ }
74
+
75
+ get clip_far() {
76
+ return this.__clip_far;
77
+ }
78
+
79
+ set clip_far(v) {
80
+ this.__clip_far = v;
81
+
82
+ if (this.object !== null) {
83
+ this.object.far = v;
84
+ }
85
+ }
86
+
87
+ get clip_near() {
88
+ return this.__clip_near;
89
+ }
90
+
91
+ set clip_near(v) {
92
+ this.__clip_near = v;
93
+
94
+ if (this.object !== null) {
95
+ this.object.near = v;
96
+ }
59
97
  }
60
98
 
61
99
  updateMatrices() {
@@ -9,7 +9,6 @@ import { Transform } from '../../../ecs/transform/Transform.js';
9
9
  import {
10
10
  Frustum as ThreeFrustum,
11
11
  Matrix4,
12
- Matrix4 as ThreeMatrix4,
13
12
  OrthographicCamera as ThreeOrthographicCamera,
14
13
  PerspectiveCamera as ThreePerspectiveCamera,
15
14
  Vector3 as ThreeVector3,
@@ -76,16 +75,25 @@ function setAspectRatio(camera, width, height) {
76
75
  * @returns {PerspectiveCamera| OrthographicCamera}
77
76
  */
78
77
  function buildThreeCamera(component) {
78
+
79
+ let result;
79
80
  switch (component.projectionType.getValue()) {
80
81
  default:
81
82
  console.error(`Unsupported camera projection type "${component.projectionType.getValue()}", defaulting to perspective projection`);
82
83
  //fallthrough
83
84
  case Camera.ProjectionType.Perspective:
84
- return new ThreePerspectiveCamera(component.fov.getValue(), 1, 1, 50);
85
-
85
+ result = new ThreePerspectiveCamera(component.fov.getValue(), 1, 1, 50);
86
+ break;
86
87
  case Camera.ProjectionType.Orthographic:
87
- return new ThreeOrthographicCamera(-10, 10, 20, -20, 1, 1);
88
+ result = new ThreeOrthographicCamera(-10, 10, 20, -20, 1, 1);
89
+ break;
88
90
  }
91
+
92
+
93
+ result.far = component.clip_far;
94
+ result.near = component.clip_near;
95
+
96
+ return result;
89
97
  }
90
98
 
91
99
  export class CameraSystem extends System {
@@ -289,8 +297,19 @@ export class CameraSystem extends System {
289
297
  * @param {Camera} c
290
298
  */
291
299
  function visitCameraEntity(c) {
292
- if (c.active.getValue() && c.autoClip && c.object !== null) {
300
+ if (c.object === null) {
301
+ return;
302
+ }
303
+
304
+ if (!c.active.getValue()) {
305
+ return;
306
+ }
307
+
308
+ if (c.autoClip === true) {
293
309
  autoSetClippingPlanes(c, layers);
310
+ } else {
311
+ c.object.far = c.clip_far;
312
+ c.object.near = c.clip_near;
294
313
  }
295
314
  }
296
315
 
@@ -376,7 +395,7 @@ export class CameraSystem extends System {
376
395
  }
377
396
  }
378
397
 
379
- const matrix4 = new ThreeMatrix4();
398
+ const matrix4 = new Matrix4();
380
399
 
381
400
  /**
382
401
  *
@@ -313,13 +313,19 @@ export class ShadedGeometrySystem extends System {
313
313
  const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
314
314
  const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
315
315
  const local_direction_z = scratch_m4[2] * direction_x + scratch_m4[6] * direction_y + scratch_m4[10] * direction_z;
316
- // NOTE: direction is not normalized
316
+
317
+ const local_direction_magnitude = Math.hypot(local_direction_x, local_direction_y, local_direction_z);
318
+ const local_direction_magnitude_inverse = 1 / local_direction_magnitude;
319
+
320
+ const local_direction_normalized_x = local_direction_x * local_direction_magnitude_inverse;
321
+ const local_direction_normalized_y = local_direction_y * local_direction_magnitude_inverse;
322
+ const local_direction_normalized_z = local_direction_z * local_direction_magnitude_inverse;
317
323
 
318
324
  const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_primitive(
319
325
  scratch_point,
320
326
  sg.geometry,
321
327
  local_origin_x, local_origin_y, local_origin_z,
322
- local_direction_x, local_direction_y, local_direction_z
328
+ local_direction_normalized_x, local_direction_normalized_y, local_direction_normalized_z
323
329
  );
324
330
 
325
331
  if (!geometry_hit_found) {
@@ -20,6 +20,9 @@ import { randomFromArray } from "../../../../../core/math/random/randomFromArray
20
20
  import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
21
21
  import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
22
22
  import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
23
+ import { MicronShadedGeometryRenderAdapter } from "../../../micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js";
24
+ import { MicronRenderContext } from "../../../micron/render/v1/MicronRenderContext.js";
25
+ import { randomIntegerBetween } from "../../../../../core/math/random/randomIntegerBetween.js";
23
26
 
24
27
  const eh = new EngineHarness();
25
28
 
@@ -50,7 +53,17 @@ async function main(engine) {
50
53
 
51
54
  const em = engine.entityManager;
52
55
 
53
- await em.addSystem(new ShadedGeometrySystem(engine));
56
+ const sgs = new ShadedGeometrySystem(engine);
57
+
58
+ const mrc = new MicronRenderContext();
59
+ sgs.register_render_adapter(2, () => {
60
+ const adapter = new MicronShadedGeometryRenderAdapter();
61
+ adapter.ctx = mrc;
62
+
63
+ return adapter;
64
+ });
65
+
66
+ await em.addSystem(sgs);
54
67
  await em.addSystem(new BehaviorSystem(engine));
55
68
 
56
69
  EngineHarness.buildBasics({
@@ -74,7 +87,7 @@ async function main(engine) {
74
87
 
75
88
  const random = seededRandom(0);
76
89
 
77
- const INSTANCE_COUNT = 0;
90
+ const INSTANCE_COUNT = 10000;
78
91
 
79
92
  const geometries = [];
80
93
 
@@ -87,7 +100,9 @@ async function main(engine) {
87
100
  const sg = ShadedGeometry.from(geometry, material);
88
101
 
89
102
  // sg.draw_method = DRAW_METHOD_PLAIN;
90
- sg.draw_method = DRAW_METHOD_INSTANCED;
103
+ // sg.draw_method = DRAW_METHOD_INSTANCED;
104
+ // sg.draw_method = 2;
105
+ sg.draw_method = randomIntegerBetween(random, 0, 2);
91
106
  // sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
92
107
  sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
93
108
 
@@ -105,7 +120,7 @@ async function main(engine) {
105
120
  .build(ecd);
106
121
  }
107
122
 
108
- makeMovingShadedGeometry().build(ecd);
123
+ // makeMovingShadedGeometry().build(ecd);
109
124
 
110
125
  debug_button(engine, () => {
111
126
  const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
@@ -10,7 +10,7 @@ import { RibbonXPlugin } from "../../trail/x/RibbonXPlugin.js";
10
10
  import { RibbonPathBuilder } from "./ribbon/RibbonPathBuilder.js";
11
11
  import { PathEvents } from "../../../navigation/ecs/components/PathEvents.js";
12
12
  import { assert } from "../../../../core/assert.js";
13
- import { TubePathBuilder } from "./tube/TubePathBuilder.js";
13
+ import { TubePathBuilder } from "./tube/build/TubePathBuilder.js";
14
14
 
15
15
  const builders = {
16
16
  [PathDisplayType.None]: function (style, path, result) {
@@ -1,5 +1,4 @@
1
1
  import { EngineHarness } from "../../../EngineHarness.js";
2
- import RenderSystem from "../../../ecs/systems/RenderSystem.js";
3
2
  import { makeEngineOptionsModel } from "../../../../../model/game/options/makeEngineOptionsModel.js";
4
3
  import Path from "../../../navigation/ecs/components/Path.js";
5
4
  import Vector3 from "../../../../core/geom/Vector3.js";
@@ -68,6 +67,7 @@ import { TubePathStyle } from "./tube/TubePathStyle.js";
68
67
  import { TubeMaterialType } from "./tube/TubeMaterialType.js";
69
68
  import { MatcapMaterialDefinition } from "./tube/MatcapMaterialDefinition.js";
70
69
  import { TextureAssetLoader } from "../../../asset/loaders/texture/TextureAssetLoader.js";
70
+ import { ShadedGeometrySystem } from "../mesh-v2/ShadedGeometrySystem.js";
71
71
 
72
72
  const engineHarness = new EngineHarness();
73
73
 
@@ -156,7 +156,8 @@ function makeConfig(engine) {
156
156
  async function init(harness) {
157
157
  const engine = harness.engine;
158
158
 
159
- engine.entityManager.addSystem(new RenderSystem(engine.graphics));
159
+ // engine.entityManager.addSystem(new RenderSystem(engine.graphics));
160
+ engine.entityManager.addSystem(new ShadedGeometrySystem(engine));
160
161
 
161
162
  makeEngineOptionsModel(engine.options, engine);
162
163
 
@@ -323,8 +324,8 @@ function main(engine) {
323
324
  EngineHarness.buildBasics({ engine });
324
325
 
325
326
  const _p = new Path();
326
- // _p.interpolation = InterpolationType.CatmullRom;
327
- _p.interpolation = InterpolationType.Linear;
327
+ _p.interpolation = InterpolationType.CatmullRom;
328
+ // _p.interpolation = InterpolationType.Linear;
328
329
 
329
330
  // _p.setPositionsFromVectorArray(Path.smoothPath([
330
331
  // new Vector3(3, 1, 1),
@@ -352,14 +353,14 @@ function main(engine) {
352
353
 
353
354
  const pathDisplay = new PathDisplay();
354
355
  pathDisplay.specs.push(
355
- // PathDisplaySpec.from(
356
- // PathDisplayType.Ribbon,
357
- // trailPathStyle
358
- // ),
359
- // PathDisplaySpec.from(
360
- // PathDisplayType.Entity,
361
- // sample_style_entity()
362
- // ),
356
+ PathDisplaySpec.from(
357
+ PathDisplayType.Ribbon,
358
+ trailPathStyle
359
+ ),
360
+ PathDisplaySpec.from(
361
+ PathDisplayType.Entity,
362
+ sample_style_entity()
363
+ ),
363
364
  PathDisplaySpec.from(
364
365
  PathDisplayType.Tube,
365
366
  sample_style_tube()
@@ -11,4 +11,6 @@ export class TubePathStyle {
11
11
  public width: number
12
12
  public resolution: number
13
13
  public radial_resolution: number
14
+ public cast_shadow: boolean
15
+ public receive_shadow: boolean
14
16
  }
@@ -5,8 +5,15 @@ import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
5
5
 
6
6
  export class TubePathStyle {
7
7
  constructor() {
8
+ /**
9
+ *
10
+ * @type {Color}
11
+ */
8
12
  this.color = new Color(1, 1, 1);
9
13
 
14
+ /**
15
+ * @type {TubeMaterialType}
16
+ */
10
17
  this.material_type = TubeMaterialType.Unknown;
11
18
 
12
19
  /**
@@ -15,13 +22,43 @@ export class TubePathStyle {
15
22
  */
16
23
  this.material = null;
17
24
 
25
+ /**
26
+ *
27
+ * @type {number}
28
+ */
18
29
  this.opacity = 1;
30
+
31
+ /**
32
+ *
33
+ * @type {number}
34
+ */
19
35
  this.width = 1;
20
36
 
21
37
  // TODO expose shading style "flat/smooth"
22
38
 
39
+ /**
40
+ *
41
+ * @type {number}
42
+ */
23
43
  this.resolution = 10;
44
+
45
+ /**
46
+ *
47
+ * @type {number}
48
+ */
24
49
  this.radial_resolution = 16;
50
+
51
+ /**
52
+ *
53
+ * @type {boolean}
54
+ */
55
+ this.cast_shadow = false;
56
+
57
+ /**
58
+ *
59
+ * @type {boolean}
60
+ */
61
+ this.receive_shadow = false;
25
62
  }
26
63
 
27
64
  static fromJSON(j) {
@@ -39,7 +76,9 @@ export class TubePathStyle {
39
76
  opacity = 1,
40
77
  width = 1,
41
78
  resolution = 10,
42
- radial_resolution = 16
79
+ radial_resolution = 16,
80
+ cast_shadow = false,
81
+ receive_shadow = false
43
82
  }) {
44
83
  assert.enum(material_type, TubeMaterialType, 'material_type');
45
84
 
@@ -55,6 +94,9 @@ export class TubePathStyle {
55
94
  this.resolution = resolution;
56
95
  this.radial_resolution = radial_resolution;
57
96
 
97
+ this.cast_shadow = cast_shadow;
98
+ this.receive_shadow = receive_shadow;
99
+
58
100
  switch (material_type) {
59
101
  case TubeMaterialType.Matcap:
60
102
  this.material = new MatcapMaterialDefinition();
@@ -0,0 +1,138 @@
1
+ import { BufferGeometry, MeshMatcapMaterial, MeshStandardMaterial, Vector3 } from "three";
2
+ import { InterpolationType } from "../../../../../navigation/ecs/components/InterpolationType.js";
3
+ import EntityBuilder from "../../../../../ecs/EntityBuilder.js";
4
+ import { Transform } from "../../../../../ecs/transform/Transform.js";
5
+ import { TubeMaterialType } from "../TubeMaterialType.js";
6
+ import { GameAssetType } from "../../../../../asset/GameAssetType.js";
7
+ import { build_geometry_linear } from "./build_geometry_linear.js";
8
+ import { build_geometry_catmullrom } from "./build_geometry_catmullrom.js";
9
+ import { ShadedGeometry } from "../../../mesh-v2/ShadedGeometry.js";
10
+ import { ShadedGeometryFlags } from "../../../mesh-v2/ShadedGeometryFlags.js";
11
+
12
+ export class TubePathBuilder {
13
+ constructor() {
14
+ /**
15
+ *
16
+ * @type {TubePathStyle|null}
17
+ */
18
+ this.style = null;
19
+
20
+ /**
21
+ *
22
+ * @type {Path|null}
23
+ */
24
+ this.path = null;
25
+
26
+ /**
27
+ *
28
+ * @type {MaterialManager|null}
29
+ */
30
+ this.materials = null;
31
+
32
+ /**
33
+ *
34
+ * @type {AssetManager|null}
35
+ */
36
+ this.assetManager = null;
37
+ }
38
+
39
+ setPath(path) {
40
+ this.path = path;
41
+ }
42
+
43
+ setStyle(style) {
44
+ this.style = style;
45
+ }
46
+
47
+ setMaterials(m) {
48
+ this.materials = m;
49
+ }
50
+
51
+ setAssetManager(assetManager) {
52
+ this.assetManager = assetManager;
53
+ }
54
+
55
+ /**
56
+ *
57
+ * @param {EntityBuilder[]} destination
58
+ */
59
+ build(destination) {
60
+ const style = this.style;
61
+
62
+ // generate three.js curve from path
63
+ const path_component = this.path;
64
+
65
+ const three_points = [];
66
+
67
+ const pointCount = path_component.getPointCount();
68
+
69
+ if (pointCount < 2) {
70
+ // no curve possible without at least 2 points
71
+ return;
72
+ }
73
+
74
+ for (let i = 0; i < pointCount; i++) {
75
+ const v3 = new Vector3();
76
+
77
+ path_component.getPosition(i, v3);
78
+
79
+ three_points.push(v3);
80
+ }
81
+
82
+
83
+ /**
84
+ * @type {THREE.BufferGeometry}
85
+ */
86
+ let geometry;
87
+
88
+ if (path_component.interpolation === InterpolationType.Linear) {
89
+ geometry = build_geometry_linear(three_points, pointCount, style);
90
+ } else if (path_component.interpolation === InterpolationType.CatmullRom) {
91
+ geometry = build_geometry_catmullrom(three_points, pointCount, style);
92
+ } else {
93
+ throw new Error(`Unsupported interpolation type '${path_component.interpolation}'`);
94
+ }
95
+
96
+
97
+ let material_def;
98
+
99
+ if (style.material_type === TubeMaterialType.Standard) {
100
+ material_def = new MeshStandardMaterial({
101
+ metalness: style.material.metalness,
102
+ roughness: style.material.roughness
103
+ });
104
+ } else if (style.material_type === TubeMaterialType.Matcap) {
105
+
106
+ material_def = new MeshMatcapMaterial();
107
+
108
+ this.assetManager.get(style.material.texture, GameAssetType.Texture, asset => {
109
+ material_def.matcap = asset.create();
110
+
111
+ material_def.needsUpdate = true;
112
+ }, console.error);
113
+
114
+ } else {
115
+ throw new Error(`Unsupported material type '${style.material_type}'`);
116
+ }
117
+
118
+ material_def.color.set(style.color.toUint());
119
+
120
+ if (style.opacity < 1) {
121
+ material_def.transparent = true;
122
+ material_def.opacity = style.opacity;
123
+ }
124
+
125
+ const entityBuilder = new EntityBuilder();
126
+
127
+ entityBuilder.add(new Transform());
128
+
129
+ const shaded_geometry = ShadedGeometry.from(geometry, material_def);
130
+
131
+ shaded_geometry.writeFlag(ShadedGeometryFlags.CastShadow, style.cast_shadow);
132
+ shaded_geometry.writeFlag(ShadedGeometryFlags.ReceiveShadow, style.receive_shadow);
133
+
134
+ entityBuilder.add(shaded_geometry);
135
+
136
+ destination.push(entityBuilder);
137
+ }
138
+ }