編集: これは、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;
}
}