前回はSabilizationPlaneの基本的な挙動について触れました。Mixed Reality Toolkit には、標準でこの安定化平面の位置を設定するスクリプトが含まれています。
InputManager PrefabにアタッチされているスクリプトにStabilizationPlaneModifierがその役目を担っています。
安定化平面の位置決め方法
更新はLateUpdateで行われ、3パターンの方法で安定化平面の位置が決定づけられます。
- TagertObjectを指定する場合
- Gaze位置ベースで位置を指定する場合
- 位置を固定する場合
if (SetStabilizationPlane) { float deltaTime = UseUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime; //TagertObjectを指定する場合 if (TargetOverride != null) { ConfigureTransformOverridePlane(deltaTime); } //Gaze位置ベースで位置を指定する場合 else if (UseGazeManager) { ConfigureGazeManagerPlane(deltaTime); } //位置を固定する場合 else { ConfigureFixedDistancePlane(deltaTime); } }
設定項目
- SetStabilizationPlane: 安定化平面を用いるか
- Use Unscaled Time: 安定化平面の位置補間用の速度計算にTime.deltaTimeを利用するか、Time.unscaleddDeltaTimeを利用するか
- Lerp Stabilization Plane Closer: 安定化平面がカメラに近づく方向に移動する際の速度の重み
- Lerp Stabilizaiton Plane Father: 安定化平面がカメラから遠ざかる方向に移動する際の速度の重み
- Target Override: 強制的に安定化平面を適応したいオブジェクト
- Track Velocity: Target Overrideにオブジェクトを指定した際に、オブジェクトの移動速度をSetFocusPointに利用する
- Use GazeManager: Gaze位置をもとに安定化平面を決定する
- Default Plane Distance: デフォルトの安定化平面の距離
- DrawGizmo: デバッグ用の安定化平面を表示する
適応される優先度は
Target Override -> GazeManager -> Default Distance の順です。
Target OverrideにGameObjectを指定した際は、GazeManagerやDefault Distanceで設定した値は使われません。
OverridePlane
オブジェクトの位置ベース設定
やっていることは前回のブログの内容と同じです。SetFocusPointForFrameにオブジェクトの位置、カメラの向いている向きの逆方向を渡します。加えて速度を入力として与えます。速度は、単純に位置の変化量を時間で割っているだけです。
/// <summary> /// Configures the stabilization plane to update its position based on an object in the scene. /// </summary> private void ConfigureTransformOverridePlane(float deltaTime) { //Targetとなるオブジェクトの位置を取得 planePosition = TargetOverride.position; //速度決定 Vector3 velocity = Vector3.zero; if (TrackVelocity) { velocity = UpdateVelocity(deltaTime); } #if UNITY_WSA // Place the plane at the desired depth in front of the user and billboard it to the gaze origin. //FocusPointをオブジェクトの位置、カメラと向きと逆方向、速度をセットする HolographicSettings.SetFocusPointForFrame(planePosition, -GazeNormal, velocity); #endif }
速度の計算
/// <summary> /// Tracks the velocity of the target object to be used as a hint for the plane stabilization. /// 安定化平面へ与えるヒントとして利用されるターゲットオブジェクトの速度の追跡 /// </summary> private Vector3 UpdateVelocity(float deltaTime) { // Roughly calculate the velocity based on previous position, current position, and frame time. // 前の位置、現在の位置、およびフレーム時間に基づいて、速度を大まかに計算。 // 速度=単位時間あたりの位置の変化量 Vector3 velocity = (TargetOverride.position - targetOverridePreviousPosition) / deltaTime; // 位置の更新 targetOverridePreviousPosition = TargetOverride.position; return velocity; }
GazeManagerPlane
Gaze位置を利用した設定
GazeManagerPlaneでは、向いている方向に対してオブジェクトがあるかないかに基づいて安定化平面を決定します。
ない場合はカメラからの固定の距離で設定されます。
/// <summary> /// Configures the stabilization plane to update its position based on what your gaze intersects in the scene. // シーン内で視線が交差する位置を基に、安定化平面の位置を更新してを設定する /// </summary> private void ConfigureGazeManagerPlane(float deltaTime) { Vector3 gazeOrigin = GazeOrigin; Vector3 gazeDirection = GazeNormal; // Calculate the delta between gaze origin's position and current hit position. If no object is hit, use default distance. // Gazeが出るもと(カメラ)の位置と現在のヒットしている位置の変位を計算する。ヒットしていない場合はデフォルトの距離を用いる。 float focusPointDistance; Vector3 gazeHitPosition; // GazeManager.Instance.HitPositionでヒットしているかどうかを取得しています if (TryGetGazeHitPosition(out gazeHitPosition)) { focusPointDistance = (gazeOrigin - gazeHitPosition).magnitude; } else { focusPointDistance = DefaultPlaneDistance; } // FocusPointと現在の平面の位置関係をみて、近づくのかと遠のくのかを決定します。 float lerpPower = focusPointDistance > currentPlaneDistance ? LerpStabilizationPlanePowerFarther : LerpStabilizationPlanePowerCloser; // Smoothly move the focus point from previous hit position to new position. // 現在位置とフォーカスポイントの距離を補間します。 currentPlaneDistance = Mathf.Lerp(currentPlaneDistance, focusPointDistance, lerpPower * deltaTime); //向いている方向をもとに平面の最終的な位置を決定します。 planePosition = gazeOrigin + (gazeDirection * currentPlaneDistance); #if UNITY_WSA HolographicSettings.SetFocusPointForFrame(planePosition, -gazeDirection, Vector3.zero); #endif }
FixedDistancePlane
固定距離の安定化平面 あまり解説することはありません。常にカメラからの固定距離に平面が設定されます。
/// <summary> /// Configures the stabilization plane to update based on a fixed distance away from you. /// 自分の位置に基づいて、固定距離に安定化平面を設定する /// </summary> private void ConfigureFixedDistancePlane(float deltaTime) { Vector3 gazeOrigin = GazeOrigin; Vector3 gazeNormal = GazeNormal; float lerpPower = DefaultPlaneDistance > currentPlaneDistance ? LerpStabilizationPlanePowerFarther : LerpStabilizationPlanePowerCloser; // Smoothly move the focus point from previous hit position to new position. currentPlaneDistance = Mathf.Lerp(currentPlaneDistance, DefaultPlaneDistance, lerpPower * deltaTime); planePosition = gazeOrigin + (gazeNormal * currentPlaneDistance); #if UNITY_WSA HolographicSettings.SetFocusPointForFrame(planePosition, -gazeNormal, Vector3.zero); #endif }
以上3つの方法で安定化平面の位置を決めています。前回あれこれ考えていましたが、内包されているものはシンプルでした。