福岡XR部 Monthly Meetup の紹介
この記事は、『地方でXR系(VR/AR・MR/裸眼立体視など)勉強会 Advent Calendar 2024』の22日目に書くだったはずが遅れに遅れて今になってしまった記事です 😇
福岡XR部のながみねです!
もはや遅刻どころではないですが、せっかくなので書きます!(junさんごめんなさい)
この記事では福岡XR部が毎月開催している「Monthly Meetup」についてご紹介します。
福岡XR部とは?
福岡XR部は福岡を中心にXR技術・表現に興味のある様々な人が集まるコミュニティです。ミートアップ、体験会、勉強会、もくもく会、ハンズオンなど様々なイベントを通して、同じ興味を持つ人が集まって話をしたり教えあったり遊んだりする部室のような「場」になることをイメージして活動しています。
属性・職種・経験など問わず、XR技術・表現に興味があればどなたでも、もちろん福岡でない方も参加歓迎です。活動内容も話したり試したり遊んだり学んだり、XRへの理解を深める活動であれば何でもありです。
それぞれがやってみたいことを気軽に提案して実行できる、みんなで作るコミュニティになるといいなという気持ちで活動しています。
Monthly Meetup とは?
Monthly Meetup は毎月第1水曜日に開催しているオンラインミートアップイベントです。
Discordのボイスチャット・テキストチャット、Notionで作成したイベント用ページ、オンラインホワイトボードツールを組み合わせて、以下の構成で開催しています。
-
今月のXRニュースをみんなで振り返ろう
-
今月の深堀りテーマ
-
LT
今月のXRニュースをみんなで振り返ろう
Mogura VRのニュース記事を中心に、その月のXRニュースを読んで気になる記事について詳しい人が解説したり質問しあったりします。
最初に15分各自でニュースを読む時間をとり、ニュース記事を読みながらコメントや感想、質問などをホワイトボードに書いていきます。
その後、ホワイトボードを見ながらコメントの多かったニュースを取り上げて詳しい人が解説したり質問しあったりします。
取り上げるニュース記事はXR部メンバーでMoguraVRのライターでもある Ayuko Haitsukaさんが事前にピックアップしてくれています。

今月の深掘りテーマ
Connpassで参加登録するときのアンケートで、深掘りして話したい/聞きたいテーマを任意で募っています。
なければスキップするのですが、だいたい誰かは何かを書いてくれているので、15~30分くらい、そのテーマについて会話をしています。
直近で参加/開催したイベントのレポート的な話だったり、体験したデバイスの感想だったりがテーマになることが多い気がします。

LT
いわゆるLighting Talkで参加者が話したい内容を話してもらう時間です。1人だいたい5-10分くらいを目安にしていますが、その日の進行状況や発表人数に応じて時間はまちまちです。
できるだけハードルを下げたいのでテーマなんでもOKで発表形式も自由です。資料があってもなくても問題なし。LT希望者がいなければスキップです。
大事にしてる/工夫してるポイント
できるだけ参加者のコミュニケーションが取りやすいイベント
Monthly Meetupは、コロナ禍でオフラインのイベントができない時期に始めたイベントです。
コロナ禍でいろいろなイベントがオンライン化していく中で、実際に参加していて感じたのが、オンラインイベントだと発表者の話を聞くことが中心で、参加者同士のコミュニケーションが発生しづらいということでした。
オフラインのイベントであれば、参加者同士が物理的に近くにいるので、交流の時間を作ることで自然とコミュニケーションを取ることができますが、オンラインイベントだとなかなか難しいなと思っていました。
オンラインでももう少しコミュニケーションがとりやすい形式にできないかなと思って始めたのが、MonthlyMeetupです。
主なコンテンツであるニュース振り返りでは、参加者が各自でホワイトボードツールに付箋を貼っていき、付箋のコメントを拾いつつ会話をしていきます。基本は運営側が進行しますが、詳しそうな人に話を振ったり、双方向になることを意識して進めています。

また、Discordの「リアクションロール」という機能を使って参加者の属性や興味を表示できるようにしています。
イベントの最初にオープニングの時間として参加者の出欠確認をするのですが、はじめましての人がいたら選択したロールを見ながらXRのどのあたりに興味があるかなど、自己紹介的に話を振るのに活用しています。

継続しやすい内容/運営
定期的にコミュニティ仲間とのワイワイする機会を作るために"Monthly"という名前で毎月開催することを目標に始めたので、できるだけ継続しやすい内容・運営になるようにしています。
内容面では、XRニュース振り返りのコーナーを基本にすることで、毎月発生するXR業界の動き自体がコンテンツになります。
深掘りやLTのコーナーはテーマ/希望者がいなければスキップすることができ、運営側で発表者を用意したりコンテンツに頭を悩ませなくて良い設計になっています。
XRニュースの記事をたくさん公開してくれているMoguraVRさんと、毎月記事のピックアップをしてくれている、はいつかさんに大感謝です。

運営面では、このイベントは3人(そいちろ・はいつか・ながみね)の3人で運営する体制にしています。
はいつかさんは前述のとおりニュース記事のピックアップ、イベントページ作成や当日の主な進行をそいちろさん、僕は進行で合いの手を入れたり、そいちろさん不在のときには進行をしたり。
また、イベント準備や当日の流れはNotionのページにまとめていて、毎回ページをコピーして手順に沿って準備・進行できるようにしています。基本的にはそいちろさんか僕が進行していますが、理想は運営側が誰もいなくてもNotionページがあれば参加者だけで進行できる状態です。(今のところそのケースは発生していませんがw)
Notionページは公開状態になっているので気になる方は参考にどうぞ。

まとめ
この記事では福岡XR部が毎月第1水曜日に開催している「Monthly Meetup」について紹介しました。
継続しやすい内容・運営を意識することで、2025年2月時点で53回、たぶん毎月開催できていると思います。
次回は2025年3月5日に開催予定です。XR技術や表現に興味がある方ならどなたでも、初心者、はじめましての方、学生の方も大歓迎なので、興味のある方はぜひご参加ください。
XR Interaction Toolkitに挑戦!VIVE FlowやPICO4向けに拡張してみた

こんにちは、ながみねです。とってもとっても久しぶりにブログというものを書いています。書き出し方をまったく覚えていないけどこんなんでよかったっけ?
さて、この記事は「Qiita x エンジニアカフェ共催!今年がんばった技術(と好きなラーメンと麺のかたさ) Advent Calendar 2022」の14日目の記事です。
好きな食べ物はラーメンです
好きなラーメンは豚骨なんですが、先日福岡空港のラーメン滑走路でたまたま入ってみた「Noodle Laboratory 金斗雲」というお店の味噌ラーメンが美味しかったです。
ラーメン滑走路は10軒ほどのラーメン屋さんが並んでいる飲食街のこと。福岡には他にもラーメンスタジアムとか博多めん街道とか、ラーメン屋が集まってるところが割と近い範囲に複数あるんだけど、他の地域にもこういうのあるんだろうか?
XR Interaction Toolkitとは
というわけでここから本題。
XR Interaction ToolkitはUnity公式が提供しているXR開発用のパッケージです。
長いので以降はXRIと表記します。
MetaQuestやVIVEシリーズなどの各種VRデバイスには、それぞれ開発用のSDKが提供されています。VR開発の際は対象デバイスごとにカメラや入力、操作といった処理をそれぞれ実装する必要がありました。
XRIはVRに必要な基本的な機能を抽象化してデバイスごとの差異を吸収してくれます。XRIを利用することで、クロスプラットフォームなVRアプリを開発することができます。
XRIの基本的な使い方、どういった機能があるかは、以下のブログがとても参考になります。
Device-basedとAction-basedの入力
XRIの入力制御コンポーネントには、Device-basedとAction-basedという2種類があります。
Device-basedではデバイスからの入力値を直接参照し、Action-basedはInput Systemというデバイスからの入力をActionという形式に抽象化する仕組みを使って入力値を参照します。
Action-basedを利用するとボタンのカスタマイズやクロスプラットフォーム対応が容易になるため、ドキュメントではAction-basedの使用が推奨されています。
It is recommended that you use the Action-based variant instead of the Device-based variant to take advantage of the benefits that the Input System package provides. For example, it separates the logical inputs from the physical inputs, and users can create and switch between customized action maps, bind multiple cross-platform controller inputs to a single semantic action, and use event callbacks of input actions. Some features of the XR Interaction Toolkit package, such as the XR Device Simulator, are only supported when using input actions.
Device-basedのコントローラー設定。参照するボタンを直接設定しています。

