@woosh/meep-engine 2.34.45 → 2.34.49

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 (27) hide show
  1. package/core/binary/BitSet.js +10 -3
  2. package/core/bvh2/BinaryNode.js +53 -25
  3. package/core/bvh2/traversal/bvh_traverse_pre_order_using_stack.js +43 -0
  4. package/core/bvh2/visual/convert_bvh_to_dot_format_string.js +50 -0
  5. package/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +1 -1
  6. package/core/geom/3d/frustum/frustum_from_projection_matrix_array.js +27 -24
  7. package/core/graph/convertGraphToDotString.js +4 -4
  8. package/core/graph/v2/Graph.js +4 -0
  9. package/engine/asset/loaders/geometry/geometry/computeGeometryEquality.js +2 -1
  10. package/engine/ecs/foliage/ecs/Foliage2System.js +22 -5
  11. package/engine/graphics/compute_geometry_polycount.js +21 -0
  12. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +64 -9
  13. package/engine/graphics/micron/convert_three_object_to_micron.js +0 -2
  14. package/engine/graphics/micron/format/MicronGeometry.js +1 -3
  15. package/engine/graphics/micron/format/MicronGeometryPatch.js +33 -23
  16. package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +6 -0
  17. package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +176 -0
  18. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +1 -135
  19. package/engine/graphics/micron/prototypeVirtualGeometry.js +9 -5
  20. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +14 -53
  21. package/engine/graphics/micron/render/refinement/RefinementSpec.js +0 -11
  22. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +125 -0
  23. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +318 -13
  24. package/engine/graphics/render/layers/RenderLayer.js +22 -14
  25. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +18 -5
  26. package/engine/graphics/render/visibility/VisibilityComputer.js +11 -15
  27. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
- import { squirrel3 } from "../../../../core/math/hash/squirrel3.js";
2
1
  import { ConicRay } from "../../../../core/geom/ConicRay.js";
3
2
  import { vec4 } from "gl-matrix";
3
+ import { assert } from "../../../../core/assert.js";
4
4
 
5
5
  /**
6
6
  * Patches are organized into a tree hierarchy
@@ -13,18 +13,11 @@ export class MicronGeometryPatch {
13
13
  */
14
14
  this.id = 0;
15
15
 
16
- /**
17
- * Continuous memory region for various pieces of data to get better memory access patterns
18
- * All pieces of data end up in a continuous piece of memory, resulting in better cache coherence
19
- * @type {ArrayBuffer}
20
- */
21
- const array_buffer = new ArrayBuffer((6 + 6 + 24) * 4);
22
-
23
16
  /**
24
17
  * Bounds are used to determine screen error and whether a patch should be subdivided or not for rendering
25
18
  * @type {number[]}
26
19
  */
27
- this.bounding_box = new Float32Array(array_buffer, 0, 6);
20
+ this.bounding_box = null;
28
21
 
29
22
  /**
30
23
  *
@@ -36,13 +29,21 @@ export class MicronGeometryPatch {
36
29
  *
37
30
  * @type {number[]|Float32Array}
38
31
  */
39
- this.group_bounding_box = new Float32Array(array_buffer, 6 * 4, 6);
32
+ this.group_bounding_box = null;
40
33
 
41
34
  /**
42
35
  *
43
36
  * @type {number[]|Float32Array}
44
37
  */
45
- this.group_bounding_box_corners = new Float32Array(array_buffer, 12 * 4, 24);
38
+ this.group_bounding_box_corners = null;
39
+
40
+ /**
41
+ * Continuous memory region for various pieces of data to get better memory access patterns
42
+ * All pieces of data end up in a continuous piece of memory, resulting in better cache coherence
43
+ * @type {ArrayBuffer}
44
+ */
45
+ const array_buffer = new ArrayBuffer(144);
46
+ this.allocate_metadata(array_buffer, 0);
46
47
 
47
48
  /**
48
49
  *
@@ -114,21 +115,25 @@ export class MicronGeometryPatch {
114
115
  }
115
116
 
116
117
  /**
117
- * @deprecated
118
+ *
119
+ * @param {ArrayBuffer} buffer
120
+ * @param {number} offset
121
+ * @returns {number}
118
122
  */
