1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "../common/ray.h"
7#include "../common/scene_points.h"
8#include "curve_intersector_precalculations.h"
9
10namespace embree
11{
12 namespace isa
13 {
14 template<int M>
15 struct DiscIntersectorHitM
16 {
17 __forceinline DiscIntersectorHitM() {}
18
19 __forceinline DiscIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)
20 : vu(u), vv(v), vt(t), vNg(Ng)
21 {
22 }
23
24 __forceinline void finalize() {}
25
26 __forceinline Vec2f uv(const size_t i) const
27 {
28 return Vec2f(vu[i], vv[i]);
29 }
30 __forceinline float t(const size_t i) const
31 {
32 return vt[i];
33 }
34 __forceinline Vec3fa Ng(const size_t i) const
35 {
36 return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);
37 }
38
39 public:
40 vfloat<M> vu;
41 vfloat<M> vv;
42 vfloat<M> vt;
43 Vec3vf<M> vNg;
44 };
45
46 template<int M>
47 struct DiscIntersector1
48 {
49 typedef CurvePrecalculations1 Precalculations;
50
51 template<typename Epilog>
52 static __forceinline bool intersect(
53 const vbool<M>& valid_i,
54 Ray& ray,
55 IntersectContext* context,
56 const Points* geom,
57 const Precalculations& pre,
58 const Vec4vf<M>& v0i,
59 const Epilog& epilog)
60 {
61 vbool<M> valid = valid_i;
62
63 const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
64 const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
65 const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
66
67 const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
68 const Vec3vf<M> center = v0.xyz();
69 const vfloat<M> radius = v0.w;
70
71 const Vec3vf<M> c0 = center - ray_org;
72 const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
73
74 valid &= (vfloat<M>(ray.tnear()) <= projC0) & (projC0 <= vfloat<M>(ray.tfar));
75 if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
76 valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale; // ignore self intersections
77 if (unlikely(none(valid)))
78 return false;
79
80 const Vec3vf<M> perp = c0 - projC0 * ray_dir;
81 const vfloat<M> l2 = dot(perp, perp);
82 const vfloat<M> r2 = radius * radius;
83 valid &= (l2 <= r2);
84 if (unlikely(none(valid)))
85 return false;
86
87 DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
88 return epilog(valid, hit);
89 }
90
91 template<typename Epilog>
92 static __forceinline bool intersect(const vbool<M>& valid_i,
93 Ray& ray,
94 IntersectContext* context,
95 const Points* geom,
96 const Precalculations& pre,
97 const Vec4vf<M>& v0i,
98 const Vec3vf<M>& normal,
99 const Epilog& epilog)
100 {
101 vbool<M> valid = valid_i;
102 const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
103
104 const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
105 const Vec3vf<M> center = v0.xyz();
106 const vfloat<M> radius = v0.w;
107
108 vfloat<M> divisor = dot(Vec3vf<M>((Vec3fa)ray.dir), normal);
109 const vbool<M> parallel = divisor == vfloat<M>(0.f);
110 valid &= !parallel;
111 divisor = select(parallel, 1.f, divisor); // prevent divide by zero
112
113 vfloat<M> t = dot(center - Vec3vf<M>((Vec3fa)ray.org), Vec3vf<M>(normal)) / divisor;
114
115 valid &= (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));
116 if (unlikely(none(valid)))
117 return false;
118
119 Vec3vf<M> intersection = Vec3vf<M>((Vec3fa)ray.org) + Vec3vf<M>((Vec3fa)ray.dir) * t;
120 vfloat<M> dist2 = dot(intersection - center, intersection - center);
121 valid &= dist2 < radius * radius;
122 if (unlikely(none(valid)))
123 return false;
124
125 DiscIntersectorHitM<M> hit(zero, zero, t, normal);
126 return epilog(valid, hit);
127 }
128 };
129
130 template<int M, int K>
131 struct DiscIntersectorK
132 {
133 typedef CurvePrecalculationsK<K> Precalculations;
134
135 template<typename Epilog>
136 static __forceinline bool intersect(const vbool<M>& valid_i,
137 RayK<K>& ray,
138 size_t k,
139 IntersectContext* context,
140 const Points* geom,
141 const Precalculations& pre,
142 const Vec4vf<M>& v0i,
143 const Epilog& epilog)
144 {
145 vbool<M> valid = valid_i;
146
147 const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
148 const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
149 const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
150
151 const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
152 const Vec3vf<M> center = v0.xyz();
153 const vfloat<M> radius = v0.w;
154
155 const Vec3vf<M> c0 = center - ray_org;
156 const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
157
158 valid &= (vfloat<M>(ray.tnear()[k]) <= projC0) & (projC0 <= vfloat<M>(ray.tfar[k]));
159 if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f)
160 valid &= projC0 > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR) * radius * pre.depth_scale[k]; // ignore self intersections
161 if (unlikely(none(valid)))
162 return false;
163
164 const Vec3vf<M> perp = c0 - projC0 * ray_dir;
165 const vfloat<M> l2 = dot(perp, perp);
166 const vfloat<M> r2 = radius * radius;
167 valid &= (l2 <= r2);
168 if (unlikely(none(valid)))
169 return false;
170
171 DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
172 return epilog(valid, hit);
173 }
174
175 template<typename Epilog>
176 static __forceinline bool intersect(const vbool<M>& valid_i,
177 RayK<K>& ray,
178 size_t k,
179 IntersectContext* context,
180 const Points* geom,
181 const Precalculations& pre,
182 const Vec4vf<M>& v0i,
183 const Vec3vf<M>& normal,
184 const Epilog& epilog)
185 {
186 vbool<M> valid = valid_i;
187 const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
188 const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
189
190 const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
191 const Vec3vf<M> center = v0.xyz();
192 const vfloat<M> radius = v0.w;
193
194 vfloat<M> divisor = dot(Vec3vf<M>(ray_dir), normal);
195 const vbool<M> parallel = divisor == vfloat<M>(0.f);
196 valid &= !parallel;
197 divisor = select(parallel, 1.f, divisor); // prevent divide by zero
198
199 vfloat<M> t = dot(center - Vec3vf<M>(ray_org), Vec3vf<M>(normal)) / divisor;
200
201 valid &= (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));
202 if (unlikely(none(valid)))
203 return false;
204
205 Vec3vf<M> intersection = Vec3vf<M>(ray_org) + Vec3vf<M>(ray_dir) * t;
206 vfloat<M> dist2 = dot(intersection - center, intersection - center);
207 valid &= dist2 < radius * radius;
208 if (unlikely(none(valid)))
209 return false;
210
211 DiscIntersectorHitM<M> hit(zero, zero, t, normal);
212 return epilog(valid, hit);
213 }
214 };
215 } // namespace isa
216} // namespace embree
217

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