VR 研究記

3D技術の経験を活かして、VRに挑戦するおっさんの奮闘記

Oculusインストール環境のトラブルと対策

OculusのインストールでのPCIドライバインストールエラー

私のノートPCでドライバのインストール中にPCIドライバだけがエラーを出していた。
Specは、以下の通りである。
  CPU: Xeon E3-1505M
  GPU: nVidia Quadro M1000M

とある店舗の店員から聞いた話ですと、Optimus機能があるとOculusのドライバがインストールされないという情報を得たので検証してみた。
※実機があっての比較ではなく、機能差分等での比較となります。

Optimus機能とは何か?

GPUの負荷具合を基に判断して、Intel GPUnVidia GPUを切り替える機能。
ラップトップ(ノートPC)の消費電力を抑える目的で作られた機能です。

Optimus Technology | NVIDIA

NVIDIA Optimus Technology: Performance and Battery Life for your Notebook | How Optimus Works

Optimus機能をOFFにする方法はあるのか?

以下の2つの記事を発見した。

www.pcworld.com

forums.autodesk.com

 

内容を見ると、BIOSの設定とドライバーをインストールする際にカスタムインストールを選択する事で関連ドライバのインストールを回避できるとある。

Devel/OculusRift/製品版のセットアップ - cubic9.com


が、私のPCのBIOSではこれらの設定を弄る項目が無く対応していなかった。
LINUX系ならなんとかなりそうだが、Windows専用なので意味が無い。

別の観点で調べてみた

上記の通り、設定を変えるという観点では失敗に終わった。
なので、External GPUという方法でラップトップPCを拡張する形でVideoボードを出すことを検討してみました。

調査した結果、3つほど救済策があることが分かった。

1. Dell ALIENWARE グラフィックボード外部拡張外付けボックス

Amazon CAPTCHA

この機種はビデオボードの外付け及び拡張には向いてますが、出力端子がDell

ALIENWAREシリーズ専用になっていて、他では使えない制約があります。
私のワークステーションは、Dell製ですがALIENWAREシリーズではないので接続できません。
なので、選択肢としてはなくなりました。


2. Mac向けの外部接続 PCI-E Box

MacPCI-Eを使って拡張したい人向けの救済策として用意されている商品になります。

公式を見るとWindowsでもThunderboltさえ対応していれば使えるようでした。
しかし、PCI-Eに挿して使えるボードとしては、HDDやサウンドボードビデオキャプチャーボード、ネットワークボードなどでした。
ビデオボードを挿してもnVidiaのドライバにブリッジする必要があり、ソフト的な対応が必要になるためNGでした。

www.amazon.co.jp

【正規国内品】ソネット SONNET Echo Express SE I Thunderbolt 2-to-PCIe Card Expansion Chassis

Amazon CAPTCHA

HighPoint RocketStor 6361A デュアルThunderbolt接続 拡張アダプタ PCI-Expressポート

Amazon CAPTCHA

 

3. PCI-Eボード

PCI-Eのみを剥き出しにしたPCI-Eボードという選択があります。
以下の2つはPCI-Eですが、ver 2.0止まりで最新のビデオカードが挿ささらないと分かった。
出力端子もExpressカードで昔のスタイルでした。

DIR-EB262-シリーズ - PCケース&パーツ、オーディオのパイオニア-株式会社ディラック

PE4C V2.1 (PCIe x16 Adapter)

また、海外でのE-GPUの動画を発見しました。

www.youtube.com

これを参考にして、外付けGPU用のPCI-Eボードを発見しました。(日本でも輸入可能です。)

Aliexpress.com : Buy V8.0 EXP GDC Laptop External Independent Video Card Dock with Mini PCI E Version from Reliable card interface suppliers on Geekworm official store

 

端子が、mini PCI-EになっていてラップトップPCのボードで切り替えが出来れば使える事が分かった。
ビデオボードを拡張できてBIOS次第では切り替えも可能な方法はこれしかないと分かりました。

そこで、私のPCの構成を調べてみた結果ですが、私のQuadroマザーボード上にチップが載っていてPCI-E自体を使用していない事が分かりました。
よって、私のラップトップから拡張してGPUを活用する方法が絶たれてしまったという結果に終わりました。

結論:

Oculusを使うためにNoteを買うときは、PCI-Eに注意するかOculusが推奨するGPUが載っているPCを購入するかのいずれかを選択するほうが無難です。

360°パノラマビューをUnityで作ってみた

今流行の360°ビューの仕組みとは

