@woosh/meep-engine 2.34.49 → 2.35.2

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 (57) hide show
  1. package/core/bvh2/BinaryNode.js +19 -35
  2. package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +5 -5
  3. package/core/bvh2/aabb3/aabb3_intersects_frustum_degree.js +6 -6
  4. package/core/bvh2/aabb3_combined_surface_area.js +21 -0
  5. package/core/bvh2/traversal/queryBinaryNode_CollectData.js +1 -2
  6. package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +42 -17
  7. package/core/cache/Cache.d.ts +2 -0
  8. package/core/cache/Cache.js +27 -23
  9. package/core/collection/HashMap.js +1 -1
  10. package/core/geom/3d/frustum/frustum_from_projection_matrix_array.js +2 -0
  11. package/core/math/max2.js +2 -6
  12. package/core/math/min2.js +2 -6
  13. package/engine/asset/loaders/geometry/geometry/computeGeometryEquality.js +1 -1
  14. package/engine/asset/loaders/geometry/geometry/computeGeometryHash.js +9 -1
  15. package/engine/ecs/EntityComponentDataset.js +7 -2
  16. package/engine/ecs/foliage/ViewState.js +13 -3
  17. package/engine/ecs/parent/EntityNode.js +23 -11
  18. package/engine/ecs/transform/Transform.js +15 -13
  19. package/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.js +13 -4
  20. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +46 -108
  21. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +72 -10
  22. package/engine/graphics/ecs/mesh-v2/build_three_object.js +39 -0
  23. package/engine/graphics/ecs/mesh-v2/render/AbstractRenderAdapter.js +67 -0
  24. package/engine/graphics/ecs/mesh-v2/render/GenericRendererAdapter.js +48 -0
  25. package/engine/graphics/ecs/mesh-v2/render/InstancedRendererAdapter.js +158 -0
  26. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +98 -0
  27. package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +5 -0
  28. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +37 -10
  29. package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +8 -3
  30. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +29 -82
  31. package/engine/graphics/geometry/instancing/rewriteMaterial.js +9 -45
  32. package/engine/graphics/material/optimization/BUFFER_GEOMETRY_UVS.js +10 -0
  33. package/engine/graphics/material/optimization/MaterialDescriptor.js +46 -0
  34. package/engine/graphics/material/optimization/MaterialOptimizationContext.js +470 -201
  35. package/engine/graphics/material/optimization/UvContext.js +18 -0
  36. package/engine/graphics/material/optimization/is_compliant_mesh.js +71 -0
  37. package/engine/graphics/material/optimization/prepare_atlas_texture.js +23 -0
  38. package/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +127 -0
  39. package/engine/graphics/micron/format/MicronGeometryPatch.js +1 -1
  40. package/engine/graphics/micron/format/VirtualGeometry.js +47 -11
  41. package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +16 -0
  42. package/engine/graphics/micron/prototypeVirtualGeometry.js +3 -2
  43. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +5 -7
  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 -1
  47. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +17 -24
  48. package/engine/graphics/micron/render/v1/MaterialContext.js +3 -2
  49. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +20 -4
  50. package/engine/graphics/render/utils/ThreeBypassRenderer.js +3 -2
  51. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
  52. package/engine/graphics/texture/normalized_internal_format.js +48 -0
  53. package/engine/graphics/texture/sampler/Sampler2D.js +6 -0
  54. package/engine/graphics/texture/sampler/sampler2d_copy_channel_data.js +25 -0
  55. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -0
  56. package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +14 -1
  57. package/package.json +1 -1
