Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds 3DTILES_binary_buffers extension #415

Closed
wants to merge 7 commits into from
Closed
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions extensions/3DTILES_binary_buffers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# 3DTILES_binary_buffers

## Overview

This extension to 3D Tiles enables storage of binary data in external buffers.

## Properties Reference

---------------------------------------
### 3DTILES_binary_buffers.bufferViews

`bufferViews` provide a typed view into a `buffer`.

**Properties**

| |Type|Description|Required|
|---|----|-----------|--------|
|**buffer**|`integer`|The index of the buffer.|☑️ Yes|
|**byteOffset**|`integer`|The offset relative to the start of the buffer in bytes.|☑️ Yes|
|**byteLength**|`integer`|The length of the bufferView in bytes.| ☑️ Yes|
|**elementCount**|`integer`|The number of elements in the buffer view.| ☑️ Yes|
|**elementByteOffsetsBufferView**|`integer`|The index of the bufferView containing byte offsets for each element. Must be defined for the STRING element type.|No|
|**elementType**|`string`|Specifies if the attribute is a scalar, vector, matrix or string.|No, default is `SCALAR`.|
|**componentType**|`string`|The datatype of components in the attribute. Must be defined for every other element type, except STRING (in which case it will be ignored).|No|


#### Element Types

| Element Type | No. of components |
|:------------:|:-----------------:|
| SCALAR | 1 |
| STRING | 1 |
| VEC2 | 2 |
| VEC3 | 3 |
| VEC4 | 4 |
| MAT2 | 4 |
| MAT3 | 9 |
| MAT4 | 16 |

*Note: The `STRING` element type only stores UTF-8 encoded strings.*

#### Component Types

| Component | Size (bits) |
|:---------:|:------------:|
| BIT | 1 |
| BYTE | 8 |
| UNSIGNED_BYTE | 8 |
| SHORT | 16 |
| UNSIGNED_SHORT | 16 |
| HALF_FLOAT | 16 |
| INT | 32 |
| UNSIGNED_INT | 32 |
| FLOAT | 32 |
| DOUBLE | 64 |


*Note: The buffer views for the `BIT` component type must be padded with trailing `0`s to meet the nearest byte boundary.*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The padding requirements should be defined for the other component types. In general properties must start on a byte offset that's a multiple of the size of the component type.

See https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/BatchTable#padding

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason behind this? As long as the byte boundary is respected, the data can be read using byte offsets and byte lengths. What is gained by having the offset be a multiple of the size of the component type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked offline about this, but it's for performance reasons. In JavaScript typed arrays need to be aligned to their component type within the underlying array buffer which means unaligned data needs to be cloned into a new typed array. Proper alignment also provides performance benefits in systems level languages.

Early on glTF had the same rationale: KhronosGroup/glTF#167

https://github.com/CesiumGS/cesium/blob/2a9ca28dcbb38eee7013505987516446a8eacb4f/Source/Scene/Batched3DModel3DTileContent.js#L370-L382 - this is where CesiumJS clones the typed array if it isn't aligned. 3D Tiles didn't always have byte alignment requirements which lead to slow paths like this.


---------------------------------------
### 3DTILES_binary_buffers.buffers
A buffer points to a blob data.

**Properties**

| |Type|Description|Required|
|---|----|-----------|--------|
|**uri**|`string`|The uri of the buffer.| ☑️ Yes|
|**byteLength**|`integer`|The total byte length of the buffer.| ☑️ Yes|

## Examples

### 3DTILES_implicit_tiling and 3DTILES_tile_metadata

```json
{
"asset": {
"version": "1.0"
},
"extensions": {
"3DTILES_implicit_tiling": {
"tilingScheme": "quadtree",
"subdivision": {
"completeLevels": 2,
"bufferView": 0
},
"content": {
"levelOffset": 2,
"levelOffsetFill": 0,
"bufferView": 1
},
"metadata": {
"levelOffset": 2,
"levelOffsetFill": 0,
"bufferView": 1
}
},
"3DTILES_tile_metadata": {
"properties": {
"surfaceArea": {
"semantic": "_SURFACE_AREA",
"bufferView": 2
},
"tileId": {
"semantic": "_TILE_ID",
"bufferView": 3
}
}
},
"3DTILES_binary_buffers": {
"bufferViews": [
{
"elementType": "VEC2",
"componentType": "BIT",
"byteOffset": 0,
"byteLength": 2,
"buffer": 0
},
{
"elementType": "SCALAR",
"componentType": "BIT",
"byteOffset": 2,
"byteLength": 4,
"buffer": 0
},
{
"elementType": "SCALAR",
"componentType": "FLOAT",
"byteOffset": 0,
"byteLength": 32,
"buffer": 1
},
{
"elementType": "STRING",
"byteOffset": 32,
"byteLength": 64,
"elementByteOffsetsBufferView": 4,
"buffer": 2
},
{
"elementType": "SCALAR",
"componentType": "UNSIGNED_INT",
"byteOffset": 0,
"byteLength": 32,
"buffer": 2
}
],
"buffers": [
{
"uri": "implicit.bin",
"byteLength": 6
},
{
"uri": "metadata_surface_area.bin",
"byteLength": 32
},
{
"uri": "metadata_tile_id.bin",
"byteLength": 96
}
]
}
}
}

```