@xeokit/xeokit-sdk 2.5.2-beta-7 → 2.5.2-beta-9

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.
@@ -0,0 +1,663 @@
1
+ /*
2
+ Parser for .XKT Format V10
3
+ */
4
+
5
+ import {utils} from "../../../viewer/scene/utils.js";
6
+ import * as p from "./lib/pako.js";
7
+ import {math} from "../../../viewer/scene/math/math.js";
8
+ import {geometryCompressionUtils} from "../../../viewer/scene/math/geometryCompressionUtils.js";
9
+ import {JPEGMediaType, PNGMediaType} from "../../../viewer/scene/constants/constants.js";
10
+
11
+ let pako = window.pako || p;
12
+ if (!pako.inflate) { // See https://github.com/nodeca/pako/issues/97
13
+ pako = pako.default;
14
+ }
15
+
16
+ const tempVec4a = math.vec4();
17
+ const tempVec4b = math.vec4();
18
+
19
+ const NUM_TEXTURE_ATTRIBUTES = 9;
20
+
21
+ function extract(elements) {
22
+
23
+ let i = 0;
24
+
25
+ return {
26
+ metadata: elements[i++],
27
+ textureData: elements[i++],
28
+ eachTextureDataPortion: elements[i++],
29
+ eachTextureAttributes: elements[i++],
30
+ positions: elements[i++],
31
+ normals: elements[i++],
32
+ colors: elements[i++],
33
+ uvs: elements[i++],
34
+ indices: elements[i++],
35
+ edgeIndices: elements[i++],
36
+ eachTextureSetTextures: elements[i++],
37
+ matrices: elements[i++],
38
+ reusedGeometriesDecodeMatrix: elements[i++],
39
+ eachGeometryPrimitiveType: elements[i++],
40
+ eachGeometryPositionsPortion: elements[i++],
41
+ eachGeometryNormalsPortion: elements[i++],
42
+ eachGeometryColorsPortion: elements[i++],
43
+ eachGeometryUVsPortion: elements[i++],
44
+ eachGeometryIndicesPortion: elements[i++],
45
+ eachGeometryEdgeIndicesPortion: elements[i++],
46
+ eachMeshGeometriesPortion: elements[i++],
47
+ eachMeshMatricesPortion: elements[i++],
48
+ eachMeshTextureSet: elements[i++],
49
+ eachMeshMaterialAttributes: elements[i++],
50
+ eachEntityId: elements[i++],
51
+ eachEntityMeshesPortion: elements[i++],
52
+ eachTileAABB: elements[i++],
53
+ eachTileEntitiesPortion: elements[i++]
54
+ };
55
+ }
56
+
57
+ function inflate(deflatedData) {
58
+
59
+
60
+ const zip = false;
61
+
62
+ function inflate(array, options) {
63
+ return (array.length === 0) ? [] : (zip ? pako.inflate(array, options).buffer : array.buffer);
64
+ }
65
+
66
+ return {
67
+ metadata: JSON.parse(pako.inflate(deflatedData.metadata, {to: 'string'})),
68
+ textureData: new Uint8Array(inflate(deflatedData.textureData)), // <<----------------------------- ??? ZIPPing to blame?
69
+ eachTextureDataPortion: new Uint32Array(inflate(deflatedData.eachTextureDataPortion)),
70
+ eachTextureAttributes: new Uint16Array(inflate(deflatedData.eachTextureAttributes)),
71
+ positions: new Uint16Array(inflate(deflatedData.positions)),
72
+ normals: new Int8Array(inflate(deflatedData.normals)),
73
+ colors: new Uint8Array(inflate(deflatedData.colors)),
74
+ uvs: new Float32Array(inflate(deflatedData.uvs)),
75
+ indices: new Uint32Array(inflate(deflatedData.indices)),
76
+ edgeIndices: new Uint32Array(inflate(deflatedData.edgeIndices)),
77
+ eachTextureSetTextures: new Int32Array(inflate(deflatedData.eachTextureSetTextures)),
78
+ matrices: new Float32Array(inflate(deflatedData.matrices)),
79
+ reusedGeometriesDecodeMatrix: new Float32Array(inflate(deflatedData.reusedGeometriesDecodeMatrix)),
80
+ eachGeometryPrimitiveType: new Uint8Array(inflate(deflatedData.eachGeometryPrimitiveType)),
81
+ eachGeometryPositionsPortion: new Uint32Array(inflate(deflatedData.eachGeometryPositionsPortion)),
82
+ eachGeometryNormalsPortion: new Uint32Array(inflate(deflatedData.eachGeometryNormalsPortion)),
83
+ eachGeometryColorsPortion: new Uint32Array(inflate(deflatedData.eachGeometryColorsPortion)),
84
+ eachGeometryUVsPortion: new Uint32Array(inflate(deflatedData.eachGeometryUVsPortion)),
85
+ eachGeometryIndicesPortion: new Uint32Array(inflate(deflatedData.eachGeometryIndicesPortion)),
86
+ eachGeometryEdgeIndicesPortion: new Uint32Array(inflate(deflatedData.eachGeometryEdgeIndicesPortion)),
87
+ eachMeshGeometriesPortion: new Uint32Array(inflate(deflatedData.eachMeshGeometriesPortion)),
88
+ eachMeshMatricesPortion: new Uint32Array(inflate(deflatedData.eachMeshMatricesPortion)),
89
+ eachMeshTextureSet: new Int32Array(inflate(deflatedData.eachMeshTextureSet)), // Can be -1
90
+ eachMeshMaterialAttributes: new Uint8Array(inflate(deflatedData.eachMeshMaterialAttributes)),
91
+ eachEntityId: JSON.parse(pako.inflate(deflatedData.eachEntityId, {to: 'string'})),
92
+ eachEntityMeshesPortion: new Uint32Array(inflate(deflatedData.eachEntityMeshesPortion)),
93
+ eachTileAABB: new Float64Array(inflate(deflatedData.eachTileAABB)),
94
+ eachTileEntitiesPortion: new Uint32Array(inflate(deflatedData.eachTileEntitiesPortion)),
95
+ };
96
+ }
97
+
98
+ const decompressColor = (function () {
99
+ const floatColor = new Float32Array(3);
100
+ return function (intColor) {
101
+ floatColor[0] = intColor[0] / 255.0;
102
+ floatColor[1] = intColor[1] / 255.0;
103
+ floatColor[2] = intColor[2] / 255.0;
104
+ return floatColor;
105
+ };
106
+ })();
107
+
108
+ const imagDataToImage = (function () {
109
+ const canvas = document.createElement('canvas');
110
+ const context = canvas.getContext('2d');
111
+ return function (imagedata) {
112
+ canvas.width = imagedata.width;
113
+ canvas.height = imagedata.height;
114
+ context.putImageData(imagedata, 0, 0);
115
+ return canvas.toDataURL();
116
+ };
117
+ })();
118
+
119
+ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) {
120
+
121
+ const modelPartId = manifestCtx.getNextId();
122
+
123
+ const metadata = inflatedData.metadata;
124
+ const textureData = inflatedData.textureData;
125
+ const eachTextureDataPortion = inflatedData.eachTextureDataPortion;
126
+ const eachTextureAttributes = inflatedData.eachTextureAttributes;
127
+ const positions = inflatedData.positions;
128
+ const normals = inflatedData.normals;
129
+ const colors = inflatedData.colors;
130
+ const uvs = inflatedData.uvs;
131
+ const indices = inflatedData.indices;
132
+ const edgeIndices = inflatedData.edgeIndices;
133
+ const eachTextureSetTextures = inflatedData.eachTextureSetTextures;
134
+ const matrices = inflatedData.matrices;
135
+ const reusedGeometriesDecodeMatrix = inflatedData.reusedGeometriesDecodeMatrix;
136
+ const eachGeometryPrimitiveType = inflatedData.eachGeometryPrimitiveType;
137
+ const eachGeometryPositionsPortion = inflatedData.eachGeometryPositionsPortion;
138
+ const eachGeometryNormalsPortion = inflatedData.eachGeometryNormalsPortion;
139
+ const eachGeometryColorsPortion = inflatedData.eachGeometryColorsPortion;
140
+ const eachGeometryUVsPortion = inflatedData.eachGeometryUVsPortion;
141
+ const eachGeometryIndicesPortion = inflatedData.eachGeometryIndicesPortion;
142
+ const eachGeometryEdgeIndicesPortion = inflatedData.eachGeometryEdgeIndicesPortion;
143
+ const eachMeshGeometriesPortion = inflatedData.eachMeshGeometriesPortion;
144
+ const eachMeshMatricesPortion = inflatedData.eachMeshMatricesPortion;
145
+ const eachMeshTextureSet = inflatedData.eachMeshTextureSet;
146
+ const eachMeshMaterialAttributes = inflatedData.eachMeshMaterialAttributes;
147
+ const eachEntityId = inflatedData.eachEntityId;
148
+ const eachEntityMeshesPortion = inflatedData.eachEntityMeshesPortion;
149
+ const eachTileAABB = inflatedData.eachTileAABB;
150
+ const eachTileEntitiesPortion = inflatedData.eachTileEntitiesPortion;
151
+
152
+ const numTextures = eachTextureDataPortion.length;
153
+ const numTextureSets = eachTextureSetTextures.length / 5;
154
+ const numGeometries = eachGeometryPositionsPortion.length;
155
+ const numMeshes = eachMeshGeometriesPortion.length;
156
+ const numEntities = eachEntityMeshesPortion.length;
157
+ const numTiles = eachTileEntitiesPortion.length;
158
+
159
+ if (metaModel) {
160
+ metaModel.loadData(metadata, {
161
+ includeTypes: options.includeTypes,
162
+ excludeTypes: options.excludeTypes,
163
+ globalizeObjectIds: options.globalizeObjectIds
164
+ }); // Can be empty
165
+ }
166
+
167
+ // Create textures
168
+
169
+ for (let textureIndex = 0; textureIndex < numTextures; textureIndex++) {
170
+ const atLastTexture = (textureIndex === (numTextures - 1));
171
+ const textureDataPortionStart = eachTextureDataPortion[textureIndex];
172
+ const textureDataPortionEnd = atLastTexture ? textureData.length : (eachTextureDataPortion[textureIndex + 1]);
173
+
174
+ const textureDataPortionSize = textureDataPortionEnd - textureDataPortionStart;
175
+ const textureDataPortionExists = (textureDataPortionSize > 0);
176
+
177
+ const textureAttrBaseIdx = (textureIndex * NUM_TEXTURE_ATTRIBUTES);
178
+
179
+ const compressed = (eachTextureAttributes[textureAttrBaseIdx + 0] === 1);
180
+ const mediaType = eachTextureAttributes[textureAttrBaseIdx + 1];
181
+ const width = eachTextureAttributes[textureAttrBaseIdx + 2];
182
+ const height = eachTextureAttributes[textureAttrBaseIdx + 3];
183
+ const minFilter = eachTextureAttributes[textureAttrBaseIdx + 4];
184
+ const magFilter = eachTextureAttributes[textureAttrBaseIdx + 5]; // LinearFilter | NearestFilter
185
+ const wrapS = eachTextureAttributes[textureAttrBaseIdx + 6]; // ClampToEdgeWrapping | MirroredRepeatWrapping | RepeatWrapping
186
+ const wrapT = eachTextureAttributes[textureAttrBaseIdx + 7]; // ClampToEdgeWrapping | MirroredRepeatWrapping | RepeatWrapping
187
+ const wrapR = eachTextureAttributes[textureAttrBaseIdx + 8]; // ClampToEdgeWrapping | MirroredRepeatWrapping | RepeatWrapping
188
+
189
+ if (textureDataPortionExists) {
190
+
191
+ const imageDataSubarray = new Uint8Array(textureData.subarray(textureDataPortionStart, textureDataPortionEnd));
192
+ const arrayBuffer = imageDataSubarray.buffer;
193
+ const textureId = `${modelPartId}-texture-${textureIndex}`;
194
+
195
+ if (compressed) {
196
+
197
+ sceneModel.createTexture({
198
+ id: textureId,
199
+ buffers: [arrayBuffer],
200
+ minFilter,
201
+ magFilter,
202
+ wrapS,
203
+ wrapT,
204
+ wrapR
205
+ });
206
+
207
+ } else {
208
+
209
+ const mimeType = mediaType === JPEGMediaType ? "image/jpeg" : (mediaType === PNGMediaType ? "image/png" : "image/gif");
210
+ const blob = new Blob([arrayBuffer], {type: mimeType});
211
+ const urlCreator = window.URL || window.webkitURL;
212
+ const imageUrl = urlCreator.createObjectURL(blob);
213
+ const img = document.createElement('img');
214
+ img.src = imageUrl;
215
+
216
+ sceneModel.createTexture({
217
+ id: textureId,
218
+ image: img,
219
+ //mediaType,
220
+ minFilter,
221
+ magFilter,
222
+ wrapS,
223
+ wrapT,
224
+ wrapR
225
+ });
226
+ }
227
+ }
228
+ }
229
+
230
+ // Create texture sets
231
+
232
+ for (let textureSetIndex = 0; textureSetIndex < numTextureSets; textureSetIndex++) {
233
+ const eachTextureSetTexturesIndex = textureSetIndex * 5;
234
+ const textureSetId = `${modelPartId}-textureSet-${textureSetIndex}`;
235
+ const colorTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 0];
236
+ const metallicRoughnessTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 1];
237
+ const normalsTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 2];
238
+ const emissiveTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 3];
239
+ const occlusionTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 4];
240
+ sceneModel.createTextureSet({
241
+ id: textureSetId,
242
+ colorTextureId: colorTextureIndex >= 0 ? `${modelPartId}-texture-${colorTextureIndex}` : null,
243
+ normalsTextureId: normalsTextureIndex >= 0 ? `${modelPartId}-texture-${normalsTextureIndex}` : null,
244
+ metallicRoughnessTextureId: metallicRoughnessTextureIndex >= 0 ? `${modelPartId}-texture-${metallicRoughnessTextureIndex}` : null,
245
+ emissiveTextureId: emissiveTextureIndex >= 0 ? `${modelPartId}-texture-${emissiveTextureIndex}` : null,
246
+ occlusionTextureId: occlusionTextureIndex >= 0 ? `${modelPartId}-texture-${occlusionTextureIndex}` : null
247
+ });
248
+ }
249
+
250
+ // Count instances of each geometry
251
+
252
+ const geometryReuseCounts = new Uint32Array(numGeometries);
253
+
254
+ for (let meshIndex = 0; meshIndex < numMeshes; meshIndex++) {
255
+ const geometryIndex = eachMeshGeometriesPortion[meshIndex];
256
+ if (geometryReuseCounts[geometryIndex] !== undefined) {
257
+ geometryReuseCounts[geometryIndex]++;
258
+ } else {
259
+ geometryReuseCounts[geometryIndex] = 1;
260
+ }
261
+ }
262
+
263
+ // Iterate over tiles
264
+
265
+ const tileCenter = math.vec3();
266
+ const rtcAABB = math.AABB3();
267
+
268
+ const geometryArraysCache = {};
269
+
270
+ for (let tileIndex = 0; tileIndex < numTiles; tileIndex++) {
271
+
272
+ const lastTileIndex = (numTiles - 1);
273
+
274
+ const atLastTile = (tileIndex === lastTileIndex);
275
+
276
+ const firstTileEntityIndex = eachTileEntitiesPortion [tileIndex];
277
+ const lastTileEntityIndex = atLastTile ? (numEntities - 1) : (eachTileEntitiesPortion[tileIndex + 1] - 1);
278
+
279
+ const tileAABBIndex = tileIndex * 6;
280
+ const tileAABB = eachTileAABB.subarray(tileAABBIndex, tileAABBIndex + 6);
281
+
282
+ math.getAABB3Center(tileAABB, tileCenter);
283
+
284
+ rtcAABB[0] = tileAABB[0] - tileCenter[0];
285
+ rtcAABB[1] = tileAABB[1] - tileCenter[1];
286
+ rtcAABB[2] = tileAABB[2] - tileCenter[2];
287
+ rtcAABB[3] = tileAABB[3] - tileCenter[0];
288
+ rtcAABB[4] = tileAABB[4] - tileCenter[1];
289
+ rtcAABB[5] = tileAABB[5] - tileCenter[2];
290
+
291
+ const tileDecodeMatrix = geometryCompressionUtils.createPositionsDecodeMatrix(rtcAABB);
292
+
293
+ const geometryCreatedInTile = {};
294
+
295
+ // Iterate over each tile's entities
296
+
297
+ for (let tileEntityIndex = firstTileEntityIndex; tileEntityIndex <= lastTileEntityIndex; tileEntityIndex++) {
298
+
299
+ const xktEntityId = eachEntityId[tileEntityIndex];
300
+
301
+ const entityId = options.globalizeObjectIds ? math.globalizeObjectId(sceneModel.id, xktEntityId) : xktEntityId;
302
+
303
+ const finalTileEntityIndex = (numEntities - 1);
304
+ const atLastTileEntity = (tileEntityIndex === finalTileEntityIndex);
305
+ const firstMeshIndex = eachEntityMeshesPortion [tileEntityIndex];
306
+ const lastMeshIndex = atLastTileEntity ? (eachMeshGeometriesPortion.length - 1) : (eachEntityMeshesPortion[tileEntityIndex + 1] - 1);
307
+
308
+ const meshIds = [];
309
+
310
+ const metaObject = viewer.metaScene.metaObjects[entityId];
311
+ const entityDefaults = {};
312
+ const meshDefaults = {};
313
+
314
+ if (metaObject) {
315
+
316
+ // Mask loading of object types
317
+
318
+ if (options.excludeTypesMap && metaObject.type && options.excludeTypesMap[metaObject.type]) {
319
+ continue;
320
+ }
321
+
322
+ if (options.includeTypesMap && metaObject.type && (!options.includeTypesMap[metaObject.type])) {
323
+ continue;
324
+ }
325
+
326
+ // Get initial property values for object types
327
+
328
+ const props = options.objectDefaults ? options.objectDefaults[metaObject.type] || options.objectDefaults["DEFAULT"] : null;
329
+
330
+ if (props) {
331
+ if (props.visible === false) {
332
+ entityDefaults.visible = false;
333
+ }
334
+ if (props.pickable === false) {
335
+ entityDefaults.pickable = false;
336
+ }
337
+ if (props.colorize) {
338
+ meshDefaults.color = props.colorize;
339
+ }
340
+ if (props.opacity !== undefined && props.opacity !== null) {
341
+ meshDefaults.opacity = props.opacity;
342
+ }
343
+ if (props.metallic !== undefined && props.metallic !== null) {
344
+ meshDefaults.metallic = props.metallic;
345
+ }
346
+ if (props.roughness !== undefined && props.roughness !== null) {
347
+ meshDefaults.roughness = props.roughness;
348
+ }
349
+ }
350
+
351
+ } else {
352
+ if (options.excludeUnclassifiedObjects) {
353
+ continue;
354
+ }
355
+ }
356
+
357
+ // Iterate each entity's meshes
358
+
359
+ for (let meshIndex = firstMeshIndex; meshIndex <= lastMeshIndex; meshIndex++) {
360
+
361
+ const geometryIndex = eachMeshGeometriesPortion[meshIndex];
362
+ const geometryReuseCount = geometryReuseCounts[geometryIndex];
363
+ const isReusedGeometry = (geometryReuseCount > 1);
364
+
365
+ const atLastGeometry = (geometryIndex === (numGeometries - 1));
366
+
367
+ const textureSetIndex = eachMeshTextureSet[meshIndex];
368
+
369
+ const textureSetId = (textureSetIndex >= 0) ? `${modelPartId}-textureSet-${textureSetIndex}` : null;
370
+
371
+ const meshColor = decompressColor(eachMeshMaterialAttributes.subarray((meshIndex * 6), (meshIndex * 6) + 3));
372
+ const meshOpacity = eachMeshMaterialAttributes[(meshIndex * 6) + 3] / 255.0;
373
+ const meshMetallic = eachMeshMaterialAttributes[(meshIndex * 6) + 4] / 255.0;
374
+ const meshRoughness = eachMeshMaterialAttributes[(meshIndex * 6) + 5] / 255.0;
375
+
376
+ const meshId = manifestCtx.getNextId();
377
+
378
+ if (isReusedGeometry) {
379
+
380
+ // Create mesh for multi-use geometry - create (or reuse) geometry, create mesh using that geometry
381
+
382
+ const meshMatrixIndex = eachMeshMatricesPortion[meshIndex];
383
+ const meshMatrix = matrices.slice(meshMatrixIndex, meshMatrixIndex + 16);
384
+
385
+ const geometryId = `${modelPartId}-geometry.${tileIndex}.${geometryIndex}`; // These IDs are local to the SceneModel
386
+
387
+ let geometryArrays = geometryArraysCache[geometryId];
388
+
389
+ if (!geometryArrays) {
390
+ geometryArrays = {
391
+ batchThisMesh: (!options.reuseGeometries)
392
+ };
393
+ const primitiveType = eachGeometryPrimitiveType[geometryIndex];
394
+ let geometryValid = false;
395
+ switch (primitiveType) {
396
+ case 0:
397
+ geometryArrays.primitiveName = "solid";
398
+ geometryArrays.geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
399
+ geometryArrays.geometryNormals = normals.subarray(eachGeometryNormalsPortion [geometryIndex], atLastGeometry ? normals.length : eachGeometryNormalsPortion [geometryIndex + 1]);
400
+ geometryArrays.geometryUVs = uvs.subarray(eachGeometryUVsPortion [geometryIndex], atLastGeometry ? uvs.length : eachGeometryUVsPortion [geometryIndex + 1]);
401
+ geometryArrays.geometryIndices = indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry ? indices.length : eachGeometryIndicesPortion [geometryIndex + 1]);
402
+ geometryArrays.geometryEdgeIndices = edgeIndices.subarray(eachGeometryEdgeIndicesPortion [geometryIndex], atLastGeometry ? edgeIndices.length : eachGeometryEdgeIndicesPortion [geometryIndex + 1]);
403
+ geometryValid = (geometryArrays.geometryPositions.length > 0 && geometryArrays.geometryIndices.length > 0);
404
+ break;
405
+ case 1:
406
+ geometryArrays.primitiveName = "surface";
407
+ geometryArrays.geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
408
+ geometryArrays.geometryNormals = normals.subarray(eachGeometryNormalsPortion [geometryIndex], atLastGeometry ? normals.length : eachGeometryNormalsPortion [geometryIndex + 1]);
409
+ geometryArrays.geometryUVs = uvs.subarray(eachGeometryUVsPortion [geometryIndex], atLastGeometry ? uvs.length : eachGeometryUVsPortion [geometryIndex + 1]);
410
+ geometryArrays.geometryIndices = indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry ? indices.length : eachGeometryIndicesPortion [geometryIndex + 1]);
411
+ geometryArrays.geometryEdgeIndices = edgeIndices.subarray(eachGeometryEdgeIndicesPortion [geometryIndex], atLastGeometry ? edgeIndices.length : eachGeometryEdgeIndicesPortion [geometryIndex + 1]);
412
+ geometryValid = (geometryArrays.geometryPositions.length > 0 && geometryArrays.geometryIndices.length > 0);
413
+ break;
414
+ case 2:
415
+ geometryArrays.primitiveName = "points";
416
+ geometryArrays.geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
417
+ geometryArrays.geometryColors = colors.subarray(eachGeometryColorsPortion [geometryIndex], atLastGeometry ? colors.length : eachGeometryColorsPortion [geometryIndex + 1]);
418
+ geometryValid = (geometryArrays.geometryPositions.length > 0);
419
+ break;
420
+ case 3:
421
+ geometryArrays.primitiveName = "lines";
422
+ geometryArrays.geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
423
+ geometryArrays.geometryIndices = indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry ? indices.length : eachGeometryIndicesPortion [geometryIndex + 1]);
424
+ geometryValid = (geometryArrays.geometryPositions.length > 0 && geometryArrays.geometryIndices.length > 0);
425
+ break;
426
+ case 4:
427
+ geometryArrays.primitiveName = "lines";
428
+ geometryArrays.geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
429
+ geometryArrays.geometryIndices = lineStripToLines(
430
+ geometryArrays.geometryPositions,
431
+ indices.subarray(eachGeometryIndicesPortion [geometryIndex],
432
+ atLastGeometry
433
+ ? indices.length
434
+ : eachGeometryIndicesPortion [geometryIndex + 1]));
435
+ geometryValid = (geometryArrays.geometryPositions.length > 0 && geometryArrays.geometryIndices.length > 0);
436
+ break;
437
+ default:
438
+ continue;
439
+ }
440
+
441
+ if (!geometryValid) {
442
+ geometryArrays = null;
443
+ }
444
+
445
+ if (geometryArrays) {
446
+ if (geometryReuseCount > 1000) { // TODO: Heuristic to force batching of instanced geometry beyond a certain reuse count (or budget)?
447
+ // geometryArrays.batchThisMesh = true;
448
+ }
449
+ if (geometryArrays.geometryPositions.length > 1000) { // TODO: Heuristic to force batching on instanced geometry above certain vertex size?
450
+ // geometryArrays.batchThisMesh = true;
451
+ }
452
+ if (geometryArrays.batchThisMesh) {
453
+ geometryArrays.decompressedPositions = new Float32Array(geometryArrays.geometryPositions.length);
454
+ geometryArrays.transformedAndRecompressedPositions = new Uint16Array(geometryArrays.geometryPositions.length)
455
+ const geometryPositions = geometryArrays.geometryPositions;
456
+ const decompressedPositions = geometryArrays.decompressedPositions;
457
+ for (let i = 0, len = geometryPositions.length; i < len; i += 3) {
458
+ decompressedPositions[i + 0] = geometryPositions[i + 0] * reusedGeometriesDecodeMatrix[0] + reusedGeometriesDecodeMatrix[12];
459
+ decompressedPositions[i + 1] = geometryPositions[i + 1] * reusedGeometriesDecodeMatrix[5] + reusedGeometriesDecodeMatrix[13];
460
+ decompressedPositions[i + 2] = geometryPositions[i + 2] * reusedGeometriesDecodeMatrix[10] + reusedGeometriesDecodeMatrix[14];
461
+ }
462
+ geometryArrays.geometryPositions = null;
463
+ geometryArraysCache[geometryId] = geometryArrays;
464
+ }
465
+ }
466
+ }
467
+
468
+ if (geometryArrays) {
469
+
470
+ if (geometryArrays.batchThisMesh) {
471
+
472
+ const decompressedPositions = geometryArrays.decompressedPositions;
473
+ const transformedAndRecompressedPositions = geometryArrays.transformedAndRecompressedPositions;
474
+
475
+ for (let i = 0, len = decompressedPositions.length; i < len; i += 3) {
476
+ tempVec4a[0] = decompressedPositions[i + 0];
477
+ tempVec4a[1] = decompressedPositions[i + 1];
478
+ tempVec4a[2] = decompressedPositions[i + 2];
479
+ tempVec4a[3] = 1;
480
+ math.transformVec4(meshMatrix, tempVec4a, tempVec4b);
481
+ geometryCompressionUtils.compressPosition(tempVec4b, rtcAABB, tempVec4a)
482
+ transformedAndRecompressedPositions[i + 0] = tempVec4a[0];
483
+ transformedAndRecompressedPositions[i + 1] = tempVec4a[1];
484
+ transformedAndRecompressedPositions[i + 2] = tempVec4a[2];
485
+ }
486
+
487
+ sceneModel.createMesh(utils.apply(meshDefaults, {
488
+ id: meshId,
489
+ textureSetId,
490
+ origin: tileCenter,
491
+ primitive: geometryArrays.primitiveName,
492
+ positionsCompressed: transformedAndRecompressedPositions,
493
+ normalsCompressed: geometryArrays.geometryNormals,
494
+ uv: geometryArrays.geometryUVs,
495
+ colorsCompressed: geometryArrays.geometryColors,
496
+ indices: geometryArrays.geometryIndices,
497
+ edgeIndices: geometryArrays.geometryEdgeIndices,
498
+ positionsDecodeMatrix: tileDecodeMatrix,
499
+ color: meshColor,
500
+ metallic: meshMetallic,
501
+ roughness: meshRoughness,
502
+ opacity: meshOpacity
503
+ }));
504
+
505
+ meshIds.push(meshId);
506
+
507
+ } else {
508
+
509
+ if (!geometryCreatedInTile[geometryId]) {
510
+
511
+ sceneModel.createGeometry({
512
+ id: geometryId,
513
+ primitive: geometryArrays.primitiveName,
514
+ positionsCompressed: geometryArrays.geometryPositions,
515
+ normalsCompressed: geometryArrays.geometryNormals,
516
+ uv: geometryArrays.geometryUVs,
517
+ colorsCompressed: geometryArrays.geometryColors,
518
+ indices: geometryArrays.geometryIndices,
519
+ edgeIndices: geometryArrays.geometryEdgeIndices,
520
+ positionsDecodeMatrix: reusedGeometriesDecodeMatrix
521
+ });
522
+
523
+ geometryCreatedInTile[geometryId] = true;
524
+ }
525
+
526
+ sceneModel.createMesh(utils.apply(meshDefaults, {
527
+ id: meshId,
528
+ geometryId,
529
+ textureSetId,
530
+ matrix: meshMatrix,
531
+ color: meshColor,
532
+ metallic: meshMetallic,
533
+ roughness: meshRoughness,
534
+ opacity: meshOpacity,
535
+ origin: tileCenter
536
+ }));
537
+
538
+ meshIds.push(meshId);
539
+ }
540
+ }
541
+
542
+ } else { // Do not reuse geometry
543
+
544
+ const primitiveType = eachGeometryPrimitiveType[geometryIndex];
545
+
546
+ let primitiveName;
547
+ let geometryPositions;
548
+ let geometryNormals;
549
+ let geometryUVs;
550
+ let geometryColors;
551
+ let geometryIndices;
552
+ let geometryEdgeIndices;
553
+ let geometryValid = false;
554
+
555
+ switch (primitiveType) {
556
+ case 0:
557
+ primitiveName = "solid";
558
+ geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
559
+ geometryNormals = normals.subarray(eachGeometryNormalsPortion [geometryIndex], atLastGeometry ? normals.length : eachGeometryNormalsPortion [geometryIndex + 1]);
560
+ geometryUVs = uvs.subarray(eachGeometryUVsPortion [geometryIndex], atLastGeometry ? uvs.length : eachGeometryUVsPortion [geometryIndex + 1]);
561
+ geometryIndices = indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry ? indices.length : eachGeometryIndicesPortion [geometryIndex + 1]);
562
+ geometryEdgeIndices = edgeIndices.subarray(eachGeometryEdgeIndicesPortion [geometryIndex], atLastGeometry ? edgeIndices.length : eachGeometryEdgeIndicesPortion [geometryIndex + 1]);
563
+ geometryValid = (geometryPositions.length > 0 && geometryIndices.length > 0);
564
+ break;
565
+ case 1:
566
+ primitiveName = "surface";
567
+ geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
568
+ geometryNormals = normals.subarray(eachGeometryNormalsPortion [geometryIndex], atLastGeometry ? normals.length : eachGeometryNormalsPortion [geometryIndex + 1]);
569
+ geometryUVs = uvs.subarray(eachGeometryUVsPortion [geometryIndex], atLastGeometry ? uvs.length : eachGeometryUVsPortion [geometryIndex + 1]);
570
+ geometryIndices = indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry ? indices.length : eachGeometryIndicesPortion [geometryIndex + 1]);
571
+ geometryEdgeIndices = edgeIndices.subarray(eachGeometryEdgeIndicesPortion [geometryIndex], atLastGeometry ? edgeIndices.length : eachGeometryEdgeIndicesPortion [geometryIndex + 1]);
572
+ geometryValid = (geometryPositions.length > 0 && geometryIndices.length > 0);
573
+ break;
574
+ case 2:
575
+ primitiveName = "points";
576
+ geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
577
+ geometryColors = colors.subarray(eachGeometryColorsPortion [geometryIndex], atLastGeometry ? colors.length : eachGeometryColorsPortion [geometryIndex + 1]);
578
+ geometryValid = (geometryPositions.length > 0);
579
+ break;
580
+ case 3:
581
+ primitiveName = "lines";
582
+ geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
583
+ geometryIndices = indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry ? indices.length : eachGeometryIndicesPortion [geometryIndex + 1]);
584
+ geometryValid = (geometryPositions.length > 0 && geometryIndices.length > 0);
585
+ break;
586
+ case 4:
587
+ primitiveName = "lines";
588
+ geometryPositions = positions.subarray(eachGeometryPositionsPortion [geometryIndex], atLastGeometry ? positions.length : eachGeometryPositionsPortion [geometryIndex + 1]);
589
+ geometryIndices = lineStripToLines(
590
+ geometryPositions,
591
+ indices.subarray(eachGeometryIndicesPortion [geometryIndex], atLastGeometry
592
+ ? indices.length
593
+ : eachGeometryIndicesPortion [geometryIndex + 1]));
594
+ geometryValid = (geometryPositions.length > 0 && geometryIndices.length > 0);
595
+ break;
596
+ default:
597
+ continue;
598
+ }
599
+
600
+ if (geometryValid) {
601
+
602
+ sceneModel.createMesh(utils.apply(meshDefaults, {
603
+ id: meshId,
604
+ textureSetId,
605
+ origin: tileCenter,
606
+ primitive: primitiveName,
607
+ positionsCompressed: geometryPositions,
608
+ normalsCompressed: geometryNormals,
609
+ uv: geometryUVs && geometryUVs.length > 0 ? geometryUVs : null,
610
+ colorsCompressed: geometryColors,
611
+ indices: geometryIndices,
612
+ edgeIndices: geometryEdgeIndices,
613
+ positionsDecodeMatrix: tileDecodeMatrix,
614
+ color: meshColor,
615
+ metallic: meshMetallic,
616
+ roughness: meshRoughness,
617
+ opacity: meshOpacity
618
+ }));
619
+
620
+ meshIds.push(meshId);
621
+ }
622
+ }
623
+ }
624
+
625
+ if (meshIds.length > 0) {
626
+
627
+ sceneModel.createEntity(utils.apply(entityDefaults, {
628
+ id: entityId,
629
+ isObject: true,
630
+ meshIds: meshIds
631
+ }));
632
+ }
633
+ }
634
+ }
635
+ }
636
+
637
+ function lineStripToLines(positions, indices) {
638
+ const linesIndices = [];
639
+ if (indices.length > 1) {
640
+ for (let i = 0, len = indices.length - 1; i < len; i++) {
641
+ linesIndices.push(indices[i]);
642
+ linesIndices.push(indices[i + 1]);
643
+ }
644
+ } else if (positions.length > 1) {
645
+ for (let i = 0, len = (positions.length / 3) - 1; i < len; i++) {
646
+ linesIndices.push(i);
647
+ linesIndices.push(i + 1);
648
+ }
649
+ }
650
+ return linesIndices;
651
+ }
652
+
653
+ /** @private */
654
+ const ParserV11 = {
655
+ version: 11,
656
+ parse: function (viewer, options, elements, sceneModel, metaModel, manifestCtx) {
657
+ const deflatedData = extract(elements);
658
+ const inflatedData = inflate(deflatedData);
659
+ load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx);
660
+ }
661
+ };
662
+
663
+ export {ParserV11};