我想在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]);
}
当我渲染场景时,我在场景中使用的三角形是红色的。无论我将相机向后移动多远,三角形都会将整个场景填满整个场景。我不知道为什么会这样。
答案 0 :(得分:0)
平面交叉码中的一个重要错误是此比较操作:
a === 0
它有两个问题:
对于光线追踪,您希望光线在其源的前面中击中,而不是在它后面,因此您需要a < 0
。
即使你 希望光线击中它后面的平面,你也必须从不在浮点值之间进行相等操作,因为浮点计算是< em>不准确。 (您必须执行类似abs(a) < 1e-6f
或某些小值的操作)