1

マゾヒスティックな私と同じように、JS ライブラリを使用せずにモデルビューとパースペクティブ マトリックスを生成するための独自の関数を記述できるように、モデルビューとパースペクティブ マトリックスの作成の背後にあるすべてのマトリックス数学を学習しようとしています。

行列の概念は理解していますが、実際に行列を生成する方法はわかりません。私は glMatrix ライブラリを非常に詳しく調べてきましたが、次の質問があります。

1) 次のmat4.perspeciveメソッドでは何が起こっていますか?

/**
 * Generates a perspective projection matrix with the given bounds
 *
 * @param {mat4} out mat4 frustum matrix will be written into
 * @param {number} fovy Vertical field of view in radians
 * @param {number} aspect Aspect ratio. typically viewport width/height
 * @param {number} near Near bound of the frustum
 * @param {number} far Far bound of the frustum
 * @returns {mat4} out
 */
mat4.perspective = function (out, fovy, aspect, near, far) {
    var f = 1.0 / Math.tan(fovy / 2),
        nf = 1 / (near - far);
    out[0] = f / aspect;
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[5] = f;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[10] = (far + near) * nf;
    out[11] = -1;
    out[12] = 0;
    out[13] = 0;
    out[14] = (2 * far * near) * nf;
    out[15] = 0;
    return out;
};

具体的には、Math.tan(fovy / 2)計算しているものはわかりますが、なぜそれを逆にするのですか? 同様に、近い境界と遠い境界の差の逆数を取るのはなぜでしょうか? また、なぜにout[11]設定され-1、値は何のために保存さout[14]れますか?

2)mat4.lookAtライブラリの次のメソッドも混乱しています:

/**
 * Generates a look-at matrix with the given eye position, focal point, 
 * and up axis
 *
 * @param {mat4} out mat4 frustum matrix will be written into
 * @param {vec3} eye Position of the viewer
 * @param {vec3} center Point the viewer is looking at
 * @param {vec3} up vec3 pointing up
 * @returns {mat4} out
 */
mat4.lookAt = function (out, eye, center, up) {
    var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
        eyex = eye[0],
        eyey = eye[1],
        eyez = eye[2],
        upx = up[0],
        upy = up[1],
        upz = up[2],
        centerx = center[0],
        centery = center[1],
        centerz = center[2];

    if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
        Math.abs(eyey - centery) < GLMAT_EPSILON &&
        Math.abs(eyez - centerz) < GLMAT_EPSILON) {
        return mat4.identity(out);
    }

    z0 = eyex - centerx;
    z1 = eyey - centery;
    z2 = eyez - centerz;

    len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
    z0 *= len;
    z1 *= len;
    z2 *= len;

    x0 = upy * z2 - upz * z1;
    x1 = upz * z0 - upx * z2;
    x2 = upx * z1 - upy * z0;
    len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
    if (!len) {
        x0 = 0;
        x1 = 0;
        x2 = 0;
    } else {
        len = 1 / len;
        x0 *= len;
        x1 *= len;
        x2 *= len;
    }

    y0 = z1 * x2 - z2 * x1;
    y1 = z2 * x0 - z0 * x2;
    y2 = z0 * x1 - z1 * x0;

    len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
    if (!len) {
        y0 = 0;
        y1 = 0;
        y2 = 0;
    } else {
        len = 1 / len;
        y0 *= len;
        y1 *= len;
        y2 *= len;
    }

    out[0] = x0;
    out[1] = y0;
    out[2] = z0;
    out[3] = 0;
    out[4] = x1;
    out[5] = y1;
    out[6] = z1;
    out[7] = 0;
    out[8] = x2;
    out[9] = y2;
    out[10] = z2;
    out[11] = 0;
    out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
    out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
    out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
    out[15] = 1;

    return out;
};

メソッドと同様にmat4.perspecive、ベクトルの長さの逆数が計算されるのはなぜですか? また、なぜその値にz0,z1との値を掛けるのz2でしょうか? x0-x2変数とy0-変数についても同じことが行われていy2ます。なんで?out[12]最後に、 -に設定された値の意味は何out[14]ですか?