Action-basedのコントローラー設定。InputSystemのActionを設定しています。

この記事では、XRIのAction-basedに対応していない入力をXRI対応させるために試してみたことについて書いてみます。
仕組みを調べつつ試行錯誤しながら最終的に上手くいった方法なので、もっと良いやり方があったり正確じゃない部分があるかもしれません。
参考にしたドキュメントや記事は最後にまとめて記載するのでより詳しく知りたい方はそちらも見てみてください。
①VIVE FlowのAction-based対応
VIVE Flowとは
VIVE FlowはHTCが開発・販売するVRデバイスで、小型軽量のためメガネのように装着することができます。

一般的なVRデバイスとは異なり手の動きをトラッキングするハンドコントローラーは付属せず、スマートフォンか専用の3DoFコントローラーを接続してポインター入力で操作します。

VIVE FlowのXRI対応状況
VIVE Flowアプリの開発にはVIVE Wave XR Pluginを利用します。
VIVE Wave XR Pluginには機能拡張用のEssenceパッケージが用意されており、XRIを使うためにはこちらも一緒にインポートします。

ただし、Essenceパッケージを追加するだけでは不十分で、ProjectSettingsのWaveXR > Essenceの設定でXRIを有効化するとようやく使えるようになります。

XRIが動作するサンプルシーンが追加されているので、コントローラーの設定がどうなっているか確認してみます。XRControllerがDevice-basedになっており、現状のSDKではAction-basedには対応していないようです。

Action-basedに対応する
Action-basedに対応するというのは、デバイスからの入力をInputSystemで扱えるようにするということです。そのためInputSystemの仕組みを理解する必要があるのですが、これがなかなか奥深く大変でした。自分の理解もまだ浅いこともありここでは詳細には書かないですが、興味があれば公式ドキュメントのArchitectureの項目を読み込んでみることをオススメします。
デバイスの入力をInputSystemで扱うために以下の手順を踏みました。
- デバイスから流れてくるデータの構造を確認する
- 1のデータ構造に合わせたクラスを定義する
- アプリ起動時に2のクラスをInputSystemに登録する
1. デバイスから流れてくるデータの構造を確認する
デバイスが接続されると、Unityに対してデバイス固有のデータ構造でデータを流すような仕組みになっているようです。
デバイスのデータ構造はInputSystemで取得できるので、今回はJSON形式にしてログ出力することで確認しました。
データ構造を確認するためのコード。
出力したVIVE Flowのコントローラーのデータ構造。inputFeaturesの部分でどういった入力が取得できるかが分かります。
2. 1のデータ構造に合わせたクラスを定義する
以下のようなクラスを定義しました。
- 1のinputFeaturesに対応するInputControlのプロパティを定義していく
- aliaceの部分でinputFeaturesのnameを指定
- プロパティ名はInputSystemのActionを作成する際のパス名になる(重要)
3. アプリ起動時に2のクラスをInputSystemに登録する
起動時の早いタイミングで登録するため、2のクラスの静的コンストラクタでクラスを登録、コンストラクタが必ず実行されるようにRuntimeInitializeOnLoadMethodの空メソッドを用意しています。
WithInterace(), WithProduct()はデバイスデータとクラスをマッチングするための条件付けで、VIVE Flowのコントローラーが接続されたときにこのクラスが使われるように設定しています。
動作確認
まずはInputSystemへの登録がうまくいっているかを見てみます。
InputDebugウィンドウを開くと、クラス定義したWave Controllerの情報が追加されていることが分かります。これでInputSystemがこのデータ構造を知っている状態になりました。

ここまで来ればシーンをAction-basedが動くように整えてあげればOKです。
まずは、InputActionManagerを追加してInputActionが有効になるように設定します。
今回はXRIのサンプルに含まれるデフォルトアセットを使用しています。(デフォルトアセットが使えるようにクラス定義のところでプロパティ名を合わせていた)

続いてコントローラーのオブジェクトをAction-basedに置き換えます。ここでもXRIのデフォルトのInputActionを設定してます。

この状態でビルドすると、無事にAction-basedのXRIが動作していることが確認できます。
これでVIVE FlowのAction-based対応は完成です。
デバイスのクラス定義の全体は以下のGistにあります。記事ではコントローラーのみ言及しましたが、コードではHMDにも対応しています。
VIVE FlowのInputControlLayout定義 · GitHub
②PICO 4のハンドトラッキング対応
PICO 4とは
PICO 4はPico Technologyが開発・販売するVRヘッドセットです。2022年10月に発売されたばかりの新しいデバイスで、比較的小型軽量、高画質、安価といった特徴があります。

PICO 4のXRI対応状況
PICO 4のアプリ開発にはPICO Integrationを使います。PICO IntegrationはXRIのAction-basedにも対応しており、ドキュメントのQuickstartでもXRI (Action-based) を使う形で記載されています。
Quickstart - Create a simple XR scene
PICO Integrationのパッケージ内を見てみると、VIVE Flowの場合に自作したデバイス構造を登録するためのクラス定義があることが分かります。

というわけで、コントローラーを使う分にはデフォルトのままでもAction-basedのXRIが動作します。
そこで今度は、PICO 4で利用できるハンドトラッキング操作をXRIに対応させることにチャレンジしてみました。
ハンドトラッキングを扱う方法はSDKで提供されており、ドキュメントにも記載されています。
画像のようにプレハブを配置するだけでハンドモデルの表示とトラッキング状態の適用は簡単にできるようになっています。

