@itwin/core-frontend 3.0.0-dev.170 → 3.0.0-dev.175
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/LICENSE.md +1 -1
- package/lib/cjs/IModelApp.js +1 -1
- package/lib/cjs/IModelApp.js.map +1 -1
- package/lib/cjs/render/primitives/Primitives.d.ts +1 -1
- package/lib/cjs/render/primitives/Primitives.d.ts.map +1 -1
- package/lib/cjs/render/primitives/Primitives.js.map +1 -1
- package/lib/cjs/tile/GltfReader.d.ts +29 -17
- package/lib/cjs/tile/GltfReader.d.ts.map +1 -1
- package/lib/cjs/tile/GltfReader.js +102 -78
- package/lib/cjs/tile/GltfReader.js.map +1 -1
- package/lib/esm/IModelApp.js +1 -1
- package/lib/esm/IModelApp.js.map +1 -1
- package/lib/esm/render/primitives/Primitives.d.ts +1 -1
- package/lib/esm/render/primitives/Primitives.d.ts.map +1 -1
- package/lib/esm/render/primitives/Primitives.js.map +1 -1
- package/lib/esm/tile/GltfReader.d.ts +29 -17
- package/lib/esm/tile/GltfReader.d.ts.map +1 -1
- package/lib/esm/tile/GltfReader.js +103 -79
- package/lib/esm/tile/GltfReader.js.map +1 -1
- package/package.json +22 -22
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/** @packageDocumentation
|
|
6
6
|
* @module Tiles
|
|
7
7
|
*/
|
|
8
|
-
import { assert, ByteStream, JsonUtils, utf8ToString } from "@itwin/core-bentley";
|
|
8
|
+
import { assert, ByteStream, compareBooleans, compareNumbers, compareStrings, Dictionary, JsonUtils, utf8ToString } from "@itwin/core-bentley";
|
|
9
9
|
import { Angle, Matrix3d, Point2d, Point3d, Point4d, Range2d, Range3d, Transform, Vector3d } from "@itwin/core-geometry";
|
|
10
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
11
|
import { getImageSourceFormatForMimeType, imageElementFromImageSource, tryImageElementFromUrl } from "../ImageUtil";
|
|
@@ -99,6 +99,12 @@ function getNodeMeshIds(node) {
|
|
|
99
99
|
return [node.mesh];
|
|
100
100
|
return [];
|
|
101
101
|
}
|
|
102
|
+
/** GL states that can be enabled by a [[GltfTechnique]]. Only those queried by this implementation are enumerated. */
|
|
103
|
+
var GltfTechniqueState;
|
|
104
|
+
(function (GltfTechniqueState) {
|
|
105
|
+
/** Enables alpha blending. */
|
|
106
|
+
GltfTechniqueState[GltfTechniqueState["Blend"] = 3042] = "Blend";
|
|
107
|
+
})(GltfTechniqueState || (GltfTechniqueState = {}));
|
|
102
108
|
function isGltf1Material(material) {
|
|
103
109
|
const mat1 = material;
|
|
104
110
|
return undefined !== mat1.technique || undefined !== mat1.values;
|
|
@@ -283,21 +289,23 @@ const emptyDict = {};
|
|
|
283
289
|
function colorFromJson(values) {
|
|
284
290
|
return ColorDef.from(values[0] * 255, values[1] * 255, values[2] * 255, (1.0 - values[3]) * 255);
|
|
285
291
|
}
|
|
286
|
-
function colorFromMaterial(material) {
|
|
292
|
+
function colorFromMaterial(material, isTransparent) {
|
|
287
293
|
var _a, _b, _c, _d, _e;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
294
|
+
let color = ColorDef.white;
|
|
295
|
+
if (isGltf1Material(material)) {
|
|
296
|
+
if (((_a = material.values) === null || _a === void 0 ? void 0 : _a.color) && Array.isArray(material.values.color))
|
|
297
|
+
color = colorFromJson(material.values.color);
|
|
298
|
+
}
|
|
299
|
+
else if ((_d = (_c = (_b = material.extensions) === null || _b === void 0 ? void 0 : _b.KHR_techniques_webgl) === null || _c === void 0 ? void 0 : _c.values) === null || _d === void 0 ? void 0 : _d.u_color) {
|
|
300
|
+
color = colorFromJson(material.extensions.KHR_techniques_webgl.values.u_color);
|
|
301
|
+
}
|
|
302
|
+
else if ((_e = material.pbrMetallicRoughness) === null || _e === void 0 ? void 0 : _e.baseColorFactor) {
|
|
303
|
+
color = colorFromJson(material.pbrMetallicRoughness.baseColorFactor);
|
|
299
304
|
}
|
|
300
|
-
|
|
305
|
+
// SPEC: Opaque materials ignore any alpha channel.
|
|
306
|
+
if (!isTransparent)
|
|
307
|
+
color = color.withTransparency(0);
|
|
308
|
+
return color;
|
|
301
309
|
}
|
|
302
310
|
class TransformStack {
|
|
303
311
|
constructor() {
|
|
@@ -351,12 +359,25 @@ function* traverseNodes(ids, nodes, traversed) {
|
|
|
351
359
|
yield child;
|
|
352
360
|
}
|
|
353
361
|
}
|
|
362
|
+
function compareTextureKeys(lhs, rhs) {
|
|
363
|
+
const cmp = compareBooleans(lhs.isTransparent, rhs.isTransparent);
|
|
364
|
+
if (0 !== cmp)
|
|
365
|
+
return cmp;
|
|
366
|
+
assert(typeof lhs.id === typeof rhs.id);
|
|
367
|
+
if ("string" === typeof lhs.id) {
|
|
368
|
+
assert("string" === typeof rhs.id);
|
|
369
|
+
return compareStrings(lhs.id, rhs.id);
|
|
370
|
+
}
|
|
371
|
+
assert("number" === typeof lhs.id && "number" === typeof rhs.id);
|
|
372
|
+
return compareNumbers(lhs.id, rhs.id);
|
|
373
|
+
}
|
|
354
374
|
/** Deserializes [glTF](https://www.khronos.org/gltf/).
|
|
355
375
|
* @internal
|
|
356
376
|
*/
|
|
357
377
|
export class GltfReader {
|
|
358
378
|
constructor(args) {
|
|
359
379
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
380
|
+
this._resolvedTextures = new Dictionary((lhs, rhs) => compareTextureKeys(lhs, rhs));
|
|
360
381
|
this._glTF = args.props.glTF;
|
|
361
382
|
this._version = args.props.version;
|
|
362
383
|
this._yAxisUp = args.props.yAxisUp;
|
|
@@ -654,22 +675,41 @@ export class GltfReader {
|
|
|
654
675
|
}
|
|
655
676
|
}
|
|
656
677
|
}
|
|
657
|
-
const id = extractId((_g = material.
|
|
658
|
-
return id !== null && id !== void 0 ? id : extractId((_j =
|
|
678
|
+
const id = extractId((_h = (_g = material.pbrMetallicRoughness) === null || _g === void 0 ? void 0 : _g.baseColorTexture) === null || _h === void 0 ? void 0 : _h.index);
|
|
679
|
+
return id !== null && id !== void 0 ? id : extractId((_j = material.emissiveTexture) === null || _j === void 0 ? void 0 : _j.index);
|
|
680
|
+
}
|
|
681
|
+
isMaterialTransparent(material) {
|
|
682
|
+
var _a, _b;
|
|
683
|
+
if (isGltf1Material(material)) {
|
|
684
|
+
if (this._glTF.techniques && undefined !== material.technique) {
|
|
685
|
+
const technique = this._glTF.techniques[material.technique];
|
|
686
|
+
if ((_b = (_a = technique === null || technique === void 0 ? void 0 : technique.states) === null || _a === void 0 ? void 0 : _a.enable) === null || _b === void 0 ? void 0 : _b.some((state) => state === GltfTechniqueState.Blend))
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
// Default: OPAQUE.
|
|
693
|
+
// ###TODO support MASK. For now treat as opaque.
|
|
694
|
+
return "BLEND" === material.alphaMode;
|
|
695
|
+
}
|
|
659
696
|
}
|
|
660
|
-
createDisplayParams(
|
|
661
|
-
const
|
|
662
|
-
const
|
|
663
|
-
const
|
|
697
|
+
createDisplayParams(material, hasBakedLighting) {
|
|
698
|
+
const isTransparent = this.isMaterialTransparent(material);
|
|
699
|
+
const textureId = this.extractTextureId(material);
|
|
700
|
+
const textureMapping = undefined !== textureId ? this.findTextureMapping(textureId, isTransparent) : undefined;
|
|
701
|
+
const color = colorFromMaterial(material, isTransparent);
|
|
664
702
|
return new DisplayParams(DisplayParams.Type.Mesh, color, color, 1, LinePixels.Solid, FillFlags.Always, undefined, undefined, hasBakedLighting, textureMapping);
|
|
665
703
|
}
|
|
666
704
|
readMeshPrimitive(primitive, featureTable, pseudoRtcBias) {
|
|
667
|
-
var _a, _b, _c, _d, _e, _f;
|
|
705
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
668
706
|
const materialName = JsonUtils.asString(primitive.material);
|
|
669
|
-
const hasBakedLighting = undefined === primitive.attributes.NORMAL;
|
|
670
707
|
const material = 0 < materialName.length ? this._materials[materialName] : undefined;
|
|
708
|
+
if (!material)
|
|
709
|
+
return undefined;
|
|
710
|
+
const hasBakedLighting = undefined === primitive.attributes.NORMAL || undefined !== ((_a = material.extensions) === null || _a === void 0 ? void 0 : _a.KHR_materials_unlit);
|
|
671
711
|
const displayParams = material ? this.createDisplayParams(material, hasBakedLighting) : undefined;
|
|
672
|
-
if (
|
|
712
|
+
if (!displayParams)
|
|
673
713
|
return undefined;
|
|
674
714
|
let primitiveType = -1;
|
|
675
715
|
const meshMode = JsonUtils.asInt(primitive.mode, GltfMeshMode.Triangles);
|
|
@@ -707,9 +747,9 @@ export class GltfReader {
|
|
|
707
747
|
if (undefined !== colorIndices && material) {
|
|
708
748
|
let texStep;
|
|
709
749
|
if (isGltf1Material(material))
|
|
710
|
-
texStep = (
|
|
750
|
+
texStep = (_b = material.values) === null || _b === void 0 ? void 0 : _b.texStep;
|
|
711
751
|
else
|
|
712
|
-
texStep = (
|
|
752
|
+
texStep = (_e = (_d = (_c = material.extensions) === null || _c === void 0 ? void 0 : _c.KHR_techniques_webgl) === null || _d === void 0 ? void 0 : _d.values) === null || _e === void 0 ? void 0 : _e.u_texStep;
|
|
713
753
|
if (texStep) {
|
|
714
754
|
const uvParams = [];
|
|
715
755
|
for (let i = 0; i < colorIndices.count; i++)
|
|
@@ -719,7 +759,7 @@ export class GltfReader {
|
|
|
719
759
|
mesh.uvQParams = paramList.params;
|
|
720
760
|
}
|
|
721
761
|
}
|
|
722
|
-
if ((
|
|
762
|
+
if ((_f = primitive.extensions) === null || _f === void 0 ? void 0 : _f.KHR_draco_mesh_compression) {
|
|
723
763
|
return undefined; // Defer Draco decompression until web workers implementation.
|
|
724
764
|
/*
|
|
725
765
|
const dracoExtension = primitive.extensions.KHR_draco_mesh_compression;
|
|
@@ -738,8 +778,12 @@ export class GltfReader {
|
|
|
738
778
|
return undefined;
|
|
739
779
|
if (!displayParams.ignoreLighting && !this.readNormals(mesh, primitive.attributes, "NORMAL"))
|
|
740
780
|
return undefined;
|
|
741
|
-
if (!mesh.uvs)
|
|
742
|
-
|
|
781
|
+
if (!mesh.uvs) {
|
|
782
|
+
let texCoordIndex = 0;
|
|
783
|
+
if (!isGltf1Material(material) && undefined !== ((_h = (_g = material.pbrMetallicRoughness) === null || _g === void 0 ? void 0 : _g.baseColorTexture) === null || _h === void 0 ? void 0 : _h.texCoord))
|
|
784
|
+
texCoordIndex = JsonUtils.asInt(material.pbrMetallicRoughness.baseColorTexture.texCoord);
|
|
785
|
+
this.readUVParams(mesh, primitive.attributes, `TEXCOORD_${texCoordIndex}`);
|
|
786
|
+
}
|
|
743
787
|
if (this._deduplicateVertices && !this.deduplicateVertices(mesh))
|
|
744
788
|
return undefined;
|
|
745
789
|
break;
|
|
@@ -757,7 +801,7 @@ export class GltfReader {
|
|
|
757
801
|
}
|
|
758
802
|
if (displayParams.textureMapping && !mesh.uvs)
|
|
759
803
|
return undefined;
|
|
760
|
-
if ((
|
|
804
|
+
if ((_j = primitive.extensions) === null || _j === void 0 ? void 0 : _j.CESIUM_primitive_outline) {
|
|
761
805
|
const data = this.readBufferData32(primitive.extensions.CESIUM_primitive_outline, "indices");
|
|
762
806
|
if (data !== undefined) {
|
|
763
807
|
assert(0 === data.count % 2);
|
|
@@ -776,6 +820,8 @@ export class GltfReader {
|
|
|
776
820
|
const indices = mesh.indices;
|
|
777
821
|
if (indices instanceof Uint16Array && numPoints > 0xffff)
|
|
778
822
|
mesh.indices = new Uint32Array(numPoints);
|
|
823
|
+
else if (indices instanceof Uint8Array && numPoints > 0xff)
|
|
824
|
+
mesh.indices = new Uint32Array(numPoints);
|
|
779
825
|
const points = new Uint16Array(3 * numPoints);
|
|
780
826
|
const normals = mesh.normals ? new Uint16Array(numPoints) : undefined;
|
|
781
827
|
const uvs = mesh.uvs ? new Uint16Array(2 * numPoints) : undefined;
|
|
@@ -876,10 +922,22 @@ export class GltfReader {
|
|
|
876
922
|
readBatchTable(_mesh, _json) {
|
|
877
923
|
}
|
|
878
924
|
readMeshIndices(mesh, json) {
|
|
879
|
-
|
|
880
|
-
if (undefined
|
|
925
|
+
var _a;
|
|
926
|
+
if (undefined !== json.indices) {
|
|
927
|
+
const data = this.readBufferData16(json, "indices") || this.readBufferData32(json, "indices");
|
|
928
|
+
if (data && (data.buffer instanceof Uint8Array || data.buffer instanceof Uint16Array || data.buffer instanceof Uint32Array)) {
|
|
929
|
+
mesh.indices = data.buffer;
|
|
930
|
+
return true;
|
|
931
|
+
}
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
// Non-indexed geometry. Manufacture triangle indices from points.
|
|
935
|
+
const numPoints = (_a = mesh.points) === null || _a === void 0 ? void 0 : _a.length;
|
|
936
|
+
if (undefined === numPoints || 0 !== numPoints % 3)
|
|
881
937
|
return false;
|
|
882
|
-
mesh.indices =
|
|
938
|
+
mesh.indices = numPoints < 255 ? new Uint8Array(numPoints) : (numPoints < 0xffff ? new Uint16Array(numPoints) : new Uint32Array(numPoints));
|
|
939
|
+
for (let i = 0; i < numPoints; i++)
|
|
940
|
+
mesh.indices[i] = i;
|
|
883
941
|
return true;
|
|
884
942
|
}
|
|
885
943
|
readNormals(mesh, json, accessorName) {
|
|
@@ -1017,9 +1075,6 @@ export class GltfReader {
|
|
|
1017
1075
|
if (!image.resolvedImage)
|
|
1018
1076
|
promises.push(this.resolveImage(image));
|
|
1019
1077
|
await Promise.all(promises);
|
|
1020
|
-
if (this._isCanceled)
|
|
1021
|
-
return;
|
|
1022
|
-
this.resolveTextures();
|
|
1023
1078
|
}
|
|
1024
1079
|
catch (_) {
|
|
1025
1080
|
}
|
|
@@ -1077,64 +1132,33 @@ export class GltfReader {
|
|
|
1077
1132
|
if (undefined !== url)
|
|
1078
1133
|
image.resolvedImage = await tryImageElementFromUrl(url);
|
|
1079
1134
|
}
|
|
1080
|
-
resolveTextures() {
|
|
1081
|
-
var _a, _b;
|
|
1082
|
-
if (undefined === this._glTF.textures)
|
|
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...
|
|
1085
|
-
const transparentTextures = new Set();
|
|
1086
|
-
if (this._glTF.techniques) {
|
|
1087
|
-
for (const name of Object.keys(this._materials)) {
|
|
1088
|
-
const material = this._materials[name];
|
|
1089
|
-
if (material && isGltf1Material(material) && undefined !== material.technique && undefined !== ((_a = material.values) === null || _a === void 0 ? void 0 : _a.tex)) {
|
|
1090
|
-
const technique = this._glTF.techniques[material.technique];
|
|
1091
|
-
if ((_b = technique === null || technique === void 0 ? void 0 : technique.states) === null || _b === void 0 ? void 0 : _b.enable) {
|
|
1092
|
-
for (const enable of technique.states.enable) {
|
|
1093
|
-
if (3042 === enable) { // 3042 = BLEND
|
|
1094
|
-
transparentTextures.add(material.values.tex.toString());
|
|
1095
|
-
break;
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
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));
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
1135
|
resolveTexture(textureId, isTransparent) {
|
|
1117
1136
|
var _a;
|
|
1118
1137
|
const texture = this._textures[textureId];
|
|
1119
|
-
if (!texture ||
|
|
1120
|
-
return;
|
|
1138
|
+
if (!texture || undefined === texture.source)
|
|
1139
|
+
return false;
|
|
1121
1140
|
const image = (_a = this._images[texture.source]) === null || _a === void 0 ? void 0 : _a.resolvedImage;
|
|
1122
1141
|
if (!image)
|
|
1123
|
-
return;
|
|
1142
|
+
return false;
|
|
1124
1143
|
const samplerId = texture.sampler;
|
|
1125
1144
|
const sampler = undefined !== samplerId ? this._samplers[samplerId] : undefined;
|
|
1126
|
-
|
|
1127
|
-
|
|
1145
|
+
// ###TODO: RenderTexture should support different wrapping behavior for U vs V, and support mirrored repeat.
|
|
1146
|
+
// For now, repeat unless either explicitly clamps.
|
|
1147
|
+
const textureType = GltfWrapMode.ClampToEdge === (sampler === null || sampler === void 0 ? void 0 : sampler.wrapS) || GltfWrapMode.ClampToEdge === (sampler === null || sampler === void 0 ? void 0 : sampler.wrapT) ? RenderTexture.Type.TileSection : RenderTexture.Type.Normal;
|
|
1148
|
+
const renderTexture = this._system.createTexture({
|
|
1128
1149
|
type: textureType,
|
|
1129
1150
|
image: {
|
|
1130
1151
|
source: image,
|
|
1131
1152
|
transparency: isTransparent ? TextureTransparency.Translucent : TextureTransparency.Opaque,
|
|
1132
1153
|
},
|
|
1133
1154
|
});
|
|
1155
|
+
return renderTexture !== null && renderTexture !== void 0 ? renderTexture : false;
|
|
1134
1156
|
}
|
|
1135
|
-
findTextureMapping(
|
|
1136
|
-
|
|
1137
|
-
|
|
1157
|
+
findTextureMapping(id, isTransparent) {
|
|
1158
|
+
let texture = this._resolvedTextures.get({ id, isTransparent });
|
|
1159
|
+
if (undefined === texture)
|
|
1160
|
+
this._resolvedTextures.set({ id, isTransparent }, texture = this.resolveTexture(id, isTransparent));
|
|
1161
|
+
return texture ? new TextureMapping(texture, new TextureMapping.Params()) : undefined;
|
|
1138
1162
|
}
|
|
1139
1163
|
}
|
|
1140
1164
|
/** Produce a [[RenderGraphic]] from a [glTF](https://www.khronos.org/gltf/) asset suitable for use in [view decorations]($docs/learning/frontend/ViewDecorations).
|