メインコンテンツへ移動
AIチュートリアル

ブラウザでプロシージャルな3D東京を構築・探索する

このチュートリアルでは、PLATEAU、OpenStreetMap、GSIのデータから構築したブラウザベースの3Dビジュアライゼーション「Procedural Tokyo」を紹介します。ローカルでの実行方法、都市データの取得とコンパイル、操作方法、タイルパイプラインの仕組み、デプロイの準備について学びます。

ブラウザでプロシージャルな3D東京を構築・探索する

プロシージャル東京とは?

プロシージャル東京は、ブラウザ上で動作する東京のリアルタイム3Dモデルです。実在する建物、道路、地形、鉄道、地理的特徴に加え、ファサード、窓、ストリートファニチャー、交通、照明、水面、天候、鳥などのプロシージャルなディテールを組み合わせています。

このプロジェクトでは、Project PLATEAU、OpenStreetMap、国土地理院の公開データを使用しています。オフラインコンパイラが元データをコンパクトなバイナリタイルに変換し、ブラウザはカメラ周辺のタイルをストリーミングしてメッシュ化します。

ホスト版はjeantimex.github.io/tokyoで試せます。デスクトップブラウザ向けに設計されており、モバイルブラウザでの利用は推奨されません。

利用可能なシーンを探索する

各シーンは、およそ3.4×2.8キロメートルの範囲をカバーします。収録エリアは次のとおりです。

  • 東京: 東京駅、丸の内、皇居の堀。
  • 芝: 東京タワー、増上寺、芝公園。
  • 渋谷: スクランブル交差点、渋谷駅、高速道路。
  • 新宿: 新宿駅、高層ビル街、歌舞伎町、新宿御苑。
  • 千代田: 秋葉原、神田、お茶の水。
  • 中央: 築地、勝どき、月島、晴海、ウォーターフロント、運河。
  • 富士宮: 富士山の近くにある町で、60キロメートルに及ぶ地形の背景を含みます。

PLATEAUは日本の数百都市をカバーしていますが、利用できる詳細度は異なります。都市中心部には精細な屋根形状や航空写真テクスチャが含まれる場合がある一方、小規模な町ではより簡略化された建物ブロックが使われることがあります。

主な機能

リアルな建物と地面

建物には、実際の建築形状、高さ、階数、用途の情報を使用しています。PLATEAUが詳細な建物外形や屋根の写真を提供している場合は、それらのアセットを直接使用します。生成されたファサード、窓、バルコニー、パラペット、屋上設備、店舗看板の帯が、近距離でのディテールを加えます。

地面には、5メートル解像度の標高モデル、航空写真、道路面、縁石、公園、森林、水面を使用しています。道路標示には、車線、横断歩道、停止線、矢印、日本語の止まれ標示、ペイントされた速度制限が含まれます。

動き続ける都市の営み

交通は実際の道路グラフに沿って走行し、左側通行、一方通行、信号を守り、交差点で列を作り、高速道路やランプを利用します。列車は実在する鉄道路線に沿って走ります。シーンには、電柱、電線、街灯、交通信号、自動販売機、鳥居、駅のプラットフォーム、歩道橋、木々、駐車車両も含まれます。

時間、天候、反射

タイムスライダーまたは東京のライブ時計が、太陽、月、空、影、露出を制御します。夕方になると、暗闇が薄明を経て訪れる前に都市の明かりが点灯します。レンダラーは、ボリューメトリック雲、大気遠近、波打つ水面、窓の反射、光る看板、ヘッドライト、東京タワーのライトアップにも対応しています。

鳥の群れは木に止まったり、再び飛び去ったりします。富士宮シーンでは、オプションの粗い地形背景によって町の背後に富士山を配置でき、航空画像と雪化粧も含まれます。

プロジェクトをインストールして実行する

リポジトリをクローンし、npmで依存関係をインストールします。

npm install

プロジェクトで使用するCC0テクスチャをダウンロードします。この手順は一度だけ必要で、public/textures/に約14 MBを保存します。

node tools/assets/fetch_textures.mjs

次に、エリアの元データを取得します。以下の例では東京の元データをダウンロードします。

