近年、MetaがQuest 3を発売したり、AppleがVision Proを発表するなど、VR(仮想現実)やAR(拡張現実)への注目度が高まっています。そんな中、今回は、Webブラウザ上で3Dモデルを表示できるライブラリ「model-viewer」を紹介します。
model-viewerとは
model-viewerは、Googleが開発したWebコンポーネントです。まるでWebページに動画を埋め込むように、3Dモデルを簡単に表示できます。しかも、マウスや指でグリグリ動かしたり、拡大縮小したりと、インタラクティブな操作も可能です。対応している3Dモデルの形式はglTFとGLBで、これらのファイルを準備すればOKです。
model-viewerを使うには、以下のようなHTMLタグを記述します。
<!-- ライブラリ読み込み -->
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.3.0/model-viewer.min.js"></script>
<!-- Web Componentsとしてmodel-viewerタグが使えます -->
<model-viewer
alt="Neil Armstrong"s Spacesuit from the Smithsonian Digitization Programs Office and National Air and Space Museum"
src="shared-assets/models/NeilArmstrong.glb"
ar
environment-image="shared-assets/environments/moon_1k.hdr"
poster="shared-assets/models/NeilArmstrong.webp"
shadow-intensity="1"
camera-controls
touch-action="pan-y"
>
</model-viewer>
上記のコードでは、以下のような設定がされています。
- src属性で、表示する3Dモデルのファイルパスを指定
- ar属性で、ARモードを有効化
- environment-image属性で、3Dモデルの背景画像を指定
- poster属性で、3Dモデルが読み込まれるまでの代替画像を指定
- shadow-intensity属性で、影の濃さを調整
- camera-controls属性で、カメラのコントロールを有効化
- touch-action属性で、タッチ操作を制限
サポートするブラウザ
公式サイトによると、以下のブラウザで動作します。
- Google Chrome(Windows、macOS、Android)
- Microsoft Edge
- Mozilla Firefox(Windows、macOS)
- Safari(macOSのみ。iOSは非対応)
公式サイトによれば、基本的にChromium系のブラウザであれば動作します。Safariはサポート対象外となっていますが、macOS版であれば動作します(iOSのSafariでは動作しません)。Firefoxもデスクトップ版であれば動作可能です。
ただし、WebXRを利用する場合は、Chromium系でのみ動作するようです。
対応している3Dモデルのフォーマット
model-viewerが対応している3Dモデルのフォーマットは、以下の2種類です。
- glTF(gl Transmission Format)
- GLB(Binary glTF)
glTFは、3Dモデルのデータを JSON 形式で記述するフォーマットで、テクスチャなどの関連ファイルは別ファイルとして管理されます。
一方、GLBは、glTFをベースにしつつ、関連ファイルをまとめて1つのバイナリファイルにしたフォーマットです。
ARモードについて
model-viewerの大きな特徴の一つが、ARモードの提供です。ARモードを使うことで、実世界に3Dモデルを重ねて表示することができます。
ARモードを使うには、対応するデバイスとブラウザが必要です。現在、ARモードに対応しているのは、Android端末とChromiumベースのブラウザ(Google ChromeやMicrosoft Edgeなど)のみとなっています。
ARモードを有効にするには、
他の3Dモデルビューワーとの違い
model-viewer以外にも、Webブラウザ上で3Dモデルを表示できるライブラリはいくつかあります。ここでは、オープンソースのライブラリを中心に紹介します。
glTF Viewer
glTF ViewerはThree.jsを使ったglTFビューワーです。名前の通り、glTFのみに対応しています。また、バージョン2以降のみに対応しています。
A WebGL multiple file 3D viewer
A WebGL multiple file 3D viewerは、45種類もの3Dモデルフォーマットの表示に対応したビューワーです。Unity 3Dを利用して開発されているのが特徴です。また、React向けに開発されているのも特徴の一つです。
Rufus31415/react-webgl-3d-viewer-demo
Online 3D Viewer
Online 3D Viewerは、20種類近くの3Dモデルフォーマットに対応したビューワーです。3Dモデルのインポートとエクスポートの両方に対応しているのが特徴です。3D表示部分はThree.jsを利用しています。
Web 3D Viewer
Web 3D Viewerは、3Dモデルの表示だけでなく、ツリーリストの表示や簡易的な編集機能も備えたソフトウェアです。ワイヤーフレーム表示やオブジェクトの向きをクリックで変更できるのが特徴です。編集結果は別のファイルフォーマットでエクスポートすることができます。
React Three Fiber
React Three Fiberは、React向けの3D表示コンポーネントです。3D表示にはThree.jsを利用しています。
A-Frame
A-Frameは、主にWebVRに特化したライブラリです。glTFとGLBの両方に対応しています。AR.jsと組み合わせることで、AR表示にも利用できます。
model-viewerの使い方
ここからは
デモ
「model-viewer」を使ったデモを試してみるには、Model Editorを利用するのが便利です。ここでは、自作の3Dモデルなどを読み込ませて、表示を確認することができます。
WebXRでの表示
WebXRでの表示を行う際の書き方です。
この例では、VRデバイスに対応し、手を表示したりできます。また、JavaScriptでのタップイベントなどとの組み合わせも可能です。
<model-viewer
src="../../assets/ShopifyModels/Chair.glb"
poster="../../assets/ShopifyModels/Chair.webp"
shadow-intensity="1"
ar
camera-controls
touch-action="pan-y"
alt="A 3D model carousel"
>
<button slot="ar-button" id="ar-button">
View in your space
</button>
<div id="ar-prompt">
<img src="../../assets/hand.png">
</div>
<button id="ar-failure">
AR is not tracking!
</button>
<div class="slider">
<div class="slides">
<button class="slide selected" onclick="switchSrc(this, "Chair")" style="background-image: url("../../assets/ShopifyModels/Chair.webp");">
</button><button class="slide" onclick="switchSrc(this, "Mixer")" style="background-image: url("../../assets/ShopifyModels/Mixer.webp");">
</button><button class="slide" onclick="switchSrc(this, "GeoPlanter")" style="background-image: url("../../assets/ShopifyModels/GeoPlanter.webp");">
</button><button class="slide" onclick="switchSrc(this, "ToyTrain")" style="background-image: url("../../assets/ShopifyModels/ToyTrain.webp");">
</button><button class="slide" onclick="switchSrc(this, "Canoe")" style="background-image: url("../../assets/ShopifyModels/Canoe.webp");">
</button></div>
</div>
</model-viewer>
ARでの表示
ARで表示を行う際には、ページがHTTPSで提供されている必要があります。また、iframeを利用するのですが、そのページがxr-spatial-trackingを有効にしている必要があります。
iOSの場合は、ios-src属性で指定したUSDZファイルを利用します。
<model-viewer
src="../../shared-assets/models/Astronaut.glb"
ar
ar-scale="fixed"
camera-controls
touch-action="pan-y"
alt="A 3D model of an astronaut"
skybox-image="../../shared-assets/environments/aircraft_workshop_01_1k.hdr"
ios-src="../../shared-assets/models/Astronaut.usdz"
xr-environment
>
</model-viewer>
カスタムボタンの追加
モデル上にJavaScriptと組み合わせるボタンを配置することができます。これは、AR対応デバイスでの利用を想定しています。
<model-viewer
ar
camera-controls
touch-action="pan-y"
src="../../shared-assets/models/Astronaut.glb"
alt="A 3D model of an astronaut">
<button slot="ar-button" style="background-color: white; border-radius: 4px; border: none; position: absolute; top: 16px; right: 16px; ">
Activate AR
</button>
</model-viewer>
透明な背景の設定
通常は白などの背景が表示されますが、style属性でbackground-color: unset;を指定することで、背景を透明にできます。これにより、3Dモデルの背後にあるHTMLコンテンツが表示されるようになります。
<div
class="demo"
style="background: linear-gradient(#ffffff, #ada996);
overflow-x: hidden;"
>
<span
style="position: absolute; text-align: center; font-size: 100px; line-height: 100px; left: 50%; transform: translateX(-50%);">
Background<br>is visible<br>through<br>transparent<br>objects.
</span>
<model-viewer
camera-controls
touch-action="pan-y"
src="../../shared-assets/models/glTF-Sample-Assets/Models/ToyCar/glTF-Binary/ToyCar.glb"
ar
alt="A 3D transparency test"
style="background-color: unset;"
>
</model-viewer>
</div>
カメラコントロール
camera-controls
要素を付けると、VRデバイスやマウスによる視点変更が可能になります。
<model-viewer
camera-controls
touch-action="pan-y"
src="../../shared-assets/models/Astronaut.glb"
alt="A 3D model of an astronaut"
>
</model-viewer>
カメラの初期アングルの設定
カメラの初期アングルは camera-orbit
で指定します。単位は deg
(度)か rad
(ラジアン)です。また、 deg
は省略可能です。
<model-viewer
camera-controls
touch-action="pan-y"
camera-orbit="45deg 55deg 4m"
src="../../shared-assets/models/Astronaut.glb"
alt="A 3D model of an astronaut"
>
</model-viewer>
CSS風にcalcも利用できます。
<model-viewer
camera-controls
touch-action="pan-y"
camera-orbit="calc(-1.5rad + env(window-scroll-y) * 4rad) calc(0deg + env(window-scroll-y) * 180deg) calc(5m - env(window-scroll-y) * 10m)"
src="../../shared-assets/models/Astronaut.glb"
alt="A 3D model of an astronaut"
>
</model-viewer>
ズーム機能の無効化
disable-zoom
を指定するとズーム機能が無効になります。
<model-viewer
camera-controls
touch-action="pan-y"
disable-zoom
src="../../shared-assets/models/Astronaut.glb"
alt="A 3D model of an astronaut"
>
</model-viewer>
JavaScriptによるカメラ操作
cameraOrbit
プロパティを使って、JavaScriptからカメラを操作することができます。
<model-viewer
id="orbit-demo"
interpolation-decay="200"
src="../../shared-assets/models/Astronaut.glb"
alt="A 3D model of an astronaut"
>
</model-viewer>
<script>
(() => {
const modelViewer = document.querySelector("#orbit-demo");
const orbitCycle = [
"45deg 55deg 4m",
"-60deg 110deg 2m",
modelViewer.cameraOrbit
];
setInterval(() => {
const currentOrbitIndex = orbitCycle.indexOf(modelViewer.cameraOrbit);
modelViewer.cameraOrbit =
orbitCycle[(currentOrbitIndex + 1) % orbitCycle.length];
}, 3000);
})();
</script>
アニメーションの再生
3Dモデルがアニメーションをサポートしている場合、 autoplay
を指定すると自動的に再生されます。
<model-viewer
camera-controls
touch-action="pan-y"
autoplay
ar
ar-modes="webxr scene-viewer"
scale="0.2 0.2 0.2"
shadow-intensity="1"
src="../../shared-assets/models/RobotExpressive.glb"
alt="An animated 3D model of a robot"
>
</model-viewer>
色の変更
同じモデルを使いつつ、色を変更する例です。
<model-viewer
id="shoe"
camera-controls
touch-action="pan-y"
src="../../shared-assets/models/glTF-Sample-Assets/Models/MaterialsVariantsShoe/glTF-Binary/MaterialsVariantsShoe.glb"
ar
alt="A 3D model of a Shoe"
>
<div class="controls">
<div>Variant: <select id="variant"></select></div>
</div>
</model-viewer>
<script>
const modelViewerVariants = document.querySelector("model-viewer#shoe");
const select = document.querySelector("#variant");
modelViewerVariants.addEventListener("load", () => {
const names = modelViewerVariants.availableVariants;
for (const name of names) {
const option = document.createElement("option");
option.value = name;
option.textContent = name;
select.appendChild(option);
}
// Adds a default option.
const option = document.createElement("option");
option.value = "default";
option.textContent = "Default";
select.appendChild(option);
});
select.addEventListener("input", (event) => {
modelViewerVariants.variantName = event.target.value === "default" ? null : event.target.value;
});
</script>
まとめ
<model-viewer>
はWeb Componentsとして作られているので、HTMLタグとして利用できます。また、JavaScriptと組み合わせることで、様々な表現が可能です。フレームワークに依存していないので、ReactやVue.jsと組み合わせることも可能です。
VR表示やもちろん、ARでも利用できるので、さまざまなプロジェクトで利用できるでしょう。ぜひ試してみてください。