@woosh/meep-engine 2.34.47 → 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.
Files changed (56) hide show
  1. package/core/binary/BitSet.js +10 -3
  2. package/core/bvh2/BinaryNode.js +19 -35
  3. package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +5 -5
  4. package/core/bvh2/aabb3_combined_surface_area.js +21 -0
  5. package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +24 -12
  6. package/core/cache/Cache.d.ts +2 -0
  7. package/core/cache/Cache.js +27 -23
  8. package/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +1 -1
  9. package/core/geom/3d/frustum/frustum_from_projection_matrix_array.js +29 -24
  10. package/core/math/max2.js +2 -6
  11. package/core/math/min2.js +2 -6
  12. package/engine/asset/loaders/geometry/geometry/computeGeometryEquality.js +3 -2
  13. package/engine/asset/loaders/geometry/geometry/computeGeometryHash.js +9 -1
  14. package/engine/ecs/EntityComponentDataset.js +7 -2
  15. package/engine/ecs/foliage/ViewState.js +13 -3
  16. package/engine/ecs/foliage/ecs/Foliage2System.js +15 -3
  17. package/engine/ecs/parent/EntityNode.js +23 -11
  18. package/engine/ecs/transform/Transform.js +15 -13
  19. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +63 -26
  20. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +63 -3
  21. package/engine/graphics/ecs/mesh-v2/render/AbstractRenderAdapter.js +67 -0
  22. package/engine/graphics/ecs/mesh-v2/render/GenericRendererAdapter.js +48 -0
  23. package/engine/graphics/ecs/mesh-v2/render/InstancedRendererAdapter.js +110 -0
  24. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +98 -0
  25. package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +5 -0
  26. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +23 -5
  27. package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +8 -3
  28. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +23 -85
  29. package/engine/graphics/geometry/instancing/rewriteMaterial.js +9 -45
  30. package/engine/graphics/material/optimization/BUFFER_GEOMETRY_UVS.js +10 -0
  31. package/engine/graphics/material/optimization/MaterialDescriptor.js +46 -0
  32. package/engine/graphics/material/optimization/MaterialOptimizationContext.js +470 -201
  33. package/engine/graphics/material/optimization/UvContext.js +18 -0
  34. package/engine/graphics/material/optimization/is_compliant_mesh.js +71 -0
  35. package/engine/graphics/material/optimization/prepare_atlas_texture.js +23 -0
  36. package/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +127 -0
  37. package/engine/graphics/micron/convert_three_object_to_micron.js +0 -2
  38. package/engine/graphics/micron/format/MicronGeometry.js +1 -3
  39. package/engine/graphics/micron/format/MicronGeometryPatch.js +34 -24
  40. package/engine/graphics/micron/format/VirtualGeometry.js +47 -11
  41. package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +22 -0
  42. package/engine/graphics/micron/prototypeVirtualGeometry.js +10 -5
  43. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +14 -55
  44. package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +1 -45
  45. package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +18 -7
  46. package/engine/graphics/micron/render/refinement/RefinementSpec.js +0 -12
  47. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +118 -0
  48. package/engine/graphics/micron/render/v1/MaterialContext.js +3 -2
  49. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +19 -4
  50. package/engine/graphics/render/utils/ThreeBypassRenderer.js +3 -2
  51. package/engine/graphics/texture/normalized_internal_format.js +48 -0
  52. package/engine/graphics/texture/sampler/Sampler2D.js +6 -0
  53. package/engine/graphics/texture/sampler/sampler2d_copy_channel_data.js +25 -0
  54. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -0
  55. package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +14 -1
  56. package/package.json +1 -1
