※この度、8th WallのLightship VPSについて寄稿いただきました。全3回に渡り解説をお送りします。今回は3回目となります。前回の記事はこちらです!
8th WallのVPSのサンプルコードを見ていきながら、実装してみます(2022/10/10現在の情報です)。
今回は、公式が出しているLightship VPS Bespokeのコードを見ていきましょう。
どういう仕組みなのか
Bespokeのサンプルでは、木にぶつかった風船が凹んで、そのままフワッと飛んでいっているのですが、実はこの風船の動きの部分は、コードで制御しているのではなく、3D側で制御しています。
前回書いたように、Geospatial browserのページで、Wayspot空間のglbデータをダウンロードできるようになっています。
この空間のglbメッシュの原点が、VPS体験の原点となるので、
このglbにピッタリと合うように配置した3Dモデルを作る事で、実際の空間に重なるようにうまく表示してくれるのです。
ということで、VPSは、いかにリッチな3Dモデルを作って見せられるか、がめちゃくちゃ肝になってくるのではないかな、と思います。
前回の記事では、Wayspotをプロジェクトに登録する時に、綺麗なメッシュのglbをプロジェクトに入れるといいよ、というお話をしました。
その理由は、この空間glbに合わせて、3Dモデルのデータを作成するので、その位置合わせをやりやすくするため、なんですね。
コードを見ていこう
body.html(体験の元になる部分)
さて、ざっくりと仕組みが大体わかったところで、コードを見ていきます。
まずはbody.htmlを見ていきます。公式のコードから、重要そうな部分を抜粋したのがこちらです。
<a-scene
landing-page
vps-coaching-overlay
background="color: #303030"
renderer="colorManagement: true"
gltf-model="dracoDecoderPath: https://cdn.8thwall.com/web/aframe/draco-decoder/"
xrextras-runtime-error
xrextras-loading
xrweb="enableVps: true">
<a-assets>
<a-asset-item id="vps-mesh" src="./assets/california-p.glb"></a-asset-item>
<a-asset-item id="vps-anim" src="./assets/california-p-anim.glb"></a-asset-item>
</a-assets>
<!-- 中略 -->
<a-entity named-wayspot="name: california-p">
<!--hider material-->
<a-entity
gltf-model="#vps-mesh"
xrextras-hider-material>
</a-entity>
<!--shadow material-->
<a-entity
gltf-model="#vps-mesh"
shadow-shader
shadow="cast: false">
</a-entity>
<!--vps animation-->
<a-entity
gltf-model="#vps-anim"
cubemap-realtime
play-vps-animation
shadow="receive: false">
</a-entity>
</a-entity>
<!-- 後略 -->
a-sceneの中で、xrweb=”enableVps: true”を指定することで、VPSをすぐプロジェクトで使い始められます。
3行目のvps-coaching-overlayを入れておくと、VPS登録地点に近づいた時に、端末をかざすように指示するUIが表示されます。
※プロジェクトに登録されていない地点でも、近くに登録地点があると表示される仕様のようです。
18行目、named-wayspot=”name: california-p”という部分で、Wayspotを登録しています。
このnameは、以下の部分にあたります。以下のように日本語でもOKです。
private scanされた地点の場合、12文字の英数字になるはずです。
19-23行目、xrextras-hider-materialというコンポーネントを指定しています。
#vps-meshというモデルには、空間glbが指定されています(12行目)。このglbを、実空間に合わせて配置して、そこを透明なメッシュにしてくれます。この透明メッシュにめり込むようにモデルを置くと、めり込んだ部分が隠れます。
以下は床面にのみ透明メッシュが置いてある状況ですが、これが空間の凹凸に合わせて置かれている、と考えるとわかりやすいかなと思います。
24-29行目で影を指定しています。
30-36行目で3Dモデルのアニメーションについて指定しています。play-vps-animationを指定しておくと、vps-coaching-overlayが消えるのを待ってから、アニメーションを開始できます。このコンポーネントは、named-wayspot.jsの中で定義されています。
components/realtime-cubemap.js(モデルに環境を反射させる)
realtime-cubemapは、環境に置いてあるものをモデルに反射させる仕組みです。
詳細は、こちらのサンプルから。
このGIFを見るとわかると思いますが、みかんやオブジェの色や、ろうそくの光などが、リアルタイムでくるくる回る球体に映り込んでいるのがわかりますよね。
components/shadow-shader.js(影を落とす)
shadow-shaderは文字通り、モデルの影を落とすための実装です。
components/named-wayspot.js(Wayspotでのモデル表示制御)
named-wayspotの中で、モデルの表示・非表示を制御しています。
このコードの、namedWayspotComponentがVPSの肝になってくる部分ですので、抜粋して見てみましょう。
const namedWayspotComponent = {
schema: {
name: {type: 'string'},
},
init() {
const {object3D} = this.el
const {name} = this.data
object3D.visible = false
const foundWayspot = ({detail}) => {
if (name !== detail.name) {
return
}
object3D.position.copy(detail.position)
object3D.quaternion.copy(detail.rotation)
object3D.visible = true
}
const updateWayspot = ({detail}) => {
if (name !== detail.name) {
return
}
object3D.position.copy(detail.position)
object3D.quaternion.copy(detail.rotation)
}
const lostWayspot = ({detail}) => {
if (name !== detail.name) {
return
}
object3D.visible = false
}
this.el.sceneEl.addEventListener('xrprojectwayspotfound', foundWayspot)
this.el.sceneEl.addEventListener('xrprojectwayspotupdated', updateWayspot)
this.el.sceneEl.addEventListener('xrprojectwayspotlost', lostWayspot)
},
}
やっていることは比較的シンプルで、xrprojectwayspotfound, xrprojectwayspotupdated, xrprojectwayspotupdated, というイベントがそれぞれ走った時に、モデルを出したり、引っ込めたり、表示をアップデートしたりしています。
実装する時のポイント
基本的に、bespokeのサンプルを元に実装して、モデルの差し替えをするだけで、簡単に自分の好きな場所でモデルを出せます。
モデル作成のコツ
プロジェクトから空間glbをダウンロードして、Blenderなどのソフトを使って、そこに合わせてモデルを作成・配置しましょう。
この時、空間glbの原点を動かさないように注意してください。動かしてしまうと、AR表示位置が狂ってしまいます。
複数地点で出し分けるには
複数のWayspotを検知させることも可能です。
その場合は、body.htmlのa-asset-itemに追加して、それぞれに違うidを振っておき、
named-wayspotごとにa-entityを追加していけばOKです。
(それぞれのgltf-modelのidを対応させることをお忘れなく)コードにすると、こんな感じになると思います。
<a-scene
landing-page
vps-coaching-overlay
background="color: #303030"
renderer="colorManagement: true"
gltf-model="dracoDecoderPath: https://cdn.8thwall.com/web/aframe/draco-decoder/"
xrextras-runtime-error
xrextras-loading
xrweb="enableVps: true">
<a-assets>
<a-asset-item id="vps-mesh1" src="./assets/spot1.glb"></a-asset-item>
<a-asset-item id="vps-anim1" src="./assets/spot1-anim.glb"></a-asset-item>
<a-asset-item id="vps-mesh2" src="./assets/spot2.glb"></a-asset-item>
<a-asset-item id="vps-anim2" src="./assets/spot2-anim.glb"></a-asset-item>
</a-assets>
<!-- 中略 -->
<a-entity named-wayspot="name: ここにspot1の名前">
<!--hider material-->
<a-entity
gltf-model="#vps-mesh1"
xrextras-hider-material>
</a-entity>
<!--shadow material-->
<a-entity
gltf-model="#vps-mesh1"
shadow-shader
shadow="cast: false">
</a-entity>
<!--vps animation-->
<a-entity
gltf-model="#vps-anim1"
cubemap-realtime
play-vps-animation
shadow="receive: false">
</a-entity>
</a-entity>
<a-entity named-wayspot="name: ここにspot2の名前">
<!--hider material-->
<a-entity
gltf-model="#vps-mesh2"
xrextras-hider-material>
</a-entity>
<!--shadow material-->
<a-entity
gltf-model="#vps-mesh2"
shadow-shader
shadow="cast: false">
</a-entity>
<!--vps animation-->
<a-entity
gltf-model="#vps-anim2"
cubemap-realtime
play-vps-animation
shadow="receive: false">
</a-entity>
</a-entity>
<!-- 後略 -->
まとめ
ということで、bespokeを例に取りながら、VPSの仕組みについてまとめてみました。
こうして見ていくと、シンプルなコードで、かなり柔軟で面白いAR表現を追求できそうな仕組みだなと思いました。
ますますリッチなWebAR体験ができそうで、ワクワクしますね!
執筆者 影織(@kageori_ar)
ARと切り絵を組み合わせた作品を中心に、様々な制作をしています。https://kageori.pythonanywhere.com/
8th Wallを手軽に使える「palanAR」
本メディアの運営会社である株式会社palanは8th Wallのオフィシャルパートナー企業でもあります。
palanが開発するノーコードAR作成ツール「palanAR(パラナル)」では、8th Wallの高精度な平面認識・画像認識の技術を利用してARを作成していただける「プレミアムオプション」もございます。
直接8th Wallと契約するよりも手軽に8th Wallを利用してARを作成することができます。
palanARについてはこちら:https://palanar.com/
プレミアムオプションについてはこちら:https://palanar.com/about_premium
palanについて
palanARを使ってご自身で制作いただくだけでなく、弊社で8th Wallを使ったARの制作をご依頼いただくことも可能です。
8th Wallを使ったARを制作したい際は、お気軽にお問合せください。
8th Wall開発について詳細はこちら:https://studio.palanar.com/development/webar-8thwall
お問い合わせはこちら:https://studio.palanar.com/contact