mat4.translate3) 最後に、方法についていくつか質問があります。具体的には、Professional WebGL Programming: Developing 3D Graphics for the Webという本を購入しましたが、次の 4x4 マトリックスを使用して頂点を変換すると書かれています。

1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1 

ただし、mat4.translateglMatrix ライブラリの次のメソッドを見ると、いくつかの複雑out[12]out[15]方程式によって設定されていることがわかります。これらの値が設定されているのはなぜですか?

/**
 * Translate a mat4 by the given vector
 *
 * @param {mat4} out the receiving matrix
 * @param {mat4} a the matrix to translate
 * @param {vec3} v vector to translate by
 * @returns {mat4} out
 */
mat4.translate = function (out, a, v) {
    var x = v[0], y = v[1], z = v[2],
        a00, a01, a02, a03,
        a10, a11, a12, a13,
        a20, a21, a22, a23;

    if (a === out) {
        out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
        out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
        out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
        out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
    } else {
        a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
        a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
        a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];

        out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
        out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
        out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;

        out[12] = a00 * x + a10 * y + a20 * z + a[12];
        out[13] = a01 * x + a11 * y + a21 * z + a[13];
        out[14] = a02 * x + a12 * y + a22 * z + a[14];
        out[15] = a03 * x + a13 * y + a23 * z + a[15];
    }

    return out;
};

お時間を割いていただき、ありがとうございました。また、質問をして申し訳ありません。私は OpenGL/3D プログラミングのバックグラウンドではなく、JS のバックグラウンドを持っているため、すべての行列の背後にある数学を理解するのは困難です。

これらの方程式/方法に使用される数学を説明する優れたリソースがあれば、それも素晴らしいでしょう。ありがとう。

4

1 に答える 1

3

具体的には、Math.tan(fovy / 2) が計算しているものを取得しますが、なぜそれを逆にするのでしょうか?

焦点距離dは式から得られるので

Math.tan(fovy / 2) = y / d

掛ける必要がある焦点距離を取得するには

1 / Math.tan(fovy / 2)

近い境界と遠い境界の差の逆数を取るのはなぜですか? また、out[11] が -1 に設定されているのはなぜですか? また、out[14] に格納されている値は何のためですか?

焦点距離(x,y,z)を使用して に投影できます。これで十分ですが、OpenGL では、射影が で座標を与えるなどの線形変換が必要です。このような正規化された座標は、クリッピングを簡素化し、非表示のサーフェスを削除するために使用される z 情報を保持します。(x*d/z, y*d/z)d(x,y,z)[-1,1]

反射が適用されない限り、正規化された座標を与える線形変換がないため、out[11] は -1 に設定されます。この -1 により、システムの利き手が正規化された座標で切り替えられます。

out[14] は out[10] とともに使用され、投影後に z を [-n -f] から [-1 1] に変換します。

mat4.perspecive メソッドと同様に、ベクトルの長さの逆数が計算されるのはなぜですか? また、その値に z0、z1、z2 の値を掛けるのはなぜですか? x0-x2 変数と y0-y2 変数についても同じことが行われています。なんで?

ベクトル x、y、z を正規化するには

out[12]~out[14]に設定された値の意味は何ですか?

カメラは、ベクトルのベースと位置で構成されます。out[12]-out[14] 逆変換を適用してカメラ位置を設定します。

ただし、glMatrix ライブラリの次の mat4.translate メソッドを見ると、out[12]-out[15] がいくつかの複雑な方程式によって設定されていることがわかります。これらの値が設定されているのはなぜですか?

方程式は、平行移動行列と既存の行列の積であるため、複雑に見えますa

Professional WebGL プログラミング: Web 用の 3D グラフィックスの開発

私はこの本を知りません。数学について説明しているかもしれませんが、詳細な説明が必要な場合は、3D ラスター グラフィックスで使用される重要な数学を説明および導出するEric Lengyel の本を検討してください。

于 2013-07-14T23:56:44.213 に答える