ちら帳

喉元を過ぎると熱さを忘れる自分の為の、ちら裏メモ帳ブログです。

React VRで頭の動きに追従するカーソルを表示する

VR初心者のちらです。

今回はVRでよくある、頭の動きに追従するカーソルの表示方法についてのお話です。

まずReact VRのカーソルシステムについてのドキュメントはこちら。

facebook.github.io

カーソルの実装

カーソルはRayCasterを利用して実装します。

学生時代のおぼろげな記憶で説明をするのも良くないので、レイキャストについての詳細は割愛しますが、ちゃんと調べたい人はレイキャストとかレイキャスティングで検索をかけるといいと思います。

RayCasterで実装が必要なメソッドは以下の3つになります。

  • getType - raycasterを一意に特定できるような文字列を指定します。
  • getRayOrigin - カメラを基準にしたときの光線の原点を3次元座標で指定します。
  • getRayDirection - カメラの向きをもとに光線の方向を3次元ベクトルで指定します。

さらにオプションで2つのメソッドが用意されています。

  • frame - アプリケーションのフレーム毎に呼び出されるメソッドです。
  • drawCursor - 目に見えるカーソルを描画するかどうか決定するメソッドです。

カーソル用に各メソッドを実装するのであれば、  

  • getType : 任意の文字列
  • getRayOrigin : [0, 0, 0] カメラの原点
  • getRayDirection : [0, 0, -1] カメラの正面方向
  • frame : 実装しない
  • drawCursor : true

とするのがいいと思います。

カーソルの可視性の制御

カーソルの可視性はcursorVisibilityというオプションで制御できます。
このオプションはclient.jsやindex.htmlでの初期化の際に設定することができます。

設定できる値は以下の3つです。

  • hidden - カーソルを常に非表示にします。デフォルトではhiddenになっています。
  • visible - カーソルを常に表示します。
  • auto - 入力イベントハンドラを持つコンポーネント(など)に視線がぶつかっているときにカーソルを表示します。

autoを設定する場合も、デバッグ中はvisibleにしておくのがよさそうです。

実装

今回はアプリケーション全体でカーソルを可視化する体でclient.jsに可視化処理を実装しました。
初期化時のオプションのraycastersにカーソル用のRayCasterを実装し、同じくオプションのcursorVisibilityをvisibleにします。

// Auto-generated content.
// This file contains the boilerplate to set up your React app.
// If you want to modify your application, start in "index.vr.js"

// Auto-generated content.
import {VRInstance} from 'react-vr-web';

function init(bundle, parent, options) {

  const vr = new VRInstance(bundle, 'ReactVrSample', parent, {
     // Pass in the custom font as an initialization property
     raycasters: [
          {
            getType: () => "mycursor",
            getRayOrigin: () => [0, 0, 0],
            getRayDirection: () => [0, 0, -1],
            drawsCursor: () => true
          } 
     ],
     cursorVisibility: 'visible',
     ...options,
  });

  vr.render = function() {
  // Any custom behavior you want to perform on each frame goes here
  };
  // Begin the animation loop
  vr.start();
  return vr;
};

window.ReactVR = {init};

せっかくなのでカーソルの当たり判定も確認できるようにします。
index.vr.jsに画面上にピンクの文字列を表示して、文字列にカーソルが当たっているときには色を赤に変える処理を書きます。

import React from 'react';
import { AppRegistry, asset, Pano, Text, View } from 'react-vr';


export default class ReactVrSample extends React.Component {
 constructor() {
    super();

    this.state = {textColor: 'pink'};
  }

  render() {
    return (
        <View>
        <Pano source={asset('chess-world.jpg')}/>
      <Text
        style={{color: this.state.textColor, 
            fontSize: 0.3,
            fontWeight: '400',
            layoutOrigin: [0.5, 0.5],
            paddingLeft: 0.2,
            paddingRight: 0.2,
            textAlign: 'center',
            textAlignVertical: 'center',
            transform: [{translate: [0, 0, -3]}],
          }}
        onEnter={() => this.setState({textColor: 'red'})}
        onExit={() => this.setState({textColor: 'pink'})}>
        This text will turn red when you look at it.
      </Text>
      </View>
    );
  }  
};

AppRegistry.registerComponent('ReactVrSample', () => ReactVrSample);

確認

白い丸がカーソルです。GIFはありませんが、VRモードにして頭を動かすとちゃんと追従します。

f:id:chira_pym:20170528234908p:plain

文字の方を見ると、カーソルが文字に当たって文字の色が変わります。 f:id:chira_pym:20170528234940p:plain

ひとこと

A-Frameのtracked controllersのサンプルみたいにコントローラーの位置をトラッキングして手を表示したいのですが、公式サンプルはまだですか。