よく理解する必要がある最初のことは、3Dポイントを2Dスクリーン座標に変換し、再び戻すことです。ここでは、そのテーマについて私が出したいくつかの回答を示します。3Dから画面へ、3Dから2D への理解。
ここで、マウス座標から2Dから3Dに移動するには、3Dから2Dへの逆変換を行う必要があります。これはかなり簡単です。
オブジェクト/ローカル座標は、ワールドマトリックス(世界座標を取得)、ビューマトリックス(カメラを基準に世界座標を作成)、投影行列(スクリーン座標を取得)で乗算することにより、画面空間に変換されます。 。
これを逆に行うのは簡単です。すべての行列を反転します。次に、逆投影法を掛け、次に逆ビュー行列を掛けます。これで、マウスの3D座標がなくなります。その理由は、データのディメンションが欠落していたためです。だからあなたが持っているのは代わりに光線です。しかし、それは良いことです。光線には定義座標があり、カメラがベクトルを見ている方向と同じ方向を指します。また、オブジェクトのワールドマトリックスを反転する必要がないことに気付くかもしれません。これは、オブジェクト/ローカルスペースに光線を本当に必要としないからです。意味がありません。おそらく、コリジョンボリュームをワールドスペースでも定義します。
これで、光線がオブジェクトと交差するかどうかを確認するために、円/ボックス/ポリ光線の交差テストを行うだけです。
交差するすべてのオブジェクトを見つけ、リストを保持します。次に、各オブジェクトのカメラからの距離を計算します。カメラに最も近いものは、ユーザーが選択したいものです。
これは、XNAでこれを行うために必要なコードです。このソリューションは、他の種類のプロジェクトでも機能するはずです(最初に変換する限り)。2Dスプライトのみをレンダリングする場合は、おそらく射影行列を使用していないので、関数をMatrix.Identityに渡します。
using System;
using Microsoft.Xna.Framework;
namespace FluxPrototype
{
/// <summary>
/// Contains functions useful in working with XNA Vectors.
/// </summary>
static class VectorHelper
{
/// <summary>
/// Converts a Vector2 position into a 3D ray.
/// </summary>
/// <param name="Position">The 2D position.</param>
/// <param name="View">The view matrix for the camera.</param>
/// <param name="Projection">The projection matrix for the camera.</param>
/// <param name="Point">The returned point defining part of the 3D ray.</param>
/// <param name="Direction">The direction of the 3D ray.</param>
public static void Unproject(Vector2 Position, Matrix View, Matrix Projection, out Vector3 Point, out Vector3 Direction)
{
if (Position == null)
Position = Vector2.Zero;
// Create two 3D points from the position. The first one we will return.
Point = new Vector3(Position, 0);
Vector3 Point2 = new Vector3(Position, 1);
// Transform the points.
Matrix InvertedProjection = Matrix.Invert(Projection);
Point = Vector3.Transform(Point, InvertedProjection);
Point2 = Vector3.Transform(Point2, InvertedProjection);
Matrix InvertedView = Matrix.Invert(View);
Point = Vector3.Transform(Point, InvertedView);
Point2 = Vector3.Transform(Point2, InvertedView);
// Use the difference between the points to define the ray direction.
// This will only be the camera direction if the view frustum is orthographic.
Direction = (Point2 - Point);
Direction.Normalize();
}
}
}