CameraからPlaneを取得する
カメラから視錐台の面の情報であるPlaneを取得します。
//[0] = Left, [1] = Right, [2] = Down, [3] = Up, [4] = Near, [5] = Far
var planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
なお、このメソッドの返り値はPlaneの配列になっていて、
左、右、下、上、手前、奥の順番に格納されています。
GeometryUtility-CalculateFrustumPlanes - Unity スクリプトリファレンス
錐台平面を計算します
平面の方程式を使って式を計算する
次に平面の方程式を使って式を計算します。
平面の方程式は以下です。
$$ax + by + cz + d = 0$$
\(a\)\(b\)\(c\)は平面の法線ですが、
Planeクラスは法線をプロパティとして用意しているので以下のように書けます。
var leftPlane = planes[0];
var a = leftPlane.normal.x;
var b = leftPlane.normal.y;
var c = leftPlane.normal.z;
\(d\)は通常、平面上の点を代入して求めますが、Planeクラスのプロパティに原点からの距離が用意されているので、それを使って以下のように書けます。
$$d = D * \sqrt{a^2 + b^2 + c^2}$$
var leftPlane = planes[0];
var d = leftPlane.distance * Mathf.Pow(a * a + b * b + c * c, 0.5f);
代入する
平面の方程式を解いたので、必要な値を式に代入して答えを出します。
今回は_targetのx軸だけを動かしてカメラの視錐台の交点(_result)を算出することにします。
var pos = _target.position;
var x = -(b * pos.y + c * pos.z + d) / a;
_result.position = new Vector3(x, pos.y, pos.z);
結果
最終的なコードと結果はこちらです。
public class CameraFrustum : MonoBehaviour
{
[SerializeField]
private Transform _target;
[SerializeField]
private Transform _result;
private void Update()
{
//[0] = Left, [1] = Right, [2] = Down, [3] = Up, [4] = Near, [5] = Far
var planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
var leftPlane = planes[0];
var a = leftPlane.normal.x;
var b = leftPlane.normal.y;
var c = leftPlane.normal.z;
var d = leftPlane.distance * Mathf.Pow(a * a + b * b + c * c, 0.5f);
var pos = _target.position;
var x = -(b * pos.y + c * pos.z + d) / a;
_result.position = new Vector3(x, pos.y, pos.z);
}
}
青が_targetで、赤が_resultです。
まとめ
Planeクラスと平面の方程式を使って簡単に実装できました。
どのような場面でこの知識が使われるかは不明ですが、
僕はエフェクトが画面から見切れないようにするために使いました。
ちなみに、PlaneクラスにRayの交点や最も近い交点を返すメソッドがあり、
ご紹介したものと似たような処理ができますのでそちらも合わせてみておくとよいと思います。
Plane - Unity スクリプトリファレンス
3D 空間での平面の表示
Planeクラスで実行できるメソッドの結果が動画で見たい方は、
こちらのサイトがとても分かりやすいのでチェックしておくとよいと思います。
【Unity】平面の計算を楽できるPlane構造体の使い方
Unityには、平面に関する計算を楽に扱えるようにしたPlane構造体が存在します。 このPlane構造体を用いると、次のような計算を楽に行うことが可能です。 これらの計算をPlane構造体のメソッドで行うことにより、数 ...
コメント