@@ -0,0 +1,158 @@
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
+ import { DrawMode } from "../DrawMode.js";
6
+
7
+ const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
8
+ | ShadedGeometryFlags.ReceiveShadow
9
+ ;
10
+
11
+ /**
12
+ *
13
+ * @param {ShadedGeometry} a
14
+ * @param {ShadedGeometry} b
15
+ * @returns {number}
16
+ */
17
+ function compare(a, b) {
18
+ const d_geometry = a.geometry.id - b.geometry.id;
19
+ if (d_geometry !== 0) {
20
+ return d_geometry;
21
+ }
22
+
23
+ const d_material = a.material.id - b.material.id;
24
+ if (d_material !== 0) {
25
+ return d_material;
26
+ }
27
+
28
+ const d_flags = (a.flags & INSTANCED_EQUALITY_FLAGS) - (b.flags & INSTANCED_EQUALITY_FLAGS);
29
+ if (d_flags !== 0) {
30
+ return d_flags;
31
+ }
32
+
33
+ const d_mode = a.mode - b.mode;
34
+ if (d_mode !== 0) {
35
+ return d_mode;
36
+ }
37
+
38
+ return 0;
39
+ }
40
+
41
+ export class InstancedRendererAdapter extends AbstractRenderAdapter {
42
+ constructor() {
43
+ super();
44
+
45
+ /**
46
+ *
47
+ * @type {HashMap<ShadedGeometry, InstancedMeshGroup>}
48
+ * @private
49
+ */
50
+ this.__instanced_meshes = new HashMap({
51
+ keyHashFunction(sg) {
52
+ return sg.geometry.id ^ sg.material.id ^ sg.mode;
53
+ },
54
+ keyEqualityFunction(a, b) {
55
+ return a.material.id === b.material.id
56
+ && a.geometry.id === b.geometry.id
57
+ && a.mode === b.mode
58
+ && (a.flags & INSTANCED_EQUALITY_FLAGS) === (b.flags & INSTANCED_EQUALITY_FLAGS)
59
+ ;
60
+ }
61
+ });
62
+
63
+ /**
64
+ *
65
+ * @type {Set<InstancedMeshGroup>}
66
+ * @private
67
+ */
68
+ this.__active_meshes = new Set();
69
+ }
70
+
71
+ /**
72
+ *
73
+ * @param {ShadedGeometry} sg
74
+ * @returns {InstancedMeshGroup}
75
+ * @private
76
+ */
77
+ __get_instanced_mesh(sg) {
78
+ let im = this.__instanced_meshes.get(sg);
79
+
80
+
81
+ if (im !== undefined) {
82
+
83
+ return im;
84
+
85
+ } else {
86
+
87
+ if (sg.mode !== DrawMode.Triangles) {
88
+ throw new Error(`Unsupported draw mode ${sg.mode}`);
89
+ }
90
+
91
+ im = new InstancedMeshGroup();
92
+ im.shrinkFactor = 0; // prevent shrinking as we're essentially rebuilding this geometry frame
93
+
94
+ im.setMaterial(sg.material);
95
+ im.setGeometry(sg.geometry);
96
+
97
+ im.mesh.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
98
+ im.mesh.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
99
+
100
+ this.__instanced_meshes.set(sg, im);
101
+
102
+ return im;
103
+
104
+ }
105
+ }
106
+
107
+ add(sg) {
108
+ const mesh = this.__get_instanced_mesh(sg);
109
+
110
+ const index = mesh.count;
111
+
112
+ const new_size = index + 1;
113
+
114
+ if (new_size > mesh.capacity) {
115
+ mesh.ensureCapacity(new_size);
116
+ }
117
+
118
+ mesh.setTransformAt(index, sg.transform);
119
+
120
+ mesh.count++;
121
+
122
+ this.__active_meshes.add(mesh);
123
+ }
124
+
125
+ build_start() {
126
+ this.clear();
127
+ }
128
+
129
+ build_end() {
130
+ const objects = this.__objects;
131
+
132
+ for (const activeMesh of this.__active_meshes) {
133
+ // force underlying geometry to update
134
+ activeMesh.setCount(activeMesh.getCount());
135
+ activeMesh.requestAttributeUpdate();
136
+
137
+ objects[this.__object_count++] = activeMesh.mesh;
138
+ }
139
+
140
+ }
141
+
142
+ clear() {
143
+ super.clear();
144
+
145
+ for (const activeMesh of this.__active_meshes) {
146
+ activeMesh.setCount(0);
147
+ }
148
+
149
+ this.__active_meshes.clear();
150
+ }
151
+
152
+ dispose() {
153
+ // release GPU memory
154
+ this.__instanced_meshes.forEach((value, key) => {
155
+ value.dispose();
156
+ });
157
+ }
158
+ }
@@ -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
+ }
@@ -6,6 +6,7 @@ import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
6
6
  import { three_object_to_entity_composition } from "../three_object_to_entity_composition.js";