npm run fetch -- --area=tokyo

ダウンロードしたレコードをブラウザ用のタイルにコンパイルします。

npm run compile -- --area=tokyo

最後に、開発サーバーを起動します。

npm run dev

デスクトップブラウザでhttp://localhost:5280を開きます。コンパイル済みの都市ファイルはリポジトリにコミットされていないため、各エリアを元データから再構築する必要があります。

データパイプラインを理解する

パイプラインには2つの主な段階があります。fetchコマンドは元ファイルをdata/raw/<area>/に、航空画像をpublic/ortho/<area>/にダウンロードします。compileコマンドは、それらのレコードをpublic/tiles/<area>/にストリーミングされるタイルとして変換します。

選択したエリアのパイプライン全体を次のコマンドで実行します。

npm run fetch -- --area=shibuya
npm run compile -- --area=shibuya

PLATEAUの建物写真が含まれるため、元データのダウンロード容量は大きくなる場合があります。READMEには、東京が約3.6 GB、芝が3.0 GB、渋谷が1.3 GB、富士宮が0.2 GBと記載されています。コンパイルにかかる時間はエリアによって異なり、数秒から数分です。

コンパイル済みデータを確認・テストする

次のコマンドでエリアの俯瞰プレビューを作成します。

npm run preview -- --area=tokyo

プロジェクトのテストを実行して、タイルの往復変換と道路標示のクリアランスを確認します。

npm test

これらのチェックは、特に地形との位置合わせに役立ちます。道路面、車線標示、記号は地形メッシュの三角形に沿って分割されるため、傾斜した地面の上に保たれ、タイル境界を通り抜けて沈み込むことがありません。

ブラウザの操作方法

  • ドラッグして視点を移動します。
  • 右ドラッグして回転します。
  • マウスホイールでズームします。
  • WASDで移動します。
  • 移動中にShiftを押し続けると、より速く移動します。
  • Nを押すと昼夜を切り替えます。
  • 建物をクリックすると詳細を確認できます。

右上の設定パネルでは、エリアの切り替えや、時刻、交通量、雲、照明、レンダリング品質の調整ができます。設定はブラウザーに保存されます。

URLパラメータでシーンを開く

URLパラメータは、特定の表示状態を共有したり、レンダリング設定をテストしたりする場合に便利です。例:

https://jeantimex.github.io/tokyo/?area=shibuya&time=18.5&traffic=0

使用できるパラメータ:

  • area=tokyo|shiba|shibuya|shinjuku|chiyoda|chuo|fujinomiyaでエリアを選択します。
  • time=18.5で東京の現地時間を設定します。
  • night=1で夜間モードに切り替えます。
  • cam=x,z,distance,azimuth,elevationでカメラを設定します。
  • radius=900でアクティブな表示半径を設定します。
  • traffic=0で交通を無効にします。
  • cars=600で車の台数を変更します。
  • birds=150で鳥の数を変更します。
  • clouds=0.25で雲量を設定します。
  • ortho=0で正投影モードを無効にします。

URLパラメータで開いたページでは、保存済みのブラウザー設定は上書きされません。

コンパイル済みタイルの仕組み

クライアントは、エリアの中心を原点とするローカルなメートル座標系を使用します。x軸は東、y軸は上、z軸は南を指します。タイルは256メートル四方で、サイトが現在の表示範囲付近のタイルをストリーミングする間に、Web Workerでメッシュ化されます。

コンパイル済みエリアには次のファイルが含まれます:

  • manifest.jsonには、原点、境界、タイル一覧、地形グリッド、橋のデッキ、帰属表示が保存されます。
  • t_<x>_<z>.binには、建物、地表、道路標示、プロップ、電線、標識の1タイル分のデータが保存されます。
  • terrain.binには、5メートル間隔のFloat32地形標高グリッドが保存されます。
  • roads.jsonには、道路グラフ、ポイントのレベル、信号のある交差点が保存されます。
  • rails.jsonとstructures.jsonには、鉄道路線、プラットフォーム、上屋、歩道橋が保存されます。
  • backdrop.binには、エリア周辺のオプションの粗い地形が保存されます。

エリアの追加または設定

