spherical-volume-rendering / svr-algorithm

A spherical volume rendering algorithm that performs ray casting through a spherical voxel grid.
Other
6 stars 7 forks source link

Math for sphere intersection. #31

Closed cgyurgyik closed 4 years ago

cgyurgyik commented 4 years ago

A while back, I did a primer on ray tracing. Part of this dealt with ray intersection with spheres. They use similar equations to the one we're using to calculate intersection with spheres. More information can be found here: https://raytracing.github.io/books/RayTracingInOneWeekend.html#addingasphere

And here's the code I wrote (it was originally C++, but turned it into pseudocode since a lot of the C++ keywords will cause more confusion than anything.

    // Determines whether a ray has hit a sphere in the boundaries (minimum, maximum)
    // with the given center and radius. The formula is generated as follows:
    // -> (x - Cx)^2 + (y - Cy)^2 + (z - Cz)^2 = R^2  (sphere centered at Cx, Cy, Cz)
    // -> Since a vector from center C to a point P = (x, y, z) is (P - C)
    // -> Then, dot((p - C), (p - C)) = R^2
    // -> = dot((p(t) - C), p(t) - C)) = R^2
    // -> = dot((A + t * B - C), A + t * B - C)) = R^2
    // -> = t^2 * dot(B, B) + 2t * dot(B, A - C) + dot (A - C, A - C) - R^2 = 0
    bool hit(ray, t_min, t_max) {
        oc = ray.origin() - circle_center;
        direction = ray.direction()
        a = direction.dot(direction);
        b = direction.dot(oc);
        c = oc.dot(oc) - (radius_ * radius_);
        discriminant = (b * b) - (a * c);
        if (discriminant <= 0) return false;

        hit_point_one = (-b - sqrt(discriminant)) / a;
        if (hit_point_one > t_min && hit_point_one < t_max) {
            // Given the hit point and ray, we can also calculate where along the ray it intersects.
            return true;
        }
        hit_point_two = (-b + sqrt(discriminant)) / a;
        if (hit_point_two > t_min && hit_point_two < t_max) {
            return true;
        }
        return false;
    }