Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/geometry/disc_intersector.h
9905 views
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
10
namespace 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
return Vec2f(vu[i], vv[i]);
28
}
29
__forceinline Vec2vf<M> uv() const {
30
return Vec2vf<M>(vu, vv);
31
}
32
__forceinline float t(const size_t i) const {
33
return vt[i];
34
}
35
__forceinline vfloat<M> t() const {
36
return vt;
37
}
38
__forceinline Vec3fa Ng(const size_t i) const {
39
return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);
40
}
41
__forceinline Vec3vf<M> Ng() const {
42
return vNg;
43
}
44
45
public:
46
vfloat<M> vu;
47
vfloat<M> vv;
48
vfloat<M> vt;
49
Vec3vf<M> vNg;
50
};
51
52
template<>
53
struct DiscIntersectorHitM<1>
54
{
55
__forceinline DiscIntersectorHitM() {}
56
57
__forceinline DiscIntersectorHitM(const float& u, const float& v, const float& t, const Vec3fa& Ng)
58
: vu(u), vv(v), vt(t), vNg(Ng) {}
59
60
__forceinline void finalize() {}
61
62
__forceinline Vec2f uv() const {
63
return Vec2f(vu, vv);
64
}
65
66
__forceinline float t() const {
67
return vt;
68
}
69
70
__forceinline Vec3fa Ng() const {
71
return vNg;
72
}
73
74
public:
75
float vu;
76
float vv;
77
float vt;
78
Vec3fa vNg;
79
};
80
81
template<int M>
82
struct DiscIntersector1
83
{
84
typedef CurvePrecalculations1 Precalculations;
85
86
template<typename Ray, typename Epilog>
87
static __forceinline bool intersect(
88
const vbool<M>& valid_i,
89
Ray& ray,
90
RayQueryContext* context,
91
const Points* geom,
92
const Precalculations& pre,
93
const Vec4vf<M>& v0i,
94
const Epilog& epilog)
95
{
96
vbool<M> valid = valid_i;
97
98
const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
99
const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);
100
const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
101
102
const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
103
const Vec3vf<M> center = v0.xyz();
104
const vfloat<M> radius = v0.w;
105
106
/* compute ray distance projC0 to hit point with ray oriented plane */
107
const Vec3vf<M> c0 = center - ray_org;
108
const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
109
110
valid &= (vfloat<M>(ray.tnear()) <= projC0) & (projC0 <= vfloat<M>(ray.tfar));
111
if (unlikely(none(valid)))
112
return false;
113
114
/* check if hit point lies inside disc */
115
const Vec3vf<M> perp = c0 - projC0 * ray_dir;
116
const vfloat<M> l2 = dot(perp, perp);
117
const vfloat<M> r2 = radius * radius;
118
valid &= (l2 <= r2);
119
if (unlikely(none(valid)))
120
return false;
121
122
/* We reject hits where the ray origin lies inside the ray
123
* oriented disc to avoid self intersections. */
124
#if defined(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE)
125
const vfloat<M> m2 = dot(c0, c0);
126
valid &= (m2 > r2);
127
if (unlikely(none(valid)))
128
return false;
129
#endif
130
131
DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
132
return epilog(valid, hit);
133
}
134
135
template<typename Ray, typename Epilog>
136
static __forceinline bool intersect(const vbool<M>& valid_i,
137
Ray& ray,
138
RayQueryContext* context,
139
const Points* geom,
140
const Precalculations& pre,
141
const Vec4vf<M>& v0i,
142
const Vec3vf<M>& normal,
143
const Epilog& epilog)
144
{
145
vbool<M> valid = valid_i;
146
const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);
147
148
const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
149
const Vec3vf<M> center = v0.xyz();
150
const vfloat<M> radius = v0.w;
151
152
vfloat<M> divisor = dot(Vec3vf<M>((Vec3fa)ray.dir), normal);
153
const vbool<M> parallel = divisor == vfloat<M>(0.f);
154
valid &= !parallel;
155
divisor = select(parallel, 1.f, divisor); // prevent divide by zero
156
157
vfloat<M> t = dot(center - Vec3vf<M>((Vec3fa)ray.org), Vec3vf<M>(normal)) / divisor;
158
159
valid &= (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));
160
if (unlikely(none(valid)))
161
return false;
162
163
Vec3vf<M> intersection = Vec3vf<M>((Vec3fa)ray.org) + Vec3vf<M>((Vec3fa)ray.dir) * t;
164
vfloat<M> dist2 = dot(intersection - center, intersection - center);
165
valid &= dist2 < radius * radius;
166
if (unlikely(none(valid)))
167
return false;
168
169
DiscIntersectorHitM<M> hit(zero, zero, t, normal);
170
return epilog(valid, hit);
171
}
172
};
173
174
template<int M, int K>
175
struct DiscIntersectorK
176
{
177
typedef CurvePrecalculationsK<K> Precalculations;
178
179
template<typename Epilog>
180
static __forceinline bool intersect(const vbool<M>& valid_i,
181
RayK<K>& ray,
182
size_t k,
183
RayQueryContext* context,
184
const Points* geom,
185
const Precalculations& pre,
186
const Vec4vf<M>& v0i,
187
const Epilog& epilog)
188
{
189
vbool<M> valid = valid_i;
190
191
const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
192
const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
193
const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));
194
195
const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
196
const Vec3vf<M> center = v0.xyz();
197
const vfloat<M> radius = v0.w;
198
199
/* compute ray distance projC0 to hit point with ray oriented plane */
200
const Vec3vf<M> c0 = center - ray_org;
201
const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;
202
203
valid &= (vfloat<M>(ray.tnear()[k]) <= projC0) & (projC0 <= vfloat<M>(ray.tfar[k]));
204
if (unlikely(none(valid)))
205
return false;
206
207
/* check if hit point lies inside disc */
208
const Vec3vf<M> perp = c0 - projC0 * ray_dir;
209
const vfloat<M> l2 = dot(perp, perp);
210
const vfloat<M> r2 = radius * radius;
211
valid &= (l2 <= r2);
212
if (unlikely(none(valid)))
213
return false;
214
215
/* We reject hits where the ray origin lies inside the ray
216
* oriented disc to avoid self intersections. */
217
#if defined(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE)
218
const vfloat<M> m2 = dot(c0, c0);
219
valid &= (m2 > r2);
220
if (unlikely(none(valid)))
221
return false;
222
#endif
223
224
DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);
225
return epilog(valid, hit);
226
}
227
228
template<typename Epilog>
229
static __forceinline bool intersect(const vbool<M>& valid_i,
230
RayK<K>& ray,
231
size_t k,
232
RayQueryContext* context,
233
const Points* geom,
234
const Precalculations& pre,
235
const Vec4vf<M>& v0i,
236
const Vec3vf<M>& normal,
237
const Epilog& epilog)
238
{
239
vbool<M> valid = valid_i;
240
const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);
241
const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);
242
243
const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);
244
const Vec3vf<M> center = v0.xyz();
245
const vfloat<M> radius = v0.w;
246
247
vfloat<M> divisor = dot(Vec3vf<M>(ray_dir), normal);
248
const vbool<M> parallel = divisor == vfloat<M>(0.f);
249
valid &= !parallel;
250
divisor = select(parallel, 1.f, divisor); // prevent divide by zero
251
252
vfloat<M> t = dot(center - Vec3vf<M>(ray_org), Vec3vf<M>(normal)) / divisor;
253
254
valid &= (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));
255
if (unlikely(none(valid)))
256
return false;
257
258
Vec3vf<M> intersection = Vec3vf<M>(ray_org) + Vec3vf<M>(ray_dir) * t;
259
vfloat<M> dist2 = dot(intersection - center, intersection - center);
260
valid &= dist2 < radius * radius;
261
if (unlikely(none(valid)))
262
return false;
263
264
DiscIntersectorHitM<M> hit(zero, zero, t, normal);
265
return epilog(valid, hit);
266
}
267
};
268
} // namespace isa
269
} // namespace embree
270
271