@woosh/meep-engine 2.35.9 → 2.35.13

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 +38 -3
  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 +19 -12
  9. package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +3 -0
  10. package/engine/graphics/ecs/path/tube/TubePathStyle.js +71 -2
  11. package/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +160 -0
  12. package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +61 -0
  13. package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +56 -0
  14. package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +165 -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 +161 -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/navigation/ecs/components/Path.js +5 -6
  27. package/package.json +1 -1
  28. package/engine/graphics/ecs/path/tube/TubePathBuilder.js +0 -522
@@ -1,6 +1,8 @@
1
1
  import { AbstractRenderAdapter } from "../../../ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js";
2
2
  import Vector2 from "../../../../../core/geom/Vector2.js";
3
- import { MaterialVertexSpec } from "../../render/v1/MaterialVertexSpec.js";
3
+ import { buildMicronGeometryFromBufferGeometry } from "../../build/buildMicronGeometryFromBufferGeometry.js";
4
+ import { ShadedGeometryFlags } from "../../../ecs/mesh-v2/ShadedGeometryFlags.js";
5
+ import { MaterialVertexSpec, MaterialVertexSpecFlags } from "../../render/v1/MaterialVertexSpec.js";
4
6
 
5
7
  /**
6
8
  *
@@ -8,35 +10,16 @@ import { MaterialVertexSpec } from "../../render/v1/MaterialVertexSpec.js";
8
10
  */
9
11
  const scratch_mvc = new MaterialVertexSpec();
10
12
 
11
- class MicronRenderContext {
12
-
13
- }
14
-
15
13
  export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
16
- constructor({
17
- vgtr
18
- }) {
19
- super();
20
-
21
- /**
22
- * @type {VGThreeRenderer}
23
- * @private
24
- */
25
- this.__vgtr = vgtr;
26
14
 
27
- /**
28
- *
29
- * @type {VirtualGeometry|null}
30
- * @private
31
- */
32
- this.__vg = null;
15
+ constructor() {
16
+ super();
33
17
 
34
18
  /**
35
19
  *
36
- * @type {VirtualGeometryBuilder|null}
37
- * @private
20
+ * @type {MicronRenderContext|null}
38
21
  */
39
- this.__vgb = null;
22
+ this.ctx = null;
40
23
 
41
24
  /**
42
25
  *
@@ -47,18 +30,41 @@ export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
47
30
 
48
31
  /**
49
32
  *
50
- * @type {Set<MaterialContext>}
33
+ * @type {Map<number, Promise>}
51
34
  * @private
52
35
  */
53
- this.__active_contexts = new Set();
36
+ this.__geometry_building_promises = new Map();
54
37
  }
55
38
 
56
39
  add(sg) {
57
40
 
58
- const micron_geometry = this.__geometry_map.get(sg.geometry.id);
41
+ const geometry_id = sg.geometry.id;
42
+
43
+ const micron_geometry = this.__geometry_map.get(geometry_id);
44
+
45
+ if (micron_geometry === undefined) {
46
+ // no micron geometry
47
+ if (!this.__geometry_building_promises.has(geometry_id)) {
48
+ const p = buildMicronGeometryFromBufferGeometry(sg.geometry);
49
+
50
+ this.__geometry_building_promises.set(geometry_id, p);
51
+
52
+ p.then(mg => this.__geometry_map.set(geometry_id, mg));
53
+ }
54
+ return;
55
+ }
59
56
 
60
57
  // populate virtual geometry for this instance
61
- this.__vgb.buildForMesh(sg.entity, micron_geometry, sg.transform);
58
+ this.ctx.builder.buildForMesh(sg.entity, micron_geometry, sg.transform);
59
+
60
+ scratch_mvc.material = sg.material;
61
+ scratch_mvc.spec = micron_geometry.vertex_spec;
62
+ scratch_mvc.writeFlag(MaterialVertexSpecFlags.CastShadow, sg.getFlag(ShadedGeometryFlags.CastShadow));
63
+ scratch_mvc.writeFlag(MaterialVertexSpecFlags.ReceiveShadow, sg.getFlag(ShadedGeometryFlags.ReceiveShadow));
64
+
65
+ const material_context = this.ctx.obtain_material(scratch_mvc);
66
+
67
+ material_context.instances.add(sg.entity);
62
68
 
63
69
  }
64
70
 
@@ -84,67 +90,30 @@ export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
84
90
  pixelRatio = renderer.getPixelRatio();
85
91
  }
