@woosh/meep-engine 2.46.26 → 2.46.28
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/package.json +1 -1
- package/src/core/bvh2/binary/2/BinaryUint32BVH.js +9 -12
- package/src/core/bvh2/bvh3/EBBVHLeafProxy.js +60 -0
- package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +1 -0
- package/src/core/collection/HashMap.js +21 -5
- package/src/core/events/signal/Signal.js +3 -3
- package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -10
- package/src/core/geom/3d/ray/ray3_array_apply_matrix4.js +15 -13
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +6 -24
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +4 -25
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +2 -6
- package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.d.ts +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +10 -43
- package/src/engine/graphics/render/forward_plus/LightManager.js +164 -56
- package/src/engine/graphics/render/forward_plus/{PointLightData.js → LightRenderMetadata.js} +18 -11
- package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash.js +1 -1
- package/src/engine/graphics/render/forward_plus/model/AbstractLight.js +1 -1
- package/src/engine/graphics/render/forward_plus/model/Decal.js +1 -4
- package/src/engine/graphics/render/forward_plus/model/PointLight.js +6 -12
- package/src/engine/graphics/render/forward_plus/model/SpotLight.js +0 -4
- package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts +3 -0
- package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +12 -0
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +3 -2
- package/src/engine/graphics/render/forward_plus/query/point_light_inside_volume.js +1 -1
- package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_objects.js +3 -3
- package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +1 -1
- package/src/engine/graphics/texture/atlas/CachingTextureAtlas.js +0 -1
- package/src/engine/intelligence/behavior/util/BranchBehavior.js +5 -0
- package/src/engine/plugin/EnginePluginManager.d.ts +2 -0
- package/src/engine/intelligence/behavior/util/SelectorBehavior.js +0 -83
package/package.json
CHANGED
|
@@ -119,10 +119,7 @@ function build_morton(data, address, matrix) {
|
|
|
119
119
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
const scratch_box_0 =
|
|
123
|
-
const scratch_box_1 = [];
|
|
124
|
-
const scratch_box_2 = [];
|
|
125
|
-
|
|
122
|
+
const scratch_box_0 = new Float32Array(18);
|
|
126
123
|
const stack = [];
|
|
127
124
|
|
|
128
125
|
export class BinaryUint32BVH {
|
|
@@ -294,16 +291,16 @@ export class BinaryUint32BVH {
|
|
|
294
291
|
*/
|
|
295
292
|
__compute_bounds_area_of_3_boxes(a, b, c) {
|
|
296
293
|
this.readBounds(a, scratch_box_0, 0);
|
|
297
|
-
this.readBounds(b,
|
|
298
|
-
this.readBounds(c,
|
|
294
|
+
this.readBounds(b, scratch_box_0, 6);
|
|
295
|
+
this.readBounds(c, scratch_box_0, 12);
|
|
299
296
|
|
|
300
|
-
const x0 = min3(scratch_box_0[0],
|
|
301
|
-
const y0 = min3(scratch_box_0[1],
|
|
302
|
-
const z0 = min3(scratch_box_0[2],
|
|
297
|
+
const x0 = min3(scratch_box_0[0], scratch_box_0[6], scratch_box_0[12]);
|
|
298
|
+
const y0 = min3(scratch_box_0[1], scratch_box_0[7], scratch_box_0[13]);
|
|
299
|
+
const z0 = min3(scratch_box_0[2], scratch_box_0[8], scratch_box_0[14]);
|
|
303
300
|
|
|
304
|
-
const x1 = max3(scratch_box_0[3],
|
|
305
|
-
const y1 = max3(scratch_box_0[4],
|
|
306
|
-
const z1 = max3(scratch_box_0[5],
|
|
301
|
+
const x1 = max3(scratch_box_0[3], scratch_box_0[9], scratch_box_0[15]);
|
|
302
|
+
const y1 = max3(scratch_box_0[4], scratch_box_0[10], scratch_box_0[16]);
|
|
303
|
+
const z1 = max3(scratch_box_0[5], scratch_box_0[11], scratch_box_0[17]);
|
|
307
304
|
|
|
308
305
|
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
|
|
309
306
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A convenience class to work with BVH leaf nodes
|
|
5
|
+
*/
|
|
6
|
+
export class EBBVHLeafProxy {
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @type {ExplicitBinaryBoundingVolumeHierarchy|null}
|
|
10
|
+
*/
|
|
11
|
+
#tree = null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @type {number}
|
|
16
|
+
*/
|
|
17
|
+
#node_id = -1;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @readonly
|
|
21
|
+
* @type {number[]}
|
|
22
|
+
*/
|
|
23
|
+
bounds = new Float32Array(6);
|
|
24
|
+
|
|
25
|
+
get is_linked(){
|
|
26
|
+
return this.#node_id !== -1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param {ExplicitBinaryBoundingVolumeHierarchy} tree
|
|
32
|
+
* @param {number} data Must be a uint32
|
|
33
|
+
*/
|
|
34
|
+
link(tree, data) {
|
|
35
|
+
assert.defined(tree, 'tree');
|
|
36
|
+
assert.isNonNegativeInteger(data, 'data');
|
|
37
|
+
|
|
38
|
+
this.#tree = tree;
|
|
39
|
+
|
|
40
|
+
const node_id = tree.allocate_node();
|
|
41
|
+
|
|
42
|
+
this.#node_id = node_id;
|
|
43
|
+
|
|
44
|
+
tree.node_set_aabb(node_id, this.bounds);
|
|
45
|
+
tree.node_set_user_data(node_id, data);
|
|
46
|
+
tree.insert_leaf(node_id);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
unlink() {
|
|
50
|
+
this.#tree.remove_leaf(this.#node_id);
|
|
51
|
+
this.#tree.release_node(this.#node_id);
|
|
52
|
+
|
|
53
|
+
this.#node_id = -1;
|
|
54
|
+
this.#tree = null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
write_bounds() {
|
|
58
|
+
this.#tree.node_move_aabb(this.#node_id, this.bounds);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -267,6 +267,7 @@ export class ExplicitBinaryBoundingVolumeHierarchy {
|
|
|
267
267
|
*/
|
|
268
268
|
node_set_user_data(id, value) {
|
|
269
269
|
assert.isNonNegativeInteger(id, 'id');
|
|
270
|
+
assert.isNonNegativeInteger(value, 'value');
|
|
270
271
|
|
|
271
272
|
this.__data_uint32[ELEMENT_WORD_COUNT * id + COLUMN_USER_DATA] = value;
|
|
272
273
|
}
|
|
@@ -11,8 +11,9 @@ class MapEntry {
|
|
|
11
11
|
*
|
|
12
12
|
* @param {K} key
|
|
13
13
|
* @param {V} value
|
|
14
|
+
* @param {number} hash
|
|
14
15
|
*/
|
|
15
|
-
constructor(key, value) {
|
|
16
|
+
constructor(key, value, hash) {
|
|
16
17
|
/**
|
|
17
18
|
*
|
|
18
19
|
* @type {K}
|
|
@@ -23,6 +24,12 @@ class MapEntry {
|
|
|
23
24
|
* @type {V}
|
|
24
25
|
*/
|
|
25
26
|
this.value = value;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @type {number}
|
|
31
|
+
*/
|
|
32
|
+
this.hash = hash;
|
|
26
33
|
}
|
|
27
34
|
}
|
|
28
35
|
|
|
@@ -219,7 +226,11 @@ export class HashMap {
|
|
|
219
226
|
|
|
220
227
|
const entryKey = entry.key;
|
|
221
228
|
|
|
222
|
-
|
|
229
|
+
|
|
230
|
+
if (
|
|
231
|
+
entry.hash === raw_hash
|
|
232
|
+
&& (entryKey === key || this.keyEqualityFunction(entryKey, key))
|
|
233
|
+
) {
|
|
223
234
|
|
|
224
235
|
// found record with matching key, replace the value
|
|
225
236
|
|
|
@@ -234,7 +245,7 @@ export class HashMap {
|
|
|
234
245
|
|
|
235
246
|
}
|
|
236
247
|
|
|
237
|
-
bucket.push(new MapEntry(key, value));
|
|
248
|
+
bucket.push(new MapEntry(key, value,raw_hash));
|
|
238
249
|
|
|
239
250
|
const old_size = this.size;
|
|
240
251
|
const new_size = old_size + 1;
|
|
@@ -269,8 +280,10 @@ export class HashMap {
|
|
|
269
280
|
|
|
270
281
|
const entryKey = entry.key;
|
|
271
282
|
|
|
272
|
-
if (
|
|
273
|
-
|
|
283
|
+
if (
|
|
284
|
+
entry.hash === raw_hash
|
|
285
|
+
&& (entryKey === key || this.keyEqualityFunction(entryKey, key))
|
|
286
|
+
) {
|
|
274
287
|
return entry.value;
|
|
275
288
|
|
|
276
289
|
}
|
|
@@ -432,6 +445,9 @@ export class HashMap {
|
|
|
432
445
|
|
|
433
446
|
//check hash
|
|
434
447
|
const raw_hash = this.keyHashFunction(entry.key);
|
|
448
|
+
|
|
449
|
+
entry.hash = raw_hash;
|
|
450
|
+
|
|
435
451
|
const actual_bucket_index = this.__compute_bucket_index(raw_hash);
|
|
436
452
|
|
|
437
453
|
|
|
@@ -147,7 +147,7 @@ export class Signal {
|
|
|
147
147
|
* @param {*} [context]
|
|
148
148
|
*/
|
|
149
149
|
addOne(h, context) {
|
|
150
|
-
assert.
|
|
150
|
+
assert.isFunction( h, "handler");
|
|
151
151
|
|
|
152
152
|
const handler = new SignalHandler(h, context);
|
|
153
153
|
|
|
@@ -195,8 +195,8 @@ export class Signal {
|
|
|
195
195
|
* Remove all handlers
|
|
196
196
|
*/
|
|
197
197
|
removeAll() {
|
|
198
|
-
const
|
|
199
|
-
|
|
198
|
+
const handlers = this.handlers;
|
|
199
|
+
handlers.splice(0, handlers.length);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
@@ -4,7 +4,7 @@ import { v3_angle_between } from "../../v3_angle_between.js";
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* NOTE: used stackoverflow answer as a basis for circle part: https://stackoverflow.com/questions/2592011/bounding-boxes-for-circle-and-arcs-in-3d
|
|
7
|
-
* @param {
|
|
7
|
+
* @param {number[]|ArrayLike<number>|Float32Array} result
|
|
8
8
|
* @param {number} originX
|
|
9
9
|
* @param {number} originY
|
|
10
10
|
* @param {number} originZ
|
|
@@ -41,14 +41,11 @@ export function computeConeBoundingBox(result, originX, originY, originZ, direct
|
|
|
41
41
|
const cz1 = centerZ + rZ;
|
|
42
42
|
|
|
43
43
|
//combine bounds of the origin and base of the cone
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
result[0] = min2(originX, cx0);
|
|
45
|
+
result[1] = min2(originY, cy0);
|
|
46
|
+
result[2] = min2(originZ, cz0);
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
//write result
|
|
53
|
-
result.setBounds(x0, y0, z0, x1, y1, z1);
|
|
48
|
+
result[3] = max2(originX, cx1);
|
|
49
|
+
result[4] = max2(originY, cy1);
|
|
50
|
+
result[5] = max2(originZ, cz1);
|
|
54
51
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
*
|
|
3
3
|
* @param {number[]|ArrayLike<number>|Float32Array} output 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
4
|
+
* @param {number} output_offset
|
|
4
5
|
* @param {number[]|ArrayLike<number>|Float32Array} input 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
6
|
+
* @param {number} input_offset
|
|
5
7
|
* @param {number[]|ArrayLike<number>|Float32Array} m4 4x4 matrix
|
|
6
8
|
* @returns {boolean} false if matrix transformation is impossible, such as when scale of the matrix is 0
|
|
7
9
|
*/
|
|
8
|
-
export function ray3_array_apply_matrix4(output, input, m4) {
|
|
9
|
-
const origin_x = input[0];
|
|
10
|
-
const origin_y = input[1];
|
|
11
|
-
const origin_z = input[2];
|
|
10
|
+
export function ray3_array_apply_matrix4(output, output_offset, input, input_offset, m4) {
|
|
11
|
+
const origin_x = input[input_offset + 0];
|
|
12
|
+
const origin_y = input[input_offset + 1];
|
|
13
|
+
const origin_z = input[input_offset + 2];
|
|
12
14
|
|
|
13
|
-
const direction_x = input[3];
|
|
14
|
-
const direction_y = input[4];
|
|
15
|
-
const direction_z = input[5];
|
|
15
|
+
const direction_x = input[input_offset + 3];
|
|
16
|
+
const direction_y = input[input_offset + 4];
|
|
17
|
+
const direction_z = input[input_offset + 5];
|
|
16
18
|
|
|
17
19
|
// transform ray to local space (inlined for speed)
|
|
18
20
|
const det = m4[3] * origin_x + m4[7] * origin_y + m4[11] * origin_z + m4[15];
|
|
@@ -44,13 +46,13 @@ export function ray3_array_apply_matrix4(output, input, m4) {
|
|
|
44
46
|
const out_direction_normalized_y = out_direction_y * out_direction_magnitude_inverse;
|
|
45
47
|
const out_direction_normalized_z = out_direction_z * out_direction_magnitude_inverse;
|
|
46
48
|
|
|
47
|
-
output[0] = out_origin_x;
|
|
48
|
-
output[1] = out_origin_y;
|
|
49
|
-
output[2] = out_origin_z;
|
|
49
|
+
output[output_offset + 0] = out_origin_x;
|
|
50
|
+
output[output_offset + 1] = out_origin_y;
|
|
51
|
+
output[output_offset + 2] = out_origin_z;
|
|
50
52
|
|
|
51
|
-
output[3] = out_direction_normalized_x;
|
|
52
|
-
output[4] = out_direction_normalized_y;
|
|
53
|
-
output[5] = out_direction_normalized_z;
|
|
53
|
+
output[output_offset + 3] = out_direction_normalized_x;
|
|
54
|
+
output[output_offset + 4] = out_direction_normalized_y;
|
|
55
|
+
output[output_offset + 5] = out_direction_normalized_z;
|
|
54
56
|
|
|
55
57
|
return true;
|
|
56
58
|
}
|
|
@@ -6,6 +6,7 @@ import { mat4 } from "gl-matrix";
|
|
|
6
6
|
import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
|
|
7
7
|
import { GeometrySpatialQueryAccelerator } from "../../geometry/buffered/query/GeometrySpatialQueryAccelerator.js";
|
|
8
8
|
import { assert } from "../../../../core/assert.js";
|
|
9
|
+
import { EBBVHLeafProxy } from "../../../../core/bvh2/bvh3/EBBVHLeafProxy.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @readonly
|
|
@@ -55,26 +56,7 @@ export class ShadedGeometry {
|
|
|
55
56
|
*/
|
|
56
57
|
this.depth_material = null;
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
*
|
|
60
|
-
* @type {number}
|
|
61
|
-
* @private
|
|
62
|
-
*/
|
|
63
|
-
this.__bvh_leaf_id = -1;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
*
|
|
67
|
-
* @type {ExplicitBinaryBoundingVolumeHierarchy|null}
|
|
68
|
-
* @private
|
|
69
|
-
*/
|
|
70
|
-
this.__bvh_tree = null;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* @readonly
|
|
74
|
-
* @type {number[]|Float32Array}
|
|
75
|
-
* @private
|
|
76
|
-
*/
|
|
77
|
-
this.__bvh_aabb = new Float32Array(6);
|
|
59
|
+
this.__bvh_leaf = new EBBVHLeafProxy();
|
|
78
60
|
|
|
79
61
|
/**
|
|
80
62
|
* Transient, assigned in the system
|
|
@@ -240,7 +222,7 @@ export class ShadedGeometry {
|
|
|
240
222
|
* @param {AABB3} destination
|
|
241
223
|
*/
|
|
242
224
|
getBoundingBox(destination) {
|
|
243
|
-
const aabb = this.
|
|
225
|
+
const aabb = this.__bvh_leaf.bounds;
|
|
244
226
|
|
|
245
227
|
destination.readFromArray(aabb);
|
|
246
228
|
}
|
|
@@ -280,7 +262,7 @@ export class ShadedGeometry {
|
|
|
280
262
|
updateTransform() {
|
|
281
263
|
this.update_bounds();
|
|
282
264
|
|
|
283
|
-
this.
|
|
265
|
+
this.__bvh_leaf.write_bounds();
|
|
284
266
|
}
|
|
285
267
|
|
|
286
268
|
update_bounds() {
|
|
@@ -317,7 +299,7 @@ export class ShadedGeometry {
|
|
|
317
299
|
scratch_aabb3_array[4] = y1;
|
|
318
300
|
scratch_aabb3_array[5] = z1;
|
|
319
301
|
|
|
320
|
-
aabb3_matrix4_project(this.
|
|
302
|
+
aabb3_matrix4_project(this.__bvh_leaf.bounds, scratch_aabb3_array, this.transform);
|
|
321
303
|
}
|
|
322
304
|
|
|
323
305
|
/**
|
|
@@ -333,7 +315,7 @@ export class ShadedGeometry {
|
|
|
333
315
|
mat4.invert(scratch_m4, transform_matrix4);
|
|
334
316
|
|
|
335
317
|
// transform ray to local space
|
|
336
|
-
if (!ray3_array_apply_matrix4(scratch_ray_0, ray, scratch_m4)) {
|
|
318
|
+
if (!ray3_array_apply_matrix4(scratch_ray_0,0, ray,0, scratch_m4)) {
|
|
337
319
|
// invalid transform matrix
|
|
338
320
|
return false;
|
|
339
321
|
}
|
|
@@ -289,25 +289,13 @@ export class ShadedGeometrySystem extends System {
|
|
|
289
289
|
|
|
290
290
|
sg.update_bounds();
|
|
291
291
|
|
|
292
|
-
t.
|
|
293
|
-
t.rotation.onChanged.add(sg.updateTransform, sg);
|
|
294
|
-
t.scale.onChanged.add(sg.updateTransform, sg);
|
|
292
|
+
t.subscribeAllChanges(sg.updateTransform, sg);
|
|
295
293
|
|
|
296
294
|
// remember entity for lookups
|
|
297
295
|
sg.__entity = entity;
|
|
298
296
|
|
|
299
297
|
// insert BVH entry
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const bvh_node_id = bvh.allocate_node();
|
|
303
|
-
|
|
304
|
-
bvh.node_set_aabb(bvh_node_id, sg.__bvh_aabb);
|
|
305
|
-
bvh.node_set_user_data(bvh_node_id, entity);
|
|
306
|
-
bvh.insert_leaf(bvh_node_id);
|
|
307
|
-
|
|
308
|
-
sg.__bvh_tree = bvh;
|
|
309
|
-
sg.__bvh_leaf_id = bvh_node_id;
|
|
310
|
-
|
|
298
|
+
sg.__bvh_leaf.link(this.__bvh_binary, entity);
|
|
311
299
|
|
|
312
300
|
// update usage count
|
|
313
301
|
const geometry_id = sg.geometry.id;
|
|
@@ -324,19 +312,10 @@ export class ShadedGeometrySystem extends System {
|
|
|
324
312
|
* @param {number} entity
|
|
325
313
|
*/
|
|
326
314
|
unlink(sg, t, entity) {
|
|
327
|
-
t.
|
|
328
|
-
t.rotation.onChanged.remove(sg.updateTransform, sg);
|
|
329
|
-
t.scale.onChanged.remove(sg.updateTransform, sg);
|
|
315
|
+
t.unsubscribeAllChanges(sg.updateTransform, sg);
|
|
330
316
|
|
|
331
317
|
// disconnect BVH
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
this.__bvh_binary.remove_leaf(node_id);
|
|
335
|
-
this.__bvh_binary.release_node(node_id);
|
|
336
|
-
|
|
337
|
-
// reset BVH references
|
|
338
|
-
sg.__bvh_leaf_id = -1;
|
|
339
|
-
sg.__bvh_tree = null;
|
|
318
|
+
sg.__bvh_leaf.unlink();
|
|
340
319
|
|
|
341
320
|
const geometry_id = sg.geometry.id;
|
|
342
321
|
const count_existing = this.__geometry_usage_counters.get(geometry_id);
|
|
@@ -162,15 +162,11 @@ export class SGMeshSystem extends System {
|
|
|
162
162
|
|
|
163
163
|
entity_node.build(ecd);
|
|
164
164
|
|
|
165
|
-
transform.
|
|
166
|
-
transform.rotation.onChanged.add(copy_transform);
|
|
167
|
-
transform.scale.onChanged.add(copy_transform);
|
|
165
|
+
transform.subscribeAllChanges(copy_transform);
|
|
168
166
|
|
|
169
167
|
entity_node.on.destroyed.addOne(() => {
|
|
170
168
|
|
|
171
|
-
transform.
|
|
172
|
-
transform.rotation.onChanged.remove(copy_transform);
|
|
173
|
-
transform.scale.onChanged.remove(copy_transform);
|
|
169
|
+
transform.unsubscribeAllChanges(copy_transform);
|
|
174
170
|
|
|
175
171
|
});
|
|
176
172
|
|
|
@@ -194,7 +194,7 @@ export class BVHGeometryRaycaster {
|
|
|
194
194
|
directionX, directionY, directionZ
|
|
195
195
|
);
|
|
196
196
|
|
|
197
|
-
ray3_array_apply_matrix4(ray_tmp, ray_tmp, m4_tmp);
|
|
197
|
+
ray3_array_apply_matrix4(ray_tmp, 0,ray_tmp,0, m4_tmp);
|
|
198
198
|
|
|
199
199
|
const _originX = ray_tmp[0];
|
|
200
200
|
const _originY = ray_tmp[1];
|
|
@@ -11,5 +11,5 @@ export class ParameterLookupTable {
|
|
|
11
11
|
|
|
12
12
|
write(value: number[], positions: number[]): void
|
|
13
13
|
|
|
14
|
-
static from(itemSize: number, value: number[], positions
|
|
14
|
+
static from(itemSize: number, value: number[], positions?: number[]): ParameterLookupTable
|
|
15
15
|
}
|
|
@@ -6,6 +6,7 @@ import { ParameterLookupTableFlags } from "./ParameterLookupTableFlags.js";
|
|
|
6
6
|
import { ParameterLookupTableSerializationAdapter } from "../emitter/serde/ParameterLookupTableSerializationAdapter.js";
|
|
7
7
|
import { computeHashIntegerArray } from "../../../../../../core/collection/array/computeHashIntegerArray.js";
|
|
8
8
|
import { computeHashFloatArray } from "../../../../../../core/math/hash/computeHashFloatArray.js";
|
|
9
|
+
import { isArrayEqualStrict } from "../../../../../../core/collection/array/isArrayEqualStrict.js";
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
export class ParameterLookupTable {
|
|
@@ -211,7 +212,7 @@ export class ParameterLookupTable {
|
|
|
211
212
|
|
|
212
213
|
if (positions === undefined) {
|
|
213
214
|
|
|
214
|
-
console.warn('positions are undefined, assuming uniform distribution');
|
|
215
|
+
//console.warn('positions are undefined, assuming uniform distribution');
|
|
215
216
|
this.computeUniformPositions();
|
|
216
217
|
|
|
217
218
|
} else {
|
|
@@ -309,52 +310,18 @@ export class ParameterLookupTable {
|
|
|
309
310
|
* @returns {boolean}
|
|
310
311
|
*/
|
|
311
312
|
equals(other) {
|
|
312
|
-
if
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const thisData = this.data;
|
|
317
|
-
const otherData = other.data;
|
|
318
|
-
|
|
319
|
-
const thisDataLength = thisData.length;
|
|
320
|
-
const otherDataLength = otherData.length;
|
|
321
|
-
|
|
322
|
-
if (thisDataLength !== otherDataLength) {
|
|
323
|
-
return false;
|
|
313
|
+
if(this === other){
|
|
314
|
+
// identity shortcut
|
|
315
|
+
return true;
|
|
324
316
|
}
|
|
325
317
|
|
|
326
|
-
|
|
327
|
-
const otherPositions = other.positions;
|
|
328
|
-
|
|
329
|
-
const thisPositionsLength = thisPositions.length;
|
|
330
|
-
const otherPositionsLength = otherPositions.length;
|
|
331
|
-
|
|
332
|
-
if (thisPositionsLength !== otherPositionsLength) {
|
|
318
|
+
if (this.itemSize !== other.itemSize) {
|
|
333
319
|
return false;
|
|
334
320
|
}
|
|
335
321
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const pA = thisPositions[i];
|
|
340
|
-
const pB = otherPositions[i];
|
|
341
|
-
|
|
342
|
-
if (pA !== pB) {
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
for (i = 0; i < thisDataLength; i++) {
|
|
348
|
-
const dA = thisData[i];
|
|
349
|
-
const dB = otherData[i];
|
|
350
|
-
|
|
351
|
-
if (dA !== dB) {
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
//equal
|
|
357
|
-
return true;
|
|
322
|
+
return isArrayEqualStrict(this.data, other.data)
|
|
323
|
+
&& isArrayEqualStrict(this.positions, other.positions)
|
|
324
|
+
;
|
|
358
325
|
}
|
|
359
326
|
|
|
360
327
|
validate() {
|
|
@@ -408,7 +375,7 @@ export class ParameterLookupTable {
|
|
|
408
375
|
static from(itemSize, values, positions) {
|
|
409
376
|
const r = new ParameterLookupTable(itemSize);
|
|
410
377
|
|
|
411
|
-
r.write(values, positions)
|
|
378
|
+
r.write(values, positions);
|
|
412
379
|
|
|
413
380
|
return r;
|
|
414
381
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PointLightData } from "./PointLightData.js";
|
|
1
|
+
import { LightRenderMetadata } from "./LightRenderMetadata.js";
|
|
3
2
|
import {
|
|
4
3
|
ClampToEdgeWrapping,
|
|
5
4
|
DataTexture,
|
|
@@ -14,7 +13,6 @@ import {
|
|
|
14
13
|
UnsignedShortType
|
|
15
14
|
} from "three";
|
|
16
15
|
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
17
|
-
import { query_bvh_frustum_from_objects } from "./query/query_bvh_frustum_from_objects.js";
|
|
18
16
|
import { IncrementalDeltaSet } from "../visibility/IncrementalDeltaSet.js";
|
|
19
17
|
import { computeFrustumCorners } from "./computeFrustumCorners.js";
|
|
20
18
|
import { read_plane_pair } from "./cluster/read_plane_pair.js";
|
|
@@ -42,10 +40,19 @@ import { array_copy } from "../../../../core/collection/array/copyArray.js";
|
|
|
42
40
|
import { arrayQuickSort } from "../../../../core/collection/array/arrayQuickSort.js";
|
|
43
41
|
import { frustum_from_camera } from "../../ecs/camera/frustum_from_camera.js";
|
|
44
42
|
import { arraySwapElements } from "../../../../core/collection/array/arraySwapElements.js";
|
|
45
|
-
import { compareObjectsByNumericId } from "../../../../core/model/object/compareObjectsByNumericId.js";
|
|
46
43
|
import { slice_frustum_linear_to_points } from "../../../../core/geom/3d/frustum/slice_frustum_linear_to_points.js";
|
|
47
44
|
import { read_cluster_frustum_corners } from "../../../../core/geom/3d/frustum/read_cluster_frustum_corners.js";
|
|
48
45
|
import { assign_cluster, LOOKUP_CACHE, scratch_corners, scratch_frustum_planes } from "./assign_cluster.js";
|
|
46
|
+
import {
|
|
47
|
+
ExplicitBinaryBoundingVolumeHierarchy
|
|
48
|
+
} from "../../../../core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
49
|
+
import {
|
|
50
|
+
bvh_query_user_data_overlaps_frustum
|
|
51
|
+
} from "../../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_frustum.js";
|
|
52
|
+
import { point_light_inside_volume } from "./query/point_light_inside_volume.js";
|
|
53
|
+
import { bvh_query_leaves_ray } from "../../../../core/bvh2/bvh3/query/bvh_query_leaves_ray.js";
|
|
54
|
+
import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
|
|
55
|
+
import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
|
|
49
56
|
|
|
50
57
|
|
|
51
58
|
/**
|
|
@@ -82,7 +89,7 @@ function encode_light_descriptor(address, light) {
|
|
|
82
89
|
|
|
83
90
|
/**
|
|
84
91
|
*
|
|
85
|
-
* @param {IncrementalDeltaSet<
|
|
92
|
+
* @param {IncrementalDeltaSet<LightRenderMetadata>} data_set
|
|
86
93
|
* @param {BinaryUint32BVH} bvh
|
|
87
94
|
*/
|
|
88
95
|
function build_light_data_bvh(data_set, bvh) {
|
|
@@ -96,18 +103,18 @@ function build_light_data_bvh(data_set, bvh) {
|
|
|
96
103
|
|
|
97
104
|
/**
|
|
98
105
|
*
|
|
99
|
-
* @type {
|
|
106
|
+
* @type {LightRenderMetadata}
|
|
100
107
|
*/
|
|
101
108
|
const datum = elements[i];
|
|
102
109
|
|
|
103
|
-
const bb = datum.
|
|
110
|
+
const bb = datum.bvh_leaf.bounds;
|
|
104
111
|
|
|
105
112
|
const payload = encode_light_descriptor(datum.address, datum.light);
|
|
106
113
|
|
|
107
114
|
bvh.setLeafData(
|
|
108
115
|
i, payload,
|
|
109
|
-
bb
|
|
110
|
-
bb
|
|
116
|
+
bb[0], bb[1], bb[2],
|
|
117
|
+
bb[3], bb[4], bb[5],
|
|
111
118
|
);
|
|
112
119
|
}
|
|
113
120
|
|
|
@@ -117,22 +124,32 @@ function build_light_data_bvh(data_set, bvh) {
|
|
|
117
124
|
bvh.build();
|
|
118
125
|
}
|
|
119
126
|
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
* @param {LightRenderMetadata} a
|
|
130
|
+
* @param {LightRenderMetadata} b
|
|
131
|
+
* @returns {number}
|
|
132
|
+
*/
|
|
133
|
+
function compareLRMByLightId(a, b) {
|
|
134
|
+
return b.light.id - a.light.id;
|
|
135
|
+
}
|
|
136
|
+
|
|
120
137
|
export class LightManager {
|
|
121
138
|
|
|
122
|
-
|
|
139
|
+
/**
|
|
140
|
+
* @readonly
|
|
141
|
+
* @type {ExplicitBinaryBoundingVolumeHierarchy}
|
|
142
|
+
*/
|
|
143
|
+
#light_data_bvh = new ExplicitBinaryBoundingVolumeHierarchy();
|
|
123
144
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Mapping from a light/decal object ID internal metadata
|
|
147
|
+
* @type {Map<number,LightRenderMetadata>}
|
|
148
|
+
*/
|
|
149
|
+
#metadata_map = new Map();
|
|
129
150
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
* @type {Map<AbstractLight, PointLightData>}
|
|
133
|
-
* @private
|
|
134
|
-
*/
|
|
135
|
-
this.__light_data_map = new Map();
|
|
151
|
+
|
|
152
|
+
constructor() {
|
|
136
153
|
|
|
137
154
|
/**
|
|
138
155
|
* Number of cluster slices along each dimension
|
|
@@ -235,22 +252,22 @@ export class LightManager {
|
|
|
235
252
|
|
|
236
253
|
/**
|
|
237
254
|
*
|
|
238
|
-
* @type {IncrementalDeltaSet<
|
|
255
|
+
* @type {IncrementalDeltaSet<LightRenderMetadata>}
|
|
239
256
|
* @readonly
|
|
240
257
|
* @private
|
|
241
258
|
*/
|
|
242
|
-
this.__visible_lights = new IncrementalDeltaSet(
|
|
259
|
+
this.__visible_lights = new IncrementalDeltaSet(compareLRMByLightId);
|
|
243
260
|
/**
|
|
244
261
|
*
|
|
245
|
-
* @type {IncrementalDeltaSet<
|
|
262
|
+
* @type {IncrementalDeltaSet<LightRenderMetadata>}
|
|
246
263
|
* @readonly
|
|
247
264
|
* @private
|
|
248
265
|
*/
|
|
249
|
-
this.__visible_decals = new IncrementalDeltaSet(
|
|
266
|
+
this.__visible_decals = new IncrementalDeltaSet(compareLRMByLightId);
|
|
250
267
|
|
|
251
268
|
/**
|
|
252
269
|
*
|
|
253
|
-
* @type {
|
|
270
|
+
* @type {LightRenderMetadata[]}
|
|
254
271
|
* @private
|
|
255
272
|
*/
|
|
256
273
|
this.__sorted_visible_lights = [];
|
|
@@ -487,7 +504,7 @@ export class LightManager {
|
|
|
487
504
|
|
|
488
505
|
/**
|
|
489
506
|
*
|
|
490
|
-
* @param {
|
|
507
|
+
* @param {LightRenderMetadata} data
|
|
491
508
|
* @private
|
|
492
509
|
*/
|
|
493
510
|
__handle_visible_decal_added(data) {
|
|
@@ -519,7 +536,7 @@ export class LightManager {
|
|
|
519
536
|
|
|
520
537
|
/**
|
|
521
538
|
*
|
|
522
|
-
* @param {
|
|
539
|
+
* @param {LightRenderMetadata} data
|
|
523
540
|
* @private
|
|
524
541
|
*/
|
|
525
542
|
__handle_visible_decal_removed(data) {
|
|
@@ -556,7 +573,7 @@ export class LightManager {
|
|
|
556
573
|
|
|
557
574
|
/**
|
|
558
575
|
*
|
|
559
|
-
* @param {
|
|
576
|
+
* @param {LightRenderMetadata} data
|
|
560
577
|
* @private
|
|
561
578
|
*/
|
|
562
579
|
__handle_visible_light_added(data) {
|
|
@@ -569,7 +586,7 @@ export class LightManager {
|
|
|
569
586
|
|
|
570
587
|
/**
|
|
571
588
|
*
|
|
572
|
-
* @param {
|
|
589
|
+
* @param {LightRenderMetadata} data
|
|
573
590
|
* @private
|
|
574
591
|
*/
|
|
575
592
|
__handle_visible_light_removed(data) {
|
|
@@ -581,7 +598,7 @@ export class LightManager {
|
|
|
581
598
|
|
|
582
599
|
/**
|
|
583
600
|
*
|
|
584
|
-
* @param {
|
|
601
|
+
* @param {LightRenderMetadata} light
|
|
585
602
|
* @returns {number}
|
|
586
603
|
* @protected
|
|
587
604
|
*/
|
|
@@ -599,7 +616,7 @@ export class LightManager {
|
|
|
599
616
|
|
|
600
617
|
/**
|
|
601
618
|
* DEBUG method
|
|
602
|
-
* @param {
|
|
619
|
+
* @param {LightRenderMetadata} lights
|
|
603
620
|
* @param {number} count
|
|
604
621
|
* @returns {number} lower = better sorting score
|
|
605
622
|
* @private
|
|
@@ -696,7 +713,7 @@ export class LightManager {
|
|
|
696
713
|
|
|
697
714
|
/**
|
|
698
715
|
*
|
|
699
|
-
* @type {IncrementalDeltaSet<
|
|
716
|
+
* @type {IncrementalDeltaSet<LightRenderMetadata>}
|
|
700
717
|
*/
|
|
701
718
|
const visible_lights = this.__visible_lights;
|
|
702
719
|
|
|
@@ -710,20 +727,54 @@ export class LightManager {
|
|
|
710
727
|
|
|
711
728
|
read_frustum_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes)
|
|
712
729
|
|
|
713
|
-
|
|
730
|
+
/*
|
|
731
|
+
Search is done in 2 phases:
|
|
732
|
+
1) broad phase using bounding boxes
|
|
733
|
+
2) granular phase where we use object-specific shape to check against frustum
|
|
734
|
+
*/
|
|
735
|
+
|
|
736
|
+
const broad_match_count = bvh_query_user_data_overlaps_frustum(nodes, 0, this.#light_data_bvh, scratch_frustum_planes);
|
|
737
|
+
|
|
738
|
+
for (let i = 0; i < broad_match_count; i++) {
|
|
714
739
|
|
|
715
|
-
|
|
740
|
+
const light_id = nodes[i];
|
|
716
741
|
|
|
717
742
|
/**
|
|
718
743
|
*
|
|
719
|
-
* @type {
|
|
744
|
+
* @type {LightRenderMetadata}
|
|
720
745
|
*/
|
|
721
|
-
const light_data =
|
|
746
|
+
const light_data = this.#metadata_map.get(light_id);
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
*
|
|
750
|
+
* @type {PointLight|Decal}
|
|
751
|
+
*/
|
|
752
|
+
const light = light_data.light;
|
|
753
|
+
|
|
754
|
+
if (light.isDecal === true) {
|
|
755
|
+
|
|
722
756
|
|
|
723
|
-
if (light_data.light instanceof Decal) {
|
|
724
757
|
// decals go into a separate bucket
|
|
725
758
|
visible_decals.push(light_data);
|
|
726
|
-
|
|
759
|
+
|
|
760
|
+
} else if (light.isPointLight === true) {
|
|
761
|
+
// perform granular check
|
|
762
|
+
|
|
763
|
+
const light_position = light.position;
|
|
764
|
+
|
|
765
|
+
const light_x = light_position.x;
|
|
766
|
+
const light_y = light_position.y;
|
|
767
|
+
const light_z = light_position.z;
|
|
768
|
+
|
|
769
|
+
const radius = light.radius.getValue();
|
|
770
|
+
|
|
771
|
+
if (!point_light_inside_volume(light_x, light_y, light_z, radius, this.__view_frustum_points, scratch_frustum_planes)) {
|
|
772
|
+
// outside of view frustum
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
// register as visible
|
|
727
778
|
visible_lights.push(light_data);
|
|
728
779
|
}
|
|
729
780
|
|
|
@@ -738,7 +789,7 @@ export class LightManager {
|
|
|
738
789
|
|
|
739
790
|
/**
|
|
740
791
|
*
|
|
741
|
-
* @type {
|
|
792
|
+
* @type {LightRenderMetadata[]}
|
|
742
793
|
*/
|
|
743
794
|
const visible_lights = this.__sorted_visible_lights;
|
|
744
795
|
|
|
@@ -1082,17 +1133,17 @@ export class LightManager {
|
|
|
1082
1133
|
* @param {number} z
|
|
1083
1134
|
*/
|
|
1084
1135
|
setTileMapResolution(x, y, z) {
|
|
1085
|
-
assert.isNumber(x,'x');
|
|
1086
|
-
assert.isNonNegativeInteger(x,'x');
|
|
1087
|
-
assert.isFiniteNumber(x,'x');
|
|
1136
|
+
assert.isNumber(x, 'x');
|
|
1137
|
+
assert.isNonNegativeInteger(x, 'x');
|
|
1138
|
+
assert.isFiniteNumber(x, 'x');
|
|
1088
1139
|
|
|
1089
|
-
assert.isNumber(y,'y');
|
|
1090
|
-
assert.isNonNegativeInteger(y,'y');
|
|
1091
|
-
assert.isFiniteNumber(y,'y');
|
|
1140
|
+
assert.isNumber(y, 'y');
|
|
1141
|
+
assert.isNonNegativeInteger(y, 'y');
|
|
1142
|
+
assert.isFiniteNumber(y, 'y');
|
|
1092
1143
|
|
|
1093
|
-
assert.isNumber(z,'z');
|
|
1094
|
-
assert.isNonNegativeInteger(z,'z');
|
|
1095
|
-
assert.isFiniteNumber(z,'z');
|
|
1144
|
+
assert.isNumber(z, 'z');
|
|
1145
|
+
assert.isNonNegativeInteger(z, 'z');
|
|
1146
|
+
assert.isFiniteNumber(z, 'z');
|
|
1096
1147
|
|
|
1097
1148
|
const r = this.__tiles_resolution;
|
|
1098
1149
|
|
|
@@ -1126,13 +1177,11 @@ export class LightManager {
|
|
|
1126
1177
|
* @param {AbstractLight} light
|
|
1127
1178
|
*/
|
|
1128
1179
|
addLight(light) {
|
|
1129
|
-
const lightData = new
|
|
1130
|
-
|
|
1131
|
-
lightData.link();
|
|
1180
|
+
const lightData = new LightRenderMetadata(light);
|
|
1132
1181
|
|
|
1133
|
-
|
|
1182
|
+
lightData.link(this.#light_data_bvh);
|
|
1134
1183
|
|
|
1135
|
-
this.
|
|
1184
|
+
this.#metadata_map.set(light.id, lightData);
|
|
1136
1185
|
}
|
|
1137
1186
|
|
|
1138
1187
|
/**
|
|
@@ -1142,7 +1191,9 @@ export class LightManager {
|
|
|
1142
1191
|
*/
|
|
1143
1192
|
removeLight(light) {
|
|
1144
1193
|
|
|
1145
|
-
const
|
|
1194
|
+
const light_id = light.id;
|
|
1195
|
+
|
|
1196
|
+
const data = this.#metadata_map.get(light_id);
|
|
1146
1197
|
|
|
1147
1198
|
if (data === undefined) {
|
|
1148
1199
|
return false;
|
|
@@ -1150,8 +1201,65 @@ export class LightManager {
|
|
|
1150
1201
|
|
|
1151
1202
|
data.unlink();
|
|
1152
1203
|
|
|
1153
|
-
this.
|
|
1204
|
+
this.#metadata_map.delete(light_id);
|
|
1154
1205
|
|
|
1155
1206
|
return true;
|
|
1156
1207
|
}
|
|
1208
|
+
|
|
1209
|
+
/**
|
|
1210
|
+
*
|
|
1211
|
+
* @param {Decal[]} result
|
|
1212
|
+
* @param {number} result_offset
|
|
1213
|
+
* @param {number[]} query
|
|
1214
|
+
* @param {number} query_offset
|
|
1215
|
+
* @returns {number} number of elements added to the result
|
|
1216
|
+
*/
|
|
1217
|
+
query_decals_by_ray(result, result_offset, query, query_offset) {
|
|
1218
|
+
|
|
1219
|
+
const leaves = [];
|
|
1220
|
+
const local_ray = new Float32Array(6);
|
|
1221
|
+
|
|
1222
|
+
const hit_count = bvh_query_leaves_ray(this.#light_data_bvh, leaves, 0,
|
|
1223
|
+
query[query_offset], query[query_offset + 1], query[query_offset + 2],
|
|
1224
|
+
query[query_offset + 3], query[query_offset + 4], query[query_offset + 5]
|
|
1225
|
+
);
|
|
1226
|
+
|
|
1227
|
+
let result_count = 0;
|
|
1228
|
+
|
|
1229
|
+
for (let i = 0; i < hit_count; i++) {
|
|
1230
|
+
const node = leaves[i];
|
|
1231
|
+
const light_id = this.#light_data_bvh.node_get_user_data(node);
|
|
1232
|
+
|
|
1233
|
+
const metadata = this.#metadata_map.get(light_id);
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
*
|
|
1237
|
+
* @type {Decal}
|
|
1238
|
+
*/
|
|
1239
|
+
const prop = metadata.light;
|
|
1240
|
+
|
|
1241
|
+
if (prop.isDecal !== true) {
|
|
1242
|
+
// wrong prop type
|
|
1243
|
+
continue;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// transform ray into decal's local space
|
|
1247
|
+
ray3_array_apply_matrix4(local_ray, 0, query, query_offset, prop.transform_inverse);
|
|
1248
|
+
|
|
1249
|
+
if (aabb3_intersects_ray(
|
|
1250
|
+
-0.5, -0.5, -0.5,
|
|
1251
|
+
0.5, 0.5, 0.5,
|
|
1252
|
+
|
|
1253
|
+
local_ray[0], local_ray[1], local_ray[2],
|
|
1254
|
+
local_ray[3], local_ray[4], local_ray[5],
|
|
1255
|
+
)) {
|
|
1256
|
+
result[result_offset + result_count] = prop;
|
|
1257
|
+
|
|
1258
|
+
result_count++;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
return result_count;
|
|
1264
|
+
}
|
|
1157
1265
|
}
|
package/src/engine/graphics/render/forward_plus/{PointLightData.js → LightRenderMetadata.js}
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EBBVHLeafProxy } from "../../../../core/bvh2/bvh3/EBBVHLeafProxy.js";
|
|
2
|
+
|
|
3
|
+
export class LightRenderMetadata {
|
|
4
|
+
|
|
2
5
|
|
|
3
|
-
export class PointLightData {
|
|
4
6
|
/**
|
|
5
7
|
*
|
|
6
8
|
* @param {AbstractLight} light
|
|
@@ -18,12 +20,12 @@ export class PointLightData {
|
|
|
18
20
|
*/
|
|
19
21
|
this.address = 0;
|
|
20
22
|
|
|
21
|
-
this.
|
|
23
|
+
this.bvh_leaf = new EBBVHLeafProxy();
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
*
|
|
26
|
-
* @param {
|
|
28
|
+
* @param {LightRenderMetadata} other
|
|
27
29
|
* @returns {number}
|
|
28
30
|
*/
|
|
29
31
|
compare(other) {
|
|
@@ -31,17 +33,22 @@ export class PointLightData {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
update() {
|
|
36
|
+
const leaf = this.bvh_leaf;
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
this.light.getAABB(leaf.bounds);
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (leaf.parentNode !== null) {
|
|
40
|
-
leaf.parentNode.bubbleRefit();
|
|
40
|
+
if (leaf.is_linked) {
|
|
41
|
+
leaf.write_bounds();
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
|
|
48
|
+
*/
|
|
49
|
+
link(bvh) {
|
|
50
|
+
this.bvh_leaf.link(bvh, this.light.id);
|
|
51
|
+
|
|
45
52
|
this.update();
|
|
46
53
|
|
|
47
54
|
this.light.onDimensionChanged(this.update, this);
|
|
@@ -52,6 +59,6 @@ export class PointLightData {
|
|
|
52
59
|
this.light.offDimensionChanged(this.update, this);
|
|
53
60
|
|
|
54
61
|
// disconnect from bvh
|
|
55
|
-
this.
|
|
62
|
+
this.bvh_leaf.unlink();
|
|
56
63
|
}
|
|
57
64
|
}
|
|
@@ -6,7 +6,6 @@ import { mat4 } from "gl-matrix";
|
|
|
6
6
|
import Signal from "../../../../../core/events/signal/Signal.js";
|
|
7
7
|
|
|
8
8
|
const corners = [];
|
|
9
|
-
const aabb_array = new Float32Array(6);
|
|
10
9
|
|
|
11
10
|
export class Decal extends AbstractLight {
|
|
12
11
|
constructor() {
|
|
@@ -89,9 +88,7 @@ export class Decal extends AbstractLight {
|
|
|
89
88
|
getAABB(result) {
|
|
90
89
|
aabb3_build_corners(corners, 0, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5);
|
|
91
90
|
|
|
92
|
-
aabb3_matrix4_project_by_corners(
|
|
93
|
-
|
|
94
|
-
result.readFromArray(aabb_array, 0);
|
|
91
|
+
aabb3_matrix4_project_by_corners(result, corners, this.transform);
|
|
95
92
|
}
|
|
96
93
|
|
|
97
94
|
toArray(destination, address) {
|
|
@@ -36,10 +36,6 @@ export class PointLight extends AbstractLight {
|
|
|
36
36
|
this.position.writeToArray(result, 0);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
*
|
|
41
|
-
* @param {AABB3} result
|
|
42
|
-
*/
|
|
43
39
|
getAABB(result) {
|
|
44
40
|
const r = this.radius.getValue();
|
|
45
41
|
const p = this.position;
|
|
@@ -48,15 +44,13 @@ export class PointLight extends AbstractLight {
|
|
|
48
44
|
const center_y = p.y;
|
|
49
45
|
const center_z = p.z;
|
|
50
46
|
|
|
51
|
-
result
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
center_z - r,
|
|
47
|
+
result[0] = center_x - r;
|
|
48
|
+
result[1] = center_y - r;
|
|
49
|
+
result[2] = center_z - r;
|
|
55
50
|
|
|
56
|
-
center_x + r
|
|
57
|
-
center_y + r
|
|
58
|
-
center_z + r
|
|
59
|
-
);
|
|
51
|
+
result[3] = center_x + r;
|
|
52
|
+
result[4] = center_y + r;
|
|
53
|
+
result[5] = center_z + r;
|
|
60
54
|
}
|
|
61
55
|
|
|
62
56
|
onDimensionChanged(listener, context) {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {EnginePlugin} from "../../../../plugin/EnginePlugin";
|
|
2
|
+
import {Decal} from "../../../ecs/decal/v2/Decal";
|
|
2
3
|
|
|
3
4
|
export class ForwardPlusRenderingPlugin extends EnginePlugin {
|
|
4
5
|
setClusterResolution(x: number, y: number, z: number): void
|
|
6
|
+
|
|
7
|
+
queryDecalsByRay(result: Decal[], result_offset: number, query: ArrayLike<number>, query_offset?: number): number
|
|
5
8
|
}
|
|
@@ -88,4 +88,16 @@ export class ForwardPlusRenderingPlugin extends EnginePlugin {
|
|
|
88
88
|
getLightManager() {
|
|
89
89
|
return this.__light_manager;
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param {Decal[]} result
|
|
95
|
+
* @param {number} result_offset
|
|
96
|
+
* @param {number[]} query
|
|
97
|
+
* @param {number} query_offset
|
|
98
|
+
* @returns {number} number of elements added to the result
|
|
99
|
+
*/
|
|
100
|
+
queryDecalsByRay(result, result_offset, query, query_offset=0){
|
|
101
|
+
return this.__light_manager.query_decals_by_ray(result,result_offset, query,query_offset);
|
|
102
|
+
}
|
|
91
103
|
}
|
|
@@ -1559,11 +1559,12 @@ function draw_camera_view_planes() {
|
|
|
1559
1559
|
}
|
|
1560
1560
|
|
|
1561
1561
|
// prepare_scene_2();
|
|
1562
|
-
prepare_scene_decal_0();
|
|
1562
|
+
// prepare_scene_decal_0();
|
|
1563
1563
|
// prepare_scene_decal_1();
|
|
1564
1564
|
// prepare_scene_decal_2();
|
|
1565
1565
|
// prepare_scene_9();
|
|
1566
|
-
// prepare_scene_0();
|
|
1566
|
+
// prepare_scene_0(); // stress test
|
|
1567
|
+
prepare_scene_4(); // sponza
|
|
1567
1568
|
animate();
|
|
1568
1569
|
|
|
1569
1570
|
// draw_camera_view_planes();
|
|
@@ -6,7 +6,7 @@ import { detailed_sphere_frustum_intersection_test } from "./detailed_sphere_fru
|
|
|
6
6
|
* @param {number} light_y
|
|
7
7
|
* @param {number} light_z
|
|
8
8
|
* @param {number} radius
|
|
9
|
-
* @param {number[]} points
|
|
9
|
+
* @param {number[]|Float32Array} points
|
|
10
10
|
* @param {number[]|Float32Array|Float64Array} planes
|
|
11
11
|
* @returns {boolean}
|
|
12
12
|
*/
|
|
@@ -14,9 +14,9 @@ let stackPointer = 0;
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Most of the data is in flat continuous array for cache coherence
|
|
17
|
-
* @param {
|
|
17
|
+
* @param {LightRenderMetadata[]} destination
|
|
18
18
|
* @param {number} destination_offset
|
|
19
|
-
* @param {BinaryNode<
|
|
19
|
+
* @param {BinaryNode<LightRenderMetadata>} root
|
|
20
20
|
* @param {number[]|Float32Array|Float64Array} planes
|
|
21
21
|
* @param {number[]|Float32Array|Float64Array} points
|
|
22
22
|
* @returns {number} number of items added to the destination, non-negative integer
|
|
@@ -84,7 +84,7 @@ export function query_bvh_frustum_from_objects(
|
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
*
|
|
87
|
-
* @type {
|
|
87
|
+
* @type {LightRenderMetadata}
|
|
88
88
|
*/
|
|
89
89
|
const light_data = n.object;
|
|
90
90
|
|
|
@@ -69,7 +69,7 @@ export class PathTracedMesh {
|
|
|
69
69
|
hit(out, ray, min_distance, max_distance) {
|
|
70
70
|
//transform ray
|
|
71
71
|
const m4 = this.__transform_inverse;
|
|
72
|
-
ray3_array_apply_matrix4(local_ray, ray, m4);
|
|
72
|
+
ray3_array_apply_matrix4(local_ray,0, ray,0, m4);
|
|
73
73
|
|
|
74
74
|
const scale_d = this.__local_scale_inverse;
|
|
75
75
|
|
|
@@ -5,6 +5,11 @@ import { BehaviorStatus } from "../BehaviorStatus.js";
|
|
|
5
5
|
|
|
6
6
|
const DEFAULT = new SucceedingBehavior();
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Utility behavior that works just like an IF/ELSE statement
|
|
10
|
+
* If you are not sure if this is the right behavior for your use-case, consider using a selector behavior instead,
|
|
11
|
+
* as selector is a more commonly applicable behavior type
|
|
12
|
+
*/
|
|
8
13
|
export class BranchBehavior extends Behavior {
|
|
9
14
|
#successBranch = DEFAULT
|
|
10
15
|
#failureBranch = DEFAULT
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { CompositeBehavior } from "../composite/CompositeBehavior.js";
|
|
2
|
-
import { BehaviorStatus } from "../BehaviorStatus.js";
|
|
3
|
-
|
|
4
|
-
export class SelectorBehavior extends CompositeBehavior {
|
|
5
|
-
constructor() {
|
|
6
|
-
super();
|
|
7
|
-
|
|
8
|
-
this.__index = 0;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param {Behavior[]} children
|
|
14
|
-
* @return {SelectorBehavior}
|
|
15
|
-
*/
|
|
16
|
-
static from(children) {
|
|
17
|
-
const r = new SelectorBehavior();
|
|
18
|
-
|
|
19
|
-
r.__children = children.slice();
|
|
20
|
-
|
|
21
|
-
return r;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
tick(timeDelta) {
|
|
25
|
-
const children = this.__children;
|
|
26
|
-
const child_count = children.length;
|
|
27
|
-
|
|
28
|
-
if (child_count === 0) {
|
|
29
|
-
// arbitrarily decide success
|
|
30
|
-
return BehaviorStatus.Succeeded;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
for (; ;) {
|
|
34
|
-
const child = children[this.__index];
|
|
35
|
-
|
|
36
|
-
const s = child.tick(timeDelta);
|
|
37
|
-
|
|
38
|
-
//if child succeeds or keeps running, do the same
|
|
39
|
-
if (s !== BehaviorStatus.Failed) {
|
|
40
|
-
return s;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
//continue search for fallback behavior until the last child
|
|
45
|
-
this.__index++;
|
|
46
|
-
|
|
47
|
-
if (this.__index >= child_count) {
|
|
48
|
-
return BehaviorStatus.Failed;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
//initialize new child
|
|
52
|
-
const next = children[this.__index];
|
|
53
|
-
|
|
54
|
-
child.finalize();
|
|
55
|
-
next.initialize(this.context);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
//we should never reach this point
|
|
59
|
-
return BehaviorStatus.Invalid;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
finalize() {
|
|
63
|
-
super.finalize();
|
|
64
|
-
|
|
65
|
-
if (this.__children.length > 0) {
|
|
66
|
-
const b = this.__children[this.__index];
|
|
67
|
-
|
|
68
|
-
b.finalize();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
initialize(context) {
|
|
74
|
-
super.initialize(context);
|
|
75
|
-
|
|
76
|
-
this.__index = 0;
|
|
77
|
-
|
|
78
|
-
if (this.__children.length > 0) {
|
|
79
|
-
this.__children[0].initialize(context);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
}
|