@woosh/meep-engine 2.33.59 → 2.33.60

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 (39) hide show
  1. package/core/bvh2/aabb3/AABB3.js +4 -1
  2. package/core/bvh2/traversal/traverseBinaryNodeUsingVisitor.js +6 -6
  3. package/core/cache/Cache.js +7 -0
  4. package/core/collection/array/fastArrayEquals.js +17 -0
  5. package/core/collection/array/typed/is_typed_array_equals.js +58 -0
  6. package/core/collection/map/AbstractAsyncMap.js +30 -0
  7. package/core/collection/map/AsyncMapWrapper.js +16 -0
  8. package/core/collection/map/AsyncRemoteHashMap.js +358 -0
  9. package/core/collection/map/CachedAsyncMap.js +34 -0
  10. package/core/geom/Vector4.js +5 -5
  11. package/engine/animation/removeEntityGenericEffect.js +22 -31
  12. package/engine/asset/Asset.js +0 -45
  13. package/engine/asset/AssetDescription.js +51 -0
  14. package/engine/asset/AssetManager.d.ts +7 -0
  15. package/engine/asset/AssetManager.js +98 -2
  16. package/engine/asset/AssetTransformer.d.ts +5 -0
  17. package/engine/asset/AssetTransformer.js +15 -0
  18. package/engine/asset/loaders/GLTFAssetLoader.js +27 -25
  19. package/engine/asset/loaders/material/computeImageBitmapEquality.js +2 -2
  20. package/engine/asset/loaders/material/computeTextureEquality.js +2 -2
  21. package/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +60 -45
  22. package/engine/ecs/storage/binary/BinaryClassUpgrader.js +1 -0
  23. package/engine/ecs/util/removeComponentsExcept.js +3 -3
  24. package/engine/graphics/GraphicsEngine.js +3 -3
  25. package/engine/graphics/ecs/mesh/Mesh.js +5 -5
  26. package/engine/graphics/ecs/mesh/MeshSystem.js +12 -20
  27. package/engine/graphics/ecs/trail2d/Trail2D.js +35 -1
  28. package/engine/graphics/ecs/trail2d/Trail2DSystem.js +26 -19
  29. package/engine/graphics/ecs/trail2d/makeGradientTrail.js +68 -0
  30. package/engine/graphics/micron/convert_three_object_to_micron.js +24 -7
  31. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +107 -4
  32. package/engine/graphics/micron/plugin/serialization/BufferGeometrySerializationAdapter.js +176 -0
  33. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -2
  34. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +3 -1
  35. package/engine/graphics/shadows/ShadowMapRenderer.js +10 -4
  36. package/engine/graphics/texture/sampler/Sampler2D.js +24 -45
  37. package/engine/intelligence/behavior/ecs/WaitForEventBehavior.js +3 -0
  38. package/engine/save/storage/IndexedDBStorage.js +8 -1
  39. package/package.json +1 -1
@@ -18,7 +18,6 @@ import Mesh, { MeshFlags } from "./Mesh.js";
18
18
  import { applyComponentPropertiesToThreeObject, setMesh } from "./setMesh.js";
19
19
  import { GLTFAssetLoader } from "../../../asset/loaders/GLTFAssetLoader.js";
20
20
  import { MeshEvents } from "./MeshEvents.js";
21
- import { MicronRenderPlugin } from "../../micron/plugin/MicronRenderPlugin.js";
22
21
  import { assert } from "../../../../core/assert.js";
23
22
 
24
23
  const placeholderGeometry = new BoxBufferGeometry(1, 1, 1);
@@ -86,13 +85,6 @@ export class MeshSystem extends System {
86
85
  * @type {BinaryNode}
87
86
  */
88
87
  this.bvh = null;
89
-
90
- /**
91
- *
92
- * @type {boolean}
93
- * @private
94
- */
95
- this.__use_micron = false;
96
88
  }
97
89
 
