1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "subgrid.h"
7#include "quad_intersector_moeller.h"
8#include "quad_intersector_pluecker.h"
9
10namespace embree
11{
12 namespace isa
13 {
14
15 template<int M>
16 __forceinline void interpolateUV(PlueckerHitM<M,UVIdentity<M>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint<M> &stepX, const vint<M> &stepY)
17 {
18 /* correct U,V interpolation across the entire grid */
19 const vint<M> sx((int)subgrid.x());
20 const vint<M> sy((int)subgrid.y());
21 const vint<M> sxM(sx + stepX);
22 const vint<M> syM(sy + stepY);
23 const float inv_resX = rcp(x: (float)((int)g.resX-1));
24 const float inv_resY = rcp(x: (float)((int)g.resY-1));
25 hit.U = (hit.U + vfloat<M>(sxM) * hit.UVW) * inv_resX;
26 hit.V = (hit.V + vfloat<M>(syM) * hit.UVW) * inv_resY;
27 }
28
29 template<int M, bool filter>
30 struct SubGridQuadMIntersector1Pluecker;
31
32 template<int M, bool filter>
33 struct SubGridQuadMIntersector1Pluecker
34 {
35 __forceinline SubGridQuadMIntersector1Pluecker() {}
36
37 __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
38
39 __forceinline void intersect(RayHit& ray, IntersectContext* context,
40 const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
41 const GridMesh::Grid &g, const SubGrid& subgrid) const
42 {
43 UVIdentity<M> mapUV;
44 PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
45 PlueckerIntersector1<M> intersector(ray,nullptr);
46
47 Intersect1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
48
49 /* intersect first triangle */
50 if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
51 {
52 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
53 epilog(hit.valid,hit);
54 }
55
56 /* intersect second triangle */
57 if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
58 {
59 hit.U = hit.UVW - hit.U;
60 hit.V = hit.UVW - hit.V;
61 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
62 epilog(hit.valid,hit);
63 }
64 }
65
66 __forceinline bool occluded(Ray& ray, IntersectContext* context,
67 const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3,
68 const GridMesh::Grid &g, const SubGrid& subgrid) const
69 {
70 UVIdentity<M> mapUV;
71 PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
72 PlueckerIntersector1<M> intersector(ray,nullptr);
73 Occluded1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID());
74
75 /* intersect first triangle */
76 if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))
77 {
78 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
79 if (epilog(hit.valid,hit))
80 return true;
81 }
82
83 /* intersect second triangle */
84 if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))
85 {
86 hit.U = hit.UVW - hit.U;
87 hit.V = hit.UVW - hit.V;
88 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
89 if (epilog(hit.valid,hit))
90 return true;
91 }
92 return false;
93 }
94 };
95
96#if defined (__AVX__)
97
98 /*! Intersects 4 quads with 1 ray using AVX */
99 template<bool filter>
100 struct SubGridQuadMIntersector1Pluecker<4,filter>
101 {
102 __forceinline SubGridQuadMIntersector1Pluecker() {}
103
104 __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
105
106 template<typename Epilog>
107 __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid& subgrid, const Epilog& epilog) const
108 {
109 const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
110#if !defined(EMBREE_BACKFACE_CULLING)
111 const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
112 const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
113#else
114 const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
115 const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
116#endif
117
118 UVIdentity<8> mapUV;
119 PlueckerHitM<8,UVIdentity<8>> hit(mapUV);
120 PlueckerIntersector1<8> intersector(ray,nullptr);
121 const vbool8 flags(0,0,0,0,1,1,1,1);
122 if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit)))
123 {
124 /* correct U,V interpolation across the entire grid */
125 const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U);
126 const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V);
127 hit.U = U;
128 hit.V = V;
129 hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
130 interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
131 if (unlikely(epilog(hit.valid,hit)))
132 return true;
133 }
134 return false;
135 }
136
137 __forceinline bool intersect(RayHit& ray, IntersectContext* context,
138 const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
139 const GridMesh::Grid &g, const SubGrid& subgrid) const
140 {
141 return intersect(ray,v0,v1,v2,v3,g,subgrid,Intersect1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
142 }
143
144 __forceinline bool occluded(Ray& ray, IntersectContext* context,
145 const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
146 const GridMesh::Grid &g, const SubGrid& subgrid) const
147 {
148 return intersect(ray,v0,v1,v2,v3,g,subgrid,Occluded1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID()));
149 }
150 };
151
152#endif
153
154
155 /* ----------------------------- */
156 /* -- ray packet intersectors -- */
157 /* ----------------------------- */
158
159 template<int K>
160 __forceinline void interpolateUV(const vbool<K>& valid, PlueckerHitK<K,UVIdentity<K>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const unsigned int i)
161 {
162 /* correct U,V interpolation across the entire grid */
163 const unsigned int sx = subgrid.x() + (unsigned int)(i % 2);
164 const unsigned int sy = subgrid.y() + (unsigned int)(i >>1);
165 const float inv_resX = rcp(x: (float)(int)(g.resX-1));
166 const float inv_resY = rcp(x: (float)(int)(g.resY-1));
167 hit.U = select(valid,(hit.U + vfloat<K>((float)sx) * hit.UVW) * inv_resX,hit.U);
168 hit.V = select(valid,(hit.V + vfloat<K>((float)sy) * hit.UVW) * inv_resY,hit.V);
169 }
170
171 template<int M, int K, bool filter>
172 struct SubGridQuadMIntersectorKPlueckerBase
173 {
174 __forceinline SubGridQuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {}
175
176 template<typename Epilog>
177 __forceinline bool intersectK(const vbool<K>& valid,
178 RayK<K>& ray,
179 const Vec3vf<K>& v0,
180 const Vec3vf<K>& v1,
181 const Vec3vf<K>& v2,
182 const Vec3vf<K>& v3,
183 const GridMesh::Grid &g,
184 const SubGrid &subgrid,
185 const unsigned int i,
186 const Epilog& epilog) const
187 {
188 UVIdentity<K> mapUV;
189 PlueckerHitK<K,UVIdentity<K>> hit(mapUV);
190 PlueckerIntersectorK<M,K> intersector;
191
192 const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit);
193 if (any(valid0))
194 {
195 interpolateUV(valid0,hit,g,subgrid,i);
196 epilog(valid0,hit);
197 }
198 const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit);
199 if (any(valid1))
200 {
201 hit.U = hit.UVW - hit.U;
202 hit.V = hit.UVW - hit.V;
203 interpolateUV(valid1,hit,g,subgrid,i);
204 epilog(valid1,hit);
205 }
206 return any(valid0|valid1);
207 }
208
209 template<typename Epilog>
210 __forceinline bool occludedK(const vbool<K>& valid,
211 RayK<K>& ray,
212 const Vec3vf<K>& v0,
213 const Vec3vf<K>& v1,
214 const Vec3vf<K>& v2,
215 const Vec3vf<K>& v3,
216 const GridMesh::Grid &g,
217 const SubGrid &subgrid,
218 const unsigned int i,
219 const Epilog& epilog) const
220 {
221 UVIdentity<K> mapUV;
222 PlueckerHitK<K,UVIdentity<K>> hit(mapUV);
223 PlueckerIntersectorK<M,K> intersector;
224
225 vbool<K> valid_final = valid;
226 const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit);
227 if (any(valid0))
228 {
229 interpolateUV(valid0,hit,g,subgrid,i);
230 epilog(valid0,hit);
231 valid_final &= !valid0;
232 }
233 if (none(valid_final)) return true;
234 const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit);
235 if (any(valid1))
236 {
237 hit.U = hit.UVW - hit.U;
238 hit.V = hit.UVW - hit.V;
239 interpolateUV(valid1,hit,g,subgrid,i);
240 epilog(valid1,hit);
241 valid_final &= !valid1;
242 }
243 return none(valid_final);
244 }
245
246
247 };
248
249
250
251
252 template<int M, int K, bool filter>
253 struct SubGridQuadMIntersectorKPluecker : public SubGridQuadMIntersectorKPlueckerBase<M,K,filter>
254 {
255 __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
256 : SubGridQuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {}
257
258 __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
259 const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
260 {
261 UVIdentity<M> mapUV;
262 PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
263 Intersect1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
264 PlueckerIntersectorK<M,K> intersector;
265
266 /* intersect first triangle */
267 if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))
268 {
269 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
270 epilog(hit.valid,hit);
271 }
272
273 /* intersect second triangle */
274 if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))
275 {
276 hit.U = hit.UVW - hit.U;
277 hit.V = hit.UVW - hit.V;
278 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
279 epilog(hit.valid,hit);
280 }
281 }
282
283 __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
284 const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
285 {
286 UVIdentity<M> mapUV;
287 PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
288 Occluded1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());
289 PlueckerIntersectorK<M,K> intersector;
290
291 /* intersect first triangle */
292 if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))
293 {
294 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
295 if (epilog(hit.valid,hit)) return true;
296 }
297
298 /* intersect second triangle */
299 if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))
300 {
301 hit.U = hit.UVW - hit.U;
302 hit.V = hit.UVW - hit.V;
303 interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1));
304 if (epilog(hit.valid,hit)) return true;
305 }
306 return false;
307 }
308 };
309
310
311#if defined (__AVX__)
312
313 /*! Intersects 4 quads with 1 ray using AVX */
314 template<int K, bool filter>
315 struct SubGridQuadMIntersectorKPluecker<4,K,filter> : public SubGridQuadMIntersectorKPlueckerBase<4,K,filter>
316 {
317 __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
318 : SubGridQuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
319
320 template<typename Epilog>
321 __forceinline bool intersect1(RayK<K>& ray, size_t k,const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
322 const GridMesh::Grid &g, const SubGrid &subgrid, const Epilog& epilog) const
323 {
324 const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
325#if !defined(EMBREE_BACKFACE_CULLING)
326 const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
327 const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
328#else
329 const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
330 const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
331#endif
332 UVIdentity<8> mapUV;
333 PlueckerHitM<8,UVIdentity<8>> hit(mapUV);
334 PlueckerIntersectorK<8,K> intersector;
335 const vbool8 flags(0,0,0,0,1,1,1,1);
336 if (unlikely(intersector.intersect(ray,k,vtx0,vtx1,vtx2,mapUV,hit)))
337 {
338 /* correct U,V interpolation across the entire grid */
339 const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U);
340 const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V);
341 hit.U = U;
342 hit.V = V;
343 hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));
344 interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1));
345 if (unlikely(epilog(hit.valid,hit)))
346 return true;
347 }
348 return false;
349 }
350
351 __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context,
352 const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
353 {
354 return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Intersect1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
355 }
356
357 __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
358 const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const
359 {
360 return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Occluded1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID()));
361 }
362 };
363#endif
364
365
366 }
367}
368

source code of qtquick3d/src/3rdparty/embree/kernels/geometry/subgrid_intersector_pluecker.h