3d Tiles Overview
3d Tiles Overview
• How the concepts behind 3D Tiles can be implemented 7. Optimized Rendering with 3D Tiles
for efficient rendering and interaction 8. Spatial Queries in 3D Tiles
• The technical details of the different tile formats in 9. Tile Formats: Introduction
3D Tiles 10. Tile Formats
If you are looking for 3D Tilesets to get started, Cesium ion (https://cesium.com/ion) hosts curated 3D
Tilesets and also allows users to upload their own data to create, host, and stream 3D Tiles.
Both tilesets and tiles are described in JSON. The tileset JSON file contains basic information about the
tileset itself, and the description of the tiles.
Tileset Properties:
Root tile: The root property of a tileset is a tile that represents the root of the tile hierarchy.
Geometric The geometricError property is used to quantify the visual error that would occur if the
error: tileset was not rendered. When the visual error exceeds a certain threshold, then the
tileset and the tiles that it contains are considered for rendering. Details of how the
geometric error is used are given in Section 5, "Geometric Error."
Property The renderable content of tiles may have associated properties. For example, when
summaries: the tiles contain buildings, then the height of each building can be stored in the tile.
The properties object of a tileset contains the minimum and the maximum of
select property values for all tiles in the tileset.
Metadata: Information about the 3D Tiles version and application-specific version information can
be stored in the asset property of a tileset.
Tile Properties:
Content: The actual renderable content that is associated with a tile is referred to via a URI
in the content property.
Children: The hierarchical structure of tiles is modeled as a tree: each tile may have children,
which are tiles in an array named children.
Bounding Each tile has an associated bounding volume, and different types of bounding volumes
Volume: may be stored in the boundingVolume property. The possible types of bounding volumes
are presented in Section 3, "Bounding Volumes." Each bounding volume encloses the
content of the tile and the content of all children, yielding a spatially coherent hierarchy
of bounding volumes.
Geometric The renderable content of tiles may have different levels of detail. For tiles, the
error: geometricError property quantifies the degree of simplification of the content in the
tile compared to the highest level of detail. The geometric error is used as described
in Section 5, "Geometric Error," to determine when the child tiles should be considered
for rendering.
Refinement When the visual error of a tile with a certain level of detail exceeds a threshold, then
strategy: the child tiles are considered for rendering. The way the additional detail from the
child tiles is incorporated into the rendering process is determined by the refine
property. The different refinement strategies are explained in Section 6, "Refinement."
2
3. Bounding Volumes
Each tileset is a set of tiles that are organized in a hierarchical manner, and each tile has an associated
bounding volume. This yields a hierarchical spatial data structure that can be used for optimized rendering
and efficient spatial queries. Additionally, each tile can contain actual renderable content that also has a
bounding volume. In contrast to the tile bounding volume, the content bounding volume fits tightly only
to the content and can be used for visibility queries and view frustum culling to further increase the
rendering performance.
The 3D Tiles format supports different types of bounding volumes, and different strategies for their
hierarchical organization.
"boundingVolume": {
An oriented bounding box fits the bounding volume
"box": [ more tightly to the geometry, particularly for regular,
0, 0, 10, Center technical structures like CAD models. It is defined by
20, 0, 0, x-axis the center position of the box, and three 3D vectors.
0, 30, 0, y-axis
0, 0, 10 z-axis
The vectors define the directions and half-lengths
] of the x, y, and z-axis.
}
3
4. Spatial Data Structures
The tiles in a tileset are organized in a tree data structure. Each tile has an associated bounding volume.
This allows modeling different spatial data structures. The following section will present different types of
spatial data structures that can all be modeled with 3D Tiles. The runtime engine can use the spatial
information generically in order to optimize the rendering performance, independent of the actual
characteristics of the spatial data structure.
Spatial Coherence
All types of bounding volumes and spatial data
structures in 3D Tiles have spatial coherence, "boundingVolume": {
meaning that the bounding volume of a parent "sphere": [
tile always encloses the content of all its child 49.3, 23.0, 10.0, 56.5
]
tiles. }, ...
Spatial coherence is crucial for conservative "children": [
visibility tests and intersection tests because it {
"boundingVolume": {
guarantees that when an object does not
"sphere" : [
intersect the bounding volume of a tile, then 18.1, 14.2, 8.2, 24.0
it also does not intersect the content of any ]
child tile. }, ...
}, {
In contrast, when the object does intersect a
"boundingVolume": {
bounding volume, then the bounding volumes "sphere" : [
of the children are tested for intersections. This 83.6, 21.8, 9.2, 28.4
can be used to quickly prune large parts of the ]
}, ...
hierarchy, leaving only a few leaf tiles where
}
the object must be tested for intersections ]
with the actual tile content geometry.
children[0]:
geometricError: 28
content: SSE:
about
2 pixels
children[0]:
geometricError: 12
content: SSE:
about
1 pixel
When the SSE exceeds a certain threshold, the runtime will render a higher level of detail. For a tileset,
the geometric error is used to determine whether the root tile should be rendered. For a tile, the
geometric error is used to determine whether the children of the tile should be rendered.
where geometricError is the geometric error that was stored in the tileset or tile, screenHeight is the height
of the rendering screen in pixels, tileDistance is the distance of the tile from the eye point, and fovy is the
opening angle of the view frustum in the y-direction.
5
6. Refinement Strategies
When a tileset is rendered, the runtime traverses the hierarchy of tiles, examines the geometric error of
each tile, and computes the associated screen space error. When this screen space error exceeds a
certain threshold, then the runtime will recursively consider the child tiles for rendering. The child tiles
that contain renderable content have a higher level of detail and a smaller screen space error.
The content of the child tiles can be used to increase the level of detail through one of two refinement
strategies. The refinement strategy is determined by the refine property of a tile, and can either be
REPLACE or ADD:
The child tiles contain a content: The child tiles contain content:
The refine property can be given for each tile individually but is only required in the root tile of a
tileset. When it is not given, the strategy will be inherited from the parent tile.
View frustum
During rendering, the runtime maintains a view frustum, which is defined
by the camera position, orientation, and the field-of-view angle. The view Orientation
frustum can be tested for intersections with the bounding volumes of Position
tilesets and tiles.
Field-of-view angle
6
7.1. Optimized Rendering with 3D Tiles: Example
Initially, the runtime loads the main tileset JSON, and tests the
view frustum for intersections with the bounding volume of the
root tile. In this example, the frustum does intersect the til
ese
t
bounding volume of the root tile, which means that the tile is roo
t
The runtime can then test the bounding volumes of the child
tiles for intersections with the view frustum.
chi
In the example, the bounding volumes of two of the three ldr
en[
0]
til
ese
t
roo
child tiles do intersect the view frustum. This means that t
chi
the content of these child tiles is considered for rendering. ldr
en[
1] chi
ldr
Only the content of these child tiles must be loaded. en[
2]
effect of the geometric error that is associated with the rendered chi
ldr
e
con n[1] chi
tiles: it is translated into a screen space error, to estimate the ten
t
ldr
en[
2]
quality of the visual representation. As long as a threshold (which
may be 18.0 in the example) is not exceeded, no refinement of
Screen space error (SSE) : 12.3
the rendered content is necessary. 3 SSE threshold : 18.0
The user can then interact with the rendered tileset. For example,
the user can zoom in to a certain building. This will cause the
chi
screen space error to increase, and when it exceeds a certain ldr
e
con n[0]
til
ese
t
roo
threshold, then the next level of tiles is considered for rendering. ten
t t
chi
These tiles contain a representation of the same content, with a ldr
e
con n[1] chi
ldr
higher level of detail, and therefore, with a smaller geometric ten
t en[
2]
error. The runtime only has to load the content of tiles that have
bounding volumes that intersect the new view frustum.
Screen space error (SSE) : 45.8
4 SSE threshold : 18.0
be rendered efficiently.
Screen space error (SSE) : 15.9
5 SSE threshold : 18.0
This example shows how 3D Tiles balances the rendering performance and visual quality at any scale.
The runtime can detect whether the view frustum intersects the bounding volume of a tile, and only if
this is the case will tile content be downloaded. The runtime can initially display the tile content with
the lowest level of detail, and only download and render the content with a higher level of detail on
demand, when the screen space error exceeds a threshold—for example, when the user zooms closely
to one feature of the dataset.
7
8. Spatial Queries in 3D Tiles
The hierarchical structure of tiles with bounding volumes in 3D Tiles allows for efficient spatial queries.
An example of such a spatial query is ray casting: When a tileset is rendered by the runtime, the user
may interact with the scene by picking individual models or features, for example, to highlight the
model or to display metadata.
To achieve this, a picking ray is computed from the inverse projection matrix. The ray starts at the
current eye position and passes through the mouse position in the view plane. The closest intersection
of this ray with any element of the scene determines which part of the model has been picked.
Picking ray
Eye point
The test for intersections starts at the root tile of the Pseudocode for finding the tile that was
rendered tileset. When the ray intersects the bounding picked with a ray:
volume of this tile, it is tested for intersections with function intersect(ray, tile) {
if (ray.intersects(tile.boundingVolume)) {
each of the child tiles. When an intersection with a leaf
if (tile.isLeaf) {
tile is found, the actual geometry data of the content return tile;
of this tile can be tested for intersections with the ray, }
to determine the actual picking position. for (child in tile.children) {
intersection = intersect(ray, child);
if (intersection) return intersection;
}
During the intersection tests, the spatial coherence
return undefined;
of the tree makes it possible to quickly prune parts of the }
hierarchy that are not intersected: when the bounding
volume of a tile is not intersected, then the intersection Picked
tests for the children of this tile can be skipped. In position
the example, the bounding volumes that are shown
with dashed lines do not intersect the picking ray,
and the traversal may stop there.
For certain types of tiles, knowing that the content of a certain tile was hit with a mouse click may not
be sufficient: In tile formats like Batched 3D Models (Section 10.2) or batched Point Clouds (Section 10.4),
multiple distinct models or parts of models (features) may be combined into a single geometry. In these
cases, the vertices of the geometry are extended with a batch ID, which identifies the feature. This
makes it possible to determine the actual feature that was hit with the mouse click.
8
9. Tile Formats: Introduction
The renderable content of a tile is referred to by a URI that is part of the tile JSON. This renderable content
can be stored in different formats for different model types:
• Batched 3D Model: Heterogenous models like textured terrain or 3D buildings
• Instanced 3D Model: Multiple instances of the same 3D model
• Point Clouds: A massive number of points
A tileset can contain any combination of tile formats. Additional flexibility is achieved by allowing tiles
with different formats to be combined as a Composite Tile (Section 10.5).
The renderable content of a tile contains different features. For Batched 3D Models, each part of the
geometry may be a feature. For example, when several buildings are combined in a Batched 3D Model,
then each building may be a feature. For Instanced 3D Models, each instance is a feature. For Point
Clouds, there are two options: a feature can either be a single point, or a group of points that represent
an identifiable part of the model.
The Batch Table can contain additional, application-specific properties for each feature. For example, in
a Batched 3D Model, metadata that is associated with each model is stored in the Batch Table:
Batched 3D Model Batch Table The information from the Batch
Contains heterogeneous Contains metadata for Table is associated with the model:
models. each model (feature)
Address:
model address 123 Main Street
Each model 0 234 Second Street
is a feature. 1 123 Main Street
... ...
Models in a Batched 3D Model: Batch Table: Declarative styling applied to the rendered model,
based on the information from the batch table:
Model 0 Model 1 Model 2 31.8
model height
23.0
0 23.0
16.2
1 31.8
2 16.2
... ...
9
10. Tile Formats
The actual renderable content of a tile is stored as a binary blob. This blob consists of a header with
structural information, and a body, which contains the actual payload:
Tile format header Tile format body
magic version byteLength For most tile formats, the remaining part
(uchar[4]) (uint32) (uint32) of the header contains information about
the sizes of the Feature- and Batch Table
10
10.1. Tile Formats: Feature Table and Batch Table
The Feature Table and the Batch Table are stored in the tile format body. Both kinds of tables have the
same structure: they consist of a header part, which is interpreted as a JSON string, and a binary body:
JSON header Binary body
(UTF-8)
The JSON part may contain global properties that refer to the whole tile. Additionally, the JSON part
may contain references to the binary body. The exact set of properties that are supported depend
on the tile format, but all properties define segments of the binary body that contain arrays of values
for each feature that appears in the tile.
Feature Table JSON header 1.0 3.4 7.9 1.3 3.6 7.4 ...
120
{
"INSTANCES_LENGTH" : 10, Global properties that are stored in the JSON part of a Feature Table may,
... for example, be the number of points in a Point Cloud or the number of
"POSITION" : { instances for an Instanced 3D Model.
"byteOffset" : 120
}, Additionally, the JSON can contain references to segments of the binary
... body that contain property values for each feature. For example, the
} positions of points in a Point Cloud or the positions of instances in an
Instanced 3D Model.
The section of the binary body that one property refers to is given by the byteOffset inside the body.
The type of the data depends on the property semantics. For example, the POSITION property refers
to a section of the body that represents an array of 32-bit floating-point values, representing the
x, y, and z coordinates of the positions.
Batch Table JSON header (2.1, 3.4) (4.2, 1.8) ... 325 582 ...
0 32
{
"BATCH_LENGTH" : 4,
"location" : { The JSON part of the Batch Table contains global properties, like the
"byteOffset" : 0, number of features in the tile.
"componentType" : "FLOAT",
"type" : "VEC2" Properties that are defined for each feature are given with binary
},
"id" : {
body references. These references define a segment of the binary
"byteOffset" : 32, body that represents an array with the property values. The data
"componentType" : "INT", that is stored in the Batch Table is application specific. Therefore,
"type" : "SCALAR" the references contain additional information about the type of
}
}
elements in the array.
The location of the array data in the binary body is given by the byteOffset. The type says whether the
elements of the array are scalars or vectors. The componentType defines the type of the scalar or vector
components.
The following tables contain the number of bytes that each component type consists of, and the
number of elements that each type consists of. This can be used to compute the byte size of the
property data in the binary body:
componentType Size in bytes type Number of components
“BYTE“ 1 “SCALAR“ 1
“UNSIGNED BYTE“ 1 “VEC2“ 2
“SHORT“ 2 “VEC3“ 3
“UNSIGNED SHORT“ 2 “VEC4“ 4
“INT“ 4
“UNSIGNED INT“ 4
“FLOAT“ 4
“DOUBLE“ 8
11
10.2. Tile Formats: Batched 3D Models (b3dm)
A Batched 3D Model tile contains the rendering data of heterogeneous models. These models may be
terrain or 3D buildings, for example, for Building Information Management (BIM) or engineering
applications.
The actual rendering data in a Batched 3D Model is stored as Binary glTF - a binary form of the GL
Transmission Format. This format allows individual models or even complete 3D scenes with textures
and animations to be stored in a compact form that can be efficiently transferred over networks and
directly rendered by runtime engines. Geometry data in glTF is stored in a buffer that is structured by
dividing the buffer into parts that represent different attributes, like the vertex positions or normals.
A summary and links to further resources about glTF are given in Section 13, "Common Definitions."
The term "batched" refers to the fact that the geometry data of multiple models, each consisting of
vertex positions and optional normals and texture coordinates, can be combined into a single buffer,
in order to improve the rendering performance: the data of a single buffer can be copied directly into
GPU memory, resulting in fewer copying operations, and it can be structured in a form that minimizes
the number of draw calls.
When multiple models are combined into a single buffer, it must still be possible to support styling and
interaction for the individual models. This can refer to highlighting a model by rendering it with a
different color or determining which model has been picked with a mouse click. In 3D Tiles, this is
achieved by extending the buffer with an additional vertex attribute.
The geometry data is extended with position x y z x y z ... x y z x y z x y z ... x y z ...
the batchId attribute. It stores the normal x y z x y z ... x y z x y z x y z ... x y z ...
batch ID for each vertex as an integral batchId 0 0 ... 0 1 1 ... 1 ...
number. Vertices with the same ID are
part of the same model.
The batch ID can then be used to identify the models for
interaction or styling: when the user clicks on a Batched
3D Model, the runtime can determine the batch ID of the
part of the model that was selected. The batch ID serves
as an index for looking up styling information or metadata
in the Batch Table.
Body
12
10.3. Tile Formats: Instanced 3D Models (i3dm)
In many application scenarios, complex scenes contain the same model multiple times, but with small
variations. Examples of such models may be trees, CAD features like bolts, or elements of interior
design like furniture.
The 3D Tiles format therefore supports Instanced 3D Models, where a single model is rendered multiple
times. Each appearance of this model is an instance (or feature), and the instances can be rendered
with different transformations—for example, at different positions.
The actual model is stored as a binary glTF (see Section 13, "Common Definitions"). It can be stored
directly in the binary body. Alternatively, the body can contain a URI for the binary glTF file. Information
about how many instances will be rendered, and the positions and orientations of these instances, are
stored in the Feature Table. The first part of the Feature Table contains JSON data, and the second part
contains the binary data.
Feature Table JSON header Feature Table binary body
{
"INSTANCES_LENGTH" : 3, The JSON part of the Feature Table of an Instanced 3D Model contains the
"POSITION" : { global INSTANCES_LENGTH property, which determines the number of
"byteOffset" : 0 instances that will be rendered.
},
"NORMAL_UP" : {
It further contains properties for each feature (instance), given as references
"byteOffset" : 36 into the binary body of the Feature Table. The section of the binary body that
}, starts at the respective byteOffset represents an array. The array length is
"NORMAL_RIGHT" : { given by the number of instances. The type of the array is determined by the
"byteOffset" : 72
}, property: in the example, the properties are POSITION, NORMAL_UP, and
"SCALE" : { NORMAL_RIGHT, each given by three floating-point values for the x, y, and z
"byteOffset" : 108 coordinates, and a SCALE factor for each instance, given as single
}
} floating-point values.
1 2 3 4 5 6 7
Body
Feature Table Batch Table URI (UTF-8) or Binary glTF External data
13
Instanced 3D Models: Properties
The Feature Table of an Instanced 3D Model may contain the following properties:
Number of The number of instances that will be rendered, stored in the INSTANCES_LENGTH property. This determines the length
instances: of the arrays that store the per-instance properties. It also determines the size of the Batch Table in the case that the
Batch Table stores metadata for each instance.
Batch ID: An identifier for each instance, stored in the BATCH_ID attribute. This batch ID serves as an index that can be used
to look up properties for each instance in the Batch Table.
Position: The positions of the instances, given as cartesian x, y, and z coordinates. The positions can be stored directly in a
POSITION attribute, or using a compressed, quantized representation in the POSITIONS_QUANTIZED attribute.
Relative-to- The center point for relative-to-center positions, can be stored in the RTC_CENTER attribute. When it is defined, then
center point: the positions are given relative to this point.
Quantized The volume that is used for quantization when the positions are given in their compressed form in the
volume: POSITIONS_QUANTIZED property. The volume is defined by the QUANTIZED_VOLUME_OFFSET, which defines the offset
of the volume, and the QUANTIZED_VOLUME_SCALE, which defines the scale for the quantized volume.
Orientation: The orientation of each instance can be defined with two vectors: one vector defining the up-direction, and one
vector defining the right direction. These normals can be stored in the NORMAL_UP and NORMAL_RIGHT attribute, or
using a compressed, oct-encoded representation of the normals, where the normals are stored in the
NORMAL_UP_OCT16P and NORMAL_RIGHT_16P attribute.
Default When the orientation is not given for the individual instances, then the EAST_NORTH_UP can be used to indicate
orientation: that each instance will default to the east/north/up reference frame's orientation on the WGS84 ellipsoid.
Scale: The scaling factors for the instances. The scaling for each instance can either be a uniform scaling, which is a single
value stored in the SCALE attribute, or scaling factors along the x, y, and z-axes, given via the SCALE_NON_UNIFORM
attribute.
Further information about the quantized position and oct-encoded normal representations, about the
concept of relative-to-center positions, and the WGS84 ellipsoid, can be found in Section 13, "Common
Definitions."
Per-instance Properties
Each of these properties is a reference to a section of the binary body of the Feature Table. This
section contains the data of an array with the actual property values. The data type of the array
elements is given by the type of the property. The length of the array is determined by the
number of instances.
Property Type Description
POSITION float32[3] The x,y, and z coordinates for the position of the instance
POSITION_QUANTIZED uint16[3]
NORMAL_UP float32[3] A unit vector defining the up-direction of the instance
NORMAL_UP_OCT32P uint16[2]
NORMAL_RIGHT float32[3] A unit vector defining the right-direction of the instance
NORMAL_RIGHT_OCT32P uint16[2]
SCALE float32 A scaling factor for all axes of the instance
SCALE_NON_UNIFORM float32[3] The scaling factors for the x, y, and z-axis of the instance
BATCH_ID uint8/16/32 The batch ID, to look up metadata for the instance in the batch table
14
10.4. Tile Formats: Point Clouds (pnts)
A common way of obtaining 3D data from existing structures like buildings or the environment is via
photogrammetry or LIDAR scanning. The result of this acquisition process is a point cloud, where each
point is defined by its position, and additional properties that define its appearance.
The Point Clouds format is a format in 3D Tiles that allows streaming massive point clouds for 3D
visualization.
The information about the positions and other visual properties of the points is stored in the Feature Table,
which consists of a JSON header and a binary body.
{
The JSON part of the Feature Table of a point cloud contains the global
"POINTS_LENGTH" : "219",
"POSITION" : { POINTS_LENGTH property that determines the number of points.
"byteOffset" : 0 Further properties are given by references into the binary body: for each
},
property, the byteOffset determines the position in the binary body that
"NORMAL" : {
"byteOffset" : 2628 contains an array with the property values for each of the points. The type
}, of the array depends on the property: for the POSITION and NORMAL, the
"RGB" : { array elements will be 3D vectors of floating-point values. For the RGB color,
"byteOffset" : 5256
} the elements will consist of three unsigned 8 bit values for the red, green,
} and blue component of the color.
...
...
...
...
15
Batched Point Clouds
In a Point Cloud, it is possible to define groups of points that represent distinct features. For example,
there may be groups of points that represent a door, a window, or the roof of a house.
In 3D Tiles, these groups are defined by assigning a batch ID to the points, similar to the concept that is
used for Batched 3D Models.
For batched Point Clouds, the JSON part of the Feature Table contains a BATCH_LENGTH property that
defines the number of groups of points, and a BATCH_ID property that refers to a section of the binary
body that contains the array with batch IDs for the points, stored as 8, 16, or 32-bit integer values. The
batch ID can then be used as an index to look up metadata for that group of points in the Batch Table.
Body
16
Point Clouds: Properties
The Feature Table of a Point Cloud may contain the following properties:
Number of The number of points in the Point Cloud is given by the POINTS_LENGTH property. This determines the length of the
points: arrays that store the per-point properties.
Number of The number of batches (groups of points) in the Point Cloud, stored in the BATCH_LENGTH property. It is therefore the
batches: number of unique values in the BATCH_ID attribute, and the number of entries in the Batch Table.
Batch ID: An identifier for the batch (group) that the point belongs to is stored in the BATCH_ID attribute. All points with
the same batch ID belong to one batch. The batch ID serves as an index to look up properties for this group of
points in the Batch Table.
Position: The positions of the points, given as cartesian x, y, and z coordinates. The positions can be stored directly in a
POSITION attribute, or in a compressed, quantized representation in the POSITIONS_QUANTIZED attribute.
Relative-to- The center point for relative-to-center positions can be stored in the RTC_CENTER attribute. When it is defined, then
center point: the positions are given relative to this point.
Quantized The volume that is used for quantization when the positions are given in their compressed form in the
volume: POSITIONS_QUANTIZED property. The volume is defined by the QUANTIZED_VOLUME_OFFSET, which defines the offset
of the volume, and the QUANTIZED_VOLUME_SCALE, which is the scale for the quantized volume.
Normal: Unit vectors defining the normals of the points. These can be stored in the NORMAL attribute, or using a compressed,
oct-encoded representation of the normal, using the NORMALS_OCT16P attribute.
Color: The color for each point can be given as RGB or RGBA colors that are stored in the RGB or RGBA properties.
Alternatively, a compressed representation of the colors can be stored, in the RGB565 property.
Constant A color for all the points in the tile can be given in the CONSTANT_RGBA property. This color will be used when no
color: colors for the individual points are defined.
Further information about the quantized position and oct-encoded normal representations, and about
the concept of relative-to-center positions, can be found in Section 13, "Common Definitions."
Global Properties
Property Type Description
POINTS_LENGTH uint32 The number of points
QUANTIZED_VOLUME_OFFSET float32[3] The offset of the quantized volume in x, y, and z-direction
QUANTIZED_VOLUME_SCALE float32[3] The scale of the quantized volume in x, y, and z-direction
CONSTANT_RBGA uint8[4] The RGBA color components for all points in the tile
BATCH_LENGTH uint32 The number of batches for the points
RTC_CENTER float32[3] The center position when positions are defined relative-to-center
Per-point Properties
Each of these properties is a reference to a section of the binary body of the Feature Table. This
section contains the data of an array with the actual property values. The data type of the array
elements is given by the type of the property. The length of the array is determined by the number
of points.
Property Type Description
POSITION float32[3] The x,y, and z coordinates for the position of the point
POSITION_QUANTIZED uint16[3]
RGBA uint8[4] The RGBA color components of the point
RGB uint8[3] The RGB color components of the point
RGB565 uint16 A compressed, 16bit representation of RGB colors, with 5 bits for red, 6 bits for
green, and 5 bits for blue
NORMAL float32[3] A unit vector defining the normal of the point
NORMAL_OCT16P uint8[2]
BATCH_ID uint8/16/32 The batch ID, to look up metadata for the points the batch table
17
10.5. Tile Formats: Composite Tiles (cmpt)
3D Tiles supports streaming heterogenous datasets. Multiple tile formats can be combined in one tileset.
It is also possible to combine multiple tiles of different formats in a Composite Tile for additional flexibility.
One example for the use of Composite tiles can be found
Batched 3D Model Instanced 3D Model
in geospatial applications: A set of buildings could be
stored in a Batched 3D Model, and a set of trees could
be stored as an Instanced 3D Model. When these elements
appear at the same geographic location, it is useful to
combine these models in a single Composite tile: The
renderable content for a given geolocation can then be
obtained as a single tile, with a single request.
The tiles that are combined in a single Composite cmpt ... b3dm ... ... i3dm ... ...
tile are referred to as inner tiles. Composite tiles can
also be nested, meaning that each inner tile can again
be a Composite tile.
Composite Tile:
As for other tile formats, the header of a Composite
tile starts with the magic bytes that indicate the
tile format (cmpt), followed by a version number,
and the total length of the tile data, including the
header, in bytes.
The common part of the header is followed by an integer that indicates the number of tiles that have
been combined in the Composite tile.
The body of a Composite tile just consists of an array of inner tiles. Each inner tile is a binary blob
representing a tile: It starts with the common header, indicating the format, version, and length of the
inner tile data, followed by the body for the respective tile format.
11. Extensions
3D Tiles offers a mechansim to extend the base specification with new features: each JSON object in
3D Tiles may contain an extensions dictionary. The keys of this dictionary are the names of the
extensions, and the values may be extension specific objects. Vendors can propose extensions and
provide a specification for the structure and semantics of the extension objects that are contained
in the dictionary.
{ This example shows the JSON that may be added to a tile JSON
...
"extensions": {
in the context of a hypothetical vendor extension that defines
"VENDOR_collision_volume": { a collision volume for the tile. The name of the extension is
"sphere": [ 5.0, 3.0, 7.0, 10.0 ] VENDOR_collision_volume, and it defines a collision sphere
} via its center and radius, similar to the bounding volumes
}
} that are already supported in 3D Tiles.
The names of extensions that are used in a tileset or one of its descendants must be listed in the
top-level extensionsUsed dictionary of the tileset. When a certain extension is required in order to
properly load and render the tileset, it must also be listed in the extensionsRequired dictionary.
Implementations can inspect these dictionaries when the tileset is loaded, and check whether they
support the extensions that are used or required by the tileset.
18
12. Declarative Styling
Depending on the tile format, the renderable content of a tile may contain different features. For Batched
3D Models, each model that is identified with a batchId is a feature. For Instanced 3D Models, each
instance is a feature. For Point Clouds, there are two options: when the points are batched together,
each group of points that has the same batchId is a feature. Otherwise, each point is a feature.
3D Tiles allows modifying the appearance of features at runtime, using declarative styling: a style is
defined with JSON that contains a set of expressions. The values of these expressions determine the
visibility or color of the features. The runtime engine can evaluate these expressions and apply styling
to the features based on user interaction and the feature properties that are stored in the Batch Table.
For example, in a Batched 3D Model where each building is a feature, the color of the buildings may be
modified at runtime, based on different criteria. The following is an example of a style JSON that
causes buildings to be rendered with different colors, depending on their height:
{
"color": {
"conditions": [
["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
["${height} >= 200", "rgb(102, 71, 151)"],
["${height} >= 100", "rgb(170, 162, 204)"],
["${height} >= 50", "rgb(224, 226, 238)"],
["${height} >= 25", "rgb(252, 230, 200)"],
["${height} >= 10", "rgb(248, 176, 87)"],
["${height} >= 5", "rgb(198, 106, 11)"],
["true", "rgb(127, 59, 8)"]
]
}
Expressions
The styling language supports most of the unary and binary operators that are supported by JavaScript,
as well as the ternary conditional operator and common built-in mathematical functions like abs, max,
or cos.
The types of the language include the vector types vec2, vec3, and vec4. The vec4 type is used to
represent RGBA colors.
Vector components of the vec2, vec3, and vec4 types can be accessed using the dot notation. For
example, the elements of a 4D vector v can be interpreted as x, y, z, and w-coordinates and accessed
as v.x, v.y, v.z, and v.w. Equivalently, they can be interpreted as RGBA color components, and
accessed as v.r, v.g, v.b, and v.a.
Alternatively, the components can be accessed using the array notation, where the elements of a 4D
vector v can be accessed as v[0], v[1], v[2], and v[3].
Colors are represented with the vec4 type, containing the RGBA color components. There are different
convenience functions for creating colors from different arguments. These functions resemble the
ways colors can be defined in CSS. For example:
• color('red')) From a keyword
• color('blue', 0.5) From a keyword, with an opacity (alpha) of 0.5
• color('#00FFFF') From a hex RGB string
• rgb(100, 255, 90) From red, green and blue components in [0, 255]
• hsl(1.0, 0.6, 0.7) From hue, saturation and lightness, each in [0, 1]
Several built-in functions are defined that can be applied to numbers as well as certain vector types:
the clamp function can be used to constrain numbers or vector components to a certain range. The
mix function allows linearly interpolating between numbers or vectors. The length, distance,
normalize, and dot functions may be used for geometric computations on vectors. The cross function
allows computing the cross product of 3D vectors.
Expressions can be parsed into an abstract syntax tree (AST) and be evaluated. The type of an evaluated
expression must match the type of the style property.
Variables
The expressions that are used in a style may contain variables. These variables refer to properties of the
features in a tile. The actual values of these properties are stored in the Batch Table.
Variables are written using the ECMAScript 2015 template literal syntax: the literal ${property} refers
to a property of a feature, where property is the case-sensitive property name.
The following is an example of a style that assigns a color to a feature, based on the height of the
feature that is stored in the Batch Table: features with a height greater than 50 will be colored red,
and all others will be white:
{
"color" : "(${height} > 50) ? color('red') : color('white')"
}
20
12. Declarative Styling)
Conditions
The style properties may also be written using conditions. A condition consists of two expressions: an
expression that evaluates to a boolean value, and an expression that is evaluated when the boolean
value is true. Multiple conditions can be combined as an array.
Defining Variables
In addition to the variables that refer to properties in the Batch Table, a style may also define its own
variables. These definitions are given in the defines property of a style. Each definition consists of the
name of the new variable, which is mapped to an expression. The expression may not refer to other
defines, but it may refer to existing variables from the Batch Table.
Regular Expressions
Styles support regular expressions, so that it is possible to formulate conditions for rendering based on
property values from the Feature Table that are stored as strings.
{ A style that will only show features that have a ${name}
"show" : "regExp('Building\s\d').test(${name})" property that matches the given pattern: the string
}
"Building", followed by a space and an integer.
Further information about the quantized position and oct-encoded normal representations can be found
in Section 13, "Common Definitions."
21
13. Common Definitions
13.1. glTF - The GL Transmission Format
Batched 3D Models and Instanced 3D Models in 3D Tiles may embed models that are stored as Binary
glTF. This is the binary form of the GL Transmission Format, which is an open specification for the
efficient transmission of 3D content, maintained by the Khronos Group.
https://github.com/KhronosGroup/glTF
Theoretical value Actual 32-bit single-precision value Despite the different values of
131072.01 131072.0156250 131072.01 and 131072.02, the
representations of these values
131072.02 131072.0156250
as 32-bit single-precision values
131072.03 131072.0312500 are equal.
This lack of accuracy can result in rendering artifacts—most noticeably, in visual jitter when zooming
closely to one of the rendered objects. To alleviate this problem, 3D Tiles supports a technique for
compensating the error that results from large coordinate values. This technique is called Relative To
Center (RTC) rendering.
The vertex positions for Batched 3D Models are stored as one attribute in the glTF representation of the
model. For Instanced 3D Models and Point Clouds, the Feature Table contains a position property for the
instances and points. The coordinate values of these positions are usually stored as single precision,
32-bit floating-point values. To support RTC rendering, the respective tile formats allow specifying an
RTC_CENTER property in their Feature Table. This property defines the center of an application-specific
coordinate system, and if it is present, all positions are assumed to be given relative to this center.
To take into account the relative positions of the vertices, the RTC_CENTER is used to modify the
Model-View-Matrix that is used for rendering. Initially, this is a matrix MV GPU, stored in double-precision
on the CPU. The RTC_CENTER is transformed into eye coordinates using the original Model-View matrix:
The Model-View-Matrix that is used for rendering then is a matrix MV GPU that is stored in single-precision,
and which is created by replacing the last column of the original Model-View matrix with the resulting
RTC_CENTEREye.
With this technique, it is possible to avoid the appearance of large values in the positions of the model,
which would cause rendering artifacts due to the limited precision of the subsequent rendering pipeline:
the positions can be given as small values, relative to the RTC_CENTER, and the modified Model-View
matrix properly transforms them into the eye coordinate system for rendering.
22
(13. Common Definitions)
13.4. Transforms in 3D Tiles
The renderable content in 3D Tiles may be given in different coordinate systems. For example, a tileset
for a city could contain a nested tileset for a single building, and the latter could be given in its own
coordinate system.
In order to convert between local coordinate systems, each tile has an optional transform property.
This property is a column-major 4⨉4 affine transformation matrix and transforms the coordinate
system of the tile into the coordinate system of the parent, defaulting to the identity matrix when it
is not defined.
The transform matrix of a tile affects the positions, normals, and the bounding volumes of the tile and
its content. The positions of features (like instances in an Instanced 3D Model, or points in a Point
Cloud) are multiplied with the transform matrix to bring them from the local coordinate system into the
coordinate system of the parent tile. The normals are multiplied with the top-left 3⨉3 matrix of the
transpose of the inverse of the matrix, to properly take non-uniform scaling into account. The bounding
volumes are transformed with the matrix, except the "region" bounding volumes, which are explicitly
defined to be in EPSG:4979 coordinates.
Similarly, the normals of points and instances can be given as vectors consisting of three floating-point
values, in the NORMAL, NORMAL_UP, and NORMAL_RIGHT attribute. For larger numbers of points or
instances, these normals can be stored in a compressed form, indicated by the _OCT16P suffix of these
attribute names. This compressed form consists of a bidirectional mapping: the normal vectors are
mapped from the octants of a unit sphere to the faces of an octahedron, which are then projected to
the plane and unfold into a unit square. Using this compression, a 3D normal vector can be represented
with a single 16-bit value.
https://github.com/CesiumGS/3d-tiles/blob/master/specification/TileFormats/PointCloud/README.md#oct-encoded-normal-vectors
23