3D Tiles の概念や雰囲気をざっくりと説明する

3次元の地理情報データをストリーミングするための規格である 3D Tiles の概要を説明します。詳しい話はいくらでもありますが、ここでは雰囲気をつかむことを目的とします。

（これは2023年9月末に社内用に書いたメモ書きをほぼそのまま転載したものです）

## 2Dタイルおさらい

2Dの地図タイルについては既にご存知とします。

### おなじみのXYZタイル (2D)

MapTiler 社のこのページが分かりやすいです：

https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection/

技術的にいえば「四分木（Quad-tree）」というツリー構造です：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95370/635dfda7-306f-286f-a014-dfc56635b5a6.png)

**特徴**：

- 地球全体を表現できる
- ズームインして詳細を見れる
- 必要な部分だけ随時ダウンロードすれば済む（ストリーミングできる）

---

これらの特徴は**2Dのタイルでも3Dタイルでも同じ**です。

## 3Dもタイル化したい...

ということで、[Cesium](https://cesium.com/) が策定した仕様「**3D Tiles」**。今では OGC (Open Geospatial Consortium) のオープン標準になっています。

3D Tilesももちろんツリー構造なのですが、必ずしも XYZ タイル（四分木）のような規則的なツリーでなくていいのが特徴です。つまり空間をツリー構造に分割していく方法はかなり自由です。

3D Tiles **1.0** と 3D Tiles **1.1** があり、いずれもOGCのオープン標準になっています。仕様書: [3D Tiles Specification](https://docs.ogc.org/cs/22-025r4/22-025r4.html)

## 3D Tilesで表現できるもの

Cesium のデモをみると、何がどこまでできるのかがわかりやすいです。色々なデモがあります。

https://sandcastle.cesium.com/#c=bVNha9swEP0rR9gHB1IpJS2DLA3rksEC6zrWsDLwh8rWxRGTJSOdk6Yl/32yZXfp1k/2O9179/QkcQ6faqWlMgVIQQJyWztCfwC7gW+/FnBboVk2C5V1JPQUtkTVlPP9fn/OzCFnhd1xrwi5tIqIK6NICVI79Hwiz7JOnFWiwNTk1niCncI9OrgCg3tYoFd1yX62tSQd5C1eWENCGXTpYATPqQEgdC5Upj1hHTHbOFveW6dlV0iGo9Qchx9Sk5o4iPkcDbJC2wyZxIq2a/R0XYRmTx0rmCFX4ykLHwmNTLpxsRjBZLlWGv3K+Apzsu5GPSrTTIzbU3292dONlaiDeieavynQqredrQFyh7jnqEdNL1IQEXuhqA/glRekNoiVNdc+gJVM3l9OLiZddgBoRKZxiVld3CuHGydKnLZbHjUNbV4Ar/KqnCpVe5BMSJl0LmJjB0KaQXBhtXXqCVsjp0G+CD5ZW65tEq103FFEJ1fgC4rmqnxXlG9/CFNgRwAYs/Go/z8bs8sX0PvIbG0a7l21RYfMBaHaA4cLNo6tw+bTeD9CLoI+JOHcrRv+zdlqZNoWycPnZgG0bc30E6bw7rllHB+iymA0mHk6aJz3Xj6qsnkjUDudMMYJy0qL8JR4Vue/g8fc+xgewIyfUmdS7UDJqzfuPuRaeB9WNrXWdyHjdDCf8dD/H7Xze7tDp8Whaduez7/GImNsxgN8m0nW6ky4f5T/AA

- **3Dメッシュ：** 建物、地形、etc.
- **点群**
- **3Dインスタンス**： 同じ物体（例：電柱）を大量に配置  (GPU Instancing)

---

地物や頂点などにメタデータを付与することもできます。

![Untitled.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95370/25b2b190-e60d-11d0-5b3e-81eb8a2529f1.jpeg)

## Google Photorealistic 3D Tiles

[Google Photorealistic 3D Tiles](https://developers.google.com/maps/documentation/tile/3d-tiles) も「3D Tiles **1.0**」(2023年9月時点) として利用できます。

https://sandcastle.cesium.com/#c=dVPbjtowEP2VEepDkKiTEGBpy6JWULWVdlW0W/UpD2ucAUZ1bGSbW1f8e+0kLLRs8+Q5M2fO3CK0sg62hDs0cAsKdzBBS5uS/aywKG+Jyp5o5TgpNHmrA8+5AnBUovTIe1hwabETMK6o5I60ugStQIX3usAZiV9oLl1zbvGOH9Bcu5ZSzy9yH9sfclXXyXDvUBVRU2gN1kY2/UES7Tdl1yicNve0JxWYuYpj+FQUMFtpjyOXZB0JyKZQMXLlzKHuS1QjcQFF52fCd5zcaSrCUx1+0Xop8e9UjTS6KOhBM1NWNc/WhkpytEXLeFFETfIQeATBnVhBhMZo0z6XoCUyqZfR0+fgAKl5QWr5v/pP9bJAf/NcJTs+VQJN8zNNyre1Qi9YouHAa6vuZS1x/zLfuuY6jPmk4RSiqrACvapqNnxxLBNunH9xlbGF0eUUlwbRRoFSf2kvZdkgGQ66/ax/M+ynN52zs5exZNBLB0n3XTbM+oNhB87ObpKwJJjtiqENob/Eqwq+YjWfGflhPmgpG+20kXl7eryk8gcFrU5rZN1B4vik95HKtTYONkZGjMUOy7X0C7fxfOMP1DFhbb1egFF8SR0VtAUqbl/5X0BIbq33LDZSPtJvzFvjUezjr6jNkr9v0Uh+CGGrdHxXg4yxUezN15lOaznn5p/MfwA

Google Photorealistic 3D Tiles は、地上の人工物だけでなく地形もいっしょくたに表現されていますので、Cesium上に表示するときはCesiumが提供する地形は非表示にしましょう。

```jsx
// Google Photorealistic 3D Tiles は地面もいっしょに含んでいるため、
// Cesiumが提供する地球は表示しなくてよい。
globe: false;
```

各タイルがどうなっているかを、デバッグ表示でみてみます。

![Untitled2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95370/6a74cf73-9365-332f-c1c6-3f9665ab9672.jpeg)

ちなみに、どのタイルもファイルサイズは 10〜100 KB程度になっています。

## 3D Tiles (1.0) のタイル分割

### 2Dなタイルと似ている点

- ツリー構造なのは同じ。
- ツリーの子にいくほど詳細度が上がるのも同じ。HLOD = Hierarchical Level of Detail

### 2Dなタイルと異なる点

- **空間を分割していく方法がまったく自由。** 各自で自由に決める。
    - 直方体、球、リージョン（今回は触れない）で自由に分割していく。
    - もちろん単純な4分割や8分割を繰り返していってもいい。
    - 県 → 市 → 町字 みたいな分割でもいい。
    - なんでもいい。
    - 注）3D Tiles 1.1 には “implicit tiling” もある（あとでさらっと言及）。
- **タイルの境界が重なり合っていてもいい。**
    - タイルのバウンディングボリュームに重複があってもいい。公式デモなどで BoundingVolume を表示してみればわかる： [https://sandcastle.cesium.com/?src=3D Tiles Inspector.html&label=3D Tiles](https://sandcastle.cesium.com/?src=3D%20Tiles%20Inspector.html&label=3D%20Tiles)
- 詳細度を上げていく（ツリーの子をたどる）際の方法として refine: `REPLACE` と refine: `ADD` が選べる
    - `REPLACE` → 子タイルの内容で親タイルの内容を入れかえる方式 (→ [Photorealistic 3D Tiles](https://sandcastle.cesium.com/#c=dVPbjtowEP2VEepDkKiTEGBpy6JWULWVdlW0W/UpD2ucAUZ1bGSbW1f8e+0kLLRs8+Q5M2fO3CK0sg62hDs0cAsKdzBBS5uS/aywKG+Jyp5o5TgpNHmrA8+5AnBUovTIe1hwabETMK6o5I60ugStQIX3usAZiV9oLl1zbvGOH9Bcu5ZSzy9yH9sfclXXyXDvUBVRU2gN1kY2/UES7Tdl1yicNve0JxWYuYpj+FQUMFtpjyOXZB0JyKZQMXLlzKHuS1QjcQFF52fCd5zcaSrCUx1+0Xop8e9UjTS6KOhBM1NWNc/WhkpytEXLeFFETfIQeATBnVhBhMZo0z6XoCUyqZfR0+fgAKl5QWr5v/pP9bJAf/NcJTs+VQJN8zNNyre1Qi9YouHAa6vuZS1x/zLfuuY6jPmk4RSiqrACvapqNnxxLBNunH9xlbGF0eUUlwbRRoFSf2kvZdkgGQ66/ax/M+ynN52zs5exZNBLB0n3XTbM+oNhB87ObpKwJJjtiqENob/Eqwq+YjWfGflhPmgpG+20kXl7eryk8gcFrU5rZN1B4vik95HKtTYONkZGjMUOy7X0C7fxfOMP1DFhbb1egFF8SR0VtAUqbl/5X0BIbq33LDZSPtJvzFvjUezjr6jNkr9v0Uh+CGGrdHxXg4yxUezN15lOaznn5p/MfwA))
    - `ADD` → 子タイルの内容を親タイルの内容に追加していく方式 (→ [OSM建物デモ](https://sandcastle.cesium.com/?src=Cesium%20OSM%20Buildings.html&label=3D%20Tiles))
    - これらはツリーの途中で切り替えることも可能

---

ツリーの組み方の主な**ルールは以下の2つ。あとは自由**です：

- 子のコンテンツが、親のバウンディングボリュームを超えないこと
- 子にいくほどジオメトリの誤差 (`geometricError`) が小さくなること

## 少しだけ詳しいタイルツリーの構造

Google Photorealistic 3D Tiles の実際のタイルツリーをみてみると次のようになっています：

- タイルのツリー構造（＝タイルセット）は JSON で記述されている。
- ツリーの途中で別のタイルセットファイルを参照できる（例えば地球規模のタイルセットの場合、1つの超巨大なJSONファイルで表現するのはまずい or 不可能であるため）。
- 各タイルにそのタイルのジオメトリ誤差 (`geometricError`) が記載されている。
    - 表示側は、その誤差では不十分と判断したら、さらに子をたどる

![Tiling.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95370/04f3aa11-8b0f-7c57-c205-bb61a5491d0b.jpeg)


## 3D Tiles 1.1 の新機能

3D Tiles 1.1（かつて 3D Tiles Next と言われていたもの）。

主には：

- 3Dデータを **すべてglTF** で表すようになった（1.0 ではglTF の利用は拡張機能だった）
    - いままでのデータ形式 (.b3dm, .i3dm, .pnts, .cmpt) はすべて deprecated になった。
- “**Implicit Tiling**”（暗黙的タイリング）も使えるようになった
    - XYZタイルのような「4分木 (Quad-tree)」ないし「8分木 (Octree)」で、効率的に空間分割できる。具体的な実現については複雑なのでここでは触れない。

## 詳しく知りたい方は

仕様書・サンプルが充実しています。

### **3D Tiles 1.0 & 1.1**

- 3D Tiles 1.1 Specification: https://docs.ogc.org/cs/22-025r4/22-025r4.html
- GitHub: https://github.com/CesiumGS/3d-tiles
    - JSON Schema: https://github.com/CesiumGS/3d-tiles/tree/main/specification/schema
    - Reference cards: https://github.com/CesiumGS/3d-tiles/tree/main/reference-cards/1.1
- Sample Tilesets: https://github.com/CesiumGS/3d-tiles-samples

### **glTF 2.0**

- glTF 2.0 Specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html
- GitHub: https://github.com/KhronosGroup/glTF
    - JSON Schema: https://github.com/KhronosGroup/glTF/tree/main/specification/2.0/schema
- Sample Assets:
    - https://github.com/KhronosGroup/glTF-Sample-Assets
    - (deprecated) https://github.com/KhronosGroup/glTF-sample-models

#### Geospatial のための glTF 拡張

- https://github.com/CesiumGS/3d-tiles-samples/blob/main/README.md
- `EXT_mesh_features`
    - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features
- `EXT_structural_metadata`
    - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata

#### 標準的な圧縮形式・技法

Cesiumがサポートしているもの：

- Draco
- Meshopt 
- KTX2
- など

---

3D Tiles, 3D Tiles ~~Next~~ (1.1) の デモ色々

https://sandcastle.cesium.com/#c=dVPbjtowEP2VEepDkKiTEGBpy6JWULWVdlW0W/UpD2ucAUZ1bGSbW1f8e+0kLLRs8+Q5M2fO3CK0sg62hDs0cAsKdzBBS5uS/aywKG+Jyp5o5TgpNHmrA8+5AnBUovTIe1hwabETMK6o5I60ugStQIX3usAZiV9oLl1zbvGOH9Bcu5ZSzy9yH9sfclXXyXDvUBVRU2gN1kY2/UES7Tdl1yicNve0JxWYuYpj+FQUMFtpjyOXZB0JyKZQMXLlzKHuS1QjcQFF52fCd5zcaSrCUx1+0Xop8e9UjTS6KOhBM1NWNc/WhkpytEXLeFFETfIQeATBnVhBhMZo0z6XoCUyqZfR0+fgAKl5QWr5v/pP9bJAf/NcJTs+VQJN8zNNyre1Qi9YouHAa6vuZS1x/zLfuuY6jPmk4RSiqrACvapqNnxxLBNunH9xlbGF0eUUlwbRRoFSf2kvZdkgGQ66/ax/M+ynN52zs5exZNBLB0n3XTbM+oNhB87ObpKwJJjtiqENob/Eqwq+YjWfGflhPmgpG+20kXl7eryk8gcFrU5rZN1B4vik95HKtTYONkZGjMUOy7X0C7fxfOMP1DFhbb1egFF8SR0VtAUqbl/5X0BIbq33LDZSPtJvzFvjUezjr6jNkr9v0Uh+CGGrdHxXg4yxUezN15lOaznn5p/MfwA