Oculus Go + WebVR + A-Frameで開発するときに役に立った情報

Oculus GoでWebVR開発してて役に立ったURL等を書き連ねたメモです．

経緯：　Oculus Go買ったので，VR環境整備を兼ねてアプリ作りたい → Unityで開発してapkをインストールするの面倒になってWebVRにすることに → フレームワークはA-Frameが手軽でよかった

# Oculus GoでWeb開発する

Androidなのでどうにかなるだろうと思ってたけど，意外とググって確認することが多かった．

## Oculus Goを開発者モードにする

サイトで開発者登録しないといけないのが少し面倒．

https://www.scriptlife.jp/contents/programming/2018/05/10/oculus-go-adb/

## Chromeのリモートデバッグを使う

ADBで接続するのでOculus Goを開発者モードにする必要があります．
WebVRのレンダリング結果は表示されないのはちょっと不便．

https://qiita.com/massie_g/items/ba6fa38c923d3509e469

## DDMSでスクリーンショットを保存

Oculus Goにある画像を保存する機能もWebVRのレンダリング結果は保存できなかったりするので，結局Android SDKのddmsで画像を保存している．
Androidの開発環境があるなら手軽だけど，多分もっと良い方法もあるはず．

https://www.scriptlife.jp/contents/programming/2018/05/10/oculus-go-screenshots/

## HTTPプロキシを設定

Oculus Goのブラウザからのリクエストを覗いたり中身を書き換えたりしたいので，プロキシを設定．
Oculus GoのWiFi設定を長押しすると詳細設定画面が開きます．

https://forums.oculusvr.com/developer/discussion/64905/proxy-settings-for-wifi-networks-on-oculus-go

プロキシは何でも良いですが，ある程度パフォーマンスが出てかつ色々書き換えたかったので， https://github.com/elazarl/goproxy を使ってGolangで書いた．


## ブラウザの素性を確認する

Oculus Goに入ってるブラウザは微妙に古いバージョンのChromiumがベースっぽかったり，ビルド時のオプションを知りたかったりするので，`chrome://version` で確認．あまり必要は無いけど，もちろんchrome://flagsとかもいじれる．

## ブックマークレット

あまり開発とは関係ないですが，Chromeの拡張機能はインストールできないので他所様のサイトでスクリプト起動したいときはブックマークレットを作っておくと便利．久しぶりにURL欄でJavaScript書いた．．．
動画は倍速で見る派なので，Video Element のplaybackRateを設定するやつとかが必須だった．

https://9ballsyndrome.github.io/tool/180603_oculusgo_bookmarklet/build/

javascript:～から始まるURLはブックマーク保存時に拒否されるけど，頭にスペース入れると保存できるので便利．

## Oculus GoコントローラをGamepad APIで使う

Gamepad APIに対応しているはずなのにデバイスが見えない．．．と思ったらWebVRモードにしたら使えた．
普段はマウス扱いで，フルスクリーンになるとGamepad に切り替わるっぽい．

## キーボードをつなぐ

USBでつながるっぽいけど，ADBで設定ダイアログ開けるならBluetoothの設定ができる．

https://medium.com/@yukotan/oculus-go-tips-825807c19fdb

Bluetoothで思い出して，おもむろにブラウザで `chrome://bluetooth-internals` とか開いたら普通にデバイス一覧とか出てきた．Chrome便利．


# A-Frame

いくつか試して，[A-Frame](https://aframe.io/)に落ち着きました．

- 中身はThree.js．Three.jsを直接触ることもできるので最悪どうにでもなるのは安心
- コンポーネント周りの仕組みが良い．標準で付いてくるインスペクタも高機能(Unityっぽい？)
- ビルド環境が素直＆自分でビルドせずCDN上に用意されたスクリプトを読み込むだけでも動く

まだ開発途上っぽくて，バージョン間の互換性は微妙．GitHubとかで良さげなコンポーネント見つけても手を入れないと最新版で動かないこと多い．masterブランチ追いかけてるけど，コミットの内容追いかけながら使う感じになっている．．．

以下，はまった箇所のうち覚えてるもの．

### ソフトウェアキーボードがほしい

Oculus Go自体のソフトウェアキーボードはWebVR内には表示してくれない.

とりあえず https://github.com/etiennepinchon/aframe-material のキーボードを使っている．

A-frame v0.8.2で動かすには少し修正必要だった．
＆すでに修正されてるのもあった． https://github.com/vizorvr/aframe-material/tree/vizor

### [0.8.2] jsで生成した要素(image, video, canvas)をテクスチャにすると表示が壊れていく

A-Frame内部のテクスチャ管理時に要素のIDや属性のハッシュ値から生成したキーでテクスチャのキャッシュを持っているので，
createElementした要素は同じキーになったりする．．．

https://github.com/aframevr/aframe/blob/v0.8.2/src/systems/material.js

とりあえず，一意になるように適当なidを付けておけば良さげ．
正しい作法は分かってない．

### [0.8.2] Canvasをテクスチャにするとパフォーマンスが落ちる

なぜか，Three.jsのVideoTextureが生成されてて毎フレームテクスチャが更新されている．
THREE.jsのテクスチャを自前で用意してmaterial.srcとかに渡して回避．

masterブランチでは修正されてた．
https://github.com/aframevr/aframe/commit/b47f20363ba366514b1c493d3a9dcb59e73c0426

### [0.8.2] Oculus Goコントローラが一度切断されたあと復帰しない

内部的には動いてるっぽいけどtracked-controlsのリスナが外れたままになってる．バグっぽい．

→ masterには修正入った．
https://github.com/aframevr/aframe/commit/dc8662be60989e0af6b9a8e77a86185e7333c2c3

### [0.8.2] マウスとOculus Goコントローラを同居させたい


入力周りは古い情報が多め．PC上でデバッグのためにマウスを使う＆各デバイスのコントローラを使う想定．

``` html
<a-scene cursor="rayOrigin: mouse; fuse:false" ... >
     ...
    <a-entity laser-controls="hand: right"></a-entity>
    <a-entity laser-controls="hand: left"></a-entity>
```

とかで良さげ．

`oculus-go-controls`とかを使わないければいけないのかと思ったけど，`laser-controls`が自動的に切り替えてくれる．
マウスの方は`fuse:false`が入ってなくて意図しないクリックイベントが発生して悩んだりした．マウスもコントローラも無い環境は一旦忘れる．

### [0.8.2] textコンポーネントのシェーダはthree.jsのclippingPlanesでクリッピングできない

日本語使いたくてCanvasからテクスチャ作ることにしたのでどうでも良くなった．

### [master2018-09-17] Oculus Goでカメラとコントローラの座標がずれる

WebVRモードでは視線の高さが反映されるのですが，THREE.jsとA-Frame両方でカメラの座標にユーザの高さを加算してしまっている．
とりあえず強引にy方向に-1.6くらいカメラを下げてるけど，修正待つのが良さそう．

### [master2018-09-17] オブジェクトがクリックできなくなった

よくわからないけど，デフォルトでscene直下にあるオブジェクトしか触れない仕様になったっぽい．

https://github.com/aframevr/aframe/commit/8809e7fd5eccd4c4ce76892f4a5673b911dfd60f

とりあえず`raycaster="objects:[geometry]"` とかして回避．