@loaders.gl/tile-converter 5.0.0-alpha.11 → 5.0.0-alpha.14
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 +1 -1
- package/README.md +180 -4
- package/bin/converter-v5.js +2 -0
- package/dist/converter.min.cjs +172 -182
- package/dist/i3s-server/bin/i3s-server.min.cjs +113 -158
- package/dist/index.cjs +18832 -19228
- package/dist/index.js +19566 -19968
- package/dist/v5/adapters.cjs +2002 -230
- package/dist/v5/adapters.d.ts +20 -0
- package/dist/v5/adapters.js +2005 -214
- package/dist/v5/archive-source.d.ts +36 -0
- package/dist/v5/browser-tileset-source.d.ts +55 -11
- package/dist/v5/browser.cjs +18 -0
- package/dist/v5/browser.d.ts +15 -1
- package/dist/v5/browser.js +26 -0
- package/dist/v5/conversion-api.d.ts +34 -0
- package/dist/v5/converter-cli.d.ts +1 -0
- package/dist/v5/converter-cli.js +1230 -0
- package/dist/v5/core.cjs +547 -77
- package/dist/v5/core.d.ts +3 -1
- package/dist/v5/core.js +540 -70
- package/dist/v5/feature-arrow.d.ts +1 -1
- package/dist/v5/i3s-mesh-conversion.d.ts +5 -1
- package/dist/v5/i3s-mesh-source-features.d.ts +2 -2
- package/dist/v5/i3s-mesh-source-material.d.ts +1 -1
- package/dist/v5/i3s-mesh-source.d.ts +2 -2
- package/dist/v5/i3s-selection-source.d.ts +70 -0
- package/dist/v5/index.cjs +15 -0
- package/dist/v5/index.d.ts +13 -1
- package/dist/v5/index.js +22 -0
- package/dist/v5/mesh-conversion.d.ts +21 -3
- package/dist/v5/mesh-draco.d.ts +2 -2
- package/dist/v5/mesh-features.d.ts +2 -2
- package/dist/v5/mesh-hierarchy.d.ts +47 -0
- package/dist/v5/mesh-source-features.d.ts +6 -5
- package/dist/v5/mesh-source-schema.d.ts +12 -0
- package/dist/v5/mesh-source-texture.d.ts +3 -3
- package/dist/v5/mesh-source.d.ts +10 -7
- package/dist/v5/mesh-tileset-sink.d.ts +5 -0
- package/dist/v5/mesh.d.ts +1 -1
- package/dist/v5/node-cli.d.ts +9 -0
- package/dist/v5/node-conversion.d.ts +34 -0
- package/dist/v5/node-feature-schema.d.ts +3 -0
- package/dist/v5/node-i3s-source.d.ts +41 -0
- package/dist/v5/node-source.d.ts +47 -0
- package/dist/v5/node.cjs +913 -0
- package/dist/v5/node.d.ts +6 -0
- package/dist/v5/node.js +890 -0
- package/dist/v5/point-cloud-attributes.d.ts +19 -0
- package/dist/v5/point-cloud-conversion.d.ts +1 -1
- package/dist/v5/point-cloud-copc.d.ts +44 -0
- package/dist/v5/point-cloud-file.d.ts +83 -0
- package/dist/v5/point-cloud-potree.d.ts +47 -0
- package/dist/v5/point-cloud-source-encoder.d.ts +1 -1
- package/dist/v5/point-cloud-source.d.ts +1 -1
- package/dist/v5/point-cloud-tileset.d.ts +44 -0
- package/dist/v5/point-cloud.d.ts +1 -1
- package/dist/v5/resource-manifest.d.ts +10 -1
- package/dist/v5/selected-mesh-source.d.ts +53 -0
- package/dist/v5/spatial-conversion.d.ts +1 -1
- package/dist/v5/tileset-source.d.ts +1 -1
- package/package.json +25 -32
- package/src/index.ts +4 -1
- package/src/v4/3d-tiles-converter/3d-tiles-converter.ts +11 -12
- package/src/v4/3d-tiles-converter/helpers/3d-tiles-content-converter.ts +7 -3
- package/src/v4/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.ts +2 -2
- package/src/v4/3d-tiles-converter/helpers/load-i3s.ts +4 -6
- package/src/v4/3d-tiles-converter/helpers/texture-atlas.ts +1 -1
- package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +2 -2
- package/src/v4/3d-tiles-converter/json-templates/tileset.ts +58 -39
- package/src/v4/converter-cli.ts +10 -4
- package/src/v4/deps-installer/deps-installer.ts +3 -3
- package/src/v4/i3s-converter/helpers/attribute-metadata-info.ts +1 -1
- package/src/v4/i3s-converter/helpers/batch-ids-extensions.ts +9 -10
- package/src/v4/i3s-converter/helpers/conversion-gltf.ts +108 -0
- package/src/v4/i3s-converter/helpers/coordinate-converter.ts +6 -5
- package/src/v4/i3s-converter/helpers/create-scene-server-path.ts +5 -6
- package/src/v4/i3s-converter/helpers/feature-attributes.ts +4 -4
- package/src/v4/i3s-converter/helpers/geometry-attributes.ts +1 -1
- package/src/v4/i3s-converter/helpers/geometry-converter.ts +69 -77
- package/src/v4/i3s-converter/helpers/gltf-attributes.ts +58 -74
- package/src/v4/i3s-converter/helpers/load-3d-tiles.ts +6 -54
- package/src/v4/i3s-converter/helpers/node-debug.ts +7 -3
- package/src/v4/i3s-converter/helpers/node-index-document.ts +11 -9
- package/src/v4/i3s-converter/helpers/node-pages.ts +3 -4
- package/src/v4/i3s-converter/helpers/preprocess-3d-tiles.ts +2 -2
- package/src/v4/i3s-converter/helpers/tileset-traversal.ts +1 -1
- package/src/v4/i3s-converter/i3s-converter.ts +29 -31
- package/src/v4/i3s-converter/json-templates/geometry-definitions.ts +71 -66
- package/src/v4/i3s-converter/json-templates/layers.ts +97 -132
- package/src/v4/i3s-converter/json-templates/metadata.ts +31 -21
- package/src/v4/i3s-converter/json-templates/node.ts +60 -74
- package/src/v4/i3s-converter/json-templates/scene-server.ts +36 -27
- package/src/v4/i3s-converter/json-templates/shared-resources.ts +62 -123
- package/src/v4/i3s-converter/json-templates/store.ts +39 -57
- package/src/v4/i3s-converter/types.ts +4 -4
- package/src/v4/i3s-server/controllers/slpk-controller.ts +3 -3
- package/src/v4/i3s-server/utils/create-scene-server.ts +3 -3
- package/src/v4/lib/utils/builder-input.ts +8 -0
- package/src/v4/lib/utils/conversion-dump.ts +5 -1
- package/src/v4/lib/utils/file-utils.ts +1 -1
- package/src/v4/lib/utils/hash-string.ts +21 -0
- package/src/v4/lib/utils/lod-conversion-utils.ts +3 -3
- package/src/v4/pgm-loader.ts +2 -2
- package/src/v5/adapters.ts +53 -0
- package/src/v5/archive-source.ts +235 -0
- package/src/v5/browser-tileset-source.ts +418 -48
- package/src/v5/browser.ts +46 -0
- package/src/v5/conversion-api.ts +184 -17
- package/src/v5/conversion-archive.ts +2 -2
- package/src/v5/converter-cli.ts +28 -0
- package/src/v5/core.ts +7 -0
- package/src/v5/feature-arrow.ts +2 -2
- package/src/v5/i3s-mesh-conversion.ts +41 -3
- package/src/v5/i3s-mesh-sink.ts +1 -1
- package/src/v5/i3s-mesh-source-features.ts +3 -3
- package/src/v5/i3s-mesh-source-material.ts +18 -11
- package/src/v5/i3s-mesh-source.ts +3 -2
- package/src/v5/i3s-selection-source.ts +298 -0
- package/src/v5/index.ts +41 -0
- package/src/v5/mesh-conversion.ts +24 -4
- package/src/v5/mesh-draco.ts +2 -2
- package/src/v5/mesh-features.ts +3 -3
- package/src/v5/mesh-hierarchy.ts +648 -0
- package/src/v5/mesh-source-features.ts +165 -51
- package/src/v5/mesh-source-schema.ts +140 -0
- package/src/v5/mesh-source-texture.ts +49 -19
- package/src/v5/mesh-source.ts +80 -49
- package/src/v5/mesh-tileset-archive.ts +1 -1
- package/src/v5/mesh-tileset-sink.ts +2 -2
- package/src/v5/mesh.ts +1 -1
- package/src/v5/node-cli.ts +201 -0
- package/src/v5/node-conversion.ts +362 -0
- package/src/v5/node-feature-schema.ts +155 -0
- package/src/v5/node-i3s-source.ts +181 -0
- package/src/v5/node-source.ts +328 -0
- package/src/v5/node.ts +16 -0
- package/src/v5/point-cloud-attributes.ts +113 -0
- package/src/v5/point-cloud-conversion.ts +1 -1
- package/src/v5/point-cloud-copc.ts +289 -0
- package/src/v5/point-cloud-file.ts +306 -0
- package/src/v5/point-cloud-potree.ts +134 -0
- package/src/v5/point-cloud-source-encoder.ts +1 -1
- package/src/v5/point-cloud-source.ts +1 -1
- package/src/v5/point-cloud-spatial.ts +2 -2
- package/src/v5/point-cloud-tileset.ts +137 -0
- package/src/v5/point-cloud.ts +3 -3
- package/src/v5/resource-fetcher.ts +4 -1
- package/src/v5/resource-manifest.ts +40 -5
- package/src/v5/selected-mesh-source.ts +384 -0
- package/src/v5/spatial-conversion.ts +90 -19
- package/src/v5/tileset-source.ts +2 -2
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import {getConversionMaterials} from './conversion-gltf';
|
|
2
|
+
import type {
|
|
3
|
+
ConversionAccessor,
|
|
4
|
+
ConversionMaterial,
|
|
5
|
+
ConversionNode,
|
|
6
|
+
ConversionPrimitive,
|
|
7
|
+
ConversionMesh,
|
|
8
|
+
ConversionTexture
|
|
9
|
+
} from './conversion-gltf';
|
|
1
10
|
/* eslint-disable camelcase */
|
|
2
|
-
import type {FeatureTableJson, Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
11
|
+
import type {FeatureTableJson, Tiles3DTileContent} from '@loaders.gl/tiles-3d/3d-tiles';
|
|
3
12
|
import type {
|
|
4
|
-
GLTFAccessorPostprocessed,
|
|
5
|
-
GLTFMaterialPostprocessed,
|
|
6
|
-
GLTFNodePostprocessed,
|
|
7
|
-
GLTFMeshPrimitivePostprocessed,
|
|
8
|
-
GLTFMeshPostprocessed,
|
|
9
|
-
GLTFTexturePostprocessed,
|
|
10
13
|
GLTF_EXT_feature_metadata_GLTF,
|
|
11
14
|
GLTF_EXT_feature_metadata_FeatureTable,
|
|
12
15
|
GLTF_EXT_feature_metadata_FeatureTexture,
|
|
@@ -23,15 +26,15 @@ import {createRequire} from 'node:module';
|
|
|
23
26
|
/* @ts-expect-error TS2732: Cannot find module 'node:module' or its corresponding type declarations. */
|
|
24
27
|
|
|
25
28
|
import {DracoWriterWorker} from '@loaders.gl/draco';
|
|
26
|
-
import {
|
|
29
|
+
import {encode, assert} from '@loaders.gl/core';
|
|
27
30
|
import {
|
|
28
31
|
concatenateArrayBuffers,
|
|
29
32
|
concatenateTypedArrays,
|
|
30
33
|
NumberArray,
|
|
31
34
|
TypedArray
|
|
32
|
-
} from '@loaders.gl/loader-utils';
|
|
33
|
-
import
|
|
34
|
-
import {
|
|
35
|
+
} from '@loaders.gl/core/loader-utils';
|
|
36
|
+
import {hashString} from '../../lib/utils/hash-string';
|
|
37
|
+
import {randomUUID} from 'node:crypto';
|
|
35
38
|
import {generateAttributes} from './geometry-attributes';
|
|
36
39
|
import {encodeStringAttribute} from './encode-string-attribute';
|
|
37
40
|
import {createBoundingVolumesFromGeometry} from './coordinate-converter';
|
|
@@ -47,21 +50,21 @@ import {
|
|
|
47
50
|
I3SMaterialDefinition,
|
|
48
51
|
MaterialDefinitionInfo,
|
|
49
52
|
TextureDefinitionInfo
|
|
50
|
-
} from '@loaders.gl/i3s';
|
|
51
|
-
import {Geoid} from '@math.gl/geoid';
|
|
53
|
+
} from '@loaders.gl/tiles-3d/i3s';
|
|
54
|
+
import {Geoid} from '@math.gl/earth/geoid';
|
|
52
55
|
import {prepareDataForAttributesConversion} from './gltf-attributes';
|
|
53
56
|
import {getTextureByMetadataClass, handleBatchIdsExtensions} from './batch-ids-extensions';
|
|
54
57
|
import {checkPropertiesLength, flattenPropertyTableByFeatureIds} from './feature-attributes';
|
|
55
|
-
import {GL} from '@math.gl/geometry
|
|
58
|
+
import {GL} from '@math.gl/geometry/utils';
|
|
56
59
|
|
|
57
60
|
/*
|
|
58
|
-
At the moment of writing the type TypedArrayConstructor is not exported in '@math.gl/types'.
|
|
61
|
+
At the moment of writing the type TypedArrayConstructor is not exported in '@math.gl/core/types'.
|
|
59
62
|
So the following import is replaced with the local import
|
|
60
|
-
import type {TypedArrayConstructor} from '@math.gl/types';
|
|
63
|
+
import type {TypedArrayConstructor} from '@math.gl/core/types';
|
|
61
64
|
*/
|
|
62
|
-
import type {GLTFAttributesData, TextureImageProperties
|
|
65
|
+
import type {GLTFAttributesData, TextureImageProperties} from '../types';
|
|
63
66
|
import {generateSyntheticIndices} from '../../lib/utils/geometry-utils';
|
|
64
|
-
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
|
|
67
|
+
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/geometry/culling';
|
|
65
68
|
|
|
66
69
|
import {EXT_FEATURE_METADATA, EXT_STRUCTURAL_METADATA} from '@loaders.gl/gltf';
|
|
67
70
|
|
|
@@ -136,7 +139,7 @@ export default async function convertB3dmToI3sGeometry({
|
|
|
136
139
|
}): Promise<I3SConvertedResources[] | null> {
|
|
137
140
|
const useCartesianPositions = generateBoundingVolumes;
|
|
138
141
|
const materialAndTextureList: I3SMaterialWithTexture[] = await convertMaterials(
|
|
139
|
-
tileContent.gltf
|
|
142
|
+
tileContent.gltf ? getConversionMaterials(tileContent.gltf) : [],
|
|
140
143
|
shouldMergeMaterials
|
|
141
144
|
);
|
|
142
145
|
|
|
@@ -339,7 +342,10 @@ async function _makeNodeResources({
|
|
|
339
342
|
compressedGeometry,
|
|
340
343
|
texture,
|
|
341
344
|
hasUvRegions: Boolean(uvRegions.length),
|
|
342
|
-
sharedResources: getSharedResources(
|
|
345
|
+
sharedResources: getSharedResources(
|
|
346
|
+
tileContent.gltf ? getConversionMaterials(tileContent.gltf) : [],
|
|
347
|
+
nodeId
|
|
348
|
+
),
|
|
343
349
|
meshMaterial: material,
|
|
344
350
|
vertexCount,
|
|
345
351
|
attributes,
|
|
@@ -437,7 +443,7 @@ function convertNodes({
|
|
|
437
443
|
matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
|
438
444
|
featureTexture
|
|
439
445
|
}: {
|
|
440
|
-
nodes:
|
|
446
|
+
nodes: ConversionNode[];
|
|
441
447
|
images: (TextureImageProperties | null)[];
|
|
442
448
|
cartographicOrigin: Vector3;
|
|
443
449
|
cartesianModelMatrix: Matrix4;
|
|
@@ -468,7 +474,7 @@ function convertNodes({
|
|
|
468
474
|
* @param node
|
|
469
475
|
* @param matrix
|
|
470
476
|
*/
|
|
471
|
-
function getCompositeTransformationMatrix(node:
|
|
477
|
+
function getCompositeTransformationMatrix(node: ConversionNode, matrix: Matrix4) {
|
|
472
478
|
let transformationMatrix = matrix;
|
|
473
479
|
|
|
474
480
|
const {matrix: nodeMatrix, rotation, scale, translation} = node;
|
|
@@ -515,7 +521,7 @@ function convertNode({
|
|
|
515
521
|
matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
|
516
522
|
featureTexture
|
|
517
523
|
}: {
|
|
518
|
-
node:
|
|
524
|
+
node: ConversionNode;
|
|
519
525
|
images: (TextureImageProperties | null)[];
|
|
520
526
|
cartographicOrigin: Vector3;
|
|
521
527
|
cartesianModelMatrix: Matrix4;
|
|
@@ -578,7 +584,7 @@ function convertMeshToTable({
|
|
|
578
584
|
matrix,
|
|
579
585
|
featureTexture
|
|
580
586
|
}: {
|
|
581
|
-
mesh:
|
|
587
|
+
mesh: ConversionMesh;
|
|
582
588
|
images: (TextureImageProperties | null)[];
|
|
583
589
|
cartographicOrigin: Vector3;
|
|
584
590
|
cartesianModelMatrix: Matrix4;
|
|
@@ -604,7 +610,8 @@ function convertMeshToTable({
|
|
|
604
610
|
assert(
|
|
605
611
|
primitive.mode === undefined ||
|
|
606
612
|
primitive.mode === GL.TRIANGLES ||
|
|
607
|
-
primitive.mode === GL.TRIANGLE_STRIP
|
|
613
|
+
primitive.mode === GL.TRIANGLE_STRIP ||
|
|
614
|
+
primitive.mode === GL.TRIANGLE_FAN,
|
|
608
615
|
`Primitive - unsupported mode ${primitive.mode}`
|
|
609
616
|
);
|
|
610
617
|
const attributes = primitive.attributes;
|
|
@@ -661,44 +668,32 @@ function convertMeshToTable({
|
|
|
661
668
|
}
|
|
662
669
|
}
|
|
663
670
|
/**
|
|
664
|
-
* Converts
|
|
671
|
+
* Converts triangle strips and fans to independent triangles
|
|
665
672
|
* @param primitive - the primitive to get the indices from
|
|
666
673
|
* @returns indices of vertices of the independent triangles
|
|
667
674
|
*/
|
|
668
|
-
function normalizeIndices(primitive:
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
// [i1, i2, i3, i4, i5, i6, ...] -> [i3, i2, i1, i2, i3, i4, i5, i4, i3, i4, i5, i6, ...]
|
|
691
|
-
for (let i = 1; i + 2 < indices.length; i++) {
|
|
692
|
-
triangleIndex += 3;
|
|
693
|
-
currentTriangle = indices.slice(i, i + 3);
|
|
694
|
-
if (i % 2 === 0) {
|
|
695
|
-
newIndices.set(currentTriangle, triangleIndex);
|
|
696
|
-
} else {
|
|
697
|
-
// The following "reverce" is necessary to calculate normals correctly
|
|
698
|
-
newIndices.set(currentTriangle.reverse(), triangleIndex);
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
indices = newIndices;
|
|
675
|
+
function normalizeIndices(primitive: ConversionPrimitive): TypedArray {
|
|
676
|
+
const source = primitive.indices?.value;
|
|
677
|
+
const vertexCount = primitive.attributes.POSITION.value.length / VALUES_PER_VERTEX;
|
|
678
|
+
const count = source?.length ?? vertexCount;
|
|
679
|
+
if (primitive.mode !== GL.TRIANGLE_STRIP && primitive.mode !== GL.TRIANGLE_FAN) {
|
|
680
|
+
return source || generateSyntheticIndices(vertexCount);
|
|
681
|
+
}
|
|
682
|
+
const indices = new Uint32Array(Math.max(0, count - 2) * 3);
|
|
683
|
+
for (let triangleIndex = 0; triangleIndex + 2 < count; triangleIndex++) {
|
|
684
|
+
const first = primitive.mode === GL.TRIANGLE_FAN ? 0 : triangleIndex;
|
|
685
|
+
const second =
|
|
686
|
+
primitive.mode === GL.TRIANGLE_FAN
|
|
687
|
+
? triangleIndex + 1
|
|
688
|
+
: triangleIndex + 1 + (triangleIndex % 2);
|
|
689
|
+
const third =
|
|
690
|
+
primitive.mode === GL.TRIANGLE_FAN
|
|
691
|
+
? triangleIndex + 2
|
|
692
|
+
: triangleIndex + 2 - (triangleIndex % 2);
|
|
693
|
+
indices.set(
|
|
694
|
+
[source?.[first] ?? first, source?.[second] ?? second, source?.[third] ?? third],
|
|
695
|
+
triangleIndex * 3
|
|
696
|
+
);
|
|
702
697
|
}
|
|
703
698
|
return indices;
|
|
704
699
|
}
|
|
@@ -822,10 +817,7 @@ function flattenTexCoords(texCoords: TypedArray, indices: TypedArray): Float32Ar
|
|
|
822
817
|
* @param indices - gltf primitive indices
|
|
823
818
|
* @returns flattened colors attribute
|
|
824
819
|
*/
|
|
825
|
-
function flattenColors(
|
|
826
|
-
colorsAttribute: GLTFAccessorPostprocessed,
|
|
827
|
-
indices: TypedArray
|
|
828
|
-
): Uint8Array {
|
|
820
|
+
function flattenColors(colorsAttribute: ConversionAccessor, indices: TypedArray): Uint8Array {
|
|
829
821
|
const components = colorsAttribute?.components || VALUES_PER_COLOR_ELEMENT;
|
|
830
822
|
const newColors = new Uint8Array(indices.length * components);
|
|
831
823
|
if (!colorsAttribute) {
|
|
@@ -888,9 +880,9 @@ function flattenBatchIds(batchedIds: NumberArray, indices: TypedArray): number[]
|
|
|
888
880
|
*/
|
|
889
881
|
function getBatchIds(
|
|
890
882
|
attributes: {
|
|
891
|
-
[key: string]:
|
|
883
|
+
[key: string]: ConversionAccessor;
|
|
892
884
|
},
|
|
893
|
-
primitive:
|
|
885
|
+
primitive: ConversionPrimitive,
|
|
894
886
|
images: (TextureImageProperties | null)[],
|
|
895
887
|
featureTexture: string | null
|
|
896
888
|
): NumberArray {
|
|
@@ -926,7 +918,7 @@ function getBatchIds(
|
|
|
926
918
|
* @returns Array of Couples I3SMaterialDefinition + texture content
|
|
927
919
|
*/
|
|
928
920
|
async function convertMaterials(
|
|
929
|
-
sourceMaterials:
|
|
921
|
+
sourceMaterials: ConversionMaterial[] = [],
|
|
930
922
|
shouldMergeMaterials: boolean
|
|
931
923
|
): Promise<I3SMaterialWithTexture[]> {
|
|
932
924
|
let materials: I3SMaterialWithTexture[] = [];
|
|
@@ -1059,7 +1051,7 @@ async function mergeMaterials(
|
|
|
1059
1051
|
* @param sourceMaterial - material object
|
|
1060
1052
|
* @returns I3S material definition and texture
|
|
1061
1053
|
*/
|
|
1062
|
-
export function convertMaterial(sourceMaterial:
|
|
1054
|
+
export function convertMaterial(sourceMaterial: ConversionMaterial): I3SMaterialWithTexture {
|
|
1063
1055
|
const material: I3SMaterialDefinition = {
|
|
1064
1056
|
doubleSided: sourceMaterial.doubleSided,
|
|
1065
1057
|
emissiveFactor: sourceMaterial.emissiveFactor?.map(c => Math.round(c * 255)) as [
|
|
@@ -1092,7 +1084,7 @@ export function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SM
|
|
|
1092
1084
|
};
|
|
1093
1085
|
}
|
|
1094
1086
|
|
|
1095
|
-
sourceMaterial.id
|
|
1087
|
+
sourceMaterial.id ||= randomUUID();
|
|
1096
1088
|
const mergedMaterials: MergedMaterial[] = [{originalMaterialId: sourceMaterial.id}];
|
|
1097
1089
|
if (!texture) {
|
|
1098
1090
|
// Should use default baseColorFactor if it is not present in source material
|
|
@@ -1156,7 +1148,7 @@ function getDefaultMaterial(): I3SMaterialDefinition {
|
|
|
1156
1148
|
* 2 arrays in format of i3s sharedResources data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/sharedResource.cmn.md
|
|
1157
1149
|
*/
|
|
1158
1150
|
function getSharedResources(
|
|
1159
|
-
gltfMaterials:
|
|
1151
|
+
gltfMaterials: ConversionMaterial[],
|
|
1160
1152
|
nodeId: number
|
|
1161
1153
|
): SharedResourcesArrays {
|
|
1162
1154
|
const i3sResources: SharedResourcesArrays = {};
|
|
@@ -1187,7 +1179,7 @@ function getSharedResources(
|
|
|
1187
1179
|
* @returns - Couple {materialDefinitionInfo, textureDefinitionInfo} extracted from gltf material data
|
|
1188
1180
|
*/
|
|
1189
1181
|
function convertGLTFMaterialToI3sSharedResources(
|
|
1190
|
-
gltfMaterial:
|
|
1182
|
+
gltfMaterial: ConversionMaterial,
|
|
1191
1183
|
nodeId: number
|
|
1192
1184
|
): {
|
|
1193
1185
|
materialDefinitionInfo: MaterialDefinitionInfo;
|
|
@@ -1270,7 +1262,7 @@ function extractSharedResourcesMaterialInfo(
|
|
|
1270
1262
|
* @returns texture definition infor for shared resource
|
|
1271
1263
|
*/
|
|
1272
1264
|
function extractSharedResourcesTextureInfo(
|
|
1273
|
-
texture:
|
|
1265
|
+
texture: ConversionTexture,
|
|
1274
1266
|
nodeId: number
|
|
1275
1267
|
): TextureDefinitionInfo {
|
|
1276
1268
|
return {
|
|
@@ -1294,7 +1286,7 @@ function extractSharedResourcesTextureInfo(
|
|
|
1294
1286
|
* @param nodeId - I3S node ID
|
|
1295
1287
|
* @returns calculate image ID according to the spec
|
|
1296
1288
|
*/
|
|
1297
|
-
function generateImageId(texture:
|
|
1289
|
+
function generateImageId(texture: ConversionTexture, nodeId: number) {
|
|
1298
1290
|
const {width, height} = texture.source?.image || {};
|
|
1299
1291
|
if (!width || !height) {
|
|
1300
1292
|
return '';
|
|
@@ -1386,7 +1378,7 @@ function getOrCreateUniqueFeatureId(
|
|
|
1386
1378
|
featuresHashArray: any[]
|
|
1387
1379
|
): number {
|
|
1388
1380
|
const batchTableStr = generateStringFromBatchTableByIndex(batchTable, index);
|
|
1389
|
-
const hash =
|
|
1381
|
+
const hash = hashString(batchTableStr);
|
|
1390
1382
|
|
|
1391
1383
|
if (featuresHashArray.includes(hash)) {
|
|
1392
1384
|
return featuresHashArray.indexOf(hash);
|
|
@@ -1797,14 +1789,14 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
|
|
|
1797
1789
|
extension: string | GLTF_EXT_feature_metadata_GLTF | GLTF_EXT_structural_metadata_GLTF | null;
|
|
1798
1790
|
} {
|
|
1799
1791
|
const extensionsWithPropertyTables = [EXT_FEATURE_METADATA, EXT_STRUCTURAL_METADATA];
|
|
1800
|
-
const extensionsUsed = tileContent?.gltf?.extensionsUsed;
|
|
1792
|
+
const extensionsUsed = tileContent?.gltf?.json.extensionsUsed;
|
|
1801
1793
|
|
|
1802
1794
|
if (!extensionsUsed) {
|
|
1803
1795
|
return {extensionName: null, extension: null};
|
|
1804
1796
|
}
|
|
1805
1797
|
|
|
1806
1798
|
let extensionName: string = '';
|
|
1807
|
-
for (const extensionItem of tileContent?.gltf?.extensionsUsed || []) {
|
|
1799
|
+
for (const extensionItem of tileContent?.gltf?.json.extensionsUsed || []) {
|
|
1808
1800
|
if (extensionsWithPropertyTables.includes(extensionItem)) {
|
|
1809
1801
|
extensionName = extensionItem;
|
|
1810
1802
|
/*
|
|
@@ -1821,7 +1813,7 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
|
|
|
1821
1813
|
return {extensionName: null, extension: null};
|
|
1822
1814
|
}
|
|
1823
1815
|
|
|
1824
|
-
const extension = tileContent?.gltf?.extensions?.[extensionName] as
|
|
1816
|
+
const extension = tileContent?.gltf?.json.extensions?.[extensionName] as
|
|
1825
1817
|
| string // EXT_mesh_features doesn't have global metadata
|
|
1826
1818
|
| GLTF_EXT_feature_metadata_GLTF
|
|
1827
1819
|
| GLTF_EXT_structural_metadata_GLTF;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import {getConversionAccessor} from './conversion-gltf';
|
|
2
|
+
import type {GLTFWithBuffers} from '@loaders.gl/gltf';
|
|
3
|
+
import type {ConversionNode} from './conversion-gltf';
|
|
4
|
+
import type {Tiles3DTileContent} from '@loaders.gl/tiles-3d/3d-tiles';
|
|
5
|
+
import {Matrix4, Vector3} from '@math.gl/core';
|
|
6
|
+
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/geometry/culling';
|
|
5
7
|
import {getImageData} from '@loaders.gl/images';
|
|
6
8
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
7
9
|
import {GLTFAttributesData} from '../types';
|
|
@@ -19,32 +21,26 @@ export function prepareDataForAttributesConversion(
|
|
|
19
21
|
tileTransform: Matrix4,
|
|
20
22
|
boundingVolume: OrientedBoundingBox | BoundingSphere
|
|
21
23
|
): GLTFAttributesData {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const gltf = tileContent.gltf;
|
|
25
|
+
const json = gltf?.json;
|
|
26
|
+
const roots =
|
|
27
|
+
(json?.scene === undefined ? undefined : json.scenes?.[json.scene]?.nodes) ||
|
|
28
|
+
json?.scenes?.[0]?.nodes ||
|
|
29
|
+
json?.nodes?.map((_, index) => index) ||
|
|
26
30
|
[];
|
|
27
|
-
|
|
28
|
-
const images =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
height,
|
|
41
|
-
width,
|
|
42
|
-
components: data.length / (width * height),
|
|
43
|
-
mimeType: imageObject.mimeType
|
|
44
|
-
};
|
|
45
|
-
}) || [];
|
|
46
|
-
|
|
47
|
-
prepareNodes(nodes);
|
|
31
|
+
const nodes = gltf ? prepareNodes(gltf, roots) : [];
|
|
32
|
+
const images = (gltf?.images || []).map((image, index) => {
|
|
33
|
+
if (!image || (image as any).compressed) return null;
|
|
34
|
+
const {data, width, height} = getImageData(image);
|
|
35
|
+
return {
|
|
36
|
+
data: Uint8Array.from(data),
|
|
37
|
+
compressed: false,
|
|
38
|
+
height,
|
|
39
|
+
width,
|
|
40
|
+
components: data.length / (width * height),
|
|
41
|
+
mimeType: json?.images?.[index]?.mimeType
|
|
42
|
+
};
|
|
43
|
+
});
|
|
48
44
|
|
|
49
45
|
const {cartographicOrigin, modelMatrix: cartesianModelMatrix} = calculateTransformProps(
|
|
50
46
|
tileContent,
|
|
@@ -60,25 +56,6 @@ export function prepareDataForAttributesConversion(
|
|
|
60
56
|
};
|
|
61
57
|
}
|
|
62
58
|
|
|
63
|
-
/**
|
|
64
|
-
* Keep only values for glTF attributes to pass data to worker thread.
|
|
65
|
-
* @param attributes - geometry attributes
|
|
66
|
-
* @returns attributes with only `value` item
|
|
67
|
-
*/
|
|
68
|
-
function getB3DMAttributesWithoutBufferView(
|
|
69
|
-
attributes: Record<string, GLTFAccessorPostprocessed>
|
|
70
|
-
): Record<string, {value: TypedArray}> {
|
|
71
|
-
const attributesWithoutBufferView: Record<string, {value: TypedArray}> = {};
|
|
72
|
-
|
|
73
|
-
for (const attributeName in attributes) {
|
|
74
|
-
attributesWithoutBufferView[attributeName] = {
|
|
75
|
-
value: attributes[attributeName].value
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return attributesWithoutBufferView;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
59
|
/**
|
|
83
60
|
* Calculate transformation properties to transform vertex attributes (POSITION, NORMAL, etc.)
|
|
84
61
|
* from METER_OFFSET coorditantes to LNGLAT_OFFSET coordinates
|
|
@@ -133,30 +110,37 @@ export function calculateTransformProps(
|
|
|
133
110
|
* Traverse all nodes to replace all sensible data with copy to avoid data corruption in worker.
|
|
134
111
|
* @param nodes
|
|
135
112
|
*/
|
|
136
|
-
function prepareNodes(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
113
|
+
function prepareNodes(
|
|
114
|
+
gltf: GLTFWithBuffers,
|
|
115
|
+
indices: number[],
|
|
116
|
+
ancestors = new Set<number>()
|
|
117
|
+
): ConversionNode[] {
|
|
118
|
+
return indices.map(index => {
|
|
119
|
+
if (ancestors.has(index)) throw new Error('Cyclic glTF node hierarchy');
|
|
120
|
+
const node = gltf.json.nodes![index];
|
|
121
|
+
const mesh = node.mesh === undefined ? undefined : gltf.json.meshes?.[node.mesh];
|
|
122
|
+
return {
|
|
123
|
+
...node,
|
|
124
|
+
mesh: mesh
|
|
125
|
+
? {
|
|
126
|
+
primitives: mesh.primitives.map(primitive => ({
|
|
127
|
+
...primitive,
|
|
128
|
+
indices:
|
|
129
|
+
primitive.indices === undefined
|
|
130
|
+
? undefined
|
|
131
|
+
: getConversionAccessor(gltf, primitive.indices),
|
|
132
|
+
attributes: Object.fromEntries(
|
|
133
|
+
Object.entries(primitive.attributes).map(([name, reference]) => [
|
|
134
|
+
name,
|
|
135
|
+
getConversionAccessor(gltf, reference)
|
|
136
|
+
])
|
|
137
|
+
),
|
|
138
|
+
material:
|
|
139
|
+
primitive.material === undefined ? undefined : {id: String(primitive.material)}
|
|
140
|
+
}))
|
|
141
|
+
}
|
|
142
|
+
: undefined,
|
|
143
|
+
children: prepareNodes(gltf, node.children || [], new Set([...ancestors, index]))
|
|
144
|
+
};
|
|
145
|
+
});
|
|
162
146
|
}
|
|
@@ -3,20 +3,12 @@ import type {
|
|
|
3
3
|
Tiles3DTileContent,
|
|
4
4
|
Tiles3DTileJSONPostprocessed,
|
|
5
5
|
Tiles3DTilesetJSONPostprocessed
|
|
6
|
-
} from '@loaders.gl/3d-tiles';
|
|
7
|
-
import {
|
|
6
|
+
} from '@loaders.gl/tiles-3d/3d-tiles';
|
|
7
|
+
import {parse3DTilesArchive} from '@loaders.gl/tiles-3d/3d-tiles';
|
|
8
8
|
import {LoaderWithParser, load} from '@loaders.gl/core';
|
|
9
|
-
import type {ReadableFile} from '@loaders.gl/loader-utils';
|
|
10
|
-
import {HttpFile, NodeFile, isBrowser} from '@loaders.gl/loader-utils';
|
|
11
|
-
import {
|
|
12
|
-
CD_HEADER_SIGNATURE,
|
|
13
|
-
ZipFileSystem,
|
|
14
|
-
parseHashTable,
|
|
15
|
-
parseZipCDFileHeader,
|
|
16
|
-
parseZipLocalFileHeader,
|
|
17
|
-
searchFromTheEnd,
|
|
18
|
-
readRange
|
|
19
|
-
} from '@loaders.gl/zip';
|
|
9
|
+
import type {ReadableFile} from '@loaders.gl/core/loader-utils';
|
|
10
|
+
import {HttpFile, NodeFile, isBrowser} from '@loaders.gl/core/loader-utils';
|
|
11
|
+
import {ZipFileSystem} from '@loaders.gl/archives/zip';
|
|
20
12
|
|
|
21
13
|
/**
|
|
22
14
|
* Load nested 3DTiles tileset. If the sourceTile is not nested tileset - do nothing
|
|
@@ -116,8 +108,7 @@ export async function loadFromArchive(
|
|
|
116
108
|
if (filename) {
|
|
117
109
|
const tz3Path = `${tz3UrlParts[0]}.3tz`;
|
|
118
110
|
const fileProvider = createReadableFile(tz3Path);
|
|
119
|
-
const
|
|
120
|
-
const archive = new Tiles3DArchive(fileProvider, hashTable, tz3Path);
|
|
111
|
+
const archive = await parse3DTilesArchive(fileProvider, undefined, tz3Path);
|
|
121
112
|
const fileSystem = new ZipFileSystem(archive);
|
|
122
113
|
const archiveLoadOptions = {
|
|
123
114
|
...loadOptions,
|
|
@@ -145,42 +136,3 @@ function createReadableFile(path: string): ReadableFile {
|
|
|
145
136
|
}
|
|
146
137
|
return isBrowser ? new HttpFile(path) : new NodeFile(path);
|
|
147
138
|
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Load hash file from 3TZ
|
|
151
|
-
* @param fileProvider - binary reader of 3TZ
|
|
152
|
-
* @returns hash table of the 3TZ file content or undefined if the hash file is not presented inside
|
|
153
|
-
*/
|
|
154
|
-
async function loadHashTable(
|
|
155
|
-
fileProvider: ReadableFile
|
|
156
|
-
): Promise<undefined | Record<string, bigint>> {
|
|
157
|
-
let hashTable: undefined | Record<string, bigint>;
|
|
158
|
-
|
|
159
|
-
const hashCDOffset = await searchFromTheEnd(fileProvider, CD_HEADER_SIGNATURE);
|
|
160
|
-
|
|
161
|
-
const cdFileHeader = await parseZipCDFileHeader(hashCDOffset, fileProvider);
|
|
162
|
-
|
|
163
|
-
// '@3dtilesIndex1@' is index file that must be the last in the archive. It allows
|
|
164
|
-
// to improve load and read performance when the archive contains a very large number
|
|
165
|
-
// of files.
|
|
166
|
-
if (cdFileHeader?.fileName === '@3dtilesIndex1@') {
|
|
167
|
-
const localFileHeader = await parseZipLocalFileHeader(
|
|
168
|
-
cdFileHeader.localHeaderOffset,
|
|
169
|
-
fileProvider
|
|
170
|
-
);
|
|
171
|
-
if (!localFileHeader) {
|
|
172
|
-
throw new Error('corrupted 3tz');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const fileDataOffset = localFileHeader.fileDataOffset;
|
|
176
|
-
const hashFile = await readRange(
|
|
177
|
-
fileProvider,
|
|
178
|
-
fileDataOffset,
|
|
179
|
-
fileDataOffset + localFileHeader.compressedSize
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
hashTable = parseHashTable(hashFile);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return hashTable;
|
|
186
|
-
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type {Mbs, Node3DIndexDocument, Obb} from '@loaders.gl/i3s';
|
|
2
|
-
import {
|
|
1
|
+
import type {Mbs, Node3DIndexDocument, Obb} from '@loaders.gl/tiles-3d/i3s';
|
|
2
|
+
import {
|
|
3
|
+
OrientedBoundingBox,
|
|
4
|
+
BoundingSphere,
|
|
5
|
+
makeOrientedBoundingBoxFromQuaternion
|
|
6
|
+
} from '@math.gl/geometry/culling';
|
|
3
7
|
import {Vector3} from '@math.gl/core';
|
|
4
8
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
5
9
|
|
|
@@ -85,7 +89,7 @@ function createBoundingSphereFromTileMbs(mbs: Mbs): BoundingSphere {
|
|
|
85
89
|
*/
|
|
86
90
|
function createBoundingBoxFromTileObb(obb: Obb): OrientedBoundingBox {
|
|
87
91
|
const {center, halfSize, quaternion} = obb;
|
|
88
|
-
return
|
|
92
|
+
return makeOrientedBoundingBoxFromQuaternion(center, halfSize, quaternion);
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
/**
|
|
@@ -5,12 +5,11 @@ import {
|
|
|
5
5
|
Node3DIndexDocument,
|
|
6
6
|
NodeInPage,
|
|
7
7
|
NodeReference
|
|
8
|
-
} from '@loaders.gl/i3s';
|
|
9
|
-
import
|
|
10
|
-
import {v4 as uuidv4} from 'uuid';
|
|
8
|
+
} from '@loaders.gl/tiles-3d/i3s';
|
|
9
|
+
import {randomUUID} from 'node:crypto';
|
|
11
10
|
import {openJson, writeFileForSlpk} from '../../lib/utils/file-utils';
|
|
12
11
|
import I3SConverter from '../i3s-converter';
|
|
13
|
-
import {
|
|
12
|
+
import {createNode} from '../json-templates/node';
|
|
14
13
|
import {I3SConvertedResources} from '../types';
|
|
15
14
|
import {DumpMetadata} from '../../lib/utils/conversion-dump';
|
|
16
15
|
|
|
@@ -97,7 +96,7 @@ export class NodeIndexDocument {
|
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
/**
|
|
100
|
-
* Add neighbors
|
|
99
|
+
* Add neighbors, save leaf documents and children, then release finalized child data.
|
|
101
100
|
*/
|
|
102
101
|
public async addNeighbors(): Promise<void> {
|
|
103
102
|
if (this.finalized) {
|
|
@@ -130,7 +129,10 @@ export class NodeIndexDocument {
|
|
|
130
129
|
}
|
|
131
130
|
await childNode.save();
|
|
132
131
|
}
|
|
133
|
-
//
|
|
132
|
+
// Internal documents were saved during child traversal. A root mesh leaf has no such traversal.
|
|
133
|
+
if (!this.children.length) {
|
|
134
|
+
await this.save();
|
|
135
|
+
}
|
|
134
136
|
this.finalize();
|
|
135
137
|
}
|
|
136
138
|
|
|
@@ -250,7 +252,7 @@ export class NodeIndexDocument {
|
|
|
250
252
|
*/
|
|
251
253
|
static createRootNodeIndexDocument(boundingVolumes: BoundingVolumes): Node3DIndexDocument {
|
|
252
254
|
const root0data = {
|
|
253
|
-
version: `{${
|
|
255
|
+
version: `{${randomUUID().toUpperCase()}}`,
|
|
254
256
|
id: 'root',
|
|
255
257
|
level: 0,
|
|
256
258
|
lodSelection: [
|
|
@@ -266,7 +268,7 @@ export class NodeIndexDocument {
|
|
|
266
268
|
...boundingVolumes,
|
|
267
269
|
children: []
|
|
268
270
|
};
|
|
269
|
-
return
|
|
271
|
+
return createNode(root0data);
|
|
270
272
|
}
|
|
271
273
|
|
|
272
274
|
/**
|
|
@@ -305,7 +307,7 @@ export class NodeIndexDocument {
|
|
|
305
307
|
children: [],
|
|
306
308
|
neighbors: []
|
|
307
309
|
};
|
|
308
|
-
const node =
|
|
310
|
+
const node = createNode(nodeData);
|
|
309
311
|
|
|
310
312
|
if (nodeInPage.mesh) {
|
|
311
313
|
node.geometryData = [{href: './geometries/0'}];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {join} from 'path';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {NodeInPage} from '@loaders.gl/i3s';
|
|
2
|
+
import {createMetadata} from '../json-templates/metadata';
|
|
3
|
+
import {NodeInPage} from '@loaders.gl/tiles-3d/i3s';
|
|
5
4
|
import {isFileExists, openJson} from '../../lib/utils/file-utils';
|
|
6
5
|
import I3SConverter from '../i3s-converter';
|
|
7
6
|
|
|
@@ -197,7 +196,7 @@ export default class NodePages {
|
|
|
197
196
|
* Save metadata file (for slpk only)
|
|
198
197
|
*/
|
|
199
198
|
async saveMetadata(): Promise<void> {
|
|
200
|
-
const metadata =
|
|
199
|
+
const metadata = createMetadata({nodeCount: this.nodesCounter});
|
|
201
200
|
const compress = false;
|
|
202
201
|
await this.converter.writeQueue.enqueue({
|
|
203
202
|
archiveKey: 'metadata.json',
|