読者です 読者をやめる 読者になる 読者になる

自習室

こもります

HoloToolkit-Unity の InputManager の使い方

はじめに

HoloLens を入手して楽しそうなアプリを一通り試して、Academy をやってみたりしてそろそろ自分でアプリを作ってみようかなというところなのですが、ちょっと一息ついて便利な HoloToolkit-Unity 様を調査してみようと思いました。

Academy では、3分クッキング的と言うか「これとこれを足して、ここだけ手作業ね☆」 みたいな感じであまり頭に入らなかった + HoloToolkit-Unity はAcademy でやっていることをほぼラップして使いやすくしてくれているようだったので、HoloToolkit-Unity を実際に触りながら多少試行錯誤的に調べてみた内容をまとめてみます。

HoloLensCamera の次に、HoloLens開発をしていたら間違いなく使うだろう、 InputManager について、本記事ではまとめたいと思います。

InputManager の概要

ソースコードInput/Readme.md に、 InputManager の概説がまとめてあります。 基本的なとこを抜き出すと

github.com

Scripts that leverage HoloLens input features namely Gaze, Gesture and Voice.
This contains a fully-featured input module, which allows you to handle various types of input and send them to any game object being currently gazed at, or any fallback object. It also includes a cursor similar to the HoloLens shell cursor that fully leverages the Unity’s animation system.

HoloLens のインプット機能(すなわち Gaze, Gesture, Voice) を活用するためのスクリプト
各種インプットをハンドルして、注視しているオブジェクトに対しそれらインプットを送ります。(注視対象がない場合はフォールバックのターゲットに送ります) また、HoloLens標準と似た挙動をするカーソルも用意しています。

InputManager を使うと、視線、ジェスチャ、音声コマンドを使えるようになるし、視線カーソルも使えるようになる、ってことですね。なんて素敵!

内容

多くの部分は先人達が探索して下さってますので、この記事ではそのまとめをしつつ、説明があまりなかった辺りを調査してみた結果をまとめます。

  • HoloToolkit-Unity の基本的な使い方
  • InputManager の基本的な使い方
  • InputManager の使い方の少しだけ詳細
  • HandDraggable の使い方
  • SpeechInputManager の使い方
  • InputManager が他にやっていること

HoloToolkit-Unity の基本的な使い方

大前提として。 @kaorun55 大先生がまとめてくださっています。間違いなし。

docs.com

InputManager の基本的な使い方

@noshipu さんがまとめてくださっています。こちらの記事では、InputManager がさばくイベントのうち、 FocusedObjects に対するイベントについてに説明されています。視線を向けた対象にタップや音声コマンドなどを紐付ける方法についてです。

noshipu.hateblo.jp

InputManager のやっていること少しだけ詳細

多くの場合は、@noshipu さんのまとめて下さっている情報で足りると思うのですが、せっかくなのでもう少し InputManager.cs を読んでみて、中でやっていることをざっくりと調べてみました。

InputManager が管理するインプットのハンドラは大まかに5種類
GlobalListeners いかなるときも呼ばれる。カーソルの状態を切り替えたりするのに使われている
ModalInputStack FocusedObjectsに先んじて呼ばれる。ある特定のモード(例えばドラッグ中)に入っているときに処理される
FocusedObjects 上記で @noshipu さんが説明してくださっている内容。専用のinterfaceを実装することで、ゲームオブジェクトを注視した状態でクリックや音声コマンドなどを入れることができる
UnityUIPointerEvent uGUIで消費する。uGUIを置くだけで使えるので便利
FallbackInputStack ModalにもFocusedObjectsにもUnityUIにも引っかからなかった場合に呼ばれる。どんな場所でも何かしら特定のインタラクションが起きたこと自体を拾いたい場合に使う
GloblListeners の使い方

ざっくり読んでみたところ、HoloToolkit-Unityとして提供されている中では、GlobalListeners はカーソルの状態制御にのみ利用されています。(オブジェクトの注視状態に関わらず)手の上げ下げというインプットを受けてカーソルの状態を変えたりしています。

それ以外の使い出としては、たとえば 「リスナーを備えた対象物があってもなくてもとにかくタップした回数を数えたい」 みたいなときには、以下の様なスクリプトを作って、空のオブジェクトに貼り付けると可能です。

using UnityEngine;
using HoloToolkit.Unity.InputModule;

