じゅころぐAR

ARのブログ

<model-viewer>をWebサイトに合わせてカスタマイズする

Webサイトで3Dモデルを表示してARビューアーの起動ができる<model-viewer>がリリースされてから一年余りが経ちました。

前に書いた記事:
<model-viewer>を使って3DモデルをScene ViewerでAR表示する - じゅころぐAR

3DモデルをARで表示する機能はARビューアー(Scene ViewerやAR Quick Look)に依存するため大きく変わってはいませんが、3Dモデルビューアーとしての<model-viewer>にはアップデートが入っており、Webサイトに組み込みやすくなっています。

本記事では<model-viewer>の使い方をおさらいしつつ、利用頻度が高そうな機能を紹介します。

<model-viewer>とは

Webサイトに3DモデルのビューアーをHTML要素として追加し、ARに対応したデバイスであればARビューアーを起動することができます。

対応しているARビューアーは以下になります。

Android iOS WebXR
Scene Viewer AR Quick Look WebXR Device API

2020年7月現在、WebXRはGoogle Chromeしか対応しておらず、ユーザー自身がフラグを有効にするかCanaryバージョンを利用しないと動作しないため、実質的にはScene ViewerとAR Quick LookでAR表示することになります。

Scene ViewerはARCore、AR Quick LookはARKitに対応したデバイスで利用することができ、その他のデバイスではWebサイト上での3D表示のみとなります。

3Dモデルの準備

<model-viewer>で表示できる3Dモデルはglb/glTFです。また、iOSのAR Quick Look向けにUSDZ形式のファイルも必要となります。

作成手順としては、

汎用的な3Dフォーマット(FBX、OBJ、VRMなど) → glb/glTF → USDZ

で変換を行うのが簡単かと思います。

元のモデルのフォーマット(FBX、OBJなど)や3Dモデルの作成ツール(Unity、Blenderなど)、アニメーションの有無などによって必要な手順が異なると思いますが、本記事では詳細を割愛して変換に使えるツールの紹介のみとします。

利用規約・ライセンスの確認

以前の記事にも書きましたが、WebXRで3Dモデルを扱う上で利用規約・ライセンスには細心の注意が必要です。

他者が配布したモデルを二次利用する場合、3Dモデルのフォーマット変換やWeb上へのアップロード(第三者がダウンロード可能な形で公開)を行うことになりますので、改変および再配布に該当するとみなされます。
そのため、利用規約で改変・再配布が禁止されているモデルは利用できないと考えた方がよいです。

また、二次利用の条件として著作表示が求められている場合、アクセスしたユーザーの目に見える形でサイト上に表記を行う必要があります。

本記事ではスクリーンショットのみの利用ですが、改変・再配布を含む二次利用が許可されており、著作表示も不要な「暮井 慧(プロ生ちゃん)」のモデルを利用させて頂いています。

glb/glTFの作成

Unityからエクスポートする場合、UniVRMにパッケージされているUniGLTFでglb形式のファイルが出力できます。
代替のツールとしては、Khronos Groupのリポジトリで公開されているUnityGLTFも推奨されているのですが、筆者の環境(Mac)では上手く動きませんでした。
旧バージョンのglTF-Tools-for-Unity だと上手く動作する場合があります。

Blenderからglb/glTFでエクスポートするアドオンとしては、glTF-Blender-IOが公開されています。

エクスポートしたモデルのチェックについては、Mac/Windows問わず使えるglTF Viewerが便利です。
three.jsで作成されているWeb製のアプリなのでWebXRでの見た目に近く、FPSを測定したり、Lightingを調整した場合の見た目も確認できます。

f:id:jyuko49:20200723225905p:plain
glTF Viewer

USDZの作成

USDZへの変換に関しては、MacにてAppleの提供するReality Converterを使うのが確実かと思います。
glbファイルをインポートした時点でUSDZに変換されるため、Reality Converter上でUSDZでの表示をチェックできます。

