@woosh/meep-engine 2.34.49 → 2.35.0
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/bvh2/BinaryNode.js +19 -35
- package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +5 -5
- package/core/bvh2/aabb3_combined_surface_area.js +21 -0
- package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +24 -12
- package/core/cache/Cache.d.ts +2 -0
- package/core/cache/Cache.js +27 -23
- package/core/geom/3d/frustum/frustum_from_projection_matrix_array.js +2 -0
- package/core/math/max2.js +2 -6
- package/core/math/min2.js +2 -6
- package/engine/asset/loaders/geometry/geometry/computeGeometryEquality.js +1 -1
- package/engine/asset/loaders/geometry/geometry/computeGeometryHash.js +9 -1
- package/engine/ecs/EntityComponentDataset.js +7 -2
- package/engine/ecs/foliage/ViewState.js +13 -3
- package/engine/ecs/parent/EntityNode.js +23 -11
- package/engine/ecs/transform/Transform.js +15 -13
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +63 -26
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +63 -3
- package/engine/graphics/ecs/mesh-v2/render/AbstractRenderAdapter.js +67 -0
- package/engine/graphics/ecs/mesh-v2/render/GenericRendererAdapter.js +48 -0
- package/engine/graphics/ecs/mesh-v2/render/InstancedRendererAdapter.js +110 -0
- package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +98 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +5 -0
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +23 -5
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +8 -3
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +23 -85
- package/engine/graphics/geometry/instancing/rewriteMaterial.js +9 -45
- package/engine/graphics/material/optimization/BUFFER_GEOMETRY_UVS.js +10 -0
- package/engine/graphics/material/optimization/MaterialDescriptor.js +46 -0
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +470 -201
- package/engine/graphics/material/optimization/UvContext.js +18 -0
- package/engine/graphics/material/optimization/is_compliant_mesh.js +71 -0
- package/engine/graphics/material/optimization/prepare_atlas_texture.js +23 -0
- package/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +127 -0
- package/engine/graphics/micron/format/MicronGeometryPatch.js +1 -1
- package/engine/graphics/micron/format/VirtualGeometry.js +47 -11
- package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +16 -0
- package/engine/graphics/micron/prototypeVirtualGeometry.js +3 -2
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +5 -7
- package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +1 -45
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +18 -7
- package/engine/graphics/micron/render/refinement/RefinementSpec.js +0 -1
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +17 -24
- package/engine/graphics/micron/render/v1/MaterialContext.js +3 -2
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +19 -4
- package/engine/graphics/render/utils/ThreeBypassRenderer.js +3 -2
- package/engine/graphics/texture/normalized_internal_format.js +48 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +6 -0
- package/engine/graphics/texture/sampler/sampler2d_copy_channel_data.js +25 -0
- package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -0
- package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +14 -1
- package/package.json +1 -1
package/core/bvh2/BinaryNode.js
CHANGED
|
@@ -15,7 +15,7 @@ import { BVHVisitor } from "./traversal/BVHVisitor.js";
|
|
|
15
15
|
import { traverseBinaryNodeUsingVisitor } from "./traversal/traverseBinaryNodeUsingVisitor.js";
|
|
16
16
|
import { aabb3_intersect_aabb3 } from "./aabb3/aabb3_intersect_aabb3.js";
|
|
17
17
|
import { aabb3_box_surface_area_2 } from "./aabb3/aabb3_box_surface_area_2.js";
|
|
18
|
-
import {
|
|
18
|
+
import { aabb3_combined_surface_area } from "./aabb3_combined_surface_area.js";
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -206,6 +206,7 @@ export class BinaryNode extends Node {
|
|
|
206
206
|
/**
|
|
207
207
|
* For incremental insertion, a sibling needs to be found, newly inserted node will be parented together with this sibling
|
|
208
208
|
* @see https://github.com/erincatto/box2d/blob/9dc24a6fd4f32442c4bcf80791de47a0a7d25afb/src/collision/b2_dynamic_tree.cpp#L197
|
|
209
|
+
* @private
|
|
209
210
|
* @param {AABB3} box
|
|
210
211
|
* @returns {BinaryNode|LeafNode}
|
|
211
212
|
*/
|
|
@@ -215,13 +216,13 @@ export class BinaryNode extends Node {
|
|
|
215
216
|
let cost_left = 0;
|
|
216
217
|
let cost_right = 0;
|
|
217
218
|
|
|
218
|
-
while (node.isBinaryNode) {
|
|
219
|
+
while (node.isBinaryNode === true) {
|
|
219
220
|
const left = node.left;
|
|
220
221
|
const right = node.right;
|
|
221
222
|
|
|
222
223
|
const area = aabb3_box_surface_area_2(node);
|
|
223
224
|
|
|
224
|
-
const combined_area =
|
|
225
|
+
const combined_area = aabb3_combined_surface_area(node, box);
|
|
225
226
|
|
|
226
227
|
//cost of creating a new parent for this node and the new leaf
|
|
227
228
|
const cost = combined_area;
|
|
@@ -231,10 +232,11 @@ export class BinaryNode extends Node {
|
|
|
231
232
|
|
|
232
233
|
// cost of descending left
|
|
233
234
|
if (left !== null) {
|
|
235
|
+
const combined_left = aabb3_combined_surface_area(left, box);
|
|
234
236
|
if (left.isLeafNode) {
|
|
235
|
-
cost_left =
|
|
237
|
+
cost_left = combined_left + inheritance_cost;
|
|
236
238
|
} else {
|
|
237
|
-
cost_left =
|
|
239
|
+
cost_left = combined_left - aabb3_box_surface_area_2(left) + inheritance_cost;
|
|
238
240
|
}
|
|
239
241
|
} else {
|
|
240
242
|
cost_left = Infinity;
|
|
@@ -243,10 +245,11 @@ export class BinaryNode extends Node {
|
|
|
243
245
|
// cost of descending right
|
|
244
246
|
if (right !== null) {
|
|
245
247
|
|
|
248
|
+
const combined_right = aabb3_combined_surface_area(right, box);
|
|
246
249
|
if (right.isLeafNode) {
|
|
247
|
-
cost_right =
|
|
250
|
+
cost_right = combined_right + inheritance_cost;
|
|
248
251
|
} else {
|
|
249
|
-
cost_right =
|
|
252
|
+
cost_right = combined_right - aabb3_box_surface_area_2(right) + inheritance_cost;
|
|
250
253
|
}
|
|
251
254
|
} else {
|
|
252
255
|
cost_right = Infinity;
|
|
@@ -1045,10 +1048,9 @@ export class BinaryNode extends Node {
|
|
|
1045
1048
|
|
|
1046
1049
|
const sibling = this.__insertion_findSiblingFor(child);
|
|
1047
1050
|
|
|
1048
|
-
|
|
1049
|
-
let parent = sibling_parent;
|
|
1051
|
+
let parent = sibling.parentNode;
|
|
1050
1052
|
|
|
1051
|
-
if (
|
|
1053
|
+
if (parent === null) {
|
|
1052
1054
|
// "sibling" is the root node
|
|
1053
1055
|
|
|
1054
1056
|
parent = sibling;
|
|
@@ -1069,15 +1071,15 @@ export class BinaryNode extends Node {
|
|
|
1069
1071
|
|
|
1070
1072
|
// non-root
|
|
1071
1073
|
|
|
1072
|
-
if (
|
|
1074
|
+
if (parent.left === sibling && parent.right === null) {
|
|
1073
1075
|
|
|
1074
1076
|
// right node is free, take it
|
|
1075
|
-
|
|
1077
|
+
parent.setChildRight(child);
|
|
1076
1078
|
|
|
1077
|
-
} else if (
|
|
1079
|
+
} else if (parent.right === sibling && parent.left === null) {
|
|
1078
1080
|
|
|
1079
1081
|
// left node is free, take it
|
|
1080
|
-
|
|
1082
|
+
parent.setChildLeft(child);
|
|
1081
1083
|
|
|
1082
1084
|
} else {
|
|
1083
1085
|
|
|
@@ -1088,7 +1090,7 @@ export class BinaryNode extends Node {
|
|
|
1088
1090
|
}
|
|
1089
1091
|
|
|
1090
1092
|
// walk back up the tree fixing heights and bounds
|
|
1091
|
-
|
|
1093
|
+
do {
|
|
1092
1094
|
// parent = this.balance();
|
|
1093
1095
|
|
|
1094
1096
|
const left = parent.left;
|
|
@@ -1098,7 +1100,7 @@ export class BinaryNode extends Node {
|
|
|
1098
1100
|
parent.refit();
|
|
1099
1101
|
|
|
1100
1102
|
parent = parent.parentNode;
|
|
1101
|
-
}
|
|
1103
|
+
} while (parent !== null);
|
|
1102
1104
|
}
|
|
1103
1105
|
|
|
1104
1106
|
/**
|
|
@@ -1152,25 +1154,7 @@ BinaryNode.prototype.isBinaryNode = true;
|
|
|
1152
1154
|
* @returns {number}
|
|
1153
1155
|
*/
|
|
1154
1156
|
function inclusion_surface_area_heuristic(node, addition) {
|
|
1155
|
-
return
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
/**
|
|
1159
|
-
*
|
|
1160
|
-
* @param {AABB3} node
|
|
1161
|
-
* @param {AABB3} addition
|
|
1162
|
-
* @returns {number}
|
|
1163
|
-
*/
|
|
1164
|
-
function combined_surface_area(node, addition) {
|
|
1165
|
-
const x0 = min2(node.x0, addition.x0);
|
|
1166
|
-
const y0 = min2(node.y0, addition.y0);
|
|
1167
|
-
const z0 = min2(node.z0, addition.z0);
|
|
1168
|
-
|
|
1169
|
-
const x1 = max2(node.x1, addition.x1);
|
|
1170
|
-
const y1 = max2(node.y1, addition.y1);
|
|
1171
|
-
const z1 = max2(node.z1, addition.z1);
|
|
1172
|
-
|
|
1173
|
-
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
|
|
1157
|
+
return aabb3_combined_surface_area(node, addition) - aabb3_box_surface_area_2(node);
|
|
1174
1158
|
}
|
|
1175
1159
|
|
|
1176
1160
|
/**
|
|
@@ -32,13 +32,13 @@ export function aabb3_intersects_frustum_array(aabb, frustum) {
|
|
|
32
32
|
export function aabb3_intersects_frustum(x0, y0, z0, x1, y1, z1, frustum) {
|
|
33
33
|
for (let i = 0; i < 24; i += 4) {
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
35
|
+
const plane_x = frustum[i];
|
|
36
|
+
const plane_y = frustum[i + 1];
|
|
37
|
+
const plane_z = frustum[i + 2];
|
|
38
|
+
const plane_w = frustum[i + 3];
|
|
39
39
|
|
|
40
40
|
const plane_distance = aabb3_computeDistanceAbovePlane(
|
|
41
|
-
|
|
41
|
+
plane_x, plane_y, plane_z, plane_w,
|
|
42
42
|
x0, y0, z0,
|
|
43
43
|
x1, y1, z1
|
|
44
44
|
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { min2 } from "../math/min2.js";
|
|
2
|
+
import { max2 } from "../math/max2.js";
|
|
3
|
+
import { aabb3_compute_half_surface_area } from "./aabb3/aabb3_compute_half_surface_area.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {AABB3} a
|
|
8
|
+
* @param {AABB3} b
|
|
9
|
+
* @returns {number}
|
|
10
|
+
*/
|
|
11
|
+
export function aabb3_combined_surface_area(a, b) {
|
|
12
|
+
const x0 = min2(a.x0, b.x0);
|
|
13
|
+
const y0 = min2(a.y0, b.y0);
|
|
14
|
+
const z0 = min2(a.z0, b.z0);
|
|
15
|
+
|
|
16
|
+
const x1 = max2(a.x1, b.x1);
|
|
17
|
+
const y1 = max2(a.y1, b.y1);
|
|
18
|
+
const z1 = max2(a.z1, b.z1);
|
|
19
|
+
|
|
20
|
+
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
|
|
21
|
+
}
|
|
@@ -8,45 +8,57 @@ const stack = [];
|
|
|
8
8
|
/**
|
|
9
9
|
* @template T
|
|
10
10
|
* @param {T[]} destination
|
|
11
|
-
* @param {number}
|
|
11
|
+
* @param {number} destination_offset
|
|
12
12
|
* @param {BinaryNode<T>} root
|
|
13
13
|
* @param {ArrayLike<number>|number[]|Float32Array} frustum
|
|
14
14
|
* @returns {number} Number of results
|
|
15
15
|
*/
|
|
16
|
-
export function queryBinaryNode_FrustumIntersections_Data(destination,
|
|
16
|
+
export function queryBinaryNode_FrustumIntersections_Data(destination, destination_offset, root, frustum) {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {BinaryNode<T>|LeafNode<T>}
|
|
20
|
+
*/
|
|
17
21
|
let n;
|
|
18
|
-
let
|
|
22
|
+
let offset = destination_offset;
|
|
19
23
|
let stackPointer = 1;
|
|
20
24
|
|
|
21
25
|
stack[0] = root;
|
|
22
26
|
|
|
23
27
|
while (stackPointer > 0) {
|
|
28
|
+
|
|
24
29
|
stackPointer--;
|
|
25
30
|
|
|
26
31
|
n = stack[stackPointer];
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
const node_intersects_frustum = n.intersectFrustum_array(frustum);
|
|
34
|
+
|
|
35
|
+
if (!node_intersects_frustum) {
|
|
29
36
|
continue;
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
if (n.isBinaryNode) {
|
|
39
|
+
if (n.isBinaryNode === true) {
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
const right = n.right;
|
|
42
|
+
|
|
43
|
+
if (right !== null) {
|
|
44
|
+
stack[stackPointer++] = right;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
const left = n.left;
|
|
48
|
+
|
|
49
|
+
if (left !== null) {
|
|
50
|
+
stack[stackPointer++] = left;
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
} else {
|
|
54
|
+
// leaf node
|
|
43
55
|
|
|
44
|
-
destination[
|
|
56
|
+
destination[offset] = n.object;
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
offset++;
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
}
|
|
50
62
|
|
|
51
|
-
return
|
|
63
|
+
return offset - destination_offset;
|
|
52
64
|
}
|
package/core/cache/Cache.d.ts
CHANGED
package/core/cache/Cache.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assert } from "../assert.js";
|
|
2
2
|
import { HashMap } from "../collection/HashMap.js";
|
|
3
3
|
import Signal from "../events/signal/Signal.js";
|
|
4
|
-
import {
|
|
4
|
+
import { returnOne, returnZero, strictEquals } from "../function/Functions.js";
|
|
5
5
|
import { CacheElement } from "./CacheElement.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -14,33 +14,25 @@ export class Cache {
|
|
|
14
14
|
* @param {number} [maxWeight=Number.POSITIVE_INFINITY]
|
|
15
15
|
* @param {function(key:Key):number} [keyWeigher= key=>0]
|
|
16
16
|
* @param {function(value:Value):number} [valueWeigher= value=>1]
|
|
17
|
-
* @param {function(key:Key, value:Value)} [removeListener] will be notified when element is either explicitly removed or evicted
|
|
18
17
|
* @param {function(Key):number} [keyHashFunction]
|
|
19
18
|
* @param {function(Key, Key):boolean} [keyEqualityFunction]
|
|
20
19
|
* @param {number} capacity initial capacity for the cache, helps prevent early resizing
|
|
21
20
|
* @constructor
|
|
22
|
-
* @template Key, Value
|
|
23
21
|
*/
|
|
24
22
|
constructor({
|
|
25
23
|
maxWeight = Number.POSITIVE_INFINITY,
|
|
26
24
|
keyWeigher = returnZero,
|
|
27
25
|
valueWeigher = returnOne,
|
|
28
|
-
removeListener = noop,
|
|
29
26
|
keyHashFunction = returnZero,
|
|
30
27
|
keyEqualityFunction = strictEquals,
|
|
31
28
|
capacity
|
|
32
29
|
} = {}) {
|
|
33
30
|
|
|
34
31
|
assert.isNumber(maxWeight, 'maxWeight');
|
|
35
|
-
assert.
|
|
36
|
-
assert.
|
|
37
|
-
assert.
|
|
38
|
-
assert.
|
|
39
|
-
assert.typeOf(keyEqualityFunction, 'function', 'keyEqualityFunction');
|
|
40
|
-
|
|
41
|
-
if (removeListener !== noop) {
|
|
42
|
-
console.warn('removalListener is deprecated, use onRemoved signal instead');
|
|
43
|
-
}
|
|
32
|
+
assert.isFunction(keyWeigher, 'keyWeigher');
|
|
33
|
+
assert.isFunction(valueWeigher, 'valueWeigher');
|
|
34
|
+
assert.isFunction(keyHashFunction, 'keyHashFunction');
|
|
35
|
+
assert.isFunction(keyEqualityFunction, 'keyEqualityFunction');
|
|
44
36
|
|
|
45
37
|
/**
|
|
46
38
|
*
|
|
@@ -70,13 +62,6 @@ export class Cache {
|
|
|
70
62
|
*/
|
|
71
63
|
this.valueWeigher = valueWeigher;
|
|
72
64
|
|
|
73
|
-
/**
|
|
74
|
-
*
|
|
75
|
-
* @type {function(Key, Value)}
|
|
76
|
-
* @private
|
|
77
|
-
*/
|
|
78
|
-
this.removeListener = removeListener;
|
|
79
|
-
|
|
80
65
|
/**
|
|
81
66
|
*
|
|
82
67
|
* @type {CacheElement<Key,Value>|null}
|
|
@@ -93,7 +78,7 @@ export class Cache {
|
|
|
93
78
|
|
|
94
79
|
/**
|
|
95
80
|
*
|
|
96
|
-
* @type {HashMap<Key, CacheElement<Key,Value
|
|
81
|
+
* @type {HashMap<Key, CacheElement<Key,Value>>}
|
|
97
82
|
* @private
|
|
98
83
|
*/
|
|
99
84
|
this.data = new HashMap({
|
|
@@ -398,13 +383,32 @@ export class Cache {
|
|
|
398
383
|
this.__removeElement(element);
|
|
399
384
|
|
|
400
385
|
//notify
|
|
401
|
-
this.removeListener(key, element.value);
|
|
402
|
-
|
|
403
386
|
this.onRemoved.send2(key, element.value);
|
|
404
387
|
|
|
405
388
|
return true;
|
|
406
389
|
}
|
|
407
390
|
|
|
391
|
+
/**
|
|
392
|
+
*
|
|
393
|
+
* @param {Key} key
|
|
394
|
+
* @param {function(Key):Value} compute
|
|
395
|
+
* @param {*} [compute_context]
|
|
396
|
+
* @return {Value}
|
|
397
|
+
*/
|
|
398
|
+
getOrCompute(key, compute, compute_context) {
|
|
399
|
+
const existing = this.get(key);
|
|
400
|
+
|
|
401
|
+
if (existing !== null) {
|
|
402
|
+
return existing;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const value = compute.call(compute_context, key);
|
|
406
|
+
|
|
407
|
+
this.set(key, value);
|
|
408
|
+
|
|
409
|
+
return value;
|
|
410
|
+
}
|
|
411
|
+
|
|
408
412
|
/**
|
|
409
413
|
* Remove all elements from the cache
|
|
410
414
|
*/
|
|
@@ -25,6 +25,8 @@ function array_set_plane_normalized(
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Set frustum from projection matrix
|
|
28
|
+
* NOTE: uses Gribb/Hartmann method
|
|
29
|
+
* @see "Fast Extraction of Viewing Frustum Planes from the WorldView-Projection Matrix", 2001 by Gribb & Hartmann
|
|
28
30
|
* @param {number[]|Float32Array} frustum_planes
|
|
29
31
|
* @param {number[]} m4
|
|
30
32
|
*/
|
package/core/math/max2.js
CHANGED
package/core/math/min2.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computeBufferAttributeHash } from "./computeBufferAttributeHash.js";
|
|
2
|
+
import { computeStringHash } from "../../../../../core/primitives/strings/computeStringHash.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
*
|
|
@@ -6,7 +7,14 @@ import { computeBufferAttributeHash } from "./computeBufferAttributeHash.js";
|
|
|
6
7
|
* @returns {number}
|
|
7
8
|
*/
|
|
8
9
|
export function computeGeometryHash(geometry) {
|
|
9
|
-
let hash =
|
|
10
|
+
let hash = 0;
|
|
11
|
+
const attributes = geometry.attributes;
|
|
12
|
+
|
|
13
|
+
for (const attributesKey in attributes) {
|
|
14
|
+
hash = hash * 31 + computeStringHash(attributesKey);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
hash ^= computeBufferAttributeHash(geometry.getIndex());
|
|
10
18
|
|
|
11
19
|
const position_attribute = geometry.getAttribute('position');
|
|
12
20
|
|
|
@@ -1319,11 +1319,16 @@ export class EntityComponentDataset {
|
|
|
1319
1319
|
|
|
1320
1320
|
const numObservers = observersStore.length;
|
|
1321
1321
|
|
|
1322
|
-
|
|
1322
|
+
if (numObservers === 0) {
|
|
1323
|
+
// no observers
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
let i = 0;
|
|
1323
1328
|
|
|
1324
1329
|
const args = [];
|
|
1325
1330
|
|
|
1326
|
-
for (
|
|
1331
|
+
for (; i < numObservers; i++) {
|
|
1327
1332
|
const observer = observersStore[i];
|
|
1328
1333
|
|
|
1329
1334
|
const match = matchComponentMask(this.componentOccupancy, entityIndex, this.componentTypeCount, observer.componentMask);
|
|
@@ -2,6 +2,8 @@ import { BitSet } from "../../../core/binary/BitSet.js";
|
|
|
2
2
|
import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
|
|
3
3
|
import { queryBinaryNode_FrustumIntersections_Data } from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
|
|
4
4
|
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
5
|
+
import { compose_matrix4_array } from "../../graphics/util/composeMatrix4.js";
|
|
6
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
*
|
|
@@ -153,13 +155,21 @@ export class ViewState {
|
|
|
153
155
|
|
|
154
156
|
tempQuaternion.decodeFromUint32(encodedRotation);
|
|
155
157
|
|
|
158
|
+
scratch_v3_0.set(positionX, positionY, positionZ);
|
|
159
|
+
scratch_v3_1.set(scaleX, scaleY, scaleZ);
|
|
160
|
+
|
|
161
|
+
// compose transform
|
|
162
|
+
compose_matrix4_array(scratch_transform, scratch_v3_0, tempQuaternion, scratch_v3_1);
|
|
163
|
+
|
|
156
164
|
//apply instance transforms
|
|
157
|
-
instances.
|
|
158
|
-
instances.
|
|
159
|
-
instances.setScaleAt(i, scaleX, scaleY, scaleZ);
|
|
165
|
+
instances.setTransformAt(i, scratch_transform);
|
|
166
|
+
instances.requestAttributeUpdate();
|
|
160
167
|
}
|
|
161
168
|
}
|
|
162
169
|
}
|
|
163
170
|
|
|
164
171
|
const tempQuaternion = new Quaternion();
|
|
172
|
+
const scratch_v3_0 = new Vector3();
|
|
173
|
+
const scratch_v3_1 = new Vector3();
|
|
165
174
|
const rowData = [];
|
|
175
|
+
const scratch_transform = new Float32Array(16);
|
|
@@ -4,7 +4,7 @@ import { array_remove_first } from "../../../core/collection/array/array_remove_
|
|
|
4
4
|
import { assert } from "../../../core/assert.js";
|
|
5
5
|
import { array_push_if_unique } from "../../../core/collection/array/array_push_if_unique.js";
|
|
6
6
|
import { Transform } from "../transform/Transform.js";
|
|
7
|
-
import { TransformAttachment } from "../transform-attachment/TransformAttachment.js";
|
|
7
|
+
import { TransformAttachment, TransformAttachmentFlags } from "../transform-attachment/TransformAttachment.js";
|
|
8
8
|
|
|
9
9
|
export class EntityNode {
|
|
10
10
|
/**
|
|
@@ -18,12 +18,14 @@ export class EntityNode {
|
|
|
18
18
|
* @private
|
|
19
19
|
*/
|
|
20
20
|
this.__parent = null;
|
|
21
|
+
|
|
21
22
|
/**
|
|
22
23
|
*
|
|
23
24
|
* @type {EntityBuilder}
|
|
24
25
|
* @private
|
|
25
26
|
*/
|
|
26
27
|
this.__entity = entity;
|
|
28
|
+
|
|
27
29
|
/**
|
|
28
30
|
*
|
|
29
31
|
* @type {EntityNode[]}
|
|
@@ -32,7 +34,7 @@ export class EntityNode {
|
|
|
32
34
|
this.__children = [];
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
|
-
*
|
|
37
|
+
* Local transform
|
|
36
38
|
* @type {Transform}
|
|
37
39
|
* @private
|
|
38
40
|
*/
|
|
@@ -45,13 +47,18 @@ export class EntityNode {
|
|
|
45
47
|
*/
|
|
46
48
|
__transform_sync_down() {
|
|
47
49
|
|
|
50
|
+
const transform = this.__transform;
|
|
51
|
+
|
|
48
52
|
if (this.__parent === null) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
// not attached to anything, world and local transforms match
|
|
54
|
+
const cTransform = this.__entity.getComponent(Transform);
|
|
55
|
+
|
|
56
|
+
if (cTransform !== null) {
|
|
57
|
+
cTransform.copy(transform);
|
|
52
58
|
}
|
|
59
|
+
|
|
53
60
|
} else {
|
|
54
|
-
this.__safe_get_attachment().transform.copy(
|
|
61
|
+
this.__safe_get_attachment().transform.copy(transform);
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
}
|
|
@@ -85,7 +92,7 @@ export class EntityNode {
|
|
|
85
92
|
|
|
86
93
|
if (attachment === null) {
|
|
87
94
|
attachment = new TransformAttachment();
|
|
88
|
-
attachment.
|
|
95
|
+
attachment.setFlag(TransformAttachmentFlags.Immediate);
|
|
89
96
|
|
|
90
97
|
entity.add(attachment);
|
|
91
98
|
}
|
|
@@ -115,13 +122,15 @@ export class EntityNode {
|
|
|
115
122
|
set parent(node) {
|
|
116
123
|
this.__parent = node;
|
|
117
124
|
|
|
125
|
+
const this_entity = this.__entity;
|
|
126
|
+
|
|
118
127
|
// check if entity is built
|
|
119
|
-
if (!
|
|
128
|
+
if (!this_entity.isBuilt) {
|
|
120
129
|
return;
|
|
121
130
|
}
|
|
122
131
|
|
|
123
|
-
let parent_entity =
|
|
124
|
-
let attachment =
|
|
132
|
+
let parent_entity = this_entity.removeComponent(ParentEntity);
|
|
133
|
+
let attachment = this_entity.removeComponent(TransformAttachment);
|
|
125
134
|
|
|
126
135
|
if (node !== null) {
|
|
127
136
|
|
|
@@ -141,7 +150,7 @@ export class EntityNode {
|
|
|
141
150
|
parent_entity.entity = parent_entity_id;
|
|
142
151
|
|
|
143
152
|
// add component back
|
|
144
|
-
|
|
153
|
+
this_entity.add(parent_entity);
|
|
145
154
|
|
|
146
155
|
|
|
147
156
|
// handle component Attachment
|
|
@@ -230,6 +239,8 @@ export class EntityNode {
|
|
|
230
239
|
}
|
|
231
240
|
|
|
232
241
|
this.__transform_sync_down();
|
|
242
|
+
|
|
243
|
+
// attach listeners
|
|
233
244
|
this.__transform.position.onChanged.add(this.__transform_sync_down, this);
|
|
234
245
|
this.__transform.scale.onChanged.add(this.__transform_sync_down, this);
|
|
235
246
|
this.__transform.rotation.onChanged.add(this.__transform_sync_down, this);
|
|
@@ -247,6 +258,7 @@ export class EntityNode {
|
|
|
247
258
|
}
|
|
248
259
|
|
|
249
260
|
destroy() {
|
|
261
|
+
// remove listeners
|
|
250
262
|
this.__transform.position.onChanged.remove(this.__transform_sync_down, this);
|
|
251
263
|
this.__transform.scale.onChanged.remove(this.__transform_sync_down, this);
|
|
252
264
|
this.__transform.rotation.onChanged.remove(this.__transform_sync_down, this);
|
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import Vector3 from "../../../core/geom/Vector3.js";
|
|
6
6
|
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
7
|
-
import { Matrix4 } from "../../../core/geom/Matrix4.js";
|
|
8
7
|
import { compose_matrix4_array } from "../../graphics/util/composeMatrix4.js";
|
|
9
8
|
import { decompose_matrix_4_array } from "../../graphics/util/decompose_matrix_4_array.js";
|
|
9
|
+
import { mat4 } from "gl-matrix";
|
|
10
10
|
|
|
11
11
|
const delta = new Vector3();
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const scratch_buffer = new ArrayBuffer(32 * 4);
|
|
14
|
+
|
|
15
|
+
const m4_0 = new Float32Array(scratch_buffer, 0, 16);
|
|
16
|
+
const m4_1 = new Float32Array(scratch_buffer, 64, 16)
|
|
15
17
|
|
|
16
18
|
export class Transform {
|
|
17
19
|
/**
|
|
@@ -152,12 +154,12 @@ export class Transform {
|
|
|
152
154
|
* @param {Transform} b
|
|
153
155
|
*/
|
|
154
156
|
multiplyTransforms(a, b) {
|
|
155
|
-
m4_0
|
|
156
|
-
m4_1
|
|
157
|
+
compose_matrix4_array(m4_0, a.position, a.rotation, a.scale);
|
|
158
|
+
compose_matrix4_array(m4_1, b.position, b.rotation, b.scale);
|
|
157
159
|
|
|
158
|
-
|
|
160
|
+
mat4.multiply(m4_0, m4_0, m4_1);
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
this.fromMatrix4(m4_0);
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
/**
|
|
@@ -170,18 +172,18 @@ export class Transform {
|
|
|
170
172
|
|
|
171
173
|
/**
|
|
172
174
|
*
|
|
173
|
-
* @param {
|
|
175
|
+
* @param {Matrix4} matrix
|
|
174
176
|
*/
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
toThreeMatrix(matrix) {
|
|
178
|
+
this.toMatrix4(matrix.elements);
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
/**
|
|
180
182
|
*
|
|
181
|
-
* @param {
|
|
183
|
+
* @param {mat4|number[]|Float32Array} m
|
|
182
184
|
*/
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
+
fromMatrix4(m) {
|
|
186
|
+
decompose_matrix_4_array(m, this.position, this.rotation, this.scale);
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
/**
|