@woosh/meep-engine 2.34.33 → 2.34.37

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 (62) hide show
  1. package/core/assert.js +11 -0
  2. package/core/binary/BitSet.js +5 -0
  3. package/core/bvh2/BinaryNode.js +880 -848
  4. package/core/bvh2/LeafNode.js +80 -82
  5. package/core/bvh2/Node.d.ts +3 -0
  6. package/core/bvh2/Node.js +111 -114
  7. package/core/bvh2/aabb3/AABB3.js +50 -4
  8. package/core/bvh2/aabb3/AABB3.spec.js +27 -1
  9. package/core/bvh2/aabb3/AABB3Math.js +1 -1
  10. package/core/bvh2/aabb3/aabb3_from_v3_array.js +34 -0
  11. package/core/bvh2/aabb3/aabb3_from_v3_array_transformed.js +39 -0
  12. package/core/bvh2/aabb3/aabb3_intersects_frustum_degree.js +46 -0
  13. package/core/bvh2/transform/RotationOptimizer.js +2 -262
  14. package/core/bvh2/transform/tryRotateSingleNode.js +259 -0
  15. package/core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js +16 -35
  16. package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +52 -0
  17. package/core/collection/list/List.js +0 -34
  18. package/core/events/signal/Signal.js +1 -1
  19. package/core/geom/3d/aabb/aabb3_matrix4_project.js +3 -4
  20. package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +13 -0
  21. package/core/geom/3d/triangle/computeTriangleRayIntersection.js +1 -2
  22. package/core/geom/Quaternion.d.ts +2 -0
  23. package/core/geom/Vector3.js +22 -11
  24. package/engine/asset/loaders/ArrayBufferLoader.js +7 -0
  25. package/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -6
  26. package/engine/ecs/EntityBuilder.js +12 -5
  27. package/engine/ecs/EntityComponentDataset.js +26 -6
  28. package/engine/ecs/attachment/AttachmentSystem.js +1 -1
  29. package/engine/ecs/attachment/TransformAttachmentBinding.js +0 -1
  30. package/engine/ecs/foliage/FoliageVisibilitySetBuilder.js +1 -31
  31. package/engine/ecs/foliage/InstancedFoliage.js +85 -152
  32. package/engine/ecs/foliage/ViewState.js +190 -0
  33. package/engine/ecs/foliage/ecs/Foliage2System.js +82 -19
  34. package/engine/ecs/foliage/ecs/InstancedMeshComponent.js +30 -0
  35. package/engine/ecs/foliage/ecs/InstancedMeshLayer.js +16 -0
  36. package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -2
  37. package/engine/ecs/parent/EntityNode.js +31 -49
  38. package/engine/ecs/sockets/AttachmentSockets.js +11 -1
  39. package/engine/ecs/transform-attachment/TransformAttachment.js +88 -0
  40. package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +59 -0
  41. package/engine/graphics/GraphicsEngine.js +23 -2
  42. package/engine/graphics/ecs/camera/Camera.js +33 -16
  43. package/engine/graphics/ecs/camera/unprojectPoint.js +14 -0
  44. package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +2 -19
  45. package/engine/graphics/ecs/mesh/updateNodeByTransformAndBBB.js +21 -21
  46. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +9 -1
  47. package/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +4 -1
  48. package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +40 -8
  49. package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +3 -3
  50. package/engine/graphics/ecs/water2/shader/AlexWaterShader.js +7 -1
  51. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +17 -11
  52. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -34
  53. package/engine/graphics/micron/build/fill_patch_geometry_data.js +12 -0
  54. package/engine/graphics/micron/format/MicronGeometry.js +21 -0
  55. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -3
  56. package/engine/graphics/micron/prototypeVirtualGeometry.js +69 -1
  57. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +5 -1
  58. package/engine/graphics/render/layers/RenderLayer.js +22 -85
  59. package/engine/graphics/render/visibility/VisibilityComputer.js +23 -103
  60. package/engine/sound/ecs/emitter/SoundEmitterSystem.js +1 -1
  61. package/package.json +1 -1
  62. package/samples/terrain/editor.js +0 -1
