2012-03-29 3 views
0

私はOpenGLアプリケーション用に独自の行列演算を実装しています。これまでのところ、大変うまくいきましたが、難しいです。私の最近の問題は、説明や特定の問題が私に指摘されることに多大な苦労をしたことのないglOrtho()の実装と関係しています。私のglOrthoに何が問題なのですか?

特に、私のバージョンでは、行列[14]要素が負のゼロになります。 (-0.000000)、廃止予定のglOrtho()を使用した後のOpenGLからのglGet()のバージョンは通常のゼロです。 (0.000000)

これが何かに影響を与えるかどうかはわかりませんが、マッチングしていない数学に邪魔されています。

私はきちんと以下、そして正しく数学をやっていると信じて参照するためにglOrthoのOpenGLの仕様、: http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml

私自身glOrtho機能を:

vec_t* Utils::OrthoMatrix(vec_t* out_matrix, const vec_t& left, const vec_t& right, const vec_t& bottom, const vec_t& top, const vec_t& znear, const vec_t& zfar) 
{ 
    memcpy(out_matrix, zeroMatrix, 16*sizeof(vec_t)); 

    out_matrix[0] = 2.0f/(right - left); 
    out_matrix[5] = 2.0f/(top - bottom); 
    out_matrix[10] = -2.0f/(zfar - znear); 
    out_matrix[12] = -((right + left)/(right - left)); 
    out_matrix[13] = -((top + bottom)/(top - bottom)); 
    out_matrix[14] = -((zfar + znear)/(zfar - znear)); 
    out_matrix[15] = 1.0f; 

    return out_matrix; 
}

マイサイズ変更機能(剥奪ダウンはかなり読みやすくするため):

void GameLogic::OnResize(int width, int height) // For purposes of this test, width = 640, height = 480. 
{ 
    if(height == 0) // Avoid potential divide-by-zero 
     height = 1; 

    glViewport(0, 0, width, height); 

    Utils::OrthoMatrix(m_orthoMatrix, 0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -100.0f, 100.0f); 

    // Setup fixed function OpenGL to compare against. 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -100.0f, 100.0f); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
}
void GameLogic::Render() // Drastically cut down to illustrate issue. 
{ 
    vec_t modelviewmatrix[16], projectionmatrix[16]; 
    glGetFloatv(GL_MODELVIEW_MATRIX, modelviewmatrix); 

    glGetFloatv(GL_PROJECTION_MATRIX, projectionmatrix); 
/* 
    At this point, projectionmatrix and m_orthoMatrix are identical, 
    except in the matrix[14] element, which is 0.000000 for projectionmatrix, 
    and -0.000000 for m_orthoMatrix. 
*/ 
}

私はこれがなぜ起こり得るのか、それが何をもたらすのかを理解できません。数学は私が見る限り正確にチェックアウトするので、負のゼロでなければならないが、OpenGLは正のゼロを返す。これまでのところ私の推測では、ドライバーがマイナスのゼロを避けるために数値を偽っている何らかのドライバークルークがありますか?私はこのコードを2つの別々のnVidia GPUでテストし、同じ結果を得ました。テストするためにATIなどにアクセスしないでください。

免責事項:glOrthoのnear値とfar値がどのように機能するかは、私にはあまり知られていませんが、負の値が許可されています。

投影行列を単位行列で初期化するか、または単位行列を透視行列に乗算する必要がありますか?私はそうする必要はないと思っています。私のglFrustumの実装はそれをしないで大丈夫だと思われますが、それは多分でしょうか?私はそれが正しさのために行われるべきかどうかを知るために数学を十分に理解していません。

私が間違っていることや誤解していることについてのアイデアは誰ですか?あるいは、私が本当に何らかの奇妙な変わったことを見つけたら?何かがあったとしても、負のゼロを使用すると、現在の値から値を調整しようとするのではなく、それに付随するのが最善の方法であるとアドバイスされている場合、

答えて

1

"修正"しないでください - コードが正しく動作しています。 「奇妙な奇妙な」はそれをうまくカバーしている、と私は思う。

ゼロ以外の値にゼロを追加すると(マトリックス乗算と同じ)、まったく同じ結果が得られます。これは重大な相違としてみなされません。

実際には、は、同じ名目上の結果を計算する2つの異なる浮動小数点プロシージャを比較するときに矛盾が発生すると予想してください。浮動小数点は厳密ではないので、あなたが違うやり方(例えば、加算の順番を変える)であれば、やや異なる結果になるでしょう。結果として、浮動小数点の結果を比較するたびに、許容差を指定する必要があります。

+0

答えをよく説明していただきありがとうございます。何が起こっているのか、なぜそれが起こっているのか、もっと理解できるようになりました。 – Azuvector

3

CPUとGPU内の浮動小数点精度は必ずしも同一ではないため、小さな矛盾が予想されます。

0

負のゼロと正のゼロは、数学的に同じ浮動小数点値です。彼らはと同じです。ですが、IEEE-754によれば同じことになります。

等価を異なる浮動小数点計算とまったく一致させようとしないでください。行列の数学をチェックする必要がある場合は、少なくとも範囲(プラスまたはマイナスの数)に対してテストします。

+0

実際には、標準では+0と-0 *が等しいと言います(とにかく、比較に関する限り)。 – comingstorm

関連する問題