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

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