@woosh/meep-engine 2.33.64 → 2.33.65

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.
package/core/FilePath.js CHANGED
@@ -1,3 +1,5 @@
1
+ const PATH_SEPARATOR = '/';
2
+
1
3
  /**
2
4
  * Strips all directories from the path.
3
5
  * @example 'a/b/c' -> 'c'
@@ -9,7 +11,7 @@ function computePathBase(path) {
9
11
  throw new Error('path is not a string');
10
12
  }
11
13
 
12
- const lastSlashIndex = path.lastIndexOf('/');
14
+ const lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
13
15
 
14
16
  if (lastSlashIndex !== -1) {
15
17
  return path.substring(lastSlashIndex + 1);
@@ -18,6 +20,30 @@ function computePathBase(path) {
18
20
  }
19
21
  }
20
22
 
23
+ /**
24
+ * Returns the directory name of a path, similar to the Unix dirname command.
25
+ * @param {string} path
26
+ * @return {string}
27
+ */
28
+ export function computePathDirectory(path) {
29
+ if (typeof path !== "string") {
30
+ throw new Error('path is not a string');
31
+ }
32
+
33
+ let lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
34
+
35
+ //rewind in case of trailing slashes
36
+ while (lastSlashIndex > 0 && path.charAt(lastSlashIndex - 1) === PATH_SEPARATOR) {
37
+ lastSlashIndex--;
38
+ }
39
+
40
+ if (lastSlashIndex !== -1) {
41
+ return path.substring(0, lastSlashIndex);
42
+ } else {
43
+ return path;
44
+ }
45
+ }
46
+
21
47
  /**
22
48
  *
23
49
  * @param {string} path
@@ -44,4 +70,4 @@ function computeFileExtension(path) {
44
70
  export {
45
71
  computePathBase,
46
72
  computeFileExtension
47
- };
73
+ };
@@ -57,6 +57,19 @@ BinaryBuffer.prototype.fromArrayBuffer = function (arrayBuffer) {
57
57
  this.position = 0;
58
58
  };
59
59
 
60
+ /**
61
+ *
62
+ * @param {ArrayBuffer} v
63
+ * @return {BinaryBuffer}
64
+ */
65
+ BinaryBuffer.fromArrayBuffer = function (v) {
66
+ const r = new BinaryBuffer();
67
+
68
+ r.fromArrayBuffer(v);
69
+
70
+ return r;
71
+ };
72
+
60
73
  /**
61
74
  *
62
75
  * @returns {BinaryBuffer}
@@ -231,7 +231,7 @@ AssetManager.prototype.submitRequest = function (path, type, request) {
231
231
  for (let i = 0; i < transformer_count; i++) {
232
232
  const transformer = transformers[i];
233
233
 
234
- const transformed_asset = await transformer.transform(asset);
234
+ const transformed_asset = await transformer.transform(asset, assetDescription);
235
235
 
236
236
  if (typeof transformed_asset !== "object") {
237
237
  console.error('Transformer produced invalid result. Ignoring result.', transformer, assetDescription);
@@ -7,9 +7,10 @@
7
7
  export class AssetTransformer {
8
8
  /**
9
9
  * @param {A} source
10
+ * @param {AssetDescription} asset_description
10
11
  * @returns {A}
11
12
  */
12
- async transform(source) {
13
+ async transform(source, asset_description) {
13
14
  throw new Error('Not Implemented');
14
15
  }
15
16
  }
@@ -25,6 +25,8 @@ import { computeGeometryEquality } from "./geometry/geometry/computeGeometryEqua
25
25
  import { traverseThreeObject } from "../../graphics/ecs/highlight/renderer/traverseThreeObject.js";
26
26
  import { computeTextureHash } from "./material/computeTextureHash.js";
27
27
  import { computeTextureEquality } from "./material/computeTextureEquality.js";
28
+ import { async_traverse_three_object } from "./async_traverse_three_object.js";
29
+ import { deinterleaveBufferGeometry } from "../../graphics/geometry/buffered/deinterleaveBufferGeometry.js";
28
30
 
29
31
  const animationOptimizer = new AnimationOptimizer();
