@woosh/meep-engine 2.43.20 → 2.43.22

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.
Files changed (25) hide show
  1. package/core/collection/HashMap.d.ts +2 -2
  2. package/core/collection/HashMap.js +22 -2
  3. package/core/geom/3d/morton/mortonEncode_magicbits.js +18 -0
  4. package/core/geom/3d/topology/struct/BinaryElementPool.js +292 -0
  5. package/core/geom/3d/topology/struct/BinaryElementPool.spec.js +36 -0
  6. package/core/geom/3d/topology/struct/BinaryTopology.js +454 -66
  7. package/core/geom/3d/topology/struct/BinaryTopology.spec.js +16 -0
  8. package/core/geom/3d/topology/struct/TopoEdge.js +4 -0
  9. package/core/geom/3d/topology/struct/TopoMesh.js +25 -0
  10. package/core/geom/3d/topology/struct/TopoTriangle.js +4 -0
  11. package/core/geom/3d/topology/struct/TopoVertex.js +8 -0
  12. package/core/geom/3d/topology/struct/bt_index_geometry_to_topology.js +329 -0
  13. package/core/geom/3d/topology/struct/bt_index_geometry_to_topology.spec.js +26 -0
  14. package/core/geom/3d/topology/struct/prototypeBinaryTopology.js +55 -0
  15. package/engine/graphics/ecs/mesh-v2/aggregate/SGMeshHighlightSystem.js +12 -3
  16. package/engine/graphics/micron/format/MicronGeometryPatch.d.ts +1 -1
  17. package/engine/graphics/micron/format/MicronGeometryPatch.js +2 -1
  18. package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +89 -64
  19. package/engine/graphics/sh3/path_tracer/PathTracedMesh.js +4 -0
  20. package/engine/graphics/sh3/path_tracer/PathTracer.js +90 -36
  21. package/engine/graphics/sh3/path_tracer/getBiasedNormalSample.js +1 -1
  22. package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +44 -10
  23. package/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +28 -13
  24. package/engine/save/storage/IndexedDBStorage.js +1 -0
  25. package/package.json +1 -1