@@ -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
- const t = this.__entity.getComponent(Transform);
50
- if (t !== null) {
51
- t.copy(this.__transform);
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(this.__transform);
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.immediate = true;
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 (!this.__entity.isBuilt) {
128
+ if (!this_entity.isBuilt) {
120
129
  return;
121
130
  }
122
131
 
123
- let parent_entity = this.__entity.removeComponent(ParentEntity);
124
- let attachment = this.__entity.removeComponent(TransformAttachment);
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
- this.__entity.add(parent_entity);
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 m4_0 = new Matrix4();
14
- const m4_1 = new Matrix4();
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.compose(a.position, a.rotation, a.scale);
156
- m4_1.compose(b.position, b.rotation, b.scale);
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
- m4_0.multiplyMatrices(m4_0, m4_1);
160
+ mat4.multiply(m4_0, m4_0, m4_1);
159
161
 
160
- m4_0.decompose(this.position, this.rotation, this.scale);
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 {mat4|number[]|Float32Array} m
175
+ * @param {Matrix4} matrix
174
176
  */
175
- fromMatrix4(m) {
176
- decompose_matrix_4_array(m, this.position, this.rotation, this.scale);
177
+ toThreeMatrix(matrix) {
178
+ this.toMatrix4(matrix.elements);
177
179
  }
178
180
 
179
181
  /**
180
182
  *
181
- * @param {Matrix4} matrix
183
+ * @param {mat4|number[]|Float32Array} m
182
184
  */
183
- toThreeMatrix(matrix) {
184
- this.toMatrix4(matrix.elements);
185
+ fromMatrix4(m) {
186
+ decompose_matrix_4_array(m, this.position, this.rotation, this.scale);
185
187
  }
186
188
 
187
189
  /**
@@ -12,6 +12,42 @@ const DEFAULT_FLAGS = ShadedGeometryFlags.CastShadow
12
12
  | ShadedGeometryFlags.ReceiveShadow
13
13
  ;
14
14
 
15
+ /**
16
+ *
17
+ * @param {ShadedGeometry} sg
18
+ * @returns {THREE.Object3D}
19
+ */
20
+ export function build_three_object(sg) {
21
+
22
+ /**
23
+ * @type {THREE.Object3D}
24
+ */
25
+ let object;
26
+
27
+ const mode = sg.mode;
28
+ const shader = sg.material;
29
+ const geo = sg.geometry;
30
+
31
+ if (mode === DrawMode.Triangles) {
32
+ object = new Mesh(geo, shader);
33
+ } else if (mode === DrawMode.Lines) {
34
+ object = new Line(geo, shader);
35
+ } else if (mode === DrawMode.LineSegments) {
36
+ object = new LineSegments(geo, shader);
37
+ } else {
38
+ throw new Error(`Unsupported draw mode '${mode}'`);
39
+ }
40
+
41
+ object.matrixAutoUpdate = false;
42
+ object.frustumCulled = false;
43
+ object.matrixWorldNeedsUpdate = false;
44
+
45
+ object.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
46
+ object.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
47
+
48
+ return object;
49
+ }
50
+
15
51
  export class ShadedGeometry {
16
52
  constructor() {
17
53
  /**
@@ -51,6 +87,7 @@ export class ShadedGeometry {
51
87
  * @private
52
88
  */
53
89
  this.__entity = -1;
90
+
54
91
  /**
55
92
  * Transform matrix
56
93
  * Transient, assigned in the system
@@ -59,6 +96,12 @@ export class ShadedGeometry {
59
96
  */
60
97
  this.__transform = null;
61
98
 
99
+ /**
100
+ * Transient property signifying how to render object
101
+ * @type {number}
102
+ */
103
+ this.draw_method = 0;
104
+
62
105
  /**
63
106
  *
64
107
  * @type {number}
@@ -106,6 +149,25 @@ export class ShadedGeometry {
106
149
  return (this.flags & flag) === flag;
107
150
  }
108
151
 
152
+ /**
153
+ *
154
+ * @return {number}
155
+ */
156
+ hash() {
157
+ return this.geometry.id ^ this.material.id;
158
+ }
159
+
160
+ /**
161
+ *
162
+ * @param {ShadedGeometry} other
163
+ * @returns {boolean}
164
+ */
165
+ equals(other) {
166
+ return this.geometry.id === other.geometry.id
167
+ && this.material.id === other.material.id
168
+ ;
169
+ }
170
+
109
171
  /**
110
172
  * Current cached entity that this component is attached to
111
173
  * @return {number}
@@ -130,32 +192,7 @@ export class ShadedGeometry {
130
192
  }
131
193
 
132
194
  __build_object() {
133
- /**
134
- * @type {THREE.Object3D}
135
- */
136
- let object;
137
-
138
- const mode = this.mode;
139
- const shader = this.material;
140
- const geo = this.geometry;
141
-
142
- if (mode === DrawMode.Triangles) {
143
- object = new Mesh(geo, shader);
144
- } else if (mode === DrawMode.Lines) {
145
- object = new Line(geo, shader);
146
- } else if (mode === DrawMode.LineSegments) {
147
- object = new LineSegments(geo, shader);
148
- } else {
149
- throw new Error(`Unsupported draw mode '${mode}'`);
150
- }
151
-
152
- object.matrixAutoUpdate = false;
153
- object.frustumCulled = false;
154
-
155
- object.castShadow = this.getFlag(ShadedGeometryFlags.CastShadow);
156
- object.receiveShadow = this.getFlag(ShadedGeometryFlags.ReceiveShadow);
157
-
158
- this.__cached_object = object;
195
+ this.__cached_object = build_three_object(this);
159
196
  }
160
197
 
161
198
  get bvh() {
@@ -7,6 +7,8 @@ import { v3_distance_sqr } from "../../../../core/geom/v3_distance_sqr.js";
7
7
  import { mat4 } from "gl-matrix";
8
8
  import { returnTrue } from "../../../../core/function/Functions.js";
9
9
  import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
10
+ import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererContext.js";
11
+ import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
10
12
 
11
13
  /**
12
14
  *
@@ -54,14 +56,72 @@ export class ShadedGeometrySystem extends System {
54
56
  * @private
55
57
  */
56
58
  this.__render_layer = null;
59
+
60
+ /**
61
+ *
62
+ * @type {Map<CameraView, ShadedGeometryRendererContext>}
63
+ * @private
64
+ */
65
+ this.__view_contexts = new Map();
66
+
67
+ this.__bvh = new BinaryNode();
68
+ this.__bvh.setNegativelyInfiniteBounds();
69
+ }
70
+
71
+ /**
72
+ *
73
+ * @param {CameraView} view
74
+ * @private
75
+ */
76
+ __handle_view_added(view) {
77
+ this.__view_contexts.set(view, new ShadedGeometryRendererContext());
78
+ }
79
+
80
+ /**
81
+ *
82
+ * @param {CameraView} view
83
+ * @private
84
+ */
85
+ __handle_view_removed(view) {
86
+ const ctx = this.__view_contexts.get(view);
87
+
88
+ this.__view_contexts.delete(view);
89
+
90
+ ctx.dispose();
57
91
  }
58
92
 
59
93
  async startup(entityManager, readyCallback, errorCallback) {
60
94
 
61
95
  const engine = this.__engine;
96
+ const graphics = engine.graphics;
97
+
98
+ const view_list = graphics.views.elements;
99
+
100
+ view_list.forEach(this.__handle_view_added, this);
101
+ view_list.on.added.add(this.__handle_view_added, this);
102
+ view_list.on.removed.add(this.__handle_view_removed, this);
103
+
104
+ this.__render_layer = graphics.layers.create('shaded-geometry');
105
+
106
+ this.__render_layer.buildVisibleSet = ((destination, destination_offset, view) => {
107
+ const ctx = this.__view_contexts.get(view);
108
+
109
+ return ctx.collect(destination, destination_offset, view, this.__bvh);
110
+ });
111
+
112
+ readyCallback();
113
+ }
114
+
115
+ async shutdown(entityManager, readyCallback, errorCallback) {
116
+
117
+ const engine = this.__engine;
118
+ const graphics = engine.graphics;
119
+
120
+ const view_list = graphics.views.elements;
62
121
 
63
- this.__render_layer = engine.graphics.layers.create('shaded-geometry');
64
- this.__render_layer.extractRenderable = (sg) => sg.__cached_object;
122
+ view_list.forEach(this.__handle_view_removed, this);
123
+ view_list.on.added.remove(this.__handle_view_added, this);
124
+ view_list.on.removed.remove(this.__handle_view_removed, this);
65
125
 
66
126
  readyCallback();
67
127
  }
@@ -87,7 +147,7 @@ export class ShadedGeometrySystem extends System {
87
147
  // remember entity for lookups
88
148
  sg.__entity = entity;
89
149
 
90
- this.__render_layer.bvh.insertNode(leaf_node);
150
+ this.__bvh.insertNode(leaf_node);
91
151
  }
92
152
 
93
153
  /**
@@ -0,0 +1,67 @@
1
+ export class AbstractRenderAdapter {
2
+ constructor() {
3
+
4
+ /**
5
+ *
6
+ * @type {number}
7
+ * @protected
8
+ */
9
+ this.__object_count = 0;
10
+
11
+ /**
12
+ *
13
+ * @type {THREE.Object3D[]}
14
+ * @protected
15
+ */
16
+ this.__objects = [];
17
+ }
18
+
19
+ /**
20
+ *
21
+ * @param {THREE.BufferGeometry} geometry
22
+ * @param {THREE.Material} material
23
+ * @returns {number}
24
+ */
25
+ score(geometry, material) {
26
+ return 0;
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @param {ShadedGeometry} sg
32
+ * @returns {void}
33
+ */
34
+ add(sg) {
35
+ throw new Error('Not Implemented');
36
+ }
37
+
38
+ build_start() {
39
+
40
+ }
41
+
42
+ build_end() {
43
+
44
+ }
45
+
46
+ clear() {
47
+ this.__object_count = 0;
48
+ }
49
+
50
+ /**
51
+ * @returns {THREE.Object3D[]}
52
+ */
53
+ get objects() {
54
+ return this.__objects;
55
+ }
56
+
57
+ /**
58
+ * @returns {number}
59
+ */
60
+ get object_count() {
61
+ return this.__object_count;
62
+ }
63
+
64
+ dispose() {
65
+
66
+ }
67
+ }
@@ -0,0 +1,48 @@
1
+ import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
2
+ import { build_three_object } from "../ShadedGeometry.js";
3
+ import { array_copy } from "../../../../../core/collection/array/copyArray.js";
4
+
5
+ export class GenericRendererAdapter extends AbstractRenderAdapter {
6
+ constructor() {
7
+ super();
8
+
9
+ /**
10
+ *
11
+ * @type {Cache<ShadedGeometry, THREE.Object3D>}
12
+ * @private
13
+ */
14
+ this.__cache = new WeakMap();
15
+ }
16
+
17
+
18
+ score(geometry, material) {
19
+ return 0;
20
+ }
21
+
22
+ build_start() {
23
+ this.clear();
24
+ }
25
+
26
+ add(sg) {
27
+ const cache = this.__cache;
28
+
29
+ /**
30
+ *
31
+ * @type {THREE.Object3D}
32
+ */
33
+ let object = cache.get(sg);
34
+
35
+ if (object === undefined) {
36
+
37
+ object = build_three_object(sg);
38
+
39
+ cache.set(sg, object);
40
+
41
+ }
42
+
43
+ array_copy(sg.__transform, 0, object.matrixWorld.elements, 0, 16);
44
+
45
+ this.__objects[this.__object_count++] = object;
46
+ }
47
+
48
+ }
@@ -0,0 +1,110 @@
1
+ import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
2
+ import { HashMap } from "../../../../../core/collection/HashMap.js";
3
+ import { InstancedMeshGroup } from "../../../geometry/instancing/InstancedMeshGroup.js";
4
+ import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
5
+
6
+ const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
7
+ | ShadedGeometryFlags.ReceiveShadow
8
+ ;
9
+
10
+ export class InstancedRendererAdapter extends AbstractRenderAdapter {
11
+ constructor() {
12
+ super();
13
+
14
+ /**
15
+ *
16
+ * @type {HashMap<ShadedGeometry, InstancedMeshGroup>}
17
+ * @private
18
+ */
19
+ this.__instanced_meshes = new HashMap({
20
+ keyHashFunction(sg) {
21
+ return sg.geometry.id ^ sg.material.id;
22
+ },
23
+ keyEqualityFunction(a, b) {
24
+ return a.material.id === b.material.id
25
+ && a.geometry.id === b.geometry.id
26
+ && (a.flags & INSTANCED_EQUALITY_FLAGS) === (b.flags & INSTANCED_EQUALITY_FLAGS)
27
+ ;
28
+ }
29
+ });
30
+
31
+ /**
32
+ *
33
+ * @type {Set<InstancedMeshGroup>}
34
+ * @private
35
+ */
36
+ this.__active_meshes = new Set();
37
+ }
38
+
39
+ /**
40
+ *
41
+ * @param {ShadedGeometry} sg
42
+ * @returns {InstancedMeshGroup}
43
+ * @private
44
+ */
45
+ __get_instanced_mesh(sg) {
46
+ let im = this.__instanced_meshes.get(sg);
47
+
48
+ if (im === undefined) {
49
+ im = new InstancedMeshGroup();
50
+ im.shrinkFactor = 0; // prevent shrinking as we're essentially rebuilding this geometry frame
51
+
52
+ im.setMaterial(sg.material);
53
+ im.setGeometry(sg.geometry);
54
+
55
+ im.mesh.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
56
+ im.mesh.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
57
+
58
+ this.__instanced_meshes.set(sg, im);
59
+ }
60
+
61
+ return im;
62
+ }
63
+
64
+ add(sg) {
65
+ const mesh = this.__get_instanced_mesh(sg);
66
+
67
+ const index = mesh.count;
68
+
69
+ mesh.ensureCapacity(index + 1);
70
+
71
+ mesh.setTransformAt(index, sg.transform);
72
+
73
+ mesh.count++;
74
+
75
+ this.__active_meshes.add(mesh);
76
+ }
77
+
78
+ build_start() {
79
+ this.clear();
80
+ }
81
+
82
+ build_end() {
83
+
84
+ for (const activeMesh of this.__active_meshes) {
85
+ // force underlying geometry to update
86
+ activeMesh.setCount(activeMesh.getCount());
87
+ activeMesh.requestAttributeUpdate();
88
+
89
+ this.__objects[this.__object_count++] = activeMesh.mesh;
90
+ }
91
+
92
+ }
93
+
94
+ clear() {
95
+ super.clear();
96
+
97
+ for (const activeMesh of this.__active_meshes) {
98
+ activeMesh.setCount(0);
99
+ }
100
+
101
+ this.__active_meshes.clear();
102
+ }
103
+
104
+ dispose() {
105
+ // release GPU memory
106
+ this.__instanced_meshes.forEach((value, key) => {
107
+ value.dispose();
108
+ });
109
+ }
110
+ }
@@ -0,0 +1,98 @@
1
+ import { queryBinaryNode_FrustumIntersections_Data } from "../../../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
2
+ import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
3
+ import { InstancedRendererAdapter } from "./InstancedRendererAdapter.js";
4
+ import { GenericRendererAdapter } from "./GenericRendererAdapter.js";
5
+
6
+ /**
7
+ * 1 - collect visible meshes
8
+ * 2 - figure out how to render a given mesh
9
+ */
10
+ export class ShadedGeometryRendererContext {
11
+ constructor() {
12
+ /**
13
+ * @readonly
14
+ * @type {AbstractRenderAdapter[]}
15
+ */
16
+ this.adapters = [
17
+ new GenericRendererAdapter(),
18
+ new InstancedRendererAdapter()
19
+ ];
20
+ }
21
+
22
+ setAdapter(index, adapter) {
23
+ const existing = this.adapters[index];
24
+ if (existing !== undefined) {
25
+ // dispose of existing adapter
26
+ existing.dispose();
27
+ }
28
+
29
+ this.adapters[index] = adapter;
30
+ }
31
+
32
+ /**
33
+ *
34
+ * @param {THREE.Object3D[]} destination
35
+ * @param {number} destination_offset
36
+ * @param {CameraView} view
37
+ * @param {BinaryNode<ShadedGeometry>} bvh
38
+ */
39
+ collect(destination, destination_offset, view, bvh) {
40
+ const adapters = this.adapters;
41
+ const adapter_count = adapters.length;
42
+
43
+ let i = 0, j = 0;
44
+ for (; i < adapter_count; i++) {
45
+ const adapter = adapters[i];
46
+
47
+ adapter.build_start();
48
+ }
49
+
50
+
51
+ // get all meshes
52
+
53
+ const data = [];
54
+
55
+ const intersection_count = queryBinaryNode_FrustumIntersections_Data(data, 0, bvh, view.frustum);
56
+
57
+ for (i = 0; i < intersection_count; i++) {
58
+ /**
59
+ *
60
+ * @type {ShadedGeometry}
61
+ */
62
+ const sg = data[i];
63
+
64
+ const adapter = adapters[sg.draw_method];
65
+
66
+ adapter.add(sg);
67
+ }
68
+
69
+ let additions = 0;
70
+
71
+ for (i = 0; i < adapter_count; i++) {
72
+ const adapter = adapters[i];
73
+
74
+ adapter.build_end();
75
+
76
+ const adapter_object_count = adapter.object_count;
77
+
78
+ for (j = 0; j < adapter_object_count; j++) {
79
+ const object3D = adapter.objects[j];
80
+
81
+ destination[destination_offset + additions] = object3D;
82
+
83
+ additions++;
84
+ }
85
+
86
+ }
87
+
88
+ return additions;
89
+ }
90
+
91
+ dispose() {
92
+ for (const adapter of this.adapters) {
93
+ if (adapter !== undefined) {
94
+ adapter.dispose();
95
+ }
96
+ }
97
+ }
98
+ }