30
32
  const materialCache = StaticMaterialCache.Global;
@@ -130,26 +132,6 @@ function buildDracoDecoderPath() {
130
132
  return `${pathname}/libs/draco/`;
131
133
  }
132
134
 
133
- /**
134
- *
135
- * @param {THREE.Object3D} object
136
- * @param {function} callback
137
- * @param {*} [thisArg]
138
- */
139
- async function async_traverse(object, callback, thisArg) {
140
- await callback.call(thisArg, object);
141
-
142
- const children = object.children;
143
- const n = children.length;
144
-
145
- for (let i = 0; i < n; i++) {
146
- const child = children[i];
147
-
148
- // TODO we can parallelize this if necessary
149
- await async_traverse(child, callback, thisArg);
150
- }
151
- }
152
-
153
135
  export class GLTFAssetLoader extends AssetLoader {
154
136
 
155
137
  constructor() {
@@ -312,6 +294,8 @@ export class GLTFAssetLoader extends AssetLoader {
312
294
  mesh.geometry = geometry;
313
295
  }
314
296
 
297
+ mesh.geometry = deinterleaveBufferGeometry(geometry);
298
+
315
299
 
316
300
  if (this.__enable_texture_cache) {
317
301
  // replace textures from cache
@@ -387,7 +371,7 @@ export class GLTFAssetLoader extends AssetLoader {
387
371
  }
388
372
 
389
373
 
390
- await async_traverse(root, process_object);
374
+ await async_traverse_three_object(root, process_object);
391
375
 
392
376
 
393
377
  // compute object bounding sphere
@@ -0,0 +1,24 @@
1
+ /**
2
+ *
3
+ * @param {THREE.Object3D} object
4
+ * @param {function} callback
5
+ * @param {*} [thisArg]
6
+ * @param {*} [ctx]
7
+ */
8
+ export async function async_traverse_three_object(object, callback, thisArg, ctx) {
9
+ await callback.call(thisArg, object, ctx);
10
+
11
+ const children = object.children;
12
+ const n = children.length;
13
+
14
+ const child_promises = [];
15
+
16
+ for (let i = 0; i < n; i++) {
17
+ const child = children[i];
18
+
19
+ child_promises.push(async_traverse_three_object(child, callback, thisArg, ctx));
20
+ }
21
+
22
+ // wait for all children at the same time
23
+ await Promise.all(child_promises);
24
+ }
@@ -0,0 +1 @@
1
+ export const MICRON_GEOMETRY_FIELD = '@micron_geometry';
@@ -0,0 +1 @@
1
+ export const MICRON_URI_FIELD = '@micron_path';
@@ -4,6 +4,7 @@ import { computeGeometryEquality } from "../../asset/loaders/geometry/geometry/c
4
4
  import { buildMicronGeometryFromBufferGeometry } from "./build/buildMicronGeometryFromBufferGeometry.js";
5
5
  import { ThreeMicronMesh } from "./format/ThreeMicronMesh.js";
6
6
  import { AsyncMapWrapper } from "../../../core/collection/map/AsyncMapWrapper.js";
7
+ import { MICRON_GEOMETRY_FIELD } from "./MICRON_GEOMETRY_FIELD.js";
7
8
 
8
9
  /**
9
10
  *
@@ -19,7 +20,6 @@ const pending_cache = new HashMap({
19
20
  keyEqualityFunction: computeGeometryEquality
20
21
  });
21
22
 
22
-
23
23
  /**
24
24
  *
25
25
  * @param {THREE.Object3D} object
@@ -36,6 +36,13 @@ export async function convert_three_object_to_micron(object, micron_cache = defa
36
36
  * @returns {MicronGeometry}
37
37
  */
38
38
  async function obtain_geometry(g) {
39
+ const attached_micron = g[MICRON_GEOMETRY_FIELD];
40
+
41
+ if (attached_micron !== undefined && attached_micron.isMicronGeometry) {
42
+ // micron geometry is already attached, use it
43
+ return attached_micron;
44
+ }
45
+
39
46
  const existing = await micron_cache.get(g);
40
47
 
41
48
  if (existing !== undefined && existing !== null) {
@@ -90,7 +97,15 @@ export async function convert_three_object_to_micron(object, micron_cache = defa
90
97
  && !mesh.isSkinnedMesh // skinned meshes not supported
91
98
  ) {
92
99
 
93
- const micronGeometry = await obtain_geometry(mesh.geometry);
100
+ let micronGeometry;
101
+ try {
102
+ micronGeometry = await obtain_geometry(mesh.geometry);
103
+ } catch (e) {
104
+ console.error(`Failed to convert geometry to micron, skipping : ${e}`);
105
+
106
+ // return original
107
+ return mesh;
108
+ }
94
109
 
95
110
  const micron_mesh = new ThreeMicronMesh(micronGeometry, mesh.material);
96
111
 
@@ -117,3 +117,9 @@ export class MicronGeometry {
117
117
  return this.__patches[id];
118
118
  }
119
119
  }
120
+
121
+ /**
122
+ * @readonly
123
+ * @type {boolean}
124
+ */
125
+ MicronGeometry.prototype.isMicronGeometry = true;
@@ -13,6 +13,13 @@ import { AsyncRemoteHashMap } from "../../../../core/collection/map/AsyncRemoteH
13
13
  import { BufferGeometrySerializationAdapter } from "./serialization/BufferGeometrySerializationAdapter.js";
14
14
  import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
15
15
  import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper.js";
16
+ import { async_traverse_three_object } from "../../../asset/loaders/async_traverse_three_object.js";
17
+ import { computePathDirectory } from "../../../../core/FilePath.js";
18
+ import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
19
+ import { MicronGeometry } from "../format/MicronGeometry.js";
20
+ import { ArrayBufferLoader } from "../../../asset/loaders/ArrayBufferLoader.js";
21
+ import { MICRON_URI_FIELD } from "../MICRON_URI_FIELD.js";
22
+ import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
16
23
 
17
24
  /**
18
25
  *
@@ -20,6 +27,7 @@ import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper
20
27
  */
21
28
  const STORAGE_KEY = '@plugin/virtual-geometry-micron/geometry-cache';
22
29
 
30
+ const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
23
31
 
24
32
  class GLTFAssetTransformer extends AssetTransformer {
25
33
  /**
@@ -35,17 +43,97 @@ class GLTFAssetTransformer extends AssetTransformer {
35
43
  * @private
36
44
  */
37
45
  this.__cache = cache;
46
+
47
+ /**
48
+ *
49
+ * @type {AssetManager|null}
50
+ * @private
51
+ */
52
+ this.__am = null;
53
+
54
+ /**
55
+ *
56
+ * @type {MicronGeometryBinarySerializationAdapter}
57
+ * @private
58
+ */
59
+ this.__serde = new MicronGeometryBinarySerializationAdapter();
60
+ }
61
+
62
+ /**
63
+ *
64
+ * @param {AssetManager|null} am
65
+ */
66
+ set assetManager(am) {
67
+ this.__am = am;
68
+ }
69
+
70
+
71
+ /**
72
+ * @param {THREE.Object3D} object
73
+ * @param {{asset:AssetDescription}} ctx
74
+ * @return {Promise<void>}
75
+ * @private
76
+ */
77
+ async __visitObjectToLoadMicron(object, ctx) {
78
+ if (!object.isMesh) {
79
+ return;
80
+ }
81
+
82
+ /**
83
+ * @type {THREE.BufferGeometry}
84
+ */
85
+ const geometry = object.geometry;
86
+
87
+ const micron_uri = geometry.userData[MICRON_URI_FIELD];
88
+
89
+ if (typeof micron_uri !== "string") {
90
+ return;
91
+ }
92
+
93
+
94
+ /**
95
+ * @type {AssetDescription}
96
+ */
97
+ const ad = ctx.asset;
98
+
99
+ const base = computePathDirectory(ad.path);
100
+
101
+ const micron_data = await this.__am.promise(`${base}/${micron_uri}`, ASSET_TYPE_ARRAY_BUFFER);
102
+
103
+ // deserialize micron data
104
+ const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
105
+ const micron_geometry = new MicronGeometry();
106
+
107
+ this.__serde.deserialize(buffer, micron_geometry);
108
+
109
+ geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
38
110
  }
39
111
 
40
- async transform(source) {
112
+
113
+ /**
114
+ *
115
+ * @param {Asset} source
116
+ * @param asset_description
117
+ * @return {Promise<Asset>}
118
+ */
119
+ async transform(source, asset_description) {
41
120
  const animationClips = source.animations;
121
+
42
122
  if (animationClips !== undefined && animationClips.length > 0) {
43
123
  // not suitable
44
124
  return source;
45
125
  }
46
126
 
127
+ /**
128
+ * @type {THREE.Object3D}
129
+ */
47
130
  const root = source.create();
48
131
 
132
+ // attempt to load existing micron geometries
133
+ await async_traverse_three_object(root, this.__visitObjectToLoadMicron, this, {
134
+ asset: asset_description
135
+ });
136
+
49
137
  const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
50
138
  micron_root.boundingSphere = root.boundingSphere;
51
139
 
@@ -117,7 +205,7 @@ export class MicronRenderPlugin extends EnginePlugin {
117
205
 
118
206
  /**
119
207
  *
120
- * @type {AssetTransformer}
208
+ * @type {GLTFAssetTransformer}
121
209
  * @private
122
210
  */
123
211
  this.__asset_transformer = new GLTFAssetTransformer(this.__cache);
@@ -180,8 +268,17 @@ export class MicronRenderPlugin extends EnginePlugin {
180
268
 
181
269
  const engine = this.engine;
182
270
 
183
- engine.assetManager.registerTransformer("model/gltf", this.__asset_transformer);
184
- engine.assetManager.registerTransformer("model/gltf+json", this.__asset_transformer);
271
+ const am = engine.assetManager;
272
+
273
+ // ensure that "arraybuffer" asset loader is present
274
+ if (am.getLoaderByType(ASSET_TYPE_ARRAY_BUFFER) === undefined) {
275
+ am.registerLoader(ASSET_TYPE_ARRAY_BUFFER, new ArrayBufferLoader());
276
+ }
277
+
278
+ this.__asset_transformer.assetManager = am;
279
+
280
+ am.registerTransformer("model/gltf", this.__asset_transformer);
281
+ am.registerTransformer("model/gltf+json", this.__asset_transformer);
185
282
 
186
283
  /**
187
284
  *
@@ -207,8 +304,12 @@ export class MicronRenderPlugin extends EnginePlugin {
207
304
 
208
305
  this.__persisted_geometry.detach_storage();
209
306
 
210
- engine.assetManager.unregisterTransformer("model/gltf", this.__asset_transformer);
211
- engine.assetManager.unregisterTransformer("model/gltf+json", this.__asset_transformer);
307
+ const am = engine.assetManager;
308
+
309
+ am.unregisterTransformer("model/gltf", this.__asset_transformer);
310
+ am.unregisterTransformer("model/gltf+json", this.__asset_transformer);
311
+
312
+ this.__asset_transformer.assetManager = null;
212
313
 
213
314
  const ge = engine.graphics;
214
315
 
@@ -433,7 +433,9 @@ async function sample_scene_nam(engine) {
433
433
  "distanceMax": 1000
434
434
  });
435
435
 
436
- load_model('moicon/20_Dec_2021_Nammo/with_assets(for_alex)/model.gltf', ecd)
436
+ // load_model('moicon/20_Dec_2021_Nammo/with_assets(for_alex)/model.gltf', ecd)
437
+ load_model('moicon/20_Dec_2021_Nammo/with_assets_micron_conveted/model.gltf', ecd)
438
+ // load_model('moicon/micron_container/model.gltf', ecd)
437
439
 
438
440
  const P_SIZE_SMALL = 0.15;
439
441
  const P_SIZE_MEDIUM = 0.6;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "productName": "Meep",
6
6
  "description": "production-ready JavaScript game engine based on Entity Component System Architecture",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.33.64",
8
+ "version": "2.33.65",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",