3

これで、世界に投影されていないマウスを表す光線を正常に作成できました。次に、その光線がクワッド オブジェクトと交差できるかどうかを確認する必要があります。光線を取得するために使用するコードは次のとおりです。

public Ray GetMouseRay()
    {
        Vector2 mousePosition = new Vector2(cursor.getX(), cursor.getY());

        Vector3 nearPoint = new Vector3(mousePosition, 0);
        Vector3 farPoint = new Vector3(mousePosition, 1);

        nearPoint = viewport.Unproject(nearPoint, projectionMatrix, viewMatrix, Matrix.Identity);
        farPoint = viewport.Unproject(farPoint, projectionMatrix, viewMatrix, Matrix.Identity);

        Vector3 direction = farPoint - nearPoint;
        direction.Normalize();

        return new Ray(nearPoint, direction);
    }

同様に、これは 3D 空間で「立方体の世界」を描画するために使用する私の quad 構造体です。public struct Quad { public Vector3 Origin; public Vector3 アッパーレフト; public Vector3 LowerLeft; パブリック Vector3 右上; public Vector3 LowerRight; public Vector3 通常。パブリック Vector3 アップ; public Vector3 左。

    public VertexPositionNormalTexture[] Vertices;
      public int[] Indexes;
    public short[] Indexes;


    public Quad( Vector3 origin, Vector3 normal, Vector3 up, 
        float width, float height )
    {
        Vertices = new VertexPositionNormalTexture[4];
        Indexes = new short[6];
        Origin = origin;
        Normal = normal;
        Up = up;

        // Calculate the quad corners
        Left = Vector3.Cross( normal, Up );
        Vector3 uppercenter = (Up * height / 2) + origin;
        UpperLeft = uppercenter + (Left * width / 2);
        UpperRight = uppercenter - (Left * width / 2);
        LowerLeft = UpperLeft - (Up * height);
        LowerRight = UpperRight - (Up * height);

        FillVertices();
    }

    private void FillVertices()
    {
        // Fill in texture coordinates to display full texture
        // on quad
        Vector2 textureUpperLeft = new Vector2( 0.0f, 0.0f );
        Vector2 textureUpperRight = new Vector2( 1.0f, 0.0f );
        Vector2 textureLowerLeft = new Vector2( 0.0f, 1.0f );
        Vector2 textureLowerRight = new Vector2( 1.0f, 1.0f );

        // Provide a normal for each vertex
        for (int i = 0; i < Vertices.Length; i++)
        {
            Vertices[i].Normal = Normal;
        }

        // Set the position and texture coordinate for each
        // vertex
        Vertices[0].Position = LowerLeft;
        Vertices[0].TextureCoordinate = textureLowerLeft;
        Vertices[1].Position = UpperLeft;
        Vertices[1].TextureCoordinate = textureUpperLeft;
        Vertices[2].Position = LowerRight;
        Vertices[2].TextureCoordinate = textureLowerRight;
        Vertices[3].Position = UpperRight;
        Vertices[3].TextureCoordinate = textureUpperRight;

        // Set the index buffer for each vertex, using
        // clockwise winding
        Indexes[0] = 0;
        Indexes[1] = 1;
        Indexes[2] = 2;
        Indexes[3] = 2;
        Indexes[4] = 1;
        Indexes[5] = 3;
    }
}

ray クラスには、平面構造体をパラメーターとして取るメソッド intersects() があり、平面構造体はコンストラクターで法線と原点からの距離を取ることがわかりましたが、私の平面には、原点からの距離だけでなく、位置と法線があります、だから私はそれらを変換することはできません。光線が quad 構造体と交差しているかどうかを検出するにはどうすればよいですか?

編集: クワッドのように有限サイズではなく、コーナーが含まれていないため、平面構造体を使用できないことに気付きました。このレイが作成したクワッドと交差しているかどうかを検出する方法を見つける必要があります...

読んでくれてありがとう。この質問は少し長いと思います。よろしくお願いします。

4

3 に答える 3

3

「原点からの法線に沿った距離」が何を意味するのか正確にはわかりませんが、原点からの距離を意味しているだけだと思います。これは、 Vector3の length プロパティから取得できます。

それがうまくいかない場合は、平面上の 3 点を取る平面のコンストラクターもあります。

public Plane (
     Vector3 point1,
     Vector3 point2,
     Vector3 point3
)

クワッドのコーナーなど、平面上の任意の 3 点でこれを使用して、平面を作成できます。

于 2012-10-24T03:17:31.050 に答える
1

キューブを使用しているため、Ray.Intersects(Plane)メソッドを使用できます。あと数機必要です。

最初の交点を決定したら、立方体の垂直面ごとにさらに平面を作成できます。次に、Plane.Distance(Vector3)(これまたはそれに似たものが存在すると確信しています)を使用して、ポイントが垂直面の各ペアの間にあることを確認できます。それらの間にない場合は、交差点を無視できます。

于 2012-10-24T16:39:52.607 に答える
0

あなたの質問に対する正確な答えではありませんが、おそらくこれは関連性があると思います。

BoundingBox オブジェクトを作成して Intersects(Ray) を使用することを検討しましたか? http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.boundingbox.intersects.aspx

編集1:それは私が通常行う方法です。データ構造によっては、最適化が容易になる場合もあります (たとえば、ボアする大きなバウンディング ボックスを構築する場合)。

編集2:Nikoの提案によると:サンプルから関連するコードを投稿したくありません(コンテキストを理解するために合計で数ページの長さになるため)。に興味を持つでしょう。

  1. http://xbox.create.msdn.com/en-US/education/catalog/sample/picking_triangleからサンプルをダウンロードします
  2. Cursor.cs ファイルの下部には、光線を計算する既知の内容が含まれています。
  3. Game.cs ファイルに移動します。そこには、RayIntersectsTriangle(...) を呼び出す RayIntersectsModel(...) を呼び出す UpdatePicking() があります。

Ray の変換は次の部分です。

Matrix inverseTransform = Matrix.Invert( modelTransform );

ray.Position = Vector3.Transform( ray.Position, inverseTransform );
ray.Direction = Vector3.TransformNormal( ray.Direction, inverseTransform );

もちろん、どこまで深く掘り下げるか (どれだけ正確にピッキングするか) はニーズ次第ですが、その通りです。

于 2012-10-24T14:21:04.970 に答える