Looking for on-premises 3D Tiling? Contact sales for an evaluation.
Extract the contents of
The main executable is
model-tiler and can be found under
If you wish to run the examples download and extract SampleData.zip into a new
Windows binaries require Visual C++ Redistributable for Visual Studio 2017. Download and run the installer.
Using the tiler
A typical tiler command follows the following format:
<input-type> must be one of the following types:
PHOTOGRAMMETRY: Meshes produced by photogrammetry software.
3DSCAN: Meshes captured by 3D Scanners or LiDAR.
CAD: Computer-aided design models.
BIM: Building information models. Includes architecture design models and city models.
OTHER: All other types of 3D models. Use this option when in doubt.
A sample BIM model is available in the
SampleData/OfficePlan directory. Tile it into 3D Tiles by running:
This will produce a 3D Tiles tileset in the
Photogrammetry works the same way. A sample photogrammetry model is available in the
SampleData/AGI_HQ directory. Tile it by running:
When combining multiple files, it is important to verify that the models use the same origin and do not occupy the same 3D space.
We can also specify longitude and latitude in degrees and height in meters relative to the WGS84 reference ellipsoid so the tileset will appear in the correct location when streamed in CesiumJS.
These coordinates specify where the model’s origin should be on the map. See Positioning the output below for more details.
The model tiler can take advantage of multicore systems by concurrently tiling separate spatial areas of the input model(s). By default, a concurrency level is automatically set based on available system resources. This can be configured manually with the
The example below enables up to four-way concurrency.
When running inside Docker, it is recommended to set this manually since containerization prevents the tiler from querying system resources.
Tiles can be compressed using lossless gzip compression with the
--gzip option. This requires setting the
gzip in the HTTP header on the server.
Draco compression for meshes is enabled by default and greatly optimizes streaming speed at minimal precision loss. See our blog post to learn more. Use the
--compression-level option to set compression level between 0 (least compression) and 10 (highest compression), as shown below.
Draco compression can be disabled using
Below is a list of command line options to configure the tiler.
||Display help message.|
||Display version number.|
||The path(s) to the OBJ and/or DAE file(s) to be tiled. Required if
||A text file with a list of files to process, one file per line. Required if
||Type of input to be tiled. Options are
||The path to the output directory or
||Suppress output during tiling.||
||Show verbose output.||
||A guideline in megabytes for how much memory may be used for tiling. When running inside Docker, it’s recommended to set this manually since containerization prevents the tiler from querying system resources.||System available.|
||Maximum number of processors to use for concurrent tile processing. Actual utilization depends on system resources. When running inside Docker, it’s recommended to set this manually since containerization prevents the tiler from querying system resources.||System available.|
||When set, overrides the model’s default up axis and treats the given axis as up. By default obj is treated as z-up for
||The longitude in
||The latitude in
||The height in meters relative to the WGS84 ellipsoid at which to place the model’s origin.|
||The rotation in degrees from the local north direction where a positive angle is increasing eastward.||
||The rotation in degrees from the local east-north plane. Positive pitch angles are above the plane. Negative pitch angles are below the plane.||
||The rotation in degrees applied to the local east axis.||
||The uniform scale to apply to the model. The tiler assumes the units for the input model(s) are in meters.||
||The image format to use when encoding textures. When set to
||The image quality to use when encoding textures. Range is
||Draco compression level between 0 and 10. In general, the highest setting, 10, will have the most compression but worst decompression speed. 0 will have the least compression, but best decompression speed. Compression level does not affect precision.||
||Precision in meters for Draco compression. Defaults to millimeter precision. Set to 0 for lossless compression which produces larger tile sizes.||
||Disable Draco geometry compression. See the Compression section for more details.||
||Save tiles with gzip compression.||
||When true, double-sided geometry will be produced. Use when the geometry is not closed or to be able to view it from the inside in CesiumJS.||
||A version number or string to assign to the tileset. This is written to
Now that we’ve tiled our models into 3D Tiles, the next step is to stream them into CesiumJS. All we need is a web server to host our tiles, and then we can pass a URL to our tileset as shown below.
The Hosting 3D Content tutorial walks you through setting up the Cesium ion Asset Server and streaming 3D content with CesiumJS.
Positioning the output
height options allow you to control the position of the model’s origin, which we define as the Cartesian coordinate (0, 0, 0) in model space. All positions in the specified OBJ files (or all transformed positions in the specified COLLADA or glTF files) are Cartesian offsets in meters relative to this origin.
For example, if a house model’s origin is the tip of the chimney, most of the house’s coordinates will be negative, because they specify points below the chimney and therefore below (0, 0, 0).
# house.obj - OBJ files specify position using "v" and inline comments using "#" # tip of chimney v 0 0 0 # second floor (US/Canadian convention), below tip of chimney v 0 0 -6 # ground floor, below tip of chimney v 0 0 -9
When tiling this dataset, the input coordinates should be the
height of the model’s origin, with height relative to the WGS84 reference ellipsoid.
So if the tip of the chimney (the model’s origin) is 9 meters above the ground floor, and if the target CesiumJS app does not use terrain, an input
9 will place the model’s ground floor directly on the ellipsoid surface.
If the app uses terrain, we need to take this into account when placing the model. Assume we want the house to be on a hill 10 meters above the WGS84 reference ellipsoid. We add 10 meters (terrain height) to the 9 meters of the model origin height. Providing an input
19 will place the house dataset with model’s ground floor on the terrain.
If we take into account only the model’s origin position and provide an input
9, the house will end up below terrain in CesiumJS because the
height input is relative to the WGS84 ellipsoid and not relative to terrain. In other words, the tileset is on the ellipsoid surface, but the ellipsoid surface is buried beneath terrain.
Similarly, if we provide an input
10, the house will be under terrain in CesiumJS because we have taken the terrain into account, but not the height of the model’s origin.
The examples above focus on
latitude are relative to the model’s origin in the same way.
The produced tileset’s position can also be offset in CesiumJS as shown in this Sandcastle example.
Tileset is sideways in CesiumJS
input-up-axis option, which defaults to
Z for OBJs. A sideways tileset could indicate that this must be changed to
input-up-axis=Y as shown below.
Tileset isn’t in the right location in CesiumJS
--height are specified when running the tiler.
latitude are in degrees, with
longitude between (-180, 180) and
latitude between (-90, 90).
Height is in meters.
Note that these options are case sensitive. See Positioning the output above for more details.
Tileset is too small or too large in CesiumJS
The tiler assumes the units for the input model(s) are in meters. Use the
--scale option to adjust.
No textures in the output model in CesiumJS
If using OBJs, make sure the textures are accessible via the
.mtl and the
.obj file can access the
The tiler supports
For best results use power-of-two textures.
Some triangles are missing from the tileset
The input models may not be using a consistent winding order, so some triangles may be oriented inwards, causing them to render on the wrong side. Use the
--double-sided option to generate a tileset that forces all triangles to face both ways. This may cause a slight performance hit in CesiumJS.
Third-party licenses used by the tilers can be found in
Patents: US10878613 US10878628 US10872469