86
92
 
87
- const vg_builder = this.__vgb;
93
+ const vg_builder = this.ctx.builder;
88
94
 
89
95
  vg_builder.resolution.set(resolution.x * pixelRatio, resolution.y * pixelRatio);
90
96
  vg_builder.setMatricesFromCamera(view.camera);
91
- vg_builder.setOutput(this.__vg);
97
+ vg_builder.setOutput(this.ctx.geometry);
92
98
 
93
- vg_builder.build();
99
+ vg_builder.initialize_build();
94
100
  }
95
101
 
96
102
  build_end() {
97
- const contexts = this.__contexts_array;
98
- const context_count = contexts.length;
99
-
100
- /**
101
- *
102
- * @type {Map<number, MaterialContext>}
103
- */
104
- const instance_to_ctx = new Map();
103
+ this.ctx.render();
105
104
 
106
- for (let i = 0; i < context_count; i++) {
107
- const ctx = contexts[i];
108
- ctx.__patch_count = 0;
105
+ const material_contexts = this.ctx.contexts_array;
106
+ const contexts_count = material_contexts.length;
107
+ for (let i = 0; i < contexts_count; i++) {
108
+ const mc = material_contexts[i];
109
109
 
110
- for (const instance of ctx.instances) {
111
- instance_to_ctx.set(instance, ctx);
110
+ if (mc.instances.size > 0) {
111
+ this.__objects[this.__object_count++] = mc.mesh;
112
112
  }
113
113
  }
114
-
115
- // sort patches into relevant contexts
116
- const geometry = this.geometry;
117
- const patch_count = geometry.patch_count;
118
- const patches = geometry.patches;
119
-
120
- for (let i = 0; i < patch_count; i++) {
121
- const i3 = i * 3;
122
-
123
- const instance_id = patches[i3];
124
- const geometry_id = patches[i3 + 1];
125
- const patch_id = patches[i3 + 2];
126
-
127
- const ctx = instance_to_ctx.get(instance_id);
128
-
129
- const target_address = ctx.__patch_count * 3;
130
- ctx.__patch_count++;
131
-
132
- const ctx_patches = ctx.__patches;
133
-
134
- ctx_patches[target_address] = instance_id;
135
- ctx_patches[target_address + 1] = geometry_id;
136
- ctx_patches[target_address + 2] = patch_id;
137
- }
138
-
139
- // build each context
140
- for (let i = 0; i < context_count; i++) {
141
- const ctx = contexts[i];
142
-
143
- ctx.build(this.geometry);
144
- }
145
114
  }
146
115
 
147
116
  dispose() {
148
-
117
+ // rendering context is not owned, do nothing
149
118
  }
150
119
  }
@@ -1,17 +1,10 @@
1
1
  import { array_copy } from "../../../../core/collection/array/copyArray.js";
2
2
  import Vector2 from "../../../../core/geom/Vector2.js";
3
3
  import { RefinementSpec } from "./refinement/RefinementSpec.js";
4
- import { ActivePatchList } from "./refinement/ActivePatchList.js";
5
4
  import { mat4 } from "gl-matrix";
6
5
  import { get_geometry_patch_cut } from "./refinement/get_geometry_patch_cut.js";
7
6
  import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
8
7
 
9
- /**
10
- * @readonly
11
- * @type {RefinementSpec}
12
- */
13
- const refinement_spec = new RefinementSpec();
14
-
15
8
  export class VirtualGeometryBuilder {
16
9
  constructor() {
17
10
 
@@ -60,13 +53,6 @@ export class VirtualGeometryBuilder {
60
53
  */
61
54
  this.resolution = new Vector2();
62
55
 
63
- /**
64
- *
65
- * @type {ActivePatchList}
66
- * @private
67
- */
68
- this.__acl = new ActivePatchList();
69
-
70
56
  /**
71
57
  * How much error to accept when deciding to subdivide a cluster
72
58
  * Measured in pixels
@@ -74,10 +60,15 @@ export class VirtualGeometryBuilder {
74
60
  * @type {number}
75
61
  */
76
62
  this.error_bias = 2;
63
+
64
+ /**
65
+ *
66
+ * @type {RefinementSpec}
67
+ */
68
+ this.refinement_spec = new RefinementSpec();
77
69
  }
78
70
 
79
71
  dropCache() {
80
- this.__acl.clear();
81
72
  }
82
73
 
83
74
  /**
@@ -103,7 +94,7 @@ export class VirtualGeometryBuilder {
103
94
  mat4.multiply(this.view_projection_matrix, this.matrix_projection, this.matrix_world_inverse);
104
95
 
105
96
  //
106
- refinement_spec.focal_length = camera.fov / 180;
97
+ this.refinement_spec.focal_length = camera.fov / 180;
107
98
  }
108
99
 
109
100
  /**
@@ -121,17 +112,15 @@ export class VirtualGeometryBuilder {
121
112
  * @type {MicronGeometry|undefined}
122
113
  */
123
114
  const micron_geometry = object.geometry;
124
- if (micron_geometry !== undefined) {
125
- // get acl
126
- const acl = this.__acl;
127
115
 
116
+ if (micron_geometry !== undefined) {
128
117
 
129
118
  this.buildForMesh(
130
119
  object.instance_id,
131
120
  micron_geometry,
132
- object.matrixWorld.elements,
133
- acl
121
+ object.matrixWorld.elements
134
122
  );
123
+
135
124
  }
136
125
  }
137
126
  }
@@ -147,6 +136,8 @@ export class VirtualGeometryBuilder {
147
136
  geometry,
148
137
  transform
149
138
  ) {
139
+ const refinement_spec = this.refinement_spec;
140
+
150
141
  refinement_spec.build(transform, this.view_projection_matrix);
151
142
 
152
143
  const output = this.output;
@@ -183,17 +174,21 @@ export class VirtualGeometryBuilder {
183
174
  this.input_scene_length += object_count;
184
175
  }
185
176
 
186
- build() {
177
+ initialize_build() {
187
178
 
188
179
  // update refinement spec
189
- refinement_spec.error_threshold = this.error_bias;
180
+ this.refinement_spec.error_threshold = this.error_bias;
190
181
 
191
182
  const resolution = this.resolution;
192
183
 
193
- refinement_spec.setResolution(resolution.x, resolution.y);
184
+ this.refinement_spec.setResolution(resolution.x, resolution.y);
194
185
 
195
186
  // clear output
196
187
  this.output.clear();
188
+ }
189
+
190
+ build() {
191
+ this.initialize_build();
197
192
 
198
193
 
199
194
  const n = this.input_scene_length;
@@ -125,7 +125,7 @@ export class ThreeInstancedAdapter {
125
125
 
126
126
  /**
127
127
  *
128
- * @param {Uint32Array[]} patches
128
+ * @param {Uint32Array} patches
129
129
  * @param {number} patch_count
130
130
  * @param {VirtualGeometry} virtual_geometry
131
131
  */
@@ -52,7 +52,7 @@ export class MaterialContext {
52
52
 
53
53
  /**
54
54
  *
55
- * @type {MicronGeometryPatchOccurrence[]}
55
+ * @type {Uint32Array|number[]}
56
56
  */
57
57
  this.__patches = [];
58
58
 
@@ -63,16 +63,6 @@ export class MaterialContext {
63
63
  this.__patch_count = 0;
64
64
  }
65
65
 
66
-
67
- /**
68
- *
69
- * @param {MicronGeometryPatchOccurrence} occurrence
70
- * @returns {boolean}
71
- */
72
- filter(occurrence) {
73
- return this.instances.has(occurrence.instance_id);
74
- }
75
-
76
66
  init() {
77
67
 
78
68
  const material = this.material.clone();
@@ -1,3 +1,8 @@
1
+ export const MaterialVertexSpecFlags = {
2
+ CastShadow: 1,
3
+ ReceiveShadow: 2
4
+ };
5
+
1
6
  export class MaterialVertexSpec {
2
7
  constructor() {
3
8
  /**
@@ -10,6 +15,52 @@ export class MaterialVertexSpec {
10
15
  * @type {THREE.Material|null}
11
16
  */
12
17
  this.material = null;
18
+
19
+ /**
20
+ *
21
+ * @type {number}
22
+ */
23
+ this.flags = 0;
24
+ }
25
+
26
+ /**
27
+ *
28
+ * @param {number|MaterialVertexSpecFlags} flag
29
+ * @returns {void}
30
+ */
31
+ setFlag(flag) {
32
+ this.flags |= flag;
33
+ }
34
+
35
+ /**
36
+ *
37
+ * @param {number|MaterialVertexSpecFlags} flag
38
+ * @returns {void}
39
+ */
40
+ clearFlag(flag) {
41
+ this.flags &= ~flag;
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @param {number|MaterialVertexSpecFlags} flag
47
+ * @param {boolean} value
48
+ */
49
+ writeFlag(flag, value) {
50
+ if (value) {
51
+ this.setFlag(flag);
52
+ } else {
53
+ this.clearFlag(flag);
54
+ }
55
+ }
56
+
57
+ /**
58
+ *
59
+ * @param {number|MaterialVertexSpecFlags} flag
60
+ * @returns {boolean}
61
+ */
62
+ getFlag(flag) {
63
+ return (this.flags & flag) === flag;
13
64
  }
14
65
 
15
66
  /**
@@ -19,6 +70,7 @@ export class MaterialVertexSpec {
19
70
  copy(other) {
20
71
  this.spec = other.spec;
21
72
  this.material = other.material;
73
+ this.flags = other.flags;
22
74
  }
23
75
 
24
76
  /**
@@ -47,7 +99,7 @@ export class MaterialVertexSpec {
47
99
  }
48
100
 
49
101
  hash() {
50
- return this.spec.hash() ^ this.material.id;
102
+ return this.spec.hash() ^ this.material.id ^ this.flags;
51
103
  }
52
104
 
53
105
  equals(other) {
@@ -55,8 +107,9 @@ export class MaterialVertexSpec {
55
107
  return true;
56
108
  }
57
109
 
58
- return this.spec.equals(other.spec)
110
+ return this.flags === other.flags
59
111
  && this.material === other.material
112
+ && this.spec.equals(other.spec)
60
113
  ;
61
114
  }
62
115
  }
@@ -0,0 +1,151 @@
1
+ import { VirtualGeometry } from "../../format/VirtualGeometry.js";
2
+ import { VirtualGeometryBuilder } from "../VirtualGeometryBuilder.js";
3
+ import { HashMap } from "../../../../../core/collection/HashMap.js";
4
+ import Signal from "../../../../../core/events/signal/Signal.js";
5
+ import { MaterialContext } from "./MaterialContext.js";
6
+ import { MaterialVertexSpec, MaterialVertexSpecFlags } from "./MaterialVertexSpec.js";
7
+
8
+ /**
9
+ *
10
+ * @type {MaterialVertexSpec}
11
+ */
12
+ const scratch_mvc = new MaterialVertexSpec();
13
+
14
+ export class MicronRenderContext {
15
+ constructor() {
16
+
17
+ this.geometry = new VirtualGeometry();
18
+
19
+ this.builder = new VirtualGeometryBuilder();
20
+
21
+ /**
22
+ *
23
+ * @type {Map<MaterialVertexSpec, MaterialContext>}
24
+ */
25
+ this.material_contexts = new HashMap();
26
+
27
+ /**
28
+ *
29
+ * @type {MaterialContext[]}
30
+ * @private
31
+ */
32
+ this.__contexts_array = [];
33
+
34
+ this.on = {
35
+ /**
36
+ * @type {Signal<MaterialContext>}
37
+ */
38
+ contextAdded: new Signal()
39
+ };
40
+ }
41
+
42
+ /**
43
+ *
44
+ * @returns {MaterialContext[]}
45
+ */
46
+ get contexts_array() {
47
+ return this.__contexts_array;
48
+ }
49
+
50
+ /**
51
+ * Enable/disable wireframe rendering
52
+ * @param {boolean} x
53
+ */
54
+ set wireframe(x) {
55
+ this.material_contexts.forEach((ctx, mv) => {
56
+
57
+
58
+ ctx.compiled_material.wireframe = x;
59
+
60
+ });
61
+ }
62
+
63
+
64
+ /**
65
+ *
66
+ * @param {MaterialVertexSpec} descriptor
67
+ * @returns {MaterialContext}
68
+ */
69
+ obtain_material(descriptor) {
70
+
71
+ const existing = this.material_contexts.get(descriptor);
72
+
73
+ if (existing !== undefined) {
74
+ return existing;
75
+ }
76
+
77
+ // create a separate instance to be stored alongside the context
78
+ const key = descriptor.clone();
79
+
80
+ const ctx = new MaterialContext(descriptor.spec, descriptor.material);
81
+
82
+ ctx.init();
83
+
84
+ ctx.mesh.castShadow = descriptor.getFlag(MaterialVertexSpecFlags.CastShadow);
85
+ ctx.mesh.receiveShadow = descriptor.getFlag(MaterialVertexSpecFlags.ReceiveShadow);
86
+
87
+ this.material_contexts.set(key, ctx);
88
+ this.__contexts_array.push(ctx);
89
+
90
+ this.on.contextAdded.send1(ctx);
91
+
92
+ return ctx;
93
+ }
94
+
95
+ render() {
96
+ const render_context = this;
97
+ const contexts = render_context.__contexts_array;
98
+ const context_count = contexts.length;
99
+
100
+ /**
101
+ *
102
+ * @type {Map<number, MaterialContext>}
103
+ */
104
+ const instance_to_ctx = new Map();
105
+
106
+ let i = 0;
107
+
108
+ for (i = 0; i < context_count; i++) {
109
+ const ctx = contexts[i];
110
+ ctx.__patch_count = 0;
111
+
112
+ for (const instance of ctx.instances) {
113
+ instance_to_ctx.set(instance, ctx);
114
+ }
115
+ }
116
+
117
+ // sort patches into relevant contexts
118
+ const geometry = render_context.geometry;
119
+ const patch_count = geometry.patch_count;
120
+ const patches = geometry.patches;
121
+
122
+ for (i = 0; i < patch_count; i++) {
123
+ const i3 = i * 3;
124
+
125
+ const instance_id = patches[i3];
126
+ const geometry_id = patches[i3 + 1];
127
+ const patch_id = patches[i3 + 2];
128
+
129
+ const ctx = instance_to_ctx.get(instance_id);
130
+
131
+ const target_index = ctx.__patch_count;
132
+ const target_address = target_index * 3;
133
+
134
+ ctx.__patch_count++;
135
+
136
+ const ctx_patches = ctx.__patches;
137
+
138
+ ctx_patches[target_address] = instance_id;
139
+ ctx_patches[target_address + 1] = geometry_id;
140
+ ctx_patches[target_address + 2] = patch_id;
141
+ }
142
+
143
+ // build each context
144
+ for (i = 0; i < context_count; i++) {
145
+ const ctx = contexts[i];
146
+
147
+ ctx.build(geometry);
148
+ }
149
+ }
150
+
151
+ }