f:id:jyuko49:20200723231659p:plain
Reality Converter

Macを使わずにWindowsでUSDZを作成したい場合、USD Unity SDKをインストールすることで、UnityからUSDZファイルを出力できます。
ただし、メッシュにマテリアルを複数割り当てると結果がおかしくなるなどの制約があり、glb経由でReality Converterを使う変換よりも扱いが難しいです。

f:id:jyuko49:20200723231157p:plain
Unity USD SDK のエクスポート失敗例

<model-viewer>のカスタマイズ

ここからが本記事の主題となりますが、書いている内容のほとんどはhttps://modelviewer.devに仕様が記載されています。
ドキュメントは英語のみですが、こちらを定期的にチェックすることで最新の情報が得られます。

基本のHTML

最初に以下のHTMLを記述します。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>model-viewer demo</title>    
    <script type="module" src="https://unpkg.com/@google/model-viewer@1.0.0/dist/model-viewer.min.js"></script>
  </head>
  <body>
    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
    >
    </model-viewer>
  </body>
</html>

<model-viewer>のAttributeとして、ブラウザおよびScene Viewer(Android)表示用のglbモデルをsrcに、AR Quick Look(iOS)表示用のUSDZモデルをios-srcにセットします。
arはAR表示(対応デバイスのみ)を有効にするため、camera-controlsはブラウザ上で3Dモデルの回転や拡大・縮小を有効にするためのAttributeです。

canvasが小さいですが、ひとまず3DモデルとARボタンが表示され、モデルを回転させることができます。

f:id:jyuko49:20200724005428j:plain
初期状態

canvas要素のカスタマイズ

CSSを使ってcanvas要素の調整をしていきます。

canvasのサイズ

CSSが有効なため、widthheightで設定できます。

  <style>
    model-viewer {
      width: 100%;
      height: 640px;
    }
  </style>

f:id:jyuko49:20200724005414j:plain
canvasサイズの変更

canvasの背景色

こちらもCSSのbackground-colorで簡単に変えられます。

  <style>
    model-viewer {
      width: 100%;
      height: 640px;
      background-color: greenyellow;
    }
  </style>

f:id:jyuko49:20200724005354j:plain
背景色の設定

background-imageで背景画像を設定するのも簡単です。

f:id:jyuko49:20200724005400j:plain
背景画像の利用

目がチカチカするので、元に戻します。

3Dビューのカスタマイズ

Webサイト上での3Dモデルの表示(AR起動する前)を調整します。

影を付ける

デフォルトの3Dビューでは影の表示が有効になっていません。

shadow-intensityで影の強さを設定することで影が表示され、shadow-softnessで影の柔らかさの調節ができます。

    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
      shadow-intensity = 1
      shadow-softness = 0
    >
    </model-viewer>

f:id:jyuko49:20200724005644j:plain
影の表示

上記はあくまで3Dビュー用の設定で、ARモードでの影の表示はARビューアーの仕様に依存します。現在の仕様ではshadow-intensityを設定していなくてもAR起動した後は影が表示されます。

カメラの視点を変える

デフォルトではモデルが表面を向いて全体が見えるくらいの大きさで表示されます。

そのままで問題ないケースが多いとは思うのですが、モデルの見栄えとして、モデルの中心ではない部分をアップで表示したり、正面以外の角度から表示させたいケースもあるかとは思います。
そういった場合、camera-targetcamera-orbitで調整ができます。

camera-targetでカメラの中心をずらしてみます。

    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
      shadow-intensity = 1
      shadow-softness = 0
      camera-target = "1.0m 1.0m 0m"
    >
    </model-viewer>

camera-targetを指定したことでカメラの中心点が変わりますが、モデルの回転がカメラ中心を軸に行われているため、回転の軸も変わります。

