🏢

Mapbox Newsletter WEEKLY TIPSの解説 -「Add a 3D model with threebox」

2024/04/11に公開

はじめに

この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「Add a 3D model with threebox」についての解説です。このサンプルではThreeboxの使い方を例示しています。また、Newsletterの購読はこちらからお申し込みいただけます。

以下が本サンプルのデモです。

Threeboxとは

これまでのWEEKLY TIPSではカスタムレイヤーを用いる方法を見てきました。Mapbox Newsletter WEEKLY TIPSの解説 -「カスタムスタイルレイヤーを追加」ではWebGLを直接コントロールして独自レイヤーを作成する方法、Mapbox Newsletter WEEKLY TIPSの解説 -「3Dモデルを追加」ではThree.jsを用いることで簡単に3Dモデルを表示する方法を解説しました。

Three.jsを使うことでかなりコード量を減らしつつ、複雑なことができることがわかりました。しかし、依然として行列計算等の処理を記述する必要がありました。このような手間をなくし、3Dモデルを描画することに専念できるライブラリがThreeboxです。ThreeboxはThree.jsをベースに、Mapbox GL JSのカスタムレイヤーとして3Dモデルの描画等が行えます。

コードを確認

まずExamplesのコードを見に行きましょう。このサンプルは日本語版がありません。

英語サイト

HTML

まずHTMLを見ていきましょう。

以下はThreeboxを読み込んでいます。

<script src="https://cdn.jsdelivr.net/gh/jscastro76/threebox@v.2.2.2/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://cdn.jsdelivr.net/gh/jscastro76/threebox@v.2.2.2/dist/threebox.css" rel="stylesheet">

以下は地図を表示するエレメントです。

<div id="map"></div>

Mapの作成

JavaScriptのコードを見ていきます。以下のコードはいつも通り、Mapオブジェクトを作成しています。containerで地図を表示するHTMLエレメントのidを指定します。antialias: trueを指定することで内部的にCanvas#getContextantialias: trueとして実行されます。

const map = new mapboxgl.Map({
    container: 'map',
    // Choose from Mapbox's core styles, or make your own style with Mapbox Studio
    style: 'mapbox://styles/mapbox/light-v11',
    center: { lng: -73.97627, lat: 40.75155 },
    zoom: 15.4,
    pitch: 64.9,
    bearing: 172.5,
    antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
});

Threeboxの作成

次にThreeboxオブジェクトを作成します。第1引数がMapオブジェクト、第2引数がContextです。defaultLights: trueでデフォルトのライトが使用されます。これを指定しないと真っ暗になります。

const tb = (window.tb = new Threebox(
    map,
    map.getCanvas().getContext('webgl'),
    {
        defaultLights: true
    }
));

レイヤーの作成

custom-threebox-modelはカスタムレイヤーの定義を含むレイヤーです。Symbolレイヤー等と同じ様にMap#addLayerメソッドで作成します。

map.on('style.load', () => {
  map.addLayer({
    id: 'custom-threebox-model',
    type: 'custom',
    renderingMode: '3d',
    onAdd: function () {
      //後述
    },
    render: function () {
      //後述
    }
  });
});

onAdd

onAddはカスタムレイヤーの初期化処理を書きます。
オプションは以下のとおりです。

  • obj: アセットのURL。obj, .glb, .gltf, .fbx, .daeファイル。
  • type: アセットのタイプ。"mtl", "gltf", "fbx", "dae"のいずれか。
  • scale: スケール設定
  • units: 3Dモデルの辺の長さの単位。"scene"か"meters"。
  • rotation: 3Dモデルの回転

rotationでx軸周りに90度回転させているのは、Mapbox Newsletter WEEKLY TIPSの解説 -「3Dモデルを追加」と同じ理由で、そのままだと横倒しになるからです。

// Creative Commons License attribution:  Metlife Building model by https://sketchfab.com/NanoRay
// https://sketchfab.com/3d-models/metlife-building-32d3a4a1810a4d64abb9547bb661f7f3
const scale = 3.2;
const options = {
  obj: 'https://docs.mapbox.com/mapbox-gl-js/assets/metlife-building.gltf',
  type: 'gltf',
  scale: { x: scale, y: scale, z: 2.7 },
  units: 'meters',
  rotation: { x: 90, y: -90, z: 0 }
};

3Dモデルを Threebox#loadObjで読み込んでいます。第1引数に先程のオプション、第2引数にモデルロード後に呼ばれるコールバックを指定します。コールバックの第1引数はモデルです。

Object#setCoordsでモデルを配置する座標、Object#setRotationで回転を指定します。Objectで回転を指定すると、setCoorsで指定した座標を中心に回転します。

Threebox#addでモデルを追加します。

tb.loadObj(options, (model) => {
  model.setCoords([-73.976799, 40.754145]);
  model.setRotation({ x: 0, y: 0, z: 241 });
  tb.add(model);
});

render

onAddはカスタムレイヤーを描画する際に呼ばれます。ここではThreebox#updateを呼びます。

render: function () {
  tb.update();
}

まとめ

Threeboxを使うことで、更に簡単にカスタムレイヤーで3Dモデルを描画できることがわかりました。

GitHubで編集を提案
マップボックス・ジャパン合同会社

Discussion