しかし、トラッキング情報の反映はPXR_Handコンポーネントで処理されていますが、見た目の反映とトラッキング情報にアクセスするためのプロパティを公開しているだけです。
このままではオブジェクトとのインタラクション等は発生しないので、PXR_Handのプロパティを参照して独自にインタラクションを実装する必要があります。ここからXRIで扱えるように対応していきます。
XRI(Action-based)に対応させる
VIVE Flowのほうにも書いたように、XRI (Action-based)に対応するというのは、デバイスからの入力をInputSystemで扱えるようにするということです。
VIVE Flowのほうでやったのは、「デバイスから届くデータをInputSystemで扱えるようにデータの型を登録する」という作業でした。
今回の場合、ハンドトラッキングの情報はデバイスとして扱われていないので、「デバイスから届くデータ」自体がありません。
そこで、ハンドトラッキング情報を「カスタムデバイス」として扱い、スクリプトから入力データを発行する、ということをしていきます。
InputSystemのドキュメントのCreating custom Devicesの項目で詳細が解説されています。
ハンドトラッキング情報をカスタムデバイスとして扱うために下記の手順を踏みました。
- デバイスの入力状態を表す構造体を定義する
- 1の入力状態に合わせたクラスを定義する
- アプリ起動時に2のクラスをInputSystemに登録する
- 任意のタイミングで2のデバイスをInputSystemに追加する
- ハンドトラッキング情報をもとにInputSystemにデータを発行する
1. デバイスの入力状態を表す構造体を定義する
カスタムデバイスの入力状態は構造体として表されます。
コントローラー入力と同等に扱えるようにフィールド名や種類を定義しています。今回はハンドトラッキングでの選択操作をgripとして扱います。
メモリ上でのフィールドのレイアウトを明確にするためoffset設定されているのがポイントです。
2. 1の入力状態に合わせたクラスを定義する
ここは基本的にはVIVE Flowのときと同じです。
1の構造体とフィールド名を合わせているのと、grip系以外は継承元のXRControllerの定義をそのまま使うので、シンプルな状態になっています。
3. アプリ起動時に2のクラスをInputSystemに登録する
ここもほとんどVIVE Flowと同じです。デバイス追加は次の手順で明示的に行うので、デバイス情報とのマッチング条件は不要になっています。
4. 任意のタイミングで2のデバイスをInputSystemに追加する
通常のコントローラー等のデバイスの場合は、デバイスが認識された時点でデバイス情報をもとにInputSystemが内部でデバイスクラスのインスタンスを追加します。
ハンドトラッキングはデバイスとして認識されないため、明示的にインスタンスを追加する必要があります。
今回はハンドトラッキングデバイスを制御するためのコンポーネントを作成し、OnEnableのタイミングで追加するようにしています。
5. ハンドトラッキング情報をもとにInputSystemにデータを発行する
ここまでで、InputSystemがハンドトラッキングの入力状態を受け取る準備ができました。
最後に、PXR_Handから取得したハンドトラッキング情報をもとにHandDeviceStateのインスタンスを用意してInputSytemにデータを発行する処理をHandDeviceSupportに追加します。
これでInputSystem内で適切にデータが処理されてInputActionが更新されXRIまで届くようになります。
動作確認
まずはInputDebugウィンドウでデバイスが登録されているかを確認します。画像のように、クラス定義した通りの情報が表示されています。Formatの値がPCHDとなっており、入力状態を表すHandDeviceStateとの紐付けもうまくいっているようです。

続いて、シーンの適当なオブジェクトにHandDeviceSupportコンポーネントを追加してPXR_Handを設定し、XRIのポインタ操作ができるようにRay Interactor (Action-based)も配置しました。Ray InteractorのInputActionはXRIのデフォルトアセットを設定しています。

これで準備完了なのでビルドして試してみます。
ハンドトラッキングでXRIのRayInteractorが動作していることが確認できました。
これでハンドトラッキングのXRI対応が完成です。
ただ、この状態でハンドコントローラーが起動してトラッキング範囲内にあると、コントローラーとハンドトラッキングの入力が競合してレイの表示位置がおかしくなることがあります。
ハンドトラッキングの入力だけ使用したい場合は、XRIのAction設定をデフォルトのInputActionからハンドトラッキング専用のAction設定に変更する必要がありそうです。
ちなみにPICO 4のパススルー機能と組み合わせると、自分の手でオブジェクトを操作するような体験もできます。
Pico4のパススルーとハンドトラッキングでオブジェクト操作するのやっとできたー。XRInteractionToolkitと繋ぐためにInputSystemの仕組みを結構深掘りした。。。
— ながみね (@KzoNag) 2022年10月24日
オクルージョンは手のモデルにオクルージョン用のシェーダーを適用してる。 pic.twitter.com/YMtV9Yf8Yg
まとめ
長い道のりだった。。。。
今回はVIVE FlowとPICO 4でXR Interaction Toolkitを使いやすくするために拡張してみた話を書きました。
ポイントとしては、以下のようなところかなと思います。
- XR Interaction ToolkitにはDevice-basedとAction-basedがあり、Action-basedのほうが柔軟性・拡張性があり推奨されている
- Action-basedはInputSystemの仕組みを利用しているため、深掘りするためにはInputSystemの理解が必要
- InputSystemのデバイス登録まわりを理解すれば、XRI未対応デバイスやカスタムデバイスでもXRIに対応させることができる
InputSystemをまだあまり使ったことがなく、InputActionで入力を抽象化できるんだよねーくらいの浅い理解から出発したので、デバイスに近い部分がどういった仕組みになっているのかの理解が深まったのは勉強になりました。マルチデバイス対応やパフォーマンス(GCなど)を考慮してこういった作りになってるのかなと想像しています。
理解が深まったとはいえ、細部についてはフワッとした理解のまま進めた部分も多いため、記事中のコードは詳細説明を省いている部分が多いです。一応そのまま動くように書いているつもりですが、試してみてうまくいかないところがあったらゴメンなさい。
XR領域はどんどん新しいデバイスが出てくるので、またおもしろデバイスを入手したらXRI対応を試してみようと思います!
それでは!
参考
ARFoundationでデプスバッファを活用してPeopleOcclusionを実現する
概要
2週間くらい前だったか、UnityのARFoundationでPeopleOcclusionするために数日がんばりました。
思いのほか苦戦したので、せっかくなので公開しようと思い、この週末でプロジェクトを整理してGitHubにて公開しました。
先行事例
PeopleOcclusionの実装方法についてはフォーラムのこちらのスレッドで議論されており、この方法での実装記事もいくつか書かれているようです。
https://forum.unity.com/threads/how-to-setup-people-occlusion.691789/
この方法ではカメラのOnRenderImage関数を使ったポストエフェクト的な手法が取られているのですが、今回のケースではLWRPやURPでも動作させたかったため、別のアプローチとして背景描画と同時にデプスバッファに書き込むという方法で実現しました。
デモ
デプスとステンシル画像をシェーダーでエイっとするとこんなかんじになりました。
使い方
リポジトリのREADMEに書いていますが、カメラ映像を描画しているARCameraBackgroundコンポーネントにカスタムマテリアルをセットし、そのシェーダーにテクスチャを流し込むためにARCameraOcclusionコンポーネントを追加すればOKです。
RenderPipeline対応
これもREADMEに書いていることですが、Legacy/LightWeight/Universalのレンダーパイプラインに対応しています。
各レンダーパイプライン用のシェーダーを用意しているので、ARCameraBackgroundにセットしたカスタムマテリアルを適切なシェーダーにすれば各レンダーパイプラインで動作するはずです。
Legacy/LWRPは動作確認済みですが、Universalは一応用意してるもののちゃんと確認はできてません。以前試したときにURPでARFoundationがうまく動かなかったので。
仕組み
背景描画のタイミングで深度情報をデプスバッファに書き込むというアプローチで実装しています。
用意したシェーダーはARFoundationにデフォルトで用意されている背景描画用のシェーダーをベースにしたもので、デプスを書き込む部分だけ追加しています。
ベースにしているシェーダーは、ARKit XR PluginパッケージのAssets/Shadersフォルダに入っています。
背景描画と同一のタイミングでデプスについても処理することで、背景と同一のUV値をが利用でき回転の向き等の考慮を独自に考えずに済んでいます。
実装のポイントとしては大きく3つ。
1つは、デプス値を書き込むためにフラグメントシェーダーの返り値用の構造体を用意すること。以下のような構造体を作っています。
struct FragmentOutput
{
half4 color : SV_Target;
half depth : SV_Depth;
};
2つ目は、ARKitから取得したデプスの値からデプスバッファ用の値に変換すること。
具体的には以下の部分。depthの計算は、深度から位置を計算すると思われるLinearEyeDepthという関数を参考に逆算して出しています。
// Calculate 0-1 depth value from meter depth value
// Reverse of LinearEyeDepth function in UnityCG.cginc
float depthMeter = tex2D(_textureDepth, texcoord).r;
float depth = (1.0 - _ZBufferParams.w * depthMeter) / (depthMeter * _ZBufferParams.z);
最後に、ステンシルの値を元に計算したデプス値を書き込むべきか判断すること。デプステクスチャで人物領域でない部分の値は0になっています。そのまま使うと距離が0として計算されてしまうので、人物領域の部分だけ計算したデプス値を書き込むようにします。なお、Metalでのデプス値はnear→farで1→0のようなので、人物領域でない部分には0を書き込んで最も遠い位置にあるとみなしています。
ステンシルテクスチャには0か1の値が入ってると思っているのですが、そのまま使うと何故かうまくいかなかったため、step関数を使って0/1の値を作っています。
// Get people segmentation
half stencil = tex2D(_textureStencil, texcoord).r;
stencil = step(1, stencil); // Get 0 or 1
o.depth = depth * stencil; // 0 means far plane
おわりに
レンダリング周りはあまり詳しくないのでデプス値の計算の部分でかなり苦戦しました。環境によってデプス値が0→1だったり1→0だったりするというのも今回調べてて初めて知った。ARKit以外にも対応が必要になったらこの辺りもっとちゃんと理解して書かないといけないだろうなぁ。
あとはARFoundationが実機でしかテストできない&シェーダーのデバッグ方法がよく分からないのコンボでトライ&エラーにめちゃくちゃ時間がかかりました。特にシェーダーのデバッグ方法は詳しい人がいたら教えてほしいです。
最終的にはかなりシンプルな構成になってセットアップも簡単なので、興味がある人はぜひ動かしてみてください。
未来の運動会で作った『かげぴったん』をGitHubで公開しました
だいぶ時間が空いてしまいましたが、2019年3月16-17日に開催された【未来の福岡の運動会】にて制作した『かげぴったん』という種目のUnityプロジェクトとビルド済みパッケージをGitHubで公開しました。
導入方法や遊び方などの詳細は下記リポジトリを参照してください。
https://github.com/KzoNag/Kagepittan
『かげぴったん』の競技風景はコチラ
(犬飼さんのYoutubeより。素晴らしい動画ありがとうございます!)
未来の運動会については渋谷で開催されたときのこちらのページが分かりやすいです。
福岡大会では、1日目と2日目の午前中が種目を作るハッカソンで、2日目の午後に4チーム対抗の運動会が開催されました。
また、ハッカソンでの種目づくりに使用される(かもしれない)ツールを作るためのテックワークショップというのも事前に開催されました。
僕はテックワークショップから参加してベースとなるシルエットシステムを作り、ハッカソンではチームで考えた種目の内容をUnityで実現するところを担当しました。
せっかくなのでテックワークショップから運動会本番までの振り返りを書いておきます。
テックワークショップ
テックワークショップでは参加者みんなでツールのアイデアを出し合い、
面白そうなものに絞った中から各自選んでツールづくりを進めることになりました。
僕は自分で出した↓の案から作ることに。

