| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  | // Copyright 2009-2021 Intel Corporation
 | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  | // SPDX-License-Identifier: Apache-2.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../common/ray.h"
 | 
					
						
							|  |  |  | #include "../common/context.h"
 | 
					
						
							|  |  |  | #include "filter.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace embree | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   namespace isa | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     template<int M> | 
					
						
							|  |  |  |     struct UVIdentity { | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |       __forceinline void operator() (vfloat<M>& u, vfloat<M>& v, Vec3vf<M>& Ng) const {} | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<bool filter> | 
					
						
							|  |  |  |     struct Intersect1Epilog1 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHit& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Intersect1Epilog1(RayHit& ray, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                       const unsigned int geomID, | 
					
						
							|  |  |  |                                       const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask) == 0) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         hit.finalize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { | 
					
						
							|  |  |  |             HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng); | 
					
						
							|  |  |  |             const float old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = hit.t; | 
					
						
							|  |  |  |             bool found = runIntersectionFilter1(geometry,ray,context,h); | 
					
						
							|  |  |  |             if (!found) ray.tfar = old_t; | 
					
						
							|  |  |  |             return found; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         ray.tfar = hit.t; | 
					
						
							|  |  |  |         ray.Ng = hit.Ng; | 
					
						
							|  |  |  |         ray.u = hit.u; | 
					
						
							|  |  |  |         ray.v = hit.v; | 
					
						
							|  |  |  |         ray.primID = primID; | 
					
						
							|  |  |  |         ray.geomID = geomID; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UU(context->user->instID, ray.instID); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<bool filter> | 
					
						
							|  |  |  |     struct Occluded1Epilog1 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Ray& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Occluded1Epilog1(Ray& ray, | 
					
						
							|  |  |  |                                      IntersectContext* context, | 
					
						
							|  |  |  |                                      const unsigned int geomID, | 
					
						
							|  |  |  |                                      const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask) == 0) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         hit.finalize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) { | 
					
						
							|  |  |  |             HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng); | 
					
						
							|  |  |  |             const float old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = hit.t; | 
					
						
							|  |  |  |             const bool found = runOcclusionFilter1(geometry,ray,context,h); | 
					
						
							|  |  |  |             if (!found) ray.tfar = old_t; | 
					
						
							|  |  |  |             return found; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<int K, bool filter> | 
					
						
							|  |  |  |     struct Intersect1KEpilog1 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHitK<K>& ray; | 
					
						
							|  |  |  |       size_t k; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k, | 
					
						
							|  |  |  |                                        IntersectContext* context, | 
					
						
							|  |  |  |                                        const unsigned int geomID, | 
					
						
							|  |  |  |                                        const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask[k]) == 0) | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         hit.finalize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { | 
					
						
							|  |  |  |             HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng); | 
					
						
							|  |  |  |             const float old_t = ray.tfar[k]; | 
					
						
							|  |  |  |             ray.tfar[k] = hit.t; | 
					
						
							|  |  |  |             const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h)); | 
					
						
							|  |  |  |             if (!found) ray.tfar[k] = old_t; | 
					
						
							|  |  |  |             return found; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         ray.tfar[k] = hit.t; | 
					
						
							|  |  |  |         ray.Ng.x[k] = hit.Ng.x; | 
					
						
							|  |  |  |         ray.Ng.y[k] = hit.Ng.y; | 
					
						
							|  |  |  |         ray.Ng.z[k] = hit.Ng.z; | 
					
						
							|  |  |  |         ray.u[k] = hit.u; | 
					
						
							|  |  |  |         ray.v[k] = hit.v; | 
					
						
							|  |  |  |         ray.primID[k] = primID; | 
					
						
							|  |  |  |         ray.geomID[k] = geomID; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int K, bool filter> | 
					
						
							|  |  |  |     struct Occluded1KEpilog1 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayK<K>& ray; | 
					
						
							|  |  |  |       size_t k; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                       const unsigned int geomID, | 
					
						
							|  |  |  |                                       const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask[k]) == 0) | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) { | 
					
						
							|  |  |  |             hit.finalize(); | 
					
						
							|  |  |  |             HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng); | 
					
						
							|  |  |  |             const float old_t = ray.tfar[k]; | 
					
						
							|  |  |  |             ray.tfar[k] = hit.t; | 
					
						
							|  |  |  |             const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h)); | 
					
						
							|  |  |  |             if (!found) ray.tfar[k] = old_t; | 
					
						
							|  |  |  |             return found; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |     template<int M, bool filter> | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |     struct Intersect1EpilogM | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHit& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const vuint<M>& geomIDs; | 
					
						
							|  |  |  |       const vuint<M>& primIDs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Intersect1EpilogM(RayHit& ray, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                       const vuint<M>& geomIDs, | 
					
						
							|  |  |  |                                       const vuint<M>& primIDs) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         vbool<M> valid = valid_i; | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         hit.finalize(); | 
					
						
							|  |  |  |         size_t i = select_min(valid,hit.vt); | 
					
						
							|  |  |  |         unsigned int geomID = geomIDs[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         bool foundhit = false; | 
					
						
							|  |  |  |         goto entry; | 
					
						
							|  |  |  |         while (true) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (unlikely(none(valid))) return foundhit; | 
					
						
							|  |  |  |           i = select_min(valid,hit.vt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           geomID = geomIDs[i]; | 
					
						
							|  |  |  |         entry: | 
					
						
							|  |  |  |           Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |           /* goto next hit if mask test fails */ | 
					
						
							|  |  |  |           if ((geometry->mask & ray.mask) == 0) { | 
					
						
							|  |  |  |             clear(valid,i); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION) 
 | 
					
						
							|  |  |  |           /* call intersection filter function */ | 
					
						
							|  |  |  |           if (filter) { | 
					
						
							|  |  |  |             if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { | 
					
						
							|  |  |  |               const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |               HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |               const float old_t = ray.tfar; | 
					
						
							|  |  |  |               ray.tfar = hit.t(i); | 
					
						
							|  |  |  |               const bool found = runIntersectionFilter1(geometry,ray,context,h); | 
					
						
							|  |  |  |               if (!found) ray.tfar = old_t; | 
					
						
							|  |  |  |               foundhit |= found; | 
					
						
							|  |  |  |               clear(valid,i); | 
					
						
							|  |  |  |               valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
 | 
					
						
							|  |  |  |               continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |         ray.tfar = hit.vt[i]; | 
					
						
							|  |  |  |         ray.Ng.x = hit.vNg.x[i]; | 
					
						
							|  |  |  |         ray.Ng.y = hit.vNg.y[i]; | 
					
						
							|  |  |  |         ray.Ng.z = hit.vNg.z[i]; | 
					
						
							|  |  |  |         ray.u = uv.x; | 
					
						
							|  |  |  |         ray.v = uv.y; | 
					
						
							|  |  |  |         ray.primID = primIDs[i]; | 
					
						
							|  |  |  |         ray.geomID = geomID; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UU(context->user->instID, ray.instID); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<int M, bool filter> | 
					
						
							|  |  |  |     struct Occluded1EpilogM | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Ray& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const vuint<M>& geomIDs; | 
					
						
							|  |  |  |       const vuint<M>& primIDs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Occluded1EpilogM(Ray& ray, | 
					
						
							|  |  |  |                                      IntersectContext* context, | 
					
						
							|  |  |  |                                      const vuint<M>& geomIDs, | 
					
						
							|  |  |  |                                      const vuint<M>& primIDs) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if (unlikely(filter)) | 
					
						
							|  |  |  |           hit.finalize(); /* called only once */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         vbool<M> valid = valid_i; | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         size_t m=movemask(valid); | 
					
						
							|  |  |  |         goto entry; | 
					
						
							|  |  |  |         while (true) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (unlikely(m == 0)) return false; | 
					
						
							|  |  |  |         entry: | 
					
						
							|  |  |  |           size_t i=bsf(m); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const unsigned int geomID = geomIDs[i]; | 
					
						
							|  |  |  |           Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |           /* goto next hit if mask test fails */ | 
					
						
							|  |  |  |           if ((geometry->mask & ray.mask) == 0) { | 
					
						
							|  |  |  |             m=btc(m,i); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |           /* if we have no filter then the test passed */ | 
					
						
							|  |  |  |           if (filter) { | 
					
						
							|  |  |  |             if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |               HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |               const float old_t = ray.tfar; | 
					
						
							|  |  |  |               ray.tfar = hit.t(i); | 
					
						
							|  |  |  |               if (runOcclusionFilter1(geometry,ray,context,h)) return true; | 
					
						
							|  |  |  |               ray.tfar = old_t; | 
					
						
							|  |  |  |               m=btc(m,i); | 
					
						
							|  |  |  |               continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<int M, bool filter> | 
					
						
							|  |  |  |     struct Intersect1EpilogMU | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHit& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Intersect1EpilogMU(RayHit& ray, | 
					
						
							|  |  |  |                                        IntersectContext* context, | 
					
						
							|  |  |  |                                        const unsigned int geomID, | 
					
						
							|  |  |  |                                        const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask) == 0) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vbool<M> valid = valid_i; | 
					
						
							|  |  |  |         hit.finalize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         size_t i = select_min(valid,hit.vt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           bool foundhit = false; | 
					
						
							|  |  |  |           while (true) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             /* call intersection filter function */ | 
					
						
							|  |  |  |             Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |             const float old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = hit.t(i); | 
					
						
							|  |  |  |             HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |             const bool found = runIntersectionFilter1(geometry,ray,context,h); | 
					
						
							|  |  |  |             if (!found) ray.tfar = old_t; | 
					
						
							|  |  |  |             foundhit |= found; | 
					
						
							|  |  |  |             clear(valid,i); | 
					
						
							|  |  |  |             valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
 | 
					
						
							|  |  |  |             if (unlikely(none(valid))) break; | 
					
						
							|  |  |  |             i = select_min(valid,hit.vt); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           return foundhit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |         const Vec3fa Ng = hit.Ng(i); | 
					
						
							|  |  |  |         ray.tfar = hit.t(i); | 
					
						
							|  |  |  |         ray.Ng.x = Ng.x; | 
					
						
							|  |  |  |         ray.Ng.y = Ng.y; | 
					
						
							|  |  |  |         ray.Ng.z = Ng.z; | 
					
						
							|  |  |  |         ray.u = uv.x; | 
					
						
							|  |  |  |         ray.v = uv.y; | 
					
						
							|  |  |  |         ray.primID = primID; | 
					
						
							|  |  |  |         ray.geomID = geomID; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UU(context->user->instID, ray.instID); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int M, bool filter> | 
					
						
							|  |  |  |     struct Occluded1EpilogMU | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Ray& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Occluded1EpilogMU(Ray& ray, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                       const unsigned int geomID, | 
					
						
							|  |  |  |                                       const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (const vbool<M>& valid, Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask) == 0) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           hit.finalize(); | 
					
						
							|  |  |  |           for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |             const float old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = hit.t(i); | 
					
						
							|  |  |  |             HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |             if (runOcclusionFilter1(geometry,ray,context,h)) return true; | 
					
						
							|  |  |  |             ray.tfar = old_t; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |     template<int M, int K, bool filter> | 
					
						
							|  |  |  |     struct IntersectKEpilogM | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHitK<K>& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const vuint<M>& geomIDs; | 
					
						
							|  |  |  |       const vuint<M>& primIDs; | 
					
						
							|  |  |  |       const size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline IntersectKEpilogM(RayHitK<K>& ray, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                      const vuint<M>& geomIDs, | 
					
						
							|  |  |  |                                      const vuint<M>& primIDs, | 
					
						
							|  |  |  |                                      size_t i) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vfloat<K> u, v, t; | 
					
						
							|  |  |  |         Vec3vf<K> Ng; | 
					
						
							|  |  |  |         vbool<K> valid = valid_i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::tie(u,v,t,Ng) = hit(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const unsigned int geomID = geomIDs[i]; | 
					
						
							|  |  |  |         const unsigned int primID = primIDs[i]; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* ray masking test */ | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         valid &= (geometry->mask & ray.mask) != 0; | 
					
						
							|  |  |  |         if (unlikely(none(valid))) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* occlusion filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { | 
					
						
							|  |  |  |             HitK<K> h(context->user,geomID,primID,u,v,Ng); | 
					
						
							|  |  |  |             const vfloat<K> old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = select(valid,t,ray.tfar); | 
					
						
							|  |  |  |             const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h); | 
					
						
							|  |  |  |             ray.tfar = select(m_accept,ray.tfar,old_t); | 
					
						
							|  |  |  |             return m_accept; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.tfar,t); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.Ng.x,Ng.x); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.Ng.y,Ng.y); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.Ng.z,Ng.z); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.u,u); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.v,v); | 
					
						
							|  |  |  |         vuint<K>::store(valid,&ray.primID,primID); | 
					
						
							|  |  |  |         vuint<K>::store(valid,&ray.geomID,geomID); | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return valid; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int M, int K, bool filter> | 
					
						
							|  |  |  |     struct OccludedKEpilogM | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       vbool<K>& valid0; | 
					
						
							|  |  |  |       RayK<K>& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const vuint<M>& geomIDs; | 
					
						
							|  |  |  |       const vuint<M>& primIDs; | 
					
						
							|  |  |  |       const size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline OccludedKEpilogM(vbool<K>& valid0, | 
					
						
							|  |  |  |                                      RayK<K>& ray, | 
					
						
							|  |  |  |                                      IntersectContext* context, | 
					
						
							|  |  |  |                                      const vuint<M>& geomIDs, | 
					
						
							|  |  |  |                                      const vuint<M>& primIDs, | 
					
						
							|  |  |  |                                      size_t i) | 
					
						
							|  |  |  |         : valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         vbool<K> valid = valid_i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* ray masking test */ | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         const unsigned int geomID MAYBE_UNUSED = geomIDs[i]; | 
					
						
							|  |  |  |         const unsigned int primID MAYBE_UNUSED = primIDs[i]; | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         valid &= (geometry->mask & ray.mask) != 0; | 
					
						
							|  |  |  |         if (unlikely(none(valid))) return valid; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             vfloat<K> u, v, t; | 
					
						
							|  |  |  |             Vec3vf<K> Ng; | 
					
						
							|  |  |  |             std::tie(u,v,t,Ng) = hit(); | 
					
						
							|  |  |  |             HitK<K> h(context->user,geomID,primID,u,v,Ng); | 
					
						
							|  |  |  |             const vfloat<K> old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = select(valid,t,ray.tfar); | 
					
						
							|  |  |  |             valid = runOcclusionFilter(valid,geometry,ray,context,h); | 
					
						
							|  |  |  |             ray.tfar = select(valid,ray.tfar,old_t); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update occlusion */ | 
					
						
							|  |  |  |         valid0 = valid0 & !valid; | 
					
						
							|  |  |  |         return valid; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int M, int K, bool filter> | 
					
						
							|  |  |  |     struct IntersectKEpilogMU | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHitK<K>& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline IntersectKEpilogMU(RayHitK<K>& ray, | 
					
						
							|  |  |  |                                        IntersectContext* context, | 
					
						
							|  |  |  |                                        const unsigned int geomID, | 
					
						
							|  |  |  |                                        const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         vbool<K> valid = valid_org; | 
					
						
							|  |  |  |         vfloat<K> u, v, t; | 
					
						
							|  |  |  |         Vec3vf<K> Ng; | 
					
						
							|  |  |  |         std::tie(u,v,t,Ng) = hit(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* ray masking test */ | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         valid &= (geometry->mask & ray.mask) != 0; | 
					
						
							|  |  |  |         if (unlikely(none(valid))) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { | 
					
						
							|  |  |  |             HitK<K> h(context->user,geomID,primID,u,v,Ng); | 
					
						
							|  |  |  |             const vfloat<K> old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = select(valid,t,ray.tfar); | 
					
						
							|  |  |  |             const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h); | 
					
						
							|  |  |  |             ray.tfar = select(m_accept,ray.tfar,old_t); | 
					
						
							|  |  |  |             return m_accept; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.tfar,t); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.Ng.x,Ng.x); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.Ng.y,Ng.y); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.Ng.z,Ng.z); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.u,u); | 
					
						
							|  |  |  |         vfloat<K>::store(valid,&ray.v,v); | 
					
						
							|  |  |  |         vuint<K>::store(valid,&ray.primID,primID); | 
					
						
							|  |  |  |         vuint<K>::store(valid,&ray.geomID,geomID); | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return valid; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int M, int K, bool filter> | 
					
						
							|  |  |  |     struct OccludedKEpilogMU | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       vbool<K>& valid0; | 
					
						
							|  |  |  |       RayK<K>& ray; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline OccludedKEpilogMU(vbool<K>& valid0, | 
					
						
							|  |  |  |                                       RayK<K>& ray, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                       const unsigned int geomID, | 
					
						
							|  |  |  |                                       const unsigned int primID) | 
					
						
							|  |  |  |         : valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         vbool<K> valid = valid_i; | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         valid &= (geometry->mask & ray.mask) != 0; | 
					
						
							|  |  |  |         if (unlikely(none(valid))) return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* occlusion filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             vfloat<K> u, v, t; | 
					
						
							|  |  |  |             Vec3vf<K> Ng; | 
					
						
							|  |  |  |             std::tie(u,v,t,Ng) = hit(); | 
					
						
							|  |  |  |             HitK<K> h(context->user,geomID,primID,u,v,Ng); | 
					
						
							|  |  |  |             const vfloat<K> old_t = ray.tfar; | 
					
						
							|  |  |  |             ray.tfar = select(valid,t,ray.tfar); | 
					
						
							|  |  |  |             valid = runOcclusionFilter(valid,geometry,ray,context,h); | 
					
						
							|  |  |  |             ray.tfar = select(valid,ray.tfar,old_t); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update occlusion */ | 
					
						
							|  |  |  |         valid0 = valid0 & !valid; | 
					
						
							|  |  |  |         return valid; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |     template<int M, int K, bool filter> | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |     struct Intersect1KEpilogM | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHitK<K>& ray; | 
					
						
							|  |  |  |       size_t k; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const vuint<M>& geomIDs; | 
					
						
							|  |  |  |       const vuint<M>& primIDs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k, | 
					
						
							|  |  |  |                                        IntersectContext* context, | 
					
						
							|  |  |  |                                        const vuint<M>& geomIDs, | 
					
						
							|  |  |  |                                        const vuint<M>& primIDs) | 
					
						
							|  |  |  |         : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         vbool<M> valid = valid_i; | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         hit.finalize(); | 
					
						
							|  |  |  |         size_t i = select_min(valid,hit.vt); | 
					
						
							|  |  |  |         assert(i<M); | 
					
						
							|  |  |  |         unsigned int geomID = geomIDs[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         bool foundhit = false; | 
					
						
							|  |  |  |         goto entry; | 
					
						
							|  |  |  |         while (true) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (unlikely(none(valid))) return foundhit; | 
					
						
							|  |  |  |           i = select_min(valid,hit.vt); | 
					
						
							|  |  |  |           assert(i<M); | 
					
						
							|  |  |  |           geomID = geomIDs[i]; | 
					
						
							|  |  |  |         entry: | 
					
						
							|  |  |  |           Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |           /* goto next hit if mask test fails */ | 
					
						
							|  |  |  |           if ((geometry->mask & ray.mask[k]) == 0) { | 
					
						
							|  |  |  |             clear(valid,i); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION) 
 | 
					
						
							|  |  |  |           /* call intersection filter function */ | 
					
						
							|  |  |  |           if (filter) { | 
					
						
							|  |  |  |             if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { | 
					
						
							|  |  |  |               assert(i<M); | 
					
						
							|  |  |  |               const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |               HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |               const float old_t = ray.tfar[k]; | 
					
						
							|  |  |  |               ray.tfar[k] = hit.t(i); | 
					
						
							|  |  |  |               const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h)); | 
					
						
							|  |  |  |               if (!found) ray.tfar[k] = old_t; | 
					
						
							|  |  |  |               foundhit = foundhit | found; | 
					
						
							|  |  |  |               clear(valid,i); | 
					
						
							|  |  |  |               valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
 | 
					
						
							|  |  |  |               continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         assert(i<M); | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |         ray.tfar[k] = hit.t(i); | 
					
						
							|  |  |  |         ray.Ng.x[k] = hit.vNg.x[i]; | 
					
						
							|  |  |  |         ray.Ng.y[k] = hit.vNg.y[i]; | 
					
						
							|  |  |  |         ray.Ng.z[k] = hit.vNg.z[i]; | 
					
						
							|  |  |  |         ray.u[k] = uv.x; | 
					
						
							|  |  |  |         ray.v[k] = uv.y; | 
					
						
							|  |  |  |         ray.primID[k] = primIDs[i]; | 
					
						
							|  |  |  |         ray.geomID[k] = geomID; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |     template<int M, int K, bool filter> | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |     struct Occluded1KEpilogM | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayK<K>& ray; | 
					
						
							|  |  |  |       size_t k; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const vuint<M>& geomIDs; | 
					
						
							|  |  |  |       const vuint<M>& primIDs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k, | 
					
						
							|  |  |  |                                       IntersectContext* context, | 
					
						
							|  |  |  |                                       const vuint<M>& geomIDs, | 
					
						
							|  |  |  |                                       const vuint<M>& primIDs) | 
					
						
							|  |  |  |         : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         if (unlikely(filter)) | 
					
						
							|  |  |  |           hit.finalize(); /* called only once */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         vbool<M> valid = valid_i; | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         size_t m=movemask(valid); | 
					
						
							|  |  |  |         goto entry; | 
					
						
							|  |  |  |         while (true) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (unlikely(m == 0)) return false; | 
					
						
							|  |  |  |         entry: | 
					
						
							|  |  |  |           size_t i=bsf(m); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const unsigned int geomID = geomIDs[i]; | 
					
						
							|  |  |  |           Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |           /* goto next hit if mask test fails */ | 
					
						
							|  |  |  |           if ((geometry->mask & ray.mask[k]) == 0) { | 
					
						
							|  |  |  |             m=btc(m,i); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |           /* execute occlusion filer */ | 
					
						
							|  |  |  |           if (filter) { | 
					
						
							|  |  |  |             if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |               const float old_t = ray.tfar[k]; | 
					
						
							|  |  |  |               ray.tfar[k] = hit.t(i); | 
					
						
							|  |  |  |               HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |               if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true; | 
					
						
							|  |  |  |               ray.tfar[k] = old_t; | 
					
						
							|  |  |  |               m=btc(m,i); | 
					
						
							|  |  |  |               continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int M, int K, bool filter> | 
					
						
							|  |  |  |     struct Intersect1KEpilogMU | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayHitK<K>& ray; | 
					
						
							|  |  |  |       size_t k; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k, | 
					
						
							|  |  |  |                                         IntersectContext* context, | 
					
						
							|  |  |  |                                         const unsigned int geomID, | 
					
						
							|  |  |  |                                         const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask[k]) == 0) | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* finalize hit calculation */ | 
					
						
							|  |  |  |         vbool<M> valid = valid_i; | 
					
						
							|  |  |  |         hit.finalize(); | 
					
						
							|  |  |  |         size_t i = select_min(valid,hit.vt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             bool foundhit = false; | 
					
						
							|  |  |  |             while (true) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |               const float old_t = ray.tfar[k]; | 
					
						
							|  |  |  |               ray.tfar[k] = hit.t(i); | 
					
						
							|  |  |  |               HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |               const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h)); | 
					
						
							|  |  |  |               if (!found) ray.tfar[k] = old_t; | 
					
						
							|  |  |  |               foundhit = foundhit | found; | 
					
						
							|  |  |  |               clear(valid,i); | 
					
						
							|  |  |  |               valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
 | 
					
						
							|  |  |  |               if (unlikely(none(valid))) break; | 
					
						
							|  |  |  |               i = select_min(valid,hit.vt); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return foundhit; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* update hit information */ | 
					
						
							|  |  |  |         const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |         const Vec3fa Ng = hit.Ng(i); | 
					
						
							|  |  |  |         ray.tfar[k] = hit.t(i); | 
					
						
							|  |  |  |         ray.Ng.x[k] = Ng.x; | 
					
						
							|  |  |  |         ray.Ng.y[k] = Ng.y; | 
					
						
							|  |  |  |         ray.Ng.z[k] = Ng.z; | 
					
						
							|  |  |  |         ray.u[k] = uv.x; | 
					
						
							|  |  |  |         ray.v[k] = uv.y; | 
					
						
							|  |  |  |         ray.primID[k] = primID; | 
					
						
							|  |  |  |         ray.geomID[k] = geomID; | 
					
						
							| 
									
										
										
										
											2021-05-20 12:49:33 +02:00
										 |  |  |         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k); | 
					
						
							| 
									
										
										
										
											2021-04-20 18:38:09 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template<int M, int K, bool filter> | 
					
						
							|  |  |  |     struct Occluded1KEpilogMU | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       RayK<K>& ray; | 
					
						
							|  |  |  |       size_t k; | 
					
						
							|  |  |  |       IntersectContext* context; | 
					
						
							|  |  |  |       const unsigned int geomID; | 
					
						
							|  |  |  |       const unsigned int primID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       __forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k, | 
					
						
							|  |  |  |                                        IntersectContext* context, | 
					
						
							|  |  |  |                                        const unsigned int geomID, | 
					
						
							|  |  |  |                                        const unsigned int primID) | 
					
						
							|  |  |  |         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       template<typename Hit> | 
					
						
							|  |  |  |       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         Scene* scene MAYBE_UNUSED = context->scene; | 
					
						
							|  |  |  |         Geometry* geometry MAYBE_UNUSED = scene->get(geomID); | 
					
						
							|  |  |  | #if defined(EMBREE_RAY_MASK)
 | 
					
						
							|  |  |  |         /* ray mask test */ | 
					
						
							|  |  |  |         if ((geometry->mask & ray.mask[k]) == 0) | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* intersection filter test */ | 
					
						
							|  |  |  | #if defined(EMBREE_FILTER_FUNCTION)
 | 
					
						
							|  |  |  |         if (filter) { | 
					
						
							|  |  |  |           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             hit.finalize(); | 
					
						
							|  |  |  |             for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               const Vec2f uv = hit.uv(i); | 
					
						
							|  |  |  |               const float old_t = ray.tfar[k]; | 
					
						
							|  |  |  |               ray.tfar[k] = hit.t(i); | 
					
						
							|  |  |  |               HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i)); | 
					
						
							|  |  |  |               if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true; | 
					
						
							|  |  |  |               ray.tfar[k] = old_t; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |