0

3D ピッキングについて助けが必要です。

ここで動作する方法を使用しています。要するに、私が持っているものは次のとおりです。

normalizedPoint[0] = (x * 2 / screenW) -1;
normalizedPoint[1] = 1 - (y * 2 / screenH);
normalizedPoint[2] = ?
normalizedPoint[3] = ?

2と3の場合、どうあるべきかわかりません(参照のように1、-1を入れましたが、機能しません)

次に、私のルート オブジェクトの場合 (疑似コードのみに従います):

matrix = perspective_matrix x model_matrix
inv_matrix = inverse(matrix)
outpoint = inv_matrix x normalizedPoint

それは私が持っているものですが、うまくいきません。受け取った outPoint は、クリックしたと思われるポイントにさえ近くありません。私は一週間以上ウェブで検索してきました。しかし、それを解決する方法がわかりません。ヘルプ!

4

1 に答える 1

3

おー。私は実際に問題を解決しました。

まず、glUnproject のソース コードを次のように変更します。

public static Vec3 unProject(
        float winx, float winy, float winz,
        Matrix44 resultantMatrix,
        int width, int height){
    float[] m = new float[16],
    in = new float[4],
    out = new float[4];

    m = Matrix44.invert(resultantMatrix.get());

    in[0] = (winx / (float)width) * 2 - 1;
    in[1] = (winy / (float)height) * 2 - 1;
    in[2] = 2 * winz - 1;
    in[3] = 1;

    Matrix.multiplyMV(out, 0, m, 0, in, 0);

    if (out[3]==0)
        return null;

    out[3] = 1/out[3];
    return new Vec3(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}

上記への入力は、投影ビュー フラスタム座標 (つまり、画面入力) 内のポイントになります。例えば:

unProject(30, 50, 0, mvpMatrix, 800, 480) 

(30,50) での画面入力 (クリック) を、オブジェクトが置かれているワールド座標に変換します。3 番目のパラメータwinzは、実際にはクリックが発生した投影面です。ここで、0 は投影面の NearZ を意味します。

ピッキング関数を作成する方法は、上記の関数を使用して、遠くと近くのクリッピング プレーンで 2 点を非投影にすることです。

Vec3 near = unProject(30, 50, 0, mvpMatrix, 800, 480);
Vec3 far = unProject(30, 50, 1, mvpMatrix, 800, 480);   // 1 for winz means projected on the far plane
Vec3 pickingRay = Subtract(far, near); // Vector subtraction

ピッキング レイを取得したら、ピッキング レイと「選択可能な」オブジェクトの「中心」との間の距離をテストするだけです。(もちろん、より洗練されたテスト アルゴリズムを使用することもできます)。

于 2011-06-24T00:48:05.903 に答える