@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.
- package/core/assert.js +11 -0
- package/core/binary/BitSet.js +5 -0
- package/core/bvh2/BinaryNode.js +880 -848
- package/core/bvh2/LeafNode.js +80 -82
- package/core/bvh2/Node.d.ts +3 -0
- package/core/bvh2/Node.js +111 -114
- package/core/bvh2/aabb3/AABB3.js +50 -4
- package/core/bvh2/aabb3/AABB3.spec.js +27 -1
- 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 +3 -4
- package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +13 -0
- package/core/geom/3d/triangle/computeTriangleRayIntersection.js +1 -2
- package/core/geom/Quaternion.d.ts +2 -0
- package/core/geom/Vector3.js +22 -11
- package/engine/asset/loaders/ArrayBufferLoader.js +7 -0
- package/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -6
- 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 +85 -152
- package/engine/ecs/foliage/ViewState.js +190 -0
- package/engine/ecs/foliage/ecs/Foliage2System.js +82 -19
- 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/camera/Camera.js +33 -16
- package/engine/graphics/ecs/camera/unprojectPoint.js +14 -0
- 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/sample/load_gltf.js +40 -8
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +3 -3
- package/engine/graphics/ecs/water2/shader/AlexWaterShader.js +7 -1
- 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 +12 -0
- 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/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +5 -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
|
|
233
|
-
|
|
234
|
-
//apply scale
|
|
235
|
-
v.multiply(scale);
|
|
225
|
+
const transform = new Float32Array(16);
|
|
236
226
|
|
|
237
|
-
|
|
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
|
-
|
|
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,60 @@ 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
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
instances.
|
|
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 {
|
|
366
|
-
* @param {function[]} [visibilityFilters]
|
|
332
|
+
* @param {CameraView} view
|
|
367
333
|
*/
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
this.bvhVisibilityVisitor.setFrustums(frustums);
|
|
334
|
+
remove_view(view) {
|
|
335
|
+
const state = this.__views.get(view);
|
|
372
336
|
|
|
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];
|
|
337
|
+
if (state === undefined) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
406
340
|
|
|
407
|
-
|
|
341
|
+
state.dispose();
|
|
408
342
|
|
|
343
|
+
this.__views.delete(view);
|
|
409
344
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const scaleZ = rowData[6];
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
413
347
|
|
|
414
|
-
|
|
348
|
+
/**
|
|
349
|
+
*
|
|
350
|
+
* @param {CameraView} view
|
|
351
|
+
* @return {ViewState}
|
|
352
|
+
*/
|
|
353
|
+
update(view) {
|
|
354
|
+
const state = this.__views.get(view);
|
|
415
355
|
|
|
416
|
-
|
|
356
|
+
state.update(this.bvh, this.data);
|
|
417
357
|
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
116
|
-
|
|
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
|
|
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(
|
|
140
|
+
const view_state = instances.update(view);
|
|
137
141
|
|
|
138
|
-
const group =
|
|
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}
|
|
225
|
+
* @param {InstancedMeshComponent} instances
|
|
170
226
|
* @param entity
|
|
171
227
|
*/
|
|
172
|
-
link(
|
|
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 =
|
|
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
|
-
//
|
|
219
|
-
|
|
274
|
+
//
|
|
275
|
+
this.graphics.views.elements.forEach(instances.add_view, instances);
|
|
220
276
|
}
|
|
221
277
|
|
|
222
|
-
|
|
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
|
-
|
|
294
|
+
this.graphics.views.elements.forEach(instances.remove_view, instances);
|
|
295
|
+
|
|
296
|
+
instances.dispose();
|
|
234
297
|
|
|
235
298
|
delete this.data[entity];
|
|
236
299
|
}
|