7
7
  import { AttachmentSystem } from "../../../../ecs/attachment/AttachmentSystem.js";
8
8
  import { TransformAttachmentSystem } from "../../../../ecs/transform-attachment/TransformAttachmentSystem.js";
9
+ import { Camera } from "../../camera/Camera.js";
9
10
 
10
11
  const eh = new EngineHarness();
11
12
 
@@ -70,6 +71,10 @@ async function main(engine) {
70
71
  enableTerrain: false
71
72
  });
72
73
 
74
+ const camera = engine.entityManager.dataset.getAnyComponent(Camera);
75
+ camera.component.autoClip = false;
76
+ camera.component.object.far = 300;
77
+
73
78
  // a small delay to let background tasks finish, so we can get better performance reading later on
74
79
  timeout(20);
75
80
 
@@ -3,7 +3,7 @@ import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
3
3
  import EntityBuilder from "../../../../ecs/EntityBuilder.js";
4
4
  import { Transform } from "../../../../ecs/transform/Transform.js";
5
5
  import { ShadedGeometry } from "../ShadedGeometry.js";
6
- import { BoxBufferGeometry, MeshBasicMaterial } from "three";
6
+ import { BoxBufferGeometry, MeshStandardMaterial } from "three";
7
7
  import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
8
8
  import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
9
9
  import ViewportPosition from "../../../../ecs/gui/position/ViewportPosition.js";
@@ -13,9 +13,16 @@ import { downloadAsFile } from "../../../../../core/binary/ByteArrayTools.js";
13
13
  import { convert_bvh_to_dot_format_string } from "../../../../../core/bvh2/visual/convert_bvh_to_dot_format_string.js";
14
14
  import ViewportPositionSystem from "../../../../ecs/gui/position/ViewportPositionSystem.js";
15
15
  import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
16
+ import Vector3 from "../../../../../core/geom/Vector3.js";
17
+ import Quaternion from "../../../../../core/geom/Quaternion.js";
18
+ import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
19
+ import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
16
20
 
17
21
  const eh = new EngineHarness();
18
22
 
