@itwin/core-frontend 4.0.0-dev.41 → 4.0.0-dev.46

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 (71) hide show
  1. package/lib/cjs/core-frontend.d.ts +1 -0
  2. package/lib/cjs/core-frontend.d.ts.map +1 -1
  3. package/lib/cjs/core-frontend.js +1 -0
  4. package/lib/cjs/core-frontend.js.map +1 -1
  5. package/lib/cjs/gltf/GltfModel.d.ts +91 -0
  6. package/lib/cjs/gltf/GltfModel.d.ts.map +1 -0
  7. package/lib/cjs/gltf/GltfModel.js +10 -0
  8. package/lib/cjs/gltf/GltfModel.js.map +1 -0
  9. package/lib/cjs/gltf/GltfParser.d.ts +26 -0
  10. package/lib/cjs/gltf/GltfParser.d.ts.map +1 -0
  11. package/lib/cjs/gltf/GltfParser.js +352 -0
  12. package/lib/cjs/gltf/GltfParser.js.map +1 -0
  13. package/lib/cjs/gltf/GltfSchema.d.ts +557 -0
  14. package/lib/cjs/gltf/GltfSchema.d.ts.map +1 -0
  15. package/lib/cjs/gltf/GltfSchema.js +138 -0
  16. package/lib/cjs/gltf/GltfSchema.js.map +1 -0
  17. package/lib/cjs/render/GraphicBuilder.d.ts +5 -2
  18. package/lib/cjs/render/GraphicBuilder.d.ts.map +1 -1
  19. package/lib/cjs/render/GraphicBuilder.js +12 -3
  20. package/lib/cjs/render/GraphicBuilder.js.map +1 -1
  21. package/lib/cjs/tile/B3dmReader.d.ts +2 -1
  22. package/lib/cjs/tile/B3dmReader.d.ts.map +1 -1
  23. package/lib/cjs/tile/B3dmReader.js +2 -1
  24. package/lib/cjs/tile/B3dmReader.js.map +1 -1
  25. package/lib/cjs/tile/GltfReader.d.ts +13 -420
  26. package/lib/cjs/tile/GltfReader.d.ts.map +1 -1
  27. package/lib/cjs/tile/GltfReader.js +118 -192
  28. package/lib/cjs/tile/GltfReader.js.map +1 -1
  29. package/lib/cjs/tile/RealityTileLoader.d.ts.map +1 -1
  30. package/lib/cjs/tile/RealityTileLoader.js +14 -2
  31. package/lib/cjs/tile/RealityTileLoader.js.map +1 -1
  32. package/lib/cjs/tile/Tile.d.ts +10 -1
  33. package/lib/cjs/tile/Tile.d.ts.map +1 -1
  34. package/lib/cjs/tile/Tile.js +22 -2
  35. package/lib/cjs/tile/Tile.js.map +1 -1
  36. package/lib/esm/core-frontend.d.ts +1 -0
  37. package/lib/esm/core-frontend.d.ts.map +1 -1
  38. package/lib/esm/core-frontend.js +1 -0
  39. package/lib/esm/core-frontend.js.map +1 -1
  40. package/lib/esm/gltf/GltfModel.d.ts +91 -0
  41. package/lib/esm/gltf/GltfModel.d.ts.map +1 -0
  42. package/lib/esm/gltf/GltfModel.js +9 -0
  43. package/lib/esm/gltf/GltfModel.js.map +1 -0
  44. package/lib/esm/gltf/GltfParser.d.ts +26 -0
  45. package/lib/esm/gltf/GltfParser.d.ts.map +1 -0
  46. package/lib/esm/gltf/GltfParser.js +329 -0
  47. package/lib/esm/gltf/GltfParser.js.map +1 -0
  48. package/lib/esm/gltf/GltfSchema.d.ts +557 -0
  49. package/lib/esm/gltf/GltfSchema.d.ts.map +1 -0
  50. package/lib/esm/gltf/GltfSchema.js +131 -0
  51. package/lib/esm/gltf/GltfSchema.js.map +1 -0
  52. package/lib/esm/render/GraphicBuilder.d.ts +5 -2
  53. package/lib/esm/render/GraphicBuilder.d.ts.map +1 -1
  54. package/lib/esm/render/GraphicBuilder.js +13 -4
  55. package/lib/esm/render/GraphicBuilder.js.map +1 -1
  56. package/lib/esm/tile/B3dmReader.d.ts +2 -1
  57. package/lib/esm/tile/B3dmReader.d.ts.map +1 -1
  58. package/lib/esm/tile/B3dmReader.js +2 -1
  59. package/lib/esm/tile/B3dmReader.js.map +1 -1
  60. package/lib/esm/tile/GltfReader.d.ts +13 -420
  61. package/lib/esm/tile/GltfReader.d.ts.map +1 -1
  62. package/lib/esm/tile/GltfReader.js +75 -149
  63. package/lib/esm/tile/GltfReader.js.map +1 -1
  64. package/lib/esm/tile/RealityTileLoader.d.ts.map +1 -1
  65. package/lib/esm/tile/RealityTileLoader.js +14 -2
  66. package/lib/esm/tile/RealityTileLoader.js.map +1 -1
  67. package/lib/esm/tile/Tile.d.ts +10 -1
  68. package/lib/esm/tile/Tile.d.ts.map +1 -1
  69. package/lib/esm/tile/Tile.js +22 -2
  70. package/lib/esm/tile/Tile.js.map +1 -1
  71. package/package.json +22 -22