namespace HoloToolkit.Unity
{
    public class GlobalInputListener : Singleton<GlobalInputListener>, IInputClickHandler
    {
        public void OnInputClicked(InputClickedEventData eventData)
        {
            Debug.Log("Call Global Listener");
            // ここでなんか数字をカウントアップしたり。
        }

        void Start()
        {
            InputManager.Instance.AddGlobalListener(gameObject);
        }
    }
}

GlobalListener の解除用に、 InputManager.Instance.RemoveGlobalListener() と言う関数も用意されています。

ModalInputStack の使い方

ModalInputStackHandDraggable.cs 中でドラッグでの consume にのみ使われているようでした。 HandDraggable.cs をちょっと改良すると、つまんでドラッグする事で物体を回転させるスクリプトも簡単に書けそうです。そんなときに ModalInputStack が使えるでしょう。

HoloToolkit-Unity/HandDraggable.cs at master · Microsoft/HoloToolkit-Unity · GitHub

ModalInputStack へのリスナーの登録/解除関数は以下です。

  • 一つ追加: InputManager.Instance.Push()
  • 一つ解除: InputManager.Instance.Pop()
  • 全部解除: InputManager.Instance.Clear()

ModalInput を利用するには、そのモードへの入り・終わりを定義する必要があるので、上記の追加・解除関数をモードの入り終わりに呼ぶ事になります。その辺は HandDraggable.cs を読むと何となく分かります。

UnityUI の使い方

通常通り GUIを作って、WorldSpace にするだけでOKです。特定の interface 等の実装は必要ありません。

そういえば、HoloLens で OnScreen な GUI を作るのってできないっすね。(カーソル = ディスプレイ中心、なので)

FallbackInputStack の使い方

FocusedObjects のように実体があって collision を持つゲームオブジェクトが、タップ等のイベントを consume しなかった場合、FallbackInputStack にハンドラを登録しておくことで、そいつが受け取ってくれるようになります。フォールバックですね。

InputManager には PushFallbackInputHandler という、フォールバックのハンドラを登録するための関数が用意されているのでそれを用います。たとえば下記のようなスクリプトを用意して、空のオブジェクトにアタッチしておくと、@noshipu さんの記事で扱った手順で登録されたゲームオブジェクトのいずれにも視線を向けずに (つまり空振りの) タップしたときに限り、「fallback input」とログが出ます。

using UnityEngine;
using HoloToolkit.Unity.InputModule;

namespace HoloToolkit.Unity
{
    public class FallbackInputManager : Singleton<FallbackInputManager>, IInputClickHandler
    {
        public void OnInputClicked(InputClickedEventData eventData)
        {
            Debug.Log("fallback input");
            // はずれ!って表示したりとか。
        }

        void Start()
        {
            InputManager.Instance.PushFallbackInputHandler(gameObject);
        }
    }
}

HandDraggable の使い方

詳しくはこちらの記事で説明されています。オブジェクトに HandDraggable.cs をくっつけたら、手でつかめます、以上。

matatabi-ux.hateblo.jp

SpeechInputManager の使い方

FocusedObjects で消費できるインプットイベントのうち、speech に関しては、まずそれが認識対象のワードである(意図のある入力操作である)、ということを事前に登録していないことには、HoloLensも認識のしようがありません。それを司るのが SpeechInputManager.cs です。使い方は先程の @noshipu さんの記事にあります。

KeywordManager との住み分け

SpeechInputManager + ISpeechHandler と似た機能を提供する KeywordManager というのがいます。 KeywordManager の使い方に関しては、こちらの記事が詳しく説明してくださっています

zuq9nn.blogspot.jp

思想の違い、って感じなのですが、 SpeechInputManager + ISpeechHandler では、ISpeechHandler を実装した スクリプトをゲームオブジェクトにアタッチすることで、そのオブジェクトを注視している際にイベントを発行(音声コマンドを言う)すると、そのゲームオブジェクトが音声に応じて反応させることができるのに対し、KeywordManager の場合、gazeとは関係なく、音声コマンドと物や処理を一対一で対応付けていくことができるようになっています。

InputManager が他にやっていること

InputManager.prefab には、(細かいことをしない限りは)我々が直接触らないいくつかのスクリプトがアタッチされていますが、ざっくりと以下の様な感じになっています

f:id:AMANE:20170419235801p:plain

InputManager にアタッチされているスクリプト

