diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/AVAILABILITY.md b/extensions/2.1/Vendor/3DTILES_implicit_tiling/AVAILABILITY.md
new file mode 100644
index 0000000000..c41cf02905
--- /dev/null
+++ b/extensions/2.1/Vendor/3DTILES_implicit_tiling/AVAILABILITY.md
@@ -0,0 +1,127 @@
+# Availability Indexing
+
+## Converting from Tile Coordinates to Morton Index
+
+A [Morton index](https://en.wikipedia.org/wiki/Z-order_curve) is computed by interleaving the bits of the `(right, forward)` or `(right, forward, up)` coordinates of a tile. Specifically:
+
+```js
+quadtreeMortonIndex = interleaveBits(right, forward)
+octreeMortonIndex = interleaveBits(right, forward, up)
+```
+
+For example:
+
+```js
+// Quadtree
+interleaveBits(0b11, 0b00) = 0b0101
+interleaveBits(0b1010, 0b0011) = 0b01001110
+interleaveBits(0b0110, 0b0101) = 0b00110110
+
+// Octree
+interleaveBits(0b001, 0b010, 0b100) = 0b100010001
+interleaveBits(0b111, 0b000, 0b111) = 0b101101101
+```
+
+
+
+## Availability Bitstream Lengths
+
+Availability Type | Length (bits) | Description
+--|--|--
+Tile availability|`+(N^subtreeLevels - 1)/(N - 1)+`|Total number of nodes in the subtree
+Content availability|`+(N^subtreeLevels - 1)/(N - 1)+`|Since there is at most one content per tile, this is the same length as tile availability
+Child subtree availability|`+(N^subtreeLevels - 1)/(N - 1)+`|Number of nodes one level deeper than the deepest level of the subtree
+
+Where `N` is 4 for quadtrees and 8 for octrees.
+
+These lengths are in number of bits in a bitstream. To compute the length of the bitstream in bytes, the following formula is used:
+
+```js
+lengthBytes = ceil(lengthBits / 8)
+```
+
+## Accessing Availability Bits
+
+For tile availability and content availability, the Morton index only determines the ordering within a single level of the subtree. Since the availability bitstream stores bits for every level of the subtree, a level offset shall be computed.
+
+Given the `(level, mortonIndex)` of a tile relative to the subtree root, the index of the corresponding bit can be computed with the following formulas:
+
+Quantity | Formula | Description
+--|--|--
+`levelOffset`|`+(N^level - 1) / (N - 1)+`|This is the number of nodes at levels `+1, 2, ... (level - 1)+`
+`tileAvailabilityIndex`|`levelOffset + mortonIndex`|The index into the buffer view is the offset for the tile's level plus the morton index for the tile
+
+Where `N` is 4 for quadtrees and 8 for octrees.
+
+Since child subtree availability stores bits for a single level, no levelOffset is needed, i.e. `childSubtreeAvailabilityIndex = mortonIndex`, where the `mortonIndex` is the Morton
+index of the desired child subtree relative to the root of the current subtree.
+
+## Global and Local Tile Coordinates
+
+When working with tile coordinates, it is important to consider which tile the coordinates are relative to. There are two main types used in implicit tiling:
+
+* *global coordinates* - coordinates relative to the implicit root tile.
+* *local coordinates* - coordinates relative to the root of a specific subtree.
+
+Global coordinates are used for locating any tile in the entire implicit tileset. For example, template URIs use global coordinates to locate content files and subtrees. Meanwhile, local coordinates are used for locating data within a single subtree file.
+
+In binary, a tile's global Morton index is the complete path from the implicit root tile to the tile. This is the concatenation of the path from the implicit root tile to the subtree root tile, followed by the path from the subtree root tile to the tile. This can be expressed with the following equation:
+
+```js
+tile.globalMortonIndex = concatBits(subtreeRoot.globalMortonIndex, tile.localMortonIndex)
+```
+
+
+
+ Illustration of how to compute the global Morton index of a tile, from the global Morton index of the root of the containing subtree, and the local Morton index of the tile in this subtree.
+
+
+Similarly, the global level of a tile is the length of the path from the implicit root tile to the tile. This is the sum of the subtree root tile's global level and the tile's local level relative to the subtree root tile:
+
+```js
+tile.globalLevel = subtreeRoot.globalLevel + tile.localLevel
+```
+
+
+
+ Illustration of how to compute the global level of a tile, from the global level of the root of the containing subtree, and the local level of the tile in this subtree.
+
+
+`(right, forward, up)` coordinates follow the same pattern as Morton indices. The only difference is that the concatenation of bits happens component-wise. That is:
+
+```js
+tile.globalRight = concatBits(subtreeRoot.globalRight, tile.localRight)
+tile.globalForward = concatBits(subtreeRoot.globalForward, tile.localForward)
+
+// Octrees only
+tile.globalUp = concatBits(subtreeRoot.globalUp, tile.localUp)
+```
+
+
+
+ Illustration of the computation of the global tile coordinates, from the global coordinates of the containing subtree, and the local coordinates of the tile in this subtree.
+
+
+## Finding Parent and Child Tiles
+
+The coordinates of a parent or child tile can also be computed with bitwise operations on the Morton index. The following formulas apply for both local and global coordinates.
+
+```js
+childTile.level = parentTile.level + 1
+childTile.mortonIndex = concatBits(parentTile.mortonIndex, childIndex)
+childTile.right = concatBits(parentTile.right, childRight)
+childTile.forward = concatBits(parentTile.forward, childForward)
+
+// Octrees only
+childTile.up = concatBits(parentTile.up, childUp)
+```
+
+Where:
+
+* `childIndex` is an integer in the range `[0, N)` that is the index of the child tile relative to the parent.
+* `childRight`, `childForward`, and `childUp` are single bits that represent which half of the parent's bounding volume the child is in in each direction.
+
+
+
+ Illustration of the computation of the coordinates of parent- and child tiles.
+
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/README.md b/extensions/2.1/Vendor/3DTILES_implicit_tiling/README.md
index 4e79bcad96..bba95601ce 100644
--- a/extensions/2.1/Vendor/3DTILES_implicit_tiling/README.md
+++ b/extensions/2.1/Vendor/3DTILES_implicit_tiling/README.md
@@ -30,35 +30,36 @@ Implicit tiling defines a concise representation of quadtrees and octrees in 3D
Implicit tiling also allows for better interoperability with existing GIS data formats with implicitly defined tiling schemes. Some examples are [TMS](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification), [WMTS](https://www.ogc.org/standards/wmts), [S2](http://s2geometry.io/), and [CDB](https://docs.opengeospatial.org/is/15-113r5/15-113r5.html).
-In order to support sparse datasets, *availability* data determines which tiles exist. To support massive datasets, availability is partitioned into fixed-size *subtrees*. Subtrees may store *metadata* for available tiles and contents.
+In order to support sparse datasets, *availability* data determines which tiles exist. To support massive datasets, availability is partitioned into fixed-size *subtrees*. Subtrees may store *attributes* and application-specific *properties* for available tiles and contents.
-An `implicitTiling` object may be added to any tile in the tileset. The object defines how the tile is subdivided and where to locate content resources. It may be added to multiple tiles to create more complex subdivision schemes.
+The `3DTILES_implicit_tiling` extension may be added to any tile in the tileset. The extension defines how the tile is subdivided and where to locate content resources. It may be added to multiple tiles to create more complex subdivision schemes.
-
-
-_A point cloud organized into a sparse octree. Data source: Trimble_
+
+
+ A point cloud organized into a sparse octree. Data source: Trimble.
+
## Implicit Root Tile
-An `implicitTiling` object may be added to any tile in the tileset. Such a tile is called an *implicit root tile*, to distinguish it from the root tile of the tileset.
+The `3DTILES_implicit_tiling` extension may be added to any tile in the tileset. Such a tile is called an *implicit root tile*, to distinguish it from the root tile of the tileset. The implicit root tile is [unconditionally refinable](../3DTILES_tileset/README.md#unconditional-refinement).
```json
{
- "boundingVolume": {
- "shape": 0
- },
"extensions": {
"3DTILES_tileset": {
"geometricError": 5000.0,
"refine": "REPLACE"
},
"3DTILES_implicit_tiling": {
- "contentUri": "content/{level}/{x}/{y}.glb",
- "subtreeUri": "subtrees/{level}/{x}/{y}.json",
+ "contentUri": "content/{level}/{right}/{forward}.glb",
+ "subtreeUri": "subtrees/{level}/{right}/{forward}.subtree.glb",
"subdivisionScheme": "QUADTREE",
"availableLevels": 21,
"subtreeLevels": 7
}
+ },
+ "boundingVolume": {
+ "shape": 0
}
}
```
@@ -67,8 +68,8 @@ The `3DTILES_implicit_tiling` extension has the following properties:
Property | Description
--|--
-`contentUri`|[Template URI]((#template-uris)) for locating content files.
-`subtreeUri`|[Template URI]((#template-uris)) for locating subtree files.
+`contentUri`|[Template URI](#template-uris) for locating content files.
+`subtreeUri`|[Template URI](#template-uris) for locating subtree files.
`subdivisionScheme`|Either `QUADTREE` or `OCTREE`. See [Subdivision scheme](#subdivision-scheme).
`availableLevels`|How many levels there are in the tree with available tiles.
`subtreeLevels`|How many levels there are in each subtree.
@@ -79,7 +80,167 @@ The following constraints apply to implicit root tiles:
- The `externalAsset` property **MUST NOT** be defined
- The contents referenced by `contentUri` **MUST NOT** be [external tilesets](../3DTILES_tileset/README.md#external-tilesets)
+## Subdivision Scheme
+
+A *subdivision scheme* is a recursive pattern for dividing a bounding volume of a tile into smaller children tiles that take up the same space.
+
+A *quadtree* divides space only on the `right` (-x) and `forward` (+z) dimensions. It divides each tile into 4 smaller tiles where the `right` and `forward` dimensions are halved. The quadtree `up` (+y) minimum and maximum remain unchanged. The resulting tree has 4 children per tile.
+
+
+
+
+
+An *octree* divides space along all 3 dimensions. It divides each tile into 8 smaller tiles where each dimension is halved. The resulting tree has 8 children per tile.
+
+
+
+
+
+Sphere bounding volumes are disallowed, as these cannot be divided into a quadtree or octree.
+
+- For subdivision of ellipsoid region bounding volumes refer to [3DTILES_shape_ellipsoid_region](../3DTILES_shape_ellipsoid_region/README.md#implicit-subdivision)
+- For subdivision of cylinder region bounding volumes refer to [3DTILES_shape_cylinder_region](../3DTILES_shape_cylinder_region/README.md#implicit-subdivision)
+- For subdivision of S2 bounding volumes refer to [3DTILES_bounding_volume_S2](../3DTILES_bounding_volume_S2/README.md#implicit-subdivision)
+
+## Subdivision Rules
+
+Implicit tiling only requires defining the subdivision scheme, refinement strategy, bounding volume, and geometric error at the implicit root tile. For descendant tiles, these properties are computed automatically, based on the following rules:
+
+Property|Subdivision Rule
+--|--
+`subdivisionScheme`|Constant for all descendant tiles.
+`refine`|Constant for all descendant tiles.
+`boundingVolume`|Divided into four or eight parts depending on the `subdivisionScheme`.
+`geometricError`|Each child's `geometricError` is half of its parent's `geometricError`.
+
+> [!NOTE]
+> In order to maintain numerical stability during this subdivision process, the actual bounding volumes should not be computed progressively by subdividing a non-root tile volume. Instead, the exact bounding volumes should be computed directly for a given level.
+>
+> Let the extent of the root bounding volume along one dimension *d* be *(mind, maxd)*. The number of bounding volumes along that dimension for a given level is *2level*. The size of each bounding volume at this level, along dimension *d*, is *sized = (maxd - mind) / 2level*. The extent of the bounding volume of a child can then be computed directly as *(mind + sized * i, mind + sized * (i + 1))*, where *i* is the index of the child in dimension *d*.
+
+The computed tile `boundingVolume` and `geometricError` can be overridden with [tile attributes](#attributes), if desired. Content bounding volumes are not computed automatically but they may be provided by [content attributes](#attributes). Tile and content bounding volumes **SHOULD** maintain [spatial coherence](../3DTILES_tileset/README.md#spatial-coherence).
+
+## Tile Coordinates
+
+*Tile coordinates* are a tuple of integers that uniquely identify a tile. Tile coordinates are either `(level, right, forward)` for quadtrees or `(level, right, forward, up)` for octrees. All tile coordinates are 0-indexed.
+
+`level` is 0 for the implicit root tile. This tile's children are at level 1, and so on.
+
+`right`, `forward`, and `up` coordinates define the location of the tile within the level.
+
+For `box` bounding volumes:
+
+Coordinate|Positive Direction
+--|--
+`right`|Along the right axis of the bounding box (`+x` to `-x`)
+`forward`|Along the forward axis of the bounding box (`-z` to `+z`)
+`up`|Along the up axis of the bounding box (`-y` to `+y`)
+
+
+
+## Template URIs
+
+A *Template URI* is a URI pattern used to refer to tiles by their tile coordinates.
+
+Template URIs **MAY** include the variables `{level}`, `{right}`, `{forward}`. Template URIs for octrees **MAY** also include `{up}`. When referring to a specific tile, the tile's coordinates are substituted for these variables.
+
+Template URIs, when given as relative paths, are resolved relative to the tileset file.
+
+
+
+## Subtrees
+
+In order to support sparse datasets, additional information is needed to indicate which tiles or contents exist. This is called *availability*.
+
+*Subtrees* are fixed size sections of the tileset tree used for storing availability. The tileset is partitioned into subtrees to bound the size of each availability buffer for optimal network transfer and caching. The `subtreeLevels` property defines the number of levels in each subtree. The subdivision scheme determines the number of children per tile.
+
+
+
+After partitioning a tileset into subtrees, the result is a tree of subtrees.
+
+
+
+### Availability
+
+Each subtree contains tile availability, content availability, and child subtree availability.
+
+- *Tile availability* indicates which tiles exist within the subtree
+- *Content availability* indicates which tiles have associated content resources
+- *Child subtree availability* indicates which subtrees are reachable from this subtree
+
+Each type of availability is represented as a separate bitstream. Each bitstream is a 1D array where each element represents a node in the quadtree or octree. A 1 bit indicates that the element is available, while a 0 bit indicates that the element is unavailable. Alternatively, if all the bits in a bitstream are the same, a single constant value can be used instead.
+
+To form the 1D bitstream, the tiles are ordered with the following rules:
+
+- Within each level of the subtree, the tiles are ordered using the [Morton Z-order curve](https://en.wikipedia.org/wiki/Z-order_curve)
+- The bits for each level are concatenated into a single bitstream
+
+
+
+In the diagram above, colored cells represent 1 bits, grey cells represent 0 bits.
+
+Storing tiles in Morton order provides these benefits:
+
+- Efficient indexing - The Morton index for a tile is computed in constant time by interleaving bits.
+- Efficient traversal - The Morton index for a parent or child tile are computed in constant time by removing or adding bits, respectively.
+- Locality of reference - Consecutive tiles are near to each other in 3D space.
+- Better Compression - Locality of reference leads to better compression of availability bitstreams.
+
+For more detailed information about working with Morton indices and availability bitstreams, see [Availability Indexing](./AVAILABILITY.md).
+
+#### Tile Availability
+
+Tile availability determines which tiles exist in a subtree.
+
+Tile availability has the following restrictions:
+
+- If a non-root tile's availability is 1, its parent tile's availability **MUST** also be 1.
+- A subtree **MUST** have at least one available tile.
+
+
+
+#### Content Availability
+
+Content availability determines which tiles have a content resource. The content resource is located using the template URI of the tile content. If there are no tiles with a content resource, then `contentUri` **MUST** be omitted.
+
+Content availability has the following restrictions:
+
+- If content availability is 1 its corresponding tile availability **MUST** also be 1. Otherwise, it would be possible to specify content files that are not reachable by the tiles of the tileset.
+- If content availability is 0 and its corresponding tile availability is 1 then the tile is considered to be an empty tile.
+
+
+
+#### Child Subtree Availability
+
+Child subtree availability determines which subtrees are reachable from the deepest level of this subtree. This links subtrees together to form a tree.
+
+Unlike tile and content availability, which store bits for every level in the subtree, child subtree availability stores bits for nodes one level deeper than the deepest level of the subtree, and represent the root nodes of child subtrees. This is used to determine which other subtrees are reachable before requesting tiles. If availability is 0 for all child subtrees, then the tileset does not subdivide further.
+
+
+
+### Attributes
+
+Each subtree may store attribute values for available tiles and content. This may include, for example, tighter fitting bounding volumes than those computed automatically based on [Subdivision Rules](#subdivision-rules).
+
+Attribute values are tightly packed by an increasing tile index according to the [Availability Ordering](#availability).
+
+For the full list of attribute semantics, see [tile attributes](../3DTILES_subtree/README.md#tile-attributes) and [content attributes](../3DTILES_subtree/README.md#content-attributes).
+
+### Properties
+
+Each subtree may store application-specific properties for available tiles and contents. Property values are stored in [property tables](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata#property-tables) with [EXT_structural_metadata](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata). The binary representation is particularly efficient for larger datasets with many tiles.
+
+Property values are tightly packed by an increasing tile index according to the [Availability Ordering](#availability). Each available tile **MUST** have a value — representation of missing values within a tile is possible only with the `noData` indicator defined by the [schema](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata#schema).
+
+> [!NOTE]
+>
+> To determine the index into a property value array for a particular tile, count the number of available tiles occurring before that index, according to the tile Availability Ordering. If `i` available tiles occur before a particular tile, that tile's property values are stored at index `i` of each property value array. These indices may be precomputed for all available tiles, as a single pass over the subtree availability buffer.
+
+### Subtree Files
+
+A subtree is a glTF with the [`3DTILES_subtree`](../3DTILES_subtree/README.md) extension. The extension specifies how availability, attributes, and application-specific properties are encoded in glTF.
+
## TODO
-- Finish extension
- Template URI bypasses glTF 2.1 `files` mechanism, which would prevent [packaging external assets](https://github.com/KhronosGroup/glTF/issues/2589).
+- Incorporate [3DTILES_implicit_tiling_custom_template_variables](https://github.com/CesiumGS/3d-tiles/pull/815)
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/availability-ordering.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/availability-ordering.png
new file mode 100644
index 0000000000..d130805144
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/availability-ordering.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/binary-subtree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/binary-subtree.png
new file mode 100644
index 0000000000..dba9d1df4c
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/binary-subtree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-coordinates.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-coordinates.png
new file mode 100644
index 0000000000..491e5fab71
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-coordinates.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-octree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-octree.png
new file mode 100644
index 0000000000..bf1e15afc8
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-octree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-quadtree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-quadtree.png
new file mode 100644
index 0000000000..2070c58dc7
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box-quadtree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box.png
new file mode 100644
index 0000000000..fc1e3a3477
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/box.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/child-subtree-availability.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/child-subtree-availability.png
new file mode 100644
index 0000000000..5c946f801c
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/child-subtree-availability.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/content-availability.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/content-availability.png
new file mode 100644
index 0000000000..4d32c54841
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/content-availability.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local-levels.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local-levels.png
new file mode 100644
index 0000000000..85a51a066d
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local-levels.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local-morton.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local-morton.png
new file mode 100644
index 0000000000..07712f30ce
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local-morton.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local.png
new file mode 100644
index 0000000000..b3ab349b46
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/global-to-local.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/morton-indexing.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/morton-indexing.png
new file mode 100644
index 0000000000..a2fa758b15
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/morton-indexing.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/octree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/octree.png
new file mode 100644
index 0000000000..850cba60ee
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/octree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/parent-and-child-coordinates.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/parent-and-child-coordinates.png
new file mode 100644
index 0000000000..2e8b536e5e
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/parent-and-child-coordinates.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/quadtree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/quadtree.png
new file mode 100644
index 0000000000..c29dba52bb
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/quadtree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-coordinates.jpg b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-coordinates.jpg
new file mode 100644
index 0000000000..4462110aef
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-coordinates.jpg differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-octree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-octree.png
new file mode 100644
index 0000000000..dd841c12dc
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-octree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-quadtree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-quadtree.png
new file mode 100644
index 0000000000..f0e649d315
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region-quadtree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region.png
new file mode 100644
index 0000000000..3c5de11251
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/region.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/sparse-octree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/sparse-octree.png
new file mode 100644
index 0000000000..ebe7f00cc1
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/sparse-octree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/subtree-anatomy.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/subtree-anatomy.png
new file mode 100644
index 0000000000..fd99760bd4
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/subtree-anatomy.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/subtree-tree.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/subtree-tree.png
new file mode 100644
index 0000000000..539bf2a913
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/subtree-tree.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/template-uri.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/template-uri.png
new file mode 100644
index 0000000000..5e38583733
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/template-uri.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-availability.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-availability.png
new file mode 100644
index 0000000000..d130805144
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-availability.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-height-semantics.png b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-height-semantics.png
new file mode 100644
index 0000000000..f02da2b410
Binary files /dev/null and b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-height-semantics.png differ
diff --git a/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-height-semantics.svg b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-height-semantics.svg
new file mode 100644
index 0000000000..06d7cfbbe3
--- /dev/null
+++ b/extensions/2.1/Vendor/3DTILES_implicit_tiling/figures/tile-height-semantics.svg
@@ -0,0 +1,436 @@
+
+
+
+
diff --git a/extensions/2.1/Vendor/3DTILES_subtree/README.md b/extensions/2.1/Vendor/3DTILES_subtree/README.md
index bbe0078f2d..b6c5db6dbf 100644
--- a/extensions/2.1/Vendor/3DTILES_subtree/README.md
+++ b/extensions/2.1/Vendor/3DTILES_subtree/README.md
@@ -26,8 +26,278 @@ This extension is required, meaning it **MUST** be placed in both `extensionsReq
## Overview
-This extension specifies a well defined subset of glTF 2.1 for representing a subtree in [3DTILES_implicit_tiling](../3DTILES_implicit_tiling/README.md). A subtree stores tile, content, and child subtree availability, as well as metadata for available tiles and contents.
+This extension specifies a subset of glTF 2.1 for representing a subtree in [3DTILES_implicit_tiling](../3DTILES_implicit_tiling/README.md). A subtree stores tile, content, and child subtree availability, as well as attributes and application-specific properties for available tiles and contents.
+
+A subtree is not intended for rendering and **SHOULD NOT** have any scenes.
## File Extensions
-Assets that use the `3DTILES_subtree` extension **SHOULD** use the `.subtree.gltf` or `.subtree.glb` file extensions. Though not required, this convention helps differentiate subtree files from tileset and content files.
+Assets that use the `3DTILES_subtree` extension **SHOULD** use the `.subtree.gltf` or `.subtree.glb` file extensions. This convention helps differentiate subtree files from tileset and content files.
+
+## Availability
+
+Tile availability (`tileAvailability`) and child subtree availability (`childSubtreeAvailability`) **MUST** always be provided for a subtree.
+
+Content availability (`contentAvailability`) **MUST** be provided if the implicit root tile has a `contentUri` property, otherwise it **MUST** be omitted.
+
+Availability may be represented either as a bitstream or a constant value. `bitstream` is an integer index that identifies the buffer view containing the availability bitstream. `constant` is an integer indicating whether all of the elements are available (`1`) or all are unavailable (`0`). `availableCount` is an integer indicating how many `1` bits exist in the availability bitstream.
+
+For a bitstream with `N` values, the buffer view that stores these availability values will consist of `ceil(N / 8)` bytes. When `N` is not divisible by `8`, then the unused bits of the last byte of this buffer **MUST** be set to 0.
+
+> [!NOTE]
+> Example accessing availability for element `i`
+>
+> ```javascript
+> byteIndex = floor(i / 8)
+> bitIndex = i % 8
+> bitValue = (buffer[byteIndex] >> bitIndex) & 1
+> available = bitValue == 1
+> ```
+
+> **Example:** A subtree where each tile is available, but not all tiles have content, and not all child subtrees are available:
+>
+> ```json
+> {
+> "buffers": [
+> {
+> "byteLength": 48
+> }
+> ],
+> "bufferViews": [
+> {
+> "buffer": 0,
+> "byteOffset": 0,
+> "byteLength": 11
+> },
+> {
+> "buffer": 0,
+> "byteOffset": 16,
+> "byteLength": 32
+> }
+> ],
+> "extensions": {
+> "3DTILES_subtree": {
+> "tileAvailability": {
+> "constant": 1
+> },
+> "contentAvailability": [
+> {
+> "bitstream": 0,
+> "availableCount": 60
+> }
+> ],
+> "childSubtreeAvailability": {
+> "bitstream": 1
+> }
+> }
+> }
+> }
+> ```
+
+## Attributes
+
+A subtree may store attribute values for available tiles and content. This may include, for example, tighter fitting bounding volumes than those computed automatically based on [Subdivision Rules](../3DTILES_implicit_tiling/README.md#subdivision-rules).
+
+Each attribute is defined as a property of an attributes object. The name of the property corresponds to a semantic identifying the attribute. The value of the property is the index of an accessor that contains the data. The number of elements in the accessor **MUST** equal the number of available elements.
+
+Tile attributes are provided in the `tileAttributes` object and content attributes are provided in the `contentAttribute` object.
+
+
+If more than one bounding volume attribute is provided, clients may select the most appropriate option based on use case and performance requirements.
+
+> **Example:** A subtree with tile and content attributes:
+>
+> ```json
+> {
+> "buffers": [
+> {
+> "name": "Availability Buffer",
+> "uri": "availability.bin",
+> "byteLength": 48
+> },
+> {
+> "name": "Attributes Buffer",
+> "uri": "attributes.bin",
+> "byteLength": 19240
+> }
+> ],
+> "bufferViews": [
+> { "buffer": 0, "byteOffset": 0, "byteLength": 11 },
+> { "buffer": 0, "byteOffset": 16, "byteLength": 32 },
+> { "buffer": 1, "byteOffset": 0, "byteLength": 10880 },
+> { "buffer": 1, "byteOffset": 10880, "byteLength": 680 },
+> { "buffer": 1, "byteOffset": 11560, "byteLength": 7680 }
+> ],
+> "accessors": [
+> {
+> "type": "MAT4",
+> "componentType": 5130,
+> "bufferView": 2,
+> "count": 85
+> },
+> {
+> "type": "SCALAR",
+> "componentType": 5130,
+> "bufferView": 3,
+> "count": 85
+> },
+> {
+> "type": "MAT4",
+> "componentType": 5130,
+> "bufferView": 4,
+> "count": 60
+> }
+> ],
+> "extensions": {
+> "3DTILES_subtree": {
+> "tileAvailability": {
+> "constant": 1
+> },
+> "contentAvailability": [{
+> "bitstream": 0,
+> "availableCount": 60
+> }],
+> "childSubtreeAvailability": {
+> "bitstream": 1
+> },
+> "tileAttributes": {
+> "TILE_BOUNDING_BOX": 0,
+> "TILE_GEOMETRIC_ERROR": 1
+> },
+> "contentAttributes": {
+> "CONTENT_BOUNDING_BOX": 2
+> }
+> }
+> }
+> }
+> ```
+
+### Tile Attributes
+
+Below is the list of tile attribute semantics. Additional semantics may be defined by extensions.
+
+Attribute Semantic|Accessor Type|Component Type|Description
+--|--|--|--
+`"TILE_BOUNDING_BOX"`|`"MAT4"`|`5130` (DOUBLE)|The bounding box of the tile, expressed as a column-major transformation matrix applied to a unit cube where the top-left 3x3 matrix encodes the box's rotation and scale and the first three elements of the fourth column encodes the box's translation. See [Bounding Box](../3DTILES_tileset/README.md#bounding-box).
+`"TILE_BOUNDING_SPHERE"`|`VEC4`|`5130` (DOUBLE)|The bounding sphere of the tile, where the first three elements encode the x, y, and z values for the center of the sphere and the the last element encodes the radius. See [Bounding Sphere](../3DTILES_tileset/README.md#bounding-sphere).
+`"TILE_GEOMETRIC_ERROR"`|`"SCALAR"`|`5130` (DOUBLE)|The geometric error of the tile. See [Geometric Error](../3DTILES_tileset/README.md#geometric-error).
+`"TILE_REFINE"`|`"SCALAR"`|`5121` (UNSIGNED_BYTE)|The tile refinement. Elements in the accessor **MUST** be either `0` (`"ADD"`) or `1` (`"REPLACE"`). See [Refinement](../3DTILES_tileset/README.md#refinement).
+`"TILE_TRANSFORM"`|`"MAT4"`|`5130` (DOUBLE)|The tile transform. See [Transforms](../3DTILES_tileset/README.md#transforms).
+
+### Content Attributes
+
+Below is the list of content attribute semantics. Additional semantics may be defined by extensions.
+
+Attribute Semantic|Accessor Type|Component Type|Description
+--|--|--|--
+`CONTENT_BOUNDING_BOX`|`MAT4`|`5130` (DOUBLE)|The bounding box of the content, expressed as a column-major transformation matrix applied to a unit cube where the top-left 3x3 matrix encodes the box's rotation and scale and the first three elements of the fourth column encodes the box's translation. See [Bounding Box](../3DTILES_tileset/README.md#bounding-box).
+`CONTENT_BOUNDING_SPHERE`|`VEC4`|`5130` (DOUBLE)|The bounding sphere of the content, where the first three elements encode the x, y, and z values for the center of the sphere and the the last element encodes the radius. See [Bounding Sphere](../3DTILES_tileset/README.md#bounding-sphere).
+
+## Properties
+
+Subtrees may store application-specific properties for available tiles and content. Property values are stored in [property tables](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata#property-tables) with [EXT_structural_metadata](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata). The binary representation is particularly efficient for larger datasets with many tiles.
+
+`tilePropertyTable` is the index of a property table containing property values for available tiles.
+
+`contentPropertyTable` is the index of a property table containing property values for available content. If the implicit root tile does not have a `contentUri` property, then none of the implicit tiles have content, and `contentPropertyTable` property **MUST** be omitted.
+
+> **Example:** A subtree with tile and content properties:
+>
+> ```json
+> {
+> "extensionsUsed": ["3DTILES_subtree", "EXT_structural_metadata"],
+> "extensionsRequired": ["3DTILES_subtree", "EXT_structural_metadata"],
+> "asset": {
+> "version": "2.1"
+> },
+> "buffers": [
+> {
+> "name": "Availability Buffer",
+> "uri": "availability.bin",
+> "byteLength": 48
+> },
+> {
+> "name": "Properties Buffer",
+> "uri": "properties.bin",
+> "byteLength": 3138
+> }
+> ],
+> "bufferViews": [
+> { "buffer": 0, "byteOffset": 0, "byteLength": 11 },
+> { "buffer": 0, "byteOffset": 16, "byteLength": 32 },
+> { "buffer": 1, "byteOffset": 0, "byteLength": 1530 },
+> { "buffer": 1, "byteOffset": 1530, "byteLength": 344 },
+> { "buffer": 1, "byteOffset": 1874, "byteLength": 1024 },
+> { "buffer": 1, "byteOffset": 2898, "byteLength": 240 }
+> ],
+> "extensions": {
+> "3DTILES_subtree": {
+> "tileAvailability": {
+> "constant": 1
+> },
+> "contentAvailability": [
+> {
+> "bitstream": 0,
+> "availableCount": 60
+> }
+> ],
+> "childSubtreeAvailability": {
+> "bitstream": 1
+> },
+> "tilePropertyTable": 0,
+> "contentPropertyTable": 1
+> },
+> "EXT_structural_metadata": {
+> "schema": {
+> "classes": {
+> "tile": {
+> "properties": {
+> "countries": {
+> "description": "Countries a tile intersects",
+> "type": "STRING",
+> "array": true
+> }
+> }
+> },
+> "content": {
+> "properties": {
+> "triangleCount": {
+> "type": "SCALAR",
+> "componentType": "UINT32"
+> }
+> }
+> }
+> }
+> },
+> "propertyTables": [
+> {
+> "class": "tile",
+> "count": 85,
+> "properties": {
+> "countries": {
+> "values": 2,
+> "arrayOffsets": 3,
+> "stringOffsets": 4,
+> "arrayOffsetType": "UINT32",
+> "stringOffsetType": "UINT32"
+> }
+> }
+> },
+> {
+> "class": "content",
+> "count": 60,
+> "properties": {
+> "triangleCount": {
+> "values": 5
+> }
+> }
+> }
+> ]
+> }
+> }
+> }
+> ```
+
+## TODO
+
+* Define attribute semantics in [3DTILES_shape_ellipsoid_region](../3DTILES_shape_ellipsoid_region/), [3DTILES_layers](TODO), and [3DTILES_horizon_occlusion_point](TODO).
\ No newline at end of file