Esempio n. 1
0
/* Function that returns whether a ray intersects a capped cylinder and fills out a variable
   for the distance from the ray's origin to the intersection if there is one and also
   fills out the "type" of the intersection -- 1 for a cylinder body intersection, 2 for a top cap
   intersection, and 3 for a bottom cap intersection */
bool intersect_capped_cylinder(const ray3f& ray, float r, float h, float& t, int& type) {
    bool valid_intersect = false;
    t = ray.tmax;
    vec3f intersect = zero3f;
    /* Check whether the ray intersects the cylinder body,
       ensuring that the intersection is not between the end caps.
       Note: most of this code is from the previous function, written
       by Jon Denning */
    if(intersect_cylinder(ray, r, h, t)) {
            valid_intersect = true;
            type = BODY;
    }

    /* Now check the circles on top/bottom of cylinder
       http://orca.st.usm.edu/~jchen/courses/graphics/lectures/Raytracing.pdf
       proved helpful for this section of the code */

    /* Using the notes on ray-plane intersection... */
    /* Intersect the top end cap, first; intersect the plane at {0, 0, h} */
    vec3f n = vec3f(0, 0, 1); // Normal
    vec3f c = vec3f(0, 0, h); // Center
    float t_cap;
    if (dot(ray.d, n) != 0) {
        t_cap = dot((c-ray.e), n)/dot(ray.d, n);
        if (t_cap >= ray.tmin && t_cap <= ray.tmax) {
            intersect = ray.eval(t_cap);
            if((intersect.x * intersect.x + intersect.y * intersect.y) <= r*r) {
                if(t_cap < t) {
                    t = t_cap;
                    valid_intersect = true;
                    type = CAP_TOP;
                }
            }
        }
    }

    /* Intersect the bottom end cap; intersect the plane at {0, 0, 0} */
    n = vec3f(0, 0, -1);
    c = vec3f(0, 0, 0);
    if (dot(ray.d, n) != 0) {
        t_cap = dot((c-ray.e), n)/dot(ray.d, n);
        if (t_cap >= ray.tmin && t_cap <= ray.tmax) {
            intersect = ray.eval(t_cap);
            if((intersect.x * intersect.x + intersect.y * intersect.y) <= r*r) {
                if(t_cap < t) {
                    t = t_cap;
                    valid_intersect = true;
                    type = CAP_BOT;
                }
            }
        }
    }

    if(valid_intersect) return true;
    else return false;
}
Esempio n. 2
0
// intersect quad
inline bool intersect_quad(const ray3f& ray, float radius, float& t, vec3f& p) {
    if(ray.d.z == 0) return false;
    t = - ray.e.z / ray.d.z;
    p = ray.eval(t);
    if(radius < p.x or -radius > p.x or radius < p.y or -radius > p.y) return false;
    if (t < ray.tmin or t > ray.tmax) return false;
    return true;
}
Esempio n. 3
0
bool intersect_quad(const ray3f& ray, float w, float h, float& t, float& ba, float& bb) {
    // TODO: BUG: handle infinite intersections
    if(ray.d.z == 0) return false;
    t = - ray.e.z / ray.d.z;
    if(t < ray.tmin or t > ray.tmax) return false;
    auto p = ray.eval(t);
    if(w/2 < p.x or -w/2 > p.x or h/2 < p.y or -h/2 > p.y) return false;
    ba = p.x/w+0.5;
    bb = p.y/h+0.5;
    return true;
}
Esempio n. 4
0
// http://geomalgorithms.com/a05-_intersect-1.html
//    // intersect2D_2Segments(): find the 2D intersection of 2 finite segments
//    //    Input:  two finite segments S1 and S2
//    //    Output: *I0 = intersect point (when it exists)
//    //            *I1 =  endpoint of intersect segment [I0,I1] (when it exists)
//    //    Return: 0=disjoint (no intersect)
//    //            1=intersect  in unique point I0
//    //            2=overlap  in segment from I0 to I1
//    int
//    intersect2D_2Segments( Segment S1, Segment S2, Point* I0, Point* I1 )
//    {
//        Vector    u = S1.P1 - S1.P0;
//        Vector    v = S2.P1 - S2.P0;
//        Vector    w = S1.P0 - S2.P0;
//        float     D = perp(u,v);
//
//        // test if  they are parallel (includes either being a point)
//        if (fabs(D) < SMALL_NUM) {           // S1 and S2 are parallel
//            if (perp(u,w) != 0 || perp(v,w) != 0)  {
//                return 0;                    // they are NOT collinear
//            }
//            // they are collinear or degenerate
//            // check if they are degenerate  points
//            float du = dot(u,u);
//            float dv = dot(v,v);
//            if (du==0 && dv==0) {            // both segments are points
//                if (S1.P0 !=  S2.P0)         // they are distinct  points
//                    return 0;
//                *I0 = S1.P0;                 // they are the same point
//                return 1;
//            }
//            if (du==0) {                     // S1 is a single point
//                if  (inSegment(S1.P0, S2) == 0)  // but is not in S2
//                    return 0;
//                *I0 = S1.P0;
//                return 1;
//            }
//            if (dv==0) {                     // S2 a single point
//                if  (inSegment(S2.P0, S1) == 0)  // but is not in S1
//                    return 0;
//                *I0 = S2.P0;
//                return 1;
//            }
//            // they are collinear segments - get  overlap (or not)
//            float t0, t1;                    // endpoints of S1 in eqn for S2
//            Vector w2 = S1.P1 - S2.P0;
//            if (v.x != 0) {
//                t0 = w.x / v.x;
//                t1 = w2.x / v.x;
//            }
//            else {
//                t0 = w.y / v.y;
//                t1 = w2.y / v.y;
//            }
//            if (t0 > t1) {                   // must have t0 smaller than t1
//                float t=t0; t0=t1; t1=t;    // swap if not
//            }
//            if (t0 > 1 || t1 < 0) {
//                return 0;      // NO overlap
//            }
//            t0 = t0<0? 0 : t0;               // clip to min 0
//            t1 = t1>1? 1 : t1;               // clip to max 1
//            if (t0 == t1) {                  // intersect is a point
//                *I0 = S2.P0 +  t0 * v;
//                return 1;
//            }
//
//            // they overlap in a valid subsegment
//            *I0 = S2.P0 + t0 * v;
//            *I1 = S2.P0 + t1 * v;
//            return 2;
//        }
//
//        // the segments are skew and may intersect in a point
//        // get the intersect parameter for S1
//        float     sI = perp(v,w) / D;
//        if (sI < 0 || sI > 1)                // no intersect with S1
//            return 0;
//
//        // get the intersect parameter for S2
//        float     tI = perp(u,w) / D;
//        if (tI < 0 || tI > 1)                // no intersect with S2
//            return 0;
//
//        *I0 = S1.P0 + sI * u;                // compute S1 intersect point
//        return 1;
//    }
//    //===================================================================
// http://geomalgorithms.com/a07-_distance.html#dist3D_Segment_to_Segment
bool intersect_line_approximate(const ray3f& ray, const vec3f& v0, const vec3f& v1, float r0, float r1, float& t, float& s) {
    auto r = ray3f::segment(v0, v1);
    if(abs(dot(ray.d,r.d)) == 1) return false;
    auto a = dot(ray.d,ray.d);
    auto b = dot(ray.d,r.d);
    auto c = dot(r.d,r.d);
    auto d = dot(ray.d,ray.e-r.e);
    auto e = dot(r.d,ray.e-r.e);
    t = (b*e-c*d)/(a*c-b*b);
    s = (a*e-b*d)/(a*c-b*b);
    t = clamp(t, ray.tmin, ray.tmax);
    s = clamp(s, r.tmin, r.tmax);
    auto ss = s / length(v1-v0);
    auto rr = r0*(1-ss)+r1*ss;
    if(dist(ray.eval(t), r.eval(s)) > rr) return false;
    s = ss;
    return true;
}
Esempio n. 5
0
// http://geomalgorithms.com/a02-_lines.html
//    distance( Point P,  Segment P0:P1 )
//    {
//        v = P1 - P0
//        w = P - P0
//
//        if ( (c1 = w·v) <= 0 )  // before P0
//            return d(P, P0)
//            if ( (c2 = v·v) <= c1 ) // after P1
//                return d(P, P1)
//
//                b = c1 / c2
//                Pb = P0 + bv
//                return d(P, Pb)
//                }
bool intersect_point_approximate(const ray3f& ray, const vec3f& p, float r, float& t) {
    t = - dot(ray.e - p, ray.d);
    t = clamp(t, ray.tmin, ray.tmax);
    return length(p-ray.eval(t)) <= r;
}