@@ -16,102 +16,7 @@ import { RealityMeshParams } from "../render/RealityMeshParams";
16
16
  import { DisplayParams } from "../render/primitives/DisplayParams";
17
17
  import { Mesh } from "../render/primitives/mesh/MeshPrimitives";
18
18
  import { Triangle } from "../render/primitives/Primitives";
19
- /* eslint-disable no-restricted-syntax */
20
- /** Enumerates the types of [[GltfMeshPrimitive]] topologies. */
21
- var GltfMeshMode;
22
- (function (GltfMeshMode) {
23
- GltfMeshMode[GltfMeshMode["Points"] = 0] = "Points";
24
- GltfMeshMode[GltfMeshMode["Lines"] = 1] = "Lines";
25
- GltfMeshMode[GltfMeshMode["LineStrip"] = 3] = "LineStrip";
26
- GltfMeshMode[GltfMeshMode["Triangles"] = 4] = "Triangles";
27
- /** Not currently supported. */
28
- GltfMeshMode[GltfMeshMode["TriangleStrip"] = 5] = "TriangleStrip";
29
- /** Not currently supported. */
30
- GltfMeshMode[GltfMeshMode["TriangleFan"] = 6] = "TriangleFan";
31
- })(GltfMeshMode || (GltfMeshMode = {}));
32
- /** Enumerates the basic data types supported by accessors, material values, technique uniforms, etc.
33
- * @internal
34
- */
35
- export var GltfDataType;
36
- (function (GltfDataType) {
37
- GltfDataType[GltfDataType["SignedByte"] = 5120] = "SignedByte";
38
- GltfDataType[GltfDataType["UnsignedByte"] = 5121] = "UnsignedByte";
39
- GltfDataType[GltfDataType["SignedShort"] = 5122] = "SignedShort";
40
- GltfDataType[GltfDataType["UnsignedShort"] = 5123] = "UnsignedShort";
41
- GltfDataType[GltfDataType["UInt32"] = 5125] = "UInt32";
42
- GltfDataType[GltfDataType["Float"] = 5126] = "Float";
43
- GltfDataType[GltfDataType["Rgb"] = 6407] = "Rgb";
44
- GltfDataType[GltfDataType["Rgba"] = 6408] = "Rgba";
45
- GltfDataType[GltfDataType["IntVec2"] = 35667] = "IntVec2";
46
- GltfDataType[GltfDataType["IntVec3"] = 35668] = "IntVec3";
47
- GltfDataType[GltfDataType["FloatVec2"] = 35664] = "FloatVec2";
48
- GltfDataType[GltfDataType["FloatVec3"] = 35665] = "FloatVec3";
49
- GltfDataType[GltfDataType["FloatVec4"] = 35666] = "FloatVec4";
50
- GltfDataType[GltfDataType["FloatMat3"] = 35675] = "FloatMat3";
51
- GltfDataType[GltfDataType["FloatMat4"] = 35676] = "FloatMat4";
52
- GltfDataType[GltfDataType["Sampler2d"] = 35678] = "Sampler2d";
53
- })(GltfDataType || (GltfDataType = {}));
54
- /** @internal */
55
- var GltfMagFilter;
56
- (function (GltfMagFilter) {
57
- GltfMagFilter[GltfMagFilter["Nearest"] = 9728] = "Nearest";
58
- GltfMagFilter[GltfMagFilter["Linear"] = 9729] = "Linear";
59
- })(GltfMagFilter || (GltfMagFilter = {}));
60
- /** @internal */
61
- var GltfMinFilter;
62
- (function (GltfMinFilter) {
63
- GltfMinFilter[GltfMinFilter["Nearest"] = 9728] = "Nearest";
64
- GltfMinFilter[GltfMinFilter["Linear"] = 9729] = "Linear";
65
- GltfMinFilter[GltfMinFilter["NearestMipMapNearest"] = 9984] = "NearestMipMapNearest";
66
- GltfMinFilter[GltfMinFilter["LinearMipMapNearest"] = 9985] = "LinearMipMapNearest";
67
- GltfMinFilter[GltfMinFilter["NearestMipMapLinear"] = 9986] = "NearestMipMapLinear";
68
- GltfMinFilter[GltfMinFilter["LinearMipMapLinear"] = 9987] = "LinearMipMapLinear";
69
- })(GltfMinFilter || (GltfMinFilter = {}));
70
- /** Describes how texture coordinates outside of the range [0..1] are handled.
71
- * @internal
72
- */
73
- export var GltfWrapMode;
74
- (function (GltfWrapMode) {
75
- GltfWrapMode[GltfWrapMode["ClampToEdge"] = 33071] = "ClampToEdge";
76
- GltfWrapMode[GltfWrapMode["MirroredRepeat"] = 33648] = "MirroredRepeat";
77
- GltfWrapMode[GltfWrapMode["Repeat"] = 10497] = "Repeat";
78
- })(GltfWrapMode || (GltfWrapMode = {}));
79
- /** Describes the intended target of a [[GltfBufferViewProps]]. */
80
- var GltfBufferTarget;
81
- (function (GltfBufferTarget) {
82
- GltfBufferTarget[GltfBufferTarget["ArrayBuffer"] = 34962] = "ArrayBuffer";
83
- GltfBufferTarget[GltfBufferTarget["ElementArrayBuffer"] = 24963] = "ElementArrayBuffer";
84
- })(GltfBufferTarget || (GltfBufferTarget = {}));
85
- function* dictionaryIterator(dict) {
86
- if (Array.isArray(dict)) {
87
- for (const elem of dict)
88
- yield elem;
89
- }
90
- else {
91
- for (const key of Object.keys(dict)) {
92
- const value = dict[key];
93
- if (undefined !== value)
94
- yield value;
95
- }
96
- }
97
- }
98
- function getNodeMeshIds(node) {
99
- if (undefined !== node.meshes)
100
- return typeof node.meshes === "string" ? [node.meshes] : node.meshes;
101
- else if (undefined !== node.mesh)
102
- return [node.mesh];
103
- return [];
104
- }
105
- /** GL states that can be enabled by a [[GltfTechnique]]. Only those queried by this implementation are enumerated. */
106
- var GltfTechniqueState;
107
- (function (GltfTechniqueState) {
108
- /** Enables alpha blending. */
109
- GltfTechniqueState[GltfTechniqueState["Blend"] = 3042] = "Blend";
110
- })(GltfTechniqueState || (GltfTechniqueState = {}));
111
- function isGltf1Material(material) {
112
- const mat1 = material;
113
- return undefined !== mat1.technique || undefined !== mat1.values;
114
- }
19
+ import { getGltfNodeMeshIds, GltfDataType, gltfDictionaryIterator, GltfMeshMode, GltfTechniqueState, GltfWrapMode, isGltf1Material, traverseGltfNodes, } from "../gltf/GltfSchema";
115
20
  /**
116
21
  * A chunk of binary data exposed as a typed array.
117
22
  * The count member indicates how many elements exist. This may be less than this.buffer.length due to padding added to the
@@ -349,20 +254,6 @@ class TransformStack {
349
254
  this._stack.pop();
350
255
  }
351
256
  }
352
- function* traverseNodes(ids, nodes, traversed) {
353
- for (const id of ids) {
354
- if (traversed.has(id))
355
- throw new Error("Cycle detected while traversing glTF nodes");
356
- const node = nodes[id];
357
- if (!node)
358
- continue;
359
- traversed.add(id);
360
- yield node;
361
- if (node.children)
362
- for (const child of traverseNodes(node.children, nodes, traversed))
363
- yield child;
364
- }
365
- }
366
257
  function compareTextureKeys(lhs, rhs) {
367
258
  const cmp = compareBooleans(lhs.isTransparent, rhs.isTransparent);
368
259
  if (0 !== cmp)
@@ -436,7 +327,7 @@ export class GltfReader {
436
327
  * @throws Error if a node appears more than once during traversal
437
328
  */
