184 } |
184 } |
185 } |
185 } |
186 return N; |
186 return N; |
187 } |
187 } |
188 |
188 |
189 // this initialization and following intersection methods implements |
189 #ifdef TRI_PLUCKER |
190 // Fast Triangle Intersection algorithm from |
190 inline void Plucker(const Vector3 &p, const Vector3 &q, Float* pl) |
191 // http://www.mpi-inf.mpg.de/~wald/PhD/ |
191 { |
|
192 pl[0] = p.x*q.y - q.x*p.y; |
|
193 pl[1] = p.x*q.z - q.x*p.z; |
|
194 pl[2] = p.x - q.x; |
|
195 pl[3] = p.y*q.z - q.y*p.z; |
|
196 pl[4] = p.z - q.z; |
|
197 pl[5] = q.y - p.y; |
|
198 } |
|
199 |
|
200 inline Float Side(const Float* pla, const Float* plb) |
|
201 { |
|
202 return pla[0]*plb[4] + pla[1]*plb[5] + pla[2]*plb[3] + pla[4]*plb[0] + pla[5]*plb[1] + pla[3]*plb[2]; |
|
203 } |
|
204 #endif |
|
205 |
192 Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial) |
206 Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial) |
193 : A(aA), B(aB), C(aC) |
207 : A(aA), B(aB), C(aC) |
194 { |
208 { |
195 material = amaterial; |
209 material = amaterial; |
196 Vector3 c = B - A; |
210 material->reflection = 0; |
197 Vector3 b = C - A; |
211 |
198 |
212 const Vector3 c = B - A; |
199 N = cross(c, b); |
213 const Vector3 b = C - A; |
200 |
214 |
|
215 N = -cross(c, b); |
|
216 N.normalize(); |
|
217 |
|
218 #ifdef TRI_PLUCKER |
|
219 Plucker(B,C,pla); |
|
220 Plucker(C,A,plb); |
|
221 Plucker(A,B,plc); |
|
222 #endif |
|
223 |
|
224 #if defined(TRI_BARI) || defined(TRI_BARI_PRE) |
201 if (fabsf(N.x) > fabsf(N.y)) |
225 if (fabsf(N.x) > fabsf(N.y)) |
202 { |
226 { |
203 if (fabsf(N.x) > fabsf(N.z)) |
227 if (fabsf(N.x) > fabsf(N.z)) |
204 k = 0; |
228 k = 0; |
205 else |
229 else |
210 if (fabsf(N.y) > fabsf(N.z)) |
234 if (fabsf(N.y) > fabsf(N.z)) |
211 k = 1; |
235 k = 1; |
212 else |
236 else |
213 k = 2; |
237 k = 2; |
214 } |
238 } |
215 |
239 #endif |
|
240 #ifdef TRI_BARI_PRE |
216 int u = (k + 1) % 3; |
241 int u = (k + 1) % 3; |
217 int v = (k + 2) % 3; |
242 int v = (k + 2) % 3; |
218 |
243 |
219 Float krec = 1.0f / N[k]; |
244 Float krec = 1.0 / N[k]; |
220 nu = N[u] * krec; |
245 nu = N[u] * krec; |
221 nv = N[v] * krec; |
246 nv = N[v] * krec; |
222 nd = dot(N, A) * krec; |
247 nd = dot(N, A) * krec; |
223 |
248 |
224 // first line equation |
249 // first line equation |
225 Float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]); |
250 Float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]); |
226 bnu = b[u] * reci; |
251 bnu = b[u] * reci; |
227 bnv = -b[v] * reci; |
252 bnv = -b[v] * reci; |
228 |
253 |
229 // second line equation |
254 // second line equation |
230 cnu = c[v] * reci; |
255 cnu = -c[u] * reci; |
231 cnv = -c[u] * reci; |
256 cnv = c[v] * reci; |
232 |
257 #endif |
233 // finalize normal |
258 } |
234 N.normalize(); |
259 |
235 } |
260 bool Triangle::intersect(const Ray &ray, Float &dist) const |
236 |
261 { |
237 // see comment for previous method |
262 #ifdef TRI_PLUCKER |
238 bool Triangle::intersect(const Ray &ray, Float &dist) |
263 Float plr[6]; |
239 { |
264 Plucker(ray.o, ray.o+ray.dir, plr); |
240 Vector3 O = ray.o; |
265 const bool side0 = Side(plr, pla) >= 0.0; |
241 Vector3 D = ray.dir; |
266 const bool side1 = Side(plr, plb) >= 0.0; |
242 |
267 if (side0 != side1) |
243 const int modulo3[5] = {0,1,2,0,1}; |
268 return false; |
244 const int ku = modulo3[k+1]; |
269 const bool side2 = Side(plr, plc) >= 0.0; |
245 const int kv = modulo3[k+2]; |
270 if (side0 != side2) |
246 const Float lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]); |
271 return false; |
247 const Float t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd; |
272 const Float t = - dot( (ray.o-A), N) / dot(ray.dir,N); |
248 |
273 if(t <= Eps || t >= dist) |
249 if (t < 0 || t >= dist) |
274 return false; |
250 return false; |
|
251 |
|
252 Float hu = O[ku] + t * D[ku] - A[ku]; |
|
253 Float hv = O[kv] + t * D[kv] - A[kv]; |
|
254 Float beta = hv * bnu + hu * bnv; |
|
255 |
|
256 if (beta < 0) |
|
257 return false; |
|
258 |
|
259 Float gamma = hu * cnu + hv * cnv; |
|
260 if (gamma < 0) |
|
261 return false; |
|
262 |
|
263 if ((beta + gamma) > 1) |
|
264 return false; |
|
265 |
|
266 dist = t; |
275 dist = t; |
267 return true; |
276 return true; |
268 } |
277 #endif |
269 |
278 |
270 BBox Triangle::get_bbox() |
279 #if defined(TRI_BARI) || defined(TRI_BARI_PRE) |
|
280 static const int modulo3[5] = {0,1,2,0,1}; |
|
281 const Vector3 &O = ray.o; |
|
282 const Vector3 &D = ray.dir; |
|
283 register const int u = modulo3[k+1]; |
|
284 register const int v = modulo3[k+2]; |
|
285 #endif |
|
286 #ifdef TRI_BARI_PRE |
|
287 const Float t = (nd - O[k] - nu * O[u] - nv * O[v]) / (D[k] + nu * D[u] + nv * D[v]); |
|
288 |
|
289 if (t >= dist || t < Eps) |
|
290 return false; |
|
291 |
|
292 const Float hu = O[u] + t * D[u] - A[u]; |
|
293 const Float hv = O[v] + t * D[v] - A[v]; |
|
294 const Float beta = hv * bnu + hu * bnv; |
|
295 |
|
296 if (beta < 0.) |
|
297 return false; |
|
298 |
|
299 const Float gamma = hu * cnv + hv * cnu; |
|
300 if (gamma < 0. || beta + gamma > 1) |
|
301 return false; |
|
302 |
|
303 dist = t; |
|
304 return true; |
|
305 #endif |
|
306 |
|
307 #ifdef TRI_BARI |
|
308 // original barycentric coordinates based intesection |
|
309 // not optimized, just for reference |
|
310 const Vector3 c = B - A; |
|
311 const Vector3 b = C - A; |
|
312 // distance test |
|
313 const Float t = - dot( (O-A), N) / dot(D,N); |
|
314 if (t < Eps || t > dist) |
|
315 return false; |
|
316 |
|
317 // calc hitpoint |
|
318 const Float Hu = O[u] + t * D[u] - A[u]; |
|
319 const Float Hv = O[v] + t * D[v] - A[v]; |
|
320 const Float beta = (b[u] * Hv - b[v] * Hu) / (b[u] * c[v] - b[v] * c[u]); |
|
321 if (beta < 0) |
|
322 return false; |
|
323 const Float gamma = (c[v] * Hu - c[u] * Hv) / (b[u] * c[v] - b[v] * c[u]); |
|
324 if (gamma < 0) |
|
325 return false; |
|
326 if (beta+gamma > 1) |
|
327 return false; |
|
328 dist = t; |
|
329 return true; |
|
330 #endif |
|
331 } |
|
332 |
|
333 BBox Triangle::get_bbox() const |
271 { |
334 { |
272 BBox bbox = BBox(); |
335 BBox bbox = BBox(); |
273 bbox.L = A; |
336 bbox.L = A; |
274 if (B.x < bbox.L.x) bbox.L.x = B.x; |
337 if (B.x < bbox.L.x) bbox.L.x = B.x; |
275 if (C.x < bbox.L.x) bbox.L.x = C.x; |
338 if (C.x < bbox.L.x) bbox.L.x = C.x; |