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