GazeManager 結構重要。視線に関して色々情報がとれる。後述
GazeStabilizer 視線情報のスタビライズ
StabilizationPlaneModifier ここがよく分からないのですが、空間中に平面を仮定してその上で視線座標を動かすことで、視線をスタイビライズするような事をしている、、のかな。このページにそれっぽいことが書いてある

InputManager の子

RawInteractionSource 手の検出などプリミティブなイベントの検出をし、 InputManager に対してイベントを上げる
EditorHandsInput Editor実行時にジェスチャをエミュレートする。個人的にはあまり使い出がないと感じている
GesturesInput HoloLens の基本API群である UnityEngine.VR.WSA.Input に含まれる GestureRecognizer のラッパで、InputManager に対して各種 input イベントを上げてくる
GazeManager の便利メンバ
  • GazeManager.Instance.HitObject - 視線が当たっているゲームオブジェクトへの参照
  • GazeManager.Instance.HitPosition - 視線が当たっている衝突点の座標
  • GazeManager.Instance.HitInfo - 上二つを含む、RaycastHit 情報全部
  • GazeManager.Instance.IsGazingAtObject - Raycast 対象にしたレイヤー中に含まれて居る物体に当たっているか否か。
  • GazeManager.Instance.GazeOrigin - 起動時を原点とした視点(頭部)位置
  • GazeManager.Instance.GazeNormal - 視線方向

あたり。使える。

最後に

便利に使わせていただこうと思います。

初めに挙げた Input/Readme.md 中に、以下の様な記述があって、今後どのように WindowsHolographic もとい、Windows Mixed Reality が進化していくのかわくわくします。

and new input sources can be created to support different input devices.
The focus can be triggered by the user’s gaze or any other gaze source.
Currently, that gaze is always coming from the GazeManager class, but this could be extended to support multiple gaze sources if the need arises.

デザイン - 直感的でないものを直感的にする

直感や慣習に任せていると、自然発生的なスピード・可能性でしか物事が進展しない。また、慣習の敷居に可能性が負けてしまう。科学は整然とした理論を持って直感や慣習を排することで、可能性の敷居を超え、スピードを上げる。

しかし科学は「そうであるはずだからそうする」という情熱を持ちながら努力を続けないと実効的な成果が上がらないことが多い。限られた人々の中だけでもてはやされるものになりがちで続かない。それはしばしば、直感や慣習に反していることがあるからである。言い換えると、多くの人によって・無意識に・継続的に体験を続けるために、直感や慣習は大きな駆動力となる。

科学を社会に着地させる際に、それが人々の直感や慣習にあっていれば、可能性の敷居を超えながら、スピードも早く、しかし自然発生的に多くの人に伝播し継続される。こういうことを可能にするのが「デザイン」の仕事なのかなーと思う。

人や社会のことを知り、直感的でないものを直感的にすること。新しい慣習を創ること。科学と人の接点にあり敷居をまたぐ助けとなるもの。僕の思うデザインってそういうもの。


触り心地や佇まいの観点から「そこにあること、手に触れること」の継続価値を最大化するデザイン、の話もあるけど、本文をシンプルにしたかったのでここでは割愛。

Windows の openFrameworks でまともに動画再生の出来る ofxDSHapVideoPlayer を利用する (追記あり)

Mac だと通常の ofVideoPlayer でもそこそこ動画再生出来るのですが、 Windows だと、数十秒の HD 動画を再生するのもろくに出来ません。がたがたしたり、止まったりします。

oF コミュニティは基本 Mac な雰囲気なのでこの件は3年前に一度諦めていたのですが、どうしても Windows + oF で動画再生をしたかったので、改めて色んな物を調べてみたのですが、 ofxDSHapVideoPlayer が一番お手軽に使えそうだったので、簡単に経過と使い方をまとめておきます。

候補

  • ofVideoPlayer
  • ofxHapPlayer
  • ofxDSHapVideoPlayer
  • ofxWMFVideolayer(追記)

ofVideoPlayer

冒頭で述べたとおり使い物になりません。

ofxHapPlayer

GitHub にも記述がありますように、どうやら VS向け0.9には対応していないようです。GitHubに上がっている物をそのまま突っ込むとビルドも通らなかったので、ちょっとコードを弄って無理矢理動かしてみたのですが、ビルドが通り起動は出来ても動画は表示されませんでした。

また、0.84 でもビルドが通りませんでした。

ここを深追いするのはやめにしました。

