简体   繁体   中英

Function to find point of intersection between a ray and a sphere? (Javascript)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM