I was going to stop at intervals on the ray and check if they were within the radius of the sphere. I found much more efficient mathematical ways to do this but they are all written in C++.
Something like this should work (inefficient version but without any dependency and easy to follow):
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.