ofxDSHapVideoPlayer

以下の通りでちゃんと使えることがわかったので、利用する事にします。FullHD の動画も、結構長い動画も、サクサク再生出来ます。

ofxWMFVideolayer(追記)

はじめ、 ofxDSHapVideoPlayer の紹介と、Hapへのエンコードの仕方だけの記事にしようと思っていたのですが、追加で ofxWMFVideolayer も試してみたところ、普通に動きました。この記事でこの後、 Hapは動画サイズがでかくなるからだるい という内容を書いていますが、 ofxWMFVideolayer なら通常の H264 .mp4 もそのまま再生出来るので、通常の利用法ならこちらの方が良さそうな気配です。(あーれー)

ofxWMFVideolayer の問題点

ただし、 Github 記載がありますように NVIDIA を想定して作られているらしく、Compatibility に問題があるようです。 下に記載した私の作業環境ではうごきました。

また、現状の ofxWMFVideolayer は、 ofBaseVideoPlayer を継承する形では実装されておらず、 getPixels() 関数や getTexture() 関数が実装されていません。この辺りが問題になる方は、 ofxDSHapVideoPlayer を利用した方が良いかも知れません。

Hap 動画の容量デカすぎ問題

Hap ではデコードのスピードを重視するために、ビデオデータの容量が通常の H264 mp4 の20倍程度のサイズになります。そこだけが問題です。たとえば、30秒程度の動画が300MB近くあったりします。大問題なのですが、今回はそれが問題にならない人向け、と言うことでここから先おつきあい下さい。

使い方

  1. Windows に codec をいれる
  2. Adobe Media Encoder でエンコードする
  3. ofxHapPlayer を oF に組み込む

作業環境

- Windows 8.1
- GIGABYTE Brix Intel Core i7-3537U @ 2.50 GHz
- oF (for Visual Studio) v0.9.7
- Visual Studio Community 2015
- Adobe Media Encoder CS5.5

1. Windows に HAP For Direct Show codec をいれる

ここでインストールされるものは再生のためだけはなく、続くエンコーダでも利用されます。

2. Adobe Media Encoder でエンコードする

ffmpeg に挫折

本当は ffmpeg を設定したら狙い通りの hap がエンコード出来ますよ! という記事にしたかったのですが、色々トライして挫折しました。

一方で、上記の codec をインストールした時点で、 Adobe Media Encoder で Hap エンコードが可能になったので、もうそちらで済ませてしまうことにしました。 Adobe 使えない人にはごめんなさい。

Media Encoder での手順

使っているのは CS5.5 の Media Encoder です

  • 形式で Microsoft AVI を選ぶ
  • 「ビデオコーデック」の中から Hap を選ぶ
  • 必要なら「コーデック設定」から最上位画質を選んだりする。私は通常のままで充分。
  • 幅・高さ・フレームレート・縦横比 などを決める
  • フィールドタイプ はプログレッシブ

f:id:AMANE:20161218211530p:plain

3. ofxDSHapVideoPlayer を oF に組み込む

最後に

解像度の多きな動画もサクサク再生出来て、自分のやりたかったことはさくっと実現できて良かったなーなのですが、動画のサイズが爆発するので、長時間の動画再生には向いていません。用法容量を守り正しくお使い下さい。

追記 → ofxWMFVideolayer もある

途中に書き加えましたが、 ofxWMFVideolayer でも普通に Full HD 30p, 尺の長い動画が安定して再生出来ました。この記事は、Hap のための個人的なメモとして残しておこうと思います(笑)

noisejs の TypeScript 型定義ファイルを作成し Contribute してみた

なぜしたか

Create.js を TypeScript で書くことがあったのですが、その中で perlin/simplex noise を使いたくなり、それももちろん TypeScript で書きたいなーとなりました。

bower/npm で手に入る perlin/simplex noise の javascript 実装として GitHub - xixixao/noisejs: Javascript 2D Perlin & Simplex noise functions がありますが、意外にも型定義ファイルがありませんでした。なので作成しました。(コンストラクタ含め関数6つだったので^^)

最近 TypeScript にぞっこんなので、愛を示すためにコントリビュートしてみたくなりました。

完成品はこちら

github.com

以下のコマンドで取ってこれます(感動)

$ tsd install noisejs --save

.d.ts ファイルの作り方調査

まずは vvakame さんのこの記事を参考に。 vvakame さんの溢れる人徳により、とても気軽にコントリビュートできそうな気がしてきます。