438
329
  traverseNodes(nodeIds) {
439
- return traverseNodes(nodeIds, this._nodes, new Set());
330
+ return traverseGltfNodes(nodeIds, this._nodes, new Set());
440
331
  }
441
332
  /** Traverse the nodes specified by their scene, recursing into their child nodes.
442
333
  * @throws Error if a node appears more than once during traversal
@@ -558,7 +449,7 @@ export class GltfReader {
558
449
  let thisBias;
559
450
  if (undefined !== pseudoRtcBias)
560
451
  thisBias = (undefined === thisTransform) ? pseudoRtcBias : thisTransform.matrix.multiplyInverse(pseudoRtcBias);
561
- for (const meshKey of getNodeMeshIds(node)) {
452
+ for (const meshKey of getGltfNodeMeshIds(node)) {
562
453
  const nodeMesh = this._meshes[meshKey];
563
454
  if (nodeMesh?.primitives) {
564
455
  const meshes = this.readMeshPrimitives(node, featureTable, thisTransform, thisBias);
@@ -776,7 +667,7 @@ export class GltfReader {
776
667
  }
777
668
  readMeshPrimitives(node, featureTable, thisTransform, thisBias) {
778
669
  const meshes = [];
779
- for (const meshKey of getNodeMeshIds(node)) {
670
+ for (const meshKey of getGltfNodeMeshIds(node)) {
780
671
  const nodeMesh = this._meshes[meshKey];
781
672
  if (nodeMesh?.primitives) {
782
673
  for (const primitive of nodeMesh.primitives) {
@@ -832,30 +723,43 @@ export class GltfReader {
832
723
  quantizePositions: true,
833
724
  });
834
725
  const mesh = new GltfMeshData(meshPrimitive);
835
- // We don't have real colormap - just load material color. This will be used if non-Bentley
836
- // tile or fit the color table is uniform. For a non-Bentley, non-Uniform, we'll set the
837
- // uv parameters to pick the colors out of the color map texture.
838
- meshPrimitive.colorMap.insert(displayParams.fillColor.tbgr); // White...
839
- const colorIndices = this.readBufferData16(primitive.attributes, "_COLORINDEX");
840
- if (undefined !== colorIndices && material) {
841
- let texStep;
842
- if (isGltf1Material(material))
843
- texStep = material.values?.texStep;
844
- else
845
- texStep = material.extensions?.KHR_techniques_webgl?.values?.u_texStep;
846
- if (texStep) {
847
- const uvParams = [];
848
- for (let i = 0; i < colorIndices.count; i++)
849
- uvParams.push(new Point2d(texStep[1] + texStep[0] * colorIndices.buffer[i], .5));
850
- const paramList = QPoint2dList.fromPoints(uvParams);
851
- mesh.uvs = paramList.toTypedArray();
852
- mesh.uvQParams = paramList.params;
726
+ // ###TODO_GLTF: There can be more than one color attribute; COLOR_0 might not be the one we want.
727
+ if (!this.readColors(mesh, primitive.attributes, "COLOR_0")) {
728
+ // We don't have real colormap - just load material color. This will be used if non-Bentley
729
+ // tile or fit the color table is uniform. For a non-Bentley, non-Uniform, we'll set the
730
+ // uv parameters to pick the colors out of the color map texture.
731
+ meshPrimitive.colorMap.insert(displayParams.fillColor.tbgr); // White...
732
+ // _COLORINDEX is an ancient holdover from glTF 1.0 and Bimium...unlikely to actually encounter it in the wild.
733
+ const colorIndices = this.readBufferData16(primitive.attributes, "_COLORINDEX");
734
+ if (undefined !== colorIndices && material) {
735
+ let texStep;
736
+ if (isGltf1Material(material))
737
+ texStep = material.values?.texStep;
738
+ else
739
+ texStep = material.extensions?.KHR_techniques_webgl?.values?.u_texStep;
740
+ if (texStep) {
741
+ const uvParams = [];
742
+ for (let i = 0; i < colorIndices.count; i++)
743
+ uvParams.push(new Point2d(texStep[1] + texStep[0] * colorIndices.buffer[i], .5));
744
+ const paramList = QPoint2dList.fromPoints(uvParams);
745
+ mesh.uvs = paramList.toTypedArray();
746
+ mesh.uvQParams = paramList.params;
747
+ }
853
748
  }
854
749
  }
855
750
  const draco = primitive.extensions?.KHR_draco_mesh_compression;
856
751
  if (draco)
857
752
  return this.readDracoMeshPrimitive(mesh.primitive, draco) ? mesh : undefined;
858
753
  this.readBatchTable(mesh.primitive, primitive);
754
+ if (mesh.primitive.features) {
755
+ const features = this.readPrimitiveFeatures(primitive);
756
+ if (features) {
757
+ if (features instanceof Feature)
758
+ mesh.primitive.features.add(features, 1);
759
+ else
760
+ mesh.primitive.features.setIndices(features);
761
+ }
762
+ }
859
763
  if (!this.readVertices(mesh, primitive, pseudoRtcBias))
860
764
  return undefined;
861
765
  switch (primitiveType) {
@@ -1017,14 +921,12 @@ export class GltfReader {
1017
921
  else {
1018
922
  if (GltfDataType.UnsignedShort !== view.type)
1019
923
  return false;
1020
- const extensions = JsonUtils.asObject(view.accessor.extensions);
1021
- const quantized = undefined !== extensions ? JsonUtils.asObject(extensions.WEB3D_quantized_attributes) : undefined;
1022
- if (undefined === quantized)
1023
- return false;
1024
- const rangeMin = JsonUtils.asArray(quantized.decodedMin);
1025
- const rangeMax = JsonUtils.asArray(quantized.decodedMax);
1026
- if (undefined === rangeMin || undefined === rangeMax)
924
+ const quantized = view.accessor.extensions?.WEB3D_quantized_attributes;
925
+ const rangeMin = quantized?.decodedMin;
926
+ const rangeMax = quantized?.decodedMax;
927
+ if (!rangeMin || !rangeMax) // required by spec...
1027
928
  return false;
929
+ // ###TODO apply WEB3D_quantized_attributes.decodeMatrix? Have not encountered in the wild; glTF 1.0 only.
1028
930
  const buffer = view.toBufferData(GltfDataType.UnsignedShort);
1029
931
  if (undefined === buffer || !(buffer.buffer instanceof Uint16Array))
1030
932
  return false;
@@ -1061,6 +963,9 @@ export class GltfReader {
1061
963
  }
1062
964
  readBatchTable(_mesh, _json) {
1063
965
  }
966
+ readPrimitiveFeatures(_primitive) {
967
+ return undefined;
968
+ }
1064
969
  readMeshIndices(mesh, json) {
1065
970
  if (undefined !== json.indices) {
1066
971
  const data = this.readBufferData16(json, "indices") || this.readBufferData32(json, "indices");
@@ -1115,6 +1020,27 @@ export class GltfReader {
1115
1020
  return false;
1116
1021
  }
1117
1022
  }
1023
+ readColors(mesh, attribute, accessorName) {
1024
+ const view = this.getBufferView(attribute, accessorName);
1025
+ if (!view || (GltfDataType.Float !== view.type && GltfDataType.UnsignedByte !== view.type && GltfDataType.SignedByte !== view.type))
1026
+ return false;
1027
+ const data = view.toBufferData(view.type);
1028
+ if (!data)
1029
+ return false;
1030
+ const hasAlpha = "VEC4" === view.accessor.type;
1031
+ const factor = view.type === GltfDataType.Float ? 255 : 1;
1032
+ const rgbt = new Uint8Array(4);
1033
+ const color = new Uint32Array(rgbt.buffer);
1034
+ for (let i = 0; i < data.count; i++) {
1035
+ const index = view.stride * i;
1036
+ rgbt[0] = data.buffer[index] * factor;
1037
+ rgbt[1] = data.buffer[index + 1] * factor;
1038
+ rgbt[2] = data.buffer[index + 2] * factor;
1039
+ rgbt[3] = hasAlpha ? (255 - data.buffer[index + 3] * factor) : 0;
1040
+ mesh.primitive.colors.push(mesh.primitive.colorMap.insert(color[0]));
1041
+ }
1042
+ return true;
1043
+ }
1118
1044
  readUVParams(mesh, json, accessorName) {
1119
1045
  const view = this.getBufferView(json, accessorName);
1120
1046
  if (view === undefined)
@@ -1139,12 +1065,9 @@ export class GltfReader {
1139
1065
  return true;
1140
1066
  }
1141
1067
  case GltfDataType.UnsignedShort: {
1142
- const extensions = JsonUtils.asObject(view.accessor.extensions);
1143
- const quantized = undefined !== extensions ? JsonUtils.asObject(extensions.WEB3D_quantized_attributes) : undefined;
1144
- if (undefined === quantized)
1145
- return false;
1146
- const rangeMin = JsonUtils.asArray(quantized.decodedMin);
1147
- const rangeMax = JsonUtils.asArray(quantized.decodedMax);
1068
+ const quantized = view.accessor.extensions?.WEB3D_quantized_attributes;
1069
+ const rangeMin = quantized?.decodedMin;
1070
+ const rangeMax = quantized?.decodedMax;
1148
1071
  if (undefined === rangeMin || undefined === rangeMax)
1149
1072
  return false;
1150
1073
  const qData = view.toBufferData(GltfDataType.UnsignedShort);
@@ -1204,7 +1127,7 @@ export class GltfReader {
1204
1127
  // If any meshes are draco-compressed, dynamically load the decoder module and then decode the meshes.
1205
1128
  const dracoMeshes = [];
1206
1129
  for (const node of this.traverseScene()) {
1207
- for (const meshId of getNodeMeshIds(node)) {
1130
+ for (const meshId of getGltfNodeMeshIds(node)) {
1208
1131
  const mesh = this._meshes[meshId];
1209
1132
  if (mesh?.primitives)
1210
1133
  for (const primitive of mesh.primitives)
@@ -1228,14 +1151,14 @@ export class GltfReader {
1228
1151
  // be required for the scene.
1229
1152
  const promises = [];
1230
1153
  try {
1231
- for (const buffer of dictionaryIterator(this._buffers))
1154
+ for (const buffer of gltfDictionaryIterator(this._buffers))
1232
1155
  if (!buffer.resolvedBuffer)
1233
1156
  promises.push(this.resolveBuffer(buffer));
1234
1157
  await Promise.all(promises);
1235
1158
  if (this._isCanceled)
1236
1159
  return;
1237
1160
  promises.length = 0;
1238
- for (const image of dictionaryIterator(this._images))
1161
+ for (const image of gltfDictionaryIterator(this._images))
1239
1162
  if (!image.resolvedImage)
1240
1163
  promises.push(this.resolveImage(image));
1241
1164
  await Promise.all(promises);
@@ -1258,7 +1181,9 @@ export class GltfReader {
1258
1181
  }
1259
1182
  resolveUrl(uri) {
1260
1183
  try {
1261
- return new URL(uri, this._baseUrl).toString();
1184
+ const resolved = new URL(uri, this._baseUrl);
1185
+ resolved.search = this._baseUrl?.search ?? "";
1186
+ return resolved.toString();
1262
1187
  }
1263
1188
  catch (_) {
1264
1189
  return undefined;
@@ -1387,7 +1312,8 @@ export class GltfReader {
1387
1312
  * @public
1388
1313
  */
1389
1314
  export async function readGltfGraphics(args) {
1390
- const props = GltfReaderProps.create(args.gltf, true, args.baseUrl); // glTF supports exactly one coordinate system with y axis up.
1315
+ const baseUrl = typeof args.baseUrl === "string" ? new URL(args.baseUrl) : args.baseUrl;
1316
+ const props = GltfReaderProps.create(args.gltf, true, baseUrl); // glTF supports exactly one coordinate system with y axis up.
1391
1317
  const reader = props ? new GltfGraphicsReader(props, args) : undefined;
1392
1318
  if (!reader)
1393
1319
  return undefined;