119
- get parent() {
120
- throw new Error('Single parent is no longer supported, use .parents instead');
121
- }
123
+ allocate_metadata(buffer, offset) {
124
+ assert.greaterThanOrEqual(buffer.byteLength, offset + 144, 'buffer underflow');
122
125
 
123
- /**
124
- * @deprecated
125
- */
126
- set parent(v) {
127
- throw new Error('Single parent is no longer supported, use .parents instead');
126
+ this.bounding_box = new Float32Array(buffer, offset, 6);
127
+
128
+ this.group_bounding_box = new Float32Array(buffer, offset + 24, 6);
129
+
130
+ this.group_bounding_box_corners = new Float32Array(buffer, offset + 48, 24);
131
+
132
+ return 144;
128
133
  }
129
134
 
130
135
  hash() {
131
- return squirrel3(this.id);
136
+ return this.id;
132
137
  }
133
138
 
134
139
  computeByteSize() {
@@ -136,8 +141,13 @@ export class MicronGeometryPatch {
136
141
 
137
142
  result += this.face_indices.buffer.byteLength;
138
143
 
139
- for (let i = 0; i < this.vertex_attribute_arrays.length; i++) {
140
- result += this.vertex_attribute_arrays[i].buffer.byteLength;
144
+ const attribute_arrays = this.vertex_attribute_arrays;
145
+ const attribute_count = attribute_arrays.length;
146
+
147
+ for (let i = 0; i < attribute_count; i++) {
148
+ const attribute_array = attribute_arrays[i];
149
+
150
+ result += attribute_array.buffer.byteLength;
141
151
  }
142
152
 
143
153
  return result;
@@ -79,12 +79,18 @@ export class MicronGeometryBinarySerializationAdapter extends BinaryClassSeriali
79
79
 
80
80
  const patches = [];
81
81
 
82
+ // for the sake of speed, we will allocate all metadata in the same piece of memory to make traversal of patch hierarchy faster
83
+ const md_buffer = new ArrayBuffer(patch_count * 144);
84
+ let md_buffer_offset = 0;
85
+
82
86
  // build initial patches
83
87
  for (let i = 0; i < patch_count; i++) {
84
88
  const patch = new MicronGeometryPatch();
85
89
 
86
90
  patch.id = i;
87
91
 
92
+ md_buffer_offset += patch.allocate_metadata(md_buffer, md_buffer_offset);
93
+
88
94
  patches[i] = patch;
89
95
  }
90
96
 
@@ -0,0 +1,176 @@
1
+ import { AssetTransformer } from "../../../asset/AssetTransformer.js";
2
+ import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
3
+ import { MICRON_URI_FIELD } from "../MICRON_URI_FIELD.js";
4
+ import { computePathDirectory } from "../../../../core/FilePath.js";
5
+ import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
6
+ import { MicronGeometry } from "../format/MicronGeometry.js";
7
+ import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
8
+ import { async_traverse_three_object } from "../../../asset/loaders/async_traverse_three_object.js";
9
+ import { convert_three_object_to_micron } from "../convert_three_object_to_micron.js";
10
+ import { compute_geometry_polycount } from "../../compute_geometry_polycount.js";
11
+ import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
12
+ import { max2 } from "../../../../core/math/max2.js";
13
+
14
+ export const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
15
+
16
+ const DEFAULT_THRESHOLD_POLYCOUNT = 1024;
17
+
18
+ /**
19
+ *
20
+ * @param {THREE.Object3D} object
21
+ * @return {number}
22
+ */
23
+ function max_polycount(object) {
24
+ let r = 0;
25
+
26
+ traverseThreeObject(object, (m) => {
27
+ if (m.isMesh) {
28
+ const geo = m.geometry;
29
+ if (geo !== null) {
30
+ r = max2(r, compute_geometry_polycount(geo))
31
+ }
32
+ }
33
+ });
34
+
35
+ return r;
36
+ }
37
+
38
+ export class GLTFAssetTransformer extends AssetTransformer {
39
+ /**
40
+ *
41
+ * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} cache
42
+ */
43
+ constructor(cache) {
44
+ super();
45
+
46
+ /**
47
+ *
48
+ * @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>}
49
+ * @private
50
+ */
51
+ this.__cache = cache;
52
+
53
+ /**
54
+ *
55
+ * @type {AssetManager|null}
56
+ * @private
57
+ */
58
+ this.__am = null;
59
+
60
+ /**
61
+ * Minimum number of polygons required for micron to be used
62
+ * @type {number}
63
+ * @private
64
+ */
65
+ this.__threshold_polycount = DEFAULT_THRESHOLD_POLYCOUNT;
66
+
67
+ /**
68
+ *
69
+ * @type {MicronGeometryBinarySerializationAdapter}
70
+ * @private
71
+ */
72
+ this.__serde = new MicronGeometryBinarySerializationAdapter();
73
+ }
74
+
75
+ /**
76
+ *
77
+ * @param {AssetManager|null} am
78
+ */
79
+ set assetManager(am) {
80
+ this.__am = am;
81
+ }
82
+
83
+
84
+ /**
85
+ * @param {THREE.Object3D} object
86
+ * @param {{asset:AssetDescription}} ctx
87
+ * @return {Promise<void>}
88
+ * @private
89
+ */
90
+ async __visitObjectToLoadMicron(object, ctx) {
91
+ if (!object.isMesh) {
92
+ return;
93
+ }
94
+
95
+ /**
96
+ * @type {THREE.BufferGeometry}
97
+ */
98
+ const geometry = object.geometry;
99
+
100
+ const micron_uri = geometry.userData[MICRON_URI_FIELD];
101
+
102
+ if (typeof micron_uri !== "string") {
103
+ return;
104
+ }
105
+
106
+
107
+ /**
108
+ * @type {AssetDescription}
109
+ */
110
+ const ad = ctx.asset;
111
+
112
+ const base = computePathDirectory(ad.path);
113
+
114
+ let micron_data;
115
+
116
+ const micron_path = `${base}/${micron_uri}`;
117
+
118
+ try {
119
+ micron_data = await this.__am.promise(micron_path, ASSET_TYPE_ARRAY_BUFFER);
120
+ } catch (e) {
121
+ console.error(`Failed to load micron geometry '${micron_path}' referenced in GLTF (will skip): ${e}`);
122
+ return;
123
+ }
124
+
125
+ // deserialize micron data
126
+ const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
127
+ const micron_geometry = new MicronGeometry();
128
+
129
+ this.__serde.deserialize(buffer, micron_geometry);
130
+
131
+ // set proxy for raycasting
132
+ micron_geometry.proxy = geometry;
133
+
134
+ geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
135
+ }
136
+
137
+
138
+ /**
139
+ *
140
+ * @param {Asset} source
141
+ * @param {AssetDescription} asset_description
142
+ * @return {Promise<Asset>}
143
+ */
144
+ async transform(source, asset_description) {
145
+ const animationClips = source.animations;
146
+
147
+ if (animationClips !== undefined && animationClips.length > 0) {
148
+ // animations might cause trouble
149
+ console.warn(`model '${asset_description.path}' contains animations, these animations might not works as intended with micron.`);
150
+ }
151
+
152
+ /**
153
+ * @type {THREE.Object3D}
154
+ */
155
+ const root = source.create();
156
+
157
+ const gltf_max_polycount = max_polycount(root);
158
+
159
+ if (gltf_max_polycount < this.__threshold_polycount) {
160
+ // no change, geometries are too small
161
+ return source;
162
+ }
163
+
164
+ // attempt to load existing micron geometries
165
+ await async_traverse_three_object(root, this.__visitObjectToLoadMicron, this, {
166
+ asset: asset_description
167
+ });
168
+
169
+ const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
170
+ micron_root.boundingSphere = root.boundingSphere;
171
+
172
+ source.override_mesh = micron_root;
173
+
174
+ return source;
175
+ }
176
+ }
@@ -2,8 +2,6 @@ import { EnginePlugin } from "../../../plugin/EnginePlugin.js";
2
2
  import { VGThreeRenderer } from "../render/v1/VGThreeRenderer.js";
3
3
  import { RenderLayer } from "../../render/layers/RenderLayer.js";
4
4
  import { RenderPassType } from "../../render/RenderPassType.js";
5
- import { AssetTransformer } from "../../../asset/AssetTransformer.js";
6
- import { convert_three_object_to_micron } from "../convert_three_object_to_micron.js";
7
5
  import { Cache } from "../../../../core/cache/Cache.js";
8
6
  import { computeGeometryHash } from "../../../asset/loaders/geometry/geometry/computeGeometryHash.js";
9
7
  import { computeGeometryEquality } from "../../../asset/loaders/geometry/geometry/computeGeometryEquality.js";
@@ -12,13 +10,9 @@ import { AsyncRemoteHashMap } from "../../../../core/collection/map/AsyncRemoteH
12
10
  import { BufferGeometrySerializationAdapter } from "./serialization/BufferGeometrySerializationAdapter.js";
13
11
  import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
14
12
  import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper.js";
15
- import { async_traverse_three_object } from "../../../asset/loaders/async_traverse_three_object.js";
16
- import { computePathDirectory } from "../../../../core/FilePath.js";
17
- import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
18
13
  import { MicronGeometry } from "../format/MicronGeometry.js";
19
14
  import { ArrayBufferLoader } from "../../../asset/loaders/ArrayBufferLoader.js";
20
- import { MICRON_URI_FIELD } from "../MICRON_URI_FIELD.js";
21
- import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
15
+ import { ASSET_TYPE_ARRAY_BUFFER, GLTFAssetTransformer } from "./GLTFAssetTransformer.js";
22
16
 
23
17
  /**
24
18
  *
@@ -26,134 +20,6 @@ import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
26
20
  */
27
21
  const STORAGE_KEY = '@plugin/virtual-geometry-micron/geometry-cache';
28
22
 
29
- const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
30
-
31
- class GLTFAssetTransformer extends AssetTransformer {
32
- /**
33
- *
34
- * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} cache
35
- */
36
- constructor(cache) {
37
- super();
38
-
39
- /**
40
- *
41
- * @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>}
42
- * @private
43
- */
44
- this.__cache = cache;
45
-
46
- /**
47
- *
48
- * @type {AssetManager|null}
49
- * @private
50
- */
51
- this.__am = null;
52
-
53
- /**
54
- *
55
- * @type {MicronGeometryBinarySerializationAdapter}
56
- * @private
57
- */
58
- this.__serde = new MicronGeometryBinarySerializationAdapter();
59
- }
60
-
61
- /**
62
- *
63
- * @param {AssetManager|null} am
64
- */
65
- set assetManager(am) {
66
- this.__am = am;
67
- }
68
-
69
-
70
- /**
71
- * @param {THREE.Object3D} object
72
- * @param {{asset:AssetDescription}} ctx
73
- * @return {Promise<void>}
74
- * @private
75
- */
76
- async __visitObjectToLoadMicron(object, ctx) {
77
- if (!object.isMesh) {
78
- return;
79
- }
80
-
81
- /**
82
- * @type {THREE.BufferGeometry}
83
- */
84
- const geometry = object.geometry;
85
-
86
- const micron_uri = geometry.userData[MICRON_URI_FIELD];
87
-
88
- if (typeof micron_uri !== "string") {
89
- return;
90
- }
91
-
92
-
93
- /**
94
- * @type {AssetDescription}
95
- */
96
- const ad = ctx.asset;
97
-
98
- const base = computePathDirectory(ad.path);
99
-
100
- let micron_data;
101
-
102
- const micron_path = `${base}/${micron_uri}`;
103
-
104
- try {
105
- micron_data = await this.__am.promise(micron_path, ASSET_TYPE_ARRAY_BUFFER);
106
- } catch (e) {
107
- console.error(`Failed to load micron geometry '${micron_path}' referenced in GLTF (will skip): ${e}`);
108
- return;
109
- }
110
-
111
- // deserialize micron data
112
- const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
113
- const micron_geometry = new MicronGeometry();
114
-
115
- this.__serde.deserialize(buffer, micron_geometry);
116
-
117
- // set proxy for raycasting
118
- micron_geometry.proxy = geometry;
119
-
120
- geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
121
- }
122
-
123
-
124
- /**
125
- *
126
- * @param {Asset} source
127
- * @param {AssetDescription} asset_description
128
- * @return {Promise<Asset>}
129
- */
130
- async transform(source, asset_description) {
131
- const animationClips = source.animations;
132
-
133
- if (animationClips !== undefined && animationClips.length > 0) {
134
- // animations might cause trouble
135
- console.warn(`model '${asset_description.path}' contains animations, these animations might not works as intended with micron.`);
136
- }
137
-
138
- /**
139
- * @type {THREE.Object3D}
140
- */
141
- const root = source.create();
142
-
143
- // attempt to load existing micron geometries
144
- await async_traverse_three_object(root, this.__visitObjectToLoadMicron, this, {
145
- asset: asset_description
146
- });
147
-
148
- const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
149
- micron_root.boundingSphere = root.boundingSphere;
150
-
151
- source.override_mesh = micron_root;
152
-
153
- return source;
154
- }
155
- }
156
-
157
23
  export class MicronRenderPlugin extends EnginePlugin {
158
24
  constructor() {
159
25
  super();
@@ -1,10 +1,8 @@
1
1
  import {
2
2
  AmbientLight,
3
3
  BoxBufferGeometry,
4
- CameraHelper,
5
4
  CubeTextureLoader,
6
5
  DirectionalLight,
7
- DirectionalLightHelper,
8
6
  FrontSide,
9
7
  Matrix4,
10
8
  Mesh,
@@ -64,6 +62,10 @@ metrics.create({
64
62
  name: 'adapter_update', buffer_size: METRIC_BUFFER_SIZE
65
63
  });
66
64
 
65
+ metrics.create({
66
+ name: 'debug_v0', buffer_size: METRIC_BUFFER_SIZE
67
+ });
68
+
67
69
  let container, stats;
68
70
 
69
71
  let camera, scene, renderer;
@@ -261,8 +263,8 @@ function init() {
261
263
 
262
264
  // shadow_camera.onBeforeRender = do_vgrt_update;
263
265
 
264
- scene.add(new CameraHelper(shadow_camera));
265
- scene.add(new DirectionalLightHelper(directionalLight));
266
+ // scene.add(new CameraHelper(shadow_camera));
267
+ // scene.add(new DirectionalLightHelper(directionalLight));
266
268
 
267
269
  shadow_camera.updateProjectionMatrix();
268
270
 
@@ -459,7 +461,7 @@ function init() {
459
461
 
460
462
  // sample_gltf_sponza();
461
463
  // gltf_sample('data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf');
462
- sample_lucy();
464
+ // sample_lucy();
463
465
  // sample_dragon();
464
466
  // sample_gltf_hapro_2();
465
467
  // sample_gltf_hapro_1();
@@ -479,6 +481,8 @@ function init() {
479
481
  // gltf_sample('moicon/03_Jan_22_Demo/8-assets/model.gltf');
480
482
  // gltf_sample('moicon/03_Jan_22_Demo/worker_test/model.gltf');
481
483
  // gltf_sample('moicon/A4/A4/model.gltf');
484
+ gltf_sample('moicon/ztest_object_many_pieces/model.gltf');
485
+ // gltf_grid('moicon/ztest_object_many_pieces/model.gltf', 10, 10);
482
486
 
483
487
  document.addEventListener("mousemove", onDocumentMouseMove);
484
488
 
@@ -1,10 +1,10 @@
1
1
  import { array_copy } from "../../../../core/collection/array/copyArray.js";
2
2
  import Vector2 from "../../../../core/geom/Vector2.js";
3
- import { MicronGeometryPatchOccurrence } from "../format/MicronGeometryPatchOccurance.js";
4
3
  import { RefinementSpec } from "./refinement/RefinementSpec.js";
5
4
  import { ActivePatchList } from "./refinement/ActivePatchList.js";
6
- import { ActivePatchFlags } from "./refinement/ActivePatchFlags.js";
7
5
  import { mat4 } from "gl-matrix";
6
+ import { get_geometry_patch_cut } from "./refinement/get_geometry_patch_cut.js";
7
+ import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
8
8
 
9
9
  /**
10
10
  * @readonly
@@ -107,7 +107,7 @@ export class VirtualGeometryBuilder {
107
107
  }
108
108
 
109
109
  /**
110
- *
110
+ * @private
111
111
  * @param {THREE.Object3D|ThreeMicronMesh} object
112
112
  */
113
113
  buildForObject(object) {
@@ -134,15 +134,6 @@ export class VirtualGeometryBuilder {
134
134
  );
135
135
  }
136
136
  }
137
-
138
- const children = object.children;
139
- const children_count = children.length;
140
-
141
- for (let i = 0; i < children_count; i++) {
142
- const child = children[i];
143
-
144
- this.buildForObject(child);
145
- }
146
137
  }
147
138
 
148
139
  /**
@@ -158,8 +149,6 @@ export class VirtualGeometryBuilder {
158
149
  transform,
159
150
  apl
160
151
  ) {
161
- apl.initializeFromGeometry(geometry);
162
-
163
152
  refinement_spec.build(transform, this.view_projection_matrix);
164
153
 
165
154
  const output = this.output;
@@ -168,48 +157,19 @@ export class VirtualGeometryBuilder {
168
157
  output.stats_source_triangle_count += geometry.source_triangle_count;
169
158
  output.stats_source_vertex_count += geometry.source_vertex_count;
170
159
 
171
- // apl.build_from_lod(geometry, 0);
172
- apl.refine(refinement_spec);
173
-
174
160
  // build up occurances
175
161
  const output_patches = output.patches;
176
- let output_patch_cursor = output.patch_count;
177
- let patch_instance;
178
-
179
- const geometry_id = geometry.id;
180
162
 
181
- for (
182
- let record = apl.records;
183
- record !== null;
184
- record = record.link_next
185
- ) {
186
-
187
- if (!record.getFlag(ActivePatchFlags.Visible)) {
188
- // patch is not visible, skip
189
- continue;
190
- }
163
+ const added_patch_count = get_geometry_patch_cut(
164
+ output_patches,
165
+ output.patch_count,
166
+ refinement_spec,
167
+ geometry,
168
+ instance_id,
169
+ transform
170
+ );
191
171
 
192
- const patch = record.patch;
193
- patch_instance = output_patches[output_patch_cursor];
194
-
195
- if (patch_instance === undefined) {
196
- // no instance available for reuse - create a new one
197
- patch_instance = new MicronGeometryPatchOccurrence();
198
- output_patches[output_patch_cursor] = patch_instance;
199
- }
200
-
201
- patch_instance.instance_id = instance_id;
202
- patch_instance.geometry_id = geometry_id;
203
- patch_instance.patch = patch;
204
- patch_instance.transform = transform;
205
-
206
- output_patch_cursor++;
207
- }
208
-
209
- output.patch_count = output_patch_cursor;
210
-
211
-
212
- // TODO sort patches based on camera distance to better utilize z-culling in hardware
172
+ output.patch_count += added_patch_count;
213
173
  }
214
174
 
215
175
  clearScene() {
@@ -243,10 +203,11 @@ export class VirtualGeometryBuilder {
243
203
  const n = this.input_scene_length;
244
204
  const input_objects = this.input_scene;
245
205
 
206
+
246
207
  for (let i = 0; i < n; i++) {
247
208
  const object3D = input_objects[i];
248
209
 
249
- this.buildForObject(object3D);
210
+ traverseThreeObject(object3D, this.buildForObject, this);
250
211
  }
251
212
 
252
213
 
@@ -50,17 +50,6 @@ export class RefinementSpec {
50
50
  * @type {Float32Array}
51
51
  */
52
52
  this.frustum_f32 = new Float32Array(array_buffer, 64, 24);
53
-
54
-
55
- /**
56
- * Object-space camera position
57
- * @type {Float32Array}
58
- */
59
- this.view_position = new Float32Array(3);
60
- }
61
-
62
- get frustum() {
63
- throw new Error('deprecated, use .frustum_f32 instead');
64
53
  }
65
54
 
66
55
  /**