我在 Java 中复制了gluPerspective,但是当我将结果矩阵应用于向量时,输出 z 永远不会超过 0.5(除了一点点浮点错误)。但是,它应该在 0 (-z = zNear) 和 1 (-z = zFar) 之间
是否在某处对该功能进行了单元测试,以便我可以测试我的实现是否与特定输入的已知正确输出相匹配?或者这个问题是基于错误的假设,z 介于 0 和 0.5 之间是否可以?
或者,你能发现错误吗?
/**
* @param fov the vertical viewing angle. This is the angle, in degrees, from the top of the screen to the bottom.
* @param aspect The aspect ratio, which controls the horizontal viewing angle relative to the vertical. We could imagine a variable fovx = aspect × fovy. For a non-stretched perspective, aspect should be the ratio of the screen width to height. For example, on a 640×480 display, aspect should be 4/3.
* @param near The inverted z coordinate of the near clipping plane.
* @param far The inverted z coordinate of the far clipping plane.
*/
public static Matrix4d create(double fov, double aspect, double near, double far) {
Preconditions.checkArgument(near > 0);
Preconditions.checkArgument(far > 0);
Preconditions.checkArgument(far < Double.POSITIVE_INFINITY);
double top = near * Math.tan(fov * Math.PI / 360.0);
double right = top * aspect;
double left = -right;
double bottom = -top;
return Matrix4d.create(
(2.0 * near) / (right - left), 0, 0, 0,
0, (2.0 * near) / (top - bottom), 0, 0,
(right + left) / (right - left), (top + bottom) / (top - bottom), (-far - near) / (far - near), -1.0,
0, 0, (-(2.0 * near) * far) / (far - near), 0
);
}
根据要求,这是我的矩阵向量乘法代码:
public Vector3d multiplied(Vector3d other) {
final double r[] = new double[4]; // x, y, z, w
for (int lRow = 0; lRow < 4; lRow++) {
// calculate the dot product of the left row and the right vector
double dp =
(this.get(0, lRow) * other.x) +
(this.get(1, lRow) * other.y) +
(this.get(2, lRow) * other.z) +
(this.get(3, lRow) * 1);
r[lRow] = dp;
}
final double w = r[3];
if (w != 1) {
for (int i = 0; i < 3; i++) {
r[i] = r[i] / w;
}
}
return new Vector3d(r[0], r[1], r[2]);
}
以下是一些数字:
fov 90, aspect 1.7777777777777777, near 1, far 1000
perspective:
0.5625000000000001, 0.0, 0.0, 0.0
0.0, 1.0000000000000002, 0.0, 0.0
0.0, 0.0, -1.002002002002002, -1.0
0.0, 0.0, -2.002002002002002, 0.0
IN OUT
outside clipping area
[0.0, 0.0, 0.0] [NaN, NaN, -Infinity]
[0.0, 0.0, -0.5] [0.0, 0.0, -0.4985]
[0.0, 0.0, -2000.0] [0.0, 0.0, 0.5002502499999999]
on clipping edges
[0.0, 0.0, -1.0] [0.0, 0.0, 9.999999999999775E-4]
[0.0, 0.0, -1000.0] [0.0, 0.0, 0.5000005]
centered
[0.0, 0.0, -2.0] [0.0, 0.0, 0.25075]
[0.0, 0.0, -4.0] [0.0, 0.0, 0.37562499999999993]
[0.0, 0.0, -20.0] [0.0, 0.0, 0.475525]
[0.0, 0.0, -40.0] [0.0, 0.0, 0.4880125]
[0.0, 0.0, -80.0] [0.0, 0.0, 0.49425625]
to the right
[100.0, 0.0, -20.0] [1.4048437500000004, 0.0, 0.475525]
[100.0, 0.0, -40.0] [0.7024218750000002, 0.0, 0.4880125]
to the left
[-100.0, 0.0, -20.0] [-1.4048437500000004, 0.0, 0.475525]
[-100.0, 0.0, -40.0] [-0.7024218750000002, 0.0, 0.4880125]
1 to the top
[0.0, -10.0, -10.0] [0.0, -0.4995000000000001, 0.45055]