struct maybe_point sphere_intersection_point(struct ray r, struct sphere s){ struct maybe_point p; double A = dot_vector(r.dir,r.dir); double B = 2 * dot_vector(difference_point(r.p,s.center), r.dir); double C = dot_vector(difference_point(r.p,s.center), difference_point(r.p, s.center)) - s.radius*s.radius; double E = (-B+sqrt(B*B-4*A*C))/2/A; double F = (-B-sqrt(B*B-4*A*C))/2/A; if((E>0&& F>0)){ p.isPoint = 1; if(E>F) p.p = translate_point(r.p, scale_vector(r.dir,F)); else p.p = translate_point(r.p, scale_vector(r.dir,E)); }else if((E>0||F>0)){ p.isPoint = 1; if(E>0) p.p = translate_point(r.p, scale_vector(r.dir,E)); else p.p = translate_point(r.p, scale_vector(r.dir,F)); }else{ p.isPoint =0; p.p = create_point(0,0,0); } return p; }
struct maybe_point sphere_intersection_point(struct ray r, struct sphere s) { double a = dot_vector(r.dir, r.dir); double b = 2 * dot_vector(difference_point(r.p, s.center), r.dir); double c = dot_vector(difference_point(r.p, s.center), difference_point(r.p, s.center)) - (s.radius * s.radius); double disc = discriminant(a, b, c); double pos_result = pos_quadratic(a, b, c); double neg_result = neg_quadratic(a, b, c); double result; if (disc < 0) { return create_maybe_point(0, create_point(0.0, 0.0, 0.0)); } if (pos_result > 0 && neg_result > 0) { if (pos_result < neg_result) { result = pos_result; } else { result = neg_result; } } else if (pos_result > 0) { result = pos_result; } else if (neg_result > 0) { result = neg_result; } else { result = -1; } if (result > 0) { /*point is valid*/ return create_maybe_point(1, translate_point(r.p, scale_vector(r.dir, result))); } else { /* point is invalid*/ return create_maybe_point(0, translate_point(r.p, scale_vector(r.dir, result))); } }
struct maybe_point sphere_intersection_point(struct ray r, struct sphere s) { double a = dot_vector(r.dir,r.dir); struct vector v=difference_point(r.p,s.center); double b = 2*dot_vector(v,r.dir); double c = dot_vector(v,v) - (s.radius*s.radius); if( (b*b-4*a*c)>0) //two real roots { double t1 = ( (-b+sqrt((b*b)-(4*a*c)))/(2*a)); double t2 = ( (-b-sqrt((b*b)-(4*a*c)))/(2*a)); if(t1>0 && t2>0) // ray hits sphere twice, need lower t value { if(t1<=t2) { struct maybe_point mp5; mp5.isPoint=1; mp5.p=translate_point(r.p,scale_vector(r.dir,t1)); return mp5; } else { struct maybe_point mp6; mp6.isPoint=1; mp6.p=translate_point(r.p,scale_vector(r.dir,t2)); return mp6; } } else if( (t1>0&&t2<0) || (t1<0&&t2>0) ) //t is positive and negative,need positive t value { if(t1>0) { struct maybe_point mp7; mp7.isPoint=1; mp7.p=translate_point(r.p,scale_vector(r.dir,t1)); return mp7; } else { struct maybe_point mp8; mp8.isPoint=1; mp8.p=translate_point(r.p,scale_vector(r.dir,t2)); return mp8; } } else //no intersection, both t's negative { struct maybe_point mp1; mp1.isPoint=0; mp1.p.x=0; mp1.p.y=0; mp1.p.z=0; return mp1; } } else if( (b*b-4*a*c)==0)//one real root { printf("oneroot!"); double t3 = -b/2*a; if(t3>0)//t is positive, so the ray intersects sphere tangentially { struct maybe_point mp2; mp2.isPoint=1; mp2.p=translate_point(r.p,scale_vector(r.dir,t3)); return mp2; } else //t is negative, so ray does not intersect sphere. //also includes the case where t==0, where the ray starting //point is on the sphere. am going to treat like non-intersection { struct maybe_point mp3; mp3.isPoint=0; mp3.p.x=0; mp3.p.y=0; mp3.p.z=0; return mp3; } } else // no real roots { struct maybe_point mp; mp.isPoint=0; mp.p.x=0; mp.p.y=0; mp.p.z=0; return mp; } }
struct vector sphere_normal_at_point(struct sphere s, struct point p) { return normalize_vector(difference_point(p, s.center)); }