1 #include "sphere.h"
2
3 Sphere::Sphere(const Vector& c, double r) : center_(c), radius_(r) {
4 }
5
6
7 const Vector& Sphere::getCenter() const { return center_; }
8
9 void Sphere::setCenter(const Vector& v) { center_ = v; }
10
11 double Sphere::getRadius() const { return radius_; }
12
13 void Sphere::setRadius(double r) { radius_ = r; }
14
15
16
17
18 inline double max(double x, double y) {
19 return (x<y) ? y : x;
20 }
21 inline double min(double x, double y) {
22 return (x>y) ? y : x;
23 }
24
25 bool Sphere::intersect(const Ray& ray,Vector& point,Vector& normal, double& distance) const {
26 // ray-sphere intersection
27
28 // ray direction
29 const Vector direction(ray.getDirection());
30 const double i = direction[0];
31 const double j = direction[1];
32 const double k = direction[2];
33
34 // ray origin
35 const Vector origin(ray.getOrigin());
36 const double x = origin[0];
37 const double y = origin[1];
38 const double z = origin[2];
39
40 // sphere's center
41 const double l = center_[0];
42 const double m = center_[1];
43 const double n = center_[2];
44 const double r = radius_;
45
46 // compute parameters a,b,c for at^2+bt+c=0
47 const double a = i*i + j*j + k*k;
48 const double b = 2*(i*(x-l) + j*(y-m) + k*(z-n));
49 const double c = l*l+m*m+n*n + x*x+y*y+z*z - 2*(l*x+m*y+n*z+r*r);
50
51 // solve at^2+bt+c=0
52 // D = b^2-4ac
53 const double D = b*b-4*a*c;
54
55 // no intersection
56 if (D < 0)
57 return false;
58
59 // nearest ray intersection
60 double t;
61
62 if (D > 0)
63 {
64 // two intersections
65 // ray parameter
66 const double t1 = (-b + sqrt(D))/2*a;
67 const double t2 = (-b - sqrt(D))/2*a;
68 t = min(t1,t2);
69 if (t < 0)
70 t = max(t1,t2);
71 }
72 else
// only one intersection
73 t = -b/2*a;
74
75 // all intersections behind the origin ?
76 if (t <= 0.001)
77 return false;
78
79
80 point = ray.getOrigin() + t*ray.getDirection();
81 normal = (point - center_)/r; // divison by "r" normalizes the vector
82 distance = t;//abs(point-ray.getOrigin());
83
84 return true;
85 }
86