ぼっちプログラマのメモ

UE4とかUE5とかについて書いたり書かなかったり。

OculusRift用のレティクルを自作

OVRPlayerControllerには元々レティクル表示機能(OVRCrossHair)がありますが、
表示に使用している2次元座標(OVRCrossHairのXL,YL)が使いにくかったり、
3次元座標にしようとすると色々おかしくなったり、
マウス位置と完全に連動していなかったりで、
ストレスMAXになったので自作…という経緯

レティクル表示に必要なもの

とりあえず、必要なものを洗い出し

マウスのスクリーン座標取得とビルボード表示については
解説サイトが山ほどあるので、2番めのカメラの取得について説明というかメモ

OVRでのカメラ取得方法

ステレオカメラなどで色々と面倒かと思いきや、案外簡単。
OVRCrossHairを見てみると、↓のコードでカメラを取得している様に見える

CameraController.GetCamera (ref MainCam);

CameraController.GetCameraの中身を見てみると、

public void GetCamera(ref Camera camera)
{
	camera = CameraRight;
}

…え、右側のカメラを使っているだけ?
補間などの面倒な処理をしているかと思っていたので拍子抜け

f:id:pafuhana1213:20130908144209j:plain
f:id:pafuhana1213:20130908144211j:plain

で、色々してこんな感じでできました

  1. マウスのスクリーン座標を取得
  2. 以前の記事で書いた方法で、マウスカーソルの3次元座標を計算
  3. 計算した3次元座標にビルボード表示

詰まった所メモ

  • GUITextureでレティクル表示しようとしたのですが、ステレオカメラ+OculusRift表示用の歪み補正などが重なっているせいか、なかなか上手くいかなかったので却下
    • Screenを用いた情報はあまり使用しない方がいい?
      • Plane+ビルボード表示を使用。デプステストへの対応が今後必要になると予想

OculusRiftで女性目線から見るおっ◯いを再現

デバッグ用にカメラの当たりを可視化

OVRPlayerControllerのPrefabは便利ですが、StandardAssetsのFirstPerson~のように
カプセルを置いておくと分かりやすいな~と思ったので早速実装

実装前
f:id:pafuhana1213:20130901234534j:plain

実装後
f:id:pafuhana1213:20130901234540j:plain

分かり…やすくなった…と信じたい…
少なくとも、どの辺りにカメラがあるのは分かるように…


やったことは、「ForwardDirection」の子にCapsule描画と、
↓のコードで作ったスクリプトをぶち込んだだけ。

public Vector3 Center = Vector3.zero;
public float Radius = 0.0f;
public float Height = 0.0f;
public GameObject Parent = null;
public CharacterController ParentController = null;
	
// Use this for initialization
void Start () {
	// 設定されていない場合、親のgameObjectを取得
	if( null == Parent ){
		Parent = gameObject.transform.parent.gameObject;
	}
	// 対象のCharacterControllerを取得
	ParentController = (CharacterController)Parent.GetComponent( "CharacterController" );
}
	
// Update is called once per frame
void Update () {
	// 各パラメータを取得
	if( null !=  ParentController ){
		Center = ParentController.center;
		Radius = ParentController.radius;	
		Height = ParentController.height;
	}
	
	Vector3 scale = this.transform.localScale;
	scale.x = Radius / 0.5f;
	scale.y = Height / 2.0f;
	scale.z = Radius / 0.5f;
	this.transform.localScale = scale;
}

親のCharacterControllerからパラメータ取ってきて、TransformのScaleに反映しているだけ
超簡単!


おまけ(という名の本編)

f:id:pafuhana1213:20130902234751j:plain
д゚)…(カプセルの代わりに、Lat式のモデルを使って…)

f:id:pafuhana1213:20130902234946j:plain
д゚)…(下を見てみると…ちっぱい…)


f:id:pafuhana1213:20130902235406j:plain
( ゚∀゚)o彡°


公開:https://dl.dropboxusercontent.com/u/30427841/Unity_web/oppai.zip

OVRPlayerControllerを改造しようとしたけど…

今後に向け、OculusRift用カメラのコントローラーである
OVRPlayerControllerを自分用に改造することに。

直接SDKのファイルを弄るのは色々とアレなので、
てきとーな名前に変えたファイル・クラスで作成開始。

とりあえず、中身をほぼそのまま移して、
英語コメントを訳したり、コードが汚い部分を整理して、
他のファイルとの整合性を調整して、
PrefubのController部分を入れ替えて、実行すると…

BroadcastException: Broadcasting message "Sensor_Attached" but listeners have a different signature than the broadcaster.
OVRMessenger.Broadcast[Device,Boolean] (System.String eventType, Device arg1, Boolean arg2) (at Assets/OVR/Scripts/OVRMessenger.cs:293)
OVRDevice.Update () (at Assets/OVR/Scripts/OVRDevice.cs:288)