qiita.com

また、具体的な作業も含めてまとめて下さっている方もいました。こちらも大変参考になりました

typescriptの定義ファイル(d.ts)を実際にDefinitelyTypedにPullRequestしてみた – 押入れ工房 – Oscillate Cobalt

他の型定義ファイルを参考にする

具体的なコードの書き方は、よくお世話になっていて使い方を知っており、コード量もあまり長くない、以下の二つを参考にしてみました。

jsdoc 対応

/**
   * [function description]
   * @param  {number} x [description]
   * @return {number}   [description]
   */

の形式の説明を、クラス/関数毎につけておきます。 atom.io エディタを使っているのですが、 docblockr を使うとお手軽でした。

テストコード

先の vvakame さんの記事中に

hoge.d.tsという型定義ファイルを作った場合、hoge-tests.tsというファイルを作成し、hoge.d.tsの利用例を書いてください。
hoge-tests.tsが"動作"するコードである必要はありません。コンパイルが通ることが確認できればよいです。
ようするに、pull request出す前に tsc --noImplicitAny hoge/hoge.d.ts と tsc --noImplicitAny hoge/hoge-tests.ts が通ることを確認しましょう。

とあります。先ほどの二つのライブラリの -tests.ts ファイルを見てみたところ、関数を順に呼ぶだけのシンプルなテストコードとなっていたので、それに準ずることとします→こちら

実際にテストしてみる

/// <reference path="./typings/noisejs/noisejd.d.ts/> を各 .ts ファイルのヘッダに入れることで定義ファイルが使える様になるのはもちろん確認した上で、恥ずかしくないようしっかりとテストをしておきたいです。

DefinitelyTyped プロジェクトのテストスクリプト実行 (怪しい)

# プロジェクトに移動
$ cd DefinitelyTyped

# テスト等に必要なパッケージをインストール
$ npm install

# テスト実行
$ npm test

これをやってみたところ、

-----------------------------------------------------------------------------
 Queued for testing
-----------------------------------------------------------------------------
noisejs/noisejs-tests.ts
noisejs/noisejs.d.ts

# 中略

-----------------------------------------------------------------------------
 Total
-----------------------------------------------------------------------------
 Elapsed time    : ~3.526 seconds (3.526s)
 Syntax error    : 0.00% (0/1)
 Failed tests    : 0.00% (0/1)
 Invalid header  : 0.00% (0/1)
 Without tests   : 0.00% (0/1)
-----------------------------------------------------------------------------

という感じの出力で、問題がなさそうです。

いや、本当か?と思って、わざと .d.ts コードに間違いを仕込んで見たりしたのですが、やはり問題無くテストが通った風になります。私のやり方が間違っている気がします。

node.js の require で確認する

CommonJS の module の仕組みがよくわからないまま .d.ts を書いていて不安なので、一応確認しておこうかな、と。

npm から noisejs を引っ張ってきて、

$ npm install noisejs

実際にnode.jsのスクリプト中で呼び出してみます

import noisejs = require('noirejs');
// 中略
var noisejs: Noise = new noisejs(Math.random());
// 後略

的なコードを node で実行したところ、ちゃんと動いたので、大丈夫そうです。とりあえずこれで CommonJS 的には OK っぽいので、良いことにします。

プルリクエストを出してみる

  1. GitHub 上で DefinitelyTyped/DefinitelyTyped を Fork して
  2. ローカルに clone し、
  3. 上で作成した noisejs.d.ts noisels-tests.ts を含む noisejs フォルダを追加して
  4. commitし、
  5. 自分のリモート(GitHub) に Push して
  6. そこで "New pull request" をクリック
  7. わかりやすいコメントを書いて、pull request を作成

Pull request 後のやりとりはこちらに。なんとも軽快。

github.com

これでコントリビュートが完了し、他の型定義ファイルと同様、 tsd install noisejs --save コマンドで取ってこれるようになりました。やったー。

オープンソースへのコミットはこれが初体験でした。結構責任が生じるので緊張しましたが、恥ずかしいことにならないよう勉強が出来たので良かったです。

Deprecate TSD

この記事を書き始めて色々調べているうちに気がついたのですが、型定義ファイルを管理する tsd コマンドが非推奨になり、新しい型定義管理ツールとして typings というのが始まっているようです。