@@ -0,0 +1,329 @@
1
+ import { HashMap } from "../../../../collection/HashMap.js";
2
+ import { split_by_2 } from "../../morton/mortonEncode_magicbits.js";
3
+ import { NULL_POINTER } from "./BinaryTopology.js";
4
+
5
+
6
+ /**
7
+ * Populates supplied topology with data from supplied indexed geometry
8
+ * @see https://github.com/blender/blender/blob/9cb061f4f0119e647173e7d354e1457e97632333/source/blender/blenkernel/intern/mesh_calc_edges.cc
9
+ * @see https://github.com/blender/blender/blob/9cb061f4f0119e647173e7d354e1457e97632333/source/blender/io/stl/importer/stl_import_mesh.cc#L63
10
+ * @param {BinaryTopology} out
11
+ * @param {number[]} indices
12
+ * @param {number[]} vertex_positions
13
+ * @param {number[]} [vertex_normals]
14
+ */
15
+ export function bt_index_geometry_to_topology(
16
+ out,
17
+ indices,
18
+ vertex_positions,
19
+ vertex_normals
20
+ ) {
21
+
22
+ // remove any existing data
23
+ out.clear();
24
+
25
+ /*
26
+ NOTES:
27
+ - we use {@link BinaryElementPool#allocate_continuous} to avoid having to allocate additional mapping structure
28
+ */
29
+
30
+ // ingest all vertices
31
+ const vertex_count = vertex_positions.length / 3;
32
+
33
+ const vertex_allocation_offset = out.vertices.allocate_continuous(vertex_count);
34
+
35
+ for (let i = 0; i < vertex_count; i++) {
36
+ const i3 = i * 3;
37
+
38
+ const vertex_id = i + vertex_allocation_offset;
39
+
40
+ out.vertex_write_coordinate(vertex_id, vertex_positions, i3);
41
+
42
+ if (vertex_normals !== undefined) {
43
+ out.vertex_write_normal(vertex_id, vertex_normals, i3);
44
+ }
45
+
46
+ // initialize edge to NULL
47
+ out.vertex_write_edge(vertex_id, NULL_POINTER);
48
+ }
49
+
50
+ const face_count = indices.length / 3;
51
+
52
+ // reserve some memory to avoid extra allocations
53
+ out.loops.ensure_capacity(face_count * 3);
54
+ out.edges.ensure_capacity(face_count * 1.6);
55
+
56
+ // create faces
57
+ const face_allocation_offset = out.faces.allocate_continuous(face_count);
58
+
59
+ /**
60
+ *
61
+ * @type {HashMap<OrderedEdge, number>}
62
+ */
63
+ const edge_hash_map = new HashMap({
64
+ capacity: Math.ceil(1 + 2.1 * face_count)
65
+ });
66
+
67
+ for (let i = 0; i < face_count; i++) {
68
+ const i3 = i * 3;
69
+
70
+ const a = indices[i3];
71
+ const b = indices[i3 + 1];
72
+ const c = indices[i3 + 2];
73
+
74
+ const vertex_a = a + vertex_allocation_offset;
75
+ const vertex_b = b + vertex_allocation_offset;
76
+ const vertex_c = c + vertex_allocation_offset;
77
+
78
+ const face_id = i + face_allocation_offset;
79
+
80
+ // create edges
81
+ const edge_ab = get_or_create_edge(vertex_a, vertex_b, edge_hash_map, out);
82
+ const edge_bc = get_or_create_edge(vertex_b, vertex_c, edge_hash_map, out);
83
+ const edge_ca = get_or_create_edge(vertex_c, vertex_a, edge_hash_map, out);
84
+
85
+ // allocate loops
86
+ const loop_a = out.loop_create();
87
+ const loop_b = out.loop_create();
88
+ const loop_c = out.loop_create();
89
+
90
+ // write loops
91
+ out.loop_write_vertex(loop_a, vertex_a);
92
+ out.loop_write_vertex(loop_b, vertex_b);
93
+ out.loop_write_vertex(loop_c, vertex_c);
94
+
95
+ // link loops to edges
96
+ link_loop_to_edge(loop_a, edge_ab, out);
97
+ link_loop_to_edge(loop_b, edge_bc, out);
98
+ link_loop_to_edge(loop_c, edge_ca, out);
99
+
100
+ out.loop_write_face(loop_a, face_id);
101
+ out.loop_write_face(loop_b, face_id);
102
+ out.loop_write_face(loop_c, face_id);
103
+
104
+ /*
105
+ NOTE: Vertices (#BMLoop.v & #BMLoop.next.v) always contain vertices from (#BMEdge.v1 & #BMEdge.v2).
106
+ */
107
+ // link up loops around the face
108
+ out.loop_write_next(loop_a, loop_b);
109
+ out.loop_write_prev(loop_a, loop_c);
110
+
111
+ out.loop_write_next(loop_b, loop_c);
112
+ out.loop_write_prev(loop_b, loop_a);
113
+
114
+ out.loop_write_next(loop_c, loop_a);
115
+ out.loop_write_prev(loop_c, loop_b);
116
+
117
+ // update face
118
+ out.face_write_loop(face_id, loop_a);
119
+
120
+ }
121
+ }
122
+
123
+ /**
124
+ * follow the pointer list to the end along radial list
125
+ * @param {number} start_loop
126
+ * @param {BinaryTopology} mesh
127
+ * @returns {number}
128
+ */
129
+ function loop_radial_get_last(start_loop, mesh) {
130
+ let prev_loop = start_loop;
131
+ let next_loop;
132
+
133
+ while ((next_loop = mesh.loop_read_radial_next(prev_loop)) !== NULL_POINTER) {
134
+ prev_loop = next_loop;
135
+ }
136
+
137
+ return prev_loop;
138
+ }
139
+
140
+ /**
141
+ *
142
+ * @param {number} loop_id
143
+ * @param {number} edge_id
144
+ * @param {BinaryTopology} mesh
145
+ */
146
+ function link_loop_to_edge(loop_id, edge_id, mesh) {
147
+ mesh.loop_write_edge(loop_id, edge_id);
148
+
149
+ /**
150
+ * First loop attached to the edge
151
+ * @type {number}
152
+ */
153
+ const edge_loop_start = mesh.edge_read_loop(edge_id);
154
+
155
+ if (edge_loop_start === NULL_POINTER) {
156
+ // no loops connected yet
157
+ mesh.edge_write_loop(edge_id, loop_id);
158
+ } else {
159
+ // connect loop to the end of the list
160
+ const last_loop_in_list = loop_radial_get_last(edge_loop_start, mesh);
161
+
162
+ mesh.loop_write_radial_next(last_loop_in_list, loop_id);
163
+ mesh.loop_write_radial_prev(loop_id, last_loop_in_list);
164
+ }
165
+
166
+ }
167
+
168
+ /**
169
+ * @see https://github.com/blender/blender/blob/9cb061f4f0119e647173e7d354e1457e97632333/source/blender/blenkernel/intern/mesh_calc_edges.cc#L209
170
+ * @param {BinaryTopology} mesh
171
+ */
172
+ function bt_mesh_calc_edges(mesh) {
173
+ /**
174
+ *
175
+ * @type {HashMap<OrderedEdge, unknown>}
176
+ */
177
+ const map = new HashMap();
178
+
179
+ add_polygon_edges_to_map(mesh, map);
180
+ }
181
+
182
+ class OrderedEdge {
183
+ /**
184
+ *
185
+ * @param {number} v1
186
+ * @param {number} v2
187
+ */
188
+ constructor(v1, v2) {
189
+ if (v1 < v2) {
190
+ this.v_low = v1;
191
+ this.v_high = v2;
192
+ } else {
193
+ this.v_low = v2;
194
+ this.v_high = v1;
195
+ }
196
+ }
197
+
198
+ /**
199
+ *
200
+ * @param {number} v1
201
+ * @param {number} v2
202
+ */
203
+ set(v1, v2) {
204
+ if (v1 < v2) {
205
+ this.v_low = v1;
206
+ this.v_high = v2;
207
+ } else {
208
+ this.v_low = v2;
209
+ this.v_high = v1;
210
+ }
211
+ }
212
+
213
+ /**
214
+ *
215
+ * @param {OrderedEdge} other
216
+ */
217
+ copy(other) {
218
+ this.v_low = other.v_low;
219
+ this.v_high = other.v_high;
220
+ }
221
+
222
+ clone() {
223
+ return new OrderedEdge(this.v_low, this.v_high);
224
+ }
225
+
226
+ /**
227
+ *
228
+ * @return {number}
229
+ */
230
+ hash() {
231
+ return split_by_2(this.v_low) | (split_by_2(this.v_high) << 1);
232
+ }
233
+
234
+ /**
235
+ *
236
+ * @param {OrderedEdge} other
237
+ * @returns {boolean}
238
+ */
239
+ equals(other) {
240
+ return this.v_low === other.v_low
241
+ && this.v_high === other.v_high
242
+ ;
243
+ }
244
+ }
245
+
246
+ /**
247
+ * @see https://github.com/blender/blender/blob/9cb061f4f0119e647173e7d354e1457e97632333/source/blender/blenkernel/intern/mesh_calc_edges.cc#L96
248
+ * @param {BinaryTopology} mesh
249
+ * @param {HashMap<OrderedEdge,*>} edge_map
250
+ */
251
+ function add_polygon_edges_to_map(mesh, edge_map) {
252
+
253
+ const faces = mesh.faces;
254
+ const face_count = faces.size;
255
+
256
+ for (let i = 0; i < face_count; i++) {
257
+ if (!faces.is_allocated(i)) {
258
+ continue;
259
+ }
260
+
261
+ const first_loop = mesh.face_read_loop(i);
262
+ let prev_loop = first_loop + j;
263
+
264
+ for (let j = 0; j < 3; j++) {
265
+ const loop = first_loop + j;
266
+
267
+
268
+ const prev_v = mesh.loop_read_vertex(prev_loop);
269
+ const next_v = mesh.loop_read_vertex(loop);
270
+
271
+ const edge = new OrderedEdge(prev_v, next_v);
272
+
273
+ edge_map.getOrSet(edge, null);
274
+
275
+ prev_loop = loop;
276
+ }
277
+ }
278
+
279
+ }
280
+
281
+ /**
282
+ *
283
+ * @param {number} v0
284
+ * @param {number} v1
285
+ * @param {HashMap<OrderedEdge,number>} map
286
+ * @param {BinaryTopology} mesh
287
+ */
288
+ function get_or_create_edge(v0, v1, map, mesh) {
289
+ const scratch_ordered_edge = new OrderedEdge(v0, v1);
290
+
291
+ const existing = map.get(scratch_ordered_edge);
292
+
293
+ if (existing !== undefined) {
294
+ return existing;
295
+ }
296
+
297
+ // doesn't exist - create
298
+ const edge_id = mesh.edges.allocate();
299
+
300
+ mesh.edge_write_vertex1(edge_id, v0);
301
+ mesh.edge_write_vertex2(edge_id, v1);
302
+
303
+ // initialize rest of the edge
304
+ mesh.edge_write_loop(edge_id, NULL_POINTER);
305
+
306
+ // TODO process disk_link pointers for the edge
307
+
308
+ map.set(scratch_ordered_edge, edge_id);
309
+
310
+ return edge_id;
311
+ }
312
+
313
+
314
+ /**
315
+ * Ensure an edge between two vertices
316
+ * NOTE: works without having to use a separate hash map, resulting in faster execution and smaller RAM requirement
317
+ * @param {number} v0
318
+ * @param {number} v1
319
+ * @param {BinaryTopology} mesh
320
+ */
321
+ function get_or_create_edge_2(v0, v1, mesh) {
322
+ const first_edge = mesh.vertex_read_edge(v0);
323
+
324
+ // iterate over all edges around the vertex
325
+
326
+ // if match is found - return the match, else create a new edge and assign
327
+
328
+ // TODO implement
329
+ }
@@ -0,0 +1,26 @@
1
+ import { bt_index_geometry_to_topology } from "./bt_index_geometry_to_topology.js";
2
+ import { BinaryTopology } from "./BinaryTopology.js";
3
+
4
+ test('Empty geometry work as expected', () => {
5
+ const mesh = new BinaryTopology();
6
+ bt_index_geometry_to_topology(mesh, [], []);
7
+
8
+ expect(mesh.faces.size).toBe(0);
9
+ expect(mesh.vertices.size).toBe(0);
10
+ expect(mesh.edges.size).toBe(0);
11
+ expect(mesh.loops.size).toBe(0);
12
+ });
13
+
14
+ test('Single triangle', () => {
15
+ const mesh = new BinaryTopology();
16
+ bt_index_geometry_to_topology(mesh, [0, 1, 2], [
17
+ 1, 3, 7,
18
+ 11, 13, 17,
19
+ 23, 27, -1
20
+ ]);
21
+
22
+ expect(mesh.faces.size).toBe(1);
23
+ expect(mesh.loops.size).toBe(3);
24
+ expect(mesh.edges.size).toBe(3);
25
+ expect(mesh.vertices.size).toBe(3);
26
+ });
@@ -0,0 +1,55 @@
1
+ import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";
2
+ import { noop } from "../../../../function/Functions.js";
3
+ import { bt_index_geometry_to_topology } from "./bt_index_geometry_to_topology.js";
4
+ import { BinaryTopology } from "./BinaryTopology.js";
5
+ import {
6
+ compute_buffer_geometry_byte_size
7
+ } from "../../../../../engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.js";
8
+ import { prettyPrint } from "../../../../NumberFormat.js";
9
+ import { TopoMesh } from "./TopoMesh.js";
10
+
11
+ function promise_ply(url) {
12
+
13
+ return new Promise((resolve, reject) => {
14
+ new PLYLoader().load(url, resolve, noop, reject);
15
+ });
16
+ }
17
+
18
+
19
+ async function main() {
20
+
21
+ // const url = "data/models/stanford/Lucy100k.ply";
22
+ const url = "data/models/stanford/dragon_recon/dragon_vrip.ply";
23
+ const lucy_geom = await promise_ply(url);
24
+
25
+ const mesh = new BinaryTopology();
26
+
27
+ const positions_array = lucy_geom.getAttribute('position').array;
28
+ const index_array = lucy_geom.getIndex().array;
29
+
30
+
31
+ const topoMesh = new TopoMesh();
32
+
33
+ console.time('topo build - obj');
34
+ topoMesh.build(positions_array, index_array);
35
+ console.timeEnd('topo build - obj');
36
+
37
+ // console.time('topo build - bin');
38
+ console.profile('topo build - bin');
39
+ bt_index_geometry_to_topology(mesh, index_array, positions_array);
40
+ console.profileEnd('topo build - bin');
41
+ // console.timeEnd('topo build - bin');
42
+
43
+ mesh.trim();
44
+
45
+ console.log(mesh, lucy_geom);
46
+
47
+ console.log(`source mesh size: ${prettyPrint(compute_buffer_geometry_byte_size(lucy_geom))} bytes`);
48
+ console.log(`binary topology size: ${prettyPrint(mesh.byteSize)} bytes`);
49
+ console.log(`object topology size: ${prettyPrint(topoMesh.byteSize)} bytes`);
50
+
51
+ window.topo_obj = topoMesh;
52
+ }
53
+
54
+ main();
55
+
@@ -16,12 +16,21 @@ export class SGMeshHighlightSystem extends System {
16
16
  * @param {number} entity
17
17
  * @private
18
18
  */
19
- __apply_highlight( event, entity) {
19
+ __apply_highlight(event, entity) {
20
20
  const ecd = this.entityManager.dataset;
21
21
 
22
22
  const sg_mesh = ecd.getComponent(entity, SGMesh);
23
+
24
+ if (sg_mesh === undefined) {
25
+ return;
26
+ }
27
+
23
28
  const highlight = ecd.getComponent(entity, Highlight);
24
29
 
30
+ if (highlight === undefined) {
31
+ return;
32
+ }
33
+
25
34
  const node = sg_mesh.__node;
26
35
 
27
36
  node.traverse(t => {
@@ -35,7 +44,7 @@ export class SGMeshHighlightSystem extends System {
35
44
  * @param {number} entity
36
45
  * @private
37
46
  */
38
- __remove_highlight( event, entity) {
47
+ __remove_highlight(event, entity) {
39
48
 
40
49
  const ecd = this.entityManager.dataset;
41
50
 
@@ -56,7 +65,7 @@ export class SGMeshHighlightSystem extends System {
56
65
  */
57
66
  link(highlight, mesh, entity) {
58
67
  if (mesh.__node !== null) {
59
- this.__apply_highlight(undefined, entity);
68
+ this.__apply_highlight(undefined, entity);
60
69
  }
61
70
 
62
71
  const ecd = this.entityManager.dataset;
@@ -1,3 +1,3 @@
1
1
  export class MicronGeometryPatch {
2
-
2
+ allocate_metadata(buffer: ArrayBuffer, offset: number): number
3
3
  }
@@ -35,7 +35,7 @@ export class MicronGeometryPatch {
35
35
  this.group_bounding_box = null;
36
36
 
37
37
  /**
38
- *
38
+ * TODO get rid of this, use bounding box instead for smaller memory footprint
39
39
  * @type {number[]|Float32Array}
40
40
  */
41
41
  this.group_bounding_box_corners = null;
@@ -124,6 +124,7 @@ export class MicronGeometryPatch {
124
124
  * @returns {number}
125
125
  */
126
126
  allocate_metadata(buffer, offset) {
127
+ assert.isNonNegativeInteger(offset, 'offset');
127
128
  assert.greaterThanOrEqual(buffer.byteLength, offset + 144, 'buffer underflow');
128
129
 
129
130
  this.bounding_box = new Float32Array(buffer, offset, 6);
@@ -56,14 +56,13 @@ function ensureProxy(object) {
56
56
  }
57
57
  }
58
58
 
59
- export class GLTFAssetTransformer extends AssetTransformer {
59
+ class TransformContext {
60
60
  /**
61
61
  *
62
- * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} [cache]
62
+ * @param {AssetManager} assetManager
63
+ * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} cache
63
64
  */
64
- constructor(cache) {
65
- super();
66
-
65
+ constructor(assetManager, cache) {
67
66
  /**
68
67
  *
69
68
  * @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>|undefined}
@@ -71,20 +70,6 @@ export class GLTFAssetTransformer extends AssetTransformer {
71
70
  */
72
71
  this.__cache = cache;
73
72
 
74
- /**
75
- *
76
- * @type {AssetManager|null}
77
- * @private
78
- */
79
- this.__am = null;
80
-
81
- /**
82
- * Minimum number of polygons required for micron to be used
83
- * @type {number}
84
- * @private
85
- */
86
- this.__threshold_polycount = DEFAULT_THRESHOLD_POLYCOUNT;
87
-
88
73
  /**
89
74
  *
90
75
  * @type {MicronGeometry[]}
@@ -92,31 +77,54 @@ export class GLTFAssetTransformer extends AssetTransformer {
92
77
  */
93
78
  this.__active_mesh_micron_cache = [];
94
79
 
95
- /**
96
- * @deprecated
97
- * Whether override mesh will be created for the asset, this is generally outdated
98
- * @type {boolean}
99
- * @private
100
- */
101
- this.__settings_build_override_mesh = false;
80
+ this.__am = assetManager;
102
81
  }
103
82
 
104
83
  /**
105
84
  *
106
- * @param {AssetManager|null} am
85
+ * @param {{userData:{}}} gltf
86
+ * @param {AssetDescription} ad
107
87
  */
108
- set assetManager(am) {
109
- this.__am = am;
110
- }
88
+ async load_mesh_micron_data(gltf, ad) {
89
+ // clear active cache
90
+ this.__active_mesh_micron_cache = [];
111
91
 
92
+ const micron_metadata = gltf.userData.micron;
93
+
94
+ if (micron_metadata === undefined) {
95
+ return;
96
+ }
97
+
98
+ const uri = micron_metadata.geometry_data_uri;
99
+ if (uri === undefined) {
100
+ return;
101
+ }
102
+
103
+ const base = computePathDirectory(ad.path);
104
+
105
+ let micron_data;
106
+
107
+ const micron_path = `${base}/${uri}`;
108
+
109
+ try {
110
+ micron_data = await this.__am.promise(micron_path, ASSET_TYPE_ARRAY_BUFFER, { skip_queue: true });
111
+ } catch (e) {
112
+ console.error(`Failed to load micron geometry '${micron_path}' referenced in GLTF (will skip): ${e}`);
113
+ return;
114
+ }
115
+
116
+ // deserialize micron data
117
+ const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
118
+
119
+ deserialize_geometry_collection(this.__active_mesh_micron_cache, buffer);
120
+ }
112
121
 
113
122
  /**
114
123
  * @param {THREE.Object3D} object
115
124
  * @param {{asset:AssetDescription}} ctx
116
125
  * @return {Promise<void>}
117
- * @private
118
126
  */
119
- async __visitObjectToLoadMicron(object, ctx) {
127
+ async visitObjectToLoadMicron(object, ctx) {
120
128
  if (!object.isMesh) {
121
129
  return;
122
130
  }
@@ -150,46 +158,59 @@ export class GLTFAssetTransformer extends AssetTransformer {
150
158
  }
151
159
  }
152
160
 
161
+ }
153
162
 
163
+ export class GLTFAssetTransformer extends AssetTransformer {
154
164
  /**
155
165
  *
156
- * @param {{userData:{}}} gltf
157
- * @param {AssetDescription} ad
158
- * @private
166
+ * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} [cache]
159
167
  */
160
- async __load_mesh_micron_data(gltf, ad) {
161
- // clear active cache
162
- this.__active_mesh_micron_cache = [];
163
-
164
- const micron_metadata = gltf.userData.micron;
165
-
166
- if (micron_metadata === undefined) {
167
- return;
168
- }
169
-
170
- const uri = micron_metadata.geometry_data_uri;
171
- if (uri === undefined) {
172
- return;
173
- }
174
-
175
- const base = computePathDirectory(ad.path);
168
+ constructor(cache) {
169
+ super();
176
170
 
177
- let micron_data;
171
+ /**
172
+ *
173
+ * @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>|undefined}
174
+ * @private
175
+ */
176
+ this.__cache = cache;
178
177
 
179
- const micron_path = `${base}/${uri}`;
178
+ /**
179
+ *
180
+ * @type {AssetManager|null}
181
+ * @private
182
+ */
183
+ this.__am = null;
180
184
 
181
- try {
182
- micron_data = await this.__am.promise(micron_path, ASSET_TYPE_ARRAY_BUFFER, { skip_queue: true });
183
- } catch (e) {
184
- console.error(`Failed to load micron geometry '${micron_path}' referenced in GLTF (will skip): ${e}`);
185
- return;
186
- }
185
+ /**
186
+ * Minimum number of polygons required for micron to be used
187
+ * @type {number}
188
+ * @private
189
+ */
190
+ this.__threshold_polycount = DEFAULT_THRESHOLD_POLYCOUNT;
187
191
 
188
- // deserialize micron data
189
- const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
192
+ /**
193
+ *
194
+ * @type {MicronGeometry[]}
195
+ * @private
196
+ */
197
+ this.__active_mesh_micron_cache = [];
190
198
 
191
- deserialize_geometry_collection(this.__active_mesh_micron_cache, buffer);
199
+ /**
200
+ * @deprecated
201
+ * Whether override mesh will be created for the asset, this is generally outdated
202
+ * @type {boolean}
203
+ * @private
204
+ */
205
+ this.__settings_build_override_mesh = false;
206
+ }
192
207
 
208
+ /**
209
+ *
210
+ * @param {AssetManager|null} am
211
+ */
212
+ set assetManager(am) {
213
+ this.__am = am;
193
214
  }
194
215
 
195
216
 
@@ -212,10 +233,12 @@ export class GLTFAssetTransformer extends AssetTransformer {
212
233
  */
213
234
  const root = source.create();
214
235
 
215
- await this.__load_mesh_micron_data(source.gltf, asset_description);
236
+ const context = new TransformContext(this.__am, this.__cache);
237
+
238
+ await context.load_mesh_micron_data(source.gltf, asset_description);
216
239
 
217
240
  // attempt to load existing micron geometries
218
- await async_traverse_three_object(root, this.__visitObjectToLoadMicron, this, {
241
+ await async_traverse_three_object(root, context.visitObjectToLoadMicron, context, {
219
242
  asset: asset_description
220
243
  });
221
244
 
@@ -227,6 +250,8 @@ export class GLTFAssetTransformer extends AssetTransformer {
227
250
  }
228
251
 
229
252
  if (this.__settings_build_override_mesh) {
253
+ console.warn(`Deprecated OVERRIDE_MESH setting is ON, generating override mesh for asset: ${asset_description}`);
254
+
230
255
  const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
231
256
  micron_root.boundingSphere = root.boundingSphere;
232
257
 
@@ -54,6 +54,10 @@ export class PathTracedMesh {
54
54
  this.__local_scale_inverse = Math.hypot(scale_x, scale_y, scale_z);
55
55
  }
56
56
 
57
+ get transform() {
58
+ return this.__transform;
59
+ }
60
+
57
61
  /**
58
62
  *
59
63
  * @param {number[]} out