3D Tiles形式で納品を求められたので勉強してみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/e4636326-fb54-4fc3-aa0f-4fa33bee731e.png)

都市ARのお仕事をしていて、「3D Tiles形式で納品してください」と言われることがあったので、あらためて勉強してみました。
せっかくなので備忘録として残します。


# 3D Tilesとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/ab31d549-2ece-4181-9c3e-6670b31f0d05.png)

3D Tilesとは、3D地理空間データの配信と可視化のために設計されたオープン規格です。

都市全体や地形データなどのような大規模な3Dデータをストリーミング表示できます。

ズームイン・アウトに滑らかに対応するため、階層的にデータを管理しています。（LOD: Level of Detail）

形状データは glTF をベースとしたフォーマットを採用しつつ、地理空間特有のメタデータや点群データ（LiDARスキャンなど）も扱います。


# 主な構成ファイル

以下のようなファイルで構成されます。

- `tileset.json` : 3D Tilesの構造を定義
- `.b3dm`（Batched 3D Model）: 複数の3Dモデルをバッチ処理してまとめたファイル（個別の位置・属性を持つ）
- `.i3dm`（Instanced 3D Model）: 同じ3Dモデルを複数の異なる位置にインスタンス化するためのファイル
- `.pnts`（ポイントクラウド）: 点群データ

:::note warn
#### 追記
v1.1ではb3dm, i3dm, pntsが非推奨となり、直接glTFを参照するようになったみたいです。
https://github.com/CesiumGS/3d-tiles/releases/tag/1.1
本記事の内容はメモとしてこのまま残します。
:::

## b3dm : Batched 3D Model
b3dm は glTF を含みつつ、メタデータを追加して、複数の3Dモデルをバッチ処理するファイル形式 です。
メタデータとは 建物のID、分類情報、カスタム属性（高さ、用途など） のことです。
b3dmは主に3D都市モデル（建物、橋、道路等）を格納します。

## i3dm : Instanced 3D Model
i3dm は glTF を参照し、大量の同じ 3D モデルを軽量にインスタンス化して配置するためのファイル形式 です。
i3dm は、街路樹や街灯、電柱などのように、同じ3Dモデルを大量に配置する場合に使用されます。

## pnts : Point Cloud Tile
pntsは点群データです。
メッシュ化前のLiDARスキャンデータをとりあえず表示したいとき等に利用します。

## tileset.json
tileset.jsonは3D Tilesの中核のファイルです。
メッシュファイルや点群ファイルへの参照を持っています。

```json
{
  "asset": { "version": "1.0" },
  "geometricError": 50.0,
  "root": {
    "boundingVolume": { "box": [0, 0, 0, 500, 500, 500] },
    "geometricError": 25.0,
    "children": [
      {
        "boundingVolume": { "box": [0, 0, 0, 100, 100, 100] },
        "geometricError": 10.0,
        "content": { "uri": "building.b3dm" }
      },
      {
        "boundingVolume": { "box": [200, 0, 0, 50, 50, 50] },
        "geometricError": 10.0,
        "content": { "uri": "tree.i3dm" }
      },
      {
        "boundingVolume": { "box": [-200, 0, 0, 50, 50, 50] },
        "geometricError": 10.0,
        "content": { "uri": "terrain.glb" }
      },
      {
        "boundingVolume": { "box": [0, 0, -100, 200, 200, 200] },
        "geometricError": 10.0,
        "content": { "uri": "lidar.pnts" }
      }
    ]
  }
} 
```

# boundingVolumeとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/681ebd62-f8da-4255-b4b3-637b61d17bae.png)

`boundingVolume` は、3D Tiles において 各タイルが占める空間を定義し、最適な描画制御や LOD（詳細度）の切り替えを行うための基準 になります。
ある意味、3D Tilesの肝となる項目です。

## Bouding region

`boundingVolume.region` は、緯度、経度、高度の座標でタイルの範囲を定義する方法です。

:::note warn
緯度と経度は ラジアン で記載する必要があります。これは、地図座標を直交座標に変換する際、内部計算が通常ラジアンで行われるためです。なお、高度はメートル単位です。
:::

```json
"boundingVolume": {
  "region": [west, south, east, north, minimum height, maximum height]
}
```

## `boundingVolume` の種類

`region` 以外にも以下のような種類があります。

| 種類 | イメージ図 | 役割 | 用途の例 |
|---|---|---|---|
| `region` | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/681ebd62-f8da-4255-b4b3-637b61d17bae.png) | 緯度・経度・高さで定義する範囲 | 地形データ、航空写真、マップ |
| `box` | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/59bece1a-6038-4685-b77d-5df333515c25.png) | 軸に沿った直方体（AABB） | 建物、都市モデル |
| `sphere` | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/0d90c14a-022a-4a00-bfc3-a92e1fd54a52.png) | 球体のバウンディングボリューム | 点群データ、衛星データ、球形オブジェクト |


# Viewer

3D Tiles形式のデータを閲覧できるビューワーについて調べてみました。

## Cesium ion

手軽に 3D Tiles を視聴・管理できるクラウドビューワーが Cesium ion です。

https://ion.cesium.com/

My Assetsのページにアップロードすれば、それだけで視聴できます。

## CesiumJS

CesiumJS は、WebGL を使用した オープンソースの 3D Tiles ビューワーおよび GISレンダリングエンジン です。
3D Tiles の公式ビューワーとして利用でき、ブラウザ上で .b3dm や .i3dm などを直接表示できます。
Cesium ionのようなクラウドサービスにデータをアップロードするのを避けたい場合は、CesiumJSを使ってローカルにビューワー環境を構築することも可能です。

https://cesium.com/platform/cesiumjs/



# Converter

3D Tilesへ変換できるソフトについて調べてみました。

## Cesium ion

Cesium ionは、ビューワーとしてだけでなく、コンバーターとしても利用できます。

https://ion.cesium.com/

My Assetsページで glTF をアップロードすれば、自動で3D Tilesに変換してくれます。
**プログラム不要で変換できるため、最も手軽な方法です。**

## 3d-tiles-tools

Cesium 公式の `3d-tiles-tools` を使用すると、glTF を `.b3dm` や `.i3dm` に変換、3D Tiles のデータセットを作成できます。
ローカル環境で変換できるため、クラウドを使いたくない場合に適しています。

https://github.com/CesiumGS/3d-tiles-tools

Node.jsベースなので、Qiita読者には馴染みやすいと思います。


## objTo3d-tiles

`objTo3d-tiles` は、OBJ形式のメッシュを直接 `.b3dm` や `.i3dm` に変換してくれるツール です。

https://github.com/PrincessGod/objTo3d-tiles

こちらもNode.jsベースです。
サードパーティー製ですが、私が試しに使ってみた範囲では、特に問題はありませんでした。


# さいごに

本記事作成にあたり、以下のページを参考にさせていただきました。

- https://ion.cesium.com/
- https://cesium.com/platform/cesiumjs/
- https://github.com/CesiumGS/3d-tiles
- https://qiita.com/waigania13/items/ce42ec615938386adcf5

ありがとうございました。