光线追踪器中的三角形交点不起作用
Triangle intersection in raytracer not working
我正在尝试在 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
或一些小值)
我正在尝试在 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
或一些小值)