23
+ const DRAW_METHOD_PLAIN = 0;
24
+ const DRAW_METHOD_INSTANCED = 1;
25
+
19
26
  /**
20
27
  *
21
28
  * @param {Engine} engine
@@ -26,12 +33,18 @@ async function main(engine) {
26
33
 
27
34
  await em.addSystem(new ShadedGeometrySystem(engine));
28
35
 
29
- EngineHarness.buildBasics({ engine })
36
+ EngineHarness.buildBasics({
37
+ engine,
38
+ yaw: -0.8,
39
+ pitch: 1,
40
+ distance: 46,
41
+ focus: new Vector3(10, 0, 10)
42
+ });
30
43
 
31
44
 
32
45
  const ecd = em.dataset;
33
46
 
34
- const material = new MeshBasicMaterial({
47
+ const material = new MeshStandardMaterial({
35
48
  color: 0xFFFFFF
36
49
  });
37
50
 
@@ -39,22 +52,36 @@ async function main(engine) {
39
52
 
40
53
  window.material = material;
41
54
 
42
- const geometry = new BoxBufferGeometry();
43
-
44
55
  const random = seededRandom(0);
45
56
 
46
- for (let i = 0; i < 100000; i++) {
57
+ const INSTANCE_COUNT = 20000;
58
+
59
+ const geometries = [];
60
+
61
+ for (let i = 0; i < 1000; i++) {
62
+ geometries.push(new BoxBufferGeometry());
63
+ }
64
+
65
+ for (let i = 0; i < INSTANCE_COUNT; i++) {
66
+ const geometry = randomFromArray(random, geometries);
67
+ const sg = ShadedGeometry.from(geometry, material);
68
+
69
+ // sg.draw_method = DRAW_METHOD_PLAIN;
70
+ sg.draw_method = DRAW_METHOD_INSTANCED;
71
+ // sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
72
+ sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
47
73
 
48
74
  new EntityBuilder()
49
75
  .add(Transform.fromJSON({
50
76
  position: {
51
- x: randomFloatBetween(random, -50, 50),
77
+ x: randomFloatBetween(random, 0, 20),
52
78
  y: randomFloatBetween(random, 0, 10),
53
- z: randomFloatBetween(random, -50, 50)
79
+ z: randomFloatBetween(random, 0, 20)
54
80
  },
55
- scale: 0.01
81
+ rotation: Quaternion.random(random),
82
+ scale: 0.05
56
83
  }))
57
- .add(ShadedGeometry.from(geometry, material))
84
+ .add(sg)
58
85
  .build(ecd);
59
86
  }
60
87
 
@@ -12,24 +12,29 @@ export function three_object_to_entity_composition(root) {
12
12
 
13
13
  node.transform.fromMatrix4(root.matrix.elements);
14
14
 
15
- node.entity.add(new Transform());
15
+ const entity = node.entity;
16
+
17
+ entity.add(new Transform());
16
18
 
17
19
  if (root.isMesh) {
18
20
  if (root.isSkinnedMesh) {
19
21
  throw new Error(`Skinned meshes are not supported`);
20
22
  }
21
23
 
22
- node.entity.add(ShadedGeometry.from(root.geometry, root.material));
24
+ const sg = ShadedGeometry.from(root.geometry, root.material);
25
+ sg.draw_method = 1;
26
+
27
+ entity.add(sg);
23
28
  }
24
29
 
25
30
  const children = root.children;
26
31
  const child_count = children.length;
32
+
27
33
  for (let i = 0; i < child_count; i++) {
28
34
  const child = children[i];
29
35
 
30
36
  const child_node = three_object_to_entity_composition(child);
31
37
 
32
-
33
38
  node.addChild(child_node);
34
39
  }
35
40
 
@@ -3,13 +3,15 @@ import {
3
3
  InstancedBufferAttribute,
4
4
  InstancedBufferGeometry,
5
5
  MeshDepthMaterial,
6
- RGBADepthPacking
6
+ RGBADepthPacking,
7
+ StreamDrawUsage
7
8
  } from 'three';
8
9
  import ThreeFactory from "../../three/ThreeFactory.js";
9
10
  import { StaticMaterialCache } from "../../../asset/loaders/material/StaticMaterialCache.js";
10
11
  import { composeCompile } from "../../material/composeCompile.js";
11
12
  import { typed_array_copy } from "../../../../core/collection/array/typed/typed_array_copy.js";
12
13
  import { rewriteMaterial } from "./rewriteMaterial.js";
14
+ import { max3 } from "../../../../core/math/max3.js";
13
15
 
14
16
  export class InstancedMeshGroup {
15
17
  /**
@@ -66,21 +68,14 @@ export class InstancedMeshGroup {
66
68
  * @type {InstancedBufferAttribute}
67
69
  * @private
68
70
  */
69
- this.__attributePosition = null;
71
+ this.__attributeTransform = null;
70
72
 
71
73
  /**
72
- *
73
- * @type {InstancedBufferAttribute}
74
- * @private
75
- */
76
- this.__attributeRotation = null;
77
-
78
- /**
79
- *
80
- * @type {InstancedBufferAttribute}
74
+ * Shortcut to buffer attribute data
75
+ * @type {Float32Array}
81
76
  * @private
82
77
  */
83
- this.__attributeScale = null;
78
+ this.__attributeTransformArray = null;
84
79
 
85
80
  /**
86
81
  *
@@ -180,7 +175,7 @@ export class InstancedMeshGroup {
180
175
  if (currentCapacity < size) {
181
176
  // grow
182
177
 
183
- const newCapacityRaw = Math.max(
178
+ const newCapacityRaw = max3(
184
179
  size,
185
180
  currentCapacity * this.growFactor,
186
181
  currentCapacity + this.growConstant
@@ -203,39 +198,16 @@ export class InstancedMeshGroup {
203
198
  /**
204
199
  *
205
200
  * @param {number} index
206
- * @param {number} x
207
- * @param {number} y
208
- * @param {number} z
201
+ * @param {number[]|ArrayLike<number>|Float32Array} transform 4x4 transform matrix of the instance
209
202
  */
