| 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 |  |