別のPLATEAU対応都市を追加するには、tools/pipeline/config.mjsにエントリを定義します。エリアには中心点と処理対象のPLATEAUグリッドマスを指定します。オプションで、背景地形のサイズと起動時のカメラ表示も定義できます。

すべてのパイプラインスクリプトは同じエリアオプションを受け付けます:

npm run fetch -- --area=my-area
npm run compile -- --area=my-area
npm run preview -- --area=my-area

PLATEAUファイルはPLATEAUデータカタログAPI経由で取得されます。パイプラインはgml:idによってレコードの重複を排除します。これは、東京のデータセットの1つのマスが複数の区にまたがって現れる場合に重要です。都市によってカバー範囲が異なるため、詳細なシェル、写真テクスチャ、道路付属物を利用できない場合、クライアントは生成されたディテールにフォールバックします。

高度な技術詳細

地形、道路、橋

PLATEAU、OpenStreetMap、GSIのデータは、1つのローカルなメートルグリッドに投影されます。共通の5メートル標高グリッドにより、隣接するタイルの境界で高さが一致します。建物の基礎はコンパイル中に地形との位置関係を確認され、その差分が記録されます。

詳細情報が不足している道路の外形は、OpenStreetMapの中心線を使用して車道と歩道に分割されます。橋と高架道路には別々のプロファイルが適用されます。道路橋は両岸の高さに合わせ、高速道路はレイヤーに応じて持ち上げ、ランプは正しく接続されるよう勾配を付けます。

照明と反射

すべてのランプごとに動的ライトを作成する代わりに、街灯とヘッドライトをライトマップに描画します。重なり合う光源では明るい方の値が維持され、ランプの高さデータによって、高架道路の下にあるライトがそのデッキを照らすのを防ぎます。

水面の反射では、水面下に都市をもう一度描画します。波紋によって結果が歪み、雲の反射には気象マップが使用されます。窓ガラスはカラーバッファのアルファチャンネルにマークされ、スクリーンスペース反射パスで処理されます。

レンダリングとパフォーマンス

レンダラーは、pmndrsのpostprocessingコンポーザーとthree.jsを使用します。エフェクトには、n8aoアンビエントオクルージョン、反射、大気、雲、ブルーム、トーンマッピングが含まれます。鳥は頂点シェーダーで配置されるため、大規模な群れでもCPU時間をほとんど消費しません。

パフォーマンスを向上させるには、アクティブ半径を適度に保ち、車と鳥の数を減らし、雲を無効にするか、設定パネルでレンダリング品質を下げてください。デフォルトのストリーミングモードでは近隣のタイルが読み込まれます。whole cityオプションを選ぶと利用可能なすべてのタイルが読み込まれ、必要なメモリが大幅に増える場合があります。

コンパイル済みサイトのデプロイ

公開するエリアをコンパイルした後、次を実行します:

npm run deploy

これによりディストリビューションがビルドされ、dist/がリポジトリのoriginにあるgh-pagesブランチへ、単一コミットとして強制プッシュされます。デプロイには、そのマシンでコンパイルされた都市が含まれます。READMEでは、含まれる7つのエリアに約650 MBが必要と見積もられています。

データの帰属とライセンス

コードはMITライセンスの下で公開されていますが、都市データには元の提供元の利用条件が適用されます。Project PLATEAUは、3D都市モデル、屋根の写真、橋、道路設備を提供しています。GSIは標高データと航空写真を提供しています。OpenStreetMapの貢献者は、ODbLの下で道路、鉄道、地名を提供しています。Poly HavenのテクスチャはCC0で、樹木にはMITライセンスのez-treeを使用し、大気と雲のコンポーネントはMITライセンスのthree-geospatialから提供されています。

まとめ

Procedural Tokyoは、公開された地理空間データセットを、豊かにアニメーションするブラウザー体験へと変えられることを示しています。利用するには、依存関係をインストールし、テクスチャとエリアデータをダウンロードして、データをタイルにコンパイルし、開発サーバーを起動します。その後は、URLパラメーター、パイプライン設定、テスト、デプロイコマンドを使って、プロジェクトを実際に試したり拡張したりできます。