|
1 /* |
|
2 * C++ RayTracer |
|
3 * file: scene.cc |
|
4 * |
|
5 * Radek Brich, 2006 |
|
6 */ |
|
7 |
|
8 #include <math.h> |
|
9 #include "scene.h" |
|
10 |
|
11 bool Sphere::intersect(const Ray &ray, float &dist) |
|
12 { |
|
13 Vector3 V = ((Ray)ray).a - center; |
|
14 |
|
15 float Vd = - dot(V, ray.dir); |
|
16 float Det = Vd * Vd - (dot(V,V) - sqr_radius); |
|
17 |
|
18 if (Det > 0) { |
|
19 Det = sqrtf(Det); |
|
20 float t1 = Vd - Det; |
|
21 if (t1 > 0) |
|
22 { |
|
23 if (t1 < dist) { |
|
24 dist = t1; |
|
25 return true; |
|
26 } |
|
27 } else { |
|
28 float t2 = Vd + Det; |
|
29 if (t2 > 0) |
|
30 { |
|
31 // ray from inside of the sphere |
|
32 dist = t2; |
|
33 return true; |
|
34 } |
|
35 } |
|
36 } |
|
37 return false; |
|
38 } |
|
39 |
|
40 bool Sphere::intersect_all(const Ray &ray, float dist, vector<float> &allts) |
|
41 { |
|
42 //allts = new vector<float>(); |
|
43 |
|
44 Vector3 V = ((Ray)ray).a - center; |
|
45 float Vd = - dot(V, ray.dir); |
|
46 float Det = Vd * Vd - (dot(V,V) - sqr_radius); |
|
47 |
|
48 if (Det > 0) { |
|
49 Det = sqrtf(Det); |
|
50 float t1 = Vd - Det; |
|
51 float t2 = Vd + Det; |
|
52 if (t1 < 0) |
|
53 { |
|
54 if (t2 > 0) |
|
55 { |
|
56 // ray from inside of the sphere |
|
57 allts.push_back(0.0); |
|
58 allts.push_back(t2); |
|
59 return true; |
|
60 } |
|
61 else |
|
62 return false; |
|
63 } |
|
64 else |
|
65 { |
|
66 allts.push_back(t1); |
|
67 allts.push_back(t2); |
|
68 return true; |
|
69 } |
|
70 } |
|
71 return false; |
|
72 } |
|
73 |
|
74 bool Plane::intersect(const Ray &ray, float &dist) |
|
75 { |
|
76 float dir = dot(N, ray.dir); |
|
77 if (dir != 0) |
|
78 { |
|
79 float newdist = -(dot(N, ray.a) + d) / dir; |
|
80 if (newdist > 0 && newdist < dist) { |
|
81 dist = newdist; |
|
82 return true; |
|
83 } |
|
84 } |
|
85 return false; |
|
86 } |
|
87 |
|
88 // this initialization and following intersection methods implements |
|
89 // Fast Triangle Intersection algorithm from |
|
90 // http://www.mpi-inf.mpg.de/~wald/PhD/ |
|
91 Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial) |
|
92 : A(aA), B(aB), C(aC) |
|
93 { |
|
94 material = amaterial; |
|
95 Vector3 c = B - A; |
|
96 Vector3 b = C - A; |
|
97 |
|
98 N = cross(c, b); |
|
99 |
|
100 if (fabsf(N.x) > fabsf(N.y)) |
|
101 { |
|
102 if (fabsf(N.x) > fabsf(N.z)) |
|
103 k = 0; |
|
104 else |
|
105 k = 2; |
|
106 } |
|
107 else |
|
108 { |
|
109 if (fabsf(N.y) > fabsf(N.z)) |
|
110 k = 1; |
|
111 else |
|
112 k = 2; |
|
113 } |
|
114 |
|
115 int u = (k + 1) % 3; |
|
116 int v = (k + 2) % 3; |
|
117 |
|
118 float krec = 1.0f / N[k]; |
|
119 nu = N[u] * krec; |
|
120 nv = N[v] * krec; |
|
121 nd = dot(N, A) * krec; |
|
122 |
|
123 // first line equation |
|
124 float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]); |
|
125 bnu = b[u] * reci; |
|
126 bnv = -b[v] * reci; |
|
127 |
|
128 // second line equation |
|
129 cnu = c[v] * reci; |
|
130 cnv = -c[u] * reci; |
|
131 |
|
132 // finalize normal |
|
133 N.normalize(); |
|
134 } |
|
135 |
|
136 // see comment for previous method |
|
137 bool Triangle::intersect(const Ray &ray, float &dist) |
|
138 { |
|
139 Vector3 O = ray.a; |
|
140 Vector3 D = ray.dir; |
|
141 |
|
142 const int modulo3[5] = {0,1,2,0,1}; |
|
143 const int ku = modulo3[k+1]; |
|
144 const int kv = modulo3[k+2]; |
|
145 const float lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]); |
|
146 const float t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd; |
|
147 |
|
148 if (!(t < dist && t > 0)) |
|
149 return false; |
|
150 |
|
151 float hu = O[ku] + t * D[ku] - A[ku]; |
|
152 float hv = O[kv] + t * D[kv] - A[kv]; |
|
153 float beta = hv * bnu + hu * bnv; |
|
154 |
|
155 if (beta < 0) |
|
156 return false; |
|
157 |
|
158 float gamma = hu * cnu + hv * cnv; |
|
159 if (gamma < 0) |
|
160 return false; |
|
161 |
|
162 if ((beta + gamma) > 1) |
|
163 return false; |
|
164 |
|
165 dist = t; |
|
166 return true; |
|
167 } |