ツール制作
作ったもの
普段Unityを使ってるので今回もUnityで作りました。
この段階で作ったのがこちら。
画像処理でカメラ画像からシルエット画像を生成し、お題のシルエット画像との差分を数値化してスコアを計算しています。
使ったアセット
画像処理にはOpenCV plus Unityというアセットを使いました。
UnityからOpenCVを使う方法はいくつかあって、日本人作者の方が出しているOpenCV for Unityというアセットが有名かなと思います。(普段は僕もこれを使っています。)
ただ、ちょうどこの時期にOpenCV plus Unityが無料で使えるようになりました。ハッカソンなど後々プロジェクトを公開することを考えると無料アセットを使ったほうが良さそうだなと思ったので、今回は"plus Unity"のほうを使ってみました。
実際、今回プロジェクト公開するにあたり外部アセットはリポジトリから除外していて各自でアセットストアからインポートしてもらう必要があるので、無料アセットを使用したのは良い選択でした。
処理の流れ
シルエット画像を作る方法は、今回はあまり時間が取れなかったので単純な背景差分を取る手法になっています。
以下のような流れです。
- 事前に背景画像を設定
- カメラ画像と背景画像の差分を取る
- グレースケール化
- 2値化して白黒画像に
- 膨張・収縮処理をかけてノイズ除去
アウトプットはこんなかんじ

