@loaders.gl/3d-tiles 4.0.0-alpha.12 → 4.0.0-alpha.13

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.
@@ -1,6 +1,7 @@
1
1
  import type {Availability, Tile3DBoundingVolume, Subtree} from '../../../types';
2
2
  import {Tile3DSubtreeLoader} from '../../../tile-3d-subtree-loader';
3
3
  import {load} from '@loaders.gl/core';
4
+ import {default as log} from '@probe.gl/log';
4
5
 
5
6
  import {getS2CellIdFromToken, getS2ChildCellId, getS2TokenFromCellId} from '../../utils/s2/index';
6
7
  import type {S2VolumeInfo} from '../../utils/obb/s2-corners-to-obb';
@@ -122,9 +123,10 @@ export async function parseImplicitTiles(params: {
122
123
 
123
124
  const childrenPerTile = SUBDIVISION_COUNT_MAP[subdivisionScheme];
124
125
 
125
- const childX = childIndex & 0b01;
126
- const childY = (childIndex >> 1) & 0b01;
127
- const childZ = (childIndex >> 2) & 0b01;
126
+ // childIndex is in range [0, 7]
127
+ const childX = childIndex & 0b01; // Get first bit for X
128
+ const childY = (childIndex >> 1) & 0b01; // Get second bit for Y
129
+ const childZ = (childIndex >> 2) & 0b01; // Get third bit for Z
128
130
 
129
131
  const levelOffset = (childrenPerTile ** level - 1) / (childrenPerTile - 1);
130
132
  let childTileMortonIndex = concatBits(parentData.mortonIndex, childIndex);
@@ -224,13 +226,37 @@ export async function parseImplicitTiles(params: {
224
226
  return tile;
225
227
  }
226
228
 
227
- function getAvailabilityResult(availabilityData: Availability, index: number): boolean {
228
- if ('constant' in availabilityData) {
229
- return Boolean(availabilityData.constant);
229
+ /**
230
+ * Check tile availability in the bitstream array
231
+ * @param availabilityData - tileAvailability / contentAvailability / childSubtreeAvailability object
232
+ * @param index - index in the bitstream array
233
+ * @returns
234
+ */
235
+ function getAvailabilityResult(
236
+ availabilityData: Availability | Availability[],
237
+ index: number
238
+ ): boolean {
239
+ let availabilityObject: Availability;
240
+ if (Array.isArray(availabilityData)) {
241
+ /** TODO: we don't support `3DTILES_multiple_contents` extension at the moment.
242
+ * https://github.com/CesiumGS/3d-tiles/blob/main/extensions/3DTILES_implicit_tiling/README.md#multiple-contents
243
+ * Take first item in the array
244
+ */
245
+ availabilityObject = availabilityData[0];
246
+ if (availabilityData.length > 1) {
247
+ // eslint-disable-next-line no-console
248
+ log.once('Not supported extension "3DTILES_multiple_contents" has been detected');
249
+ }
250
+ } else {
251
+ availabilityObject = availabilityData;
252
+ }
253
+
254
+ if ('constant' in availabilityObject) {
255
+ return Boolean(availabilityObject.constant);
230
256
  }
231
257
 
232
- if (availabilityData.explicitBitstream) {
233
- return getBooleanValueFromBitstream(index, availabilityData.explicitBitstream);
258
+ if (availabilityObject.explicitBitstream) {
259
+ return getBooleanValueFromBitstream(index, availabilityObject.explicitBitstream);
234
260
  }
235
261
 
236
262
  return false;
@@ -1,4 +1,4 @@
1
- import type {Subtree, ExplicitBitstream} from '../../../types';
1
+ import type {Subtree, Availability} from '../../../types';
2
2
  import type {LoaderContext, LoaderOptions} from '@loaders.gl/loader-utils';
3
3
 
4
4
  const SUBTREE_FILE_MAGIC = 0x74627573;
@@ -42,53 +42,54 @@ export default async function parse3DTilesSubtree(
42
42
  internalBinaryBuffer = data.slice(24 + jsonByteLength);
43
43
  }
44
44
 
45
- if ('bufferView' in subtree.tileAvailability) {
46
- subtree.tileAvailability.explicitBitstream = await getExplicitBitstream(
45
+ await loadExplicitBitstream(subtree, subtree.tileAvailability, internalBinaryBuffer, context);
46
+ if (Array.isArray(subtree.contentAvailability)) {
47
+ for (const contentAvailability of subtree.contentAvailability) {
48
+ await loadExplicitBitstream(subtree, contentAvailability, internalBinaryBuffer, context);
49
+ }
50
+ } else {
51
+ await loadExplicitBitstream(
47
52
  subtree,
48
- 'tileAvailability',
49
- internalBinaryBuffer,
50
- context
51
- );
52
- }
53
-
54
- if ('bufferView' in subtree.contentAvailability) {
55
- subtree.contentAvailability.explicitBitstream = await getExplicitBitstream(
56
- subtree,
57
- 'contentAvailability',
58
- internalBinaryBuffer,
59
- context
60
- );
61
- }
62
-
63
- if ('bufferView' in subtree.childSubtreeAvailability) {
64
- subtree.childSubtreeAvailability.explicitBitstream = await getExplicitBitstream(
65
- subtree,
66
- 'childSubtreeAvailability',
53
+ subtree.contentAvailability,
67
54
  internalBinaryBuffer,
68
55
  context
69
56
  );
70
57
  }
58
+ await loadExplicitBitstream(
59
+ subtree,
60
+ subtree.childSubtreeAvailability,
61
+ internalBinaryBuffer,
62
+ context
63
+ );
71
64
 
72
65
  return subtree;
73
66
  }
74
67
 
75
68
  /**
76
- * Get explicit bitstream for subtree availability data.
77
- * @param subtree
78
- * @param name
79
- * @param internalBinaryBuffer
69
+ * Load explicit bitstream for subtree availability data.
70
+ * @param subtree - subtree data
71
+ * @param availabilityObject - tileAvailability / contentAvailability / childSubtreeAvailability object
72
+ * @param internalBinaryBuffer - subtree binary buffer
73
+ * @param context - loaders.gl context
80
74
  */
81
- async function getExplicitBitstream(
75
+ async function loadExplicitBitstream(
82
76
  subtree: Subtree,
83
- name: string,
77
+ availabilityObject: Availability,
84
78
  internalBinaryBuffer: ArrayBuffer,
85
79
  context: LoaderContext | undefined
86
- ): Promise<ExplicitBitstream> {
87
- const bufferViewIndex = subtree[name].bufferView;
80
+ ): Promise<void> {
81
+ const bufferViewIndex = Number.isFinite(availabilityObject.bitstream)
82
+ ? availabilityObject.bitstream
83
+ : availabilityObject.bufferView;
84
+
85
+ if (typeof bufferViewIndex !== 'number') {
86
+ return;
87
+ }
88
+
88
89
  const bufferView = subtree.bufferViews[bufferViewIndex];
89
90
  const buffer = subtree.buffers[bufferView.buffer];
90
91
 
91
- if (!context?.url || !context.fetch) {
92
+ if (!context?.baseUrl) {
92
93
  throw new Error('Url is not provided');
93
94
  }
94
95
 
@@ -101,11 +102,18 @@ async function getExplicitBitstream(
101
102
  const bufferUri = `${context?.baseUrl || ''}/${buffer.uri}`;
102
103
  const response = await context.fetch(bufferUri);
103
104
  const data = await response.arrayBuffer();
104
- // Return view of bitstream.
105
- return new Uint8Array(data, bufferView.byteOffset, bufferView.byteLength);
105
+ availabilityObject.explicitBitstream = new Uint8Array(
106
+ data,
107
+ bufferView.byteOffset,
108
+ bufferView.byteLength
109
+ );
110
+ return;
106
111
  }
107
- // Return view of bitstream.
108
- return new Uint8Array(internalBinaryBuffer, bufferView.byteOffset, bufferView.byteLength);
112
+ availabilityObject.explicitBitstream = new Uint8Array(
113
+ internalBinaryBuffer,
114
+ bufferView.byteOffset,
115
+ bufferView.byteLength
116
+ );
109
117
  }
110
118
 
111
119
  /**
package/src/types.ts CHANGED
@@ -294,20 +294,57 @@ export type Tiles3DTileContent = {
294
294
 
295
295
  /**
296
296
  * 3DTILES_implicit_tiling types
297
- * Spec - https://github.com/CesiumGS/3d-tiles/tree/main/extensions/3DTILES_implicit_tiling#subtree-file-format
297
+ * Spec - https://github.com/CesiumGS/3d-tiles/tree/main/extensions/3DTILES_implicit_tiling
298
+ * JSON Schema v1.1 https://github.com/CesiumGS/3d-tiles/blob/8e5e67e078850cc8ce15bd1873fe54f11bbee02f/specification/schema/Subtree/subtree.schema.json
299
+ * JSON Schema vNext https://github.com/CesiumGS/3d-tiles/blob/8e5e67e078850cc8ce15bd1873fe54f11bbee02f/extensions/3DTILES_implicit_tiling/schema/subtree/subtree.schema.json
298
300
  */
299
301
  export type Subtree = {
302
+ /** An array of buffers. */
300
303
  buffers: Buffer[];
304
+ /** An array of buffer views. */
301
305
  bufferViews: BufferView[];
306
+ /** The availability of tiles in the subtree. The availability bitstream is a 1D boolean array where tiles are ordered by their level in the subtree and Morton index
307
+ * within that level. A tile's availability is determined by a single bit, 1 meaning a tile exists at that spatial index, and 0 meaning it does not.
308
+ * The number of elements in the array is `(N^subtreeLevels - 1)/(N - 1)` where N is 4 for subdivision scheme `QUADTREE` and 8 for `OCTREE`.
309
+ * Availability may be stored in a buffer view or as a constant value that applies to all tiles. If a non-root tile's availability is 1 its parent
310
+ * tile's availability shall also be 1. `tileAvailability.constant: 0` is disallowed, as subtrees shall have at least one tile.
311
+ */
302
312
  tileAvailability: Availability;
303
- contentAvailability: Availability;
313
+ /** It is array by spec but there are tiles that has a single object
314
+ * An array of content availability objects. If the tile has a single content this array will have one element; if the tile has multiple contents -
315
+ * as supported by 3DTILES_multiple_contents and 3D Tiles 1.1 - this array will have multiple elements.
316
+ */
317
+ contentAvailability: Availability | Availability[];
318
+ /** The availability of children subtrees. The availability bitstream is a 1D boolean array where subtrees are ordered by their Morton index in the level of the tree
319
+ * immediately below the bottom row of the subtree. A child subtree's availability is determined by a single bit, 1 meaning a subtree exists at that spatial index,
320
+ * and 0 meaning it does not. The number of elements in the array is `N^subtreeLevels` where N is 4 for subdivision scheme `QUADTREE` and 8 for `OCTREE`.
321
+ * Availability may be stored in a buffer view or as a constant value that applies to all child subtrees. If availability is 0 for all child subtrees,
322
+ * then the tileset does not subdivide further.
323
+ */
304
324
  childSubtreeAvailability: Availability;
325
+ // TODO: These are unused properties. Improve types when they are required
326
+ propertyTables: unknown;
327
+ tileMetadata: unknown;
328
+ contentMetadata: unknown;
329
+ subtreeMetadata: unknown;
305
330
  };
306
331
 
307
332
  export type Availability = {
333
+ /** Integer indicating whether all of the elements are available (1) or all are unavailable (0). */
308
334
  constant?: 0 | 1;
335
+ /** Index of a buffer view that indicates whether each element is available. The bitstream conforms to the boolean array encoding described
336
+ * in the 3D Metadata specification. If an element is available, its bit is 1, and if it is unavailable, its bit is 0. */
337
+ bitstream?: number;
338
+ /**
339
+ * v1.1 https://github.com/CesiumGS/3d-tiles/blob/8e5e67e078850cc8ce15bd1873fe54f11bbee02f/specification/schema/Subtree/availability.schema.json
340
+ * vNext https://github.com/CesiumGS/3d-tiles/blob/8e5e67e078850cc8ce15bd1873fe54f11bbee02f/extensions/3DTILES_implicit_tiling/schema/subtree/availability.schema.json
341
+ * The schemas of vNext and 1.1 are same but there are tiles with `bufferView` property instead of `bitstream`
342
+ */
309
343
  bufferView?: number;
310
- // Internal bitstream type
344
+ /**
345
+ * Postprocessing property
346
+ * contain availability bits loaded from the bufferView
347
+ */
311
348
  explicitBitstream?: ExplicitBitstream;
312
349
  };
313
350
 
@@ -324,7 +361,8 @@ type Buffer = {
324
361
  byteLength: number;
325
362
  };
326
363
 
327
- type BufferView = {
364
+ /** Subtree buffer view */
365
+ export type BufferView = {
328
366
  buffer: number;
329
367
  byteOffset: number;
330
368
  byteLength: number;