今度はcamera-orbitも使ってカメラの角度と距離も変えてみます。

    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
      shadow-intensity = 1
      shadow-softness = 0
      camera-target = "0m 1.2m 0m"
      camera-orbit = "45deg 90deg 50%"
    >
    </model-viewer>

左右の向きを45度傾け、上下は90度(90度が正面)、モデルの50%が見える距離にしているので、上半身のアップを斜めから見ているような表示になります。

f:id:jyuko49:20200724005449j:plain
カメラ視点を変更した初期表示

camera-orbitは<model-viewer>のAttributeなので、JavaScriptで書き換えることもできます。

  <body>
    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
      shadow-intensity = 1
      shadow-softness = 0
      camera-target = "0m 1.2m 0m"
      camera-orbit = "45deg 90deg 50%"
    >
    </model-viewer>
    <button id="above-button">View from above</button>
  </body>
  <script>
    document.querySelector('#above-button').addEventListener('click', (event) => {
      const modelViewer = document.querySelector("model-viewer");
      modelViewer.setAttribute('camera-orbit', "0deg 0deg 50%");
    });
  </script>

こんな感じでボタンをクリックしたらsetAttributeするスクリプトを書いてあげれば、Webサイト上での操作で自由に視点を変えることができます。

AR起動方法のカスタマイズ

ARを起動する方法もいくつかパターンがあり、WebサイトのUIデザインに合わせて変更することができます。

ARボタンのデザインを変更する

デフォルトで表示されているARボタンをオーバーライドすることができます。

<model-viewer>タグで囲われている中に<button>要素を記述して、Attributeでslot="ar-button"を付けます。

    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
    >
    <button id="custom-ar-button" slot="ar-button">Start AR</button>
    </model-viewer>

ボタンのデザインはCSSで自由に設定できます。

  <style>
    #custom-ar-button {
      font-size: 24px;
      position: absolute;
      bottom: 16px;
      left: 16px;
    }
  </style>

AR対応のデバイスで表示すると、デフォルトのARボタンが非表示になり、代わりに表示される<button>要素を押すとARビューアーが起動します。

f:id:jyuko49:20200724130319j:plain
ARボタンの変更

別のボタンから起動する

<model-viewer>にはactivateAR()というMethodが用意されています。このMethodを実行することで<model-viewer>上のARボタンを押さなくてもARビューアーを起動することができます。

先ほどのオーバーライドとは異なり、<model-viewer>タグの外の好きな位置に<button>要素を配置します。

    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
    >
    </model-viewer>
    <button id="another-ar-button">Start AR</button>

配置したボタンのクリックイベントで<model-viewer>要素を取得し、activateAR()を実行します。

  <script>
    document.querySelector('#another-ar-button').addEventListener('click', (event) => {
      const modelViewer = document.querySelector("model-viewer");
      modelViewer.activateAR();
    });
  </script>

こうすることで、デフォルトのARボタンとは別にAR起動ボタンを追加できます。

f:id:jyuko49:20200724130404j:plain
AR起動ボタンの追加

AR対応のデバイスでボタンを押すと、ARボタンを押したときと同じようにARビューアーが起動します。
ARに対応していないデバイスでボタンを押しても何も起きないので、その点は注意が必要です。

3Dモデルのロードが完了したらARを起動する(iOSのみ)

上記の応用で、 3Dモデルのロードが完了したら何もしなくてもARが起動するようにします。

実装方法はごく簡単で、<model-viewer>でモデルのロードが完了したときのloadイベントに対して、先ほどのactivateAR()を実行してやるだけです。

  <script>
    document.querySelector('model-viewer').addEventListener('load', (event) => {
      event.target.activateAR();
    });
  </script>

AR対応デバイスかつclick以外のイベントからactivateAR()を実行できる場合のみ、ARビューアーにリダイレクトするような動きになります。

この実装にはブラウザの制限があり、iOS Safari、iOS ChromeではAR Quick Lookが起動しますが、Android Chromeでは動作しません。
Android ChromeはScene Viewerを初めて起動する際にカメラ利用の同意が入るので、ユーザー操作を伴わないイベントからは実行できないようにしている可能性があります。