細かく書くと難しくなるので、簡単に書いていきます。
360°撮影できる機材を使ってパノラマ撮影した画像・映像を
擬似空間の球体(正距円筒球)の内側に張り付けて球体の中心に
カメラを設置してユーザーに見せる事であたかも自分の周りに
撮影した景色があるかのように見える技術の一つです。
ポイントは、正距円筒球を使う事です。

正距円筒球とは何か?

擬似空間でのポリゴンの表現がどんな形状で出来ているかご存知でしょうか?
実は、3D空間ではすべて3角形で表現します。

f:id:subrutm:20161109104137p:plain

美術でも遠近法が用いられることにより奥行きを感じるのと同じように
カメラから離れた位置にある三角形メッシュほど、縦長に大きくなることが
分かると思います。

画像を張り付ける手法は、頂点情報に画像の座標を記録し、それを
三角形メッシュで描画しているので画像を加工しないでそのまま
描画すると不自然な形になるのはイメージ出来ますでしょうか?

違和感の無い画像表現をする為には、球の頂点位置と画像座標が適切に
マッチさせてあげる必要があると理解できると思います。

ここからは、テクスチャーマッピングの話です。
下記のように、平面(ABCD)と画像(abcd)があるとします。
法線は、あなたに向かってくる方向が法線ベクトルの方向とします。
f:id:subrutm:20161109131215p:plain

  • ABCD = abcdの場合

元画像の解像度と等倍で正常に表示される。

  • ABCD > abcdの場合

元画像の解像度より拡大して表示される。

  • ABCD < abcdの場合

元画像の解像度より縮小して表示される。

この例から分かるように、3D空間のメッシュの大きさと画像の大きさが
マッチしないと倍率に差が出てしまい、表示が不自然になってしまう。
だから、球面の三角形に合わせた画像を作る必要があり、その手法が
正距円筒図法と呼ばれます。
これを応用すると、パノラマ投影法[プロジェクションマッピング]
になる訳です。

詳細な変形手法としては、詳しいサイトがありますのでそちらを参照下さい。
空雲礼賛

正距円筒球を入手する方法は?

正距円筒球の入手手段は、インターネットでダウンロードか
機材を用いて撮影するかの二択になります。

インターネットでダウンロード

  1. 画像検索で、「360-degree photo」をキーワードに検索する
  2. 写真共有サイト Flickrから写真をダウンロードする。*1

機材を使って撮影

下記は、360°パノラマ撮影するための機材です。

  1. GoPro Kolor*2
  2. Google Jump*3
  3. JauntVR NEO*4

Unityで360°パノラマビューを作ってみる

上記の何れかの方法で入手した画像素材を利用して、360°ビューを表示してみましょう。

まずは、球体を作成します。

f:id:subrutm:20161109120208p:plain

写したいパノラマ画像を作成した球体にドラッグアンドドロップします。
すると、球の外側に画像が表示されると思います。
これを内側に切替える方法は下記の通りです。

手順1. カスタムシェーダーを作成する

①カスタムシェーダーファイルを新規作成する
f:id:subrutm:20161109142152p:plain

②以下のコードに書き換える。

Shader "Custom/InwardShader" {
	Properties {
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200

		Cull Front
		
		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard vertex:vert//fullforwardshadows

		// 法線ベクトルを内側に向ける設定
		void vert(inout appdata_full v) {
			v.normal.xyz = v.normal * -1;
		}

		sampler2D _MainTex;

		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D(_MainTex, IN.uv_MainTex);// * _Color;
			o.Albedo = c.rgb;
		}
		ENDCG
	}
	FallBack "Diffuse"
}
手順2. Materialの設定を利用する

f:id:subrutm:20161109141441p:plain
①: 影は無用なのでチェックを外す
②: マテリアルのシェーダー設定を作成したシェーダーに変更する

手順3. MainCameraの位置を球体の中心に設定する

f:id:subrutm:20161109144142p:plain

手順4. 環境光を消して、スポットライトで内部を照らす

①環境光を消す
f:id:subrutm:20161109144424p:plain

②スポットライトを新規作成する
f:id:subrutm:20161109144948p:plain

③必要ならパラメータを修正する
f:id:subrutm:20161109145055p:plain

手順5. 球体を回転させるスクリプトを作成
using UnityEngine;
using System.Collections;

public class Rotator : MonoBehaviour {

    public Vector3 rotateRate;

    // Use this for initialization
    void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
        transform.Rotate(rotateRate * Time.deltaTime);
    }
}

作成したスクリプトを球体にアタッチして再生すると、360°パノラマビューの
簡単なテストアプリの完成です。

VR美術館の試作にて光源の描画問題ではまった件

VR向けの美術館とは

