1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "curveNi_mb.h" |
7 | #include "../subdiv/linear_bezier_patch.h" |
8 | |
9 | namespace embree |
10 | { |
11 | namespace isa |
12 | { |
13 | template<int M> |
14 | struct CurveNiMBIntersector1 |
15 | { |
16 | typedef CurveNiMB<M> Primitive; |
17 | typedef Vec3vf<M> Vec3vfM; |
18 | typedef LinearSpace3<Vec3vfM>LinearSpace3vfM; |
19 | typedef CurvePrecalculations1 Precalculations; |
20 | |
21 | static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o) |
22 | { |
23 | const size_t N = prim.N; |
24 | const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N)); |
25 | const Vec3fa offset = Vec3fa(offset_scale); |
26 | const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(v: offset_scale)); |
27 | const Vec3fa org1 = (ray.org-offset)*scale; |
28 | const Vec3fa dir1 = ray.dir*scale; |
29 | |
30 | const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)), |
31 | vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)), |
32 | vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N))); |
33 | |
34 | const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1)); |
35 | const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1)); |
36 | const Vec3vfM rcp_dir2 = rcp_safe(dir2); |
37 | |
38 | const vfloat<M> ltime = (ray.time()-prim.time_offset(N))*prim.time_scale(N); |
39 | const vfloat<M> vx_lower0 = vfloat<M>::load(prim.bounds_vx_lower0(N)); |
40 | const vfloat<M> vx_lower1 = vfloat<M>::load(prim.bounds_vx_lower1(N)); |
41 | const vfloat<M> vx_lower = madd(ltime,vx_lower1-vx_lower0,vx_lower0); |
42 | const vfloat<M> vx_upper0 = vfloat<M>::load(prim.bounds_vx_upper0(N)); |
43 | const vfloat<M> vx_upper1 = vfloat<M>::load(prim.bounds_vx_upper1(N)); |
44 | const vfloat<M> vx_upper = madd(ltime,vx_upper1-vx_upper0,vx_upper0); |
45 | |
46 | const vfloat<M> vy_lower0 = vfloat<M>::load(prim.bounds_vy_lower0(N)); |
47 | const vfloat<M> vy_lower1 = vfloat<M>::load(prim.bounds_vy_lower1(N)); |
48 | const vfloat<M> vy_lower = madd(ltime,vy_lower1-vy_lower0,vy_lower0); |
49 | const vfloat<M> vy_upper0 = vfloat<M>::load(prim.bounds_vy_upper0(N)); |
50 | const vfloat<M> vy_upper1 = vfloat<M>::load(prim.bounds_vy_upper1(N)); |
51 | const vfloat<M> vy_upper = madd(ltime,vy_upper1-vy_upper0,vy_upper0); |
52 | |
53 | const vfloat<M> vz_lower0 = vfloat<M>::load(prim.bounds_vz_lower0(N)); |
54 | const vfloat<M> vz_lower1 = vfloat<M>::load(prim.bounds_vz_lower1(N)); |
55 | const vfloat<M> vz_lower = madd(ltime,vz_lower1-vz_lower0,vz_lower0); |
56 | const vfloat<M> vz_upper0 = vfloat<M>::load(prim.bounds_vz_upper0(N)); |
57 | const vfloat<M> vz_upper1 = vfloat<M>::load(prim.bounds_vz_upper1(N)); |
58 | const vfloat<M> vz_upper = madd(ltime,vz_upper1-vz_upper0,vz_upper0); |
59 | |
60 | const vfloat<M> t_lower_x = (vx_lower-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
61 | const vfloat<M> t_upper_x = (vx_upper-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
62 | const vfloat<M> t_lower_y = (vy_lower-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
63 | const vfloat<M> t_upper_y = (vy_upper-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
64 | const vfloat<M> t_lower_z = (vz_lower-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
65 | const vfloat<M> t_upper_z = (vz_upper-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
66 | |
67 | const vfloat<M> round_up (1.0f+3.0f*float(ulp)); |
68 | const vfloat<M> round_down(1.0f-3.0f*float(ulp)); |
69 | const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear())); |
70 | const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar)); |
71 | tNear_o = tNear; |
72 | return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar); |
73 | } |
74 | |
75 | template<typename Intersector, typename Epilog> |
76 | static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
77 | { |
78 | vfloat<M> tNear; |
79 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
80 | |
81 | const size_t N = prim.N; |
82 | size_t mask = movemask(valid); |
83 | while (mask) |
84 | { |
85 | const size_t i = bscf(v&: mask); |
86 | STAT3(normal.trav_prims,1,1,1); |
87 | const unsigned int geomID = prim.geomID(N); |
88 | const unsigned int primID = prim.primID(N)[i]; |
89 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
90 | Vec3ff a0,a1,a2,a3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,i: geom->curve(i: primID),time: ray.time()); |
91 | |
92 | Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)); |
93 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
94 | } |
95 | } |
96 | |
97 | template<typename Intersector, typename Epilog> |
98 | static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
99 | { |
100 | vfloat<M> tNear; |
101 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
102 | |
103 | const size_t N = prim.N; |
104 | size_t mask = movemask(valid); |
105 | while (mask) |
106 | { |
107 | const size_t i = bscf(v&: mask); |
108 | STAT3(shadow.trav_prims,1,1,1); |
109 | const unsigned int geomID = prim.geomID(N); |
110 | const unsigned int primID = prim.primID(N)[i]; |
111 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
112 | Vec3ff a0,a1,a2,a3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,i: geom->curve(i: primID),time: ray.time()); |
113 | |
114 | if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID))) |
115 | return true; |
116 | |
117 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
118 | } |
119 | return false; |
120 | } |
121 | |
122 | template<typename Intersector, typename Epilog> |
123 | static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
124 | { |
125 | vfloat<M> tNear; |
126 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
127 | |
128 | const size_t N = prim.N; |
129 | size_t mask = movemask(valid); |
130 | while (mask) |
131 | { |
132 | const size_t i = bscf(v&: mask); |
133 | STAT3(normal.trav_prims,1,1,1); |
134 | const unsigned int geomID = prim.geomID(N); |
135 | const unsigned int primID = prim.primID(N)[i]; |
136 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
137 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time()); |
138 | Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID)); |
139 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
140 | } |
141 | } |
142 | |
143 | template<typename Intersector, typename Epilog> |
144 | static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
145 | { |
146 | vfloat<M> tNear; |
147 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
148 | |
149 | const size_t N = prim.N; |
150 | size_t mask = movemask(valid); |
151 | while (mask) |
152 | { |
153 | const size_t i = bscf(v&: mask); |
154 | STAT3(shadow.trav_prims,1,1,1); |
155 | const unsigned int geomID = prim.geomID(N); |
156 | const unsigned int primID = prim.primID(N)[i]; |
157 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
158 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time()); |
159 | |
160 | if (Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID))) |
161 | return true; |
162 | |
163 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
164 | } |
165 | return false; |
166 | } |
167 | |
168 | template<typename Intersector, typename Epilog> |
169 | static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
170 | { |
171 | vfloat<M> tNear; |
172 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
173 | |
174 | const size_t N = prim.N; |
175 | size_t mask = movemask(valid); |
176 | while (mask) |
177 | { |
178 | const size_t i = bscf(v&: mask); |
179 | STAT3(normal.trav_prims,1,1,1); |
180 | const unsigned int geomID = prim.geomID(N); |
181 | const unsigned int primID = prim.primID(N)[i]; |
182 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
183 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,i: geom->curve(i: primID),time: ray.time()); |
184 | Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)); |
185 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
186 | } |
187 | } |
188 | |
189 | template<typename Intersector, typename Epilog> |
190 | static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
191 | { |
192 | vfloat<M> tNear; |
193 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
194 | |
195 | const size_t N = prim.N; |
196 | size_t mask = movemask(valid); |
197 | while (mask) |
198 | { |
199 | const size_t i = bscf(v&: mask); |
200 | STAT3(shadow.trav_prims,1,1,1); |
201 | const unsigned int geomID = prim.geomID(N); |
202 | const unsigned int primID = prim.primID(N)[i]; |
203 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
204 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,i: geom->curve(i: primID),time: ray.time()); |
205 | if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID))) |
206 | return true; |
207 | |
208 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
209 | } |
210 | return false; |
211 | } |
212 | |
213 | template<typename Intersector, typename Epilog> |
214 | static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
215 | { |
216 | vfloat<M> tNear; |
217 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
218 | |
219 | const size_t N = prim.N; |
220 | size_t mask = movemask(valid); |
221 | while (mask) |
222 | { |
223 | const size_t i = bscf(v&: mask); |
224 | STAT3(normal.trav_prims,1,1,1); |
225 | const unsigned int geomID = prim.geomID(N); |
226 | const unsigned int primID = prim.primID(N)[i]; |
227 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
228 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time()); |
229 | Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID)); |
230 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
231 | } |
232 | } |
233 | |
234 | template<typename Intersector, typename Epilog> |
235 | static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
236 | { |
237 | vfloat<M> tNear; |
238 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
239 | |
240 | const size_t N = prim.N; |
241 | size_t mask = movemask(valid); |
242 | while (mask) |
243 | { |
244 | const size_t i = bscf(v&: mask); |
245 | STAT3(shadow.trav_prims,1,1,1); |
246 | const unsigned int geomID = prim.geomID(N); |
247 | const unsigned int primID = prim.primID(N)[i]; |
248 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
249 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray.org, primID,ray.time()); |
250 | if (Intersector().intersect(pre,ray,context,geom,primID,curve,Epilog(ray,context,geomID,primID))) |
251 | return true; |
252 | |
253 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
254 | } |
255 | return false; |
256 | } |
257 | }; |
258 | |
259 | template<int M, int K> |
260 | struct CurveNiMBIntersectorK |
261 | { |
262 | typedef CurveNiMB<M> Primitive; |
263 | typedef Vec3vf<M> Vec3vfM; |
264 | typedef LinearSpace3<Vec3vfM>LinearSpace3vfM; |
265 | typedef CurvePrecalculationsK<K> Precalculations; |
266 | |
267 | static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o) |
268 | { |
269 | const size_t N = prim.N; |
270 | const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N)); |
271 | const Vec3fa offset = Vec3fa(offset_scale); |
272 | const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(v: offset_scale)); |
273 | |
274 | const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]); |
275 | const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]); |
276 | const Vec3fa org1 = (ray_org-offset)*scale; |
277 | const Vec3fa dir1 = ray_dir*scale; |
278 | |
279 | const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)), |
280 | vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)), |
281 | vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N))); |
282 | |
283 | const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1)); |
284 | const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1)); |
285 | const Vec3vfM rcp_dir2 = rcp_safe(dir2); |
286 | |
287 | const vfloat<M> ltime = (ray.time()[k]-prim.time_offset(N))*prim.time_scale(N); |
288 | const vfloat<M> vx_lower0 = vfloat<M>::load(prim.bounds_vx_lower0(N)); |
289 | const vfloat<M> vx_lower1 = vfloat<M>::load(prim.bounds_vx_lower1(N)); |
290 | const vfloat<M> vx_lower = madd(ltime,vx_lower1-vx_lower0,vx_lower0); |
291 | const vfloat<M> vx_upper0 = vfloat<M>::load(prim.bounds_vx_upper0(N)); |
292 | const vfloat<M> vx_upper1 = vfloat<M>::load(prim.bounds_vx_upper1(N)); |
293 | const vfloat<M> vx_upper = madd(ltime,vx_upper1-vx_upper0,vx_upper0); |
294 | |
295 | const vfloat<M> vy_lower0 = vfloat<M>::load(prim.bounds_vy_lower0(N)); |
296 | const vfloat<M> vy_lower1 = vfloat<M>::load(prim.bounds_vy_lower1(N)); |
297 | const vfloat<M> vy_lower = madd(ltime,vy_lower1-vy_lower0,vy_lower0); |
298 | const vfloat<M> vy_upper0 = vfloat<M>::load(prim.bounds_vy_upper0(N)); |
299 | const vfloat<M> vy_upper1 = vfloat<M>::load(prim.bounds_vy_upper1(N)); |
300 | const vfloat<M> vy_upper = madd(ltime,vy_upper1-vy_upper0,vy_upper0); |
301 | |
302 | const vfloat<M> vz_lower0 = vfloat<M>::load(prim.bounds_vz_lower0(N)); |
303 | const vfloat<M> vz_lower1 = vfloat<M>::load(prim.bounds_vz_lower1(N)); |
304 | const vfloat<M> vz_lower = madd(ltime,vz_lower1-vz_lower0,vz_lower0); |
305 | const vfloat<M> vz_upper0 = vfloat<M>::load(prim.bounds_vz_upper0(N)); |
306 | const vfloat<M> vz_upper1 = vfloat<M>::load(prim.bounds_vz_upper1(N)); |
307 | const vfloat<M> vz_upper = madd(ltime,vz_upper1-vz_upper0,vz_upper0); |
308 | |
309 | const vfloat<M> t_lower_x = (vx_lower-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
310 | const vfloat<M> t_upper_x = (vx_upper-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
311 | const vfloat<M> t_lower_y = (vy_lower-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
312 | const vfloat<M> t_upper_y = (vy_upper-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
313 | const vfloat<M> t_lower_z = (vz_lower-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
314 | const vfloat<M> t_upper_z = (vz_upper-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
315 | |
316 | const vfloat<M> round_up (1.0f+3.0f*float(ulp)); |
317 | const vfloat<M> round_down(1.0f-3.0f*float(ulp)); |
318 | const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k])); |
319 | const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k])); |
320 | tNear_o = tNear; |
321 | return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar); |
322 | } |
323 | |
324 | template<typename Intersector, typename Epilog> |
325 | static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
326 | { |
327 | |
328 | vfloat<M> tNear; |
329 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
330 | |
331 | const size_t N = prim.N; |
332 | size_t mask = movemask(valid); |
333 | while (mask) |
334 | { |
335 | const size_t i = bscf(v&: mask); |
336 | STAT3(normal.trav_prims,1,1,1); |
337 | const unsigned int geomID = prim.geomID(N); |
338 | const unsigned int primID = prim.primID(N)[i]; |
339 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
340 | Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(i: primID),ray.time()[k]); |
341 | |
342 | Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)); |
343 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
344 | } |
345 | } |
346 | |
347 | template<typename Intersector, typename Epilog> |
348 | static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
349 | { |
350 | vfloat<M> tNear; |
351 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
352 | |
353 | const size_t N = prim.N; |
354 | size_t mask = movemask(valid); |
355 | while (mask) |
356 | { |
357 | const size_t i = bscf(v&: mask); |
358 | STAT3(shadow.trav_prims,1,1,1); |
359 | const unsigned int geomID = prim.geomID(N); |
360 | const unsigned int primID = prim.primID(N)[i]; |
361 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
362 | Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(i: primID),ray.time()[k]); |
363 | |
364 | if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID))) |
365 | return true; |
366 | |
367 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
368 | } |
369 | return false; |
370 | } |
371 | |
372 | template<typename Intersector, typename Epilog> |
373 | static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
374 | { |
375 | |
376 | vfloat<M> tNear; |
377 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
378 | |
379 | const size_t N = prim.N; |
380 | size_t mask = movemask(valid); |
381 | while (mask) |
382 | { |
383 | const size_t i = bscf(v&: mask); |
384 | STAT3(normal.trav_prims,1,1,1); |
385 | const unsigned int geomID = prim.geomID(N); |
386 | const unsigned int primID = prim.primID(N)[i]; |
387 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
388 | const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); |
389 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]); |
390 | Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID)); |
391 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
392 | } |
393 | } |
394 | |
395 | template<typename Intersector, typename Epilog> |
396 | static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
397 | { |
398 | vfloat<M> tNear; |
399 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
400 | |
401 | const size_t N = prim.N; |
402 | size_t mask = movemask(valid); |
403 | while (mask) |
404 | { |
405 | const size_t i = bscf(v&: mask); |
406 | STAT3(shadow.trav_prims,1,1,1); |
407 | const unsigned int geomID = prim.geomID(N); |
408 | const unsigned int primID = prim.primID(N)[i]; |
409 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
410 | const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); |
411 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]); |
412 | |
413 | if (Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID))) |
414 | return true; |
415 | |
416 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
417 | } |
418 | return false; |
419 | } |
420 | |
421 | template<typename Intersector, typename Epilog> |
422 | static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
423 | { |
424 | |
425 | vfloat<M> tNear; |
426 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
427 | |
428 | const size_t N = prim.N; |
429 | size_t mask = movemask(valid); |
430 | while (mask) |
431 | { |
432 | const size_t i = bscf(v&: mask); |
433 | STAT3(normal.trav_prims,1,1,1); |
434 | const unsigned int geomID = prim.geomID(N); |
435 | const unsigned int primID = prim.primID(N)[i]; |
436 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
437 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(i: primID),ray.time()[k]); |
438 | Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)); |
439 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
440 | } |
441 | } |
442 | |
443 | template<typename Intersector, typename Epilog> |
444 | static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
445 | { |
446 | vfloat<M> tNear; |
447 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
448 | |
449 | const size_t N = prim.N; |
450 | size_t mask = movemask(valid); |
451 | while (mask) |
452 | { |
453 | const size_t i = bscf(v&: mask); |
454 | STAT3(shadow.trav_prims,1,1,1); |
455 | const unsigned int geomID = prim.geomID(N); |
456 | const unsigned int primID = prim.primID(N)[i]; |
457 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
458 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(i: primID),ray.time()[k]); |
459 | if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID))) |
460 | return true; |
461 | |
462 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
463 | } |
464 | return false; |
465 | } |
466 | |
467 | template<typename Intersector, typename Epilog> |
468 | static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
469 | { |
470 | |
471 | vfloat<M> tNear; |
472 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
473 | |
474 | const size_t N = prim.N; |
475 | size_t mask = movemask(valid); |
476 | while (mask) |
477 | { |
478 | const size_t i = bscf(v&: mask); |
479 | STAT3(normal.trav_prims,1,1,1); |
480 | const unsigned int geomID = prim.geomID(N); |
481 | const unsigned int primID = prim.primID(N)[i]; |
482 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
483 | const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); |
484 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]); |
485 | Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID)); |
486 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
487 | } |
488 | } |
489 | |
490 | template<typename Intersector, typename Epilog> |
491 | static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
492 | { |
493 | vfloat<M> tNear; |
494 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
495 | |
496 | const size_t N = prim.N; |
497 | size_t mask = movemask(valid); |
498 | while (mask) |
499 | { |
500 | const size_t i = bscf(v&: mask); |
501 | STAT3(shadow.trav_prims,1,1,1); |
502 | const unsigned int geomID = prim.geomID(N); |
503 | const unsigned int primID = prim.primID(N)[i]; |
504 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
505 | const Vec3fa ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); |
506 | const TensorLinearCubicBezierSurface3fa curve = geom->getNormalOrientedHermiteCurve<typename Intersector::SourceCurve3ff, typename Intersector::SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,ray.time()[k]); |
507 | if (Intersector().intersect(pre,ray,k,context,geom,primID,curve,Epilog(ray,k,context,geomID,primID))) |
508 | return true; |
509 | |
510 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
511 | } |
512 | return false; |
513 | } |
514 | }; |
515 | } |
516 | } |
517 | |