@@ -1,23 +1,19 @@
1
1
  import { BinaryNode } from "../../../core/bvh2/BinaryNode.js";
2
2
  import { RowFirstTable } from "../../../core/collection/table/RowFirstTable.js";
3
- import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
4
- import Vector3 from "../../../core/geom/Vector3.js";
5
3
  import { LeafNode } from "../../../core/bvh2/LeafNode.js";
6
4
  import Vector4 from "../../../core/geom/Vector4.js";
7
5
 
8
6
  import { BufferGeometry } from 'three';
9
7
  import { DataType } from "../../../core/collection/table/DataType.js";
10
8
  import { RowFirstTableSpec } from "../../../core/collection/table/RowFirstTableSpec.js";
11
- import Quaternion from "../../../core/geom/Quaternion.js";
12
- import { ThreeFrustumsIntersectionBVHVisitor } from "../../../core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js";
13
- import { FoliageVisibilitySetBuilder } from "./FoliageVisibilitySetBuilder.js";
14
- import { traverseBinaryNodeUsingVisitor } from "../../../core/bvh2/traversal/traverseBinaryNodeUsingVisitor.js";
15
9
  import { serializeBinaryNodeToBinaryBuffer } from "../../../core/bvh2/serialization/serializeBinaryNodeToBinaryBuffer.js";
16
10
  import { deserializeBinaryNodeFromBinaryBuffer } from "../../../core/bvh2/serialization/deserializeBinaryNodeFromBinaryBuffer.js";
17
11
  import { computeGeometryBoundingSphereMiniball } from "../../graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.js";
18
12
  import { serializeRowFirstTable } from "../../../core/collection/table/serializeRowFirstTable.js";
19
13
  import { deserializeRowFirstTable } from "../../../core/collection/table/deserializeRowFirstTable.js";
20
- import { assert } from "../../../core/assert.js";
14
+ import { compose_matrix4_array } from "../../graphics/util/composeMatrix4.js";
15
+ import { aabb3_from_v3_array_transformed } from "../../../core/bvh2/aabb3/aabb3_from_v3_array_transformed.js";
16
+ import { ViewState } from "./ViewState.js";
21
17
 
22
18
  /**
23
19
  * @readonly
@@ -57,15 +53,16 @@ export class InstancedFoliage {
57
53
 
58
54
  /**
59
55
  *
60
- * @type {InstancedMeshGroup}
56
+ * @type {THREE.BufferGeometry|null}
61
57
  */
62
- this.instances = new InstancedMeshGroup();
58
+ this.geometry = null;
63
59
 
64
60
  /**
65
61
  *
66
- * @type {THREE.BufferGeometry|null}
62
+ * @type {THREE.Material|null}
63
+ * @private
67
64
  */
68
- this.geometry = null;
65
+ this.__material = null;
69
66
 
70
67
  /**
71
68
  *
@@ -73,32 +70,39 @@ export class InstancedFoliage {
73
70
  */
74
71
  this.instanceBoundingSphere = new Vector4(0, 0, 0, 0);
75
72
 
76
-
77
73
  /**
78
74
  *
79
- * @type {ThreeFrustumsIntersectionBVHVisitor}
75
+ * @type {Map<CameraView, ViewState>}
76
+ * @private
80
77
  */
81
- this.bvhVisibilityVisitor = new ThreeFrustumsIntersectionBVHVisitor();
78
+ this.__views = new Map();
82
79
 
83
- /**
84
- *
85
- * @type {FoliageVisibilitySetBuilder}
86
- */
87
- this.visibilitySetBuilder = new FoliageVisibilitySetBuilder();
88
- this.bvhVisibilityVisitor.collector = this.visibilitySetBuilder;
80
+ this.__cast_shadow = true;
81
+ this.__receive_shadow = true;
82
+ }
89
83
 
