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 | { |
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 | |