DefinitelyTyped の一つのリポジトリに、すべてのライブラリの .d.ts ファイルを集合させる仕組みでは無くなるらしく、おそらくそちらの方がいい気がします。今回は旧来の手法にのっとってコントリビュートしてみましたが、次は typings の手法でコントリビュートしてみたいです。

THETA S のUSBライブストリーミングをブラウザで球面マップする

はじめに

Theta S が出たときからずっと、USBカメラとして使えるなら WebRTC に流したい! と思っていたのですが、Dual Fisheye の画像を球面にマップするところが自分では実装できず困っていました。

それからしばらくして、この記事様様さまを拝見し、ありがたやー!と僕は叫びました

qiita.com

まさしく、これです。

しかし実際にページにアクセスしてみたところ、THREEのライブラリが正しく読まれていなかったり、コードの一部がgit上で先祖返りしていたりして、正常に動きませんでした。そこで、自分で動くように修正することにしました。

なので、本日の記事は、あくまで巨人の肩でちょっとだけダンスしてみた案件になります。よろしくお願いします。

完成品

コードはこちらにあげてあります。元がGistで扱いづらかったので、恐縮ですがGitのプロジェクトにしています

github.com

最近 getUserMedia が https じゃないととれなくなってしまったので、実行可能な状態でウェブにはあげていません。皆様、Gitからコードを取得して npm http-server とかで試してみてください。

かわりに、録画した物をあげておきます

RICOH THETA S USB Live Streaming to WebRTC

修正内容

環境

球面へのテクスチャマッピング

基本は元記事の通りですが、最新のリビジョン で、theta-view.js のメインの処理を行っているコードがごっそりと削除されています。(コミットミスでしょうか) 一個前のリビジョン にコードが残っているので、こちらを使うことにします。

接合面の調整

本家のコードのままだと、少々カットしすぎてしまっているので、良い感じになるよう数値を調整します。詳細はコードをご覧下さい。スムージングはやっていません。(やりたい!)

Theta S の USBライブストリーミングを受ける

今回は、ローカルに接続されたTheta S の動画像を表示することにします。WebRTC の getUserMedia の定石通り取得して、 <video> タグに流し込みます。 <video> タグは直接は表示されず、jsで作るCanvasに、Three.jsがマッピングした映像が表示されることになります。

おまけ:FOV調整

視野角を広くしたり狭くしたり出来るようにします。 OrbitControl.js のマウスホイールは別のイベントに当てられているので、独自に上下キーでFOVをコントロールできるようにします

  function keydown(e) {
    var keyCode = e.keyCode;
    switch (keyCode) {
      case 40:
        // zoom out
        camera.fov += 1;
        if(camera.fov >= 130) camera.fov = 130;
        camera.updateProjectionMatrix();
        break;
      case 38:
        // zoom in
        camera.fov -= 1;
        if(camera.fov <= 30) camera.fov = 30;
        camera.updateProjectionMatrix();
        break;
    }
  }
  document.addEventListener("keydown", keydown);

おわりに

双方向化

今回は https サーバを立てるのがめんどくさかったりしたのでローカルのカメラを表示するのにとどめましたが、テクスチャとしてWebRTCでリモートから送られてきた動画を使うだけで、双方向全天球ウェブチャットのできあがりです。

連続稼働と用途

蛇足ですが、この記事を書いたりいろいろしている間、8時間以上連続して Theta S を USB ライブストリーミング状態にしていますが、今のところ大丈夫なようです。もう少し連続して使ってみます。

常時接続して監視カメラ的に使えるかなーと思いましたが、ライブストリーミングの状態にするのに現状ハードウェアキーをしかも特殊な作法で押すしか無いので、ちょっと不便そうです。

解像度

球面にマップすると、やはり USBの 1280x720 では全然足りない感じがします。HDMI ライブストリーミングの FullHD を HDMI キャプチャして使ったとしても、おそらくまだまだ足りないんだろうなぁ、という気もします。この辺りは、これからまだまだ発展の余地があるなぁと思いました。将来が楽しみですね!

たき火

f:id:AMANE:20151228191445j:plain

たき火に惚れた

Unity や openFrameworks でたびたびパーティクルを飛ばしたり光る表現をしたりしているけど、

結局は現実の圧勝



そもそも、たき火をつくるのはそんなに簡単ではない

ようやくついた火に少しずつ薪を足して守る

代わる代わる人がやってきて、火に照らされた顔を見たり、火を見たりしながらゆっくりと語る

