@itwin/core-frontend 3.0.0-dev.167 → 3.0.0-dev.172

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 (75) hide show
  1. package/lib/cjs/IModelApp.d.ts +1 -1
  2. package/lib/cjs/IModelApp.d.ts.map +1 -1
  3. package/lib/cjs/IModelApp.js.map +1 -1
  4. package/lib/cjs/ImageUtil.d.ts.map +1 -1
  5. package/lib/cjs/ImageUtil.js +4 -1
  6. package/lib/cjs/ImageUtil.js.map +1 -1
  7. package/lib/cjs/ViewManager.d.ts +6 -6
  8. package/lib/cjs/ViewManager.js +5 -5
  9. package/lib/cjs/ViewManager.js.map +1 -1
  10. package/lib/cjs/Viewport.d.ts +5 -3
  11. package/lib/cjs/Viewport.d.ts.map +1 -1
  12. package/lib/cjs/Viewport.js +5 -3
  13. package/lib/cjs/Viewport.js.map +1 -1
  14. package/lib/cjs/render/RenderSystem.d.ts +1 -0
  15. package/lib/cjs/render/RenderSystem.d.ts.map +1 -1
  16. package/lib/cjs/render/RenderSystem.js +1 -0
  17. package/lib/cjs/render/RenderSystem.js.map +1 -1
  18. package/lib/cjs/tile/B3dmReader.js +2 -2
  19. package/lib/cjs/tile/B3dmReader.js.map +1 -1
  20. package/lib/cjs/tile/DynamicIModelTile.js +1 -1
  21. package/lib/cjs/tile/DynamicIModelTile.js.map +1 -1
  22. package/lib/cjs/tile/GltfReader.d.ts +129 -36
  23. package/lib/cjs/tile/GltfReader.d.ts.map +1 -1
  24. package/lib/cjs/tile/GltfReader.js +261 -122
  25. package/lib/cjs/tile/GltfReader.js.map +1 -1
  26. package/lib/cjs/tile/I3dmReader.js +2 -2
  27. package/lib/cjs/tile/I3dmReader.js.map +1 -1
  28. package/lib/cjs/tile/IModelTile.js +1 -1
  29. package/lib/cjs/tile/IModelTile.js.map +1 -1
  30. package/lib/cjs/tile/ImdlReader.d.ts +12 -1
  31. package/lib/cjs/tile/ImdlReader.d.ts.map +1 -1
  32. package/lib/cjs/tile/ImdlReader.js +47 -3
  33. package/lib/cjs/tile/ImdlReader.js.map +1 -1
  34. package/lib/cjs/tile/RealityTileLoader.js +1 -1
  35. package/lib/cjs/tile/RealityTileLoader.js.map +1 -1
  36. package/lib/cjs/tile/map/CesiumTerrainProvider.js +1 -1
  37. package/lib/cjs/tile/map/CesiumTerrainProvider.js.map +1 -1
  38. package/lib/esm/IModelApp.d.ts +1 -1
  39. package/lib/esm/IModelApp.d.ts.map +1 -1
  40. package/lib/esm/IModelApp.js.map +1 -1
  41. package/lib/esm/ImageUtil.d.ts.map +1 -1
  42. package/lib/esm/ImageUtil.js +4 -1
  43. package/lib/esm/ImageUtil.js.map +1 -1
  44. package/lib/esm/ViewManager.d.ts +6 -6
  45. package/lib/esm/ViewManager.js +5 -5
  46. package/lib/esm/ViewManager.js.map +1 -1
  47. package/lib/esm/Viewport.d.ts +5 -3
  48. package/lib/esm/Viewport.d.ts.map +1 -1
  49. package/lib/esm/Viewport.js +5 -3
  50. package/lib/esm/Viewport.js.map +1 -1
  51. package/lib/esm/render/RenderSystem.d.ts +1 -0
  52. package/lib/esm/render/RenderSystem.d.ts.map +1 -1
  53. package/lib/esm/render/RenderSystem.js +1 -0
  54. package/lib/esm/render/RenderSystem.js.map +1 -1
  55. package/lib/esm/tile/B3dmReader.js +2 -2
  56. package/lib/esm/tile/B3dmReader.js.map +1 -1
  57. package/lib/esm/tile/DynamicIModelTile.js +1 -1
  58. package/lib/esm/tile/DynamicIModelTile.js.map +1 -1
  59. package/lib/esm/tile/GltfReader.d.ts +129 -36
  60. package/lib/esm/tile/GltfReader.d.ts.map +1 -1
  61. package/lib/esm/tile/GltfReader.js +261 -123
  62. package/lib/esm/tile/GltfReader.js.map +1 -1
  63. package/lib/esm/tile/I3dmReader.js +2 -2
  64. package/lib/esm/tile/I3dmReader.js.map +1 -1
  65. package/lib/esm/tile/IModelTile.js +1 -1
  66. package/lib/esm/tile/IModelTile.js.map +1 -1
  67. package/lib/esm/tile/ImdlReader.d.ts +12 -1
  68. package/lib/esm/tile/ImdlReader.d.ts.map +1 -1
  69. package/lib/esm/tile/ImdlReader.js +45 -2
  70. package/lib/esm/tile/ImdlReader.js.map +1 -1
  71. package/lib/esm/tile/RealityTileLoader.js +1 -1
  72. package/lib/esm/tile/RealityTileLoader.js.map +1 -1
  73. package/lib/esm/tile/map/CesiumTerrainProvider.js +1 -1
  74. package/lib/esm/tile/map/CesiumTerrainProvider.js.map +1 -1
  75. package/package.json +22 -22
