@@ -7,25 +7,103 @@ namespace hlsl
7
7
{
8
8
namespace shapes
9
9
{
10
- struct CubicBezier
10
+ float dot2 ( float2 v ) { return dot (v,v); }
11
+ float cross2d ( float2 a, float2 b ) { return a.x*b.y - a.y*b.x; }
12
+
13
+ struct QuadraticBezier
11
14
{
12
- static CubicBezier construct ()
15
+ float2 A;
16
+ float2 B;
17
+ float2 C;
18
+ float thickness;
19
+
20
+ static QuadraticBezier construct (float2 a, float2 b, float2 c, float thickness)
13
21
{
22
+ QuadraticBezier ret = { a, b, c, thickness };
23
+ return ret;
14
24
}
15
25
16
- float signedDistance (float2 p )
26
+ float signedDistance (float2 pos )
17
27
{
28
+ float2 a = B - A;
29
+ float2 b = A - 2.0 *B + C;
30
+ float2 c = a * 2.0 ;
31
+ float2 d = A - pos;
32
+
33
+ float kk = 1.0 /dot (b,b);
34
+ float kx = kk * dot (a,b);
35
+ float ky = kk * (2.0 *dot (a,a)+dot (d,b))/3.0 ;
36
+ float kz = kk * dot (d,a);
37
+
38
+ float res = 0.0 ;
39
+ float sgn = 0.0 ;
40
+
41
+ float p = ky - kx*kx;
42
+ float q = kx*(2.0 *kx*kx - 3.0 *ky) + kz;
43
+ float p3 = p*p*p;
44
+ float q2 = q*q;
45
+ float h = q2 + 4.0 *p3;
46
+
47
+ if ( h>=0.0 )
48
+ {
49
+ // 1 root
50
+ h = sqrt (h);
51
+ float2 x = (float2 (h,-h)-q)/2.0 ;
52
+
53
+ #if 0
54
+ // When p≈0 and p<0, h-q has catastrophic cancelation. So, we do
55
+ // h=√(q²+4p³)=q·√(1+4p³/q²)=q·√(1+w) instead. Now we approximate
56
+ // √ by a linear Taylor expansion into h≈q(1+½w) so that the q's
57
+ // cancel each other in h-q. Expanding and simplifying further we
58
+ // get x=float2(p³/q,-p³/q-q). And using a second degree Taylor
59
+ // expansion instead: x=float2(k,-k-q) with k=(1-p³/q²)·p³/q
60
+ if ( abs (p)<0.001 )
61
+ {
62
+ float k = p3/q; // linear approx
63
+ //float k = (1.0-p3/q2)*p3/q; // quadratic approx
64
+ x = float2 (k,-k-q);
65
+ }
66
+ #endif
67
+
68
+ float2 uv = sign (x)*pow (abs (x), float2 (1.0 /3.0 , 1.0 /3.0 ));
69
+ float t = clamp ( uv.x+uv.y-kx, 0.0 , 1.0 );
70
+ float2 q = d+(c+b*t)*t;
71
+ res = dot2 (q);
72
+ sgn = cross2d (c+2.0 *b*t,q);
73
+ }
74
+ else
75
+ { // 3 roots
76
+ float z = sqrt (-p);
77
+ float v = acos (q/(p*z*2.0 ))/3.0 ;
78
+ float m = cos (v);
79
+ float n = sin (v)*1.732050808 ;
80
+ float3 t = clamp ( float3 (m+m,-n-m,n-m)*z-kx, 0.0 , 1.0 );
81
+ float2 qx=d+(c+b*t.x)*t.x; float dx=dot2 (qx), sx = cross2d (c+2.0 *b*t.x,qx);
82
+ float2 qy=d+(c+b*t.y)*t.y; float dy=dot2 (qy), sy = cross2d (c+2.0 *b*t.y,qy);
83
+ if ( dx<dy ) { res=dx; sgn=sx; } else {res=dy; sgn=sy; }
84
+ }
85
+
86
+ return sqrt ( res )*sign (sgn);
18
87
}
19
88
};
20
89
21
- struct QuadraticBezier
90
+ struct CubicBezier
22
91
{
23
- static QuadraticBezier construct ()
92
+ float2 a;
93
+ float2 b;
94
+ float2 c;
95
+ float2 d;
96
+ float thickness;
97
+
98
+ static CubicBezier construct (float2 a, float2 b, float2 c, float2 d, float thickness)
24
99
{
100
+ CubicBezier ret = { a, b, c, d, thickness };
101
+ return ret;
25
102
}
26
103
27
104
float signedDistance (float2 p)
28
105
{
106
+ return 0 ;
29
107
}
30
108
};
31
109
}
0 commit comments