火がパチパチと音を立て、温かくて、別に話すことがなくても時間が気持ちよく流れていく

子供が枯れ葉を投げ込んで火が大きくなるのに、きゃーきゃー言っている



たき火の熱は服を通り越して直接肌を焼いてくるような感覚がある

冷たい外気と熱い炎のダイナミックレンジ

パチパチという音は、脚色無く現実の音として鳴り、冷たい空気を揺らして直接耳に届く

赤や青の炎のダイナミックレンジ

白飛びした赤から、透明の青

うちわで扇ぐと、遅延無くゆらゆらと反応する光と熱と音

コンピュータでは当分表現できないというか

「ディスプレイ」という概念の無力さを思い知る

見上げると、月と星空

人の目と耳と肌の能力との華麗すぎるコラボレーション



たき火は身に危険を及ぼしうるが、

使いこなすことで、身を守る道具ともなる

食事を作ることも出来る

あかりのおかげで夜も活動できる

熱のおかげで冬を越すことが出来る

危険を管理することで便益を手に入れてきたことを実感する

穏やかで、当たり前すぎるのだけど、

人の能力を高めるもっとも基本的な要素のひとつであることを確認する



6歳の女の子が「たき火は消える直前も良かった」と言った

食事をし、暖を取り、仲間と語り合い、そしてこれから寝る

目に焼きついた光と体に残る暖かさ

たき火は人の生を象徴しているような気がした



Rhizomatiks Research x ELEVENPLAY "border" 体験の感想など

物販で売っていた前公演 "MOSAIC" の CD を聴きながら書いています

f:id:AMANE:20151205191109j:plain

公演の概要

公式をご参考下さい

www.rzm-research.com

感想

  • CGカッコいい
  • 照明カッコいい
  • 音カッコいい
  • ダンスカッコいい (目の前に来るのでドキドキする)
  • 運営が素晴らしい
  • チケット当たって良かった!

以下多大なネタバレが含まれます。間違いとか不理解とかあったらご指摘いただけるとありがたいです。

MIRAGE との対比

もう3年も前になってしまいますが、理研と パフォーマンスグループ GRINDER-MAN の作品「MIRAGE」を体験しました。頭をがつーんとやられたのが今でも生々しく思い出されます。

izmiz.hateblo.jp

似ている部分があったので比較してみます。

  • (同) 遮蔽型の HMD を使い、 HMD に外づけた RGB カメラの現在の映像を表示ししたりしなかったり、透過したりするのは同じ
  • (同) ダンサーが出てきて、目の前まで来たり横切ったり、体を触って実在感を確認し没入感を高める演出は同じ
  • (異) border では、リアルタイムレンダリングされる CG と、RGB カメラの映像が半透明に重ねられたり切り替えられたりしますが、 MIRAGE では、過去に収録された映像と現在の映像が切り替えられたり重ねられたりします。

最後の (異) が重要な気がしました。技術的には、10人同時参加しているすべての人(WHILL)の視点を、 ladybug 等の全天周カメラで移動しながら同時に撮るのは、以下の様な理由で相当困難です

  • ladybug で撮ってしまうと、ダンサーと環境しかなければ良いのですが、同時に体験している他のお客さんの位置に他の全天周カメラが収まってしまう
  • 他の9台にはダミーのお客さんを乗っけて10回全天周カメラで収録する、と言う手もあるけど、他人とは言え性別が入れ替わったりするとさすがにわかる
  • そもそも border ではRGBカムx2でステレオをしているので、 過去映像とのすげ替えは無理

他にも細かくいろいろありそうですが、総じて MIRAGE ほどの「現実・幻影のすげ替え・重ね合わせ」の作り込みは難しそうです。

border は、 非現実 (CGとダンスの世界、ライゾマ+MIKIKO先生的かっちょいい世界) と現実世界の境界を溶かす体験で、MIRAGE はある種の生々しい幻影を見せられる体験ってことかなーと思いました。

画質話

MIRAGEはまず低画質の世界で現実感をキャリブレーションした後幻影が融けてくる、という演出になっているので、HMDもカメラもある意味低画質で良かったのですが、カッコいいCGの世界が強く押し出されているborderでは、やはり画質がほしいなぁ、と言う感想を持ってしまいました。 Oculusもはその点まだ不足している印象です。

技術的/仕掛け的なはなし

つらつらとメモ。