@@ -7,8 +7,8 @@
7
7
  */
8
8
  import { assert, ByteStream, JsonUtils, utf8ToString } from "@itwin/core-bentley";
9
9
  import { Angle, Matrix3d, Point2d, Point3d, Point4d, Range2d, Range3d, Transform, Vector3d } from "@itwin/core-geometry";
10
- import { BatchType, ColorDef, Feature, FeatureTable, FillFlags, GltfHeader, ImageSource, ImageSourceFormat, LinePixels, MeshEdge, MeshEdges, MeshPolyline, OctEncodedNormal, PackedFeatureTable, QParams2d, QParams3d, QPoint2dList, QPoint3dList, Quantization, RenderTexture, TextureMapping, TileReadStatus, } from "@itwin/core-common";
11
- import { getImageSourceFormatForMimeType, imageElementFromImageSource } from "../ImageUtil";
10
+ import { BatchType, ColorDef, Feature, FeatureTable, FillFlags, GlbHeader, ImageSource, LinePixels, MeshEdge, MeshEdges, MeshPolyline, OctEncodedNormal, PackedFeatureTable, QParams2d, QParams3d, QPoint2dList, QPoint3dList, Quantization, RenderTexture, TextureMapping, TileFormat, TileReadStatus, } from "@itwin/core-common";
11
+ import { getImageSourceFormatForMimeType, imageElementFromImageSource, tryImageElementFromUrl } from "../ImageUtil";
12
12
  import { IModelApp } from "../IModelApp";
13
13
  import { GraphicBranch } from "../render/GraphicBranch";
14
14
  import { DisplayParams } from "../render/primitives/DisplayParams";
@@ -79,6 +79,19 @@ var GltfBufferTarget;
79
79
  GltfBufferTarget[GltfBufferTarget["ArrayBuffer"] = 34962] = "ArrayBuffer";
80
80
  GltfBufferTarget[GltfBufferTarget["ElementArrayBuffer"] = 24963] = "ElementArrayBuffer";
81
81
  })(GltfBufferTarget || (GltfBufferTarget = {}));
