@woosh/meep-engine 2.74.0 → 2.75.1
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/build/bundle-worker-image-decoder.js +1 -1
- package/build/meep.cjs +202 -204
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +202 -204
- package/package.json +1 -1
- package/src/core/binary/UINT32_MAX.js +5 -0
- package/src/core/bvh2/bvh3/BVH.js +44 -2
- package/src/core/bvh2/bvh3/BVH.spec.js +45 -0
- package/src/core/bvh2/bvh3/build_triangle_morton_codes.js +73 -0
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +5 -101
- package/src/core/bvh2/bvh3/ebvh_build_hierarchy.js +59 -0
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.js +31 -32
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.spec.js +139 -0
- package/src/core/collection/SCRATCH_UINT32_TRAVERSAL_STACK.js +1 -0
- package/src/core/events/signal/SignalBinding.js +18 -16
- package/src/core/geom/3d/aabb/aabb3_signed_distance_sqr_to_point.js +1 -0
- package/src/core/geom/3d/aabb/aabb3_unsigned_distance_sqr_to_point.js +36 -0
- package/src/core/model/ObservedBoolean.js +1 -1
- package/src/core/process/worker/OnDemandWorkerManager.js +5 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.js +13 -15
- package/src/engine/asset/loaders/image/ImageDecoderWorker.js +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +5 -7
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
- package/src/engine/asset/loaders/image/png/PNG.js +339 -332
- package/src/engine/asset/loaders/image/png/PNGReader.js +59 -16
- package/src/engine/asset/loaders/image/png/prototypePNG.js +13 -4
- package/src/engine/graphics/texture/virtual/v2/{SparseTexture.js → PageTexture.js} +62 -18
- package/src/engine/graphics/texture/virtual/v2/ResidentTileTexture.js +46 -0
- package/src/engine/graphics/texture/virtual/v2/{TileLoader.js → VirtualTextureTileLoader.js} +11 -8
- package/src/engine/graphics/texture/virtual/v2/{UsageMetadata.js → VirtualTextureUsage.js} +2 -8
- package/src/engine/graphics/texture/virtual/v2/{VirtualTextureManager.js → VirtualTextureUsageUpdater.js} +7 -5
- package/src/engine/graphics/texture/virtual/v2/debug/ResidencyDebugView.js +17 -5
- package/src/engine/graphics/texture/virtual/v2/debug/UsageDebugView.js +1 -1
- package/src/engine/graphics/texture/virtual/v2/debug/UsagePyramidDebugView.js +1 -1
- package/src/engine/graphics/texture/virtual/v2/prototype.js +78 -59
- package/src/engine/graphics/texture/virtual/v2/tile/{TextureTile.js → VirtualTextureTile.js} +2 -2
- package/src/engine/graphics/texture/virtual/v2/tile/compose_tile_address.js +4 -0
- /package/src/engine/graphics/texture/virtual/v2/{ShaderUsage.js → VirtualTextureUsageShader.js} +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { aabb3_unsigned_distance_sqr_to_point } from "../../../geom/3d/aabb/aabb3_unsigned_distance_sqr_to_point.js";
|
|
2
|
+
import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
|
|
3
|
+
import { seededRandom } from "../../../math/random/seededRandom.js";
|
|
1
4
|
import { BVH } from "../BVH.js";
|
|
2
5
|
import { bvh_query_user_data_nearest_to_point } from "./bvh_query_user_data_nearest_to_point.js";
|
|
3
6
|
|
|
@@ -68,3 +71,139 @@ test('two point, distance sufficient to both', () => {
|
|
|
68
71
|
|
|
69
72
|
expect(result).toBe(0);
|
|
70
73
|
});
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
test.skip("performance, 1M random boxes, 10k queries", () => {
|
|
77
|
+
|
|
78
|
+
const random = seededRandom(1);
|
|
79
|
+
|
|
80
|
+
const bvh = new BVH();
|
|
81
|
+
|
|
82
|
+
const min_bound = -1000;
|
|
83
|
+
const max_bound = 1000;
|
|
84
|
+
|
|
85
|
+
const OBJECT_COUNT = 1000000;
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < OBJECT_COUNT; i++) {
|
|
88
|
+
const node = bvh.allocate_node();
|
|
89
|
+
|
|
90
|
+
bvh.node_set_user_data(node, i);
|
|
91
|
+
|
|
92
|
+
const x = randomFloatBetween(random, min_bound, max_bound);
|
|
93
|
+
const y = randomFloatBetween(random, min_bound, max_bound);
|
|
94
|
+
const z = randomFloatBetween(random, min_bound, max_bound);
|
|
95
|
+
|
|
96
|
+
const extents = randomFloatBetween(random, 1, 50);
|
|
97
|
+
|
|
98
|
+
const x0 = x - extents;
|
|
99
|
+
const y0 = y - extents;
|
|
100
|
+
const z0 = z - extents;
|
|
101
|
+
|
|
102
|
+
const x1 = x + extents;
|
|
103
|
+
const y1 = y + extents;
|
|
104
|
+
const z1 = z + extents;
|
|
105
|
+
|
|
106
|
+
bvh.node_set_aabb_primitive(
|
|
107
|
+
node,
|
|
108
|
+
x0, y0, z0,
|
|
109
|
+
x1, y1, z1
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
bvh.insert_leaf(node);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const SAMPLE_POINT_COUNT = 10000;
|
|
116
|
+
|
|
117
|
+
const t0 = performance.now();
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < SAMPLE_POINT_COUNT; i++) {
|
|
120
|
+
|
|
121
|
+
const x = randomFloatBetween(random, min_bound, max_bound);
|
|
122
|
+
const y = randomFloatBetween(random, min_bound, max_bound);
|
|
123
|
+
const z = randomFloatBetween(random, min_bound, max_bound);
|
|
124
|
+
|
|
125
|
+
bvh_query_user_data_nearest_to_point(
|
|
126
|
+
bvh, x, y, z
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const t1 = performance.now();
|
|
131
|
+
|
|
132
|
+
const duration = (t1 - t0);
|
|
133
|
+
|
|
134
|
+
console.log(`${duration / SAMPLE_POINT_COUNT}ms/query`);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test.skip('naive search, 1m random boxes, 10k queries', () => {
|
|
138
|
+
|
|
139
|
+
const random = seededRandom(1);
|
|
140
|
+
|
|
141
|
+
const OBJECT_COUNT = 1000000;
|
|
142
|
+
|
|
143
|
+
const boxes = new Float32Array(OBJECT_COUNT * 6);
|
|
144
|
+
|
|
145
|
+
const min_bound = -1000;
|
|
146
|
+
const max_bound = 1000;
|
|
147
|
+
|
|
148
|
+
const extents = 25;
|
|
149
|
+
|
|
150
|
+
for (let i = 0; i < OBJECT_COUNT; i++) {
|
|
151
|
+
const address = i * 6;
|
|
152
|
+
|
|
153
|
+
const x = randomFloatBetween(random, min_bound, max_bound);
|
|
154
|
+
const y = randomFloatBetween(random, min_bound, max_bound);
|
|
155
|
+
const z = randomFloatBetween(random, min_bound, max_bound);
|
|
156
|
+
|
|
157
|
+
boxes[address] = x - extents;
|
|
158
|
+
boxes[address + 1] = y - extents;
|
|
159
|
+
boxes[address + 2] = z - extents;
|
|
160
|
+
|
|
161
|
+
boxes[address + 3] = x + extents;
|
|
162
|
+
boxes[address + 4] = y + extents;
|
|
163
|
+
boxes[address + 5] = z + extents;
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function naive_query(boxes, count, x, y, z) {
|
|
168
|
+
let best_distance_sqr = Infinity;
|
|
169
|
+
let best_index = 0;
|
|
170
|
+
|
|
171
|
+
const limit = count * 6;
|
|
172
|
+
|
|
173
|
+
for (let i = 0; i < limit; i += 6) {
|
|
174
|
+
const distance_sqr = aabb3_unsigned_distance_sqr_to_point(
|
|
175
|
+
boxes[i], boxes[i + 1], boxes[i + 2],
|
|
176
|
+
boxes[i + 3], boxes[i + 4], boxes[i + 5],
|
|
177
|
+
|
|
178
|
+
x, y, z
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if (distance_sqr < best_distance_sqr) {
|
|
182
|
+
best_index = i;
|
|
183
|
+
best_distance_sqr = distance_sqr;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return best_index;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const SAMPLE_POINT_COUNT = 10000;
|
|
191
|
+
|
|
192
|
+
const t0 = performance.now();
|
|
193
|
+
|
|
194
|
+
for (let i = 0; i < SAMPLE_POINT_COUNT; i++) {
|
|
195
|
+
|
|
196
|
+
const x = randomFloatBetween(random, min_bound, max_bound);
|
|
197
|
+
const y = randomFloatBetween(random, min_bound, max_bound);
|
|
198
|
+
const z = randomFloatBetween(random, min_bound, max_bound);
|
|
199
|
+
|
|
200
|
+
naive_query(boxes, OBJECT_COUNT, x, y, z);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const t1 = performance.now();
|
|
204
|
+
|
|
205
|
+
const duration = (t1 - t0);
|
|
206
|
+
|
|
207
|
+
console.log(`${duration / SAMPLE_POINT_COUNT}ms/query`);
|
|
208
|
+
|
|
209
|
+
});
|
|
@@ -8,6 +8,7 @@ export const SCRATCH_UINT32_TRAVERSAL_STACK = new Uint32Array(781250);
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Pointer used to track current top of the stack, make sure to unwind once your traversal is done
|
|
11
|
+
* Must be a positive integer
|
|
11
12
|
* @type {number}
|
|
12
13
|
*/
|
|
13
14
|
SCRATCH_UINT32_TRAVERSAL_STACK.pointer = 0;
|
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @copyright Alex Goldring 2018
|
|
2
|
+
* Utility class for managing connection between listeners to signals
|
|
4
3
|
*/
|
|
4
|
+
export class SignalBinding {
|
|
5
|
+
/**
|
|
6
|
+
* State flag
|
|
7
|
+
* @type {boolean}
|
|
8
|
+
*/
|
|
9
|
+
#linked = false;
|
|
5
10
|
|
|
11
|
+
get linked() {
|
|
12
|
+
return this.#linked;
|
|
13
|
+
}
|
|
6
14
|
|
|
7
|
-
export class SignalBinding {
|
|
8
15
|
/**
|
|
9
16
|
*
|
|
10
17
|
* @param {Signal} signal
|
|
11
18
|
* @param {function} handler
|
|
12
|
-
* @param {*} [context]
|
|
19
|
+
* @param {*} [context] will be passed as thisArg to the handler
|
|
13
20
|
* @constructor
|
|
14
21
|
*/
|
|
15
22
|
constructor(signal, handler, context) {
|
|
16
23
|
if (typeof handler !== "function") {
|
|
17
|
-
throw new TypeError(`handler must be a function, instead was ${handler}`);
|
|
24
|
+
throw new TypeError(`handler must be a function, instead was '${typeof handler}'`);
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
if (typeof signal !== "object") {
|
|
21
|
-
throw new TypeError(`signal must be of an object, instead was ${signal}`)
|
|
28
|
+
throw new TypeError(`signal must be of an object, instead was '${typeof signal}'`)
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
if (typeof signal.add !== "function") {
|
|
25
|
-
throw new TypeError(`signal.add must be a function, instead was ${signal.add}`);
|
|
32
|
+
throw new TypeError(`signal.add must be a function, instead was '${typeof signal.add}'`);
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
/**
|
|
@@ -43,11 +50,6 @@ export class SignalBinding {
|
|
|
43
50
|
*/
|
|
44
51
|
this.context = context;
|
|
45
52
|
|
|
46
|
-
/**
|
|
47
|
-
* State flag
|
|
48
|
-
* @type {boolean}
|
|
49
|
-
*/
|
|
50
|
-
this.linked = false;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
/**
|
|
@@ -55,11 +57,11 @@ export class SignalBinding {
|
|
|
55
57
|
* Idempotent
|
|
56
58
|
*/
|
|
57
59
|
link() {
|
|
58
|
-
if (this
|
|
60
|
+
if (this.#linked) {
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
this
|
|
64
|
+
this.#linked = true;
|
|
63
65
|
this.signal.add(this.handler, this.context);
|
|
64
66
|
}
|
|
65
67
|
|
|
@@ -68,11 +70,11 @@ export class SignalBinding {
|
|
|
68
70
|
* Idempotent
|
|
69
71
|
*/
|
|
70
72
|
unlink() {
|
|
71
|
-
if (!this
|
|
73
|
+
if (!this.#linked) {
|
|
72
74
|
return;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
this
|
|
77
|
+
this.#linked = false;
|
|
76
78
|
this.signal.remove(this.handler, this.context);
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { max3 } from "../../../math/max3.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compute squared distance to point, value is negative if the point is inside the box
|
|
5
|
+
* @param {number} x0
|
|
6
|
+
* @param {number} y0
|
|
7
|
+
* @param {number} z0
|
|
8
|
+
* @param {number} x1
|
|
9
|
+
* @param {number} y1
|
|
10
|
+
* @param {number} z1
|
|
11
|
+
* @param {number} point_x
|
|
12
|
+
* @param {number} point_y
|
|
13
|
+
* @param {number} point_z
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*/
|
|
16
|
+
export function aabb3_unsigned_distance_sqr_to_point(
|
|
17
|
+
x0, y0, z0,
|
|
18
|
+
x1, y1, z1,
|
|
19
|
+
point_x, point_y, point_z
|
|
20
|
+
) {
|
|
21
|
+
//do projection
|
|
22
|
+
const xp0 = x0 - point_x;
|
|
23
|
+
const xp1 = point_x - x1;
|
|
24
|
+
const yp0 = y0 - point_y;
|
|
25
|
+
const yp1 = point_y - y1;
|
|
26
|
+
const zp0 = z0 - point_z;
|
|
27
|
+
const zp1 = point_z - z1;
|
|
28
|
+
|
|
29
|
+
//calculate separation in each axis
|
|
30
|
+
const dx = max3(0, xp0, xp1);
|
|
31
|
+
const dy = max3(0, yp0, yp1);
|
|
32
|
+
const dz = max3(0, zp0, zp1);
|
|
33
|
+
|
|
34
|
+
//straight-line distance
|
|
35
|
+
return dx * dx + dy * dy + dz * dz;
|
|
36
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {assert} from "../../assert.js";
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
2
|
|
|
3
3
|
export class OnDemandWorkerManager {
|
|
4
4
|
|
|
@@ -35,6 +35,10 @@ export class OnDemandWorkerManager {
|
|
|
35
35
|
this.worker = worker;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* In milliseconds
|
|
40
|
+
* @param {number} v
|
|
41
|
+
*/
|
|
38
42
|
setTimeout(v) {
|
|
39
43
|
assert.isNonNegativeInteger(v, 'v');
|
|
40
44
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { noop } from "../../../core/function/Functions.js";
|
|
1
2
|
import { Asset } from "../Asset.js";
|
|
2
|
-
import { AssetLoader } from "./AssetLoader.js";
|
|
3
|
-
import { CrossOriginKind } from "../CORS/CrossOriginKind.js";
|
|
4
3
|
import { CrossOriginConfig } from "../CORS/CrossOriginConfig.js";
|
|
5
|
-
import {
|
|
4
|
+
import { CrossOriginKind } from "../CORS/CrossOriginKind.js";
|
|
5
|
+
import { AssetLoader } from "./AssetLoader.js";
|
|
6
6
|
|
|
7
7
|
export class ArrayBufferLoader extends AssetLoader {
|
|
8
8
|
/**
|
|
@@ -90,33 +90,31 @@ export class ArrayBufferLoader extends AssetLoader {
|
|
|
90
90
|
const reader = response.body.getReader();
|
|
91
91
|
const contentLength = response.headers.get('Content-Length');
|
|
92
92
|
const total = contentLength ? parseInt(contentLength) : 0;
|
|
93
|
-
const lengthComputable = total !== 0;
|
|
94
93
|
let loaded = 0;
|
|
95
94
|
|
|
96
95
|
// periodically read data into the new stream tracking while download progress
|
|
97
96
|
const stream = new ReadableStream({
|
|
97
|
+
type: "bytes",
|
|
98
98
|
start(controller) {
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
pump();
|
|
101
101
|
|
|
102
|
-
function
|
|
102
|
+
function pump() {
|
|
103
103
|
|
|
104
104
|
reader.read().then(({ done, value }) => {
|
|
105
105
|
|
|
106
106
|
if (done) {
|
|
107
|
-
|
|
107
|
+
// no more data, we're done
|
|
108
108
|
controller.close();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
loaded += value.byteLength;
|
|
113
|
-
|
|
114
|
-
progress(loaded, length);
|
|
112
|
+
loaded += value.byteLength;
|
|
115
113
|
|
|
116
|
-
|
|
117
|
-
readData();
|
|
114
|
+
progress(loaded, total);
|
|
118
115
|
|
|
119
|
-
|
|
116
|
+
controller.enqueue(value);
|
|
117
|
+
pump();
|
|
120
118
|
|
|
121
119
|
});
|
|
122
120
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { GameAssetType } from "../../GameAssetType.js";
|
|
1
|
+
import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
|
|
3
2
|
import { convertTexture2Sampler2D } from "../../../graphics/texture/sampler/convertTexture2Sampler2D.js";
|
|
4
|
-
import {
|
|
3
|
+
import { GameAssetType } from "../../GameAssetType.js";
|
|
5
4
|
import { ArrayBufferLoader } from "../ArrayBufferLoader.js";
|
|
5
|
+
import { AssetLoader } from "../AssetLoader.js";
|
|
6
6
|
import { CodecWithFallback } from "./codec/CodecWithFallback.js";
|
|
7
7
|
import { ThreadedImageDecoder } from "./codec/ThreadedImageDecoder.js";
|
|
8
|
-
import {
|
|
9
|
-
import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
|
|
8
|
+
import { ImageRGBADataAsset } from "./ImageRGBADataAsset.js";
|
|
10
9
|
|
|
11
10
|
const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
|
|
12
11
|
|
|
@@ -16,7 +15,7 @@ export class ImageRGBADataLoader extends AssetLoader {
|
|
|
16
15
|
|
|
17
16
|
this.decoder = new CodecWithFallback(
|
|
18
17
|
new ThreadedImageDecoder(),
|
|
19
|
-
new NativeImageDecoder()
|
|
18
|
+
// new NativeImageDecoder()
|
|
20
19
|
);
|
|
21
20
|
}
|
|
22
21
|
|
|
@@ -58,7 +57,6 @@ export class ImageRGBADataLoader extends AssetLoader {
|
|
|
58
57
|
|
|
59
58
|
const bitmap = await this.__decode_via_worker(path, scope);
|
|
60
59
|
|
|
61
|
-
|
|
62
60
|
let data;
|
|
63
61
|
|
|
64
62
|
const bitDepth = bitmap.bitDepth;
|