@@ -41,13 +41,9 @@ float AngleBetween(glm::vec3 a, glm::vec3 b) {
41
41
glm::vec4 CircularTangent (const glm::vec3& tangent, const glm::vec3& edgeVec) {
42
42
const glm::vec3 dir = SafeNormalize (tangent);
43
43
44
- float weight = glm::abs (glm::dot (dir, SafeNormalize (edgeVec)));
45
- if (weight == 0 ) {
46
- weight = 1 ;
47
- }
44
+ float weight = glm::max (0 .5f , glm::dot (dir, SafeNormalize (edgeVec)));
48
45
// Quadratic weighted bezier for circular interpolation
49
- const glm::vec4 bz2 =
50
- weight * glm::vec4 (dir * glm::length (edgeVec) / (2 * weight), 1 );
46
+ const glm::vec4 bz2 = glm::vec4 (dir * 0 .5f * glm::length (edgeVec), weight);
51
47
// Equivalent cubic weighted bezier
52
48
const glm::vec4 bz3 = glm::mix (glm::vec4 (0 , 0 , 0 , 1 ), bz2, 2 / 3 .0f );
53
49
// Convert from homogeneous form to geometric form
@@ -82,53 +78,72 @@ struct SmoothBezier {
82
78
struct InterpTri {
83
79
const Manifold::Impl* impl;
84
80
85
- glm::vec4 Homogeneous (glm::vec4 v) const {
81
+ static glm::vec4 Homogeneous (glm::vec4 v) {
86
82
v.x *= v.w ;
87
83
v.y *= v.w ;
88
84
v.z *= v.w ;
89
85
return v;
90
86
}
91
87
92
- glm::vec4 Homogeneous (glm::vec3 v) const { return glm::vec4 (v, 1 .0f ); }
88
+ static glm::vec4 Homogeneous (glm::vec3 v) { return glm::vec4 (v, 1 .0f ); }
93
89
94
- glm::vec3 HNormalize (glm::vec4 v) const {
90
+ static glm::vec3 HNormalize (glm::vec4 v) {
95
91
return v.w == 0 ? v : (glm::vec3 (v) / v.w );
96
92
}
97
93
98
- glm::vec4 Scale (glm::vec4 v, float scale) const {
94
+ static glm::vec4 Scale (glm::vec4 v, float scale) {
99
95
return glm::vec4 (scale * glm::vec3 (v), v.w );
100
96
}
101
97
102
- glm::vec4 Bezier (glm::vec3 point, glm::vec4 tangent) const {
98
+ static glm::vec4 Bezier (glm::vec3 point, glm::vec4 tangent) {
103
99
return Homogeneous (glm::vec4 (point, 0 ) + tangent);
104
100
}
105
101
106
- glm::mat2x4 CubicBezier2Linear (glm::vec4 p0, glm::vec4 p1, glm::vec4 p2 ,
107
- glm::vec4 p3, float x) const {
102
+ static glm::mat2x4 CubicBezier2Linear (glm::vec4 p0, glm::vec4 p1,
103
+ glm::vec4 p2, glm::vec4 p3, float x) {
108
104
glm::mat2x4 out;
109
105
glm::vec4 p12 = glm::mix (p1, p2, x);
110
106
out[0 ] = glm::mix (glm::mix (p0, p1, x), p12, x);
111
107
out[1 ] = glm::mix (p12, glm::mix (p2, p3, x), x);
112
108
return out;
113
109
}
114
110
115
- glm::vec3 BezierPoint (glm::mat2x4 points, float x) const {
111
+ static glm::vec3 BezierPoint (glm::mat2x4 points, float x) {
116
112
return HNormalize (glm::mix (points[0 ], points[1 ], x));
117
113
}
118
114
119
- glm::vec3 BezierTangent (glm::mat2x4 points) const {
115
+ static glm::vec3 BezierTangent (glm::mat2x4 points) {
120
116
return SafeNormalize (HNormalize (points[1 ]) - HNormalize (points[0 ]));
121
117
}
122
118
123
- glm::vec3 RotateFromTo (glm::vec3 v, glm::quat start, glm::quat end) const {
119
+ static glm::vec3 RotateFromTo (glm::vec3 v, glm::quat start, glm::quat end) {
124
120
return end * glm::conjugate (start) * v;
125
121
}
126
122
127
- glm::mat2x4 Bezier2Bezier (const glm::mat2x3& corners,
128
- const glm::mat2x4& tangentsX,
129
- const glm::mat2x4& tangentsY, float x,
130
- const glm::bvec2& pointedEnds,
131
- const glm::vec3& anchor) const {
123
+ static glm::quat Slerp (const glm::quat& x, const glm::quat& y, float a,
124
+ bool longWay) {
125
+ glm::quat z = y;
126
+ float cosTheta = glm::dot (x, y);
127
+
128
+ // Take the long way around the sphere only when requested
129
+ if ((cosTheta < 0 ) != longWay) {
130
+ z = -y;
131
+ cosTheta = -cosTheta;
132
+ }
133
+
134
+ if (cosTheta > 1 .0f - glm::epsilon<float >()) {
135
+ return glm::lerp (x, z, a); // for numerical stability
136
+ } else {
137
+ float angle = glm::acos (cosTheta);
138
+ return (glm::sin ((1 .0f - a) * angle) * x + glm::sin (a * angle) * z) /
139
+ glm::sin (angle);
140
+ }
141
+ }
142
+
143
+ static glm::mat2x4 Bezier2Bezier (const glm::mat2x3& corners,
144
+ const glm::mat2x4& tangentsX,
145
+ const glm::mat2x4& tangentsY, float x,
146
+ const glm::vec3& anchor) {
132
147
const glm::mat2x4 bez = CubicBezier2Linear (
133
148
Homogeneous (corners[0 ]), Bezier (corners[0 ], tangentsX[0 ]),
134
149
Bezier (corners[1 ], tangentsX[1 ]), Homogeneous (corners[1 ]), x);
@@ -151,45 +166,39 @@ struct InterpTri {
151
166
const glm::quat q1 =
152
167
glm::quat_cast (glm::mat3 (nTangentsX[1 ], biTangents[1 ],
153
168
glm::cross (nTangentsX[1 ], biTangents[1 ])));
154
- const glm::quat qTmp = glm::slerp (q0, q1, x);
169
+ const glm::vec3 edge = corners[1 ] - corners[0 ];
170
+ const bool longWay =
171
+ glm::dot (nTangentsX[0 ], edge) + glm::dot (nTangentsX[1 ], edge) < 0 ;
172
+ const glm::quat qTmp = Slerp (q0, q1, x, longWay);
155
173
const glm::quat q =
156
174
glm::rotation (qTmp * glm::vec3 (1 , 0 , 0 ), tangent) * qTmp;
157
175
158
- const glm::vec3 end0 = pointedEnds[0 ]
159
- ? glm::vec3 (0 )
160
- : RotateFromTo (glm::vec3 (tangentsY[0 ]), q0, q);
161
- const glm::vec3 end1 = pointedEnds[1 ]
162
- ? glm::vec3 (0 )
163
- : RotateFromTo (glm::vec3 (tangentsY[1 ]), q1, q);
164
- const glm::vec3 delta = glm::mix (end0, end1, x);
176
+ const glm::vec3 delta =
177
+ glm::mix (RotateFromTo (glm::vec3 (tangentsY[0 ]), q0, q),
178
+ RotateFromTo (glm::vec3 (tangentsY[1 ]), q1, q), x);
165
179
const float deltaW = glm::mix (tangentsY[0 ].w , tangentsY[1 ].w , x);
166
180
167
181
return {Homogeneous (end), glm::vec4 (delta, deltaW)};
168
182
}
169
183
170
- glm::vec3 Bezier2D (const glm::mat4x3& corners, const glm::mat4& tangentsX,
171
- const glm::mat4& tangentsY, float x, float y,
172
- const glm::vec3& centroid, bool isTriangle) const {
173
- glm::mat2x4 bez0 = Bezier2Bezier (
174
- {corners[0 ], corners[1 ]}, {tangentsX[0 ], tangentsX[1 ]},
175
- {tangentsY[0 ], tangentsY[1 ]}, x, {isTriangle, false }, centroid);
176
- glm::mat2x4 bez1 = Bezier2Bezier (
177
- {corners[2 ], corners[3 ]}, {tangentsX[2 ], tangentsX[3 ]},
178
- {tangentsY[2 ], tangentsY[3 ]}, 1 - x, {false , isTriangle}, centroid);
179
-
180
- const float flatLen =
181
- isTriangle ? x * glm::length (corners[1 ] - corners[2 ])
182
- : glm::length (glm::mix (corners[0 ], corners[1 ], x) -
183
- glm::mix (corners[3 ], corners[2 ], x));
184
- const float scale = glm::length (glm::vec3 (bez0[0 ] - bez1[0 ])) / flatLen;
185
-
186
- const glm::mat2x4 bez = CubicBezier2Linear (
187
- bez0[0 ], Bezier (glm::vec3 (bez0[0 ]), Scale (bez0[1 ], scale)),
188
- Bezier (glm::vec3 (bez1[0 ]), Scale (bez1[1 ], scale)), bez1[0 ], y);
184
+ static glm::vec3 Bezier2D (const glm::mat4x3& corners,
185
+ const glm::mat4& tangentsX,
186
+ const glm::mat4& tangentsY, float x, float y,
187
+ const glm::vec3& centroid) {
188
+ glm::mat2x4 bez0 =
189
+ Bezier2Bezier ({corners[0 ], corners[1 ]}, {tangentsX[0 ], tangentsX[1 ]},
190
+ {tangentsY[0 ], tangentsY[1 ]}, x, centroid);
191
+ glm::mat2x4 bez1 =
192
+ Bezier2Bezier ({corners[2 ], corners[3 ]}, {tangentsX[2 ], tangentsX[3 ]},
193
+ {tangentsY[2 ], tangentsY[3 ]}, 1 - x, centroid);
194
+
195
+ const glm::mat2x4 bez =
196
+ CubicBezier2Linear (bez0[0 ], Bezier (glm::vec3 (bez0[0 ]), bez0[1 ]),
197
+ Bezier (glm::vec3 (bez1[0 ]), bez1[1 ]), bez1[0 ], y);
189
198
return BezierPoint (bez, y);
190
199
}
191
200
192
- void operator ()(thrust::tuple<glm::vec3&, Barycentric> inOut) {
201
+ void operator ()(thrust::tuple<glm::vec3&, Barycentric> inOut) const {
193
202
glm::vec3& pos = thrust::get<0 >(inOut);
194
203
const int tri = thrust::get<1 >(inOut).tri ;
195
204
const glm::vec4 uvw = thrust::get<1 >(inOut).uvw ;
@@ -226,12 +235,17 @@ struct InterpTri {
226
235
const int j = Next3 (i);
227
236
const int k = Prev3 (i);
228
237
const float x = uvw[k] / (1 - uvw[i]);
229
- const glm::vec3 p =
230
- Bezier2D ({corners[i], corners[j], corners[k], corners[i]},
231
- {tangentR[i], tangentL[j], tangentR[k], tangentL[i]},
232
- {tangentL[i], tangentR[j], tangentL[k], tangentR[i]},
233
- 1 - uvw[i], x, centroid, true );
234
- posH += Homogeneous (glm::vec4 (p, uvw[i]));
238
+
239
+ const glm::mat2x4 bez =
240
+ Bezier2Bezier ({corners[j], corners[k]}, {tangentR[j], tangentL[k]},
241
+ {tangentL[j], tangentR[k]}, x, centroid);
242
+
243
+ const glm::mat2x4 bez1 = CubicBezier2Linear (
244
+ bez[0 ], Bezier (glm::vec3 (bez[0 ]), bez[1 ]),
245
+ Bezier (corners[i], glm::mix (tangentR[i], tangentL[i], x)),
246
+ Homogeneous (corners[i]), uvw[i]);
247
+ const glm::vec3 p = BezierPoint (bez1, uvw[i]);
248
+ posH += Homogeneous (glm::vec4 (p, uvw[j] * uvw[k]));
235
249
}
236
250
} else { // quad
237
251
const glm::mat4 tangentsX = {
@@ -248,12 +262,12 @@ struct InterpTri {
248
262
const float x = uvw[1 ] + uvw[2 ];
249
263
const float y = uvw[2 ] + uvw[3 ];
250
264
const glm::vec3 pX =
251
- Bezier2D (corners, tangentsX, tangentsY, x, y, centroid, false );
265
+ Bezier2D (corners, tangentsX, tangentsY, x, y, centroid);
252
266
const glm::vec3 pY =
253
267
Bezier2D ({corners[1 ], corners[2 ], corners[3 ], corners[0 ]},
254
268
{tangentsY[1 ], tangentsY[2 ], tangentsY[3 ], tangentsY[0 ]},
255
269
{tangentsX[1 ], tangentsX[2 ], tangentsX[3 ], tangentsX[0 ]}, y,
256
- 1 - x, centroid, false );
270
+ 1 - x, centroid);
257
271
posH += Homogeneous (glm::vec4 (pX, x * (1 - x)));
258
272
posH += Homogeneous (glm::vec4 (pY, y * (1 - y)));
259
273
}
@@ -885,7 +899,7 @@ void Manifold::Impl::CreateTangents(std::vector<Smoothness> sharpenedEdges) {
885
899
&triIsFlatFace](int v) {
886
900
auto it = vertTangents.find (v);
887
901
if (it == vertTangents.end ()) {
888
- fixedHalfedge[vertHalfedge[v]] == true ;
902
+ fixedHalfedge[vertHalfedge[v]] = true ;
889
903
return ;
890
904
}
891
905
const std::vector<Pair>& vert = it->second ;
@@ -918,7 +932,7 @@ void Manifold::Impl::CreateTangents(std::vector<Smoothness> sharpenedEdges) {
918
932
}
919
933
});
920
934
} else { // Sharpen vertex uniformly
921
- fixedHalfedge[vertHalfedge[v]] == true ;
935
+ fixedHalfedge[vertHalfedge[v]] = true ;
922
936
float smoothness = 0 ;
923
937
float denom = 0 ;
924
938
for (const Pair& pair : vert) {
0 commit comments