90
- /**
91
- *
92
- * @type {*[]}
93
- * @private
94
- */
95
- this.__garbage = [];
96
- /**
97
- *
98
- * @type {number}
99
- * @private
100
- */
101
- this.__garbagePointer = 0;
84
+ set castShadow(v) {
85
+ this.__cast_shadow = v;
86
+
87
+ for (const [view, state] of this.__views) {
88
+ state.instances.mesh.castShadow = v;
89
+ }
90
+ }
91
+
92
+ get castShadow() {
93
+ return this.__cast_shadow;
94
+ }
95
+
96
+ set receiveShadow(v) {
97
+ this.__receive_shadow = v;
98
+
99
+ for (const [view, state] of this.__views) {
100
+ state.instances.mesh.receiveShadow = v;
101
+ }
102
+ }
103
+
104
+ get receiveShadow() {
105
+ return this.__receive_shadow;
102
106
  }
103
107
 
104
108
  /**
@@ -136,7 +140,11 @@ export class InstancedFoliage {
136
140
  }
137
141
 
138
142
  dispose() {
139
- this.instances.dispose();
143
+ for (const [view, state] of this.__views) {
144
+ state.dispose();
145
+ }
146
+
147
+ this.__views.clear();
140
148
  }
141
149
 
142
150
  initialize() {
@@ -168,7 +176,7 @@ export class InstancedFoliage {
168
176
  );
169
177
 
170
178
  //compute bounding box for this instance
171
- this.expandBoundingBoxForInstance(position, rotation, scale, leaf);
179
+ this.bomputeInstanceBoundsTight(position, rotation, scale, leaf);
172
180
 
173
181
  //insert bounding box into the spatial index
174
182
  this.bvh.insertNode(leaf);
@@ -210,42 +218,15 @@ export class InstancedFoliage {
210
218
  * @param {Quaternion} rotation
211
219
  * @param {Vector3} scale
212
220
  */
