Mapbox Newsletter WEEKLY TIPSの解説 -「Add a 3D model with threebox」
はじめに
この記事は、先日配信された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#getContext
がantialias: 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モデルを描画できることがわかりました。
Discussion