82
+ function* dictionaryIterator(dict) {
83
+ if (Array.isArray(dict)) {
84
+ for (const elem of dict)
85
+ yield elem;
86
+ }
87
+ else {
88
+ for (const key of Object.keys(dict)) {
89
+ const value = dict[key];
90
+ if (undefined !== value)
91
+ yield value;
92
+ }
93
+ }
94
+ }
82
95
  function getNodeMeshIds(node) {
83
96
  if (undefined !== node.meshes)
84
97
  return typeof node.meshes === "string" ? [node.meshes] : node.meshes;
@@ -169,50 +182,80 @@ class GltfBufferView {
169
182
  * @internal
170
183
  */
171
184
  export class GltfReaderProps {
172
- constructor(binaryData, glTF, yAxisUp) {
173
- this.binaryData = binaryData;
185
+ constructor(glTF, version, yAxisUp, binaryData, baseUrl) {
186
+ this.version = version;
174
187
  this.glTF = glTF;
188
+ this.binaryData = binaryData;
175
189
  this.yAxisUp = yAxisUp;
190
+ this.baseUrl = baseUrl;
176
191
  }
177
192
  /** Attempt to construct a new GltfReaderProps from the binary data beginning at the supplied stream's current read position. */
178
- static create(buffer, yAxisUp = false) {
179
- const header = new GltfHeader(buffer);
180
- if (!header.isValid)
181
- return undefined;
182
- const binaryData = new Uint8Array(buffer.arrayBuffer, header.binaryPosition);
183
- buffer.curPos = header.scenePosition;
184
- const jsonStrData = buffer.nextBytes(header.sceneStrLength);
185
- const jsonStr = utf8ToString(jsonStrData);
186
- if (undefined === jsonStr)
187
- return undefined;
188
- try {
189
- const json = JSON.parse(jsonStr);
190
- const asset = JsonUtils.asObject(json.asset);
191
- if (header.version === 2 && !asset)
192
- return undefined; // asset is required in glTF 2.0
193
- const glTF = {
194
- asset,
195
- scene: JsonUtils.asString(json.scene),
196
- extensions: JsonUtils.asObject(json.extensions),
197
- extensionsUsed: JsonUtils.asArray(json.extensionsUsed),
198
- extensionsRequired: JsonUtils.asArray(json.extensionsRequired),
199
- accessors: JsonUtils.asObject(json.accessors),
200
- buffers: JsonUtils.asObject(json.buffers),
201
- bufferViews: JsonUtils.asObject(json.bufferViews),
202
- images: JsonUtils.asObject(json.images),
203
- materials: JsonUtils.asObject(json.materials),
204
- meshes: JsonUtils.asObject(json.meshes),
205
- nodes: JsonUtils.asObject(json.nodes),
206
- samplers: JsonUtils.asObject(json.samplers),
207
- scenes: JsonUtils.asObject(json.scenes),
208
- textures: JsonUtils.asObject(json.textures),
209
- techniques: JsonUtils.asObject(json.techniques),
210
- };
211
- return glTF.meshes ? new GltfReaderProps(binaryData, glTF, yAxisUp) : undefined;
193
+ static create(source, yAxisUp = false, baseUrl) {
194
+ let version;
195
+ let json;
196
+ let binaryData;
197
+ if (source instanceof Uint8Array) {
198
+ // It may be JSON - check for magic indicating glb.
199
+ const buffer = ByteStream.fromUint8Array(source);
200
+ if (TileFormat.Gltf !== buffer.nextUint32) {
201
+ try {
202
+ const utf8Json = utf8ToString(source);
203
+ if (!utf8Json)
204
+ return undefined;
205
+ json = JSON.parse(utf8Json);
206
+ version = 2;
207
+ }
208
+ catch (_) {
209
+ return undefined;
210
+ }
211
+ }
212
+ else {
213
+ buffer.reset();
214
+ const header = new GlbHeader(buffer);
215
+ if (!header.isValid)
216
+ return undefined;
217
+ version = header.version;
218
+ if (header.binaryChunk)
219
+ binaryData = new Uint8Array(source.buffer, source.byteOffset + header.binaryChunk.offset, header.binaryChunk.length);
220
+ try {
221
+ const jsonBytes = new Uint8Array(source.buffer, source.byteOffset + header.jsonChunk.offset, header.jsonChunk.length);
222
+ const jsonStr = utf8ToString(jsonBytes);
223
+ if (undefined === jsonStr)
224
+ return undefined;
225
+ json = JSON.parse(jsonStr);
226
+ }
227
+ catch (_) {
228
+ return undefined;
229
+ }
230
+ }
212
231
  }
213
- catch (e) {
214
- return undefined;
232
+ else {
233
+ version = 2; // ###TODO verify against source.asset?.version
234
+ json = source;
215
235
  }
236
+ // asset is required in glTF 2, optional in glTF 1
237
+ const asset = JsonUtils.asObject(json.asset);
238
+ if (version === 2 && !asset)
239
+ return undefined;
240
+ const glTF = {
241
+ asset,
242
+ scene: JsonUtils.asString(json.scene),
243
+ extensions: JsonUtils.asObject(json.extensions),
244
+ extensionsUsed: JsonUtils.asArray(json.extensionsUsed),
245
+ extensionsRequired: JsonUtils.asArray(json.extensionsRequired),
246
+ accessors: JsonUtils.asObject(json.accessors),
247
+ buffers: JsonUtils.asObject(json.buffers),
248
+ bufferViews: JsonUtils.asObject(json.bufferViews),
249
+ images: JsonUtils.asObject(json.images),
250
+ materials: JsonUtils.asObject(json.materials),
251
+ meshes: JsonUtils.asObject(json.meshes),
252
+ nodes: JsonUtils.asObject(json.nodes),
253
+ samplers: JsonUtils.asObject(json.samplers),
254
+ scenes: JsonUtils.asObject(json.scenes),
255
+ textures: JsonUtils.asObject(json.textures),
256
+ techniques: JsonUtils.asObject(json.techniques),
257
+ };
258
+ return glTF.meshes ? new GltfReaderProps(glTF, version, yAxisUp, binaryData, baseUrl) : undefined;
216
259
  }
217
260
  }
218
261
  /** The GltfMeshData contains the raw GLTF mesh data. If the data is suitable to create a [[RealityMesh]] directly, basically in the quantized format produced by
@@ -294,15 +337,30 @@ class TransformStack {
294
337
  this._stack.pop();
295
338
  }
296
339
  }
340
+ function* traverseNodes(ids, nodes, traversed) {
341
+ for (const id of ids) {
342
+ if (traversed.has(id))
343
+ throw new Error("Cycle detected while traversing glTF nodes");
344
+ const node = nodes[id];
345
+ if (!node)
346
+ continue;
347
+ traversed.add(id);
348
+ yield node;
349
+ if (node.children)
350
+ for (const child of traverseNodes(node.children, nodes, traversed))
351
+ yield child;
352
+ }
353
+ }
297
354
  /** Deserializes [glTF](https://www.khronos.org/gltf/).
298
355
  * @internal
299
356
  */
300
357
  export class GltfReader {
301
358
  constructor(args) {
302
359
  var _a, _b, _c, _d, _e, _f, _g;
303
- this._binaryData = args.props.binaryData;
304
360
  this._glTF = args.props.glTF;
361
+ this._version = args.props.version;
305
362
  this._yAxisUp = args.props.yAxisUp;
363
+ this._baseUrl = args.props.baseUrl;
306
364
  const rtcCenter = (_b = (_a = args.props.glTF.extensions) === null || _a === void 0 ? void 0 : _a.CESIUM_RTC) === null || _b === void 0 ? void 0 : _b.center;
307
365
  if (rtcCenter && 3 === rtcCenter.length)
308
366
  if (0 !== rtcCenter[0] || 0 !== rtcCenter[1] || 0 !== rtcCenter[2])
@@ -314,6 +372,12 @@ export class GltfReader {
314
372
  this._canceled = args.shouldAbort;
315
373
  this._deduplicateVertices = (_e = args.deduplicateVertices) !== null && _e !== void 0 ? _e : false;
316
374
  this._vertexTableRequired = (_f = args.vertexTableRequired) !== null && _f !== void 0 ? _f : false;
375
+ const binaryData = args.props.binaryData;
376
+ if (binaryData) {
377
+ const buffer = this._buffers[this._version === 2 ? 0 : "binary_glTF"];
378
+ if (buffer && undefined === buffer.uri)
379
+ buffer.resolvedBuffer = binaryData;
380
+ }
317
381
  // The original implementation of GltfReader would process and produce graphics for every node in glTF.nodes.
318
382
  // What it's *supposed* to do is process the nodes in glTF.scenes[glTF.scene].nodes
319
383
  // Some nodes may not be referenced by the configured scene, or only indirectly via GltfNode.children.
@@ -329,9 +393,26 @@ export class GltfReader {
329
393
  get _meshes() { var _a; return (_a = this._glTF.meshes) !== null && _a !== void 0 ? _a : emptyDict; }
330
394
  get _accessors() { var _a; return (_a = this._glTF.accessors) !== null && _a !== void 0 ? _a : emptyDict; }
331
395
  get _bufferViews() { var _a; return (_a = this._glTF.bufferViews) !== null && _a !== void 0 ? _a : emptyDict; }
332
- get _materialValues() { var _a; return (_a = this._glTF.materials) !== null && _a !== void 0 ? _a : emptyDict; }
396
+ get _materials() { var _a; return (_a = this._glTF.materials) !== null && _a !== void 0 ? _a : emptyDict; }
397
+ get _samplers() { var _a; return (_a = this._glTF.samplers) !== null && _a !== void 0 ? _a : emptyDict; }
398
+ get _textures() { var _a; return (_a = this._glTF.textures) !== null && _a !== void 0 ? _a : emptyDict; }
399
+ get _images() { var _a; return (_a = this._glTF.images) !== null && _a !== void 0 ? _a : emptyDict; }
400
+ get _buffers() { var _a; return (_a = this._glTF.buffers) !== null && _a !== void 0 ? _a : emptyDict; }
333
401
  get _isCanceled() { return undefined !== this._canceled && this._canceled(this); }
334
402
  get _isVolumeClassifier() { return BatchType.VolumeClassifier === this._type; }
403
+ /** Traverse the nodes specified by their Ids, recursing into their child nodes.
404
+ * @param nodeIds The Ids of the nodes to traverse.
405
+ * @throws Error if a node appears more than once during traversal
406
+ */
407
+ traverseNodes(nodeIds) {
408
+ return traverseNodes(nodeIds, this._nodes, new Set());
409
+ }
410
+ /** Traverse the nodes specified by their scene, recursing into their child nodes.
411
+ * @throws Error if a node appears more than once during traversal
412
+ */
413
+ traverseScene() {
414
+ return this.traverseNodes(this._sceneNodes);
415
+ }
335
416
  readGltfAndCreateGraphics(isLeaf, featureTable, contentRange, transformToRoot, pseudoRtcBias, instances) {
336
417
  var _a;
337
418
  if (this._isCanceled)
@@ -486,10 +567,16 @@ export class GltfReader {
486
567
  getBufferView(json, accessorName) {
487
568
  try {
488
569
  const accessorValue = JsonUtils.asString(json[accessorName]);
489
- const accessor = 0 < accessorValue.length ? JsonUtils.asObject(this._accessors[accessorValue]) : undefined;
490
- const bufferViewAccessorValue = undefined !== accessor ? JsonUtils.asString(accessor.bufferView) : "";
491
- const bufferView = 0 < bufferViewAccessorValue.length ? JsonUtils.asObject(this._bufferViews[bufferViewAccessorValue]) : undefined;
492
- if (undefined === accessor)
570
+ const accessor = accessorValue ? this._accessors[accessorValue] : undefined;
571
+ if (!accessor)
572
+ return undefined;
573
+ const bufferViewAccessorValue = accessor.bufferView;
574
+ const bufferView = undefined !== bufferViewAccessorValue ? this._bufferViews[bufferViewAccessorValue] : undefined;
575
+ if (!bufferView || undefined === bufferView.buffer)
576
+ return undefined;
577
+ const buffer = this._buffers[bufferView.buffer];
578
+ const bufferData = buffer === null || buffer === void 0 ? void 0 : buffer.resolvedBuffer;
579
+ if (!bufferData)
493
580
  return undefined;
494
581
  const type = accessor.componentType;
495
582
  let dataSize = 0;
@@ -520,8 +607,8 @@ export class GltfReader {
520
607
  const offset = ((bufferView && bufferView.byteOffset) ? bufferView.byteOffset : 0) + (accessor.byteOffset ? accessor.byteOffset : 0);
521
608
  const length = byteStride * accessor.count;
522
609
  // If the data is misaligned (Scalable mesh tile publisher) use slice to copy -- else use subarray.
523
- // assert(0 === offset % dataSize);
524
- const bytes = (0 === (this._binaryData.byteOffset + offset) % dataSize) ? this._binaryData.subarray(offset, offset + length) : this._binaryData.slice(offset, offset + length);
610
+ const aligned = 0 === (bufferData.byteOffset + offset) % dataSize;
611
+ const bytes = aligned ? bufferData.subarray(offset, offset + length) : bufferData.slice(offset, offset + length);
525
612
  return new GltfBufferView(bytes, accessor.count, type, accessor, byteStride / dataSize);
526
613
  }
527
614
  catch (e) {
@@ -580,8 +667,8 @@ export class GltfReader {
580
667
  var _a, _b, _c, _d, _e, _f;
581
668
  const materialName = JsonUtils.asString(primitive.material);
582
669
  const hasBakedLighting = undefined === primitive.attributes.NORMAL;
583
- const material = 0 < materialName.length ? this._materialValues[materialName] : undefined;
584
- const displayParams = this.createDisplayParams(material, hasBakedLighting);
670
+ const material = 0 < materialName.length ? this._materials[materialName] : undefined;
671
+ const displayParams = material ? this.createDisplayParams(material, hasBakedLighting) : undefined;
585
672
  if (undefined === displayParams)
586
673
  return undefined;
587
674
  let primitiveType = -1;
@@ -600,7 +687,6 @@ export class GltfReader {
600
687
  assert(false);
601
688
  return undefined;
602
689
  }
603
- const isPlanar = JsonUtils.asBool(primitive.isPlanar);
604
690
  const isVolumeClassifier = this._isVolumeClassifier;
605
691
  const meshPrimitive = Mesh.create({
606
692
  displayParams,
@@ -608,7 +694,7 @@ export class GltfReader {
608
694
  type: primitiveType,
609
695
  range: Range3d.createNull(),
610
696
  is2d: !this._is3d,
611
- isPlanar,
697
+ isPlanar: false,
612
698
  hasBakedLighting,
613
699
  isVolumeClassifier,
614
700
  });
@@ -834,12 +920,13 @@ export class GltfReader {
834
920
  }
835
921
  readUVParams(mesh, json, accessorName) {
836
922
  const view = this.getBufferView(json, accessorName);
837
- let data;
838
923
  if (view === undefined)
839
924
  return false;
840
925
  switch (view.type) {
841
926
  case GltfDataType.Float: {
842
- data = this.readBufferDataFloat(json, accessorName);
927
+ const data = this.readBufferDataFloat(json, accessorName);
928
+ if (!data)
929
+ return false;
843
930
  mesh.uvRange = Range2d.createNull();
844
931
  for (let i = 0; i < data.count; i++) {
845
932
  const index = view.stride * i; // 2 float per param...
@@ -914,14 +1001,91 @@ export class GltfReader {
914
1001
  polylines.push(new MeshPolyline(indices));
915
1002
  return true;
916
1003
  }
917
- async loadTextures() {
1004
+ async resolveResources() {
1005
+ // ###TODO traverse the scene nodes to find resources referenced by them, instead of resolving everything - some resources may not
1006
+ // be required for the scene.
1007
+ const promises = [];
1008
+ try {
1009
+ for (const buffer of dictionaryIterator(this._buffers))
1010
+ if (!buffer.resolvedBuffer)
1011
+ promises.push(this.resolveBuffer(buffer));
1012
+ await Promise.all(promises);
1013
+ if (this._isCanceled)
1014
+ return;
1015
+ promises.length = 0;
1016
+ for (const image of dictionaryIterator(this._images))
1017
+ if (!image.resolvedImage)
1018
+ promises.push(this.resolveImage(image));
1019
+ await Promise.all(promises);
1020
+ if (this._isCanceled)
1021
+ return;
1022
+ this.resolveTextures();
1023
+ }
1024
+ catch (_) {
1025
+ }
1026
+ }
1027
+ resolveUrl(uri) {
1028
+ try {
1029
+ return new URL(uri, this._baseUrl).toString();
1030
+ }
1031
+ catch (_) {
1032
+ return undefined;
1033
+ }
1034
+ }
1035
+ async resolveBuffer(buffer) {
1036
+ if (buffer.resolvedBuffer || undefined === buffer.uri)
1037
+ return;
1038
+ try {
1039
+ const url = this.resolveUrl(buffer.uri);
1040
+ const response = url ? await fetch(url) : undefined;
1041
+ if (this._isCanceled)
1042
+ return;
1043
+ const data = await (response === null || response === void 0 ? void 0 : response.arrayBuffer());
1044
+ if (this._isCanceled)
1045
+ return;
1046
+ if (data)
1047
+ buffer.resolvedBuffer = new Uint8Array(data);
1048
+ }
1049
+ catch (_) {
1050
+ //
1051
+ }
1052
+ }
1053
+ async resolveImage(image) {
1054
+ var _a, _b, _c;
1055
+ if (image.resolvedImage)
1056
+ return;
1057
+ const bvSrc = undefined !== image.bufferView ? image : (_a = image.extensions) === null || _a === void 0 ? void 0 : _a.KHR_binary_glTF;
1058
+ if (undefined !== (bvSrc === null || bvSrc === void 0 ? void 0 : bvSrc.bufferView)) {
1059
+ const format = undefined !== bvSrc.mimeType ? getImageSourceFormatForMimeType(bvSrc.mimeType) : undefined;
1060
+ const bufferView = this._bufferViews[bvSrc.bufferView];
1061
+ if (undefined === format || !bufferView || !bufferView.byteLength || bufferView.byteLength < 0)
1062
+ return;
1063
+ const bufferData = (_b = this._buffers[bufferView.buffer]) === null || _b === void 0 ? void 0 : _b.resolvedBuffer;
1064
+ if (!bufferData)
1065
+ return;
1066
+ const offset = (_c = bufferView.byteOffset) !== null && _c !== void 0 ? _c : 0;
1067
+ const bytes = bufferData.subarray(offset, offset + bufferView.byteLength);
1068
+ try {
1069
+ image.resolvedImage = await imageElementFromImageSource(new ImageSource(bytes, format));
1070
+ }
1071
+ catch (_) {
1072
+ //
1073
+ }
1074
+ return;
1075
+ }
1076
+ const url = undefined !== image.uri ? this.resolveUrl(image.uri) : undefined;
1077
+ if (undefined !== url)
1078
+ image.resolvedImage = await tryImageElementFromUrl(url);
1079
+ }
1080
+ resolveTextures() {
918
1081
  var _a, _b;
919
1082
  if (undefined === this._glTF.textures)
920
1083
  return;
1084
+ // ###TODO this seems pretty hacky, and won't work for glTF 2.0 even if the KHR_techniques_webgl extension is used...
921
1085
  const transparentTextures = new Set();
922
1086
  if (this._glTF.techniques) {
923
- for (const name of Object.keys(this._materialValues)) {
924
- const material = this._materialValues[name];
1087
+ for (const name of Object.keys(this._materials)) {
1088
+ const material = this._materials[name];
925
1089
  if (material && isGltf1Material(material) && undefined !== material.technique && undefined !== ((_a = material.values) === null || _a === void 0 ? void 0 : _a.tex)) {
926
1090
  const technique = this._glTF.techniques[material.technique];
927
1091
  if ((_b = technique === null || technique === void 0 ? void 0 : technique.states) === null || _b === void 0 ? void 0 : _b.enable) {
@@ -935,74 +1099,42 @@ export class GltfReader {
935
1099
  }
936
1100
  }
937
1101
  }
938
- const promises = new Array();
939
- for (const name of Object.keys(this._glTF.textures))
940
- promises.push(this.loadTexture(name, transparentTextures.has(name)));
941
- if (promises.length > 0)
942
- await Promise.all(promises);
943
- }
944
- async loadTextureImage(imageJson, samplerJson, isTransparent) {
945
- var _a;
946
- try {
947
- const binaryImageJson = (imageJson.extensions && imageJson.extensions.KHR_binary_glTF) ? JsonUtils.asObject(imageJson.extensions.KHR_binary_glTF) : imageJson;
948
- const bufferView = this._bufferViews[binaryImageJson.bufferView];
949
- if (!bufferView || undefined === bufferView.byteLength || bufferView.byteLength <= 0)
950
- return undefined;
951
- const mimeType = JsonUtils.asString(binaryImageJson.mimeType);
952
- const format = getImageSourceFormatForMimeType(mimeType);
953
- if (undefined === format)
954
- return undefined;
955
- let textureType = RenderTexture.Type.Normal;
956
- if (undefined !== samplerJson &&
957
- (undefined !== samplerJson.wrapS || undefined !== samplerJson.wrapT))
958
- textureType = RenderTexture.Type.TileSection;
959
- const offset = (_a = bufferView.byteOffset) !== null && _a !== void 0 ? _a : 0;
960
- /* -----------------------------------
961
- const jpegArray = this._binaryData.slice(offset, offset + bufferView.byteLength);
962
- const jpegArrayBuffer = jpegArray.buffer;
963
- const workerOp = new ImageDecodeWorkerOperation(jpegArrayBuffer, mimeType);
964
- try {
965
- const imageBitmap = await GltfReader.webWorkerManager.queueOperation(workerOp)
966
- return this._isCanceled ? undefined : this._system.createTextureFromImage(imageBitmap, isTransparent && ImageSourceFormat.Png === format, this._iModel, textureParams))
967
- } catch {
968
- return undefined;
1102
+ for (const node of this.traverseScene()) {
1103
+ for (const meshId of getNodeMeshIds(node)) {
1104
+ const mesh = this._meshes[meshId];
1105
+ if (!(mesh === null || mesh === void 0 ? void 0 : mesh.primitives))
1106
+ continue;
1107
+ for (const primitive of mesh.primitives) {
1108
+ const material = undefined !== primitive.material ? this._materials[primitive.material] : undefined;
1109
+ const textureId = material ? this.extractTextureId(material) : undefined;
1110
+ if (undefined !== textureId)
1111
+ this.resolveTexture(textureId, transparentTextures.has(textureId));
969
1112
  }
970
- ------------------------------------- */
971
- const bytes = this._binaryData.subarray(offset, offset + bufferView.byteLength);
972
- const imageSource = new ImageSource(bytes, format);
973
- try {
974
- const image = await imageElementFromImageSource(imageSource);
975
- if (this._isCanceled)
976
- return undefined;
977
- return this._system.createTexture({
978
- type: textureType,
979
- image: {
980
- source: image,
981
- transparency: isTransparent && ImageSourceFormat.Png === format ? TextureTransparency.Translucent : TextureTransparency.Opaque,
982
- },
983
- });
984
- }
985
- catch {
986
- return undefined;
987
1113
  }
988
1114
  }
989
- catch (e) {
990
- return undefined;
991
- }
992
1115
  }
993
- async loadTexture(textureId, isTransparent) {
994
- if (!this._glTF.textures || !this._glTF.images)
1116
+ resolveTexture(textureId, isTransparent) {
1117
+ var _a;
1118
+ const texture = this._textures[textureId];
1119
+ if (!texture || texture.resolvedTexture || undefined === texture.source)
995
1120
  return;
996
- const textureJson = JsonUtils.asObject(this._glTF.textures[textureId]);
997
- if (undefined === textureJson)
1121
+ const image = (_a = this._images[texture.source]) === null || _a === void 0 ? void 0 : _a.resolvedImage;
1122
+ if (!image)
998
1123
  return;
999
- const texture = await this.loadTextureImage(this._glTF.images[textureJson.source], this._glTF.samplers ? this._glTF.samplers[textureJson.sampler] : undefined, isTransparent);
1000
- textureJson.renderTexture = texture;
1124
+ const samplerId = texture.sampler;
1125
+ const sampler = undefined !== samplerId ? this._samplers[samplerId] : undefined;
1126
+ const textureType = undefined !== (sampler === null || sampler === void 0 ? void 0 : sampler.wrapS) || undefined !== (sampler === null || sampler === void 0 ? void 0 : sampler.wrapT) ? RenderTexture.Type.TileSection : RenderTexture.Type.Normal;
1127
+ texture.resolvedTexture = this._system.createTexture({
1128
+ type: textureType,
1129
+ image: {
1130
+ source: image,
1131
+ transparency: isTransparent ? TextureTransparency.Translucent : TextureTransparency.Opaque,
1132
+ },
1133
+ });
1001
1134
  }
1002
1135
  findTextureMapping(textureId) {
1003
- const textureJson = this._glTF.textures ? JsonUtils.asObject(this._glTF.textures[textureId]) : undefined;
1004
- const texture = undefined !== textureJson ? textureJson.renderTexture : undefined;
1005
- return undefined !== texture ? new TextureMapping(texture, new TextureMapping.Params()) : undefined;
1136
+ const texture = this._textures[textureId];
1137
+ return (texture === null || texture === void 0 ? void 0 : texture.resolvedTexture) ? new TextureMapping(texture.resolvedTexture, new TextureMapping.Params()) : undefined;
1006
1138
  }
1007
1139
  }
1008
1140
  /** Produce a [[RenderGraphic]] from a [glTF](https://www.khronos.org/gltf/) asset suitable for use in [view decorations]($docs/learning/frontend/ViewDecorations).
@@ -1014,16 +1146,17 @@ export class GltfReader {
1014
1146
  * @public
1015
1147
  */
1016
1148
  export async function readGltfGraphics(args) {
1017
- const stream = new ByteStream(args.gltf.buffer);
1018
- const props = GltfReaderProps.create(stream, true); // glTF supports exactly one coordinate system with y axis up.
1019
- const reader = props ? new Reader(props, args) : undefined;
1149
+ const props = GltfReaderProps.create(args.gltf, true, args.baseUrl); // glTF supports exactly one coordinate system with y axis up.
1150
+ const reader = props ? new GltfGraphicsReader(props, args) : undefined;
1020
1151
  if (!reader)
1021
1152
  return undefined;
1022
1153
  const result = await reader.read();
1023
1154
  return result.graphic;
1024
1155
  }
1025
- /** Implements [[readGltfGraphics]]. */
1026
- class Reader extends GltfReader {
1156
+ /** Implements [[readGltfGraphics]]. Exported strictly for tests.
1157
+ * @internal
1158
+ */
1159
+ export class GltfGraphicsReader extends GltfReader {
1027
1160
  constructor(props, args) {
1028
1161
  var _a, _b, _c;
1029
1162
  super({
@@ -1031,6 +1164,7 @@ class Reader extends GltfReader {
1031
1164
  iModel: args.iModel,
1032
1165
  vertexTableRequired: true,
1033
1166
  });
1167
+ this.binaryData = props.binaryData;
1034
1168
  const pickableId = (_a = args.pickableOptions) === null || _a === void 0 ? void 0 : _a.id;
1035
1169
  if (pickableId) {
1036
1170
  this._featureTable = new FeatureTable(1, (_c = (_b = args.pickableOptions) === null || _b === void 0 ? void 0 : _b.modelId) !== null && _c !== void 0 ? _c : pickableId, BatchType.Primary);
@@ -1038,8 +1172,12 @@ class Reader extends GltfReader {
1038
1172
  }
1039
1173
  }
1040
1174
  async read() {
1041
- await this.loadTextures();
1175
+ await this.resolveResources();
1042
1176
  return this.readGltfAndCreateGraphics(true, this._featureTable, undefined);
1043
1177
  }
1178
+ get nodes() { return this._nodes; }
1179
+ get scenes() { var _a; return (_a = this._glTF.scenes) !== null && _a !== void 0 ? _a : emptyDict; }
1180
+ get sceneNodes() { return this._sceneNodes; }
1181
+ get textures() { return this._textures; }
1044
1182
  }
1045
1183
  //# sourceMappingURL=GltfReader.js.map