0

「画面」座標を「表示」座標に変換する関数を作成しました。これは次のようになります(C#の例):

Vector2 ScreenToViewCoords(Point p)
{
    return new Vector2(
        _projMatrix.M11 * p.X + _projMatrix.M12 * p.Y + _projMatrix.M14,
        _projMatrix.M21 * p.X + _projMatrix.M22 * p.Y + _projMatrix.M24
    );
}

pOpenGLコントロール/ビューポートの左上隅を基準にしたポイント(ピクセル単位)です。

_projMatrix私の射影行列です。

私のレンダリング関数は次のようになります。

private void Render()
{
    GL.MatrixMode(MatrixMode.Projection);
    GL.LoadMatrix(ref _projMatrix);

    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();

    if (_texture != null)
    {
        _texture.Bind();
        GL.Color3(Color.White);
        GL.Begin(BeginMode.Quads);
        {
            GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
            GL.TexCoord2(0, 1); GL.Vertex2(0, _texture.Height);
            GL.TexCoord2(1, 1); GL.Vertex2(_texture.Width, _texture.Height);
            GL.TexCoord2(1, 0); GL.Vertex2(_texture.Width, 0);
        }
        GL.End();
        _texture.Unbind();
    }

    glControl.SwapBuffers();
}

これは、投影行列を使用し、画面上に常に同じ場所((0,0)から(幅、高さ))に画像を描画します。

画像は1ビューユニット=1ピクセルで描画されるため、投影マトリックスで行う必要があるのは、画像を適切な場所に配置するための少しの変換だけだと思います。したがって、私はそれが次のように見えると思います

 1  0  0  0
 0  1  0  0
 0  0  1  0
tx ty  0  1

しかし、実際には次のようになります。

(注:行ではなく列であるため、回転して表示されます)

その部分はすでに私を混乱させていますが、それにもかかわらず、私が何かを忘れていない限り、私の数学は正しいはずですか?

レンダリング機能は意図したとおりに機能することに注意してください。マウスクリックをビューの座標に変換しようとしています。また、これは2Dアプリケーションであるため、Zベクトルは実際には使用されないことに注意してください(繰り返しになりますが、なぜColumn2奇妙な結果になるのかわかりません)。

では、座標が正しく出てこないということで、ここで何が間違っているのでしょうか。

たとえば、前述のように(0,0)から(w、h)で画像を描画し、700x500画像の右下隅をクリックすると、699x499が出力されると思いますが、代わりにとして出てき(0.9959349, -0.9971989)ます。

編集:Z座標がおかしい理由を見つけました。正投影マトリックスを-1と1ではなく-1と11の間に設定しました。ただし、Z値は重要ではないため、これは実際には何も変更しません。

Edit2:投影マトリックスがモデルビューを画面座標に変換するようになったので、基本的に反対のことをしたいのですが、マトリックスを反転する必要がありますか?そうすることで、よりピクセル化された数値が得られますが、それを掛けると、代わりに座標が大きくなりすぎます。

4

1 に答える 1

1

GLの射影行列は、正規化された座標空間に変換されます。ここで、XとYは-1と1の間になります(遠近法による除算の後、正射影では1で除算するだけなので、無視できます)。

ピクセル座標を取得するには、ビューポートでスケーリング/オフセットする必要があります。これにより、-1から1の範囲が、ビューポートで指定された左右の幅と高さにマップされます。

例えば:

screenX = (viewWidth * (normX + 1) / 2) + viewLeft;

画面座標からビュー座標に変換するには、すべてを逆に実行します。画面座標を正規化された座標に変換してから、逆変換を実行します。

gluProject()そしてgluUnproject()あなたのためにこれをするでしょう、あるいはあなたは情報源に相談することができます。

于 2013-03-03T09:19:33.567 に答える