Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
9913 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "bezier_curve.h"
7
8
namespace embree
9
{
10
namespace isa
11
{
12
template<typename V>
13
struct TensorLinearQuadraticBezierSurface
14
{
15
QuadraticBezierCurve<V> L;
16
QuadraticBezierCurve<V> R;
17
18
__forceinline TensorLinearQuadraticBezierSurface() {}
19
20
__forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<V>& curve)
21
: L(curve.L), R(curve.R) {}
22
23
__forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
24
L = other.L; R = other.R; return *this;
25
}
26
27
__forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<V>& L, const QuadraticBezierCurve<V>& R)
28
: L(L), R(R) {}
29
30
__forceinline BBox<V> bounds() const {
31
return merge(L.bounds(),R.bounds());
32
}
33
};
34
35
#if !defined(__SYCL_DEVICE_ONLY__)
36
template<>
37
struct TensorLinearQuadraticBezierSurface<Vec2fa>
38
{
39
QuadraticBezierCurve<vfloat4> LR;
40
41
__forceinline TensorLinearQuadraticBezierSurface() {}
42
43
__forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<Vec2fa>& curve)
44
: LR(curve.LR) {}
45
46
__forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
47
LR = other.LR; return *this;
48
}
49
50
__forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<vfloat4>& LR)
51
: LR(LR) {}
52
53
__forceinline BBox<Vec2fa> bounds() const
54
{
55
const BBox<vfloat4> b = LR.bounds();
56
const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
57
const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
58
return merge(bl,br);
59
}
60
};
61
#endif
62
63
template<typename V>
64
struct TensorLinearCubicBezierSurface
65
{
66
CubicBezierCurve<V> L;
67
CubicBezierCurve<V> R;
68
69
__forceinline TensorLinearCubicBezierSurface() {}
70
71
__forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
72
: L(curve.L), R(curve.R) {}
73
74
__forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
75
L = other.L; R = other.R; return *this;
76
}
77
78
__forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<V>& L, const CubicBezierCurve<V>& R)
79
: L(L), R(R) {}
80
81
template<template<typename T> class SourceCurve>
82
__forceinline static TensorLinearCubicBezierSurface fromCenterAndNormalCurve(const SourceCurve<Vec3ff>& center, const SourceCurve<Vec3fa>& normal)
83
{
84
SourceCurve<Vec3ff> vcurve = center;
85
SourceCurve<Vec3fa> ncurve = normal;
86
87
/* here we construct a patch which follows the curve l(t) =
88
* p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */
89
90
const Vec3ff p0 = vcurve.eval(0.0f);
91
const Vec3ff dp0 = vcurve.eval_du(0.0f);
92
//const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); // ddp0 is assumed to be 0
93
94
const Vec3fa n0 = ncurve.eval(0.0f);
95
const Vec3fa dn0 = ncurve.eval_du(0.0f);
96
97
const Vec3ff p1 = vcurve.eval(1.0f);
98
const Vec3ff dp1 = vcurve.eval_du(1.0f);
99
//const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); // ddp1 is assumed to be 0
100
101
const Vec3fa n1 = ncurve.eval(1.0f);
102
const Vec3fa dn1 = ncurve.eval_du(1.0f);
103
104
const Vec3fa bt0 = cross(n0,dp0);
105
const Vec3fa dbt0 = cross(dn0,dp0);// + cross(n0,ddp0);
106
107
const Vec3fa bt1 = cross(n1,dp1);
108
const Vec3fa dbt1 = cross(dn1,dp1);// + cross(n1,ddp1);
109
110
const Vec3fa k0 = normalize(bt0);
111
const Vec3fa dk0 = dnormalize(bt0,dbt0);
112
113
const Vec3fa k1 = normalize(bt1);
114
const Vec3fa dk1 = dnormalize(bt1,dbt1);
115
116
const Vec3fa l0 = p0 - p0.w*k0;
117
const Vec3fa dl0 = dp0 - (dp0.w*k0 + p0.w*dk0);
118
119
const Vec3fa r0 = p0 + p0.w*k0;
120
const Vec3fa dr0 = dp0 + (dp0.w*k0 + p0.w*dk0);
121
122
const Vec3fa l1 = p1 - p1.w*k1;
123
const Vec3fa dl1 = dp1 - (dp1.w*k1 + p1.w*dk1);
124
125
const Vec3fa r1 = p1 + p1.w*k1;
126
const Vec3fa dr1 = dp1 + (dp1.w*k1 + p1.w*dk1);
127
128
const float scale = 1.0f/3.0f;
129
CubicBezierCurve<V> L(l0,l0+scale*dl0,l1-scale*dl1,l1);
130
CubicBezierCurve<V> R(r0,r0+scale*dr0,r1-scale*dr1,r1);
131
return TensorLinearCubicBezierSurface(L,R);
132
}
133
134
__forceinline BBox<V> bounds() const {
135
return merge(L.bounds(),R.bounds());
136
}
137
138
__forceinline BBox3fa accurateBounds() const {
139
return merge(L.accurateBounds(),R.accurateBounds());
140
}
141
142
__forceinline CubicBezierCurve<Interval1f> reduce_v() const {
143
return merge(CubicBezierCurve<Interval<V>>(L),CubicBezierCurve<Interval<V>>(R));
144
}
145
146
__forceinline LinearBezierCurve<Interval1f> reduce_u() const {
147
return LinearBezierCurve<Interval1f>(L.bounds(),R.bounds());
148
}
149
150
__forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx) const {
151
return TensorLinearCubicBezierSurface<float>(L.xfm(dx),R.xfm(dx));
152
}
153
154
template<int W>
155
__forceinline TensorLinearCubicBezierSurface<vfloat<W>> vxfm(const V& dx) const {
156
return TensorLinearCubicBezierSurface<vfloat<W>>(L.template vxfm<W>(dx),R.template vxfm<W>(dx));
157
}
158
159
__forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx, const V& p) const {
160
return TensorLinearCubicBezierSurface<float>(L.xfm(dx,p),R.xfm(dx,p));
161
}
162
163
__forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space) const {
164
return TensorLinearCubicBezierSurface(L.xfm(space),R.xfm(space));
165
}
166
167
__forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const {
168
return TensorLinearCubicBezierSurface(L.xfm(space,p),R.xfm(space,p));
169
}
170
171
__forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const {
172
return TensorLinearCubicBezierSurface(L.xfm(space,p,s),R.xfm(space,p,s));
173
}
174
175
__forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
176
return TensorLinearCubicBezierSurface(L.clip(u),R.clip(u));
177
}
178
179
__forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const {
180
return TensorLinearCubicBezierSurface(clerp(L,R,V(v.lower)),clerp(L,R,V(v.upper)));
181
}
182
183
__forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
184
return clip_v(v).clip_u(u);
185
}
186
187
__forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
188
{
189
CubicBezierCurve<V> L0,L1; L.split(L0,L1,u);
190
CubicBezierCurve<V> R0,R1; R.split(R0,R1,u);
191
new (&left ) TensorLinearCubicBezierSurface(L0,R0);
192
new (&right) TensorLinearCubicBezierSurface(L1,R1);
193
}
194
195
__forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
196
valid = true; clear(valid,VSIZEX-1);
197
return TensorLinearCubicBezierSurface<Vec2vfx>(L.split(u),R.split(u));
198
}
199
200
template<int W>
201
__forceinline TensorLinearCubicBezierSurface<Vec2vf<W>> vsplit_u(vbool<W>& valid, const BBox1f& u, int& i, int N) const
202
{
203
valid = true; clear(valid,W-1);
204
auto r = TensorLinearCubicBezierSurface<Vec2vf<W>>(L.template split<W>(u,i,N),R.template split<W>(u,i,N));
205
i += W-1;
206
return r;
207
}
208
209
__forceinline V eval(const float u, const float v) const {
210
return clerp(L,R,V(v)).eval(u);
211
}
212
213
__forceinline V eval_du(const float u, const float v) const {
214
return clerp(L,R,V(v)).eval_dt(u);
215
}
216
217
__forceinline V eval_dv(const float u, const float v) const {
218
return (R-L).eval(u);
219
}
220
221
__forceinline void eval(const float u, const float v, V& p, V& dpdu, V& dpdv) const
222
{
223
V p0, dp0du; L.eval(u,p0,dp0du);
224
V p1, dp1du; R.eval(u,p1,dp1du);
225
p = lerp(p0,p1,v);
226
dpdu = lerp(dp0du,dp1du,v);
227
dpdv = p1-p0;
228
}
229
230
__forceinline TensorLinearQuadraticBezierSurface<V> derivative_u() const {
231
return TensorLinearQuadraticBezierSurface<V>(L.derivative(),R.derivative());
232
}
233
234
__forceinline CubicBezierCurve<V> derivative_v() const {
235
return R-L;
236
}
237
238
__forceinline V axis_u() const {
239
return (L.end()-L.begin())+(R.end()-R.begin());
240
}
241
242
__forceinline V axis_v() const {
243
return (R.begin()-L.begin())+(R.end()-L.end());
244
}
245
246
friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
247
{
248
return cout << "TensorLinearCubicBezierSurface" << embree_endl
249
<< "{" << embree_endl
250
<< " L = " << a.L << ", " << embree_endl
251
<< " R = " << a.R << embree_endl
252
<< "}";
253
}
254
255
friend __forceinline TensorLinearCubicBezierSurface clerp(const TensorLinearCubicBezierSurface& a, const TensorLinearCubicBezierSurface& b, const float t) {
256
return TensorLinearCubicBezierSurface(clerp(a.L,b.L,V(t)), clerp(a.R,b.R,V(t)));
257
}
258
};
259
260
#if !defined(__SYCL_DEVICE_ONLY__)
261
262
template<>
263
struct TensorLinearCubicBezierSurface<Vec2fa>
264
{
265
CubicBezierCurve<vfloat4> LR;
266
267
__forceinline TensorLinearCubicBezierSurface() {}
268
269
__forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
270
: LR(curve.LR) {}
271
272
__forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
273
LR = other.LR; return *this;
274
}
275
276
__forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<vfloat4>& LR)
277
: LR(LR) {}
278
279
__forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<Vec2fa>& L, const CubicBezierCurve<Vec2fa>& R)
280
: LR(shuffle<0,1,0,1>(vfloat4(L.v0),vfloat4(R.v0)),shuffle<0,1,0,1>(vfloat4(L.v1),vfloat4(R.v1)),shuffle<0,1,0,1>(vfloat4(L.v2),vfloat4(R.v2)),shuffle<0,1,0,1>(vfloat4(L.v3),vfloat4(R.v3))) {}
281
282
__forceinline CubicBezierCurve<Vec2fa> getL() const {
283
return CubicBezierCurve<Vec2fa>(Vec2fa(LR.v0),Vec2fa(LR.v1),Vec2fa(LR.v2),Vec2fa(LR.v3));
284
}
285
286
__forceinline CubicBezierCurve<Vec2fa> getR() const {
287
return CubicBezierCurve<Vec2fa>(Vec2fa(shuffle<2,3,2,3>(LR.v0)),Vec2fa(shuffle<2,3,2,3>(LR.v1)),Vec2fa(shuffle<2,3,2,3>(LR.v2)),Vec2fa(shuffle<2,3,2,3>(LR.v3)));
288
}
289
290
__forceinline BBox<Vec2fa> bounds() const
291
{
292
const BBox<vfloat4> b = LR.bounds();
293
const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
294
const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
295
return merge(bl,br);
296
}
297
298
__forceinline BBox1f bounds(const Vec2fa& axis) const
299
{
300
const CubicBezierCurve<vfloat4> LRx = LR;
301
const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
302
const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(axis)),LRx,shuffle<1>(vfloat4(axis))*LRy);
303
const BBox<vfloat4> Lb = LRa.bounds();
304
const BBox<vfloat4> Rb(shuffle<3>(Lb.lower),shuffle<3>(Lb.upper));
305
const BBox<vfloat4> b = merge(Lb,Rb);
306
return BBox1f(b.lower[0],b.upper[0]);
307
}
308
309
__forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx) const
310
{
311
const CubicBezierCurve<vfloat4> LRx = LR;
312
const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
313
const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
314
return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
315
CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
316
}
317
318
__forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx, const Vec2fa& p) const
319
{
320
const vfloat4 pxyxy = shuffle<0,1,0,1>(vfloat4(p));
321
const CubicBezierCurve<vfloat4> LRx = LR-pxyxy;
322
const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
323
const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
324
return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
325
CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
326
}
327
328
__forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
329
return TensorLinearCubicBezierSurface(LR.clip(u));
330
}
331
332
__forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const
333
{
334
const CubicBezierCurve<vfloat4> LL(shuffle<0,1,0,1>(LR.v0),shuffle<0,1,0,1>(LR.v1),shuffle<0,1,0,1>(LR.v2),shuffle<0,1,0,1>(LR.v3));
335
const CubicBezierCurve<vfloat4> RR(shuffle<2,3,2,3>(LR.v0),shuffle<2,3,2,3>(LR.v1),shuffle<2,3,2,3>(LR.v2),shuffle<2,3,2,3>(LR.v3));
336
return TensorLinearCubicBezierSurface(clerp(LL,RR,vfloat4(v.lower,v.lower,v.upper,v.upper)));
337
}
338
339
__forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
340
return clip_v(v).clip_u(u);
341
}
342
343
__forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
344
{
345
CubicBezierCurve<vfloat4> LR0,LR1; LR.split(LR0,LR1,u);
346
new (&left ) TensorLinearCubicBezierSurface(LR0);
347
new (&right) TensorLinearCubicBezierSurface(LR1);
348
}
349
350
__forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
351
valid = true; clear(valid,VSIZEX-1);
352
return TensorLinearCubicBezierSurface<Vec2vfx>(getL().split(u),getR().split(u));
353
}
354
355
template<int W>
356
__forceinline TensorLinearCubicBezierSurface<Vec2vf<W>> vsplit_u(vbool<W>& valid, const BBox1f& u, int& i, int N) const {
357
valid = true; clear(valid,W-1);
358
auto r = TensorLinearCubicBezierSurface<Vec2vf<W>>(getL().split<W>(u,i,N),getR().split<W>(u,i,N));
359
i += W-1;
360
return r;
361
}
362
363
__forceinline Vec2fa eval(const float u, const float v) const
364
{
365
const vfloat4 p = LR.eval(u);
366
return Vec2fa(lerp(shuffle<0,1,0,1>(p),shuffle<2,3,2,3>(p),v));
367
}
368
369
__forceinline Vec2fa eval_du(const float u, const float v) const
370
{
371
const vfloat4 dpdu = LR.eval_dt(u);
372
return Vec2fa(lerp(shuffle<0,1,0,1>(dpdu),shuffle<2,3,2,3>(dpdu),v));
373
}
374
375
__forceinline Vec2fa eval_dv(const float u, const float v) const
376
{
377
const vfloat4 p = LR.eval(u);
378
return Vec2fa(shuffle<2,3,2,3>(p)-shuffle<0,1,0,1>(p));
379
}
380
381
__forceinline void eval(const float u, const float v, Vec2fa& p, Vec2fa& dpdu, Vec2fa& dpdv) const
382
{
383
vfloat4 p0, dp0du; LR.eval(u,p0,dp0du);
384
p = Vec2fa(lerp(shuffle<0,1,0,1>(p0),shuffle<2,3,2,3>(p0),v));
385
dpdu = Vec2fa(lerp(shuffle<0,1,0,1>(dp0du),shuffle<2,3,2,3>(dp0du),v));
386
dpdv = Vec2fa(shuffle<2,3,2,3>(p0)-shuffle<0,1,0,1>(p0));
387
}
388
389
__forceinline TensorLinearQuadraticBezierSurface<Vec2fa> derivative_u() const {
390
return TensorLinearQuadraticBezierSurface<Vec2fa>(LR.derivative());
391
}
392
393
__forceinline CubicBezierCurve<Vec2fa> derivative_v() const {
394
return getR()-getL();
395
}
396
397
__forceinline Vec2fa axis_u() const
398
{
399
const CubicBezierCurve<Vec2fa> L = getL();
400
const CubicBezierCurve<Vec2fa> R = getR();
401
return (L.end()-L.begin())+(R.end()-R.begin());
402
}
403
404
__forceinline Vec2fa axis_v() const
405
{
406
const CubicBezierCurve<Vec2fa> L = getL();
407
const CubicBezierCurve<Vec2fa> R = getR();
408
return (R.begin()-L.begin())+(R.end()-L.end());
409
}
410
411
friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
412
{
413
return cout << "TensorLinearCubicBezierSurface" << embree_endl
414
<< "{" << embree_endl
415
<< " L = " << a.getL() << ", " << embree_endl
416
<< " R = " << a.getR() << embree_endl
417
<< "}";
418
}
419
};
420
421
template<>
422
__forceinline TensorLinearCubicBezierSurface<Vec2f> TensorLinearCubicBezierSurface<Vec2fa>::vsplit_u<1>(bool& valid, const BBox1f& u, int& i, int N) const {
423
auto r = TensorLinearCubicBezierSurface<Vec2f>(getL().split1(u,i,N),getR().split1(u,i,N));
424
valid = true; i += 1;
425
return r;
426
}
427
428
#else
429
430
template<> template<>
431
__forceinline TensorLinearCubicBezierSurface<Vec2f> TensorLinearCubicBezierSurface<Vec2fa>::vsplit_u<1>(bool& valid, const BBox1f& u, int& i, int N) const {
432
auto r = TensorLinearCubicBezierSurface<Vec2f>(L.split1(u,i,N),R.split1(u,i,N));
433
valid = true; i += 1;
434
return r;
435
}
436
437
#endif
438
439
typedef TensorLinearCubicBezierSurface<float> TensorLinearCubicBezierSurface1f;
440
typedef TensorLinearCubicBezierSurface<Vec2fa> TensorLinearCubicBezierSurface2fa;
441
typedef TensorLinearCubicBezierSurface<Vec3fa> TensorLinearCubicBezierSurface3fa;
442
}
443
}
444
445