3

単純なレイ トレーサーを作成することで vectormath についてもう少し学ぼうとしており、それについていくつか読んでいますが、見つけることができなかったのは、一次光線の方向を決定する方法です。これは単純な問題のように聞こえますが、おそらくそうかもしれませんが、私の現在の知識では、それを理解することができませんでした.

私は、カメラ (ベクトルとしての位置と方向に過ぎない) が必要であると考え、カメラから、最終的な画像を表すカメラの前のスクリーンに一次光線を発射しました。私が理解できないのは、画面の隅の座標です。画面を知っていれば、一次光線の方向を見つけるのは簡単です。

回転行列を必要としない単純な数学だけを使用して、画面を把握できることを願っています。私の最善の推測はこれです:

カメラの方向をベクトルとして持っています。この方向は、投影スクリーンの平面の法線に等しくなります。したがって、画面の法線があり、そこから画面の中心を簡単に計算できます。

camera_location + (normal * distance) 

距離は、画面とカメラの間の距離です。しかし、それは私が迷子になる場所であり、カメラの任意の方向の平面のコーナー座標を把握する方法を見つけることができません.

ここで私を助けてくれる人はいますか?そして、私の方法がおそらく機能しない場合、何が機能しますか?

4

2 に答える 2

1

編集: これは、viewMatrix の作成を省略しているため、最初に投稿されたものから大幅に削減されたコードです。これは一部のスキャンライン レンダリングにのみ必要であり、レイ トレーシングには使用されませんでした。

大変な作業は、lookat() 関数、特に「上」ベクトルと「右」ベクトルの作成です。これらは互いに垂直である必要があり、目と画像の中心の間を走るベクトルに対しても垂直でなければなりません。これらのベクトルの作成は、クロス積ベクトル関数に依存しています。

光線をキャストするための実際の関数は、スクリーン ビューポートが Y 方向に -0.5 から +0.5 まで実行されることを前提としています。この関数は非常に単純で、'view'、'up'、および 'right' ベクトルを正しい比率で加算するだけです。

public class Camera {

    protected Point3d       eye;
    protected Point3d       center;

    protected Vector3d      up;
    protected Vector3d      right;
    protected Vector3d      view;

    protected double        fovy;           // half FoV in radians
    protected double        tanf;
    protected double        aspect;

    public Ray castRay(double x, double y) {

        Vector3d dir = new Vector3d(view);
        Vector3d t = new Vector3d();
        t.scale(tanf * x * aspect, right);
        dir.add(t);
        t.scale(tanf * y, up);

        dir.add(t);
        dir.normalize();

        return new Ray(eye, dir);
    }

    /* algorithm taken from gluLookAt */
    public void lookAt(Point3d _eye, Point3d _center, Vector3d _up) {

        eye = new Point3d(_eye);
        center = new Point3d(_center);
        Vector3d u = new Vector3d(_up);

        Vector3d f = new Vector3d(center);
        f.sub(eye);
        f.normalize();

        Vector3d s = new Vector3d();
        u.normalize();
        s.cross(f, u);
        s.normalize();
        u.cross(s, f);

        view = new Vector3d(f);
        right = new Vector3d(s);
        up = new Vector3d(u);
    }

    /* algorithm taken from gluPerspective */
    public void setfov(double _fovy, double _aspect)
    {
        fovy = Math.toRadians(_fovy) / 2.0;
        tanf = Math.tan(fovy);
        aspect = _aspect;
    }
}
于 2009-01-17T20:39:00.780 に答える
0

情報ありがとうございました。個人的には、行列変換にあまり慣れていないので、できるだけ避けたいと思います。しかし、あなたの投稿から、私がやりたいことを行うには変換が唯一の方法であることがわかりますか?私はかなり近くにいて(画面の法線と中心点を取得した)、純粋なベクトル数学ソリューションが好きだったので、それはあまりにも悪いことでした。

私はあなたのコードを採用しようとしますが、残念ながら、いくつかの時点で、主にMatrix4dオブジェクトで、オブジェクトの内部で何が起こっているのか正確にはわかりません。

PS:質問の作成者としてStackOverflowの回答に返信したい場合、その回答にコメントを付けることになっていますか、それとも新しい「回答」を作成しても大丈夫ですか?

于 2009-01-17T22:37:30.243 に答える