我正在尝试用Javascript制作自己的光线追踪器。到目前为止,这些球体运行良好。我现在想扩展功能以包括三角形,从那里我可以转到正方形、立方体等。我用于查找与三角形相交的代码如下
function triangleIntersection(t, r) {
var norm = triangleNormal(t);
var dist = triangleDistance(t);
var a = Vector.dotProduct(r.vector, norm);
if (a === 0) {
return -1;
} else {
var b = Vector.dotProduct(norm, Vector.add(r.point, Vector.negative(Vector.multiply(norm, dist))));
var d = -1 * b / a;
var qx = Vector.scale(r.vector, d).x + r.point.x;
var qy = Vector.scale(r.vector, d).y + r.point.y;
var qz = Vector.scale(r.vector, d).z + r.point.z;
var q = new Vector(qx, qy, qz);
var ca = Vector.subtract(t.points[2], t.points[0]);
var qa = Vector.subtract(q, t.points[0]);
var t1 = Vector.dotProduct(Vector.crossProduct(ca, qa), norm);
var bc = Vector.subtract(t.points[1], t.points[2]);
var qc = Vector.subtract(q, t.points[2]);
var t2 = Vector.dotProduct(Vector.crossProduct(bc, qc), norm);
var ab = Vector.subtract(t.points[0], t.points[1]);
var qb = Vector.subtract(q, t.points[1]);
var t3 = Vector.dotProduct(Vector.crossProduct(ab, qb), norm);
if ((t1 >= 0) && (t2 >= 0) && (t3 >= 0)) {
return 1 * b / a;
} else {
return -1;
}
}
}
三角形对象有一个点数组(points[]
(,项目0是点A,项目1是点B,项目2是点C。参数t
是这些三角形之一。参数r
是一个射线对象,其属性point
是原点,vector
是方向。
我也有这些函数来查找三角形的法线和距离。
function triangleNormal(s) {
var ca = Vector.subtract(s.points[2], s.points[0]);
var ba = Vector.subtract(s.points[1], s.points[0]);
var norm = Vector.unitVector(Vector.crossProduct(ca, ba));
return norm;
}
function triangleDistance(t) {
return Vector.dotProduct(triangleNormal(t, 0), t.points[0]);
}
当我渲染场景时,我在场景中使用的三角形是红色的。无论我将相机向后移动多远,三角形都会将整个场景填满红色。我不知道为什么会这样。
平面交集代码中的一个重要错误是以下比较操作:
a === 0
它有两点错误:
-
对于光线追踪,您希望光线击中其源前面的平面,而不是它后面,所以你需要
a < 0
。 -
即使您确实希望光线击中其后面的平面,也绝不能在浮点值之间进行相等运算,因为浮点计算并不精确。(你必须做一些类似
abs(a) < 1e-6f
或一些小值的事情(