ERPT 実装 : 点を画像面へ射影する。

by syoyo

経路の変異を実装しているのであるが、はたと気づいたことがある。

コースティクス摂動では、光源からの方向を摂動させる。
これがたとえば LDE の経路だったばあい、
摂動した方向に光源からレイを飛ばして交点を求め、その交点から
視点を繋ぎ、またその交点 – 視点間のレイが画像面のどのピクセル位置
に対応するのか求めなければならない。

まあふつーに幾何を解いていけばよいのでしょうが、
なんだか計算するの面倒ですなー、と思っていたら、
David Cline の A practical 〜 には親切御丁寧にも
このための変換行列が付録に書かれていました。

こいつはグレートだぜ、、、
Cline 先生、、、すばらしすぎです、、、

という訳で、ワールド座標での点(視点から最初にヒットする点)を
画像面に射影する行列の実装は以下のようになるでしょうか。

// Create the matrix which transforms a point in world space onto
// its pixel coordinate.
void
matrxi_project_point_onto_the_image_plane(double M[16])
{
        double C[16], V[16], T[16], TC[16];
        vector_t eye;

        vcpy(&eye, &render->eyepos);
        memcpy(T, render->T, sizeof(double) * 16);

        double w = render->width;
        double h = render->height;

        double tw = 45.0 * M_PI / 180.0;        // horizontal field of view
        double th = 45.0 * M_PI / 180.0;        // vertical field of view

        C[ 0] =    1.0; C[ 1] =   0.0; C[ 2] =   0.0; C[ 3] = 0.0;
        C[ 4] =    0.0; C[ 5] =   1.0; C[ 6] =   0.0; C[ 7] = 0.0;
        C[ 8] =    0.0; C[ 9] =   0.0; C[10] =   1.0; C[11] = 0.0;
        C[12] = -eye.x; C[13] = eye.y; C[14] = eye.z; C[15] = 1.0;

        V[ 0] = w / 2.0 * tan(tw / 2.0);
        V[ 1] = 0.0;
        V[ 2] = 0.0;
        V[ 3] = 0.0;

        V[ 4] = 0.0;
        V[ 5] = h / 2.0 * tan(th / 2.0);
        V[ 6] = 0.0;
        V[ 7] = 0.0;

        V[ 8] = w / 2.0;
        V[ 9] = h / 2.0;
        V[10] = 1.0;
        V[11] = 1.0;

        V[12] = 0.0;
        V[13] = 0.0;
        V[14] = 0.0;
        V[15] = 0.0;

        // M = V . T . C
        mmulmat(TC, T, C);
        mmulmat(M, V, TC);
}

render->T はカメラ行列ですが、これは gluLookAt() で計算させれば簡単に求まります。

行列 M を点 p にかけてあげればピクセル座標が求まる(はず。まだ未検証)。

to be continued…

Advertisements