現在、VR向けの美術館として照明と絵画で演出を工夫しながら考えています。
以下の写真は、開発中のスクリーンショットになります。
f:id:subrutm:20161105055540p:plain

照明としては、2タイプを使っていました。
タイプ1. 全体的に照らす天井の照明
タイプ2. 絵画を照らすための照明

問題点は、ある条件のときにタイプ2の照明が描画されない問題が発生した。
f:id:subrutm:20161105060506p:plain

※表示は、スクリプトで作成しているので、照明の条件はすべて同じです。

解決するには、優先順位を高くしろ!

Lightの設定にある【Render Mode】を【Important】にすると改善します。
f:id:subrutm:20161105061156p:plain

C#スクリプトでは、以下のようにアクセスします。

Lightの構成が、写真の通りだとする。
f:id:subrutm:20161105061817p:plain

using UnityEngine;
using System.Collections;

public class ImageLight : MonoBehaviour {

    // Unity GUIで設定を変更するLightオブジェクト(spotlight)をリンクする
    public Light imageLight;

    // Use this for initialization
    void Start () {
        // Render Modeを変更する [Important (ライトは、常にピクセル単位で描画される)]
        imageLight.renderMode = LightRenderMode.ForcePixel;
    }
}

Light周りで困ったときは、お試しください。

Unityで画面を切り替える方法

Unityで画面を切り替える方法が変わりました。

5.2.Xと最新の5.4.Xでシーンの切換え方法に大きな変更があった事が自分で作り込んでて判明したので情報共有するために記載します。
シーンファイルは、*.unityという拡張子のファイルとして存在しています。

Unity 5.2.Xのシーン切換え方法

using UnityEngine;
using System.Collections;

public class SceneChanger : MonoBehaviour {

        public String nextScene;

	// Use this for initialization
	void Start () {
	}
	
	// Update is called once per frame
	void Update () {
        if (Input.anyKey) {
            Application.LoadLevel(nextScene);
        }
    }
}

Unity 5.4.Xのシーン切換え方法

using UnityEngine;
using System.Collections;

using UnityEngine.SceneManagement;

public class SceneChanger : MonoBehaviour {

        public String nextScene;

	// Use this for initialization
	void Start () {
	}
	
	// Update is called once per frame
	void Update () {
        if (Input.anyKey) {
            SceneManager.LoadScene(nextScene);
        }
    }
}

nextSceneには、次に表示するシーンのファイル名(*.unityの*の部分)を入力すれば良いです。
シーンの切換えトリガーを【if (Input.anyKey)】としてますが、ここは任意です。
コード例の場合は、何かキーを押したらシーンを切り替えると言う意味です。

勉強やテストで作った3D作品とこれから創るVR作品を紹介します♪

・勉強のために書籍を参考にしつつ、材料を利用して作った作品

 

 SFチックな侍の単純に動き回れるアクションゲーム

ムービーですが、asset Storeから得たデータを使って自力で作った最初のアプリです。

https://www.facebook.com/subru.matsuoka/videos/1092863707428841/

 書籍を参考にUnityの機能を活用して作ったシューティングゲーム

 

素材は、書籍からとAsset Storeからの2種類です。
エフェクトなどは、アレンジしてます。
レーダーは、プレーヤーと敵との相対距離を算出して自機から位置関係を表示しています。
また、向きについては自機の方向をそのままZ軸回転させているだけです。

敵から迎撃を受けてます。

f:id:subrutm:20161030182249j:plain

 

ダメージ受けているのですが、危険レベルまで減ってしまって赤くなっているところです。 (中間色として、黄色もあります。)

f:id:subrutm:20161030182250j:plain

 

プレイヤーが攻撃しているところです。

f:id:subrutm:20161030182251j:plain

 

・これから企画として創ろうとしている作品

 VR美術館

VRを使った、絵画鑑賞の空間を作ります。
スポットライトを使った雰囲気の演出などを工夫して、絵画を飾り一人称カメラで実際に擬似空間を散策しながら参照する流れです。

部屋のようなダンジョンにも応用できるので、部屋のような空間での当たり判定や演出効果の学習を兼ねたプロジェクトです。

 

外観です。

f:id:subrutm:20161030183803p:plain

 

内装です。

f:id:subrutm:20161030182853p:plain

 

VRスーパーマリオブロス

学生時代でもやっていたマリオの模擬作品です。
VRを使ってマリオになりきろう!という想いから発足したプロジェクトです。
下準備としてブロックを設置してみただけの画像ですが、今後拡張していきますので開発途中のノウハウなどを公開するのでお楽しみに。

完成したら、遊んでみましょうw

f:id:subrutm:20161030183445p:plain


