1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | namespace embree |
7 | { |
8 | namespace isa |
9 | { |
10 | /*! Intersects a ray with a quad with backface culling |
11 | * enabled. The quad v0,v1,v2,v3 is split into two triangles |
12 | * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two |
13 | * triangles gets intersected. */ |
14 | template<int N> |
15 | __forceinline vbool<N> intersect_quad_backface_culling(const vbool<N>& valid0, |
16 | const Vec3fa& ray_org, |
17 | const Vec3fa& ray_dir, |
18 | const float ray_tnear, |
19 | const float ray_tfar, |
20 | const Vec3vf<N>& quad_v0, |
21 | const Vec3vf<N>& quad_v1, |
22 | const Vec3vf<N>& quad_v2, |
23 | const Vec3vf<N>& quad_v3, |
24 | vfloat<N>& u_o, |
25 | vfloat<N>& v_o, |
26 | vfloat<N>& t_o) |
27 | { |
28 | /* calculate vertices relative to ray origin */ |
29 | vbool<N> valid = valid0; |
30 | const Vec3vf<N> O = Vec3vf<N>(ray_org); |
31 | const Vec3vf<N> D = Vec3vf<N>(ray_dir); |
32 | const Vec3vf<N> va = quad_v0-O; |
33 | const Vec3vf<N> vb = quad_v1-O; |
34 | const Vec3vf<N> vc = quad_v2-O; |
35 | const Vec3vf<N> vd = quad_v3-O; |
36 | |
37 | const Vec3vf<N> edb = vb-vd; |
38 | const vfloat<N> WW = dot(cross(vd,edb),D); |
39 | const Vec3vf<N> v0 = select(WW <= 0.0f,va,vc); |
40 | const Vec3vf<N> v1 = select(WW <= 0.0f,vb,vd); |
41 | const Vec3vf<N> v2 = select(WW <= 0.0f,vd,vb); |
42 | |
43 | /* calculate edges */ |
44 | const Vec3vf<N> e0 = v2-v0; |
45 | const Vec3vf<N> e1 = v0-v1; |
46 | |
47 | /* perform edge tests */ |
48 | const vfloat<N> U = dot(cross(v0,e0),D); |
49 | const vfloat<N> V = dot(cross(v1,e1),D); |
50 | valid &= max(U,V) <= 0.0f; |
51 | if (unlikely(none(valid))) return false; |
52 | |
53 | /* calculate geometry normal and denominator */ |
54 | const Vec3vf<N> Ng = cross(e1,e0); |
55 | const vfloat<N> den = dot(Ng,D); |
56 | const vfloat<N> rcpDen = rcp(den); |
57 | |
58 | /* perform depth test */ |
59 | const vfloat<N> t = rcpDen*dot(v0,Ng); |
60 | valid &= vfloat<N>(ray_tnear) <= t & t <= vfloat<N>(ray_tfar); |
61 | if (unlikely(none(valid))) return false; |
62 | |
63 | /* avoid division by 0 */ |
64 | valid &= den != vfloat<N>(zero); |
65 | if (unlikely(none(valid))) return false; |
66 | |
67 | /* update hit information */ |
68 | t_o = t; |
69 | u_o = U * rcpDen; |
70 | v_o = V * rcpDen; |
71 | u_o = select(WW <= 0.0f,u_o,1.0f-u_o); |
72 | v_o = select(WW <= 0.0f,v_o,1.0f-v_o); |
73 | return valid; |
74 | } |
75 | } |
76 | } |
77 | |