@woosh/meep-engine 2.34.34 → 2.34.35
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 +2 -1
- package/core/bvh2/Node.d.ts +3 -0
- package/core/bvh2/transform/RotationOptimizer.js +2 -262
- package/core/bvh2/transform/tryRotateSingleNode.js +259 -0
- package/core/events/signal/Signal.js +1 -1
- 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/sockets/AttachmentSockets.js +11 -1
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +6 -0
- package/engine/sound/ecs/emitter/SoundEmitterSystem.js +1 -1
- package/package.json +1 -1
package/core/bvh2/BinaryNode.js
CHANGED
|
@@ -541,11 +541,12 @@ BinaryNode.prototype.bubbleRefit = function () {
|
|
|
541
541
|
n = n.parentNode;
|
|
542
542
|
|
|
543
543
|
if (n === null) {
|
|
544
|
+
// hit the root
|
|
544
545
|
return;
|
|
545
546
|
}
|
|
546
547
|
|
|
547
|
-
//check if this node violates bounds of the parent
|
|
548
548
|
|
|
549
|
+
//check if this node violates bounds of the parent
|
|
549
550
|
let flag = false;
|
|
550
551
|
|
|
551
552
|
if (_x0 < n.x0) {
|
package/core/bvh2/Node.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { boxSurfaceArea2 as computeArea, scoreBoxesSAH as computeAreaFor2 } from "../aabb3/AABB3Math.js";
|
|
2
1
|
import { BinaryNode } from "../BinaryNode.js";
|
|
3
2
|
import { isLeaf } from "../LeafNode.js";
|
|
4
|
-
import { surfaceAreaHeuristic as sah } from "../sah/surfaceAreaHeuristic.js";
|
|
5
3
|
import { StacklessTraverser } from "../StacklessTraverser.js";
|
|
4
|
+
import { tryRotateSingleNode } from "./tryRotateSingleNode.js";
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -73,266 +72,12 @@ function getLeafCount(node, leafCounts) {
|
|
|
73
72
|
return result;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
/**
|
|
77
|
-
*
|
|
78
|
-
* @param {Node} node
|
|
79
|
-
* @param {BinaryNode} parent
|
|
80
|
-
*/
|
|
81
|
-
function setParent(node, parent) {
|
|
82
|
-
node.parentNode = parent;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Based on paper "Fast, Effective BVH Updates for Animated Scenes" Kopta et. al. (url: http://www.cs.utah.edu/~thiago/papers/rotations.pdf)
|
|
87
|
-
* @param {BinaryNode} node
|
|
88
|
-
* @param {Map.<NodeDescription,int>} leafCounts
|
|
89
|
-
* @returns {int} value from 0 to 6, 0 means no rotation has taken place
|
|
90
|
-
*/
|
|
91
|
-
function tryRotateSingleNode(node, leafCounts) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const left = node.left;
|
|
95
|
-
const right = node.right;
|
|
96
|
-
|
|
97
|
-
if (left === null || right === null) {
|
|
98
|
-
return 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
let bestRotation = 0;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const nodeArea = computeArea(node);
|
|
105
|
-
const leftArea = computeArea(left);
|
|
106
|
-
const rightArea = computeArea(right);
|
|
107
|
-
|
|
108
|
-
const leftLeaves = left.leafNodeCount;
|
|
109
|
-
const rightLeaves = right.leafNodeCount;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
let bestCost = sah(
|
|
113
|
-
nodeArea,
|
|
114
|
-
leftArea,
|
|
115
|
-
rightArea,
|
|
116
|
-
leftLeaves,
|
|
117
|
-
rightLeaves
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
let candidateCost;
|
|
121
|
-
|
|
122
|
-
let leftLeftArea,
|
|
123
|
-
leftRightArea,
|
|
124
|
-
rightLeftArea,
|
|
125
|
-
rightRightArea;
|
|
126
|
-
|
|
127
|
-
let leftLeft,
|
|
128
|
-
leftRight,
|
|
129
|
-
rightLeft,
|
|
130
|
-
rightRight;
|
|
131
|
-
|
|
132
|
-
let leftLeftLeaves,
|
|
133
|
-
leftRightLeaves,
|
|
134
|
-
rightLeftLeaves,
|
|
135
|
-
rightRightLeaves;
|
|
136
|
-
|
|
137
|
-
let considerLeft = !isLeaf(left);
|
|
138
|
-
|
|
139
|
-
if (considerLeft) {
|
|
140
|
-
leftLeft = left.left;
|
|
141
|
-
leftRight = left.right;
|
|
142
|
-
|
|
143
|
-
considerLeft = (leftLeft !== null && leftRight !== null);
|
|
144
|
-
if (considerLeft) {
|
|
145
|
-
|
|
146
|
-
leftLeftArea = computeArea(leftLeft);
|
|
147
|
-
leftRightArea = computeArea(leftRight);
|
|
148
|
-
|
|
149
|
-
leftLeftLeaves = leftLeft.leafNodeCount;
|
|
150
|
-
leftRightLeaves = leftRight.leafNodeCount;
|
|
151
|
-
|
|
152
|
-
// (1) N N //
|
|
153
|
-
// / \ / \ //
|
|
154
|
-
// L R -----> L LL //
|
|
155
|
-
// / \ / \ //
|
|
156
|
-
// LL LR R LR //
|
|
157
|
-
candidateCost = sah(nodeArea, computeAreaFor2(right, leftRight), leftLeftArea, rightLeaves + leftRightLeaves, leftLeftLeaves);
|
|
158
|
-
|
|
159
|
-
if (candidateCost < bestCost) {
|
|
160
|
-
bestRotation = 1;
|
|
161
|
-
bestCost = candidateCost;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// (2) N N //
|
|
165
|
-
// / \ / \ //
|
|
166
|
-
// L R -----> L LR //
|
|
167
|
-
// / \ / \ //
|
|
168
|
-
// LL LR LL R //
|
|
169
|
-
candidateCost = sah(nodeArea, computeAreaFor2(leftLeft, right), leftRightArea, leftLeftLeaves + rightLeaves, leftRightLeaves);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (candidateCost < bestCost) {
|
|
173
|
-
bestRotation = 2;
|
|
174
|
-
bestCost = candidateCost;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (!isLeaf(right)) {
|
|
179
|
-
rightLeft = right.left;
|
|
180
|
-
rightRight = right.right;
|
|
181
|
-
if (rightLeft !== null && rightRight !== null) {
|
|
182
|
-
|
|
183
|
-
rightLeftArea = computeArea(rightLeft);
|
|
184
|
-
rightRightArea = computeArea(rightRight);
|
|
185
|
-
|
|
186
|
-
rightLeftLeaves = rightLeft.leafNodeCount;
|
|
187
|
-
rightRightLeaves = rightRight.leafNodeCount;
|
|
188
|
-
|
|
189
|
-
// (3) N N //
|
|
190
|
-
// / \ / \ //
|
|
191
|
-
// L R -----> RL R //
|
|
192
|
-
// / \ / \ //
|
|
193
|
-
// RL RR L RR //
|
|
194
|
-
candidateCost = sah(nodeArea, rightLeftArea, computeAreaFor2(left, rightRight), rightLeftLeaves, leftLeaves + rightRightLeaves);
|
|
195
|
-
|
|
196
|
-
if (candidateCost < bestCost) {
|
|
197
|
-
bestRotation = 3;
|
|
198
|
-
bestCost = candidateCost;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// (4) N N //
|
|
202
|
-
// / \ / \ //
|
|
203
|
-
// L R -----> RR R //
|
|
204
|
-
// / \ / \ //
|
|
205
|
-
// RL RR RL L //
|
|
206
|
-
candidateCost = sah(nodeArea, rightRightArea, computeAreaFor2(rightLeft, left), rightRightLeaves, rightLeftLeaves + leftLeaves);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (candidateCost < bestCost) {
|
|
210
|
-
bestRotation = 4;
|
|
211
|
-
bestCost = candidateCost;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (considerLeft) {
|
|
215
|
-
//both child nodes are not leaf
|
|
216
|
-
|
|
217
|
-
// (5) N N //
|
|
218
|
-
// / \ / \ //
|
|
219
|
-
// L R -----> L R //
|
|
220
|
-
// / \ / \ / \ / \ //
|
|
221
|
-
// LL LR RL RR LL RL LR RR //
|
|
222
|
-
candidateCost = sah(
|
|
223
|
-
nodeArea,
|
|
224
|
-
computeAreaFor2(leftLeft, rightLeft),
|
|
225
|
-
computeAreaFor2(leftRight, rightRight),
|
|
226
|
-
leftLeftLeaves + rightLeftLeaves,
|
|
227
|
-
leftRightLeaves + rightRightLeaves
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (candidateCost < bestCost) {
|
|
232
|
-
bestRotation = 5;
|
|
233
|
-
bestCost = candidateCost;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// (6) N N //
|
|
237
|
-
// / \ / \ //
|
|
238
|
-
// L R -----> L R //
|
|
239
|
-
// / \ / \ / \ / \ //
|
|
240
|
-
// LL LR RL RR LL RR RL LR //
|
|
241
|
-
candidateCost = sah(
|
|
242
|
-
nodeArea,
|
|
243
|
-
computeAreaFor2(leftLeft, rightRight),
|
|
244
|
-
computeAreaFor2(rightLeft, leftRight),
|
|
245
|
-
leftLeftLeaves + rightRightLeaves,
|
|
246
|
-
rightLeftLeaves + leftRightLeaves
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
if (candidateCost < bestCost) {
|
|
250
|
-
bestRotation = 6;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
switch (bestRotation) {
|
|
257
|
-
case 0:
|
|
258
|
-
//no rotation
|
|
259
|
-
break;
|
|
260
|
-
case 1:
|
|
261
|
-
node.right = leftLeft;
|
|
262
|
-
setParent(leftLeft, node);
|
|
263
|
-
left.left = right;
|
|
264
|
-
setParent(right, left);
|
|
265
|
-
|
|
266
|
-
left.refit();
|
|
267
|
-
//update leaf count
|
|
268
|
-
node.left.updateLeafNodeCount();
|
|
269
|
-
break;
|
|
270
|
-
case 2:
|
|
271
|
-
node.right = leftRight;
|
|
272
|
-
setParent(leftRight, node);
|
|
273
|
-
left.right = right;
|
|
274
|
-
setParent(right, left);
|
|
275
|
-
|
|
276
|
-
left.refit();
|
|
277
|
-
//update leaf count
|
|
278
|
-
node.left.updateLeafNodeCount();
|
|
279
|
-
break;
|
|
280
|
-
case 3:
|
|
281
|
-
node.left = rightLeft;
|
|
282
|
-
setParent(rightLeft, node);
|
|
283
|
-
right.left = left;
|
|
284
|
-
setParent(left, right);
|
|
285
|
-
|
|
286
|
-
right.refit();
|
|
287
|
-
//update leaf count
|
|
288
|
-
node.right.updateLeafNodeCount();
|
|
289
|
-
break;
|
|
290
|
-
case 4:
|
|
291
|
-
node.left = rightRight;
|
|
292
|
-
setParent(rightRight, node);
|
|
293
|
-
right.right = left;
|
|
294
|
-
setParent(left, right);
|
|
295
|
-
|
|
296
|
-
right.refit();
|
|
297
|
-
//update leaf count
|
|
298
|
-
node.right.updateLeafNodeCount();
|
|
299
|
-
break;
|
|
300
|
-
case 5:
|
|
301
|
-
left.right = rightLeft;
|
|
302
|
-
setParent(rightLeft, left);
|
|
303
|
-
right.left = leftRight;
|
|
304
|
-
setParent(leftRight, right);
|
|
305
|
-
|
|
306
|
-
left.refit();
|
|
307
|
-
right.refit();
|
|
308
|
-
|
|
309
|
-
//update leaf count
|
|
310
|
-
node.left.updateLeafNodeCount();
|
|
311
|
-
node.right.updateLeafNodeCount();
|
|
312
|
-
break;
|
|
313
|
-
case 6:
|
|
314
|
-
left.right = rightRight;
|
|
315
|
-
setParent(rightRight, left);
|
|
316
|
-
right.right = leftRight;
|
|
317
|
-
setParent(leftRight, right);
|
|
318
|
-
|
|
319
|
-
left.refit();
|
|
320
|
-
right.refit();
|
|
321
|
-
//update leaf count
|
|
322
|
-
node.left.updateLeafNodeCount();
|
|
323
|
-
node.right.updateLeafNodeCount();
|
|
324
|
-
break;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return bestRotation;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
75
|
/**
|
|
331
76
|
*
|
|
332
77
|
* @param {BinaryNode} root
|
|
333
78
|
* @param {int} maxIterations
|
|
334
79
|
*/
|
|
335
|
-
function optimize(root, maxIterations = 1000) {
|
|
80
|
+
export function optimize(root, maxIterations = 1000) {
|
|
336
81
|
const traverser = new StacklessTraverser();
|
|
337
82
|
|
|
338
83
|
traverser.init(root);
|
|
@@ -376,8 +121,3 @@ function optimize(root, maxIterations = 1000) {
|
|
|
376
121
|
|
|
377
122
|
return changeCounter;
|
|
378
123
|
}
|
|
379
|
-
|
|
380
|
-
export {
|
|
381
|
-
optimize,
|
|
382
|
-
tryRotateSingleNode
|
|
383
|
-
};
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { boxSurfaceArea2 as computeArea, scoreBoxesSAH as computeAreaFor2 } from "../aabb3/AABB3Math.js";
|
|
2
|
+
import { surfaceAreaHeuristic as sah } from "../sah/surfaceAreaHeuristic.js";
|
|
3
|
+
import { isLeaf } from "../LeafNode.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {Node} node
|
|
8
|
+
* @param {BinaryNode} parent
|
|
9
|
+
*/
|
|
10
|
+
function setParent(node, parent) {
|
|
11
|
+
node.parentNode = parent;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Based on paper "Fast, Effective BVH Updates for Animated Scenes" Kopta et. al. (url: http://www.cs.utah.edu/~thiago/papers/rotations.pdf)
|
|
16
|
+
* @param {BinaryNode} node
|
|
17
|
+
* @returns {int} value from 0 to 6, 0 means no rotation has taken place
|
|
18
|
+
*/
|
|
19
|
+
export function tryRotateSingleNode(node) {
|
|
20
|
+
|
|
21
|
+
const left = node.left;
|
|
22
|
+
const right = node.right;
|
|
23
|
+
|
|
24
|
+
if (left === null || right === null) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
First we compute best rotation to apply, enumerated by 0-6
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
let bestRotation = 0;
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
const nodeArea = computeArea(node);
|
|
36
|
+
const leftArea = computeArea(left);
|
|
37
|
+
const rightArea = computeArea(right);
|
|
38
|
+
|
|
39
|
+
const leftLeaves = left.leafNodeCount;
|
|
40
|
+
const rightLeaves = right.leafNodeCount;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
let bestCost = sah(
|
|
44
|
+
nodeArea,
|
|
45
|
+
leftArea,
|
|
46
|
+
rightArea,
|
|
47
|
+
leftLeaves,
|
|
48
|
+
rightLeaves
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
let candidateCost;
|
|
52
|
+
|
|
53
|
+
let leftLeftArea,
|
|
54
|
+
leftRightArea,
|
|
55
|
+
rightLeftArea,
|
|
56
|
+
rightRightArea;
|
|
57
|
+
|
|
58
|
+
let leftLeft,
|
|
59
|
+
leftRight,
|
|
60
|
+
rightLeft,
|
|
61
|
+
rightRight;
|
|
62
|
+
|
|
63
|
+
let leftLeftLeaves,
|
|
64
|
+
leftRightLeaves,
|
|
65
|
+
rightLeftLeaves,
|
|
66
|
+
rightRightLeaves;
|
|
67
|
+
|
|
68
|
+
let considerLeft = !isLeaf(left);
|
|
69
|
+
|
|
70
|
+
if (considerLeft) {
|
|
71
|
+
leftLeft = left.left;
|
|
72
|
+
leftRight = left.right;
|
|
73
|
+
|
|
74
|
+
considerLeft = (leftLeft !== null && leftRight !== null);
|
|
75
|
+
if (considerLeft) {
|
|
76
|
+
|
|
77
|
+
leftLeftArea = computeArea(leftLeft);
|
|
78
|
+
leftRightArea = computeArea(leftRight);
|
|
79
|
+
|
|
80
|
+
leftLeftLeaves = leftLeft.leafNodeCount;
|
|
81
|
+
leftRightLeaves = leftRight.leafNodeCount;
|
|
82
|
+
|
|
83
|
+
// (1) N N //
|
|
84
|
+
// / \ / \ //
|
|
85
|
+
// L R -----> L LL //
|
|
86
|
+
// / \ / \ //
|
|
87
|
+
// LL LR R LR //
|
|
88
|
+
candidateCost = sah(nodeArea, computeAreaFor2(right, leftRight), leftLeftArea, rightLeaves + leftRightLeaves, leftLeftLeaves);
|
|
89
|
+
|
|
90
|
+
if (candidateCost < bestCost) {
|
|
91
|
+
bestRotation = 1;
|
|
92
|
+
bestCost = candidateCost;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// (2) N N //
|
|
96
|
+
// / \ / \ //
|
|
97
|
+
// L R -----> L LR //
|
|
98
|
+
// / \ / \ //
|
|
99
|
+
// LL LR LL R //
|
|
100
|
+
candidateCost = sah(nodeArea, computeAreaFor2(leftLeft, right), leftRightArea, leftLeftLeaves + rightLeaves, leftRightLeaves);
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
if (candidateCost < bestCost) {
|
|
104
|
+
bestRotation = 2;
|
|
105
|
+
bestCost = candidateCost;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!isLeaf(right)) {
|
|
110
|
+
rightLeft = right.left;
|
|
111
|
+
rightRight = right.right;
|
|
112
|
+
if (rightLeft !== null && rightRight !== null) {
|
|
113
|
+
|
|
114
|
+
rightLeftArea = computeArea(rightLeft);
|
|
115
|
+
rightRightArea = computeArea(rightRight);
|
|
116
|
+
|
|
117
|
+
rightLeftLeaves = rightLeft.leafNodeCount;
|
|
118
|
+
rightRightLeaves = rightRight.leafNodeCount;
|
|
119
|
+
|
|
120
|
+
// (3) N N //
|
|
121
|
+
// / \ / \ //
|
|
122
|
+
// L R -----> RL R //
|
|
123
|
+
// / \ / \ //
|
|
124
|
+
// RL RR L RR //
|
|
125
|
+
candidateCost = sah(nodeArea, rightLeftArea, computeAreaFor2(left, rightRight), rightLeftLeaves, leftLeaves + rightRightLeaves);
|
|
126
|
+
|
|
127
|
+
if (candidateCost < bestCost) {
|
|
128
|
+
bestRotation = 3;
|
|
129
|
+
bestCost = candidateCost;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// (4) N N //
|
|
133
|
+
// / \ / \ //
|
|
134
|
+
// L R -----> RR R //
|
|
135
|
+
// / \ / \ //
|
|
136
|
+
// RL RR RL L //
|
|
137
|
+
candidateCost = sah(nodeArea, rightRightArea, computeAreaFor2(rightLeft, left), rightRightLeaves, rightLeftLeaves + leftLeaves);
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if (candidateCost < bestCost) {
|
|
141
|
+
bestRotation = 4;
|
|
142
|
+
bestCost = candidateCost;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (considerLeft) {
|
|
146
|
+
//both child nodes are not leaf
|
|
147
|
+
|
|
148
|
+
// (5) N N //
|
|
149
|
+
// / \ / \ //
|
|
150
|
+
// L R -----> L R //
|
|
151
|
+
// / \ / \ / \ / \ //
|
|
152
|
+
// LL LR RL RR LL RL LR RR //
|
|
153
|
+
candidateCost = sah(
|
|
154
|
+
nodeArea,
|
|
155
|
+
computeAreaFor2(leftLeft, rightLeft),
|
|
156
|
+
computeAreaFor2(leftRight, rightRight),
|
|
157
|
+
leftLeftLeaves + rightLeftLeaves,
|
|
158
|
+
leftRightLeaves + rightRightLeaves
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if (candidateCost < bestCost) {
|
|
163
|
+
bestRotation = 5;
|
|
164
|
+
bestCost = candidateCost;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// (6) N N //
|
|
168
|
+
// / \ / \ //
|
|
169
|
+
// L R -----> L R //
|
|
170
|
+
// / \ / \ / \ / \ //
|
|
171
|
+
// LL LR RL RR LL RR RL LR //
|
|
172
|
+
candidateCost = sah(
|
|
173
|
+
nodeArea,
|
|
174
|
+
computeAreaFor2(leftLeft, rightRight),
|
|
175
|
+
computeAreaFor2(rightLeft, leftRight),
|
|
176
|
+
leftLeftLeaves + rightRightLeaves,
|
|
177
|
+
rightLeftLeaves + leftRightLeaves
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
if (candidateCost < bestCost) {
|
|
181
|
+
bestRotation = 6;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
switch (bestRotation) {
|
|
188
|
+
case 0:
|
|
189
|
+
//no rotation
|
|
190
|
+
break;
|
|
191
|
+
case 1:
|
|
192
|
+
node.right = leftLeft;
|
|
193
|
+
setParent(leftLeft, node);
|
|
194
|
+
left.left = right;
|
|
195
|
+
setParent(right, left);
|
|
196
|
+
|
|
197
|
+
left.refit();
|
|
198
|
+
//update leaf count
|
|
199
|
+
node.left.updateLeafNodeCount();
|
|
200
|
+
break;
|
|
201
|
+
case 2:
|
|
202
|
+
node.right = leftRight;
|
|
203
|
+
setParent(leftRight, node);
|
|
204
|
+
left.right = right;
|
|
205
|
+
setParent(right, left);
|
|
206
|
+
|
|
207
|
+
left.refit();
|
|
208
|
+
//update leaf count
|
|
209
|
+
node.left.updateLeafNodeCount();
|
|
210
|
+
break;
|
|
211
|
+
case 3:
|
|
212
|
+
node.left = rightLeft;
|
|
213
|
+
setParent(rightLeft, node);
|
|
214
|
+
right.left = left;
|
|
215
|
+
setParent(left, right);
|
|
216
|
+
|
|
217
|
+
right.refit();
|
|
218
|
+
//update leaf count
|
|
219
|
+
node.right.updateLeafNodeCount();
|
|
220
|
+
break;
|
|
221
|
+
case 4:
|
|
222
|
+
node.left = rightRight;
|
|
223
|
+
setParent(rightRight, node);
|
|
224
|
+
right.right = left;
|
|
225
|
+
setParent(left, right);
|
|
226
|
+
|
|
227
|
+
right.refit();
|
|
228
|
+
//update leaf count
|
|
229
|
+
node.right.updateLeafNodeCount();
|
|
230
|
+
break;
|
|
231
|
+
case 5:
|
|
232
|
+
left.right = rightLeft;
|
|
233
|
+
setParent(rightLeft, left);
|
|
234
|
+
right.left = leftRight;
|
|
235
|
+
setParent(leftRight, right);
|
|
236
|
+
|
|
237
|
+
left.refit();
|
|
238
|
+
right.refit();
|
|
239
|
+
|
|
240
|
+
//update leaf count
|
|
241
|
+
node.left.updateLeafNodeCount();
|
|
242
|
+
node.right.updateLeafNodeCount();
|
|
243
|
+
break;
|
|
244
|
+
case 6:
|
|
245
|
+
left.right = rightRight;
|
|
246
|
+
setParent(rightRight, left);
|
|
247
|
+
right.right = leftRight;
|
|
248
|
+
setParent(leftRight, right);
|
|
249
|
+
|
|
250
|
+
left.refit();
|
|
251
|
+
right.refit();
|
|
252
|
+
//update leaf count
|
|
253
|
+
node.left.updateLeafNodeCount();
|
|
254
|
+
node.right.updateLeafNodeCount();
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return bestRotation;
|
|
259
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Asset } from "../Asset.js";
|
|
2
2
|
import { AssetLoader } from "./AssetLoader.js";
|
|
3
|
+
import { CrossOriginKind } from "../CORS/CrossOriginKind.js";
|
|
3
4
|
|
|
4
5
|
export class ArrayBufferLoader extends AssetLoader {
|
|
5
6
|
load(path, success, failure, progress) {
|
|
@@ -8,6 +9,12 @@ export class ArrayBufferLoader extends AssetLoader {
|
|
|
8
9
|
xhr.open('GET', path, true);
|
|
9
10
|
xhr.responseType = "arraybuffer";
|
|
10
11
|
|
|
12
|
+
const coc = this.assetManager.crossOriginConfig;
|
|
13
|
+
|
|
14
|
+
if (coc.kind === CrossOriginKind.UseCredentials) {
|
|
15
|
+
xhr.withCredentials = true;
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
xhr.addEventListener('load', function () {
|
|
12
19
|
if (xhr.readyState === xhr.DONE && xhr.status === 200) {
|
|
13
20
|
const arrayBuffer = xhr.response;
|
|
@@ -4,11 +4,11 @@ import { GameAssetType } from "../../GameAssetType.js";
|
|
|
4
4
|
import { convertTexture2Sampler2D } from "../../../graphics/texture/sampler/convertTexture2Sampler2D.js";
|
|
5
5
|
import { ImageRGBADataAsset } from "./ImageRGBADataAsset.js";
|
|
6
6
|
import { ArrayBufferLoader } from "../ArrayBufferLoader.js";
|
|
7
|
-
import { noop } from "../../../../core/function/Functions.js";
|
|
8
7
|
import { CodecWithFallback } from "./codec/CodecWithFallback.js";
|
|
9
8
|
import { ThreadedImageDecoder } from "./codec/ThreadedImageDecoder.js";
|
|
10
9
|
import { NativeImageDecoder } from "./codec/NativeImageDecoder.js";
|
|
11
10
|
|
|
11
|
+
const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
|
|
12
12
|
|
|
13
13
|
export class ImageRGBADataLoader extends AssetLoader {
|
|
14
14
|
constructor() {
|
|
@@ -20,6 +20,15 @@ export class ImageRGBADataLoader extends AssetLoader {
|
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
async link(assetManager, engine) {
|
|
24
|
+
|
|
25
|
+
if (assetManager.getLoaderByType(ASSET_TYPE_ARRAY_BUFFER) === undefined) {
|
|
26
|
+
assetManager.registerLoader(ASSET_TYPE_ARRAY_BUFFER, new ArrayBufferLoader());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
super.link(assetManager, engine);
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
/**
|
|
24
33
|
*
|
|
25
34
|
* @param {string} path
|
|
@@ -27,11 +36,7 @@ export class ImageRGBADataLoader extends AssetLoader {
|
|
|
27
36
|
* @private
|
|
28
37
|
*/
|
|
29
38
|
async __decode_via_worker(path) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
const asset = await new Promise((resolve, reject) => {
|
|
33
|
-
loader.load(path, resolve, reject, noop);
|
|
34
|
-
});
|
|
39
|
+
const asset = await this.assetManager.promise(path, ASSET_TYPE_ARRAY_BUFFER);
|
|
35
40
|
|
|
36
41
|
/**
|
|
37
42
|
* @type {ArrayBuffer}
|
|
@@ -132,7 +132,7 @@ class EntityBuilder {
|
|
|
132
132
|
throw new Error("Can not add " + componentInstance + " to EntityBuilder");
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
assert.notOk(this.getComponent(componentInstance.__proto__.constructor) !== null,
|
|
135
|
+
assert.notOk(this.getComponent(componentInstance.__proto__.constructor) !== null, 'Component of this type already exists');
|
|
136
136
|
|
|
137
137
|
this.element.push(componentInstance);
|
|
138
138
|
|
|
@@ -150,12 +150,16 @@ class EntityBuilder {
|
|
|
150
150
|
* @returns {T|null} component of specified class
|
|
151
151
|
*/
|
|
152
152
|
getComponent(klass) {
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
const elements = this.element;
|
|
154
|
+
const element_count = elements.length;
|
|
155
|
+
|
|
156
|
+
for (let i = 0; i < element_count; i++) {
|
|
157
|
+
const component = elements[i];
|
|
155
158
|
if (component instanceof klass) {
|
|
156
159
|
return component;
|
|
157
160
|
}
|
|
158
161
|
}
|
|
162
|
+
|
|
159
163
|
return null;
|
|
160
164
|
}
|
|
161
165
|
|
|
@@ -314,7 +318,10 @@ class EntityBuilder {
|
|
|
314
318
|
assert.defined(dataset, "dataset");
|
|
315
319
|
assert.notNull(dataset, "dataset");
|
|
316
320
|
|
|
317
|
-
if (
|
|
321
|
+
if (
|
|
322
|
+
this.getFlag(EntityBuilderFlags.Built)
|
|
323
|
+
&& checkExistingComponents(this.entity, this.element, dataset)
|
|
324
|
+
) {
|
|
318
325
|
//already built
|
|
319
326
|
return this.entity;
|
|
320
327
|
}
|
|
@@ -322,7 +329,7 @@ class EntityBuilder {
|
|
|
322
329
|
const entity = this.entity = dataset.createEntity();
|
|
323
330
|
this.dataset = dataset;
|
|
324
331
|
|
|
325
|
-
let i
|
|
332
|
+
let i;
|
|
326
333
|
|
|
327
334
|
const listeners = this.deferredListeners;
|
|
328
335
|
const listeners_count = listeners.length;
|
|
@@ -122,6 +122,13 @@ export class EntityComponentDataset {
|
|
|
122
122
|
*/
|
|
123
123
|
this.componentTypeMap = [];
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Fast index lookup from a component class
|
|
127
|
+
* @type {Map<Class, number>}
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
this.__type_to_index_map = new Map();
|
|
131
|
+
|
|
125
132
|
/**
|
|
126
133
|
* How many component types exist for this collection. This is the same as componentMap.length
|
|
127
134
|
* @private
|
|
@@ -605,6 +612,13 @@ export class EntityComponentDataset {
|
|
|
605
612
|
updateObservers(indexRemapping);
|
|
606
613
|
|
|
607
614
|
this.componentTypeMap = map;
|
|
615
|
+
|
|
616
|
+
// rebuild class->index lookup
|
|
617
|
+
this.__type_to_index_map.clear();
|
|
618
|
+
for (let i = 0; i < newComponentTypeCount; i++) {
|
|
619
|
+
this.__type_to_index_map.set(map[i], i);
|
|
620
|
+
}
|
|
621
|
+
|
|
608
622
|
this.componentTypeCount = newComponentTypeCount;
|
|
609
623
|
}
|
|
610
624
|
|
|
@@ -876,7 +890,13 @@ export class EntityComponentDataset {
|
|
|
876
890
|
* @returns {number}
|
|
877
891
|
*/
|
|
878
892
|
computeComponentTypeIndex(klass) {
|
|
879
|
-
|
|
893
|
+
const idx = this.__type_to_index_map.get(klass);
|
|
894
|
+
|
|
895
|
+
if (idx === undefined) {
|
|
896
|
+
return -1;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
return idx;
|
|
880
900
|
}
|
|
881
901
|
|
|
882
902
|
/**
|
|
@@ -926,16 +946,16 @@ export class EntityComponentDataset {
|
|
|
926
946
|
addComponentToEntity(entityIndex, componentInstance) {
|
|
927
947
|
|
|
928
948
|
if (!ENV_PRODUCTION) {
|
|
929
|
-
assert.
|
|
949
|
+
assert.notNull(componentInstance, "componentInstance");
|
|
930
950
|
|
|
931
|
-
assert.
|
|
951
|
+
assert.defined(componentInstance, "componentInstance");
|
|
932
952
|
}
|
|
933
953
|
|
|
934
954
|
const klass = componentInstance.constructor;
|
|
935
955
|
|
|
936
|
-
const componentTypeIndex = this.
|
|
956
|
+
const componentTypeIndex = this.__type_to_index_map.get(klass);
|
|
937
957
|
|
|
938
|
-
if (componentTypeIndex
|
|
958
|
+
if (typeof componentTypeIndex !== "number") {
|
|
939
959
|
|
|
940
960
|
|
|
941
961
|
throw new Error(`Component class not found in this dataset for componentInstance ${stringifyComponent(componentInstance)}`);
|
|
@@ -1509,7 +1529,7 @@ export class EntityComponentDataset {
|
|
|
1509
1529
|
sendEvent(entity, name, event) {
|
|
1510
1530
|
// console.log("sendEvent", entity, name, event);
|
|
1511
1531
|
|
|
1512
|
-
assert.
|
|
1532
|
+
assert.isString(name, "name");
|
|
1513
1533
|
|
|
1514
1534
|
dispatchEntityEventListeners(this.__entityEventListeners, entity, name, event);
|
|
1515
1535
|
|
|
@@ -175,7 +175,7 @@ export class AttachmentSystem extends System {
|
|
|
175
175
|
|
|
176
176
|
const boneName = attachmentSocket.boneName;
|
|
177
177
|
|
|
178
|
-
assert.
|
|
178
|
+
assert.isString(boneName, 'boneName');
|
|
179
179
|
|
|
180
180
|
//try to get the bone
|
|
181
181
|
const mesh = ecd.getComponent(parent, Mesh);
|
|
@@ -18,7 +18,17 @@ export class AttachmentSockets {
|
|
|
18
18
|
* @returns {AttachmentSocket|undefined}
|
|
19
19
|
*/
|
|
20
20
|
get(id) {
|
|
21
|
-
|
|
21
|
+
const elements = this.elements;
|
|
22
|
+
const n = elements.length;
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < n; i++) {
|
|
25
|
+
const socket = elements.get(i);
|
|
26
|
+
|
|
27
|
+
if (socket.id === id) {
|
|
28
|
+
return socket;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
/**
|
|
@@ -46,9 +46,15 @@ async function main(engine) {
|
|
|
46
46
|
|
|
47
47
|
const three_object = asset.create();
|
|
48
48
|
|
|
49
|
+
console.time('composition conversion');
|
|
49
50
|
const composition = three_object_to_entity_composition(three_object);
|
|
51
|
+
console.timeEnd('composition conversion');
|
|
50
52
|
|
|
53
|
+
console.time('composition build');
|
|
54
|
+
// console.profile('composition build');
|
|
51
55
|
composition.build(ecd);
|
|
56
|
+
// console.profileEnd('composition build');
|
|
57
|
+
console.timeEnd('composition build');
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
init(eh);
|
|
@@ -14,11 +14,11 @@ import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
|
|
|
14
14
|
import SoundListener from "../SoundListener.js";
|
|
15
15
|
import { IncrementalDeltaSet } from "../../../graphics/render/visibility/IncrementalDeltaSet.js";
|
|
16
16
|
import { queryBinaryNode_SphereIntersections_Data } from "../../../../core/bvh2/traversal/queryBinaryNode_SphereIntersections.js";
|
|
17
|
-
import { tryRotateSingleNode } from "../../../../core/bvh2/transform/RotationOptimizer.js";
|
|
18
17
|
import { SoundEmitterComponentContext } from "./SoundEmitterComponentContext.js";
|
|
19
18
|
import { SoundEmitterFlags } from "./SoundEmitterFlags.js";
|
|
20
19
|
import { SoundEmitterChannel } from "./SoundEmitterChannel.js";
|
|
21
20
|
import { invokeObjectCompare } from "../../../../core/model/object/invokeObjectCompare.js";
|
|
21
|
+
import { tryRotateSingleNode } from "../../../../core/bvh2/transform/tryRotateSingleNode.js";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* @readonly
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.34.
|
|
8
|
+
"version": "2.34.35",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|