@loaders.gl/i3s 4.0.0-alpha.4 → 4.0.0-alpha.5
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/dist/bundle.d.ts +2 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/dist.min.js +10374 -0
- package/dist/i3s-attribute-loader.d.ts +14 -0
- package/dist/i3s-attribute-loader.d.ts.map +1 -0
- package/dist/i3s-attribute-loader.js +1 -1
- package/dist/i3s-building-scene-layer-loader.d.ts +6 -0
- package/dist/i3s-building-scene-layer-loader.d.ts.map +1 -0
- package/dist/i3s-building-scene-layer-loader.js +1 -1
- package/dist/i3s-content-loader.d.ts +6 -0
- package/dist/i3s-content-loader.d.ts.map +1 -0
- package/dist/i3s-content-loader.js +1 -1
- package/dist/i3s-content-worker.js +391 -270
- package/dist/i3s-loader.d.ts +6 -0
- package/dist/i3s-loader.d.ts.map +1 -0
- package/dist/i3s-loader.js +1 -1
- package/dist/i3s-node-page-loader.d.ts +6 -0
- package/dist/i3s-node-page-loader.d.ts.map +1 -0
- package/dist/i3s-node-page-loader.js +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/helpers/i3s-nodepages-tiles.d.ts +73 -0
- package/dist/lib/helpers/i3s-nodepages-tiles.d.ts.map +1 -0
- package/dist/lib/helpers/i3s-nodepages-tiles.js +33 -23
- package/dist/lib/helpers/i3s-nodepages-tiles.js.map +1 -1
- package/dist/lib/parsers/constants.d.ts +40 -0
- package/dist/lib/parsers/constants.d.ts.map +1 -0
- package/dist/lib/parsers/constants.js +54 -38
- package/dist/lib/parsers/constants.js.map +1 -1
- package/dist/lib/parsers/parse-i3s-attribute.d.ts +10 -0
- package/dist/lib/parsers/parse-i3s-attribute.d.ts.map +1 -0
- package/dist/lib/parsers/parse-i3s-building-scene-layer.d.ts +9 -0
- package/dist/lib/parsers/parse-i3s-building-scene-layer.d.ts.map +1 -0
- package/dist/lib/parsers/parse-i3s-building-scene-layer.js +2 -0
- package/dist/lib/parsers/parse-i3s-building-scene-layer.js.map +1 -1
- package/dist/lib/parsers/parse-i3s-tile-content.d.ts +4 -0
- package/dist/lib/parsers/parse-i3s-tile-content.d.ts.map +1 -0
- package/dist/lib/parsers/parse-i3s-tile-content.js +76 -79
- package/dist/lib/parsers/parse-i3s-tile-content.js.map +1 -1
- package/dist/lib/parsers/parse-i3s.d.ts +6 -0
- package/dist/lib/parsers/parse-i3s.d.ts.map +1 -0
- package/dist/lib/parsers/parse-i3s.js +40 -25
- package/dist/lib/parsers/parse-i3s.js.map +1 -1
- package/dist/lib/utils/convert-i3s-obb-to-mbs.d.ts +2 -0
- package/dist/lib/utils/convert-i3s-obb-to-mbs.d.ts.map +1 -0
- package/dist/lib/utils/url-utils.d.ts +22 -0
- package/dist/lib/utils/url-utils.d.ts.map +1 -0
- package/dist/lib/utils/url-utils.js +2 -3
- package/dist/lib/utils/url-utils.js.map +1 -1
- package/dist/types.d.ts +643 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -1
- package/dist/types.js.map +1 -1
- package/dist/workers/i3s-content-worker.d.ts +2 -0
- package/dist/workers/i3s-content-worker.d.ts.map +1 -0
- package/package.json +12 -12
- package/src/index.ts +3 -3
- package/src/lib/helpers/i3s-nodepages-tiles.ts +71 -55
- package/src/lib/parsers/constants.ts +67 -54
- package/src/lib/parsers/parse-i3s-building-scene-layer.ts +2 -1
- package/src/lib/parsers/parse-i3s-tile-content.ts +150 -146
- package/src/lib/parsers/parse-i3s.ts +48 -37
- package/src/lib/utils/url-utils.ts +7 -7
- package/src/types.ts +412 -73
|
@@ -2,68 +2,80 @@ import type {TypedArray} from '@loaders.gl/schema';
|
|
|
2
2
|
import {load, parse} from '@loaders.gl/core';
|
|
3
3
|
import {Vector3, Matrix4} from '@math.gl/core';
|
|
4
4
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
5
|
-
|
|
6
5
|
import type {LoaderOptions, LoaderContext} from '@loaders.gl/loader-utils';
|
|
7
6
|
import {ImageLoader} from '@loaders.gl/images';
|
|
8
|
-
import {DracoLoader} from '@loaders.gl/draco';
|
|
7
|
+
import {DracoLoader, DracoMesh} from '@loaders.gl/draco';
|
|
9
8
|
import {BasisLoader, CompressedTextureLoader} from '@loaders.gl/textures';
|
|
10
9
|
|
|
11
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
I3STilesetHeader,
|
|
12
|
+
I3STileHeader,
|
|
13
|
+
FeatureAttribute,
|
|
14
|
+
VertexAttribute,
|
|
15
|
+
I3SMeshAttributes,
|
|
16
|
+
I3SMeshAttribute,
|
|
17
|
+
TileContentTexture,
|
|
18
|
+
HeaderAttributeProperty,
|
|
19
|
+
I3SMaterialDefinition
|
|
20
|
+
} from '../../types';
|
|
12
21
|
import {getUrlWithToken} from '../utils/url-utils';
|
|
13
22
|
|
|
14
|
-
import {
|
|
15
|
-
GL_TYPE_MAP,
|
|
16
|
-
TYPE_ARRAY_MAP,
|
|
17
|
-
SIZEOF,
|
|
18
|
-
I3S_NAMED_HEADER_ATTRIBUTES,
|
|
19
|
-
I3S_NAMED_VERTEX_ATTRIBUTES,
|
|
20
|
-
I3S_NAMED_GEOMETRY_ATTRIBUTES,
|
|
21
|
-
COORDINATE_SYSTEM
|
|
22
|
-
} from './constants';
|
|
23
|
+
import {GL_TYPE_MAP, getConstructorForDataFormat, sizeOf, COORDINATE_SYSTEM} from './constants';
|
|
23
24
|
|
|
24
25
|
const scratchVector = new Vector3([0, 0, 0]);
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
function getLoaderForTextureFormat(textureFormat?: 'jpg' | 'png' | 'ktx-etc2' | 'dds' | 'ktx2') {
|
|
28
|
+
switch (textureFormat) {
|
|
29
|
+
case 'ktx-etc2':
|
|
30
|
+
case 'dds':
|
|
31
|
+
return CompressedTextureLoader;
|
|
32
|
+
case 'ktx2':
|
|
33
|
+
return BasisLoader;
|
|
34
|
+
case 'jpg':
|
|
35
|
+
case 'png':
|
|
36
|
+
default:
|
|
37
|
+
return ImageLoader;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
33
40
|
|
|
34
41
|
const I3S_ATTRIBUTE_TYPE = 'i3s-attribute-type';
|
|
35
42
|
|
|
36
43
|
export async function parseI3STileContent(
|
|
37
44
|
arrayBuffer: ArrayBuffer,
|
|
38
|
-
tile:
|
|
39
|
-
tileset:
|
|
45
|
+
tile: I3STileHeader,
|
|
46
|
+
tileset: I3STilesetHeader,
|
|
40
47
|
options?: LoaderOptions,
|
|
41
48
|
context?: LoaderContext
|
|
42
49
|
) {
|
|
43
50
|
tile.content = tile.content || {};
|
|
44
51
|
tile.content.featureIds = tile.content.featureIds || null;
|
|
45
52
|
|
|
46
|
-
// construct featureData from defaultGeometrySchema;
|
|
47
|
-
tile.content.featureData = constructFeatureDataStruct(tile, tileset);
|
|
48
53
|
tile.content.attributes = {};
|
|
49
54
|
|
|
50
55
|
if (tile.textureUrl) {
|
|
51
56
|
const url = getUrlWithToken(tile.textureUrl, options?.i3s?.token);
|
|
52
|
-
const loader =
|
|
53
|
-
// @ts-ignore context must be defined
|
|
57
|
+
const loader = getLoaderForTextureFormat(tile.textureFormat);
|
|
54
58
|
const response = await fetch(url);
|
|
55
59
|
const arrayBuffer = await response.arrayBuffer();
|
|
56
60
|
|
|
57
61
|
if (options?.i3s.decodeTextures) {
|
|
58
62
|
if (loader === ImageLoader) {
|
|
59
63
|
const options = {...tile.textureLoaderOptions, image: {type: 'data'}};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
try {
|
|
65
|
+
// @ts-ignore context must be defined
|
|
66
|
+
// Image constructor is not supported in worker thread.
|
|
67
|
+
// Do parsing image data on the main thread by using context to avoid worker issues.
|
|
68
|
+
tile.content.texture = await context.parse(arrayBuffer, options);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
// context object is different between worker and node.js conversion script.
|
|
71
|
+
// To prevent error we parse data in ordinary way if it is not parsed by using context.
|
|
72
|
+
tile.content.texture = await parse(arrayBuffer, loader, options);
|
|
73
|
+
}
|
|
64
74
|
} else if (loader === CompressedTextureLoader || loader === BasisLoader) {
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
let texture = await load(arrayBuffer, loader, tile.textureLoaderOptions);
|
|
76
|
+
if (loader === BasisLoader) {
|
|
77
|
+
texture = texture[0];
|
|
78
|
+
}
|
|
67
79
|
tile.content.texture = {
|
|
68
80
|
compressed: true,
|
|
69
81
|
mipmaps: false,
|
|
@@ -82,35 +94,36 @@ export async function parseI3STileContent(
|
|
|
82
94
|
tile.content.texture = null;
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
return await parseI3SNodeGeometry(arrayBuffer, tile,
|
|
97
|
+
return await parseI3SNodeGeometry(arrayBuffer, tile, tileset, options);
|
|
86
98
|
}
|
|
87
99
|
|
|
88
100
|
/* eslint-disable max-statements */
|
|
89
101
|
async function parseI3SNodeGeometry(
|
|
90
102
|
arrayBuffer: ArrayBuffer,
|
|
91
|
-
tile:
|
|
92
|
-
|
|
93
|
-
|
|
103
|
+
tile: I3STileHeader,
|
|
104
|
+
tileset: I3STilesetHeader,
|
|
105
|
+
options?: LoaderOptions
|
|
94
106
|
) {
|
|
95
107
|
if (!tile.content) {
|
|
96
108
|
return tile;
|
|
97
109
|
}
|
|
98
110
|
|
|
99
111
|
const content = tile.content;
|
|
100
|
-
let attributes;
|
|
101
|
-
let vertexCount;
|
|
102
|
-
let byteOffset = 0;
|
|
103
|
-
let featureCount = 0;
|
|
112
|
+
let attributes: I3SMeshAttributes;
|
|
113
|
+
let vertexCount: number;
|
|
114
|
+
let byteOffset: number = 0;
|
|
115
|
+
let featureCount: number = 0;
|
|
116
|
+
let indices: TypedArray | undefined;
|
|
104
117
|
|
|
105
118
|
if (tile.isDracoGeometry) {
|
|
106
|
-
const decompressedGeometry = await parse(arrayBuffer, DracoLoader, {
|
|
119
|
+
const decompressedGeometry: DracoMesh = await parse(arrayBuffer, DracoLoader, {
|
|
107
120
|
draco: {
|
|
108
121
|
attributeNameEntry: I3S_ATTRIBUTE_TYPE
|
|
109
122
|
}
|
|
110
123
|
});
|
|
111
|
-
|
|
124
|
+
// @ts-expect-error
|
|
112
125
|
vertexCount = decompressedGeometry.header.vertexCount;
|
|
113
|
-
|
|
126
|
+
indices = decompressedGeometry.indices?.value;
|
|
114
127
|
const {
|
|
115
128
|
POSITION,
|
|
116
129
|
NORMAL,
|
|
@@ -126,8 +139,7 @@ async function parseI3SNodeGeometry(
|
|
|
126
139
|
color: COLOR_0,
|
|
127
140
|
uv0: TEXCOORD_0,
|
|
128
141
|
uvRegion,
|
|
129
|
-
id: featureIndex
|
|
130
|
-
indices
|
|
142
|
+
id: featureIndex
|
|
131
143
|
};
|
|
132
144
|
|
|
133
145
|
updateAttributesMetadata(attributes, decompressedGeometry);
|
|
@@ -138,10 +150,14 @@ async function parseI3SNodeGeometry(
|
|
|
138
150
|
flattenFeatureIdsByFeatureIndices(attributes, featureIds);
|
|
139
151
|
}
|
|
140
152
|
} else {
|
|
141
|
-
const {
|
|
142
|
-
|
|
153
|
+
const {
|
|
154
|
+
vertexAttributes,
|
|
155
|
+
ordering: attributesOrder,
|
|
156
|
+
featureAttributes,
|
|
157
|
+
featureAttributeOrder
|
|
158
|
+
} = tileset.store.defaultGeometrySchema;
|
|
143
159
|
// First 8 bytes reserved for header (vertexCount and featureCount)
|
|
144
|
-
const headers = parseHeaders(
|
|
160
|
+
const headers = parseHeaders(tileset, arrayBuffer);
|
|
145
161
|
byteOffset = headers.byteOffset;
|
|
146
162
|
vertexCount = headers.vertexCount;
|
|
147
163
|
featureCount = headers.featureCount;
|
|
@@ -171,7 +187,7 @@ async function parseI3SNodeGeometry(
|
|
|
171
187
|
!options?.i3s?.coordinateSystem ||
|
|
172
188
|
options.i3s.coordinateSystem === COORDINATE_SYSTEM.METER_OFFSETS
|
|
173
189
|
) {
|
|
174
|
-
const
|
|
190
|
+
const enuMatrix = parsePositions(attributes.position, tile);
|
|
175
191
|
content.modelMatrix = enuMatrix.invert();
|
|
176
192
|
content.coordinateSystem = COORDINATE_SYSTEM.METER_OFFSETS;
|
|
177
193
|
} else {
|
|
@@ -186,7 +202,7 @@ async function parseI3SNodeGeometry(
|
|
|
186
202
|
texCoords: attributes.uv0,
|
|
187
203
|
uvRegions: normalizeAttribute(attributes.uvRegion) // Normalize from UInt16
|
|
188
204
|
};
|
|
189
|
-
content.indices =
|
|
205
|
+
content.indices = indices || null;
|
|
190
206
|
|
|
191
207
|
if (attributes.id && attributes.id.value) {
|
|
192
208
|
tile.content.featureIds = attributes.id.value;
|
|
@@ -210,7 +226,10 @@ async function parseI3SNodeGeometry(
|
|
|
210
226
|
* @param decompressedGeometry
|
|
211
227
|
* @param attributes
|
|
212
228
|
*/
|
|
213
|
-
function updateAttributesMetadata(
|
|
229
|
+
function updateAttributesMetadata(
|
|
230
|
+
attributes: I3SMeshAttributes,
|
|
231
|
+
decompressedGeometry: DracoMesh
|
|
232
|
+
): void {
|
|
214
233
|
for (const key in decompressedGeometry.loaderData.attributes) {
|
|
215
234
|
const dracoAttribute = decompressedGeometry.loaderData.attributes[key];
|
|
216
235
|
|
|
@@ -230,20 +249,23 @@ function updateAttributesMetadata(attributes, decompressedGeometry) {
|
|
|
230
249
|
/**
|
|
231
250
|
* Do concatenation of attribute objects.
|
|
232
251
|
* Done as separate fucntion to avoid ts errors.
|
|
233
|
-
* @param
|
|
234
|
-
* @param
|
|
235
|
-
* @returns
|
|
252
|
+
* @param normalizedVertexAttributes
|
|
253
|
+
* @param normalizedFeatureAttributes
|
|
254
|
+
* @returns - result of attributes concatenation.
|
|
236
255
|
*/
|
|
237
|
-
function concatAttributes(
|
|
256
|
+
function concatAttributes(
|
|
257
|
+
normalizedVertexAttributes: I3SMeshAttributes,
|
|
258
|
+
normalizedFeatureAttributes: I3SMeshAttributes
|
|
259
|
+
): I3SMeshAttributes {
|
|
238
260
|
return {...normalizedVertexAttributes, ...normalizedFeatureAttributes};
|
|
239
261
|
}
|
|
240
262
|
|
|
241
263
|
/**
|
|
242
264
|
* Normalize attribute to range [0..1] . Eg. convert colors buffer from [255,255,255,255] to [1,1,1,1]
|
|
243
|
-
* @param
|
|
244
|
-
* @returns
|
|
265
|
+
* @param attribute - geometry attribute
|
|
266
|
+
* @returns - geometry attribute in right format
|
|
245
267
|
*/
|
|
246
|
-
function normalizeAttribute(attribute) {
|
|
268
|
+
function normalizeAttribute(attribute: I3SMeshAttribute): I3SMeshAttribute {
|
|
247
269
|
if (!attribute) {
|
|
248
270
|
return attribute;
|
|
249
271
|
}
|
|
@@ -251,49 +273,27 @@ function normalizeAttribute(attribute) {
|
|
|
251
273
|
return attribute;
|
|
252
274
|
}
|
|
253
275
|
|
|
254
|
-
function
|
|
255
|
-
// seed featureData from defaultGeometrySchema
|
|
256
|
-
const defaultGeometrySchema = tileset.store.defaultGeometrySchema;
|
|
257
|
-
const featureData = defaultGeometrySchema;
|
|
258
|
-
// populate the vertex attributes value types and values per element
|
|
259
|
-
for (const geometryAttribute in I3S_NAMED_GEOMETRY_ATTRIBUTES) {
|
|
260
|
-
for (const namedAttribute in I3S_NAMED_VERTEX_ATTRIBUTES) {
|
|
261
|
-
const attribute = defaultGeometrySchema[geometryAttribute][namedAttribute];
|
|
262
|
-
if (attribute) {
|
|
263
|
-
const {byteOffset = 0, count = 0, valueType, valuesPerElement} = attribute;
|
|
264
|
-
|
|
265
|
-
featureData[geometryAttribute][namedAttribute] = {
|
|
266
|
-
valueType,
|
|
267
|
-
valuesPerElement,
|
|
268
|
-
byteOffset,
|
|
269
|
-
count
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
featureData.attributesOrder = defaultGeometrySchema.ordering;
|
|
276
|
-
return featureData;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function parseHeaders(content, buffer) {
|
|
276
|
+
function parseHeaders(tileset: I3STilesetHeader, arrayBuffer: ArrayBuffer) {
|
|
280
277
|
let byteOffset = 0;
|
|
281
278
|
// First 8 bytes reserved for header (vertexCount and featurecount)
|
|
282
279
|
let vertexCount = 0;
|
|
283
280
|
let featureCount = 0;
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
281
|
+
for (const {property, type} of tileset.store.defaultGeometrySchema.header) {
|
|
282
|
+
const TypedArrayTypeHeader = getConstructorForDataFormat(type);
|
|
283
|
+
switch (property) {
|
|
284
|
+
case HeaderAttributeProperty.vertexCount:
|
|
285
|
+
vertexCount = new TypedArrayTypeHeader(arrayBuffer, 0, 4)[0];
|
|
286
|
+
byteOffset += sizeOf(type);
|
|
287
|
+
break;
|
|
288
|
+
case HeaderAttributeProperty.featureCount:
|
|
289
|
+
featureCount = new TypedArrayTypeHeader(arrayBuffer, 4, 4)[0];
|
|
290
|
+
byteOffset += sizeOf(type);
|
|
291
|
+
break;
|
|
292
|
+
default:
|
|
293
|
+
break;
|
|
295
294
|
}
|
|
296
295
|
}
|
|
296
|
+
|
|
297
297
|
return {
|
|
298
298
|
vertexCount,
|
|
299
299
|
featureCount,
|
|
@@ -304,18 +304,19 @@ function parseHeaders(content, buffer) {
|
|
|
304
304
|
/* eslint-enable max-statements */
|
|
305
305
|
|
|
306
306
|
function normalizeAttributes(
|
|
307
|
-
arrayBuffer,
|
|
308
|
-
byteOffset,
|
|
309
|
-
vertexAttributes,
|
|
310
|
-
vertexCount,
|
|
311
|
-
attributesOrder
|
|
307
|
+
arrayBuffer: ArrayBuffer,
|
|
308
|
+
byteOffset: number,
|
|
309
|
+
vertexAttributes: VertexAttribute | FeatureAttribute,
|
|
310
|
+
vertexCount: number,
|
|
311
|
+
attributesOrder: string[]
|
|
312
312
|
) {
|
|
313
|
-
const attributes = {};
|
|
313
|
+
const attributes: I3SMeshAttributes = {};
|
|
314
314
|
|
|
315
315
|
// the order of attributes depend on the order being added to the vertexAttributes object
|
|
316
316
|
for (const attribute of attributesOrder) {
|
|
317
317
|
if (vertexAttributes[attribute]) {
|
|
318
|
-
const {valueType, valuesPerElement}
|
|
318
|
+
const {valueType, valuesPerElement}: {valueType: string; valuesPerElement: number} =
|
|
319
|
+
vertexAttributes[attribute];
|
|
319
320
|
// update count and byteOffset count by calculating from defaultGeometrySchema + binnary content
|
|
320
321
|
const count = vertexCount;
|
|
321
322
|
// protect from arrayBuffer read overunns by NOT assuming node has regions always even though its declared in defaultGeometrySchema.
|
|
@@ -328,12 +329,12 @@ function normalizeAttributes(
|
|
|
328
329
|
break;
|
|
329
330
|
}
|
|
330
331
|
const buffer = arrayBuffer.slice(byteOffset);
|
|
331
|
-
let value:
|
|
332
|
+
let value: TypedArray;
|
|
332
333
|
|
|
333
334
|
if (valueType === 'UInt64') {
|
|
334
|
-
value = parseUint64Values(buffer, count * valuesPerElement,
|
|
335
|
+
value = parseUint64Values(buffer, count * valuesPerElement, sizeOf(valueType));
|
|
335
336
|
} else {
|
|
336
|
-
const TypedArrayType =
|
|
337
|
+
const TypedArrayType = getConstructorForDataFormat(valueType);
|
|
337
338
|
value = new TypedArrayType(buffer, 0, count * valuesPerElement);
|
|
338
339
|
}
|
|
339
340
|
|
|
@@ -345,7 +346,6 @@ function normalizeAttributes(
|
|
|
345
346
|
|
|
346
347
|
switch (attribute) {
|
|
347
348
|
case 'color':
|
|
348
|
-
// @ts-ignore
|
|
349
349
|
attributes.color.normalized = true;
|
|
350
350
|
break;
|
|
351
351
|
case 'position':
|
|
@@ -354,7 +354,7 @@ function normalizeAttributes(
|
|
|
354
354
|
default:
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
byteOffset = byteOffset + count * valuesPerElement *
|
|
357
|
+
byteOffset = byteOffset + count * valuesPerElement * sizeOf(valueType);
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
|
|
@@ -372,7 +372,7 @@ function parseUint64Values(
|
|
|
372
372
|
buffer: ArrayBuffer,
|
|
373
373
|
elementsCount: number,
|
|
374
374
|
attributeSize: number
|
|
375
|
-
):
|
|
375
|
+
): Uint32Array {
|
|
376
376
|
const values: number[] = [];
|
|
377
377
|
const dataView = new DataView(buffer);
|
|
378
378
|
let offset = 0;
|
|
@@ -388,10 +388,10 @@ function parseUint64Values(
|
|
|
388
388
|
offset += attributeSize;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
return values;
|
|
391
|
+
return new Uint32Array(values);
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
-
function parsePositions(attribute, tile) {
|
|
394
|
+
function parsePositions(attribute: I3SMeshAttribute, tile: I3STileHeader): Matrix4 {
|
|
395
395
|
const mbs = tile.mbs;
|
|
396
396
|
const value = attribute.value;
|
|
397
397
|
const metadata = attribute.metadata;
|
|
@@ -402,20 +402,22 @@ function parsePositions(attribute, tile) {
|
|
|
402
402
|
Ellipsoid.WGS84.eastNorthUpToFixedFrame(cartesianOrigin, enuMatrix);
|
|
403
403
|
attribute.value = offsetsToCartesians(value, metadata, cartographicOrigin);
|
|
404
404
|
|
|
405
|
-
return
|
|
406
|
-
enuMatrix
|
|
407
|
-
};
|
|
405
|
+
return enuMatrix;
|
|
408
406
|
}
|
|
409
407
|
|
|
410
408
|
/**
|
|
411
409
|
* Converts position coordinates to absolute cartesian coordinates
|
|
412
|
-
* @param
|
|
413
|
-
* @param
|
|
410
|
+
* @param vertices - "position" attribute data
|
|
411
|
+
* @param metadata - When the geometry is DRACO compressed, contain position attribute's metadata
|
|
414
412
|
* https://github.com/Esri/i3s-spec/blob/master/docs/1.7/compressedAttributes.cmn.md
|
|
415
|
-
* @param
|
|
416
|
-
* @returns
|
|
413
|
+
* @param cartographicOrigin - Cartographic origin coordinates
|
|
414
|
+
* @returns - converted "position" data
|
|
417
415
|
*/
|
|
418
|
-
function offsetsToCartesians(
|
|
416
|
+
function offsetsToCartesians(
|
|
417
|
+
vertices: number[] | TypedArray,
|
|
418
|
+
metadata: any = {},
|
|
419
|
+
cartographicOrigin: Vector3
|
|
420
|
+
): Float64Array {
|
|
419
421
|
const positions = new Float64Array(vertices.length);
|
|
420
422
|
const scaleX = (metadata['i3s-scale_x'] && metadata['i3s-scale_x'].double) || 1;
|
|
421
423
|
const scaleY = (metadata['i3s-scale_y'] && metadata['i3s-scale_y'].double) || 1;
|
|
@@ -441,10 +443,10 @@ function offsetsToCartesians(vertices, metadata = {}, cartographicOrigin) {
|
|
|
441
443
|
* @param positions positions attribute
|
|
442
444
|
* @returns Matrix4 - model matrix for geometry transformation
|
|
443
445
|
*/
|
|
444
|
-
function getModelMatrix(positions) {
|
|
446
|
+
function getModelMatrix(positions: I3SMeshAttribute): Matrix4 {
|
|
445
447
|
const metadata = positions.metadata;
|
|
446
|
-
const scaleX = metadata?.['i3s-scale_x']?.double || 1;
|
|
447
|
-
const scaleY = metadata?.['i3s-scale_y']?.double || 1;
|
|
448
|
+
const scaleX: number = metadata?.['i3s-scale_x']?.double || 1;
|
|
449
|
+
const scaleY: number = metadata?.['i3s-scale_y']?.double || 1;
|
|
448
450
|
const modelMatrix = new Matrix4();
|
|
449
451
|
modelMatrix[0] = scaleX;
|
|
450
452
|
modelMatrix[5] = scaleY;
|
|
@@ -453,12 +455,12 @@ function getModelMatrix(positions) {
|
|
|
453
455
|
|
|
454
456
|
/**
|
|
455
457
|
* Makes a glTF-compatible PBR material from an I3S material definition
|
|
456
|
-
* @param
|
|
458
|
+
* @param materialDefinition - i3s material definition
|
|
457
459
|
* https://github.com/Esri/i3s-spec/blob/master/docs/1.7/materialDefinitions.cmn.md
|
|
458
|
-
* @param
|
|
460
|
+
* @param texture - texture image
|
|
459
461
|
* @returns {object}
|
|
460
462
|
*/
|
|
461
|
-
function makePbrMaterial(materialDefinition, texture) {
|
|
463
|
+
function makePbrMaterial(materialDefinition?: I3SMaterialDefinition, texture?: TileContentTexture) {
|
|
462
464
|
let pbrMaterial;
|
|
463
465
|
if (materialDefinition) {
|
|
464
466
|
pbrMaterial = {
|
|
@@ -496,17 +498,19 @@ function makePbrMaterial(materialDefinition, texture) {
|
|
|
496
498
|
);
|
|
497
499
|
}
|
|
498
500
|
|
|
499
|
-
|
|
501
|
+
if (texture) {
|
|
502
|
+
setMaterialTexture(pbrMaterial, texture);
|
|
503
|
+
}
|
|
500
504
|
|
|
501
505
|
return pbrMaterial;
|
|
502
506
|
}
|
|
503
507
|
|
|
504
508
|
/**
|
|
505
509
|
* Convert color from [255,255,255,255] to [1,1,1,1]
|
|
506
|
-
* @param
|
|
507
|
-
* @returns
|
|
510
|
+
* @param colorFactor - color array
|
|
511
|
+
* @returns - new color array
|
|
508
512
|
*/
|
|
509
|
-
function convertColorFormat(colorFactor) {
|
|
513
|
+
function convertColorFormat(colorFactor: number[]): number[] {
|
|
510
514
|
const normalizedColor = [...colorFactor];
|
|
511
515
|
for (let index = 0; index < colorFactor.length; index++) {
|
|
512
516
|
normalizedColor[index] = colorFactor[index] / 255;
|
|
@@ -517,10 +521,10 @@ function convertColorFormat(colorFactor) {
|
|
|
517
521
|
/**
|
|
518
522
|
* Set texture in PBR material
|
|
519
523
|
* @param {object} material - i3s material definition
|
|
520
|
-
* @param
|
|
521
|
-
* @returns
|
|
524
|
+
* @param image - texture image
|
|
525
|
+
* @returns
|
|
522
526
|
*/
|
|
523
|
-
function setMaterialTexture(material, image) {
|
|
527
|
+
function setMaterialTexture(material, image: TileContentTexture): void {
|
|
524
528
|
const texture = {source: {image}};
|
|
525
529
|
// I3SLoader now support loading only one texture. This elseif sequence will assign this texture to one of
|
|
526
530
|
// properties defined in materialDefinition
|
|
@@ -548,10 +552,10 @@ function setMaterialTexture(material, image) {
|
|
|
548
552
|
|
|
549
553
|
/**
|
|
550
554
|
* Flatten feature ids using face ranges
|
|
551
|
-
* @param
|
|
552
|
-
* @returns
|
|
555
|
+
* @param normalizedFeatureAttributes
|
|
556
|
+
* @returns
|
|
553
557
|
*/
|
|
554
|
-
function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes) {
|
|
558
|
+
function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes: I3SMeshAttributes): void {
|
|
555
559
|
const {id, faceRange} = normalizedFeatureAttributes;
|
|
556
560
|
|
|
557
561
|
if (!id || !faceRange) {
|
|
@@ -584,11 +588,14 @@ function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes) {
|
|
|
584
588
|
|
|
585
589
|
/**
|
|
586
590
|
* Flatten feature ids using featureIndices
|
|
587
|
-
* @param
|
|
588
|
-
* @param
|
|
589
|
-
* @returns
|
|
591
|
+
* @param attributes
|
|
592
|
+
* @param featureIds
|
|
593
|
+
* @returns
|
|
590
594
|
*/
|
|
591
|
-
function flattenFeatureIdsByFeatureIndices(
|
|
595
|
+
function flattenFeatureIdsByFeatureIndices(
|
|
596
|
+
attributes: I3SMeshAttributes,
|
|
597
|
+
featureIds: Int32Array
|
|
598
|
+
): void {
|
|
592
599
|
const featureIndices = attributes.id.value;
|
|
593
600
|
const result = new Float32Array(featureIndices.length);
|
|
594
601
|
|
|
@@ -601,14 +608,11 @@ function flattenFeatureIdsByFeatureIndices(attributes, featureIds) {
|
|
|
601
608
|
|
|
602
609
|
/**
|
|
603
610
|
* Flatten feature ids using featureIndices
|
|
604
|
-
* @param
|
|
605
|
-
* @returns
|
|
611
|
+
* @param featureIndex
|
|
612
|
+
* @returns
|
|
606
613
|
*/
|
|
607
|
-
function getFeatureIdsFromFeatureIndexMetadata(
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
featureIndex.metadata['i3s-feature-ids'] &&
|
|
612
|
-
featureIndex.metadata['i3s-feature-ids'].intArray
|
|
613
|
-
);
|
|
614
|
+
function getFeatureIdsFromFeatureIndexMetadata(
|
|
615
|
+
featureIndex: I3SMeshAttribute
|
|
616
|
+
): Int32Array | undefined {
|
|
617
|
+
return featureIndex?.metadata?.['i3s-feature-ids']?.intArray;
|
|
614
618
|
}
|
|
@@ -4,69 +4,80 @@ import {load} from '@loaders.gl/core';
|
|
|
4
4
|
import {TILE_TYPE, TILE_REFINEMENT, TILESET_TYPE} from '@loaders.gl/tiles';
|
|
5
5
|
import I3SNodePagesTiles from '../helpers/i3s-nodepages-tiles';
|
|
6
6
|
import {generateTileAttributeUrls, getUrlWithToken} from '../utils/url-utils';
|
|
7
|
+
import {
|
|
8
|
+
I3STilesetHeader,
|
|
9
|
+
I3STileHeader,
|
|
10
|
+
Mbs,
|
|
11
|
+
I3SMinimalNodeData,
|
|
12
|
+
Node3DIndexDocument
|
|
13
|
+
} from '../../types';
|
|
14
|
+
import type {LoaderOptions, LoaderContext} from '@loaders.gl/loader-utils';
|
|
7
15
|
|
|
8
|
-
export function normalizeTileData(tile, options, context) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (tile.featureData) {
|
|
12
|
-
tile.featureUrl = `${tile.url}/${tile.featureData[0].href}`;
|
|
13
|
-
}
|
|
14
|
-
|
|
16
|
+
export function normalizeTileData(tile : Node3DIndexDocument, options : LoaderOptions, context: LoaderContext): I3STileHeader {
|
|
17
|
+
const url: string = context.url || '';
|
|
18
|
+
let contentUrl: string | undefined;
|
|
15
19
|
if (tile.geometryData) {
|
|
16
|
-
|
|
20
|
+
contentUrl = `${url}/${tile.geometryData[0].href}`;
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
let textureUrl: string | undefined;
|
|
19
24
|
if (tile.textureData) {
|
|
20
|
-
|
|
25
|
+
textureUrl = `${url}/${tile.textureData[0].href}`;
|
|
21
26
|
}
|
|
22
27
|
|
|
28
|
+
let attributeUrls: string[] | undefined;
|
|
23
29
|
if (tile.attributeData) {
|
|
24
|
-
|
|
30
|
+
attributeUrls = generateTileAttributeUrls(url, tile);
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
return normalizeTileNonUrlData(
|
|
33
|
+
return normalizeTileNonUrlData({
|
|
34
|
+
...tile,
|
|
35
|
+
url,
|
|
36
|
+
contentUrl,
|
|
37
|
+
textureUrl,
|
|
38
|
+
attributeUrls,
|
|
39
|
+
isDracoGeometry: false
|
|
40
|
+
});
|
|
28
41
|
}
|
|
29
42
|
|
|
30
|
-
export function normalizeTileNonUrlData(tile) {
|
|
31
|
-
const box =
|
|
32
|
-
|
|
33
|
-
...Ellipsoid.WGS84.cartographicToCartesian(tile.obb.center), // cartesian center of box
|
|
34
|
-
...tile.obb.halfSize, // halfSize
|
|
35
|
-
...tile.obb.quaternion // quaternion
|
|
36
|
-
]
|
|
37
|
-
: undefined;
|
|
38
|
-
let sphere;
|
|
43
|
+
export function normalizeTileNonUrlData(tile : I3SMinimalNodeData): I3STileHeader {
|
|
44
|
+
const boundingVolume: {box?: number[]; sphere?: number[]} = {};
|
|
45
|
+
let mbs: Mbs = [0, 0, 0, 1];
|
|
39
46
|
if (tile.mbs) {
|
|
40
|
-
|
|
47
|
+
mbs = tile.mbs;
|
|
48
|
+
boundingVolume.sphere = [
|
|
41
49
|
...Ellipsoid.WGS84.cartographicToCartesian(tile.mbs.slice(0, 3)), // cartesian center of sphere
|
|
42
50
|
tile.mbs[3] // radius of sphere
|
|
51
|
+
] as Mbs;
|
|
52
|
+
} else if (tile.obb) {
|
|
53
|
+
boundingVolume.box = [
|
|
54
|
+
...Ellipsoid.WGS84.cartographicToCartesian(tile.obb.center), // cartesian center of box
|
|
55
|
+
...tile.obb.halfSize, // halfSize
|
|
56
|
+
...tile.obb.quaternion // quaternion
|
|
43
57
|
];
|
|
44
|
-
} else if (box) {
|
|
45
58
|
const obb = new OrientedBoundingBox().fromCenterHalfSizeQuaternion(
|
|
46
|
-
box.slice(0, 3),
|
|
59
|
+
boundingVolume.box.slice(0, 3),
|
|
47
60
|
tile.obb.halfSize,
|
|
48
61
|
tile.obb.quaternion
|
|
49
62
|
);
|
|
50
63
|
const boundingSphere = obb.getBoundingSphere();
|
|
51
|
-
sphere = [...boundingSphere.center, boundingSphere.radius];
|
|
52
|
-
|
|
64
|
+
boundingVolume.sphere = [...boundingSphere.center , boundingSphere.radius] as Mbs;
|
|
65
|
+
mbs = [...tile.obb.center, boundingSphere.radius] as Mbs;
|
|
53
66
|
}
|
|
54
67
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// TODO only support replacement for now
|
|
64
|
-
tile.refine = TILE_REFINEMENT.REPLACE;
|
|
68
|
+
const lodMetricType = tile.lodSelection?.[0].metricType;
|
|
69
|
+
const lodMetricValue = tile.lodSelection?.[0].maxError;
|
|
70
|
+
const transformMatrix = tile.transform;
|
|
71
|
+
const type = TILE_TYPE.MESH;
|
|
72
|
+
/**
|
|
73
|
+
* I3S specification supports only REPLACE
|
|
74
|
+
*/
|
|
75
|
+
const refine = TILE_REFINEMENT.REPLACE;
|
|
65
76
|
|
|
66
|
-
return tile;
|
|
77
|
+
return {...tile, mbs, boundingVolume, lodMetricType, lodMetricValue, transformMatrix, type, refine};
|
|
67
78
|
}
|
|
68
79
|
|
|
69
|
-
export async function normalizeTilesetData(tileset, options, context) {
|
|
80
|
+
export async function normalizeTilesetData(tileset : I3STilesetHeader, options : LoaderOptions, context: LoaderContext) {
|
|
70
81
|
tileset.url = context.url;
|
|
71
82
|
|
|
72
83
|
if (tileset.nodePages) {
|