2023年のAR年賀状として、雪が降る年賀状をつくりたいと考えました。
「年賀状の部分にだけ雪が降っていたら面白いのでは?」という発想です。(ちなみに、ジョジョの奇妙な冒険のウェザー・リポートが好きで、一エリアにだけ特殊な天気を発生させる、というのをやってみたかったというのもあります。マニアックな話ですいません。)
前回は、model viewerを使ったAR年賀状のつくりかたを解説しましたが、今回は、model viewerだと実装が難しく、8th wallというARをつくるツールを使いました。
完成形はこちら。
こちらで体験できます。
https://namikawasusumu.net/nengajo2023/
※スマートフォンのブラウザでご覧ください。
自分の備忘録も兼ねつつ、このAR年賀状のつくりかたを解説します。
スマホのウェブブラウザで動く高性能なARを作ってみたい人の参考になればと思います。
また、プログラムは、githubにも置いておきます。プログラムの使用、改変は非営利/営利ともに自由です。ただし、3Dモデルの流用/販売はご遠慮ください。
https://github.com/Namy731/arsnowcard
開発環境は、
・Macbook Pro
・OSは、Catalina 10.15.7
・Blender2.82
です。
8th wallとは?
WebAR(Webブラウザで体験できるAR)を簡単かつ高性能につくれる有料ツールです。
8th wall
https://www.8thwall.com/
同じくWebブラウザで体験できるARのライブラリであるA-frameやAR.js(無料)でできることを強化してくれる、というイメージです。感覚値ですが、AR用のネイティブアプリを開発すればできることを10とし、ウェブブラウザ上でA-frameとAR.jsでできることを3とすると、7ぐらいのことができるイメージです。
だったら、ネイティブアプリを開発するのが一番いいじゃん、と思う人もいるかもしれませんが、ARを体験するためにアプリをダウンロードする、というのは結構ハードルがありますよね。手軽だけど本格的なARを提供したいという方には、8th wallは有力な選択肢だと思います。
今回は、AR.jsよりも平面検出の精度を上げたくて、8th wallを使用しました。
つくりかた
8th wallでの開発の手順は、
- ウェブブラウザ上の8th wallエディターで確認しつつ、開発。
↓ - 8th wallのサーバーにアップする
あるいは - 自分のウェブサーバーにアップする
です。
今回は、自分のドメインにしたかったので、後者を選びました。
コーディング
8thwallのコーディングは、まず、ウェブブラウザ上で使えるエディターで行っていきます。このエディター、かなり便利です。プレビュー機能やデバッグ機能もあります。
基本は、AR.js、A-frameと、コードの書き方は同じです。いくつか便利で強力な8th wall独自のライブラリもあります。
3Dモデルの制作と取り込み
降ってくる雪以外の3Dモデルは、Blenderで制作し、Embedded GLTFでアニメーション込みで出力しました。このあたりは、前回の記事も参考にしてみてください。制作した3Dモデルを、8th wallエディターにドラッグ&ドロップして取り込みます。
headerの編集
ここには、使いたいライブラリを書いておきます。アニメーションを使う場合(アニメーションするgltfモデルを使うときなど)は、aframe-extrasを加えておきます。
<meta name="8thwall:renderer" content="aframe:1.2.0">
<meta name="8thwall:package" content="@8thwall.xrextras">
<meta name="8thwall:package" content="@8thwall.landing-page">
<script src="//cdn.8thwall.com/web/aframe/aframe-extras-6.1.1.min.js">
bodyの編集
A-Frameではいろんな物体を配置することができます。
a-sceneタグで囲まれた中に、いろいろなa-◯◯タグで物体を置いていくルールです。
<a-scene
xrextras-gesture-detector
landing-page
xrextras-loading
xrextras-runtime-error
renderer="colorManagement: true"
xrweb="allowedDevices: any">
// この間にさまざまな物体を配置する
</a-scene>
a-cameraは、スマホのカメラの位置の設定です。
センターから少しずらした位置にカメラを設定しておくと、中心である"0 0 0"にモデルを配置したときに、いい感じの位置に出現するようになります。
<a-camera
id="camera"
position="0 8 8" // カメラ位置
cursor="fuse: false; rayOrigin: mouse;">
</a-camera>
ちなみに、A-Frameでの座標は、"y座標,z座標(縦),x座標"となります。
また、GLTFの3Dモデルを配置するには、a-assetsでファイル名を指定し、a-entityタグを使って配置します。複数配置することもできます。animation-mixerを設定すると、アニメーションが動きます。
<a-assets>
<a-asset-item id="snowcard" src="snowcard.gltf"></a-asset-item> // ファイル名とidを指定
</a-assets>
<a-entity
gltf-model="#snowcard" // a-assetsで指定したidを入れる
position="0 0.05 0"
scale="1 1 1"
shadow="receive: true"
animation-mixer="loop: repeat" // アニメーションの指定 今回はリピートも指定
snowbase>
</a-entity>
雪の発生
雪の発生が、今回一番苦労したところです。
- 一定の間隔で、白い球体を新たに生成。
- サイズと出現するxy座標は決められた範囲でランダムに。
- 球体にはアニメーションを設定し、次々落下させていく。
という設計にしました。
Javascriptのパートは、app.jsに書きます。8th wallの制作例を見ると、app.jsには呼び出しだけ書いて、別途jsファイルをつくるのが一般的なようですが、面倒なので、僕はapp.jsにガンガン書いていきます。
AFRAME.registerComponent('snowbase', {
init() {
setInterval(() => {
const x = Math.random()*4-2 // x位置をランダムに設定
const y = Math.random()*5.8-2.9 // y位置をランダムに設定
const ra = Math.random()*0.06+0.03 // 半径をランダムに設定
const rasize = ''+ra
const fposition = ''+x+' 10 '+y //スタート位置
const eposition = "property: position; to: "+x+" -1 "+y+"; dur: 6000; easing: linear; loop: false;" //終了位置とアニメーション
const newElement = document.createElement('a-sphere') //球体をつくる
newElement.setAttribute('position',fposition)
newElement.setAttribute('radius',rasize)
newElement.setAttribute('color','#FFF')
newElement.setAttribute('animation__position',eposition)
this.el.sceneEl.appendChild(newElement) //A-Frameのシーンに加える
}, 80)
}
});
自分のウェブブラウザにアップロードする
8th wallにファイルを一括で出力できる機能が見当たらなかったので(本当はあるのかもしれない)、エディターから手動でコピペして、アップロード用のindex.htmlファイルを作っていきました。
また、8th wallのPROJECT DASHBOARDで、HOSTINGのコーナーにあるSet Up Domainsで、最終的にアップロードするドメインを設定し、APIキーを発行しておきます。
index.htmlの構造は下記の通りです。
<!doctype html>
<html>
<head>
<title>AR snow card</title>
<!--meta情報をここに入れる-->
<!--head.htmlのコードをここに入れる-->
</script>
<script async src="//apps.8thwall.com/xrweb?appKey=<apiキーを入れる>"></script>
</head>
<script type="text/javascript">
// app.jsのコードを入れる
</script>
<body>
<!--body.htmlのコードを入れる-->
</body>
</html>
振り返り
Javascriptを使ったWeb ARには、さまざまな可能性があると思います。
クリックなどを使ったインタラクティブな表現も考えられます。
高性能でクリエイティビティに富んだWeb ARにチャレンジする人にとって、この記事がなにかのヒントになれば嬉しいです。
8th wallについて言えば、2022年3月には、あのポケモンGOのNianticが8th wallを買収したことでも話題になりました。8th wallにも、VPS(ビジュアルポジショニングシステム)が実装されました。次回は、VPSを実験した記事を書きたいと思っています。