213
- expandBoundingBoxForInstance(position, rotation, scale, result) {
221
+ bomputeInstanceBoundsTight(position, rotation, scale, result) {
214
222
 
215
223
  const vertexData = this.geometry.attributes.position.array;
216
224
 
217
- const rXYZ = new Vector3(rotation.x, rotation.y, rotation.z);
218
-
219
- const v = new Vector3(0, 0, 0);
220
-
221
- const c0 = new Vector3(0, 0, 0);
222
- const c1 = new Vector3(0, 0, 0);
223
- const c2 = new Vector3(0, 0, 0);
224
-
225
- for (let i = 0, l = vertexData.length; i < l; i += 3) {
226
- const x = vertexData[i];
227
- const y = vertexData[i + 1];
228
- const z = vertexData[i + 2];
229
-
230
- v.set(x, y, z);
231
-
232
- //transform point
233
-
234
- //apply scale
235
- v.multiply(scale);
225
+ const transform = new Float32Array(16);
236
226
 
237
- //apply rotation
238
- c1.copy(v).multiplyScalar(rotation.w);
239
- c0.copy(rXYZ).cross(v).add(c1);
240
- c2.copy(rXYZ).cross(c0).multiplyScalar(2);
227
+ compose_matrix4_array(transform, position, rotation, scale);
241
228
 
242
- v.add(c2);
243
-
244
- //apply translation
245
- v.add(position);
246
-
247
- result._expandToFitPoint(v.x, v.y, v.z);
248
- }
229
+ aabb3_from_v3_array_transformed(result, vertexData, vertexData.length, transform);
249
230
  }
250
231
 
251
232
  computeInstanceBoundingSphere() {
@@ -277,9 +258,12 @@ export class InstancedFoliage {
277
258
 
278
259
 
279
260
  this.geometry = bufferGeometry;
261
+ this.__material = material;
280
262
 
281
- this.instances.setMaterial(material);
282
- this.instances.setGeometry(bufferGeometry);
263
+ for (const [view, state] of this.__views) {
264
+ state.instances.setMaterial(material);
265
+ state.instances.setGeometry(bufferGeometry);
266
+ }
283
267
 
284
268
  this.computeInstanceBoundingSphere();
285
269
 
@@ -318,108 +302,60 @@ export class InstancedFoliage {
318
302
 
319
303
  /**
320
304
  *
321
- * @param index
322
- * @param {int} ref
305
+ * @param {CameraView} view
323
306
  */
324
- __updateVisibility(index, ref) {
325
- assert.isNonNegativeInteger(ref, 'ref');
326
-
327
- /**
328
- *
329
- * @type {FoliageVisibilitySetBuilder}
330
- */
331
- const builder = this.visibilitySetBuilder;
307
+ add_view(view) {
332
308
 
333
- /**
334
- *
335
- * @type {BitSet}
336
- */
337
- const visibleElementSet = builder.visibleSet;
338
-
339
- if (!visibleElementSet.get(ref)) {
340
- //no longer visible
341
- this.__garbage[this.__garbagePointer++] = ref;
342
- } else {
343
- //visible, and is already in the group, update the set
344
- visibleElementSet.set(ref, false);
309
+ if (this.__views.has(view)) {
310
+ throw new Error('View already registered');
345
311
  }
346
- }
347
-
348
- __removeGarbage() {
349
312
 
350
- const garbagePointer = this.__garbagePointer;
351
- const instances = this.instances;
313
+ const state = new ViewState();
352
314
 
315
+ state.__view = view;
353
316
 
354
- const garbage = this.__garbage;
355
-
356
- for (let i = 0; i < garbagePointer; i++) {
357
- const ref = garbage[i];
358
- instances.remove(ref);
317
+ if (this.geometry !== null) {
318
+ state.instances.setGeometry(this.geometry);
319
+ }
320
+ if (this.__material !== null) {
321
+ state.instances.setMaterial(this.__material);
359
322
  }
360
323
 
324
+ state.instances.mesh.castShadow = this.castShadow;
325
+ state.instances.mesh.receiveShadow = this.receiveShadow;
326
+
327
+ this.__views.set(view, state);
361
328
  }
362
329
 
363
330
  /**
364
331
  *
365
- * @param {Frustum[]} frustums
366
- * @param {function[]} [visibilityFilters]
332
+ * @param {CameraView} view
367
333
  */
368
- update(frustums, visibilityFilters = []) {
369
- const instances = this.instances;
370
-
371
- this.bvhVisibilityVisitor.setFrustums(frustums);
334
+ remove_view(view) {
335
+ const state = this.__views.get(view);
372
336
 
373
- const visibilitySetBuilder = this.visibilitySetBuilder;
374
- visibilitySetBuilder.setFilters(visibilityFilters);
375
- visibilitySetBuilder.initialize();
376
-
377
- const visibleElementSet = visibilitySetBuilder.visibleSet;
378
-
379
- //build visible set
380
- traverseBinaryNodeUsingVisitor(this.bvh, this.bvhVisibilityVisitor);
381
-
382
- visibilitySetBuilder.finalize();
383
-
384
- // console.log(`Visible: `, elementsToAdd.size);
385
-
386
- //reset garbage pointer
387
- this.__garbagePointer = 0;
388
-
389
- //remove those that are no longer visible
390
- instances.traverseReferences(this.__updateVisibility, this);
391
-
392
- //cull instances that are no longer visible
393
- this.__removeGarbage();
394
-
395
-
396
- const data = this.data;
397
-
398
- //process entities that have become newly visible
399
- for (let index = visibleElementSet.nextSetBit(0); index !== -1; index = visibleElementSet.nextSetBit(index + 1)) {
400
- //read transform data for instance
401
- data.getRow(index, rowData);
402
-
403
- const positionX = rowData[0];
404
- const positionY = rowData[1];
405
- const positionZ = rowData[2];
337
+ if (state === undefined) {
338
+ return false;
339
+ }
406
340
 
407
- const encodedRotation = rowData[3];
341
+ state.dispose();
408
342
 
343
+ this.__views.delete(view);
409
344
 
410
- const scaleX = rowData[4];
411
- const scaleY = rowData[5];
412
- const scaleZ = rowData[6];
345
+ return true;
346
+ }
413
347
 
414
- const i = instances.add(index);
348
+ /**
349
+ *
350
+ * @param {CameraView} view
351
+ * @return {ViewState}
352
+ */
353
+ update(view) {
354
+ const state = this.__views.get(view);
415
355
 
416
- tempQuaternion.decodeFromUint32(encodedRotation);
356
+ state.update(this.bvh, this.data);
417
357
 
418
- //apply instance transforms
419
- instances.setPositionAt(i, positionX, positionY, positionZ);
420
- instances.setRotationAt(i, tempQuaternion.x, tempQuaternion.y, tempQuaternion.z, tempQuaternion.w);
421
- instances.setScaleAt(i, scaleX, scaleY, scaleZ);
422
- }
358
+ return state;
423
359
  }
424
360
  }
425
361
 
@@ -442,6 +378,3 @@ function serializeLeafValueUintVar(buffer, value) {
442
378
  }
443
379
 
444
380
 
445
- const tempQuaternion = new Quaternion();
446
- const rowData = [];
447
-
@@ -0,0 +1,190 @@
1
+ import { BitSet } from "../../../core/binary/BitSet.js";
2
+ import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
3
+ import { assert } from "../../../core/assert.js";
4
+ import { queryBinaryNode_FrustumIntersections_Data } from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
5
+ import Quaternion from "../../../core/geom/Quaternion.js";
6
+
7
+ /**
8
+ *
9
+ * @type {number[]}
10
+ */
11
+ const scratch_array = [];
12
+
13
+ export class ViewState {
14
+ constructor() {
15
+ /**
16
+ *
17
+ * @type {CameraView|null}
18
+ * @private
19
+ */
20
+ this.__view = null;
21
+
22
+ this.__visible_set = new BitSet();
23
+
24
+ //prevent re-allocation
25
+ this.__visible_set.preventShrink();
26
+
27
+ /**
28
+ *
29
+ * @type {InstancedMeshGroup}
30
+ */
31
+ this.instances = new InstancedMeshGroup();
32
+
33
+ /**
34
+ *
35
+ * @type {number[]}
36
+ * @private
37
+ */
38
+ this.__garbage = [];
39
+ /**
40
+ *
41
+ * @type {number}
42
+ * @private
43
+ */
44
+ this.__garbagePointer = 0;
45
+ }
46
+
47
+ dispose() {
48
+ this.instances.dispose();
49
+ }
50
+
51
+
52
+ /**
53
+ *
54
+ * @param {number} index
55
+ * @param {int} ref
56
+ */
57
+ __updateVisibility(index, ref) {
58
+ assert.isNonNegativeInteger(ref, 'ref');
59
+
60
+ /**
61
+ *
62
+ * @type {BitSet}
63
+ */
64
+ const visibleElementSet = this.__visible_set;
65
+
66
+ if (!visibleElementSet.get(ref)) {
67
+ //no longer visible
68
+ this.__garbage[this.__garbagePointer++] = ref;
69
+ } else {
70
+ //visible, and is already in the group, update the set
71
+ visibleElementSet.set(ref, false);
72
+ }
73
+ }
74
+
75
+ __compute_visibility_update() {
76
+ const instances = this.instances;
77
+
78
+ const indices = instances.indices;
79
+
80
+ const index_count = indices.length;
81
+
82
+ /**
83
+ *
84
+ * @type {BitSet}
85
+ */
86
+ const visible_set = this.__visible_set;
87
+
88
+ const garbage = this.__garbage;
89
+
90
+ for (let ref = 0; ref < index_count; ref++) {
91
+ const index = indices[ref];
92
+
93
+ if (index === undefined) {
94
+ // unoccupied
95
+ continue;
96
+ }
97
+
98
+ if (!visible_set.get(ref)) {
99
+ //no longer visible
100
+ garbage[this.__garbagePointer++] = ref;
101
+ } else {
102
+ //visible, and is already in the group, update the set
103
+ visible_set.set(ref, false);
104
+ }
105
+ }
106
+ }
107
+
108
+ __removeGarbage() {
109
+
110
+ const garbagePointer = this.__garbagePointer;
111
+ const instances = this.instances;
112
+
113
+
114
+ const garbage = this.__garbage;
115
+
116
+ for (let i = 0; i < garbagePointer; i++) {
117
+ const ref = garbage[i];
118
+ instances.remove(ref);
119
+ }
120
+
121
+ }
122
+
123
+ /**
124
+ *
125
+ * @param {BinaryNode<number>} bvh
126
+ * @param {RowFirstTable} data
127
+ */
128
+ update(bvh, data) {
129
+
130
+ // reset visible set
131
+ this.__visible_set.reset();
132
+
133
+ //reset garbage pointer
134
+ this.__garbagePointer = 0;
135
+
136
+ const instances = this.instances;
137
+
138
+ const visible_instance_set = this.__visible_set;
139
+
140
+
141
+ // collect visible instances
142
+ const collected_nodes = queryBinaryNode_FrustumIntersections_Data(scratch_array, 0, bvh, this.__view.frustum);
143
+
144
+ for (let i = 0; i < collected_nodes; i++) {
145
+ const instance_id = scratch_array[i];
146
+
147
+ // mark them as visible
148
+ visible_instance_set.set(instance_id, true);
149
+ }
150
+
151
+ //remove those that are no longer visible
152
+ this.__compute_visibility_update();
153
+
154
+ //cull instances that are no longer visible
155
+ this.__removeGarbage();
156
+
157
+ //process entities that have become newly visible
158
+ for (
159
+ let index = visible_instance_set.nextSetBit(0);
160
+ index !== -1;
161
+ index = visible_instance_set.nextSetBit(index + 1)
162
+ ) {
163
+ //read transform data for instance
164
+ data.getRow(index, rowData);
165
+
166
+ const positionX = rowData[0];
167
+ const positionY = rowData[1];
168
+ const positionZ = rowData[2];
169
+
170
+ const encodedRotation = rowData[3];
171
+
172
+
173
+ const scaleX = rowData[4];
174
+ const scaleY = rowData[5];
175
+ const scaleZ = rowData[6];
176
+
177
+ const i = instances.add(index);
178
+
179
+ tempQuaternion.decodeFromUint32(encodedRotation);
180
+
181
+ //apply instance transforms
182
+ instances.setPositionAt(i, positionX, positionY, positionZ);
183
+ instances.setRotationAt(i, tempQuaternion.x, tempQuaternion.y, tempQuaternion.z, tempQuaternion.w);
184
+ instances.setScaleAt(i, scaleX, scaleY, scaleZ);
185
+ }
186
+ }
187
+ }
188
+
189
+ const tempQuaternion = new Quaternion();
190
+ const rowData = [];
@@ -26,13 +26,8 @@ function cleanupLayer(layerData, renderLayer) {
26
26
  export function loadFoliageLayer(layer, assetManager) {
27
27
  const instancedFoliage = layer.data;
28
28
 
29
- /**
30
- * @type {THREE.Mesh}
31
- */
32
- const threeMesh = instancedFoliage.instances.mesh;
33
-
34
- threeMesh.castShadow = layer.castShadow.getValue();
35
- threeMesh.receiveShadow = layer.receiveShadow.getValue();
29
+ instancedFoliage.castShadow = layer.castShadow.getValue();
30
+ instancedFoliage.receiveShadow = layer.receiveShadow.getValue();
36
31
 
37
32
  const modelURL = layer.modelURL.getValue();
38
33
 
@@ -112,15 +107,24 @@ export class Foliage2System extends System {
112
107
  startup(entityManager, readyCallback, errorCallback) {
113
108
  this.entityManager = entityManager;
114
109
 
115
- this.renderLayer = this.graphics.layers.create('instanced-mesh-system');
116
- this.renderLayer.buildVisibleSet = (frustums, filters, visitObject, thisArg) => {
110
+ const graphics = this.graphics;
111
+
112
+ this.renderLayer = graphics.layers.create('instanced-mesh-system');
113
+
114
+ graphics.views.elements.forEach(this.__handle_view_added, this);
115
+
116
+ graphics.views.elements.on.added.add(this.__handle_view_added, this);
117
+ graphics.views.elements.on.removed.add(this.__handle_view_removed, this);
118
+
119
+ this.renderLayer.buildVisibleSet = (view, visitObject, thisArg) => {
117
120
  const data = this.data;
118
121
 
119
122
  for (let entity in data) {
120
123
 
121
124
  const layers = data[entity];
125
+ const layer_count = layers.length;
122
126
 
123
- for (let i = 0, numLayers = layers.length; i < numLayers; i++) {
127
+ for (let i = 0; i < layer_count; i++) {
124
128
  /**
125
129
  * @type {{instances:InstancedFoliage}}
126
130
  */
@@ -133,9 +137,9 @@ export class Foliage2System extends System {
133
137
  */
134
138
  const instances = layerData.instances;
135
139
 
136
- instances.update(frustums, filters);
140
+ const view_state = instances.update(view);
137
141
 
138
- const group = instances.instances;
142
+ const group = view_state.instances;
139
143
 
140
144
  if (group.getCount() <= 0) {
141
145
  //no visible instances, skip
@@ -153,9 +157,61 @@ export class Foliage2System extends System {
153
157
  readyCallback();
154
158
  }
155
159
 
160
+ /**
161
+ *
162
+ * @param {CameraView} view
163
+ * @private
164
+ */
165
+ __handle_view_added(view) {
166
+ const em = this.entityManager;
167
+
168
+ if (em === null) {
169
+ return;
170
+ }
171
+
172
+ const ecd = em.dataset;
173
+
174
+ if (ecd === null) {
175
+ return;
176
+ }
177
+
178
+ ecd.traverseComponents(InstancedMeshComponent, im => {
179
+ im.add_view(view);
180
+ });
181
+ }
182
+
183
+
184
+ /**
185
+ *
186
+ * @param {CameraView} view
187
+ * @private
188
+ */
189
+ __handle_view_removed(view) {
190
+
191
+ const em = this.entityManager;
192
+
193
+ if (em === null) {
194
+ return;
195
+ }
196
+
197
+ const ecd = em.dataset;
198
+
199
+ if (ecd === null) {
200
+ return;
201
+ }
202
+
203
+ ecd.traverseComponents(InstancedMeshComponent, im => {
204
+ im.remove_view(view);
205
+ });
206
+ }
207
+
156
208
  shutdown(entityManager, readyCallback, errorCallback) {
157
209
  this.graphics.layers.remove(this.renderLayer);
158
210
 
211
+ this.graphics.views.elements.forEach(this.__handle_view_removed, this);
212
+ this.graphics.views.elements.on.added.remove(this.__handle_view_added, this);
213
+ this.graphics.views.elements.on.removed.remove(this.__handle_view_removed, this);
214
+
159
215
  readyCallback();
160
216
  }
161
217
 
@@ -166,16 +222,16 @@ export class Foliage2System extends System {
166
222
 
167
223
  /**
168
224
  *
169
- * @param {InstancedMeshComponent} foliage
225
+ * @param {InstancedMeshComponent} instances
170
226
  * @param entity
171
227
  */
172
- link(foliage, entity) {
228
+ link(instances, entity) {
173
229
  const layers = [];
174
230
  const data = this.data;
175
231
 
176
232
  data[entity] = layers;
177
233
 
178
- const layerList = foliage.layers;
234
+ const layerList = instances.layers;
179
235
  const layer_count = layerList.length;
180
236
 
181
237
  for (let i = 0; i < layer_count; i++) {
@@ -215,11 +271,16 @@ export class Foliage2System extends System {
215
271
  }
216
272
  }
217
273
 
218
- //TODO need to expose InstancedMesh BVH to let camera frustum calculation work correctly
219
-
274
+ //
275
+ this.graphics.views.elements.forEach(instances.add_view, instances);
220
276
  }
221
277
 
222
- unlink(foliage, entity) {
278
+ /**
279
+ *
280
+ * @param {InstancedMeshComponent} instances
281
+ * @param {number} entity
282
+ */
283
+ unlink(instances, entity) {
223
284
  const renderLayer = this.renderLayer;
224
285
  const layers = this.data[entity];
225
286
 
@@ -230,7 +291,9 @@ export class Foliage2System extends System {
230
291
  cleanupLayer(layerData, renderLayer);
231
292
  }
232
293
 
233
- foliage.dispose();
294
+ this.graphics.views.elements.forEach(instances.remove_view, instances);
295
+
296
+ instances.dispose();
234
297
 
235
298
  delete this.data[entity];
236
299
  }