最後まで、読んで頂きありがとうございました。

 

Oculus APIについて

Oculus APIとデバイスバージョンの関係

  OculusのダウンロードページよりDL出来るAPI(Application Platform Interface)のこと。
私が、試験的に使用していたのはOculus DK2(以後、DK2とする)です。
正式版との違いは、トラッキングバイスに相違がある点です。

あとは、ドライバーも違っているようで、最新のドライバではDK2をコントロールする事は出来ませんでした。

開発言語は、C++, Unity(C#, Java Script), Unreal Engine(C++)に対応しています。

■Oculus DK2の開発環境

OS ドライバ バージョン SDKバージョン Unity Package Version
Windows Oculus Runtime for Windows v0.4.3-beta Oculus SDK for Windows v0.4.3-beta *1 Unity v4.5.5
Mac Oculus Runtime for OS X v0.4.3-beta Oculus SDK for OS X v0.4.3-beta Unity v4.5.5

Oculus Riftの開発環境
Setup Tool
Oculus Platform SDK *2

Oculus の構成

Windows上でUnityを使った際の構成を画像で示します。

f:id:subrutm:20161020230956p:plain

Oculus の相関図

OVR系クラスの主要なクラスの相関図を以下の画像にまとめました。
f:id:subrutm:20161021224434p:plain

クラスのメンバ変数・メンバ関数 説明

上記、相関図のクラスのうちの主用なクラスのメンバ変数及びメンバ関数を示します。
調査環境は、Unity v5.x, Oculus Utilities for Unity 5 v1.8.0です。

■OVRManagerクラス

OVR系APIの中心的なクラスです。
このクラスを中心に周囲のクラスを管理しています。

インスタンス

R: Read
W: Write

+メンバ名称 型名 属性 役割
+instance OVRManager R OVRManagerのインスタンス
+display OVRDisplay R 有効なディスプレイへの参照
+tracker OVRTracker R 有効なセンサーへの参照
+boundary OVRBoundary R 有効な検出領域設定への参照*3
+profile OVRProfile R ユーザの設定情報や身体情報など

●イベントをトリガーにしたコールバック系

+メンバ名称 型名 属性 役割
+HMDAcquired event Action - HMDが割り当てられた
+HMDLost event Action - HMDが認識されなくなった
+HMDMounted event Action - HMDがユーザーの頭に嵌った
+HMDUnmounted event Action - HMDがユーザーの頭から離れた
+VrFocusAcquired event Action - VR焦点を得られた
+VrFocusLost event Action - VR焦点を失った
+AudioOutChanged event Action - 音出力デバイスの変更とリスタートが必要
+AudioInChanged event Action - 音入力デバイスの変更とリスタートが必要
+TrackingAcquired event Action - センサーがトラッキング対象を得た
+TrackingLost event Action - センサーがトラッキング対象を失った
+HSWDismissed event Action - 『Health & Safety Warning』というウィンドウが消えた

※『Health & Safety Warning』とは・・・

以下の画像のように表示される注意書きのウィンドウの事で、何かキーを押すことで消えます。
f:id:subrutm:20161021104216p:plain


●状態チェック・設定系

R: Read
W: Write

メンバ名称 型名 属性 初期値 役割
+isHmdPresent bool R / W - trueなら、接続されていて存在している
+audioOutId string R - 音声出力デバイス識別子*4
+audioInId string R - 音声入力デバイス識別子*5
+hasVrFocus bool R - trueなら、アプリケーションはVR Forcusを持っている
+isHSWDisplayed bool R false 常にfalse(必ず表示する)
+DismissHSWDisplay bool - - 使用されていない
chromatic bool R / W - trueなら、テクスチャーの帯域幅をコストにして色彩を改善する。
monoscopic bool R / W - trueなら、両眼は同じ絵を見る。(両眼の中心で描画する、パフォーマンスを節約し快適にする)
queueAhead bool R / W true trueなら、描画処理の映像のゆがみをCPU-GPUをパラレルで動かすことで1/4フレーム高速化する
useRecommendedMSAALevel bool R / W false trueなら、Unityがハードウェアのパフォーマンス・クォリティーに合った最適なアンチエイリアシングレベルを設定する
enableAdaptiveResolution bool R / W false trueなら、動的アクセラレーションを許容する
maxRenderScale float R / W 1.0f アプリケーションが適応可能な解像度モードの最大倍率を設定[設定可能範囲: 0.5~2.0f]*6
minRenderScale float R / W 0.7f アプリケーションが適応可能な解像度モードの最小倍率を設定[設定可能範囲: 0.5~2.0f]*7
vsyncCount int R / W - FPS(Frame per seconds)の値
+batteryLevel float R - バッテリ残量を取得
+batteryTemperature float R - バッテリの温度を取得
+batteryStatus int R - バッテリの状態を取得
+volumeLevel int R - 音量レベルを取得
+cpuLevel int R - CPU性能のレベルを取得
+cpuLevel int R / W - CPU性能のレベルを取得
+gpuLevel int R / W - GPU性能のレベルを取得
+isPowerSavingActive bool R / W - trueなら、CPU/GPUの使用電源を抑える
+trackingOriginType OVRManager.TrackingOrigin R / W - ラッキング対象の種別(EYE LEVEL, FLOOR LEVEL)
usePositionTracking bool R / W true trueなら、位置トラッキング機能をOVRCameraRigのカメラと同期する
useIPDInPositionTracking bool R / W true trueなら、ユーザーの目と目の距離をOVRCameraRigのカメラと同期する
resetTrackerOnLoad bool R / W false trueなら、各シーンをロードする度に頭の位置をリセットします。(原点とベクトルを再設定する)
isSupportedPlatform bool R - trueなら、VRがPlatformに対応している
isUserPresent bool R - trueなら、ユーザーがHMDを着用している

●外部から参照できる関数

メンバ関数名称 戻り値 引数 役割
ReturnToLauncher - - 関数をコールするとアプリやゲームから離れて、ランチャーメニュー/ダッシュボードに戻る
+PlatformUIConfirmQuit - - 関数をコールすると終了選択画面が表示される
+PlatformUIGlobalMenu - - 関数をコールするとグローバルメニュー画面が表示される

まとめ

Deviceまわりの設定は、OVRManagerである程度機能する事が見えてきたと思います。
各メンバ変数のアクセス方法は、以下の通りとなります。

	void test() {
		// staticなメンバの場合は、以下の書き方でアクセス可能です。
		if( OVRManager.isHmdPresent ) {
			// HMDが有効で使える状態でする処理を書く
		}

		// 通常のpublicメンバの場合は、以下の書き方でアクセス可能です。
		OVRManager.instance.usePositionTracking = false;
	}

*1:DK2向けのSDKは、C++によるライブラリやAPIサンプルコードが入ってました。

*2:2016/10/20現在 最新バージョン。

*3:センサーが検知する空間の境界, VIVEとかが参考に成るかもしれない

*4:Windows audio endpointが使用するためのIMMDevice(Multi Media Device Interface)のUUID(Unique User ID)を得る

*5:Windows audio endpointが使用するためのIMMDevice(Multi Media Device Interface)のUUID(Unique User ID)を得る

*6:enableAdaptiveResolutionが有効になっていることが前提

*7:enableAdaptiveResolutionが有効になっていることが前提

VRの歴史

VRの起源

最近、VRが話題沸騰してますが、起源はいつからかご存知でしょうか?
実は、1989年にバーチャルリアリティという言葉が誕生しました。
なので、専門家の『VR元年』とは、1989年なのです。


没入感を得られるVRシステムとして、1992年にCAVEという方式のVRシステムが発表されました。

Cave automatic virtual environment - Wikipedia

イリノイ大学シカゴ校で開発された仕組みで、HMD形式では視野角に限界がある事から箱形のディスプレイの中に人が入ることで、その課題をクリア出来ないかと考え試作されたそうです。

メガネにセンサーを付けることで位置をトラッキングして、ボックス型の部屋に人の方向に合わせた映像を投影するシステムでした。

これは、大変大掛かりで場所もとる仕組みだったようです。

イメージとしては、以下の通りとなるようです。

Visbox, Inc. | CAVE Systems

www.youtube.com


現在、主流となっているHMDはどこから来たのか?

現在、主流となっているHMD(Head Mount Display) がどこから来たのかと言うと、始まりはARと言う形で1938年に登場しています。
単なる、頭に着けるディスプレイと言う意味では、始まりは1938年です。

詳細は、たくさん説明ページがあるので省きます。 (最後にオススメのページを紹介します。)

CAVEが開発されていた時代には、HMD型のVRの研究開発が盛んだったそうです。 (日本バーチャルリアリティ学会の資料より)
そう考えると、Oculusの登場までにエラく時間が掛かったんだなと思いました。。

現在主流となっている、VR機器とはARとして開発されたHMDとCAVEで培われたトラッキング技術を融合させた技術と言えます。

私は、さらに先のHR(Holographic Reality)を目指したいと思ってます!

前身技術やARを含めた詳細な歴史は、以下のページが参考になりそうです。

www.vrs.org.uk

www.moguravr.com