1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "triangle.h" |
7 | #include "triangle_intersector_pluecker.h" |
8 | #include "triangle_intersector_moeller.h" |
9 | #include "triangle_intersector_woop.h" |
10 | |
11 | namespace embree |
12 | { |
13 | namespace isa |
14 | { |
15 | /*! Intersects M triangles with 1 ray */ |
16 | template<int M, bool filter> |
17 | struct TriangleMvIntersector1Moeller |
18 | { |
19 | typedef TriangleMv<M> Primitive; |
20 | typedef MoellerTrumboreIntersector1<M> Precalculations; |
21 | |
22 | /*! Intersect a ray with M triangles and updates the hit. */ |
23 | static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
24 | { |
25 | STAT3(normal.trav_prims,1,1,1); |
26 | pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
27 | } |
28 | |
29 | /*! Test if the ray is occluded by one of the M triangles. */ |
30 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
31 | { |
32 | STAT3(shadow.trav_prims,1,1,1); |
33 | return pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
34 | } |
35 | |
36 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
37 | { |
38 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
39 | } |
40 | }; |
41 | |
42 | |
43 | template<int M, bool filter> |
44 | struct TriangleMvIntersector1Woop |
45 | { |
46 | typedef TriangleMv<M> Primitive; |
47 | typedef WoopIntersector1<M> intersec; |
48 | typedef WoopPrecalculations1<M> Precalculations; |
49 | |
50 | /*! Intersect a ray with M triangles and updates the hit. */ |
51 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
52 | { |
53 | STAT3(normal.trav_prims,1,1,1); |
54 | intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
55 | } |
56 | |
57 | /*! Test if the ray is occluded by one of the M triangles. */ |
58 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
59 | { |
60 | STAT3(shadow.trav_prims,1,1,1); |
61 | return intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
62 | } |
63 | |
64 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
65 | { |
66 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
67 | } |
68 | }; |
69 | |
70 | |
71 | /*! Intersects M triangles with K rays */ |
72 | template<int M, int K, bool filter> |
73 | struct TriangleMvIntersectorKMoeller |
74 | { |
75 | typedef TriangleMv<M> Primitive; |
76 | typedef MoellerTrumboreIntersectorK<M,K> Precalculations; |
77 | |
78 | /*! Intersects K rays with M triangles. */ |
79 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri) |
80 | { |
81 | for (size_t i=0; i<M; i++) |
82 | { |
83 | if (!tri.valid(i)) break; |
84 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
85 | const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i); |
86 | const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i); |
87 | const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i); |
88 | pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity<K>(),*/IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i)); |
89 | } |
90 | } |
91 | |
92 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
93 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri) |
94 | { |
95 | vbool<K> valid0 = valid_i; |
96 | |
97 | for (size_t i=0; i<M; i++) |
98 | { |
99 | if (!tri.valid(i)) break; |
100 | STAT3(shadow.trav_prims,1,popcnt(valid_i),K); |
101 | const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i); |
102 | const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i); |
103 | const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i); |
104 | pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity<K>(),*/OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i)); |
105 | if (none(valid0)) break; |
106 | } |
107 | return !valid0; |
108 | } |
109 | |
110 | /*! Intersect a ray with M triangles and updates the hit. */ |
111 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
112 | { |
113 | STAT3(normal.trav_prims,1,1,1); |
114 | pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M |
115 | } |
116 | |
117 | /*! Test if the ray is occluded by one of the M triangles. */ |
118 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
119 | { |
120 | STAT3(shadow.trav_prims,1,1,1); |
121 | return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity<M>(),*/Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M |
122 | } |
123 | }; |
124 | |
125 | /*! Intersects M triangles with 1 ray */ |
126 | template<int M, bool filter> |
127 | struct TriangleMvIntersector1Pluecker |
128 | { |
129 | typedef TriangleMv<M> Primitive; |
130 | typedef PlueckerIntersector1<M> Precalculations; |
131 | |
132 | /*! Intersect a ray with M triangles and updates the hit. */ |
133 | static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
134 | { |
135 | STAT3(normal.trav_prims,1,1,1); |
136 | pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
137 | } |
138 | |
139 | /*! Test if the ray is occluded by one of the M triangles. */ |
140 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
141 | { |
142 | STAT3(shadow.trav_prims,1,1,1); |
143 | return pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
144 | } |
145 | |
146 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
147 | { |
148 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
149 | } |
150 | }; |
151 | |
152 | /*! Intersects M triangles with K rays */ |
153 | template<int M, int K, bool filter> |
154 | struct TriangleMvIntersectorKPluecker |
155 | { |
156 | typedef TriangleMv<M> Primitive; |
157 | typedef PlueckerIntersectorK<M,K> Precalculations; |
158 | |
159 | /*! Intersects K rays with M triangles. */ |
160 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri) |
161 | { |
162 | for (size_t i=0; i<M; i++) |
163 | { |
164 | if (!tri.valid(i)) break; |
165 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
166 | const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i); |
167 | const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i); |
168 | const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i); |
169 | pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i)); |
170 | } |
171 | } |
172 | |
173 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
174 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri) |
175 | { |
176 | vbool<K> valid0 = valid_i; |
177 | |
178 | for (size_t i=0; i<M; i++) |
179 | { |
180 | if (!tri.valid(i)) break; |
181 | STAT3(shadow.trav_prims,1,popcnt(valid_i),K); |
182 | const Vec3vf<K> v0 = broadcast<vfloat<K>>(tri.v0,i); |
183 | const Vec3vf<K> v1 = broadcast<vfloat<K>>(tri.v1,i); |
184 | const Vec3vf<K> v2 = broadcast<vfloat<K>>(tri.v2,i); |
185 | pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i)); |
186 | if (none(valid0)) break; |
187 | } |
188 | return !valid0; |
189 | } |
190 | |
191 | /*! Intersect a ray with M triangles and updates the hit. */ |
192 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
193 | { |
194 | STAT3(normal.trav_prims,1,1,1); |
195 | pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
196 | } |
197 | |
198 | /*! Test if the ray is occluded by one of the M triangles. */ |
199 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
200 | { |
201 | STAT3(shadow.trav_prims,1,1,1); |
202 | return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity<M>(),Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
203 | } |
204 | }; |
205 | } |
206 | } |
207 | |