iOS ChromeからAR Quick Lookを起動する(iOSのみ)

quick-look-browsersというAttributeがあるのですが、デフォルトの設定が"safari"になっており、iOS ChromeでWebサイトを表示したときにAR Quick Lookが起動できなくなっています。

f:id:jyuko49:20200724125048j:plain
iOS ChromeはデフォルトでARボタンが表示されない

quick-look-browsers"safari chrome"と設定してあげると動作するようになります。

    <!—model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz"
      ar
      camera-controls
      quick-look-browsers = "safari chrome"
    >

f:id:jyuko49:20200724125058j:plain
iOS ChromeでARの起動を有効化

ARビューのカスタマイズ

最初に述べた通り、ARビューアーの機能に依存するため、ARを起動した後はほとんどカスタマイズできないのですが、AR Quick LookをSafariで起動した場合だけUIの拡張ができます。

カスタムアクションを追加する(iOSのみ、制限事項あり)

カスタムアクションUIはiOS13.3以降のAR Quick Lookに追加された機能で、AR Quick Lookを起動した後にApple Payデザインの購入ボタンやカートに追加ボタンなどを表示できます。

AR Quick LookでのApple Payボタンまたはカスタムアクションの追加 - 日本語ドキュメント - Apple Developer

この機能はUSDZファイルのURLにパラメーターを付与することで有効になるため、<model-viewer>でもUIの表示を行うことができます。

    <model-viewer
      src="model/PronamaChan.glb"
      ios-src="model/PronamaChan.usdz#callToAction=カートに入れる&checkoutTitle=プロ生ちゃん&checkoutSubtitle=USDZモデル&price=5,000兆円"
      ar
      camera-controls
    >

パラメーターで渡したテキストとサイトのURL(ローカルで実行しているので192.168.x.x)を使ってカスタムアクションUIが構成されます。

f:id:jyuko49:20200724125113p:plain
カスタムアクションのUI表示

ただし、この実装は上記の書き方をすればUIが表示されるというだけで<model-viewer>が完全に対応をサポートしているわけではありません。そのため、AR Quick LookでカスタムアクションUI上のボタンがタップされ、元のサイトに戻ったときのコールバックイベントを取得することができていません。
この点についてはGithubのIssueでも議論がされているようなので、いずれ対応されるかもしれません。

結果として、UIの表示とサイトに戻るアクションだけが実行できます。

当然ながら、<model-viwer>を使わずに<a>タグでUSDZファイルにリンクするAR Quick Lookの実装を行えば、ボタンをタップした後のコールバックも取得できます。

  <body>
    <a id="ar-link" rel="ar" href="model/PronamaChan.usdz#callToAction=カートに入れる&checkoutTitle=プロ生ちゃん&checkoutSubtitle=USDZモデル&price=5,000兆円">
      <img src="image.png">
    </a>
  </body>
  <script>
    const linkElement = document.getElementById("ar-link");
    linkElement.addEventListener("message", function (event) {   
      if (event.data == "_apple_ar_quicklook_button_tapped") {
        alert("カートに入れるが押されました。");
      }
    }, false);
  </script>

上記のリンクはiOS Safariでカスタムアクションが使えるメリットの代わりにWebサイト上では3Dモデルが表示されません。
glbさえあればPCでもChromeでも3Dモデルを見ることができる<model-viewer>とどちらがいいかはケースバイケースですし、ブラウザ・OSを判別して出し分けを行ってもいいかと思います。

まとめ

<model-viewer>は機能がシンプルな分、上記のような細かい機能まで知っておくと違いが出せます。
記事のボリューム(だいぶ絞ったけどそれでも多い)の関係でAnnotationsAnimationあたりに全く触れられていないので、https://modelviewer.devを読んでいろいろ試して頂ければと思います。