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