写真に書き込んじゃいましたが、表に出てて体験者が直接触れるのはこんな感じだと思いました。

f:id:AMANE:20151205185755j:plainf:id:AMANE:20151205184257j:plain

ラッキング周り

  1. OptiでHMDに取り付けてある固有ID登録済みのマーカセットをトラッキング
  2. その位置姿勢情報を各MBPに送信
  3. MBPでレンダリング

という流れだと想像します。 Optiが理想的に取れていれば位置姿勢が取れているので Oculusのジャイロ情報は使わなくても良いのかな。

Optiの場合、(確か)固有の位置関係にある4つのマーカの組みを1つのID付きのトラッキング対象として登録出来るのだけど、それを10組登録してトラッキングするのは結構緊張感あるなーと思いました。距離が近いと入れ替わりとかありそう。意外とだいじょうぶなのかな。。。

車いす自体の制御には、それとは別に車いすの背中につけてある三角形のマーカセットでのトラッキング情報を使う。こちらは平面の仮定を置いている、のかな。

  1. OptiでWHILLの背中につけてあるマーカセットをトラッキング
  2. その位置姿勢情報を各MBPに送信
  3. MBPからWHILLをコントロール(ここはたぶん)

車いすを指定時間で指定位置まで持っていくのとか、結構専門的なプログラムな気がします。映像的なものだけじゃないライゾマさま、やっぱすごすぎ。

ステレオカメラ

公式サイトのキービジュアルではむき出しになっている前面のカメラ、4つのマイクが並んでいる独特のスタイルは、PlayStation Eyeだと思います。本番ではカバーがついていました。以前 @hecomi 先生が記事にもされていましたが、 VGA 60fps で撮れる安価なウェブカムとして超優秀で、おそらくそれが買われて採用されているのでしょう。

tips.hecomi.com

ただ、実際体験した感じだと、あまり立体視している感じは出ていなかったような気がします。他の表現や演出にあっけにとられ過ぎていて、立体化があるかどうかを気にして無すぎたのかもしれません(笑)

照明との連動?

作品中で、白い箱が動き回って、それがさらにAR的な演出で変形したりするのですが、実世界の照明との連動が、されていたようなされていなかったような、微妙な感じでした。(後から鑑賞した際は、確かに白い箱に照明が当てられてカラフルに着色していたのですが、体験したCGの世界では、それほど色がついている印象はなかったです)

照明にColorBlast を使っていたので、照明の入力はすべて楽譜のようにデータ化されているはずです。なので、CGの世界でもそれと連動するように世界に照明を配置して光らせると、より良い感じだったかもなーと思いました。(やってたかもしれません)

ポンチョ

f:id:AMANE:20151205192559j:plain

ポンチョを着せられたときに何でかなーと考えたのですが、体験したあと鑑賞までしてようやくわかりました。

終盤にHMD内ではCGのダンサーが踊っているシーンがあります。重畳しているものだと思って体験中は見ていたのですが、後で鑑賞してみると、実は、ステージで現実のダンサーが踊っているのと完全に同期したCGのダンサー「だけ」がHMDの中では踊っているのです。

しかし、HMDで見ている世界には、ほかの9名の鑑賞者もいます。現実の世界からダンサーだけ消すのは難しい気がするのですが、実はこのとき、現実世界と重畳されていると思い込んでみていたHMDのCGの世界は、実はフルCGなんですね。いつの間にかCGの世界に鑑賞者が入っていた!という驚きです。そのためにその日どんな格好で来るかわからない鑑賞者の服装を隠す必要があり、ポンチョを着せられていたわけです。

もしかしたら他のシーンでも、鑑賞者はいつの間にかCGに入れ替わっていたかも知れません。(演出とダンスが格好良すぎてほぼ気がつかない(笑)

オペレーション他

  • 待ち時間に真鍋さん直々に出演されているインストラクション動画を見ました。これで入場から退場まで迷い無く体験することが出来ました。
  • 上演の間の時間WHILLを壁寄せに並べている隙に、MBPの充電とWHILLの充電をしていたようです。ケーブル二本。すごく複雑な装置に見えますが、オペレーションがすごくスムースに行われていて素晴らしかったです

さいごに

とにもかくにもスゴイ体験でした。こんな攻めたステージを一般向けに三日間もやるというのが、すごすぎます。紅白のPerfumeといい、こういう現場での強さは Rhizomatiks さんはさすがですね。惚れます。