- カメラ画像
- 背景画像
- シルエット画像
- 3, 5を重ねた結果
- お題の画像
右上の数字がスコアの計算結果です。
ここまでを1日でざっくり作り、テックワークショップのSlackで共有しました。
いくつかアドバイス頂いたのですが、対応する時間が取れなかったこともあり、現場での調整でなんとかする方針にして事前準備はここまでということに。
ただ、この単純な背景差分を取る方法だと、影の部分までシルエットに載ったり、服の色によっては背景として扱われたり、カメラの自動露出調整によってうまく背景が除去できなかったり、かなり不安要素が多い状態でハッカソンに臨むことになってしまいました。。。
運動会ハッカソン
初日の午前中にツール紹介~アイデア出し~チームビルド。
この段階で自作ツールが使われない可能性もあったのですが、運よく興味を持ってもらえてシルエットシステムを使った種目をチームで考えることに。
初日の段階で、お題との一致度を数字じゃなくてバーで表現、一致度が閾値を超えたらお題クリア、クリアしたら次のお題に切り替える、という機能を実装しました。
チームの方々にお題のシルエット画像をたくさん作ってもらい、実際に遊べるかをテストしたのですが、全然気持ちよくプレイできない。お題によって全然クリアできなかったり、一瞬でクリアしちゃったり。。(夜中に原因となるバグを発見!)
あと不安的中でカメラの自動露出調整によって背景除去がうまくいかない問題が多発してしまい困っていたのですが、なんとスタッフの犬飼さんが自動露出調整をオフにできるカメラをビックカメラまで買いに行ってくださるという神対応。これがなかったら種目として成立しなかったと思います。本当にありがとうございました。
そんなこんなで1日目終了の19時の時点ではかなり微妙な出来で、これはマズい、成立しないのでわ、、、と涙目状態でした。
帰宅してから判定処理の見直し、お題を切り替えるたびに判定が厳しくなっていくバグを発見して即刻修正。これでだいぶマシになったので、あとはパラメータ調整でプレイ感をできるだけ改善。そしてチームメンバーやスタッフの方々から頂いていたフィードバックをもとにUI等の見せ方の部分を大幅にいじりました。できるだけのことをやったので1日目は終了。
2日目の午前中にもう一度チームの方々と一緒にテストプレイをしてパラメータ調整、次のお題を表示するのを手動にする変更をギリギリで追加実装したり。最後に直前のリハーサルで、背景をできるだけ綺麗に取れるようにパネルを移動させるなどの対応を決めてハッカソンは終了。1日目と比べるとかなり良くはなっていたのですが、それでもやはり環境に左右される部分が大きいため、うまくいくか非常に不安なまま本番を迎えることになりました。
運動会本番
本当に本番直前までうまくいくか不安で冷や汗をかいていたのですが、いざ始まってみるとシステム的に大きなトラブルも発生せず、チームメンバーが状況に合わせて上手くプレイヤーを誘導してくださり、MCガッキーさんの進行とDJモンチさんの音楽で会場に一体感が生まれ、何より参加した皆さんがものすごく熱中して取り組んでくれて、冒頭の動画のようにクリアするたび歓声があがる大変盛り上がる結果となりました。
上手くいって本当にホッとしました。がんばった甲斐があった・・・!
感想&反省点
種目としては皆さんのおかげで大いに盛り上がってエキサイティングな経験ができました!ありがとうございました!
が、担当したシステムの制作に関しては今回は反省点が多かったです。
まず、ベースの仕組みが環境に左右されやすすぎて、安定した状態を作るのが難しかったこと。今回は、特別な機材を用意しなくても使えるように普通のWebカメラだけで作る選択をしました。ある程度のところまではスムーズに作れても、信頼性を高めるためには画像処理の深い知識やノウハウが必要そうです。KinectやRealSenseを使ってデプス情報を組み合わせるなどしたほうが、より確信を持って進められたかなーと思います。
次に、スケジュール感と「ツール」を作る難しさ。今回テックワークショップに参加して事前にシルエットシステムを作ったわけですが、ちょっと作りが良くなかったと感じています。肝になるシルエット化とスコアリングの仕組みだけ作っておけば、あとは当日になんとかなるだろう、という普段のハッカソン感覚で臨んだものの、初日の夕方頃にある程度完成させるという全体スケジュールには全くハマりませんでいた。自分しか触れない作りだったので自分のプレッシャーも大きかったし、きっとチームメンバーの皆さんにも進捗が見えずヤキモキさせてしまったのではないかと思います。
もっとプリミティブで組み合わせ可能な形式でツールを用意し、ハッカソンではその組み合わせの部分に注力、できる限り追加実装はしない、みたいな感覚が良いのかもしれません。が、言うは易しでこれを実践するのはなかなか難しいのではないかなーとも思います。
スケジュールにハマらなかったことに付随しますが、自分の作業に一杯いっぱいでチームメンバーとすらあまりコミュニケーションが取れなかったのも良くなかったです。。。テックワークショップからハッカソンまで全体的に余裕が無く、ちょっと心がザワつく感があったので、次の機会にはもうちょっと余裕を持てるかんじで臨みたいなと思います。
あと最初テックワークショップに参加したときはARで何かやりたいなーと思ってたんですが、なかなか良い案がまとまらなかったので今度こそはそっち方面で考えたい。
最後に
苦しい部分もありましたが、ただ作って終わりではなく実際に一般の方、特に子どもたちと一緒に遊んでリアクションや楽しそうな顔を見られる機会はそうそうないので、とても為になったし、嬉しかったし、自分自身もすごく楽しめました。
システムが不安定な中で一緒に作り上げてくれたチームの皆さん、多くのアドバイスをくださった岩谷さん・犬飼さんをはじめとするスタッフの皆さん、熱いトークと音楽で盛り上げてくださったMCガッキーさん・DJモンチさん、楽しんでくれた運動会参加者の皆さん、ありがとうございました!!
HoloLens(1)で作ったデモとか作品とかをまとめる
あと数時間で遂にHoloLens2(仮)が発表されるかもしれないので、せっかくなのでこのタイミングでHoloLens(1)で作ったものをまとめておこうと思いました。
試してみた系のデモとか仕事で関わったものとか個人の作品とか色々あるけど、とりあえずツイートを時系列で拾いつつ時期に合わせてYoutube動画とか挟みます。
※最終的に(1)〜(20)になりました。
(1)届いた翌日に開催されたGGJに持って行って作ったゲーム。
プレイヤーにはこんなふうに見えてる。机をつないで小人をスタートからゴールまで導く。各机には小人が待機してて合流すると仲間になる。できるだけたくさんの仲間を連れて制限時間以内にゴールするのが目的。 pic.twitter.com/hvlMNDrc3b
— ながみね (@KzoNag) January 23, 2017
(2)空間にグリッドを表示するやつ。ただラインを引くだけだと無限に広がってカオスだったからSpatialMappingで部屋の中だけ表示されるようにしてたはず。
HoloLensで部屋にグリッド表示。家具の配置とかに便利かも。#HoloLens #HoloLensJP pic.twitter.com/X48xpQzTpd
— ながみね (@KzoNag) January 25, 2017
(3)TangoをHoloLensの6DoF入力デバイスにしてみる。今ならARKit/ARCoreでもある程度できそうですね。
TangoをHoloLensのコントローラーとして使う。HoloLensの認識範囲から外れてもポジショントラッキングできる。文字入力やスクロールもTangoで(これは普通のスマホでもOK#HoloLens #Tango pic.twitter.com/NjzEqTW3Ws
— ながみね (@KzoNag) January 26, 2017
(4)HoloLensで黒を表現したかったやつ。Twitterで黒表現の話になって、透明スクリーンに詳しい、あおめさん(@aomesan147)からアドバイスを頂いて実験してみました。
ホロ越しにiPhoneのカメラで撮った画像です。少し肉眼に近いかな。「黒かな?」ってところが無いんですよね。透明になってくかんじ。黒ソックスみたいにモデルの一部にあるとまた違うのかも? pic.twitter.com/cnlYA4tADh
— ながみね (@KzoNag) January 26, 2017
(5)HoloLensで表示された文字に沿って書くことで綺麗な文字が書ける。と思って試したけど焦点距離が合わないのであんまりイイかんじじゃなかった
文字を書くときにサポートしてくれる。#HoloLensのある暮らし #LifeWithHoloLens pic.twitter.com/7iCkmyhDDl
— ながみね (@KzoNag) February 13, 2017
(6)紙を丸めて筒状にしたら花火が出せるようになるやつ。Vuforiaの円筒形マーカーを使ってる
紙を丸めた筒が花火に。とりあえずパーティクルと音出してみただけだけど、体験すると結構それっぽい気がする。 #HoloLensのある暮らし #LifeWithHoloLens pic.twitter.com/xHRNixUHgE
— ながみね (@KzoNag) February 14, 2017
(7)キューブをポコポコ出して、ジェスチャー操作で重力方向を変えて浮かせたり飛ばしたりする。現実環境を認識してリアルとバーチャルが物理的に干渉できるのがHoloLensの特徴だけど、バーチャル側は物理法則を捻じ曲げることができるので魔法使いになれる。
HoloLensの特徴である現実とバーチャルの物理干渉。バーチャル空間の重力を操作してあげれば魔法使いになれます。 #HoloLens #HoloLensJP pic.twitter.com/m3R2BlwMeq
— ながみね (@KzoNag) February 21, 2017
(8)カメラ映像を取得して現実世界をズームして見れるやつ。ズームすると荒くなるのでこのままだと難しいけど、ディープラーニングを使った超解像?と組み合わせたらどんなかんじになるのかなーとか気になります。
HoloLensのカメラを活用したアプリ例。見てるところを拡大表示。目が悪いのをサポートしてくれるイメージ。HoloLensでルーペだからHoloupeってアプリ名かな #HoloLensのある生活 #LifeWithHoloLens pic.twitter.com/P6b10jVNVh
— ながみね (@KzoNag) February 26, 2017
ちなみにこれはMoguraVRに取り上げて頂いてすごく嬉しかった記憶があります。
HoloLensのカメラで虫眼鏡 物体を拡大表示して見やすく | MoguLive - バーチャルを「楽しむ」ためのエンタメメディア
(9)HoloLensでJoyConを使いたい。このときはスティックの入力がうまくとれなかった。今はどうなんだろう。
とりあえずHoloLensでもJoyConの入力とれたー。Capabilitiesの設定が必要だったことに気づかず結構ハマった。あとスティックの入力がうまく取れてないっぽい。エディタだと正しく取れてるんだけど。 #HoloLens #JoyCon pic.twitter.com/dEZxSVqlfc
— ながみね (@KzoNag) March 11, 2017
(10)上の続き。JoyConで文字入力できるようにした。HoloLensでの文字入力はかなり難しいので、手持ちキーボード的なものが欲しいとずっと思ってる。
HoloLensでJoyConによる文字入力を試す。JoyConはボタンが多くアルファベットを全部割り当てられる(22ボタン+2スティック)。余ったボタンでモード切り替えて大文字、改行、削除などに対応。 #HoloLens #JoyCon pic.twitter.com/a9E3HimBKr
— ながみね (@KzoNag) March 21, 2017
(11)マーカーと組み合わせて空間にアヒルを無限に配置できるやつ。Blenderのハンズオンで作り方を教えてもらったアヒルのモデル。これ以来Blenderちゃんとさわれてない、、、
このあいだの #AR_Fukuoka で作ってた #HoloLens とVuforiaで無限アヒル召喚。これまでのマーカーベースARはカメラとマーカーの相対位置しか分からなかったけど、HoloLensではワールド座標まで決まる。つまりマーカーを「入口」として考えることができる。 pic.twitter.com/9xS7bnibVP
— ながみね (@KzoNag) March 28, 2017
(12)HoloLensのAirTapで「つまむ」ことで操作するボタン。
空間UIにおけるボタンとは?を考えて作ってみたもの。
映画とかだと「空間にディスプレイ的なものがあって指でボタンを押す」という表現が出てくるけど、フィードバックが無いので押した感が出ない。
「つまむ」操作だと自分の指同士が接触するので、押した感を表現できるのでは?というのがコンセプト。
HoloLensで「つまむ」ボタン。つまみ範囲内に来ると色が変わり、つまむと色と形と音でフィードバック。空間上のボタンを「押す」のは感触がなくて難しい。「つまむ」だと指の感触があるのでわかりやすい、かも #HoloLens pic.twitter.com/s6Z3p9qAVU
— ながみね (@KzoNag) May 30, 2017
(13)紙に手書きしたメモをHoloLensで撮影して空間に並べる。アナログの良さとデジタルの良さをミックスしたら良さそう、と思って試したと思う。
手書きメモの空間オブジェクト化。アイデア考えるときは手書きが好きだけど、並べて比較したりは空間に置いたほうが効率いいかも、という思いつき。リアルとバーチャルの良いトコどり、MixedRealityですね。#HoloLens pic.twitter.com/FdzK0boWw0
— ながみね (@KzoNag) June 18, 2017
(14)ハッカソンの運営をしながら作ってたフリック入力キーボード。意外と良かったような記憶がある。このハッカソンにはガチ元さんが来てくれたなぁ。
そういえばこのあいだのXRハッカソンでは運営しながらちょこちょこフリック日本語入力を作って試してた。MRDesignLabsのボタンを改造、拡張してる。ナビゲーション操作でやってるけど意外とちゃんと反応する。 #HoloLens pic.twitter.com/dH1ECTJATn
— ながみね (@KzoNag) June 27, 2017
(15)HoloLensとLeapMotionの組み合わせ。LeapMotionって反応する範囲がどこまでなのか分かりにくいよね、というのを可視化するというのがスタート。緑のラインが反応する領域を表してる。LeapMotionで取ったデータをHoloLensに送ってオクルージョンしてる。ギュってするとキューブが生まれるのはオマケ。
TLでMeetupの情報がいろいろ聞こえてきたから便乗しとこー。突貫なのでオクルージョンは甘いけど。いつか参加したいなー。 #HoloLens #LeapMotion #ぎゅってすると豆腐ができるヤツ pic.twitter.com/44gQr5QMPy
— ながみね (@KzoNag) July 15, 2017
(16)HOLOBUILDER
お仕事で関わったコンテンツ。Unityでの実装部分を担当させていただきました。いろいろ挑戦できてすごく楽しかった。
HoloLensMeetupで太陽企画の伊原さんと一緒にお話もさせてもらいました。
(17)CharacterParticle(パーティクルで文字を出せるアセット)を使いたくて作ったやつ。絵画が喋るマンガみたいな表現とかできそうです。
HoloLensとTwitterを組み合わせてCharacterParticleで表示。現実世界に呟きを垂れ流せます。お店のマネキンがセール情報を呟いたりしてたら良さそう。 #ほとばしる言霊 #HoloLens pic.twitter.com/oO4V5dCpnu
— ながみね (@KzoNag) August 3, 2017
(18)特定のキーワードを喋ると続く言葉をテキスト化&HoloLensのカメラで写真を撮影してTwitterにあげるシステム。(実機でうまくキャプチャできなかったようでエディタでキャプチャしたもの)
調べたこととかをもっとツイートして共有しなきゃな、と思いつつ、なかなかできなかったので、見てるもの&呟いたことを瞬時にツイートできると良いのでは、と思って試した。
HoloLens実機だとうまく録画できないのでエディタ上での挙動。「イエス」というキーワードに反応して、その後の発言をテキスト化&その瞬間の視点をカメラ撮影、それらをツイッターAPIで投稿する。口癖をキーワードにすれば無意識にガンガン連投してくれます(怖 pic.twitter.com/hRjVggrqBq
— ながみね (@KzoNag) December 12, 2017
(19)Boxello
個人的に作ってストアで公開してみたゲーム。一言で表すと立体オセロ。
最大4人の対戦ができるのがポイント。uNET使ってる。
リリースしたときのブログ。
札幌HoloLensミートアップで登壇させて頂いたときにコレの話をしました。
(20)HoloLensでムービングライト?の色を変える。HoloLensからTouchDesignerに色の情報を送って、TouchDesignerがムービングライトを制御してる。リアル側を制御する系。
今日の成果。HoloLensでムービングライト?を動かすやつ。空間に配置してるキューブに触れるとライトがその色に変わる。けどなんかバグってて色が合ってない&謎の回転。 #サンボン #TouchDesigner #HoloLens側はTouchDesigner使ってないけど pic.twitter.com/AJSS5ENbRW
— ながみね (@KzoNag) September 20, 2018
以上。
最初の頃は、どんなことができるだろーというのでいろいろ実験してましたね。最近あんまりできてないからまたやんなきゃな。
他にもいくつかお仕事でHoloLensを扱ったり。SDユニティちゃんのランゲームみたいなのも作ってたけどキャプチャとってなかった。
書いてるあいだに時間が近づいて来た。ここまで書いた時点であと一時間ちょっと。楽しみです!!
Vuforiaでポジショントラッキングする手順とその周辺トピック
アウトプットしなきゃなーと思いつつ、全然ブログ書いてなかった!差し迫らないと書けねぇぇ!
というわけで、はじめてアドベントカレンダーに参加してみました。この記事は AR Advent Calendar 2018 10日目です。
ARアプリを作るためのライブラリにVuforiaというものがあります。マーカータイプのARライブラリとしてご存知の方が多いかと思いますが、実はマーカーレスにも対応しています。
ポジショントラッキングするだけなら非常に簡単なので、Vuforiaでポジショントラッキングを試す方法と、周辺のトピックについて書いてみたいと思います。
Vuforiaとは
VuforiaはPTC社が提供するARプラットフォームです。ARに関する製品をVuforiaブランドとしてまとめたようで、それぞれVuforia Engine, Vuforia Studio, Vuforia Chalkという製品/サービス名が付いています。
Vuforiaのライブラリを組み込んで独自のARアプリを作るときは、Vuforia Engineのサービスを使うことになりますが、本記事では簡潔に"Vuforia"と書いています。
VuforiaはiOS/Android/UWPのマルチプラットフォームで動作し、ネイティブまたはUnityを使って実装します。元々は画像ベースのマーカーARを作るライブラリだったのでそのイメージが強いかもしれませんが、2017年末ごろにリリースされたVuforia7ではGroundPlane(平面検出)などのマーカーレスARを実現する機能も追加されています。
また、Unity2017.2からはUnityエディタに統合されてより簡単に使えるようになっています。
ポジショントラッキングとは
ポジショントラッキングは、空間における対象の位置・姿勢をトラッキングする機能です。6DoFというやつですね。端末がどれくらい動いてどっちを向いたのかが分かるといったかんじです。
マーカーレスARで、3Dオブジェクトを現実に召喚→まわりこんで観察する、みたいなことをするには、ポジショントラッキングが必要になります。(というか基本的にマーカーレスARにはポジショントラッキングが必須な気がしますね。)
マーカーレスで地面を検出してオブジェクトを表示したりするのにはARKitやARCoreを使うイメージがありますが、前述の通りVuforiaにもマーカーレスARの機能が追加されており、ポジショントラッキングができます。
ポジショントラッキングを試す最短手順
Unity2017.2からVuforiaライブラリがUnityに統合されて、PlayerSettingsでポチッと設定するだけで使えるようになりました。画像マーカーを使う場合にはウェブ上でライセンスを取得したりマーカーを登録したりする手順が発生するのですが、ポジショントラッキングを使うだけなら非常に簡単な手順でできるので、その手順を紹介します。
環境
Unityのバージョンは 2018.2.18f1 を使用しています。UnityでVuforiaを使用するには、Unityをインストールする際の追加コンポーネントを選択する画面で、Vuforia Augumented Reality Supportにチェックを入れておく必要があります。

対応端末
Vuforia Fusion Supported Devices
- 上のページの表にある「Ground Plane」対応の端末
- もしくはページ下部にある「Ground Plane Minimum Requirements」に載っている要件を満たす端末
(GroundPlaneとあるけどポジショントラッキングも同じだと思う、たぶん)
手順
Unityを起動して適当なプロジェクトを作成したら、まずはPlayerSettingsを開いてVuforiaを有効にしましょう。
PlayerSettings > XR Settings > Vuforia Augumented Reality
にチェックを入れるだけでOKです。

続いて、Vuforia用のカメラオブジェクトをシーンに作成しましょう。
CreateメニューからVuforia > AR Cameraを選択します。

Vuforia関連のアセットをインポートするか聞かれるので、Importボタンを押してインポートしましょう。

これでARCameraを配置することができました。
もともとあったMain Cameraは必要ないので、削除しておきます。

ここまではVuforiaのどの機能を使用する場合でも共通して必要な手順です。
ここからが本番です。ポジショントラッキングを有効にするための作業をしていきましょう。
ARCameraオブジェクトについているVuforia Behaviourの「Open Vuforia configuration」から、Vuforiaの設定ウィンドウを開きましょう。
Device TrackerのTrack Device Pose にチェックを入れると、Tracking modeを選択するドロップダウンが出てくるので、POSITIONALを選択します。

はい、これで準備完了です。たったこれだけで、ポジショントラッキングを使用することができます。簡単ですね!!
ただ、これだけだとちゃんとトラッキングできているのか分からないので、確認用に豆腐(Cube)でも配置してみましょう。
アプリを起動したときの端末の位置が原点(0, 0, 0)になるため、Cubeのポジションを(X,Y, Z) = (0, 0, 2)としてあげると、アプリ起動地点から2メートル先に1辺1メートルの巨大豆腐が出現することになります。

さて、ではビルドして試してみたいと思います。今回はiOSでビルドしてみます。
ここで1点注意が必要なのが、iOSでデバイスのカメラを使用する場合には、PlayerSettingsのOtherSettingsにあるCamera Usage Descriptionの項目にカメラを使用する目的を入力する必要があります。このテキストは初回起動時にユーザーの許可を求めるアラートの文言として使用されます。
どこかのバージョンから自動的にデフォルトのテキストを設定してくれるようになったのですが、たしか以前は自分で設定しないといけなかったような記憶があります。
これを入力しないと起動時にそのままクラッシュして原因不明で泣くことになるので、古いバージョンで試している場合は確認しておきましょう。

ビルドして起動するとこのようになります。
豆腐が現実空間に出現し、デバイスを持って動きまわっても豆腐は同じ場所に留まり続けていますね。ポジショントラッキングが上手くいっていることが確認できました!

手順のまとめ
手順をまとめると以下のようになります。
- PlayerSettings > XR Settings > Vuforia Augumented Realityを有効にする
- ARCameraを配置する(Main Cameraは削除)
- Vuforia Configuration > Device Tracker > Track Device Poseを有効に
- Vuforia Configuration > Device Tracker > Tracking modeをPOSITIONALに
GroundPlaneとMidAir
今回は確認のためのCubeは単純にシーンに配置しただけでしたが、マーカーレスでオブジェクトを空間に固定して配置するためのオブジェクトして、Ground Plane StageとMid Air Stageというものが用意されています。
Ground Plane Stageは平面に対して、Mid Air Stageは空中に対してオブジェクトを固定します。(使用方法は公式のドキュメントに書いているのでそちらを今回は割愛します。)
単純にシーンにオブジェクトを配置することとの違いはまだしっかり理解できていないのですが、どちらのオブジェクトにもAnchorBehaviourというコンポーネントが付いています。
GroundPlaneの解説 でAnchorについて言及されており、6DoFで追跡されるポイントだというようなことが書いてあるので、カメラ画像やセンサー情報を用いて現実空間からズレが発生しづらいように何かしらの処理が行われるのかもしれません。
また、 VuforiaFusionの解説のRelocalizationの項目にもanchorが出てきているので、このあたりにも関係してきそうです。
マーカーとの併用 、ExtendedTracking
通常のマーカータイプのARではマーカーがカメラから見えなくなるとトラッキングできませんが、Vuforiaにはマーカー位置を推測してトラッキングを継続するExtendedTrackingという機能があります。
以前から使えていた機能ではあるのですが、あまり精度は良くない印象でした。しかし、現行バージョンではExtendTrackingにポジショントラッキングの情報が利用されるようになり、使い勝手が良くなりました。
マーカーをAR空間の入り口として設定し、そこから空間全体を使ったコンテンツに展開する、というような使い方ができます。
また、複数人が同一空間で体験するようなマルチプレイARの場合は、各ユーザーに共通した座標系を用意する必要があるので、現実空間に固定したマーカーを認識して座標系の原点とすることで、共通したAR空間を構築することができます。
この方法で、以下のようなマルチプレイARを実現することができました。
デジタルアート展で展示する作品、知り合いに手伝ってもらって4人プレイのテスト中〜。ポイントは犬の影。プロジェクターでリアル側に描画してる。普段は床に影だけ映っていて、デバイスを通すと犬の姿が見える、という仕掛け。もちろん全プレイヤー同じ世界が見えてる。 pic.twitter.com/SVwMzGTydT
— ながみね (@KzoNag) July 27, 2018
序盤で映っているロゴが共通座標系の原点になるマーカーです。
マーカー認識後は共通座標系での位置・姿勢を各ユーザー同士で同期し続けています。
ちなみにツイートにもありますが、このコンテンツはホストPCとも情報を共有しており、床に映っている犬の影はプロジェクターで現実環境に投影しています。
共通座標系で正しく位置・姿勢を正確に同期できていると、端末でレンダリングしている犬とプロジェクターで投影している影の位置がぴったり合います。
この動画はかなり良い状態で撮れましたが、実際は環境や状況によってズレてくるので、コンテンツのフローとしてマーカー認識を挟むことで位置を補正しています。
Vuforia FusionとARKit/ARCore
GroundPlaneの項目でさらっとVuforia Fusionという言葉が出てきました。
これは特定の機能というわけではなくて、Vuforiaの各機能のベースとなる仕組みの話です。
カメラ・センサーの能力やARKit/ARCoreといったフレームワークの対応状況など、デバイスごとに異なる様々な要素をVuforiaEngineが検知して組み合わせることで、そのデバイスが発揮しうる最適なAR体験を実現してくれるよ、みたいなことだと理解しています。
ポジショントラッキングに関して言えば、ARKit対応デバイスであれば内部的にARKitを使うし、非対応であれば独自のトラッキング処理を使う、ということになります。ARCoreについても同様です。
ただし、VuforiaFusion自体も対応端末が決まっているため、すべての端末で動作するというわけではないようです。(対応端末の一覧)
理想としては、Vuforiaを使えばARKit/ARCoreを意識しなくても内部的にイイかんじに使ってくれて最適なAR体験ができます、マルチプラットフォームで!というところを目指しているのかもしれません。
今のところは、光源の推定や環境の映り込みなどはVuforiaではできないので、こういった機能が必要な場合はそれぞれのフレームワークを使って実装する必要がありそうです。
ライセンスキーについて
前述のポジショントラッキングの手順の説明で、おや?と思った方がいるかもしれませんが、通常、Vuforiaを使用するためはライセンスキーを取得してVuforiaConfigurationに設定する必要があります。
試用や開発中に利用するDevelopment License Keyは無料で取得でき、リリースする場合は形態や企業規模に応じてClassic, Cloud, Proの有料ライセンスを購入します。
ところが、今回の記事を書くにあたりドキュメントをいろいろ眺めていたところ、Pricing and Licensing Options の「Can I create an app at no charge?」の項目に、
You can also deploy Unity apps that take advantage of our Ground Plane, Device Tracker and Stereo Rendering features for free without a License Key.
と載っているのを見つけました。
なんと、Unityでマーカーレスの機能を使う場合はライセンスキーはいらないとのこと。
ホンマかいなと思ってライセンスキーを入力せずに試してみたのが前述の手順なのですが、特に問題なく動かすことができました。
Unityだけで完結するので、試す分には非常にお手軽ですね。
その下に
Once you intend to commercialize your app, you should review the available licensing options.
と書いてあるので、商用としてアプリをリリースする場合はやはりライセンスを購入する必要がありそうです。
ライセンスに関してはアプリの形態や使用する機能によっても異なるので、リリースする場合には一度公式に問い合わせるのが良いかなと思います。
最後に
ARKit/ARCoreの名前をよく聞く昨今ですが、何かARのアイデアを思いついたとき、 パッとデモを作ってみる分にはVuforiaもお手軽なのでおすすめです。
Nianticのneonがやりたいけど行けなかったから作ってみたデモもVuforiaでマーカーとポジショントラッキングを組み合わせています。
昨日は #福岡XR部 の実験会ということで、最近作ってみたマルチプレイARのデモを複数人で試してもらいました!10端末くらい接続して軽く弾を発射するくらいであればスムーズに動いてて、連射してオブジェクトが増えると通信が詰まるような印象 pic.twitter.com/nogtE9GUCi
— ながみね (@KzoNag) October 29, 2018
他にも作ってみたデモなどをモーメントにまとめているので、よかったら見てみてください。(AR関係ないのもあるけど)
HoloLensアプリのリリース日設定を間違って購入できなくなってた
起きたこと
先日、はじめてのHoloLensアプリをストアで公開しました。
有料で7日間の無料試用版が使える設定にしてリリースしたところ、上記事にチラッと書いた通り試用版をDLした後に有料版購入の導線がありませんでした。
試用期限が終わったときにストアに誘導されるのかなーと思って数日放置していたところ、
自作HoloLensアプリの無料試用期間が終わったっぽくてアプリが起動しなくなったので、購入できるかと思ってストア開いたら何のボタンも出なくなってた。。。
— ながみね (@KzoNag) 2018年5月10日
もし同じ状況になってる人いたらゴメンなさい・・・!問い合わせているので解決できたらまた報告します! pic.twitter.com/F0RKBSgJqK
ということになり、一度試用期限が切れると購入も再DLもできない状態になってしまいました。
原因
サポートに問い合わせてみたところ、リリース日の設定が未来に設定されているためだという回答を頂きました。
HoloLensアプリを申請する際いくつか日程を設定できるのですが、今回は下記の項目を設定していました。(画像は現在の正しい設定)



このうち、「スケジュール」というのがストアで購入可能になる日程の設定のようで、ここに間違って未来の日程を入れてしまっていました。
「申請を送信して公開する」ですぐに公開する設定にしていても、「スケジュール」で日程が指定されているとそちらが優先されるようです。
さらに今回わかりづらかったのは、「無料試用版」を「できるだけ早く公開」にしており、試用版のDLだけはできるようになっていたことです。
これにより、問題なくリリースされたと勘違いしてしまいました。
解決方法
「スケジュール」のリリース設定を「できるだけ早く」に変更してもう一度申請したところ、購入できるようになりました。
無料試用版をインストールした状態でストアを見ると下画像のようになっています。
また、検索可能になるのもリリース日設定が使われるようで、今回の問題を解決したと同時に検索でも出てくるようになりました。

参考ページなど
日程等の設定についてはこのあたりに書いてます。
アプリの価格と使用可能状況の設定 - UWP app developer | Microsoft Docs
無料試用版の挙動についてはここに書いてました。
アプリの試用版の実装 - UWP app developer | Microsoft Docs
試用期限が切れた場合は
ユーザーがアプリを起動する前に試用ライセンスが期限切れになった場合、アプリは起動しません。 ユーザーには、ストアからそのアプリを購入できることを伝えるダイアログ ボックスが表示されます。
とあります。今回の場合はアプリが起動しないだけで、ダイアログは出ませんでした。
正しくリリースされて購入できる状態になっているとダイアログが出るのかなと予想しています。
まとめ
購入できない状態になっていた原因と解決策でした。
先行して申請しておいて良きタイミングで手動で公開する、みたいなことはモバイルアプリでもやったりするんですが、Windowストアアプリは項目が多いので設定漏れがないように注意する必要がありそうです。
試用期間が切れてアプリが起動しない&ストア誘導も無しだと、そのままアプリ削除&「起動しません」でレビューされそうで、かなり怖いなと思いました。
今後は気をつけます!