210
- setPositionAt(index, x, y, z) {
211
- this.__attributePosition.setXYZ(index, x, y, z);
212
- this.__attributePosition.needsUpdate = true;
203
+ setTransformAt(index, transform) {
204
+ this.__attributeTransformArray.set(transform, index * 16);
213
205
  }
214
206
 
215
- /**
216
- *
217
- * @param {number} index
218
- * @param {number} x
219
- * @param {number} y
220
- * @param {number} z
221
- * @param {number} w
222
- */
223
- setRotationAt(index, x, y, z, w) {
224
- this.__attributeRotation.setXYZW(index, x, y, z, w);
225
- this.__attributeRotation.needsUpdate = true;
207
+ requestAttributeUpdate() {
208
+ this.__attributeTransform.needsUpdate = true;
226
209
  }
227
210
 
228
- /**
229
- *
230
- * @param {number} index
231
- * @param {number} x
232
- * @param {number} y
233
- * @param {number} z
234
- */
235
- setScaleAt(index, x, y, z) {
236
- this.__attributeScale.setXYZ(index, x, y, z);
237
- this.__attributeScale.needsUpdate = true;
238
- }
239
211
 
240
212
  /**
241
213
  * Swap position in attribute arrays of two elements
@@ -327,25 +299,13 @@ export class InstancedMeshGroup {
327
299
  delete references[index];
328
300
  } else {
329
301
  //not at the end, move the very last reference to this place, effectively shrinking the set
330
- const index3 = index * 3;
331
- const start3 = lastIndex * 3;
332
- const end3 = start3 + 3;
333
302
 
334
- const index4 = index * 4;
335
- const start4 = lastIndex * 4;
336
- const end4 = start4 + 4;
337
303
 
338
- const a_position = this.__attributePosition;
339
- const a_rotation = this.__attributeRotation;
340
- const a_scale = this.__attributeScale;
304
+ const a_transform = this.__attributeTransform;
341
305
 
342
- a_position.array.copyWithin(index3, start3, end3);
343
- a_rotation.array.copyWithin(index4, start4, end4);
344
- a_scale.array.copyWithin(index3, start3, end3);
306
+ a_transform.array.copyWithin(index * 16, lastIndex * 16, lastIndex * 16 + 16);
307
+ a_transform.needsUpdate = true;
345
308
 
346
- a_position.needsUpdate = true;
347
- a_rotation.needsUpdate = true;
348
- a_scale.needsUpdate = true;
349
309
 
350
310
  //update moved reference index
351
311
  const movedReference = references[lastIndex];
@@ -391,39 +351,26 @@ export class InstancedMeshGroup {
391
351
  }
392
352
 
393
353
  //build instanced attributes
394
- const newPositionArray = new Float32Array(this.capacity * 3);
395
- const newRotationArray = new Float32Array(this.capacity * 4);
396
- const newScaleArray = new Float32Array(this.capacity * 3);
397
-
398
- if (this.__attributePosition !== null) {
399
- //copy old data
400
- const oldPositionArray = this.__attributePosition.array;
401
- typed_array_copy(oldPositionArray, newPositionArray);
402
- }
403
- if (this.__attributeRotation !== null) {
404
- //copy old data
405
- const oldRotationArray = this.__attributeRotation.array;
406
- typed_array_copy(oldRotationArray, newRotationArray);
407
- }
408
- if (this.__attributeScale !== null) {
409
- const oldScaleArray = this.__attributeScale.array;
410
- typed_array_copy(oldScaleArray, newScaleArray);
354
+ const newTransformArray = new Float32Array(this.capacity * 16);
355
+
356
+ if (this.__attributeTransform !== null) {
357
+ const oldTransformArray = this.__attributeTransform.array;
358
+ typed_array_copy(oldTransformArray, newTransformArray);
411
359
 
412
- if (newScaleArray.length > oldScaleArray.length) {
413
- //fill the rest of the array with scale factor of 1 as a default
414
- newScaleArray.fill(1, oldScaleArray.length);
360
+ if (newTransformArray.length > oldTransformArray.length) {
361
+ //fill the rest of the array with 0s
362
+ // TODO consider writing identity matrix instead
363
+ newTransformArray.fill(0, oldTransformArray.length);
415
364
  }
416
365
  }
417
366
 
418
367
  //rewrite old attributes
419
- this.__attributePosition = new InstancedBufferAttribute(newPositionArray, 3);
420
- this.__attributeRotation = new InstancedBufferAttribute(newRotationArray, 4);
421
- this.__attributeScale = new InstancedBufferAttribute(newScaleArray, 3);
368
+ this.__attributeTransformArray = newTransformArray;
369
+ this.__attributeTransform = new InstancedBufferAttribute(newTransformArray, 16);
370
+ this.__attributeTransform.setUsage(StreamDrawUsage);
422
371
 
423
372
  //add attributes to newly created geometry
424
- geometry.setAttribute("instancePosition", this.__attributePosition);
425
- geometry.setAttribute("instanceRotation", this.__attributeRotation);
426
- geometry.setAttribute("instanceScale", this.__attributeScale);
373
+ geometry.setAttribute("instanceMatrix", this.__attributeTransform);
427
374
 
428
375
 
429
376
  this.mesh.geometry = geometry;
@@ -1,55 +1,19 @@
1
1
  const SHADER_PREAMBLE = `
2
- attribute vec3 instancePosition;
3
- attribute vec4 instanceRotation;
4
- attribute vec3 instanceScale;
5
-
6
- vec3 instanceTransform( in vec3 position, vec3 T, vec4 R, vec3 S ){
7
- vec3 result = position;
8
-
9
- //applies the scale
10
- result *= S;
11
- //computes the rotation where R is a (vec4) quaternion
12
- result += 2.0 * cross( R.xyz, cross( R.xyz, result ) + R.w * result );
13
- //translates the transformed 'blueprint'
14
- result += T;
15
-
16
- return result;
17
- }
18
-
19
- mat4 getInstanceMatrix(){
20
- vec4 q = instanceRotation;
21
- vec3 s = instanceScale;
22
- vec3 v = instancePosition;
23
-
24
- vec3 q2 = q.xyz + q.xyz;
25
- vec3 a = q.xxx * q2.xyz;
26
- vec3 b = q.yyz * q2.yzz;
27
- vec3 c = q.www * q2.xyz;
28
-
29
- vec3 r0 = vec3( 1.0 - (b.x + b.z) , a.y + c.z , a.z - c.y ) * s.xxx;
30
- vec3 r1 = vec3( a.y - c.z , 1.0 - (a.x + b.z) , b.y + c.x ) * s.yyy;
31
- vec3 r2 = vec3( a.z + c.y , b.y - c.x , 1.0 - (a.x + b.x) ) * s.zzz;
32
-
33
- return mat4(
34
- r0 , 0.0,
35
- r1 , 0.0,
36
- r2 , 0.0,
37
- v , 1.0
38
- );
39
- }\n`;
2
+ attribute mat4 instanceMatrix;
3
+ \n`;
40
4
 
41
5
  export function rewriteMaterial(shader) {
42
6
  const originalVertexShader = shader.vertexShader;
43
7
 
44
8
  const newVertexShader = SHADER_PREAMBLE
45
9
  + originalVertexShader
46
- .replace(
47
- '#include <uv_vertex>',
48
- `
49
- mat4 instanceMatrix = getInstanceMatrix();
50
- #include <uv_vertex>
51
- `
52
- )
10
+ // .replace(
11
+ // '#include <uv_vertex>',
12
+ // `
13
+ // mat4 instanceMatrix = getInstanceMatrix();
14
+ // #include <uv_vertex>
15
+ // `
16
+ // )
53
17
  .replace(
54
18
  '#include <begin_vertex>',
55
19
  `
@@ -0,0 +1,10 @@
1
+ export const BUFFER_GEOMETRY_UVS = [
2
+ {
3
+ name: 'uv',
4
+ index: 0,
5
+ },
6
+ {
7
+ name: 'uv2',
8
+ index: 1
9
+ }
10
+ ];