98
90
  /**
@@ -126,11 +118,11 @@ export class MeshSystem extends System {
126
118
 
127
119
  component.setFlag(MeshFlags.Loaded);
128
120
 
129
- // micron
130
- if (asset.micron !== undefined && this.__use_micron) {
131
- component.micron_mesh = asset.micron.clone();
121
+ // override
122
+ if (asset.override_mesh !== undefined ) {
123
+ component.override_mesh = asset.override_mesh.clone();
132
124
 
133
- applyComponentPropertiesToThreeObject(component, component.micron_mesh, entity);
125
+ applyComponentPropertiesToThreeObject(component, component.override_mesh, entity);
134
126
  }
135
127
 
136
128
  setMesh(dataset, entity, component, mesh);
@@ -141,11 +133,6 @@ export class MeshSystem extends System {
141
133
  }
142
134
 
143
135
  async startup(entityManager, readyCallback, errorCallback) {
144
- const engine = this.__engine;
145
-
146
- // is micron supported here?
147
- this.__use_micron = engine.plugins.getPlugin(MicronRenderPlugin) !== undefined;
148
-
149
136
  const am = this.assetManager;
150
137
 
151
138
  this.entityManager = entityManager;
@@ -158,10 +145,15 @@ export class MeshSystem extends System {
158
145
  const graphics = this.graphics;
159
146
  this.renderLayer = graphics.layers.create("mesh-system");
160
147
 
148
+ /**
149
+ *
150
+ * @param {Mesh} component
151
+ * @return {Object3D}
152
+ */
161
153
  const extractRenderable = (component) => {
162
- if (this.__use_micron && component.micron_mesh !== null) {
163
- // use micron mesh
164
- return component.micron_mesh;
154
+ if (component.override_mesh !== null) {
155
+ // use override mesh
156
+ return component.override_mesh;
165
157
  } else {
166
158
  // use standard mesh
167
159
  return component.mesh;
@@ -6,6 +6,10 @@
6
6
  import Vector3 from "../../../../core/geom/Vector3.js";
7
7
  import Vector4 from "../../../../core/geom/Vector4.js";
8
8
  import { RibbonXMaterialSpec } from "../../trail/x/RibbonXMaterialSpec.js";
9
+ import { LeafNode } from "../../../../core/bvh2/LeafNode.js";
10
+ import { makeGradientTrail } from "./makeGradientTrail.js";
11
+ import { RibbonX } from "../../trail/x/RibbonX.js";
12
+ import ThreeFactory from "../../three/ThreeFactory.js";
9
13
 
10
14
  /**
11
15
  * @readonly
@@ -14,6 +18,7 @@ import { RibbonXMaterialSpec } from "../../trail/x/RibbonXMaterialSpec.js";
14
18
  export const Trail2DFlags = {
15
19
  Spawning: 1,
16
20
  Aging: 2,
21
+ Built: 4,
17
22
  };
18
23
 
19
24
  class Trail2D {
@@ -37,6 +42,12 @@ class Trail2D {
37
42
  */
38
43
  this.time = 0;
39
44
 
45
+ /**
46
+ *
47
+ * @type {number}
48
+ */
49
+ this.trailingIndex = 0;
50
+
40
51
  /**
41
52
  * Time elapsed since last update
42
53
  * @type {number}
@@ -72,7 +83,11 @@ class Trail2D {
72
83
  * transient
73
84
  * @type {LeafNode|null}
74
85
  */
75
- this.bvhLeaf = null;
86
+ this.bvhLeaf = new LeafNode(
87
+ this,
88
+ 0, 0, 0,
89
+ 0, 0, 0
90
+ );
76
91
 
77
92
  /**
78
93
  * @private
@@ -165,6 +180,21 @@ class Trail2D {
165
180
  }
166
181
  }
167
182
 
183
+ build(segment_count) {
184
+
185
+ const ribbon = new RibbonX();
186
+
187
+ ribbon.buildGeometry();
188
+ ribbon.setCount(segment_count);
189
+
190
+ const geometry = ribbon.getGeometry();
191
+
192
+ const mesh = ThreeFactory.createMesh(geometry, null);
193
+
194
+ this.ribbon = ribbon;
195
+ this.mesh = mesh;
196
+ }
197
+
168
198
  toJSON() {
169
199
  return {
170
200
  maxAge: this.maxAge,
@@ -187,10 +217,14 @@ class Trail2D {
187
217
  && this.offset.equals(other.offset)
188
218
  ;
189
219
  }
220
+
221
+
190
222
  }
191
223
 
192
224
  Trail2D.typeName = "Trail2D";
193
225
 
194
226
  Trail2D.serializable = false;
195
227
 
228
+ Trail2D.makeGradientTrail = makeGradientTrail;
229
+
196
230
  export default Trail2D;
@@ -10,9 +10,6 @@ import { Transform } from '../../../ecs/transform/Transform.js';
10
10
  import Vector3 from '../../../../core/geom/Vector3.js';
11
11
 
12
12
  import Trail2D, { Trail2DFlags } from './Trail2D.js';
13
-
14
- import { LeafNode } from '../../../../core/bvh2/LeafNode.js';
15
- import ThreeFactory from '../../three/ThreeFactory.js';
16
13
  import { GraphicsEngine } from "../../GraphicsEngine.js";
17
14
  import { RibbonXFixedPhysicsSimulator } from "../../trail/x/simulator/RibbonXFixedPhysicsSimulator.js";
18
15
  import { RibbonX } from "../../trail/x/RibbonX.js";
@@ -118,11 +115,11 @@ class Trail2DSystem extends System {
118
115
 
119
116
  /**
120
117
  *
121
- * @param {Transform} transform
122
118
  * @param {Trail2D} trail
123
- * @param {number} entityId
119
+ * @param {Transform} transform
120
+ * @private
124
121
  */
125
- link(trail, transform, entityId) {
122
+ __build_trail(trail, transform) {
126
123
  const segmentsPerSecond = 60;
127
124
  const maxSegments = 1000;
128
125
  //instantiation
@@ -130,24 +127,19 @@ class Trail2DSystem extends System {
130
127
  //make a mesh
131
128
  const segment_count = Math.ceil(clamp(trail.maxAge * segmentsPerSecond, 2, maxSegments));
132
129
 
133
- const ribbon = new RibbonX();
134
-
135
- ribbon.buildGeometry();
136
- ribbon.setCount(segment_count);
130
+ trail.build(segment_count);
137
131
 
138
-
139
- const geometry = ribbon.getGeometry();
132
+ const ribbon = trail.ribbon;
140
133
 
141
134
  const ribbons = this.__ribbon_plugin.getValue();
142
135
 
143
136
  const material = ribbons.obtain_material_x(trail.material);
144
137
 
145
- const mesh = ThreeFactory.createMesh(geometry, material);
138
+ trail.mesh.material = material;
146
139
 
147
140
  trail.time = 0;
148
141
  trail.trailingIndex = 0;
149
142
  trail.ribbon = ribbon;
150
- trail.mesh = mesh;
151
143
  trail.timeSinceLastUpdate = 0;
152
144
 
153
145
 
@@ -173,16 +165,31 @@ class Trail2DSystem extends System {
173
165
 
174
166
  }
175
167
 
176
- const leafNode = new LeafNode(
177
- trail,
178
-
168
+ trail.bvhLeaf.resize(
179
169
  position_x, position_y, position_z,
180
170
  position_x, position_y, position_z
181
171
  );
182
172
 
183
- trail.bvhLeaf = leafNode;
173
+ trail.setFlag(Trail2DFlags.Built);
174
+ }
175
+
176
+ /**
177
+ *
178
+ * @param {Transform} transform
179
+ * @param {Trail2D} trail
180
+ * @param {number} entityId
181
+ */
182
+ link(trail, transform, entityId) {
183
+ if (!trail.getFlag(Trail2DFlags.Built)) {
184
+ this.__build_trail(trail, transform);
185
+ } else {
186
+
187
+ const material = this.__ribbon_plugin.getValue().obtain_material_x(trail.material);
188
+ trail.mesh.material = material;
189
+ }
190
+
184
191
 
185
- this.bvh.insertNode(leafNode);
192
+ this.bvh.insertNode(trail.bvhLeaf);
186
193
  }
187
194
 
188
195
  /**
@@ -0,0 +1,68 @@
1
+ import Trail2D, { Trail2DFlags } from "./Trail2D.js";
2
+ import {
3
+ RIBBON_ATTRIBUTE_ADDRESS_AGE,
4
+ RIBBON_ATTRIBUTE_ADDRESS_COLOR,
5
+ RIBBON_ATTRIBUTE_ADDRESS_THICKNESS,
6
+ RIBBON_ATTRIBUTE_ADDRESS_UV_OFFSET
7
+ } from "../../trail/x/ribbon_attributes_spec.js";
8
+ import { assert } from "../../../../core/assert.js";
9
+
10
+ /**
11
+ *
12
+ * @param {number[]} color
13
+ * @param {number[]} thickness
14
+ * @param {number} [duration]
15
+ * @param {number} [scale]
16
+ * @param {number[]} position
17
+ * @param {number[]} ages
18
+ * @param {string} texture
19
+ * @returns {Trail2D}
20
+ */
21
+ export function makeGradientTrail({
22
+ color,
23
+ thickness,
24
+ position,
25
+ duration = 1,
26
+ scale = 1,
27
+ ages,
28
+ texture
29
+ }) {
30
+
31
+ const trail2D = new Trail2D();
32
+ trail2D.maxAge = duration;
33
+ trail2D.width = 1;
34
+ trail2D.textureURL = texture;
35
+
36
+ const point_count = thickness.length;
37
+
38
+ trail2D.build(point_count);
39
+
40
+ const ribbon = trail2D.ribbon;
41
+
42
+ for (let i = 0; i < point_count; i++) {
43
+
44
+ const f = i / (point_count - 1);
45
+ const i3 = i * 3;
46
+
47
+ ribbon.setPointAlpha(i, 0);
48
+ ribbon.setPointPosition(i, position[i3], position[i3 + 1], position[i3 + 2]);
49
+
50
+ ribbon.setPointAttribute_Scalar(i, RIBBON_ATTRIBUTE_ADDRESS_AGE, ages[i] * duration);
51
+ ribbon.setPointAttribute_Scalar(i, RIBBON_ATTRIBUTE_ADDRESS_UV_OFFSET, f);
52
+ ribbon.setPointAttribute_Scalar(i, RIBBON_ATTRIBUTE_ADDRESS_THICKNESS, thickness[i]);
53
+
54
+ const c_0 = color[i];
55
+
56
+ assert.isNumber(c_0, `color[i]`);
57
+
58
+ ribbon.setPointAttribute_Vector3(i, RIBBON_ATTRIBUTE_ADDRESS_COLOR, c_0 >> 16, c_0 >> 8, c_0);
59
+ }
60
+
61
+ // don't spawn more trail segments
62
+ trail2D.clearFlag(Trail2DFlags.Spawning);
63
+ trail2D.setFlag(Trail2DFlags.Built);
64
+
65
+ ribbon.computeBoundingBox(trail2D.bvhLeaf);
66
+
67
+ return trail2D;
68
+ }
@@ -3,12 +3,18 @@ import { computeGeometryHash } from "../../asset/loaders/geometry/geometry/compu
3
3
  import { computeGeometryEquality } from "../../asset/loaders/geometry/geometry/computeGeometryEquality.js";
4
4
  import { buildMicronGeometryFromBufferGeometry } from "./build/buildMicronGeometryFromBufferGeometry.js";
5
5
  import { ThreeMicronMesh } from "./format/ThreeMicronMesh.js";
6
+ import { AsyncMapWrapper } from "../../../core/collection/map/AsyncMapWrapper.js";
6
7
 
7
8
  /**
8
9
  *
9
10
  * @type {HashMap<THREE.BufferGeometry, MicronGeometry>}
10
11
  */
11
- const micron_cache = new HashMap({
12
+ const default_micron_cache = new AsyncMapWrapper(new HashMap({
13
+ keyHashFunction: computeGeometryHash,
14
+ keyEqualityFunction: computeGeometryEquality
15
+ }));
16
+
17
+ const pending_cache = new HashMap({
12
18
  keyHashFunction: computeGeometryHash,
13
19
  keyEqualityFunction: computeGeometryEquality
14
20
  });
@@ -17,9 +23,10 @@ const micron_cache = new HashMap({
17
23
  /**
18
24
  *
19
25
  * @param {THREE.Object3D} object
26
+ * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} micron_cache
20
27
  * @returns {THREE.Object3D}
21
28
  */
22
- export async function convert_three_object_to_micron(object) {
29
+ export async function convert_three_object_to_micron(object, micron_cache = default_micron_cache) {
23
30
 
24
31
  const promises = [];
25
32
 
@@ -29,19 +36,29 @@ export async function convert_three_object_to_micron(object) {
29
36
  * @returns {MicronGeometry}
30
37
  */
31
38
  async function obtain_geometry(g) {
32
- const existing = micron_cache.get(g);
39
+ const existing = await micron_cache.get(g);
40
+
41
+ if (existing !== undefined && existing !== null) {
42
+ return existing;
43
+ }
44
+
45
+ const pending = pending_cache.get(g);
33
46
 
34
- if (existing !== undefined) {
35
- return await existing;
47
+ if (pending !== undefined) {
48
+ return await pending;
36
49
  }
37
50
 
38
51
  const micron_geometry_promise = buildMicronGeometryFromBufferGeometry(g);
39
52
 
40
- micron_cache.set(g, micron_geometry_promise);
53
+ pending_cache.set(g, micron_geometry_promise);
41
54
 
42
55
  promises.push(micron_geometry_promise);
43
56
 
44
- return await micron_geometry_promise;
57
+ const micron_geometry = await micron_geometry_promise;
58
+
59
+ await micron_cache.set(g, micron_geometry);
60
+
61
+ return micron_geometry;
45
62
  }
46
63
 
47
64
 
@@ -3,6 +3,57 @@ 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
5
  import { SOURCE_RENDER_LAYER_PROPERTY } from "../../render/visibility/VisibilityComputer.js";
6
+ import { AssetTransformer } from "../../../asset/AssetTransformer.js";
7
+ import { convert_three_object_to_micron } from "../convert_three_object_to_micron.js";
8
+ import { Cache } from "../../../../core/cache/Cache.js";
9
+ import { computeGeometryHash } from "../../../asset/loaders/geometry/geometry/computeGeometryHash.js";
10
+ import { computeGeometryEquality } from "../../../asset/loaders/geometry/geometry/computeGeometryEquality.js";
11
+ import { CachedAsyncMap } from "../../../../core/collection/map/CachedAsyncMap.js";
12
+ import { AsyncRemoteHashMap } from "../../../../core/collection/map/AsyncRemoteHashMap.js";
13
+ import { BufferGeometrySerializationAdapter } from "./serialization/BufferGeometrySerializationAdapter.js";
14
+ import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
15
+ import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper.js";
16
+
17
+ /**
18
+ *
19
+ * @type {string}
20
+ */
21
+ const STORAGE_KEY = '@plugin/virtual-geometry-micron/geometry-cache';
22
+
23
+
24
+ class GLTFAssetTransformer extends AssetTransformer {
25
+ /**
26
+ *
27
+ * @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} cache
28
+ */
29
+ constructor(cache) {
30
+ super();
31
+
32
+ /**
33
+ *
34
+ * @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>}
35
+ * @private
36
+ */
37
+ this.__cache = cache;
38
+ }
39
+
40
+ async transform(source) {
41
+ const animationClips = source.animations;
42
+ if (animationClips !== undefined && animationClips.length > 0) {
43
+ // not suitable
44
+ return source;
45
+ }
46
+
47
+ const root = source.create();
48
+
49
+ const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
50
+ micron_root.boundingSphere = root.boundingSphere;
51
+
52
+ source.override_mesh = micron_root;
53
+
54
+ return source;
55
+ }
56
+ }
6
57
 
7
58
  export class MicronRenderPlugin extends EnginePlugin {
8
59
  constructor() {
@@ -37,6 +88,40 @@ export class MicronRenderPlugin extends EnginePlugin {
37
88
  });
38
89
 
39
90
  this.__view_observers = new Map();
91
+
92
+ /**
93
+ *
94
+ * @type {AsyncRemoteHashMap}
95
+ * @private
96
+ */
97
+ this.__persisted_geometry = new AsyncRemoteHashMap({
98
+ keyHashFunction: computeGeometryHash,
99
+ keyEqualityFunction: computeGeometryEquality,
100
+ keySerializationAdapter: new BufferGeometrySerializationAdapter(),
101
+ valueSerializationAdapter: new MicronGeometryBinarySerializationAdapter(),
102
+ storageKeyPrefix: STORAGE_KEY,
103
+
104
+ });
105
+ /**
106
+ *
107
+ * @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>}
108
+ * @private
109
+ */
110
+ this.__cache = new CachedAsyncMap(
111
+ new AsyncMapWrapper(new Cache({
112
+ keyHashFunction: computeGeometryHash,
113
+ keyEqualityFunction: computeGeometryEquality
114
+ })),
115
+ this.__persisted_geometry
116
+ );
117
+
118
+ /**
119
+ *
120
+ * @type {AssetTransformer}
121
+ * @private
122
+ */
123
+ this.__asset_transformer = new GLTFAssetTransformer(this.__cache);
124
+
40
125
  }
41
126
 
42
127
  /**
@@ -87,13 +172,22 @@ export class MicronRenderPlugin extends EnginePlugin {
87
172
  view.on.preRender.remove(observer);
88
173
  }
89
174
 
175
+ __ingest_cache() {
176
+ this.engine.storage.lo
177
+ }
178
+
90
179
  async startup() {
91
180
 
181
+ const engine = this.engine;
182
+
183
+ engine.assetManager.registerTransformer("model/gltf", this.__asset_transformer);
184
+ engine.assetManager.registerTransformer("model/gltf+json", this.__asset_transformer);
185
+
92
186
  /**
93
187
  *
94
188
  * @type {GraphicsEngine}
95
189
  */
96
- const ge = this.engine.graphics;
190
+ const ge = engine.graphics;
97
191
 
98
192
  ge.layers.add(this.__micron_render_layer);
99
193
 
@@ -101,13 +195,22 @@ export class MicronRenderPlugin extends EnginePlugin {
101
195
  ge.views.elements.on.removed.add(this.__handle_view_removed, this);
102
196
 
103
197
  // link all views
104
- ge.views.elements.forEach(this.__handle_view_added,this);
198
+ ge.views.elements.forEach(this.__handle_view_added, this);
199
+
200
+ this.__persisted_geometry.attach_storage(engine.storage);
105
201
 
106
202
  await super.startup();
107
203
  }
108
204
 
109
205
  async shutdown() {
110
- const ge = this.engine.graphics;
206
+ const engine = this.engine;
207
+
208
+ this.__persisted_geometry.detach_storage();
209
+
210
+ engine.assetManager.unregisterTransformer("model/gltf", this.__asset_transformer);
211
+ engine.assetManager.unregisterTransformer("model/gltf+json", this.__asset_transformer);
212
+
213
+ const ge = engine.graphics;
111
214
 
112
215
  ge.layers.remove(this.__micron_render_layer);
113
216
 
@@ -115,7 +218,7 @@ export class MicronRenderPlugin extends EnginePlugin {
115
218
  ge.views.elements.on.removed.remove(this.__handle_view_removed, this);
116
219
 
117
220
  // clear all observer
118
- ge.views.elements.forEach(this.__handle_view_removed,this);
221
+ ge.views.elements.forEach(this.__handle_view_removed, this);
119
222
 
120
223
  await super.shutdown();
121
224
  }
@@ -0,0 +1,176 @@
1
+ import { BinaryClassSerializationAdapter } from "../../../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
2
+ import { BufferAttribute, BufferGeometry } from "three";
3
+
4
+ function typed_array_to_enum(array) {
5
+ if (array instanceof Uint8Array) {
6
+ return 0;
7
+ } else if (array instanceof Uint16Array) {
8
+ return 1;
9
+ } else if (array instanceof Uint32Array) {
10
+ return 2;
11
+ } else if (array instanceof Uint8Array) {
12
+ return 3;
13
+ } else if (array instanceof Uint16Array) {
14
+ return 4;
15
+ } else if (array instanceof Uint32Array) {
16
+ return 5;
17
+ } else if (array instanceof Float32Array) {
18
+ return 6;
19
+ } else if (array instanceof Float64Array) {
20
+ return 7;
21
+ } else {
22
+ throw new Error('Unsupported array type');
23
+ }
24
+ }
25
+
26
+ function marker_to_typed_array_constructor(marker) {
27
+ switch (marker) {
28
+ case 0:
29
+ return Uint8Array;
30
+ case 1:
31
+ return Uint16Array;
32
+ case 2:
33
+ return Uint32Array;
34
+ case 3:
35
+ return Int8Array;
36
+ case 4:
37
+ return Int16Array;
38
+ case 5:
39
+ return Int32Array;
40
+ case 6:
41
+ return Float32Array;
42
+ case 7:
43
+ return Float64Array;
44
+ default:
45
+ throw new Error('Unsupported marker');
46
+ }
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @param {BinaryBuffer} buffer
52
+ * @param {Uint8Array|Float32Array|ArrayLike<number>} value
53
+ */
54
+ function write_typed_array(buffer, value) {
55
+
56
+ buffer.writeUint8(typed_array_to_enum(value));
57
+ buffer.writeUintVar(value.byteLength);
58
+
59
+ const data = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
60
+ buffer.writeBytes(data, 0, value.byteLength);
61
+ }
62
+
63
+ function read_typed_array(buffer) {
64
+ const type_marker = buffer.readUint8();
65
+ const byte_length = buffer.readUintVar();
66
+
67
+ const array = new Uint8Array(byte_length);
68
+
69
+ buffer.readBytes(array, 0, byte_length);
70
+
71
+ // re-interpret bytes
72
+ const TypedArray = marker_to_typed_array_constructor(type_marker);
73
+
74
+ return new TypedArray(array.buffer, 0);
75
+ }
76
+
77
+ /**
78
+ *
79
+ * @param {BinaryBuffer} buffer
80
+ * @param {BufferAttribute} value
81
+ */
82
+ function write_attribute(buffer, value) {
83
+ buffer.writeUTF8String(value.name);
84
+ buffer.writeUintVar(value.itemSize);
85
+ buffer.writeUint8(value.normalized ? 1 : 0);
86
+ buffer.writeUint32(value.usage);
87
+
88
+ write_typed_array(buffer, value.array);
89
+ }
90
+
91
+ /**
92
+ *
93
+ * @param {BinaryBuffer} buffer
94
+ * @returns {BufferAttribute}
95
+ */
96
+ function read_attribute(buffer) {
97
+ const name = buffer.readUTF8String();
98
+ const itemSize = buffer.readUintVar();
99
+ const normalized = buffer.readUint8() !== 0;
100
+ const usage = buffer.readUint32();
101
+
102
+ const array = read_typed_array(buffer);
103
+
104
+ const attribute = new BufferAttribute(array, itemSize, normalized);
105
+
106
+ attribute.usage = usage;
107
+ attribute.name = name;
108
+
109
+ return attribute;
110
+ }
111
+
112
+ export class BufferGeometrySerializationAdapter extends BinaryClassSerializationAdapter {
113
+ constructor() {
114
+ super();
115
+
116
+ this.klass = BufferGeometry;
117
+ }
118
+
119
+ /**
120
+ *
121
+ * @param {BinaryBuffer} buffer
122
+ * @param {BufferGeometry} value
123
+ */
124
+ serialize(buffer, value) {
125
+ // write index if one exists
126
+ const index = value.getIndex();
127
+ if (index === null) {
128
+ buffer.writeUint8(0);
129
+ } else {
130
+ buffer.writeUint8(1);
131
+
132
+ write_attribute(buffer, index);
133
+ }
134
+
135
+ const attributes = value.attributes;
136
+ const attribute_keys = Object.keys(attributes);
137
+
138
+ const attribute_count = attribute_keys.length;
139
+ buffer.writeUintVar(attribute_count);
140
+
141
+ for (let i = 0; i < attribute_count; i++) {
142
+ const attribute_key = attribute_keys[i];
143
+
144
+ buffer.writeUTF8String(attribute_key);
145
+
146
+ const attribute = attributes[attribute_key];
147
+
148
+ write_attribute(buffer, attribute);
149
+ }
150
+ }
151
+
152
+ /**
153
+ *
154
+ * @param {BinaryBuffer} buffer
155
+ * @param {BufferGeometry} value
156
+ */
157
+ deserialize(buffer, value) {
158
+ const index_flag = buffer.readUint8();
159
+
160
+ if (index_flag !== 0) {
161
+ value.setIndex(read_attribute(buffer));
162
+ } else {
163
+ value.setIndex(null);
164
+ }
165
+
166
+ const attribute_count = buffer.readUintVar();
167
+
168
+ for (let i = 0; i < attribute_count; i++) {
169
+ const attribute_key = buffer.readUTF8String();
170
+
171
+ const attribute = read_attribute(buffer);
172
+
173
+ value.setAttribute(attribute_key, attribute);
174
+ }
175
+ }
176
+ }