Path: blob/master/thirdparty/embree/kernels/geometry/curveNi_intersector.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "curveNi.h"67#include "roundline_intersector.h"8#include "coneline_intersector.h"9#include "curve_intersector_ribbon.h"10#include "curve_intersector_oriented.h"11#include "curve_intersector_sweep.h"1213namespace embree14{15namespace isa16{17template<int M>18struct CurveNiIntersector119{20typedef CurveNi<M> Primitive;21typedef Vec3vf<M> Vec3vfM;22typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;23typedef CurvePrecalculations1 Precalculations;2425static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o)26{27const size_t N = prim.N;28#if defined(EMBREE_SYCL_SUPPORT) && defined(__SYCL_DEVICE_ONLY__)29const Vec3fa offset = *prim.offset(N);30const float scale = *prim.scale(N);31#else32const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));33const Vec3fa offset = Vec3fa(offset_scale);34const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));35#endif36const Vec3fa org1 = (ray.org-offset)*scale;37const Vec3fa dir1 = ray.dir*scale;3839const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),40vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),41vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));4243const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));44const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));45const Vec3vfM rcp_dir2 = rcp_safe(dir2);4647const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);48const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);49const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);50const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);51const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);52const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);5354const vfloat<M> round_up (1.0f+3.0f*float(ulp));55const vfloat<M> round_down(1.0f-3.0f*float(ulp));56const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()));57const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar));58tNear_o = tNear;59return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);60}6162template<typename Intersector, typename Epilog>63static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, RayQueryContext* context, const Primitive& prim)64{65vfloat<M> tNear;66vbool<M> valid = intersect(ray,prim,tNear);6768const size_t N = prim.N;69size_t mask = movemask(valid);70while (mask)71{72const size_t i = bscf(mask);73STAT3(normal.trav_prims,1,1,1);74const unsigned int geomID = prim.geomID(N);75const unsigned int primID = prim.primID(N)[i];76const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);77Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));7879size_t mask1 = mask;80const size_t i1 = bscf(mask1);81if (mask) {82const unsigned int primID1 = prim.primID(N)[i1];83geom->prefetchL1_vertices(geom->curve(primID1));84if (mask1) {85const size_t i2 = bsf(mask1);86const unsigned int primID2 = prim.primID(N)[i2];87geom->prefetchL2_vertices(geom->curve(primID2));88}89}9091Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID));92mask &= movemask(tNear <= vfloat<M>(ray.tfar));93}94}9596template<typename Intersector, typename Epilog>97static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, RayQueryContext* context, const Primitive& prim)98{99vfloat<M> tNear;100vbool<M> valid = intersect(ray,prim,tNear);101102const size_t N = prim.N;103size_t mask = movemask(valid);104while (mask)105{106const size_t i = bscf(mask);107STAT3(shadow.trav_prims,1,1,1);108const unsigned int geomID = prim.geomID(N);109const unsigned int primID = prim.primID(N)[i];110const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);111Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));112113size_t mask1 = mask;114const size_t i1 = bscf(mask1);115if (mask) {116const unsigned int primID1 = prim.primID(N)[i1];117geom->prefetchL1_vertices(geom->curve(primID1));118if (mask1) {119const size_t i2 = bsf(mask1);120const unsigned int primID2 = prim.primID(N)[i2];121geom->prefetchL2_vertices(geom->curve(primID2));122}123}124125if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)))126return true;127128mask &= movemask(tNear <= vfloat<M>(ray.tfar));129}130return false;131}132133template<typename Intersector, typename Epilog>134static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, RayQueryContext* context, const Primitive& prim)135{136vfloat<M> tNear;137vbool<M> valid = intersect(ray,prim,tNear);138139const size_t N = prim.N;140size_t mask = movemask(valid);141while (mask)142{143const size_t i = bscf(mask);144STAT3(normal.trav_prims,1,1,1);145const unsigned int geomID = prim.geomID(N);146const unsigned int primID = prim.primID(N)[i];147const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);148149unsigned int vertexID = geom->curve(primID);150Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);151152size_t mask1 = mask;153const size_t i1 = bscf(mask1);154if (mask) {155const unsigned int primID1 = prim.primID(N)[i1];156geom->prefetchL1_vertices(geom->curve(primID1));157if (mask1) {158const size_t i2 = bsf(mask1);159const unsigned int primID2 = prim.primID(N)[i2];160geom->prefetchL2_vertices(geom->curve(primID2));161}162}163164Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID));165mask &= movemask(tNear <= vfloat<M>(ray.tfar));166}167}168169template<typename Intersector, typename Epilog>170static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, RayQueryContext* context, const Primitive& prim)171{172vfloat<M> tNear;173vbool<M> valid = intersect(ray,prim,tNear);174175const size_t N = prim.N;176size_t mask = movemask(valid);177while (mask)178{179const size_t i = bscf(mask);180STAT3(shadow.trav_prims,1,1,1);181const unsigned int geomID = prim.geomID(N);182const unsigned int primID = prim.primID(N)[i];183const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);184185unsigned int vertexID = geom->curve(primID);186Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);187188size_t mask1 = mask;189const size_t i1 = bscf(mask1);190if (mask) {191const unsigned int primID1 = prim.primID(N)[i1];192geom->prefetchL1_vertices(geom->curve(primID1));193if (mask1) {194const size_t i2 = bsf(mask1);195const unsigned int primID2 = prim.primID(N)[i2];196geom->prefetchL2_vertices(geom->curve(primID2));197}198}199200if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID)))201return true;202203mask &= movemask(tNear <= vfloat<M>(ray.tfar));204}205return false;206}207208template<typename Intersector, typename Epilog>209static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, RayQueryContext* context, const Primitive& prim)210{211vfloat<M> tNear;212vbool<M> valid = intersect(ray,prim,tNear);213214const size_t N = prim.N;215size_t mask = movemask(valid);216while (mask)217{218const size_t i = bscf(mask);219STAT3(normal.trav_prims,1,1,1);220const unsigned int geomID = prim.geomID(N);221const unsigned int primID = prim.primID(N)[i];222const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);223Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));224Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID));225mask &= movemask(tNear <= vfloat<M>(ray.tfar));226}227}228229template<typename Intersector, typename Epilog>230static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, RayQueryContext* context, const Primitive& prim)231{232vfloat<M> tNear;233vbool<M> valid = intersect(ray,prim,tNear);234235const size_t N = prim.N;236size_t mask = movemask(valid);237while (mask)238{239const size_t i = bscf(mask);240STAT3(shadow.trav_prims,1,1,1);241const unsigned int geomID = prim.geomID(N);242const unsigned int primID = prim.primID(N)[i];243const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);244Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));245if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)))246return true;247248mask &= movemask(tNear <= vfloat<M>(ray.tfar));249}250return false;251}252253template<typename Intersector, typename Epilog>254static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, RayQueryContext* context, const Primitive& prim)255{256vfloat<M> tNear;257vbool<M> valid = intersect(ray,prim,tNear);258259const size_t N = prim.N;260size_t mask = movemask(valid);261while (mask)262{263const size_t i = bscf(mask);264STAT3(normal.trav_prims,1,1,1);265const unsigned int geomID = prim.geomID(N);266const unsigned int primID = prim.primID(N)[i];267const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);268Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));269Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID));270mask &= movemask(tNear <= vfloat<M>(ray.tfar));271}272}273274template<typename Intersector, typename Epilog>275static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, RayQueryContext* context, const Primitive& prim)276{277vfloat<M> tNear;278vbool<M> valid = intersect(ray,prim,tNear);279280const size_t N = prim.N;281size_t mask = movemask(valid);282while (mask)283{284const size_t i = bscf(mask);285STAT3(shadow.trav_prims,1,1,1);286const unsigned int geomID = prim.geomID(N);287const unsigned int primID = prim.primID(N)[i];288const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);289Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));290if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID)))291return true;292293mask &= movemask(tNear <= vfloat<M>(ray.tfar));294}295return false;296}297};298299template<int M, int K>300struct CurveNiIntersectorK301{302typedef CurveNi<M> Primitive;303typedef Vec3vf<M> Vec3vfM;304typedef LinearSpace3<Vec3vfM>LinearSpace3vfM;305typedef CurvePrecalculationsK<K> Precalculations;306307static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o)308{309const size_t N = prim.N;310#if defined(EMBREE_SYCL_SUPPORT) && defined(__SYCL_DEVICE_ONLY__)311const Vec3fa offset = *prim.offset(N);312const float scale = *prim.scale(N);313#else314const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N));315const Vec3fa offset = Vec3fa(offset_scale);316const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(offset_scale));317#endif318const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);319const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);320const Vec3fa org1 = (ray_org-offset)*scale;321const Vec3fa dir1 = ray_dir*scale;322323const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)),324vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)),325vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N)));326327const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1));328const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1));329const Vec3vfM rcp_dir2 = rcp_safe(dir2);330331const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);332const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x);333const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);334const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y);335const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);336const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z);337338const vfloat<M> round_up (1.0f+3.0f*float(ulp));339const vfloat<M> round_down(1.0f-3.0f*float(ulp));340const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k]));341const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k]));342tNear_o = tNear;343return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar);344}345346template<typename Intersector, typename Epilog>347static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)348{349vfloat<M> tNear;350vbool<M> valid = intersect(ray,k,prim,tNear);351352const size_t N = prim.N;353size_t mask = movemask(valid);354while (mask)355{356const size_t i = bscf(mask);357STAT3(normal.trav_prims,1,1,1);358const unsigned int geomID = prim.geomID(N);359const unsigned int primID = prim.primID(N)[i];360const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);361Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));362363size_t mask1 = mask;364const size_t i1 = bscf(mask1);365if (mask) {366const unsigned int primID1 = prim.primID(N)[i1];367geom->prefetchL1_vertices(geom->curve(primID1));368if (mask1) {369const size_t i2 = bsf(mask1);370const unsigned int primID2 = prim.primID(N)[i2];371geom->prefetchL2_vertices(geom->curve(primID2));372}373}374375Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID));376mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));377}378}379380template<typename Intersector, typename Epilog>381static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)382{383vfloat<M> tNear;384vbool<M> valid = intersect(ray,k,prim,tNear);385386const size_t N = prim.N;387size_t mask = movemask(valid);388while (mask)389{390const size_t i = bscf(mask);391STAT3(shadow.trav_prims,1,1,1);392const unsigned int geomID = prim.geomID(N);393const unsigned int primID = prim.primID(N)[i];394const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);395Vec3ff a0,a1,a2,a3; geom->gather(a0,a1,a2,a3,geom->curve(primID));396397size_t mask1 = mask;398const size_t i1 = bscf(mask1);399if (mask) {400const unsigned int primID1 = prim.primID(N)[i1];401geom->prefetchL1_vertices(geom->curve(primID1));402if (mask1) {403const size_t i2 = bsf(mask1);404const unsigned int primID2 = prim.primID(N)[i2];405geom->prefetchL2_vertices(geom->curve(primID2));406}407}408409if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)))410return true;411412mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));413}414return false;415}416417template<typename Intersector, typename Epilog>418static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)419{420vfloat<M> tNear;421vbool<M> valid = intersect(ray,k,prim,tNear);422423const size_t N = prim.N;424size_t mask = movemask(valid);425while (mask)426{427const size_t i = bscf(mask);428STAT3(normal.trav_prims,1,1,1);429const unsigned int geomID = prim.geomID(N);430const unsigned int primID = prim.primID(N)[i];431const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);432433unsigned int vertexID = geom->curve(primID);434Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);435436size_t mask1 = mask;437const size_t i1 = bscf(mask1);438if (mask) {439const unsigned int primID1 = prim.primID(N)[i1];440geom->prefetchL1_vertices(geom->curve(primID1));441if (mask1) {442const size_t i2 = bsf(mask1);443const unsigned int primID2 = prim.primID(N)[i2];444geom->prefetchL2_vertices(geom->curve(primID2));445}446}447448Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID));449mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));450}451}452453template<typename Intersector, typename Epilog>454static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)455{456vfloat<M> tNear;457vbool<M> valid = intersect(ray,k,prim,tNear);458459const size_t N = prim.N;460size_t mask = movemask(valid);461while (mask)462{463const size_t i = bscf(mask);464STAT3(shadow.trav_prims,1,1,1);465const unsigned int geomID = prim.geomID(N);466const unsigned int primID = prim.primID(N)[i];467const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);468469unsigned int vertexID = geom->curve(primID);470Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(a0,a1,a2,a3,n0,n1,n2,n3,vertexID);471472size_t mask1 = mask;473const size_t i1 = bscf(mask1);474if (mask) {475const unsigned int primID1 = prim.primID(N)[i1];476geom->prefetchL1_vertices(geom->curve(primID1));477if (mask1) {478const size_t i2 = bsf(mask1);479const unsigned int primID2 = prim.primID(N)[i2];480geom->prefetchL2_vertices(geom->curve(primID2));481}482}483484if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID)))485return true;486487mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));488}489return false;490}491492template<typename Intersector, typename Epilog>493static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)494{495vfloat<M> tNear;496vbool<M> valid = intersect(ray,k,prim,tNear);497498const size_t N = prim.N;499size_t mask = movemask(valid);500while (mask)501{502const size_t i = bscf(mask);503STAT3(normal.trav_prims,1,1,1);504const unsigned int geomID = prim.geomID(N);505const unsigned int primID = prim.primID(N)[i];506const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);507Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));508Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID));509mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));510}511}512513template<typename Intersector, typename Epilog>514static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)515{516vfloat<M> tNear;517vbool<M> valid = intersect(ray,k,prim,tNear);518519const size_t N = prim.N;520size_t mask = movemask(valid);521while (mask)522{523const size_t i = bscf(mask);524STAT3(shadow.trav_prims,1,1,1);525const unsigned int geomID = prim.geomID(N);526const unsigned int primID = prim.primID(N)[i];527const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);528Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,geom->curve(primID));529if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)))530return true;531532mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));533}534return false;535}536537template<typename Intersector, typename Epilog>538static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)539{540vfloat<M> tNear;541vbool<M> valid = intersect(ray,k,prim,tNear);542543const size_t N = prim.N;544size_t mask = movemask(valid);545while (mask)546{547const size_t i = bscf(mask);548STAT3(normal.trav_prims,1,1,1);549const unsigned int geomID = prim.geomID(N);550const unsigned int primID = prim.primID(N)[i];551const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);552Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));553Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID));554mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));555}556}557558template<typename Intersector, typename Epilog>559static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, RayQueryContext* context, const Primitive& prim)560{561vfloat<M> tNear;562vbool<M> valid = intersect(ray,k,prim,tNear);563564const size_t N = prim.N;565size_t mask = movemask(valid);566while (mask)567{568const size_t i = bscf(mask);569STAT3(shadow.trav_prims,1,1,1);570const unsigned int geomID = prim.geomID(N);571const unsigned int primID = prim.primID(N)[i];572const CurveGeometry* geom = context->scene->get<CurveGeometry>(geomID);573Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,geom->curve(primID));574if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID)))575return true;576577mask &= movemask(tNear <= vfloat<M>(ray.tfar[k]));578}579return false;580}581};582583__forceinline void convert_to_bezier(const Geometry::GType gtype,584Vec3ff& v0, Vec3ff& v1, Vec3ff& v2, Vec3ff& v3,585Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3)586{587const Geometry::GType basis = (Geometry::GType)(gtype & Geometry::GTY_BASIS_MASK);588const Geometry::GType stype = (Geometry::GType)(gtype & Geometry::GTY_SUBTYPE_MASK);589590if (basis == Geometry::GTY_BASIS_BSPLINE) {591BezierCurveT<Vec3ff> bezier;592convert(BSplineCurveT<Vec3ff>(v0,v1,v2,v3),bezier);593v0 = bezier.v0; v1 = bezier.v1; v2 = bezier.v2; v3 = bezier.v3;594}595else if (basis == Geometry::GTY_BASIS_HERMITE) {596BezierCurveT<Vec3ff> bezier;597convert(HermiteCurveT<Vec3ff>(v0,v1,v2,v3),bezier);598v0 = bezier.v0; v1 = bezier.v1; v2 = bezier.v2; v3 = bezier.v3;599}600else if (basis == Geometry::GTY_BASIS_CATMULL_ROM) {601BezierCurveT<Vec3ff> bezier;602convert(CatmullRomCurveT<Vec3ff>(v0,v1,v2,v3),bezier);603v0 = bezier.v0; v1 = bezier.v1; v2 = bezier.v2; v3 = bezier.v3;604}605606if (stype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)607{608if (basis == Geometry::GTY_BASIS_BSPLINE) {609BezierCurveT<Vec3fa> bezier;610convert(BSplineCurveT<Vec3fa>(n0,n1,n2,n3),bezier);611n0 = bezier.v0; n1 = bezier.v1; n2 = bezier.v2; n3 = bezier.v3;612}613else if (basis == Geometry::GTY_BASIS_HERMITE) {614BezierCurveT<Vec3fa> bezier;615convert(HermiteCurveT<Vec3fa>(n0,n1,n2,n3),bezier);616n0 = bezier.v0; n1 = bezier.v1; n2 = bezier.v2; n3 = bezier.v3;617}618else if (basis == Geometry::GTY_BASIS_CATMULL_ROM) {619BezierCurveT<Vec3fa> bezier;620convert(CatmullRomCurveT<Vec3fa>(n0,n1,n2,n3),bezier);621n0 = bezier.v0; n1 = bezier.v1; n2 = bezier.v2; n3 = bezier.v3;622}623}624}625626__forceinline void convert_to_bezier(const Geometry::GType gtype, Vec3ff& v0, Vec3ff& v1, Vec3ff& v2, Vec3ff& v3)627{628const Geometry::GType basis = (Geometry::GType)(gtype & Geometry::GTY_BASIS_MASK);629630if (basis == Geometry::GTY_BASIS_BSPLINE) {631BezierCurveT<Vec3ff> bezier;632convert(BSplineCurveT<Vec3ff>(v0,v1,v2,v3),bezier);633v0 = bezier.v0; v1 = bezier.v1; v2 = bezier.v2; v3 = bezier.v3;634}635else if (basis == Geometry::GTY_BASIS_HERMITE) {636BezierCurveT<Vec3ff> bezier;637convert(HermiteCurveT<Vec3ff>(v0,v1,v2,v3),bezier);638v0 = bezier.v0; v1 = bezier.v1; v2 = bezier.v2; v3 = bezier.v3;639}640else if (basis == Geometry::GTY_BASIS_CATMULL_ROM) {641BezierCurveT<Vec3ff> bezier;642convert(CatmullRomCurveT<Vec3ff>(v0,v1,v2,v3),bezier);643v0 = bezier.v0; v1 = bezier.v1; v2 = bezier.v2; v3 = bezier.v3;644}645}646}647}648649650