@@ -14,27 +14,25 @@ namespace gpu {
14
14
namespace xpbd {
15
15
namespace XpbdImplKernels {
16
16
17
+ namespace mini = pbat::math::linalg::mini;
18
+
17
19
struct FInitializeNeoHookeanConstraint
18
20
{
19
21
PBAT_DEVICE void operator ()(GpuIndex c)
20
22
{
21
- using namespace pbat ::math::linalg:: mini;
23
+ using namespace mini ;
22
24
// Load vertex positions of element c
23
- GpuIndex const v[4 ] = {T[0 ][c], T[1 ][c], T[2 ][c], T[3 ][c]};
24
- SMatrix<GpuScalar, 3 , 4 > xc{};
25
- for (auto d = 0 ; d < 3 ; ++d)
26
- for (auto j = 0 ; j < 4 ; ++j)
27
- xc (d, j) = x[d][v[j]];
25
+ SMatrix<GpuIndex, 4 , 1 > v = FromBuffers<4 , 1 >(T, c);
26
+ SMatrix<GpuScalar, 3 , 4 > xc = FromBuffers (x, v.Transpose ());
28
27
// Compute shape matrix and its inverse
29
- SMatrix<GpuScalar, 3 , 3 > Ds = (xc.Slice <3 , 3 >(0 , 1 ) - Repeat<1 , 3 >(xc.Col (0 )));
30
- SMatrixView<GpuScalar, 3 , 3 > DmInvC (DmInv + 9 * c);
31
- DmInvC = Inverse (Ds);
28
+ SMatrix<GpuScalar, 3 , 3 > Ds = (xc.Slice <3 , 3 >(0 , 1 ) - Repeat<1 , 3 >(xc.Col (0 )));
29
+ SMatrixView<GpuScalar, 3 , 3 > DmInvC = FromFlatBuffer< 3 , 3 >(DmInv, c);
30
+ DmInvC = Inverse (Ds);
32
31
// Compute constraint compliance
33
- GpuScalar const tetVolume = Determinant (Ds) / GpuScalar{6 .};
34
- SMatrixView<GpuScalar, 2 , 1 > alphac{alpha + 2 * c};
35
- SMatrixView<GpuScalar, 2 , 1 > lamec{lame + 2 * c};
36
- alphac (0 ) = GpuScalar{1 .} / (lamec (0 ) * tetVolume);
37
- alphac (1 ) = GpuScalar{1 .} / (lamec (1 ) * tetVolume);
32
+ GpuScalar const tetVolume = Determinant (Ds) / GpuScalar{6 };
33
+ SMatrixView<GpuScalar, 2 , 1 > alphac = FromFlatBuffer<2 , 1 >(alpha, c);
34
+ SMatrixView<GpuScalar, 2 , 1 > lamec = FromFlatBuffer<2 , 1 >(lame, c);
35
+ alphac = GpuScalar{1 } / (lamec * tetVolume);
38
36
// Compute rest stability
39
37
gamma[c] = GpuScalar{1 .} + lamec (0 ) / lamec (1 );
40
38
}
@@ -69,13 +67,13 @@ struct FStableNeoHookeanConstraint
69
67
{
70
68
PBAT_DEVICE void Project (
71
69
GpuScalar C,
72
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 4 > const & gradC,
73
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 4 , 1 > const & minvc,
70
+ mini::SMatrix<GpuScalar, 3 , 4 > const & gradC,
71
+ mini::SMatrix<GpuScalar, 4 , 1 > const & minvc,
74
72
GpuScalar atilde,
75
73
GpuScalar& lambdac,
76
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 4 >& xc)
74
+ mini::SMatrix<GpuScalar, 3 , 4 >& xc)
77
75
{
78
- using namespace pbat ::math::linalg:: mini;
76
+ using namespace mini ;
79
77
GpuScalar dlambda =
80
78
-(C + atilde * lambdac) /
81
79
(minvc (0 ) * SquaredNorm (gradC.Col (0 )) + minvc (1 ) * SquaredNorm (gradC.Col (1 )) +
@@ -89,13 +87,13 @@ struct FStableNeoHookeanConstraint
89
87
90
88
PBAT_DEVICE void ProjectHydrostatic (
91
89
GpuIndex c,
92
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 4 , 1 > const & minvc,
90
+ mini::SMatrix<GpuScalar, 4 , 1 > const & minvc,
93
91
GpuScalar atilde,
94
92
GpuScalar gammac,
95
93
GpuScalar& lambdac,
96
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 4 >& xc)
94
+ mini::SMatrix<GpuScalar, 3 , 4 >& xc)
97
95
{
98
- using namespace pbat ::math::linalg:: mini;
96
+ using namespace mini ;
99
97
SMatrixView<GpuScalar, 3 , 3 > DmInvC (DmInv + 9 * c);
100
98
SMatrix<GpuScalar, 3 , 3 > F = (xc.Slice <3 , 3 >(0 , 1 ) - Repeat<1 , 3 >(xc.Col (0 ))) * DmInvC;
101
99
GpuScalar C = Determinant (F) - gammac;
@@ -111,12 +109,12 @@ struct FStableNeoHookeanConstraint
111
109
112
110
PBAT_DEVICE void ProjectDeviatoric (
113
111
GpuIndex c,
114
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 4 , 1 > const & minvc,
112
+ mini::SMatrix<GpuScalar, 4 , 1 > const & minvc,
115
113
GpuScalar atilde,
116
114
GpuScalar& lambdac,
117
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 4 >& xc)
115
+ mini::SMatrix<GpuScalar, 3 , 4 >& xc)
118
116
{
119
- using namespace pbat ::math::linalg:: mini;
117
+ using namespace mini ;
120
118
SMatrixView<GpuScalar, 3 , 3 > DmInvC (DmInv + 9 * c);
121
119
SMatrix<GpuScalar, 3 , 3 > F = (xc.Slice <3 , 3 >(0 , 1 ) - Repeat<1 , 3 >(xc.Col (0 ))) * DmInvC;
122
120
GpuScalar C = Norm (F);
@@ -128,34 +126,23 @@ struct FStableNeoHookeanConstraint
128
126
129
127
PBAT_DEVICE void operator ()(GpuIndex c)
130
128
{
131
- using namespace pbat ::math::linalg:: mini;
129
+ using namespace mini ;
132
130
133
131
// 1. Load constraint data in local memory
134
- GpuIndex const v[4 ] = {T[0 ][c], T[1 ][c], T[2 ][c], T[3 ][c]};
135
- SMatrix<GpuScalar, 3 , 4 > xc{};
136
- for (auto d = 0 ; d < 3 ; ++d)
137
- for (auto j = 0 ; j < 4 ; ++j)
138
- xc (d, j) = x[d][v[j]];
139
- SMatrix<GpuScalar, 4 , 1 > minvc{};
140
- for (auto j = 0 ; j < 4 ; ++j)
141
- minvc (j) = minv[v[j]];
142
- SMatrix<GpuScalar, 2 , 1 > lambdac{};
143
- lambdac (0 ) = lambda[2 * c];
144
- lambdac (1 ) = lambda[2 * c + 1 ];
145
- SMatrix<GpuScalar, 2 , 1 > atilde{};
146
- atilde (0 ) = alpha[2 * c] / dt2;
147
- atilde (1 ) = alpha[2 * c + 1 ] / dt2;
132
+ SMatrix<GpuIndex, 4 , 1 > v = FromBuffers<4 , 1 >(T, c);
133
+ SMatrix<GpuScalar, 3 , 4 > xc = FromBuffers (x, v.Transpose ());
134
+ SMatrix<GpuScalar, 4 , 1 > minvc = FromFlatBuffer (minv, v);
135
+ SMatrix<GpuScalar, 2 , 1 > lambdac = FromFlatBuffer<2 , 1 >(lambda, c);
136
+ SMatrix<GpuScalar, 2 , 1 > atilde = FromFlatBuffer<2 , 1 >(alpha, c);
137
+ atilde /= dt2;
148
138
149
139
// 2. Project elastic constraints
150
140
ProjectDeviatoric (c, minvc, atilde (0 ), lambdac (0 ), xc);
151
141
ProjectHydrostatic (c, minvc, atilde (1 ), gamma[c], lambdac (1 ), xc);
152
142
153
143
// 3. Update global "Lagrange" multipliers and positions
154
- lambda[2 * c] = lambdac (0 );
155
- lambda[2 * c + 1 ] = lambdac (1 );
156
- for (auto d = 0 ; d < 3 ; ++d)
157
- for (auto j = 0 ; j < 4 ; ++j)
158
- x[d][v[j]] = xc (d, j);
144
+ ToFlatBuffer (lambdac, lambda, c);
145
+ ToBuffers (xc, v.Transpose (), x);
159
146
}
160
147
161
148
std::array<GpuScalar*, 3 > x;
@@ -169,19 +156,18 @@ struct FStableNeoHookeanConstraint
169
156
GpuScalar dt2;
170
157
};
171
158
172
- PBAT_DEVICE pbat::math::linalg::mini::SMatrix<GpuScalar, 3 , 1 >
173
- PointOnPlane (auto const & X, auto const & P, auto const & n)
159
+ PBAT_DEVICE mini::SMatrix<GpuScalar, 3 , 1 > PointOnPlane (auto const & X, auto const & P, auto const & n)
174
160
{
175
- using namespace pbat ::math::linalg:: mini;
161
+ using namespace mini ;
176
162
GpuScalar const t = (n.Transpose () * (X - P))(0 , 0 );
177
163
SMatrix<GpuScalar, 3 , 1 > Xp = X - t * n;
178
164
return Xp;
179
165
}
180
166
181
- PBAT_DEVICE pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 1 >
167
+ PBAT_DEVICE mini::SMatrix<GpuScalar, 3 , 1 >
182
168
TriangleBarycentricCoordinates (auto const & AP, auto const & AB, auto const & AC)
183
169
{
184
- using namespace pbat ::math::linalg:: mini;
170
+ using namespace mini ;
185
171
GpuScalar const d00 = Dot (AB, AB);
186
172
GpuScalar const d01 = Dot (AB, AC);
187
173
GpuScalar const d11 = Dot (AC, AC);
@@ -204,15 +190,15 @@ struct FVertexTriangleContactConstraint
204
190
205
191
PBAT_DEVICE bool ProjectVertexTriangle (
206
192
GpuScalar minvv,
207
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 1 > const & minvf,
208
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 1 > const & xvt,
209
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 3 > const & xft,
210
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 3 > const & xf,
193
+ mini::SMatrix<GpuScalar, 3 , 1 > const & minvf,
194
+ mini::SMatrix<GpuScalar, 3 , 1 > const & xvt,
195
+ mini::SMatrix<GpuScalar, 3 , 3 > const & xft,
196
+ mini::SMatrix<GpuScalar, 3 , 3 > const & xf,
211
197
GpuScalar atildec,
212
198
GpuScalar& lambdac,
213
- pbat::math::linalg:: mini::SMatrix<GpuScalar, 3 , 1 >& xv)
199
+ mini::SMatrix<GpuScalar, 3 , 1 >& xv)
214
200
{
215
- using namespace pbat ::math::linalg:: mini;
201
+ using namespace mini ;
216
202
// Numerically zero inverse mass makes the Schur complement ill-conditioned/singular
217
203
if (minvv < GpuScalar{1e-10 })
218
204
return false ;
@@ -232,17 +218,17 @@ struct FVertexTriangleContactConstraint
232
218
// If xv doesn't project inside triangle, then we don't generate a contact response
233
219
// clang-format off
234
220
bool const bIsVertexInsideTriangle =
235
- (b (0 ) >= GpuScalar{0 . f }) and (b (0 ) <= GpuScalar{1 . f }) and
236
- (b (1 ) >= GpuScalar{0 . f }) and (b (1 ) <= GpuScalar{1 . f }) and
237
- (b (2 ) >= GpuScalar{0 . f }) and (b (2 ) <= GpuScalar{1 . f });
221
+ (b (0 ) >= GpuScalar{0 }) and (b (0 ) <= GpuScalar{1 }) and
222
+ (b (1 ) >= GpuScalar{0 }) and (b (1 ) <= GpuScalar{1 }) and
223
+ (b (2 ) >= GpuScalar{0 }) and (b (2 ) <= GpuScalar{1 });
238
224
// clang-format on
239
225
if (not bIsVertexInsideTriangle)
240
226
return false ;
241
227
242
228
// Project xv onto triangle's plane into xc
243
229
GpuScalar const C = Dot (n, xv - xf.Col (0 ));
244
230
// If xv is positively oriented w.r.t. triangles xf, there is no penetration
245
- if (C > GpuScalar{0 . })
231
+ if (C > GpuScalar{0 })
246
232
return false ;
247
233
// Prevent super violent projection for stability, i.e. if the collision constraint
248
234
// violation is already too large, we give up.
@@ -271,58 +257,32 @@ struct FVertexTriangleContactConstraint
271
257
return true ;
272
258
}
273
259
274
- PBAT_DEVICE void SetParticlePosition (
275
- GpuIndex v,
276
- pbat::math::linalg::mini::SMatrix<GpuScalar, 3 , 1 > const & xv,
277
- std::array<GpuScalar*, 3 > const & xx)
278
- {
279
- for (auto d = 0 ; d < 3 ; ++d)
280
- xx[d][v] = xv (d, 0 );
281
- }
282
-
283
- PBAT_DEVICE pbat::math::linalg::mini::SMatrix<GpuScalar, 3 , 1 >
284
- GetParticlePosition (GpuIndex v, std::array<GpuScalar*, 3 > const & xx)
285
- {
286
- using namespace pbat ::math::linalg::mini;
287
- SMatrix<GpuScalar, 3 , 1 > xv{};
288
- for (auto d = 0 ; d < 3 ; ++d)
289
- xv (d, 0 ) = xx[d][v];
290
- return xv;
291
- }
292
-
293
260
PBAT_DEVICE void operator ()(GpuIndex c)
294
261
{
295
- using namespace pbat ::math::linalg:: mini;
296
- GpuIndex vv = V[0 ][cpairs[c].first ]; // /< Colliding vertex
297
- GpuIndex vf[ 3 ] = {
262
+ using namespace mini ;
263
+ GpuIndex vv = V[0 ][cpairs[c].first ]; // /< Colliding vertex
264
+ SMatrix< GpuIndex, 3 , 1 > vf {
298
265
F[0 ][cpairs[c].second ],
299
266
F[1 ][cpairs[c].second ],
300
267
F[2 ][cpairs[c].second ]}; // /< Colliding triangle
301
268
302
- SMatrix<GpuScalar, 3 , 1 > xv = GetParticlePosition (vv, x);
303
- SMatrix<GpuScalar, 3 , 3 > xf{};
304
- for (auto j = 0 ; j < 3 ; ++j)
305
- xf.Col (j) = GetParticlePosition (vf[j], x);
306
-
307
- SMatrix<GpuScalar, 3 , 1 > xvt = GetParticlePosition (vv, xt);
308
- SMatrix<GpuScalar, 3 , 3 > xft{};
309
- for (auto j = 0 ; j < 3 ; ++j)
310
- xft.Col (j) = GetParticlePosition (vf[j], xt);
269
+ SMatrix<GpuScalar, 3 , 1 > xvt = FromBuffers<3 , 1 >(xt, vv);
270
+ SMatrix<GpuScalar, 3 , 1 > xv = FromBuffers<3 , 1 >(x, vv);
271
+ SMatrix<GpuScalar, 3 , 3 > xft = FromBuffers (xt, vf.Transpose ());
272
+ SMatrix<GpuScalar, 3 , 3 > xf = FromBuffers (x, vf.Transpose ());
311
273
312
- GpuScalar const minvv = minv[vv];
313
- SMatrix<GpuScalar, 3 , 1 > minvf{};
314
- for (auto j = 0 ; j < 3 ; ++j)
315
- minvf (j, 0 ) = minv[vf[j]];
316
- GpuScalar atildec = alpha[c] / dt2;
317
- GpuScalar lambdac = lambda[c];
274
+ GpuScalar const minvv = minv[vv];
275
+ SMatrix<GpuScalar, 3 , 1 > minvf = FromFlatBuffer (minv, vf);
276
+ GpuScalar atildec = alpha[c] / dt2;
277
+ GpuScalar lambdac = lambda[c];
318
278
319
279
// 2. Project collision constraint
320
280
if (not ProjectVertexTriangle (minvv, minvf, xvt, xft, xf, atildec, lambdac, xv))
321
281
return ;
322
282
323
283
// 3. Update global positions
324
284
// lambda[c] = lambdac;
325
- SetParticlePosition (vv, xv, x);
285
+ ToBuffers ( xv, x, vv );
326
286
}
327
287
328
288
std::array<GpuScalar*, 3 > x; // /< Current positions
0 commit comments