6.1. ウィンドウの指定
固定のカメラを使う場合に指定する視錐体の代わりに、ダイナミックカメラを使う場合はウィンドウを指定しなければなりません。ニアクリップ面とファークリップ面も同様に指定が必要です。
6.1.1. 仮想空間でのサイズを基にウィンドウを指定
カメラ中心からウィンドウの幅と深さを決めることができます。ウィンドウはカメラの Z 軸が中心になり、高さは本体の上画面と同じアスペクト比となるよう幅から計算されます。
ウィンドウ幅の比とウィンドウの深さが FOV を定めていることに注意してください。
この方法は、画像がスクリーン全体に表示されることを想定しています。
void SetWindowFromSize(const f32 windowWidth, const f32 nearDepth, const f32 windowDepth, const f32 farDepth);
6.1.2. ベースカメラ視錐体を基にウィンドウを導出
ベースカメラ視錐体の左辺、右辺、底辺、上辺への角度(タンジェント値)を指定することが可能です。この視錐体とウィンドウ深度の面との共通集合をウィンドウと定義します。この方法は、スクリーン全体をカバーしない場合のビューポート表現にも使えます。ビューポート境界のタンジェント値は、スクリーン正面の標準的なユーザー位置から計算されるべきです。ビューポート表現に合致する、スクリーンの最大領域に画像表示することを想定しています。
void SetWindowFromTangent(const f32 tangentLeft, const f32 tangentRight, const f32 tangentBottom, const f32 tangentTop, const f32 nearDepth, const f32 windowDepth, const f32 farDepth);
6.1.3. ビューポートからウィンドウを設定
スクリーンを部分的にカバーするビューポートを扱う場合、スクリーンのどこがビューポートなのかを知る必要があります。スクリーンを部分的にカバーするビューポートや現実感のある FOV を使う場合には、以下のメソッドが有用です。
void SetWindowFromViewport(const f32 screenHorizontalHalfFOVTangent, const f32 viewportLeftInUnitSceen, const f32 viewportRightInUnitSceen, const f32 viewportBottomInUnitSceen, const f32 viewportTopInUnitSceen, const f32 nearDepth, const f32 windowDepth, const f32 farDepth);
6.1.4. 既存のプロジェクション行列を基にウィンドウを設定
6.2. ベースカメラビューの指定
void SetView(const nn::math::MTX34* viewMatrix); void SetView(const nn::math::VEC3& position, const nn::math::VEC3& upDirection, const nn::math::VEC3& forwardDirection);
nn::math::MTX34LookAt
のような関数で生成されるビュー行列を指定する、もしくはベースカメラ位置を直接指定してください。ビュー行例や nn::math::Vector3
引数を指定するときに、CTR のグラフィックシステムに合うように右手座標系を使うことに注意してください。
6.3. 左目カメラと右目カメラの計算
f32 ComputeViewsAndProjections( nn::math::Matrix44* projL, nn::math::Matrix34* viewL, nn::math::Matrix44* projR, nn::math::Matrix34* viewR, const nn::math::VEC2* leftEyeTangent, const nn::math::VEC2* rightEyeTangent, const Setting& setting, const nn::math::PivotDirection pivot = nn::math::PIVOT_UPSIDE_TO_TOP ) const;
この関数は左目用画像と右目用画像をレンダリングするためのプロジェクション行列とビュー行列の生成に使います。
この関数では液晶から最適視認距離ほど離れた位置にユーザーがいると想定しています。現実に即したビューも、以下で説明する setting
引数に基づいた現実に即したわけではない(芸術的な)ビューも生成可能です。加えて、この関数はユーザーの頭の位置を考慮してダイナミックパースペクティブを調整することも可能です。
leftEyeTangent
引数と rightEyeTangent
引数はスクリーンに対するユーザーの左目の位置と右目の位置を表します。これらの値は nn::qtm::CTR::GetTrackingData
関数で取得できます。
leftEyeTangent
と rightEyeTangent
のいずれかが null
の場合、この関数の動作は(ダイナミックではない)静的な立体視カメラと同じになります。CTR 本体向けの開発であれば、この引数は null
となるはずです。
生成されるプロジェクション行列のカメラの上向き方向が、pivot
引数で規定される上向き方向になります。pivot
引数に nn::math::PIVOT_NONE
が設定された場合、回転は適用されません。pivot
引数に無効な値が指定されたら、関数はアサーションで止まります。デフォルトでは nn::math::PIVOT_UPSIDE_TO_TOP
が指定されます。
返り値はカメラ間の距離の係数 ƒIです。付録で説明します。
6.4. Setting クラス
struct Setting { f32 StereoFactor; f32 ParallaxDistanceLimit; f32 DynamicPerspectiveAmplitudeX; f32 DynamicPerspectiveAmplitudeY; f32 DynamicPerspectiveClampingLeft; f32 DynamicPerspectiveClampingRight; f32 DynamicPerspectiveClampingBottom; f32 DynamicPerspectiveClampingTop; f32 RealisticFovFactor; f32 WideFovMotionFactor; bool TiltEnabled; }
ComputeViewsAndProjections
関数の Setting
引数を使って立体視カメラの振る舞いを調整できます。
-
StereoFactor
は 4.7. 3D ボリュームと立体視係数 節で説明したように立体視効果を調整します。 -
ParallaxDistanceLimit
はミリメートルで指定する視差の限界値です。左目用画像のオブジェクトと右目用画像のオブジェクトの間の最大視差を意味します。4.6. 限界視差 節に説明があります -
DynamicPerspectiveAmplitudeX
とDynamicPerspectiveAmplitudeY
はユーザーの位置に乗算される係数です。頭の動きに対してダイナミックパースペクティブの効果を増幅させたり低減させたりするのに使います。 -
DynamicPerspectiveClampingLeft
、DynamicPerspectiveClampingRight
、DynamicPerspectiveClampingBottom
、DynamicPerspectiveClampingTop
はユーザー位置の水平方向および垂直方向のクランプに使います。これらは 0 から 1 の範囲の値をとります。1 が設定された場合は、GetTrackingData
で取得できる限界値で位置がクランプされます。中間の値が設定された場合は、限界値にたいして設定値に比例した位置でクランプされます。0 が設定された場合は、カメラは指定の方向には動かなくなります。DynamicPerspectiveAmplitude
による増幅の前にクランプがされることに注意してください。 -
RealisticFovFactor
は 4.2. 現実に即した FOV 係数 節で説明した現実に即したカメラとベースカメラの間にくるカメラ位置の補間に使われます。 -
WideFovMotionFactor
は 4.1. ワイド FOV 節で説明したワイド FOV の状況で、ユーザーの動き応じてカメラがどのように動くかを調整します。 -
TiltEnabled
は 4.5. 傾きと立体カメラの改善 節で説明した、傾きの有効無効を示します。
6.5. 占有領域
struct OccupancyVolume ( math::VEC3 CameraCenter; math::VEC3 ForwardDirection; math::VEC3 OrthoUpDirection; math::VEC3 RightDirection; f32 NearPlaneDepth; f32 NearLeft; f32 NearRight; f32 NearBottom; f32 NearTop; f32 CameraLeft; f32 CameraRight; f32 CameraBottom; f32 CameraTop; };
OccupancyVolume
構造体を使ってカメラの占有領域を表現できます。オブジェクトと交わることで不自然な見た目にならないことを保証するため、この領域にオブジェクトを置くべきではありません。
-
CameraCenter
はダイナミックパースペクティブを無効化したときのカメラ位置です。RealisticFovFactor
が 0 の場合、この位置はSetView
メソッドで指定される位置と同じです。0 より大きい場合、前方向の軸に沿ってカメラ位置が調整され、現実に即した FOV に近づきます。ダイナミックパースペクティブでカメラが動ける面のことをカメラ面と呼びます。 -
ForwardDirection
は前方向を示す単位ベクトルです。SetView
メソッドで指定された値と同じです。 -
OrthoUpDirection
は上方向を示す単位ベクトルです。ForwardDirection
と直交します。 -
RightDirection
は右方向を示す単位ベクトルです。ForwardDirection
とOrthoUpDirection
と直交するため、それらの外積を計算することで、右方向のベクトルを求めることができます。
RightDirection = ForwardDirection × OrthoUpDirection
-
NearPlaneDepth
はカメラ位置からニアクリップ面までの距離です。 -
NearLeft
とNearRight
はニアクリップ面における、(右方向ベクトルに沿った)水平方向の占有領域範囲です。 -
NearBottom
とNearTop
はニアクリップ面における、(上方向ベクトルに沿った)垂直方向の占有領域範囲です。 -
CameraLeft
とCameraRight
はカメラ面における水平方向の占有領域範囲です。 -
CameraBottom
とCameraTop
はカメラ面における垂直方向の占有領域範囲です。