よく分からないエラー発生\(^o^)/


公式フォーラムに同じような質問を投げている人がいるけど、解決してない!/(^o^)\
https://developer.oculusvr.com/forums/viewtopic.php?t=1110&p=11959

とりあえず、色々と調べたみたけど…

  • Prefubの「OVRMain Menu」を無効化すると正常に動作する
  • 独自ファイルで書いていたコードを「OVRPlayerController.cs」にコピペして実行すると正常に動作(謎)
  • 原因は、OVRPlayerController.cs以外のクラス名(又はファイル名)を使ったこと…?
  • 一時的処置として、SDK内のファイルでOVRPlayerController型で宣言されているものは、今回実装した独自の型に変えている(ビルドは通るが、実行時にエラー)

…ぎぶあっぷ

↑にも書いた通り、SDK内のファイルに直で書いたら
問題なく通るので…しばらくは直書きで…
(定期的に実装したコードを保存しないと、SDKアップデート時に上書きされてしまいそう…)

OculusRift+MMDforUnityで、ミクさんと一緒に散歩してみる その3(完成?)

前回の続き

OculusRiftに対応したSkyboxを使ってみる

通常のSkyboxをOculusRift用のステレオカメラに適応しても上手く重ならないので、
↓のサイトで紹介されている「SkyboxMesh.cs」を使ってみる。
http://d.hatena.ne.jp/hecomi/20130721/1374372218


f:id:pafuhana1213:20130901015837j:plain

これまでの一色の背景に比べると、見栄えが段違いに良くなるな~
製作者に感謝感謝

※ 注意
SceneビューにもSkyboxを表示されることは以下のサイトにある方法で可能ですが、
SkyboxMesh.csと競合しているせいなのか、OculusRift上で上手く重ならなくなりました

http://www40.atwiki.jp/spellbound/pages/1339.html#id_24f01384

ImageEffect(ポストエフェクト)を使ってみる

せっかくのUnity proなので、pro限定のImageEffectを使ってみる。
OculusRiftを使う場合、OVRCameraController下のCameraLeft,CameraRightに
ImageEffectコンポーネントを追加することで、ポストエフェクトを導入することができます。

UnityのImageEffect一覧:http://docs-jp.unity3d.com/Documentation/Components/comp-ImageEffects.html

とりあえず、使用前(左)と使用後(右)の比較画像を
f:id:pafuhana1213:20130901020719j:plain

使用したImageEffect
・Antialiasing As Post Effect
・Screen Overlay
・Sun Shafts

ただでさえ可愛いミクさんが、エフェクトで神々しい感じに…というイメージで
OculusRiftで見ると、SunShaftsは飛び出して見えて面白い感じ

一応、全部のImageEffectを触ってみたのですが、
DOFなどのガチ画像編集系だと上手く働かないことが多かったです。
OculusRiftへ適応するための歪み処理が影響しているからかも…?

MMD用のステージデータを使ってみる

最後に、MMD用に作られたステージをUnityで使えるか試してみる。

まず、ステージデータはこのサイトを参考に探す所から
http://www6.atwiki.jp/vpvpwiki/pages/410.html

軽く見ただけですが、「.x」「.pmd」「.pmx」形式が使用されているみたい。

各形式のUnityでの使用法についてですが、

.pmd:モデルデータと同様の流れで使用可能
.x :PMDエディタで.pmd形式に変換。あとは同じ流れ
.pmx:PMDエディタで(ry

…PMDエディタが優秀過ぎる


で、今回は↑のサイトから「アキ〇バラステージ」(x形式)を使用
f:id:pafuhana1213:20130901034746j:plain
f:id:pafuhana1213:20130901034922j:plain

キタ━━━━(゚∀゚)━━━━!!(SunShafts効きすぎ…)


画像じゃ伝わりませんが、OculusRift着けて見上げると
なかなかの迫力!買ってよかった、OculusRift!


※ステージデータを使用する過程で引っかかった部分
PMD Loaderで生成したPrefabをHierarchyに追加して実行すると
こんな感じのエラーメッセージが表示されて止まります

NullReferenceException
UnityEngine.Component.GetComponent[MMDSkinsScript] ()

解決策は、ステージデータPrefabの子であるExpressionの
「Expression Manager Script」を無効化すること
(特に、描画に影響は見当たらないのでたぶん大丈夫…)


今回でミクさんとのお散歩は終了。記念に実行ファイルをアップ
OculusRiftなしでも一応実行できますが、↑の画像と同じように分割された絵になります…
https://dl.dropboxusercontent.com/u/30427841/Unity_web/walk_inAkiba.zip


次からはゲームっぽいものを作ろうかな~