@woosh/meep-engine 2.34.32 → 2.34.36
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.
- package/core/assert.js +11 -0
- package/core/binary/BitSet.js +5 -0
- package/core/bvh2/BinaryNode.js +210 -74
- package/core/bvh2/Node.d.ts +3 -0
- package/core/bvh2/aabb3/AABB3.js +50 -4
- package/core/bvh2/aabb3/AABB3Math.js +1 -1
- package/core/bvh2/aabb3/aabb3_from_v3_array.js +34 -0
- package/core/bvh2/aabb3/aabb3_from_v3_array_transformed.js +39 -0
- package/core/bvh2/aabb3/aabb3_intersects_frustum_degree.js +46 -0
- package/core/bvh2/transform/RotationOptimizer.js +2 -262
- package/core/bvh2/transform/tryRotateSingleNode.js +259 -0
- package/core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js +16 -35
- package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +52 -0
- package/core/collection/list/List.js +0 -34
- package/core/events/signal/Signal.js +1 -1
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +2 -3
- package/core/geom/Quaternion.d.ts +2 -0
- package/engine/Engine.js +5 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +7 -0
- package/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -6
- package/engine/development/performance/AbstractMetric.js +4 -0
- package/engine/development/performance/RingBufferMetric.js +4 -0
- package/engine/ecs/EntityBuilder.js +12 -5
- package/engine/ecs/EntityComponentDataset.js +26 -6
- package/engine/ecs/attachment/AttachmentSystem.js +1 -1
- package/engine/ecs/attachment/TransformAttachmentBinding.js +0 -1
- package/engine/ecs/foliage/FoliageVisibilitySetBuilder.js +1 -31
- package/engine/ecs/foliage/InstancedFoliage.js +81 -152
- package/engine/ecs/foliage/ViewState.js +190 -0
- package/engine/ecs/foliage/ecs/Foliage2System.js +80 -12
- package/engine/ecs/foliage/ecs/InstancedMeshComponent.js +30 -0
- package/engine/ecs/foliage/ecs/InstancedMeshLayer.js +16 -0
- package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -2
- package/engine/ecs/parent/EntityNode.js +31 -49
- package/engine/ecs/sockets/AttachmentSockets.js +11 -1
- package/engine/ecs/transform-attachment/TransformAttachment.js +88 -0
- package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +59 -0
- package/engine/graphics/GraphicsEngine.js +23 -2
- package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +2 -19
- package/engine/graphics/ecs/mesh/updateNodeByTransformAndBBB.js +21 -21
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +9 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +4 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +3 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +40 -8
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +3 -3
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +17 -11
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -34
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +19 -6
- package/engine/graphics/micron/format/MicronGeometry.js +21 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -3
- package/engine/graphics/micron/prototypeVirtualGeometry.js +69 -1
- package/engine/graphics/render/layers/RenderLayer.js +22 -85
- package/engine/graphics/render/visibility/VisibilityComputer.js +23 -103
- package/engine/sound/ecs/emitter/SoundEmitterSystem.js +1 -1
- package/package.json +1 -1
- 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 {
|
|
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 {
|
|
56
|
+
* @type {THREE.BufferGeometry|null}
|
|
61
57
|
*/
|
|
62
|
-
this.
|
|
58
|
+
this.geometry = null;
|
|
63
59
|
|
|
64
60
|
/**
|
|
65
61
|
*
|
|
66
|
-
* @type {THREE.
|
|
62
|
+
* @type {THREE.Material|null}
|
|
63
|
+
* @private
|
|
67
64
|
*/
|
|
68
|
-
this.
|
|
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 {
|
|
75
|
+
* @type {Map<CameraView, ViewState>}
|
|
76
|
+
* @private
|
|
80
77
|
*/
|
|
81
|
-
this.
|
|
78
|
+
this.__views = new Map();
|
|
82
79
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
221
|
+
bomputeInstanceBoundsTight(position, rotation, scale, result) {
|
|
214
222
|
|
|
215
223
|
const vertexData = this.geometry.attributes.position.array;
|
|
216
224
|
|
|
217
|
-
const
|
|
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
|
|
225
|
+
const transform = new Float32Array(16);
|
|
233
226
|
|
|
234
|
-
|
|
235
|
-
v.multiply(scale);
|
|
227
|
+
compose_matrix4_array(transform, position, rotation, scale);
|
|
236
228
|
|
|
237
|
-
|
|
238
|
-
c1.copy(v).multiplyScalar(rotation.w);
|
|
239
|
-
c0.copy(rXYZ).cross(v).add(c1);
|
|
240
|
-
c2.copy(rXYZ).cross(c0).multiplyScalar(2);
|
|
241
|
-
|
|
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.
|
|
282
|
-
|
|
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,56 @@ export class InstancedFoliage {
|
|
|
318
302
|
|
|
319
303
|
/**
|
|
320
304
|
*
|
|
321
|
-
* @param
|
|
322
|
-
* @param {int} ref
|
|
305
|
+
* @param {CameraView} view
|
|
323
306
|
*/
|
|
324
|
-
|
|
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
|
|
351
|
-
const instances = this.instances;
|
|
313
|
+
const state = new ViewState();
|
|
352
314
|
|
|
315
|
+
state.__view = view;
|
|
353
316
|
|
|
354
|
-
|
|
317
|
+
state.instances.setGeometry(this.geometry);
|
|
318
|
+
state.instances.setMaterial(this.__material);
|
|
355
319
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
instances.remove(ref);
|
|
359
|
-
}
|
|
320
|
+
state.instances.mesh.castShadow = this.castShadow;
|
|
321
|
+
state.instances.mesh.receiveShadow = this.receiveShadow;
|
|
360
322
|
|
|
323
|
+
this.__views.set(view, state);
|
|
361
324
|
}
|
|
362
325
|
|
|
363
326
|
/**
|
|
364
327
|
*
|
|
365
|
-
* @param {
|
|
366
|
-
* @param {function[]} [visibilityFilters]
|
|
328
|
+
* @param {CameraView} view
|
|
367
329
|
*/
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
this.bvhVisibilityVisitor.setFrustums(frustums);
|
|
330
|
+
remove_view(view) {
|
|
331
|
+
const state = this.__views.get(view);
|
|
372
332
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
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];
|
|
333
|
+
if (state === undefined) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
406
336
|
|
|
407
|
-
|
|
337
|
+
state.dispose();
|
|
408
338
|
|
|
339
|
+
this.__views.delete(view);
|
|
409
340
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const scaleZ = rowData[6];
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
413
343
|
|
|
414
|
-
|
|
344
|
+
/**
|
|
345
|
+
*
|
|
346
|
+
* @param {CameraView} view
|
|
347
|
+
* @return {ViewState}
|
|
348
|
+
*/
|
|
349
|
+
update(view) {
|
|
350
|
+
const state = this.__views.get(view);
|
|
415
351
|
|
|
416
|
-
|
|
352
|
+
state.update(this.bvh, this.data);
|
|
417
353
|
|
|
418
|
-
|
|
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
|
-
}
|
|
354
|
+
return state;
|
|
423
355
|
}
|
|
424
356
|
}
|
|
425
357
|
|
|
@@ -442,6 +374,3 @@ function serializeLeafValueUintVar(buffer, value) {
|
|
|
442
374
|
}
|
|
443
375
|
|
|
444
376
|
|
|
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 = [];
|
|
@@ -112,15 +112,24 @@ export class Foliage2System extends System {
|
|
|
112
112
|
startup(entityManager, readyCallback, errorCallback) {
|
|
113
113
|
this.entityManager = entityManager;
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
const graphics = this.graphics;
|
|
116
|
+
|
|
117
|
+
this.renderLayer = graphics.layers.create('instanced-mesh-system');
|
|
118
|
+
|
|
119
|
+
graphics.views.elements.forEach(this.__handle_view_added, this);
|
|
120
|
+
|
|
121
|
+
graphics.views.elements.on.added.add(this.__handle_view_added, this);
|
|
122
|
+
graphics.views.elements.on.removed.add(this.__handle_view_removed, this);
|
|
123
|
+
|
|
124
|
+
this.renderLayer.buildVisibleSet = (view, visitObject, thisArg) => {
|
|
117
125
|
const data = this.data;
|
|
118
126
|
|
|
119
127
|
for (let entity in data) {
|
|
120
128
|
|
|
121
129
|
const layers = data[entity];
|
|
130
|
+
const layer_count = layers.length;
|
|
122
131
|
|
|
123
|
-
for (let i = 0
|
|
132
|
+
for (let i = 0; i < layer_count; i++) {
|
|
124
133
|
/**
|
|
125
134
|
* @type {{instances:InstancedFoliage}}
|
|
126
135
|
*/
|
|
@@ -133,9 +142,9 @@ export class Foliage2System extends System {
|
|
|
133
142
|
*/
|
|
134
143
|
const instances = layerData.instances;
|
|
135
144
|
|
|
136
|
-
instances.update(
|
|
145
|
+
const view_state = instances.update(view);
|
|
137
146
|
|
|
138
|
-
const group =
|
|
147
|
+
const group = view_state.instances;
|
|
139
148
|
|
|
140
149
|
if (group.getCount() <= 0) {
|
|
141
150
|
//no visible instances, skip
|
|
@@ -153,9 +162,61 @@ export class Foliage2System extends System {
|
|
|
153
162
|
readyCallback();
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
/**
|
|
166
|
+
*
|
|
167
|
+
* @param {CameraView} view
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
__handle_view_added(view) {
|
|
171
|
+
const em = this.entityManager;
|
|
172
|
+
|
|
173
|
+
if (em === null) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const ecd = em.dataset;
|
|
178
|
+
|
|
179
|
+
if (ecd === null) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
ecd.traverseComponents(InstancedMeshComponent, im => {
|
|
184
|
+
im.add_view(view);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
*
|
|
191
|
+
* @param {CameraView} view
|
|
192
|
+
* @private
|
|
193
|
+
*/
|
|
194
|
+
__handle_view_removed(view) {
|
|
195
|
+
|
|
196
|
+
const em = this.entityManager;
|
|
197
|
+
|
|
198
|
+
if (em === null) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const ecd = em.dataset;
|
|
203
|
+
|
|
204
|
+
if (ecd === null) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
ecd.traverseComponents(InstancedMeshComponent, im => {
|
|
209
|
+
im.remove_view(view);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
156
213
|
shutdown(entityManager, readyCallback, errorCallback) {
|
|
157
214
|
this.graphics.layers.remove(this.renderLayer);
|
|
158
215
|
|
|
216
|
+
this.graphics.views.elements.forEach(this.__handle_view_removed, this);
|
|
217
|
+
this.graphics.views.elements.on.added.remove(this.__handle_view_added, this);
|
|
218
|
+
this.graphics.views.elements.on.removed.remove(this.__handle_view_removed, this);
|
|
219
|
+
|
|
159
220
|
readyCallback();
|
|
160
221
|
}
|
|
161
222
|
|
|
@@ -166,16 +227,16 @@ export class Foliage2System extends System {
|
|
|
166
227
|
|
|
167
228
|
/**
|
|
168
229
|
*
|
|
169
|
-
* @param {InstancedMeshComponent}
|
|
230
|
+
* @param {InstancedMeshComponent} instances
|
|
170
231
|
* @param entity
|
|
171
232
|
*/
|
|
172
|
-
link(
|
|
233
|
+
link(instances, entity) {
|
|
173
234
|
const layers = [];
|
|
174
235
|
const data = this.data;
|
|
175
236
|
|
|
176
237
|
data[entity] = layers;
|
|
177
238
|
|
|
178
|
-
const layerList =
|
|
239
|
+
const layerList = instances.layers;
|
|
179
240
|
const layer_count = layerList.length;
|
|
180
241
|
|
|
181
242
|
for (let i = 0; i < layer_count; i++) {
|
|
@@ -215,11 +276,16 @@ export class Foliage2System extends System {
|
|
|
215
276
|
}
|
|
216
277
|
}
|
|
217
278
|
|
|
218
|
-
//
|
|
219
|
-
|
|
279
|
+
//
|
|
280
|
+
this.graphics.views.elements.forEach(instances.add_view, instances);
|
|
220
281
|
}
|
|
221
282
|
|
|
222
|
-
|
|
283
|
+
/**
|
|
284
|
+
*
|
|
285
|
+
* @param {InstancedMeshComponent} instances
|
|
286
|
+
* @param {number} entity
|
|
287
|
+
*/
|
|
288
|
+
unlink(instances, entity) {
|
|
223
289
|
const renderLayer = this.renderLayer;
|
|
224
290
|
const layers = this.data[entity];
|
|
225
291
|
|
|
@@ -230,7 +296,9 @@ export class Foliage2System extends System {
|
|
|
230
296
|
cleanupLayer(layerData, renderLayer);
|
|
231
297
|
}
|
|
232
298
|
|
|
233
|
-
|
|
299
|
+
this.graphics.views.elements.forEach(instances.remove_view, instances);
|
|
300
|
+
|
|
301
|
+
instances.dispose();
|
|
234
302
|
|
|
235
303
|
delete this.data[entity];
|
|
236
304
|
}
|