0

ゲームで gluProject を使用しようとしています。使い方はわかったのですが、回転の扱い方がわかりません。

ここに私が作ったコードがあります:

public static Vector2 getScreenCoordinates(float x, float y, float z, int height, int width)
{
    FloatBuffer screen_coords = GLAllocation.createDirectFloatBuffer(4);
    IntBuffer viewport = GLAllocation.createDirectIntBuffer(16);
    FloatBuffer modelview = GLAllocation.createDirectFloatBuffer(16);
    FloatBuffer projection = GLAllocation.createDirectFloatBuffer(16);

    GL11.glGetFloat(2982, modelview);
    GL11.glGetFloat(2983, projection);
    GL11.glGetInteger(2978, viewport);

    boolean result = GLU.gluProject(x, y, z, modelview, projection, viewport, screen_coords);
    if (result)
    {
        float screen_x = screen_coords.get(0);
        float screen_y = screen_coords.get(1);
        float scrren_z = screen_coords.get(2);

        screen_y -= height / 2;
        screen_y = -screen_y;
        screen_y += height / 2;

        return new Vector2(screen_x, screen_y);
    }
    else
    {
         System.out.printf("Failed to convert 3D coords to 2D screen coords");
         return null;
    }
}

とは、私xの3D マップの座標です。と私のウィンドウサイズです。yzheightwidth

回転 (ヨーとピッチ) を処理するように変更するにはどうすればよいですか?

ありがとう。


ここに私の新しいコードがあります:

public Vector2 worldToScreen(double x, double y, double z, int yaw, int pitch)
{   
    // Initialize the result buffer
    FloatBuffer screen_coords = GLAllocation.createDirectFloatBuffer(4);

    // Init the OpenGL buffers
    IntBuffer viewport = GLAllocation.createDirectIntBuffer(16);
    FloatBuffer modelview = GLAllocation.createDirectFloatBuffer(16);
    FloatBuffer projection = GLAllocation.createDirectFloatBuffer(16);

    // Add the rotation
    GL11.glRotatef(yaw, 0, 0, 1);
    GL11.glRotatef(pitch, 1, 0, 0);

    // Get the OpenGL data
    GL11.glGetFloat(2982, modelview);
    GL11.glGetFloat(2983, projection);
    GL11.glGetInteger(2978, viewport);

    // Remove the rotation
    GL11.glRotatef(-yaw, 0, 0, 1);
    GL11.glRotatef(-pitch, 1, 0, 0);

    // Calculate the screen position
    boolean result = GLU.gluProject(x, y, z, modelview, projection, viewport, screen_coords);

    if (result)
    {
        if ( (screen_coords.get(0) < -1.0f) || (screen_coords.get(0) > 1.0f) || (screen_coords.get(1) < -1.0f) || (screen_coords.get(1) > 1.0f) )
            return null;

        int window_half_width = getWidth() / 2;
        int window_half_height = getHeight() / 2;

        int screen_x = window_half_width + (window_half_width * -screen_coords.get(0));
        int screen_y = window_half_height + (window_half_height * screen_coords.get(1));

        System.out.printf("(Full Screen / No bounds) [" +x+ ", " +y+ ", " +z+ "] gives [" +screen_coords.get(0)+ ", " +screen_coords.get(1)+ "]");
        System.out.printf("(Every Time) [" +x+ ", " +y+ ", " +z+ "] gives [" +screen_x+ ", " +screen_y+ "]");
        return new Vector2(screen_x, screen_y);
    }
    else
    {
        System.out.printf("Failed to convert 3D coords to 2D screen coords");
        return null;
    }
}

あれは正しいですか?

4

1 に答える 1

1

ヨーは y 軸 (上向き) を中心とした回転であり、ピッチは x 軸を中心とした回転です。

GL11.glRotatef(pitch, 1, 0, 0);
GL11.glRotatef(yaw, 0, 1, 0);

射影行列をプッシュ/ポップする方が速い場合もあり、正しい行列モードにする必要があります。(モデル ビュー マトリックスと射影マトリックスの両方が正しくなければなりません)。

GL11.glPushMatrix();
// Camera rotations
GL11.glPopMatrix();

しかし、カメラの変換を元に戻す必要がある理由については疑問です。フレームまたはビューポートごとに 1 回だけ適用する必要があります。そのビューでシーンをレンダリングし、投影された座標を取得してから、2D レンダリング モードに変更します。

アップデート

カメラに関して、OpenGLの座標系で実際に意味するものを意味するために、カメラのロール、ピッチ、ヨーを使用した方がいいと思います。ポイントは、カメラのモデル ビューと射影マトリックスが正しく設定されている限り、ポイントを射影できることです。すでにどこかにカメラをセットアップしている必要があります。結果を見ることができるので、これが正しいかどうかを確認できます。その変換を適用すると、それが正しいことがわかります。

これは正しいです?それは可能性があります?すべての変換を適用する必要があります。ゲームで見るカメラ ビューとまったく同じ変換です。これには、すべての平行移動と回転が含まれます。ゲーム内でこれらの変換を既に適用しているはずなので、正しいかどうかはわかります。

ただし、考えなければならないのは、事前にカメラの射影行列とは何ですか? わからない場合は、glLoadIdentity() を呼び出してクリアしてから、カメラ変換ロジックを呼び出してください。正確なモデル ビューと投影マトリックスが必要です。これは、ゲーム内で使用しているのとまったく同じカメラ設定です。モデルビューまたは射影行列が間違った状態にある場合、それは機能しません。

于 2012-04-10T11:38:32.940 に答える