AR Quick Lookで使える3Dモデル動的生成
気軽にリッチなAR体験が楽しめるAR Quick Look(Scene Viewer)。
サーバに3Dモデルを置いてリンクを張るだけ、というのは(3Dモデルさえあれば)誰にでも作れちゃうぐらい簡単なのですが、その分「見て楽しむ」というコンテンツに特化しており、インタラクティブなコンテンツを作ることは基本的にはできません。
なにかユーザが介入できる要素をちょっとでも入れられないかな・・・と考えた末、こんなコンテンツを作ってみました。
痛車AR
https://sumanobe.imjp.co.jp/blog/2020/03/27/itasya-ar/
車体のベースカラーと好きな画像を選んでアップロードするだけで、自分好みの痛車を(の3Dモデル)を自動生成できるコンテンツです。
生成された3DモデルはAR Quick Look(またはScene Viewer)で閲覧することができます。
今回はこの「痛車AR」で採用している動的な3Dモデル生成について解説していきます。
テクスチャの差し替え
「痛車AR」のカスタマイズの仕組みはシンプルで、3Dモデル内で使用しているテクスチャファイルをユーザ毎に加工し、差し替えているだけです。
ユーザはまずサイト側で、車体のベースとなる色とボンネットなどに貼る画像を選択します。この時、選択された画像は既定の比率に合わせて切り取られます。このあたりの処理はJavaScriptでやっていますが、特に変わった処理でもないので解説は割愛します。
次に「生成する」ボタンを押すと、色情報と切り取られ画像がサーバにPOSTで送信され、サーバ側に置かれたプログラムで受信をします。
この受信プログラムは今回はphpで実装されており、受信処理の後に以下のような処理を行っています。
・ユーザ毎(アクセス毎)にユニークなIDを発行し、そのIDでディレクトリを生成する
$id = ユニークなID生成処理
mkdir($id);
・テクスチャ用画像を新規作成
$textureImage = ImageCreateTrueColor(横幅, 縦幅);
・テクスチャ用画像を受信した色情報で塗りつぶす
imagefill($textureImage, 0,0, 受信した色情報);
・テクスチャ用画像の指定座標に受信した画像ファイルを描画する
imagecopy($textureImage, 受信画像データ, 描画座標X,描画座標Y, 0,0,受信画像横幅,受信画像縦幅);
・生成したディレクトリ内にテクスチャ用画像をファイルとして書き出す(例:texture.png)
imagepng($textureImage, $id.”/texture.png”);
ここまでがテクスチャ画像生成処理です。
続いてiOS用のusdz、Android用のglb、というそれぞれの形式に合わせた3Dモデルを生成するわけですが、その処理に入る前に一旦事前準備について解説します。
3Dモデル生成の下準備
3Dモデルはそれぞれ下記のような処理を行って生成しています。
iOS用 usdzファイル
usdzは基本的にはアーカイブされた無圧縮のzipファイルとほぼ同じです。
ですがただアーカイブしてzipファイルにすればいいわけではなく、各ファイルの先頭を64Bitの倍数にしなければならない、というちょっと面倒なルールがあったりします。
そこで今回はusdzファイルそのものを対象として、該当ファイルの差し替えのみを行う、という対応をしました。
具体的には、php内でLinuxのzipコマンドを呼び出し、更新(-u)、無圧縮(-0)オプションを付けて差し替えを行う、という対応です。
zip -ur0 元となる.usdz 書き換え済みテクスチャ.png
これで元となる.usdzの形式を壊すことなく、該当のテクスチャファイルだけ差し替えることが可能となります。
Android用 glbファイル
glbファイルの生成は、シンプルにobjファイルからgltf(またはglb)ファイルを生成するコンバータ「obj2gltf」を使用しています。
obj2gltfについてはこちら
https://www.npmjs.com/package/obj2gltf
こちらもusdzファイルの生成と同様に、phpからLinuxのコマンドを呼び出す、という対応をしました。
obj2gltf -i 素材となる.obj -o 新規生成.glb
上記のような方法で各3Dモデルを生成するわけですが、アクセスしたユーザ毎に異なるファイルを生成する必要があるため、実際には「元となる.usdz」と「素材となる.obj」は加工されないオリジナルデータとして用意しておき、そのオリジナルデータをユーザ毎に生成されたディレクトリにコピーし、そのコピーしたファイルから3Dモデルを生成します。
/オリジナル/元となる.usdz
↓コピー
/$id/コピーされた.usdz
/オリジナル/素材となる.obj(他mtlファイルやテクスチャファイル一式を含む)
↓コピー
/$id/コピーされた.obj(他mtlファイルやテクスチャファイル一式を含む)
※$idは前項で生成されたユーザ毎のユニークなID
そのため、前項の最後に記述された「テクスチャ画像をファイルとして書き出す」という処理は、上記のコピー処理の後に実施して上書きする必要があります。
もしくはコピー元となるテクスチャファイルは用意しない=コピーもしない、という方法でも可能です。
3Dモデル生成とmodel-viewerによる表示処理
前項の下準備を踏まえた上で、php上では下記のようにcopy関数でユーザ毎のディレクトリにコピーした後で、exec関数によって3Dモデルの生成を行っています。
・iOS用 usdzファイルのコピーと生成
copy(“オリジナル/元となる.usdz”, $id.”/コピーされた.usdz”);
exec(“zip -ur0 “.$id.”/コピーされた.usdz “.$id.”/書き換え済みテクスチャ.png”);
・Android用 glbファイルのコピーと生成
copy(“オリジナル/素材となる.obj”, $id.”/コピーされた.obj”);
copy(“オリジナル/素材となる.mtl”, $id.”/コピーされた.mtl”);
exec(“obj2gltf -i “.$id.”/コピーされた.obj -o “.$id.”/新規生成.obj”);
最後にユーザが実際に閲覧するビュー側ですが、iOSとAndroidのどちらにも簡単に対応できるmodel-viewerを採用しました。
model-viewerについてはこちら
https://modelviewer.dev/
ユーザ側の遷移としては下図のようになっています。
ダウンロードページ(上図右)はパラメータにつけられた$idを参照し、タグを下記のように記述することで、ユーザ毎に生成された3Dモデルを指定して閲覧できるようにしています。
<model-viewer ar src=”/<?php echo $id;?>/新規作成.glb” ios-src=”/<?php echo $id;?>/コピーされた.usdz” alt=”痛車メーカー” class=”model-viewer”></model-viewer>
以上が痛車ARが内部で行っている処理となります。
usdzの生成は、本来であればルールに則って素材ファイルをzipアーカイブして64Bit揃えをするのが正当なやり方だと思いますが、このやり方なら強引ではあるものの非常に簡単にですので、手軽な実装して試してみることができると思います。
とはいえカスタマイズの幅が狭まってしまうという問題もありますので、そのうち正当なやり方でのusdzファイル生成も手をつけてみたいところです。