Path: blob/master/thirdparty/embree/kernels/geometry/intersector_epilog.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "../common/ray.h"6#include "../common/context.h"7#include "filter.h"89namespace embree10{11namespace isa12{13template<int M>14struct UVIdentity {15__forceinline void operator() (vfloat<M>& u, vfloat<M>& v, Vec3vf<M>& Ng) const {}16};171819template<bool filter>20struct Intersect1Epilog121{22RayHit& ray;23RayQueryContext* context;24const unsigned int geomID;25const unsigned int primID;2627__forceinline Intersect1Epilog1(RayHit& ray,28RayQueryContext* context,29const unsigned int geomID,30const unsigned int primID)31: ray(ray), context(context), geomID(geomID), primID(primID) {}3233template<typename Hit>34__forceinline bool operator() (Hit& hit) const35{36/* ray mask test */37Scene* scene MAYBE_UNUSED = context->scene;38Geometry* geometry MAYBE_UNUSED = scene->get(geomID);39#if defined(EMBREE_RAY_MASK)40if ((geometry->mask & ray.mask) == 0) return false;41#endif42hit.finalize();4344/* intersection filter test */45#if defined(EMBREE_FILTER_FUNCTION)46if (filter) {47if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {48HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);49const float old_t = ray.tfar;50ray.tfar = hit.t;51bool found = runIntersectionFilter1(geometry,ray,context,h);52if (!found) ray.tfar = old_t;53return found;54}55}56#endif5758/* update hit information */59ray.tfar = hit.t;60ray.Ng = hit.Ng;61ray.u = hit.u;62ray.v = hit.v;63ray.primID = primID;64ray.geomID = geomID;65instance_id_stack::copy_UU(context->user->instID, ray.instID);66#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)67instance_id_stack::copy_UU(context->user->instPrimID, ray.instPrimID);68#endif69return true;70}71};7273template<bool filter>74struct Occluded1Epilog175{76Ray& ray;77RayQueryContext* context;78const unsigned int geomID;79const unsigned int primID;8081__forceinline Occluded1Epilog1(Ray& ray,82RayQueryContext* context,83const unsigned int geomID,84const unsigned int primID)85: ray(ray), context(context), geomID(geomID), primID(primID) {}8687template<typename Hit>88__forceinline bool operator() (Hit& hit) const89{90/* ray mask test */91Scene* scene MAYBE_UNUSED = context->scene;92Geometry* geometry MAYBE_UNUSED = scene->get(geomID);939495#if defined(EMBREE_RAY_MASK)96if ((geometry->mask & ray.mask) == 0) return false;97#endif98hit.finalize();99100/* intersection filter test */101#if defined(EMBREE_FILTER_FUNCTION)102if (filter) {103if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {104HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);105const float old_t = ray.tfar;106ray.tfar = hit.t;107const bool found = runOcclusionFilter1(geometry,ray,context,h);108if (!found) ray.tfar = old_t;109return found;110}111}112#endif113return true;114}115};116117template<int K, bool filter>118struct Intersect1KEpilog1119{120RayHitK<K>& ray;121size_t k;122RayQueryContext* context;123const unsigned int geomID;124const unsigned int primID;125126__forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k,127RayQueryContext* context,128const unsigned int geomID,129const unsigned int primID)130: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}131132template<typename Hit>133__forceinline bool operator() (Hit& hit) const134{135/* ray mask test */136Scene* scene MAYBE_UNUSED = context->scene;137Geometry* geometry MAYBE_UNUSED = scene->get(geomID);138#if defined(EMBREE_RAY_MASK)139if ((geometry->mask & ray.mask[k]) == 0)140return false;141#endif142hit.finalize();143144/* intersection filter test */145#if defined(EMBREE_FILTER_FUNCTION)146if (filter) {147if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {148HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);149const float old_t = ray.tfar[k];150ray.tfar[k] = hit.t;151const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));152if (!found) ray.tfar[k] = old_t;153return found;154}155}156#endif157158/* update hit information */159ray.tfar[k] = hit.t;160ray.Ng.x[k] = hit.Ng.x;161ray.Ng.y[k] = hit.Ng.y;162ray.Ng.z[k] = hit.Ng.z;163ray.u[k] = hit.u;164ray.v[k] = hit.v;165ray.primID[k] = primID;166ray.geomID[k] = geomID;167instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);168#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)169instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, k);170#endif171return true;172}173};174175template<int K, bool filter>176struct Occluded1KEpilog1177{178RayK<K>& ray;179size_t k;180RayQueryContext* context;181const unsigned int geomID;182const unsigned int primID;183184__forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k,185RayQueryContext* context,186const unsigned int geomID,187const unsigned int primID)188: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}189190template<typename Hit>191__forceinline bool operator() (Hit& hit) const192{193/* ray mask test */194Scene* scene MAYBE_UNUSED = context->scene;195Geometry* geometry MAYBE_UNUSED = scene->get(geomID);196#if defined(EMBREE_RAY_MASK)197if ((geometry->mask & ray.mask[k]) == 0)198return false;199#endif200201/* intersection filter test */202#if defined(EMBREE_FILTER_FUNCTION)203if (filter) {204if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {205hit.finalize();206HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);207const float old_t = ray.tfar[k];208ray.tfar[k] = hit.t;209const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h));210if (!found) ray.tfar[k] = old_t;211return found;212}213}214#endif215return true;216}217};218219template<int M, bool filter>220struct Intersect1EpilogM221{222RayHit& ray;223RayQueryContext* context;224const vuint<M>& geomIDs;225const vuint<M>& primIDs;226227__forceinline Intersect1EpilogM(RayHit& ray,228RayQueryContext* context,229const vuint<M>& geomIDs,230const vuint<M>& primIDs)231: ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}232233template<typename Hit>234__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const235{236Scene* scene MAYBE_UNUSED = context->scene;237vbool<M> valid = valid_i;238hit.finalize();239size_t i = select_min(valid,hit.vt);240unsigned int geomID = geomIDs[i];241242/* intersection filter test */243#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)244bool foundhit = false;245goto entry;246while (true)247{248if (unlikely(none(valid))) return foundhit;249i = select_min(valid,hit.vt);250251geomID = geomIDs[i];252entry:253Geometry* geometry MAYBE_UNUSED = scene->get(geomID);254255#if defined(EMBREE_RAY_MASK)256/* goto next hit if mask test fails */257if ((geometry->mask & ray.mask) == 0) {258clear(valid,i);259continue;260}261#endif262263#if defined(EMBREE_FILTER_FUNCTION)264/* call intersection filter function */265if (filter) {266if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {267const Vec2f uv = hit.uv(i);268HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));269const float old_t = ray.tfar;270ray.tfar = hit.t(i);271const bool found = runIntersectionFilter1(geometry,ray,context,h);272if (!found) ray.tfar = old_t;273foundhit |= found;274clear(valid,i);275valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value276continue;277}278}279#endif280break;281}282#endif283284/* update hit information */285const Vec2f uv = hit.uv(i);286ray.tfar = hit.vt[i];287ray.Ng.x = hit.vNg.x[i];288ray.Ng.y = hit.vNg.y[i];289ray.Ng.z = hit.vNg.z[i];290ray.u = uv.x;291ray.v = uv.y;292ray.primID = primIDs[i];293ray.geomID = geomID;294instance_id_stack::copy_UU(context->user->instID, ray.instID);295#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)296instance_id_stack::copy_UU(context->user->instPrimID, ray.instPrimID);297#endif298return true;299300}301};302303template<int M, bool filter>304struct Occluded1EpilogM305{306Ray& ray;307RayQueryContext* context;308const vuint<M>& geomIDs;309const vuint<M>& primIDs;310311__forceinline Occluded1EpilogM(Ray& ray,312RayQueryContext* context,313const vuint<M>& geomIDs,314const vuint<M>& primIDs)315: ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}316317template<typename Hit>318__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const319{320Scene* scene MAYBE_UNUSED = context->scene;321/* intersection filter test */322#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)323if (unlikely(filter))324hit.finalize(); /* called only once */325326vbool<M> valid = valid_i;327size_t m=movemask(valid);328goto entry;329while (true)330{331if (unlikely(m == 0)) return false;332entry:333size_t i=bsf(m);334335const unsigned int geomID = geomIDs[i];336Geometry* geometry MAYBE_UNUSED = scene->get(geomID);337338#if defined(EMBREE_RAY_MASK)339/* goto next hit if mask test fails */340if ((geometry->mask & ray.mask) == 0) {341m=btc(m,i);342continue;343}344#endif345346#if defined(EMBREE_FILTER_FUNCTION)347/* if we have no filter then the test passed */348if (filter) {349if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))350{351const Vec2f uv = hit.uv(i);352HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));353const float old_t = ray.tfar;354ray.tfar = hit.t(i);355if (runOcclusionFilter1(geometry,ray,context,h)) return true;356ray.tfar = old_t;357m=btc(m,i);358continue;359}360}361#endif362break;363}364#endif365366return true;367}368};369370template<int M, bool filter>371struct Intersect1EpilogMU372{373RayHit& ray;374RayQueryContext* context;375const unsigned int geomID;376const unsigned int primID;377378__forceinline Intersect1EpilogMU(RayHit& ray,379RayQueryContext* context,380const unsigned int geomID,381const unsigned int primID)382: ray(ray), context(context), geomID(geomID), primID(primID) {}383384template<typename Hit>385__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const386{387/* ray mask test */388Scene* scene MAYBE_UNUSED = context->scene;389Geometry* geometry MAYBE_UNUSED = scene->get(geomID);390#if defined(EMBREE_RAY_MASK)391if ((geometry->mask & ray.mask) == 0) return false;392#endif393394vbool<M> valid = valid_i;395hit.finalize();396397size_t i = select_min(valid,hit.vt);398399/* intersection filter test */400#if defined(EMBREE_FILTER_FUNCTION)401if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))402{403bool foundhit = false;404while (true)405{406/* call intersection filter function */407Vec2f uv = hit.uv(i);408const float old_t = ray.tfar;409ray.tfar = hit.t(i);410HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));411const bool found = runIntersectionFilter1(geometry,ray,context,h);412if (!found) ray.tfar = old_t;413foundhit |= found;414clear(valid,i);415valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value416if (unlikely(none(valid))) break;417i = select_min(valid,hit.vt);418}419return foundhit;420}421#endif422423/* update hit information */424const Vec2f uv = hit.uv(i);425const Vec3fa Ng = hit.Ng(i);426ray.tfar = hit.t(i);427ray.Ng.x = Ng.x;428ray.Ng.y = Ng.y;429ray.Ng.z = Ng.z;430ray.u = uv.x;431ray.v = uv.y;432ray.primID = primID;433ray.geomID = geomID;434instance_id_stack::copy_UU(context->user->instID, ray.instID);435#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)436instance_id_stack::copy_UU(context->user->instPrimID, ray.instPrimID);437#endif438return true;439}440};441442template<int M, bool filter>443struct Occluded1EpilogMU444{445Ray& ray;446RayQueryContext* context;447const unsigned int geomID;448const unsigned int primID;449450__forceinline Occluded1EpilogMU(Ray& ray,451RayQueryContext* context,452const unsigned int geomID,453const unsigned int primID)454: ray(ray), context(context), geomID(geomID), primID(primID) {}455456template<typename Hit>457__forceinline bool operator() (const vbool<M>& valid, Hit& hit) const458{459/* ray mask test */460Scene* scene MAYBE_UNUSED = context->scene;461Geometry* geometry MAYBE_UNUSED = scene->get(geomID);462#if defined(EMBREE_RAY_MASK)463if ((geometry->mask & ray.mask) == 0) return false;464#endif465466/* intersection filter test */467#if defined(EMBREE_FILTER_FUNCTION)468if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))469{470hit.finalize();471for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))472{473const Vec2f uv = hit.uv(i);474const float old_t = ray.tfar;475ray.tfar = hit.t(i);476HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));477if (runOcclusionFilter1(geometry,ray,context,h)) return true;478ray.tfar = old_t;479}480return false;481}482#endif483return true;484}485};486487template<int M, int K, bool filter>488struct IntersectKEpilogM489{490RayHitK<K>& ray;491RayQueryContext* context;492const vuint<M>& geomIDs;493const vuint<M>& primIDs;494const size_t i;495496__forceinline IntersectKEpilogM(RayHitK<K>& ray,497RayQueryContext* context,498const vuint<M>& geomIDs,499const vuint<M>& primIDs,500size_t i)501: ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}502503template<typename Hit>504__forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const505{506Scene* scene MAYBE_UNUSED = context->scene;507508vfloat<K> u, v, t;509Vec3vf<K> Ng;510vbool<K> valid = valid_i;511512std::tie(u,v,t,Ng) = hit();513514const unsigned int geomID = geomIDs[i];515const unsigned int primID = primIDs[i];516Geometry* geometry MAYBE_UNUSED = scene->get(geomID);517518/* ray masking test */519#if defined(EMBREE_RAY_MASK)520valid &= (geometry->mask & ray.mask) != 0;521if (unlikely(none(valid))) return false;522#endif523524/* occlusion filter test */525#if defined(EMBREE_FILTER_FUNCTION)526if (filter) {527if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {528HitK<K> h(context->user,geomID,primID,u,v,Ng);529const vfloat<K> old_t = ray.tfar;530ray.tfar = select(valid,t,ray.tfar);531const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);532ray.tfar = select(m_accept,ray.tfar,old_t);533return m_accept;534}535}536#endif537538/* update hit information */539vfloat<K>::store(valid,&ray.tfar,t);540vfloat<K>::store(valid,&ray.Ng.x,Ng.x);541vfloat<K>::store(valid,&ray.Ng.y,Ng.y);542vfloat<K>::store(valid,&ray.Ng.z,Ng.z);543vfloat<K>::store(valid,&ray.u,u);544vfloat<K>::store(valid,&ray.v,v);545vuint<K>::store(valid,&ray.primID,primID);546vuint<K>::store(valid,&ray.geomID,geomID);547instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);548#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)549instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, valid);550#endif551return valid;552}553};554555template<int M, int K, bool filter>556struct OccludedKEpilogM557{558vbool<K>& valid0;559RayK<K>& ray;560RayQueryContext* context;561const vuint<M>& geomIDs;562const vuint<M>& primIDs;563const size_t i;564565__forceinline OccludedKEpilogM(vbool<K>& valid0,566RayK<K>& ray,567RayQueryContext* context,568const vuint<M>& geomIDs,569const vuint<M>& primIDs,570size_t i)571: valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}572573template<typename Hit>574__forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const575{576vbool<K> valid = valid_i;577578/* ray masking test */579Scene* scene MAYBE_UNUSED = context->scene;580const unsigned int geomID MAYBE_UNUSED = geomIDs[i];581const unsigned int primID MAYBE_UNUSED = primIDs[i];582Geometry* geometry MAYBE_UNUSED = scene->get(geomID);583#if defined(EMBREE_RAY_MASK)584valid &= (geometry->mask & ray.mask) != 0;585if (unlikely(none(valid))) return valid;586#endif587588/* intersection filter test */589#if defined(EMBREE_FILTER_FUNCTION)590if (filter) {591if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))592{593vfloat<K> u, v, t;594Vec3vf<K> Ng;595std::tie(u,v,t,Ng) = hit();596HitK<K> h(context->user,geomID,primID,u,v,Ng);597const vfloat<K> old_t = ray.tfar;598ray.tfar = select(valid,t,ray.tfar);599valid = runOcclusionFilter(valid,geometry,ray,context,h);600ray.tfar = select(valid,ray.tfar,old_t);601}602}603#endif604605/* update occlusion */606valid0 = valid0 & !valid;607return valid;608}609};610611template<int M, int K, bool filter>612struct IntersectKEpilogMU613{614RayHitK<K>& ray;615RayQueryContext* context;616const unsigned int geomID;617const unsigned int primID;618619__forceinline IntersectKEpilogMU(RayHitK<K>& ray,620RayQueryContext* context,621const unsigned int geomID,622const unsigned int primID)623: ray(ray), context(context), geomID(geomID), primID(primID) {}624625template<typename Hit>626__forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const627{628vbool<K> valid = valid_org;629vfloat<K> u, v, t;630Vec3vf<K> Ng;631std::tie(u,v,t,Ng) = hit();632633Scene* scene MAYBE_UNUSED = context->scene;634Geometry* geometry MAYBE_UNUSED = scene->get(geomID);635636/* ray masking test */637#if defined(EMBREE_RAY_MASK)638valid &= (geometry->mask & ray.mask) != 0;639if (unlikely(none(valid))) return false;640#endif641642/* intersection filter test */643#if defined(EMBREE_FILTER_FUNCTION)644if (filter) {645if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {646HitK<K> h(context->user,geomID,primID,u,v,Ng);647const vfloat<K> old_t = ray.tfar;648ray.tfar = select(valid,t,ray.tfar);649const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);650ray.tfar = select(m_accept,ray.tfar,old_t);651return m_accept;652}653}654#endif655656/* update hit information */657vfloat<K>::store(valid,&ray.tfar,t);658vfloat<K>::store(valid,&ray.Ng.x,Ng.x);659vfloat<K>::store(valid,&ray.Ng.y,Ng.y);660vfloat<K>::store(valid,&ray.Ng.z,Ng.z);661vfloat<K>::store(valid,&ray.u,u);662vfloat<K>::store(valid,&ray.v,v);663vuint<K>::store(valid,&ray.primID,primID);664vuint<K>::store(valid,&ray.geomID,geomID);665instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);666#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)667instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, valid);668#endif669return valid;670}671};672673template<int M, int K, bool filter>674struct OccludedKEpilogMU675{676vbool<K>& valid0;677RayK<K>& ray;678RayQueryContext* context;679const unsigned int geomID;680const unsigned int primID;681682__forceinline OccludedKEpilogMU(vbool<K>& valid0,683RayK<K>& ray,684RayQueryContext* context,685const unsigned int geomID,686const unsigned int primID)687: valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {}688689template<typename Hit>690__forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const691{692vbool<K> valid = valid_i;693Scene* scene MAYBE_UNUSED = context->scene;694Geometry* geometry MAYBE_UNUSED = scene->get(geomID);695696#if defined(EMBREE_RAY_MASK)697valid &= (geometry->mask & ray.mask) != 0;698if (unlikely(none(valid))) return false;699#endif700701/* occlusion filter test */702#if defined(EMBREE_FILTER_FUNCTION)703if (filter) {704if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))705{706vfloat<K> u, v, t;707Vec3vf<K> Ng;708std::tie(u,v,t,Ng) = hit();709HitK<K> h(context->user,geomID,primID,u,v,Ng);710const vfloat<K> old_t = ray.tfar;711ray.tfar = select(valid,t,ray.tfar);712valid = runOcclusionFilter(valid,geometry,ray,context,h);713ray.tfar = select(valid,ray.tfar,old_t);714}715}716#endif717718/* update occlusion */719valid0 = valid0 & !valid;720return valid;721}722};723724template<int M, int K, bool filter>725struct Intersect1KEpilogM726{727RayHitK<K>& ray;728size_t k;729RayQueryContext* context;730const vuint<M>& geomIDs;731const vuint<M>& primIDs;732733__forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k,734RayQueryContext* context,735const vuint<M>& geomIDs,736const vuint<M>& primIDs)737: ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}738739template<typename Hit>740__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const741{742Scene* scene MAYBE_UNUSED = context->scene;743vbool<M> valid = valid_i;744hit.finalize();745size_t i = select_min(valid,hit.vt);746assert(i<M);747unsigned int geomID = geomIDs[i];748749/* intersection filter test */750#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)751bool foundhit = false;752goto entry;753while (true)754{755if (unlikely(none(valid))) return foundhit;756i = select_min(valid,hit.vt);757assert(i<M);758geomID = geomIDs[i];759entry:760Geometry* geometry MAYBE_UNUSED = scene->get(geomID);761762#if defined(EMBREE_RAY_MASK)763/* goto next hit if mask test fails */764if ((geometry->mask & ray.mask[k]) == 0) {765clear(valid,i);766continue;767}768#endif769770#if defined(EMBREE_FILTER_FUNCTION)771/* call intersection filter function */772if (filter) {773if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {774assert(i<M);775const Vec2f uv = hit.uv(i);776HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));777const float old_t = ray.tfar[k];778ray.tfar[k] = hit.t(i);779const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));780if (!found) ray.tfar[k] = old_t;781foundhit = foundhit | found;782clear(valid,i);783valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value784continue;785}786}787#endif788break;789}790#endif791assert(i<M);792/* update hit information */793const Vec2f uv = hit.uv(i);794ray.tfar[k] = hit.t(i);795ray.Ng.x[k] = hit.vNg.x[i];796ray.Ng.y[k] = hit.vNg.y[i];797ray.Ng.z[k] = hit.vNg.z[i];798ray.u[k] = uv.x;799ray.v[k] = uv.y;800ray.primID[k] = primIDs[i];801ray.geomID[k] = geomID;802instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);803#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)804instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, k);805#endif806return true;807}808};809810template<int M, int K, bool filter>811struct Occluded1KEpilogM812{813RayK<K>& ray;814size_t k;815RayQueryContext* context;816const vuint<M>& geomIDs;817const vuint<M>& primIDs;818819__forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k,820RayQueryContext* context,821const vuint<M>& geomIDs,822const vuint<M>& primIDs)823: ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}824825template<typename Hit>826__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const827{828Scene* scene MAYBE_UNUSED = context->scene;829830/* intersection filter test */831#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)832if (unlikely(filter))833hit.finalize(); /* called only once */834835vbool<M> valid = valid_i;836size_t m=movemask(valid);837goto entry;838while (true)839{840if (unlikely(m == 0)) return false;841entry:842size_t i=bsf(m);843844const unsigned int geomID = geomIDs[i];845Geometry* geometry MAYBE_UNUSED = scene->get(geomID);846847#if defined(EMBREE_RAY_MASK)848/* goto next hit if mask test fails */849if ((geometry->mask & ray.mask[k]) == 0) {850m=btc(m,i);851continue;852}853#endif854855#if defined(EMBREE_FILTER_FUNCTION)856/* execute occlusion filer */857if (filter) {858if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))859{860const Vec2f uv = hit.uv(i);861const float old_t = ray.tfar[k];862ray.tfar[k] = hit.t(i);863HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));864if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;865ray.tfar[k] = old_t;866m=btc(m,i);867continue;868}869}870#endif871break;872}873#endif874return true;875}876};877878template<int M, int K, bool filter>879struct Intersect1KEpilogMU880{881RayHitK<K>& ray;882size_t k;883RayQueryContext* context;884const unsigned int geomID;885const unsigned int primID;886887__forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k,888RayQueryContext* context,889const unsigned int geomID,890const unsigned int primID)891: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}892893template<typename Hit>894__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const895{896Scene* scene MAYBE_UNUSED = context->scene;897Geometry* geometry MAYBE_UNUSED = scene->get(geomID);898#if defined(EMBREE_RAY_MASK)899/* ray mask test */900if ((geometry->mask & ray.mask[k]) == 0)901return false;902#endif903904/* finalize hit calculation */905vbool<M> valid = valid_i;906hit.finalize();907size_t i = select_min(valid,hit.vt);908909/* intersection filter test */910#if defined(EMBREE_FILTER_FUNCTION)911if (filter) {912if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))913{914bool foundhit = false;915while (true)916{917const Vec2f uv = hit.uv(i);918const float old_t = ray.tfar[k];919ray.tfar[k] = hit.t(i);920HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));921const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));922if (!found) ray.tfar[k] = old_t;923foundhit = foundhit | found;924clear(valid,i);925valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value926if (unlikely(none(valid))) break;927i = select_min(valid,hit.vt);928}929return foundhit;930}931}932#endif933934/* update hit information */935const Vec2f uv = hit.uv(i);936const Vec3fa Ng = hit.Ng(i);937ray.tfar[k] = hit.t(i);938ray.Ng.x[k] = Ng.x;939ray.Ng.y[k] = Ng.y;940ray.Ng.z[k] = Ng.z;941ray.u[k] = uv.x;942ray.v[k] = uv.y;943ray.primID[k] = primID;944ray.geomID[k] = geomID;945instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);946#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)947instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, k);948#endif949return true;950}951};952953template<int M, int K, bool filter>954struct Occluded1KEpilogMU955{956RayK<K>& ray;957size_t k;958RayQueryContext* context;959const unsigned int geomID;960const unsigned int primID;961962__forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k,963RayQueryContext* context,964const unsigned int geomID,965const unsigned int primID)966: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}967968template<typename Hit>969__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const970{971Scene* scene MAYBE_UNUSED = context->scene;972Geometry* geometry MAYBE_UNUSED = scene->get(geomID);973#if defined(EMBREE_RAY_MASK)974/* ray mask test */975if ((geometry->mask & ray.mask[k]) == 0)976return false;977#endif978979/* intersection filter test */980#if defined(EMBREE_FILTER_FUNCTION)981if (filter) {982if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))983{984hit.finalize();985for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))986{987const Vec2f uv = hit.uv(i);988const float old_t = ray.tfar[k];989ray.tfar[k] = hit.t(i);990HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));991if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;992ray.tfar[k] = old_t;993}994return false;995}996}997#endif998return true;999}1000};1001}1002}100310041005