我要在光线上间隔停下来,检查它们是否在球体半径范围内。我发现了更有效的数学方法,但它们都是用C ++编写的。
答案 0 :(得分:0)
这样的东西应该有效(低效的版本,但没有任何依赖性,易于遵循):
function dotProduct(v1, v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
function squaredLength(v) {
return dotProduct(v, v);
}
// Returns whether the ray intersects the sphere
// @param[in] center center point of the sphere (C)
// @param[in] radius radius of the sphere (R)
// @param[in] origin origin point of the ray (O)
// @param[in] direction direction vector of the ray (D)
// @param[out] intersection closest intersection point of the ray with the sphere, if any
function intersectRayWithSphere(center, radius,
origin, direction,
intersection) {
// Solve |O + t D - C|^2 = R^2
// t^2 |D|^2 + 2 t < D, O - C > + |O - C|^2 - R^2 = 0
var OC = intersection; // Use the output parameter as temporary workspace
OC.x = origin.x - center.x;
OC.y = origin.y - center.y;
OC.z = origin.z - center.z;
// Solve the quadratic equation a t^2 + 2 t b + c = 0
var a = squaredLength(direction);
var b = dotProduct(direction, OC);
var c = squaredLength(OC) - radius * radius;
var delta = b * b - a * c;
if (delta < 0) // No solution
return false;
// One or two solutions, take the closest (positive) intersection
var sqrtDelta = Math.sqrt(delta);
// a >= 0
var tMin = (-b - sqrtDelta) / a;
var tMax = (-b + sqrtDelta) / a;
if (tMax < 0) // All intersection points are behind the origin of the ray
return false;
// tMax >= 0
var t = tMin >= 0 ? tMin : tMax;
intersection.x = origin.x + t * direction.x;
intersection.y = origin.y + t * direction.y;
intersection.z = origin.z + t * direction.z;
return true;
}