PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
Kernels.h
1#ifndef PBAT_SIM_XPBD_KERNELS_H
2#define PBAT_SIM_XPBD_KERNELS_H
3
8
9#include <algorithm>
10
11namespace pbat {
12namespace sim {
13namespace xpbd {
14namespace kernels {
15
16namespace mini = pbat::math::linalg::mini;
17
31template <
32 mini::CMatrix TMatrixXT,
33 mini::CMatrix TMatrixVT,
34 mini::CMatrix TMatrixA,
35 class ScalarType = typename TMatrixXT::ScalarType>
36PBAT_HOST_DEVICE mini::SVector<ScalarType, TMatrixXT::kRows> InitialPosition(
37 TMatrixXT const& xt,
38 TMatrixVT const& vt,
39 TMatrixA const& aext,
40 ScalarType dt,
41 ScalarType dt2)
42{
43 return xt + dt * vt + dt2 * aext;
44}
45
72template <
73 mini::CMatrix TMatrixMinv,
74 mini::CMatrix TMatrixDmInv,
75 mini::CMatrix TMatrixAlphaT,
76 mini::CMatrix TMatrixGamma,
77 mini::CMatrix TMatrixXTC,
78 mini::CMatrix TMatrixL,
79 mini::CMatrix TMatrixXC,
80 class ScalarType = typename TMatrixMinv::ScalarType>
81PBAT_HOST_DEVICE void ProjectBlockNeoHookean(
82 TMatrixMinv const& minvc,
83 TMatrixDmInv const& DmInv,
84 ScalarType gammaSNHc,
85 TMatrixAlphaT atildec,
86 TMatrixGamma gammac,
87 TMatrixXTC const& xtc,
88 TMatrixL& lambdac,
89 TMatrixXC& xc)
90{
91 using namespace mini;
92#if defined(CUDART_VERSION)
93 #pragma nv_diag_suppress 174
94#endif
95 // Compute deviatoric+hydrostatic elasticity
96 SMatrix<ScalarType, 3, 3> F = (xc.template Slice<3, 3>(0, 1) - Repeat<1, 3>(xc.Col(0))) * DmInv;
97 ScalarType CD = Norm(F);
98 SMatrix<ScalarType, 3, 4> gradCD{};
99 gradCD.template Slice<3, 3>(0, 1) = (F * DmInv.Transpose()) / (CD /*+ 1e-8*/);
100 gradCD.Col(0) = -(gradCD.Col(1) + gradCD.Col(2) + gradCD.Col(3));
101 ScalarType CH = Determinant(F) - gammaSNHc;
102 SMatrix<ScalarType, 3, 3> PH{};
103 PH.Col(0) = Cross(F.Col(1), F.Col(2));
104 PH.Col(1) = Cross(F.Col(2), F.Col(0));
105 PH.Col(2) = Cross(F.Col(0), F.Col(1));
106 SMatrix<ScalarType, 3, 4> gradCH{};
107 gradCH.template Slice<3, 3>(0, 1) = PH * DmInv.Transpose();
108 gradCH.Col(0) = -(gradCH.Col(1) + gradCH.Col(2) + gradCH.Col(3));
109#if defined(CUDART_VERSION)
110 #pragma nv_diag_default 174
111#endif
112 // Construct 2x2 constraint block system
113 SVector<ScalarType, 2> b{
114 -(CD + atildec(0) * lambdac(0) + gammac(0) * Dot(gradCD, xc - xtc)),
115 -(CH + atildec(1) * lambdac(1) + gammac(1) * Dot(gradCH, xc - xtc))};
116 SVector<ScalarType, 2> D = Ones<ScalarType, 2, 1>() + gammac;
117 SMatrix<ScalarType, 2, 2> A{};
118 A(0, 0) =
119 D(0) * (minvc(0) * SquaredNorm(gradCD.Col(0)) + minvc(1) * SquaredNorm(gradCD.Col(1)) +
120 minvc(2) * SquaredNorm(gradCD.Col(2)) + minvc(3) * SquaredNorm(gradCD.Col(3))) +
121 atildec(0);
122 A(1, 1) =
123 D(1) * (minvc(0) * SquaredNorm(gradCH.Col(0)) + minvc(1) * SquaredNorm(gradCH.Col(1)) +
124 minvc(2) * SquaredNorm(gradCH.Col(2)) + minvc(3) * SquaredNorm(gradCH.Col(3))) +
125 atildec(1);
126 A(0, 1) =
127 (minvc(0) * Dot(gradCD.Col(0), gradCH.Col(0)) +
128 minvc(1) * Dot(gradCD.Col(1), gradCH.Col(1)) +
129 minvc(2) * Dot(gradCD.Col(2), gradCH.Col(2)) +
130 minvc(3) * Dot(gradCD.Col(3), gradCH.Col(3)));
131 A(1, 0) = A(0, 1);
132 A(0, 1) *= D(0);
133 A(1, 0) *= D(1);
134 // Project block constraint
135 SVector<ScalarType, 2> dlambda = Inverse(A) * b;
136 lambdac += dlambda;
137 pbat::common::ForRange<0, 4>([&]<auto i>() {
138 xc.Col(i) += minvc(i) * (dlambda(0) * gradCD.Col(i) + dlambda(1) * gradCH.Col(i));
139 });
140}
141
162template <
163 mini::CMatrix TMatrixXVT,
164 mini::CMatrix TMatrixXFT,
165 mini::CMatrix TMatrixXF,
166 mini::CMatrix TMatrixXV,
167 class ScalarType = typename TMatrixXV::ScalarType>
168PBAT_HOST_DEVICE bool ProjectVertexTriangle(
169 ScalarType minvv,
170 TMatrixXVT const& xvt,
171 TMatrixXFT const& xft,
172 TMatrixXF const& xf,
173 ScalarType muC,
174 ScalarType muS,
175 ScalarType muD,
176 ScalarType atildec,
177 ScalarType gammac,
178 ScalarType& lambdac,
179 TMatrixXV& xv)
180{
181 using namespace mini;
182 // Numerically zero inverse mass makes the Schur complement ill-conditioned/singular
183 if (minvv < ScalarType(1e-10))
184 return false;
185
186 // Compute triangle normal
187 SMatrix<ScalarType, 3, 1> T1 = xf.Col(1) - xf.Col(0);
188 SMatrix<ScalarType, 3, 1> T2 = xf.Col(2) - xf.Col(0);
189 SMatrix<ScalarType, 3, 1> n = Cross(T1, T2);
190 ScalarType const doublearea = Norm(n);
191 bool const bIsTriangleDegenerate = doublearea <= ScalarType(1e-8);
192 if (bIsTriangleDegenerate)
193 return false;
194
195 n /= doublearea;
196 using namespace pbat::geometry;
197 SMatrix<ScalarType, 3, 1> xc = ClosestPointQueries::PointOnPlane(xv, xf.Col(0), n);
198 // Check if xv projects to the triangle's interior by checking its barycentric coordinates
199 SMatrix<ScalarType, 3, 1> b =
200 IntersectionQueries::TriangleBarycentricCoordinates(xc - xf.Col(0), T1, T2);
201 // If xv doesn't project inside triangle, then we don't generate a contact response
202 // clang-format off
203 bool const bIsVertexInsideTriangle =
204 (b(0) >= ScalarType(0)) and (b(0) <= ScalarType(1)) and
205 (b(1) >= ScalarType(0)) and (b(1) <= ScalarType(1)) and
206 (b(2) >= ScalarType(0)) and (b(2) <= ScalarType(1));
207 // clang-format on
208 if (not bIsVertexInsideTriangle)
209 return false;
210
211 // Project xv onto triangle's plane into xc
212 ScalarType const C = muC * Dot(n, xv - xf.Col(0));
213 // If xv is positively oriented w.r.t. triangles xf, there is no penetration
214 if (C > ScalarType(0))
215 return false;
216 // Prevent super violent projection for stability, i.e. if the collision constraint
217 // violation is already too large, we give up.
218 // if (C < -1e-2)
219 // return false;
220
221 // Project constraints:
222 // We assume that the triangle is static (although it is not), so that the gradient is n for
223 // the vertex.
224
225 // Collision constraint
226 ScalarType const D = ScalarType(1) + gammac;
227 ScalarType dlambda =
228 -(C + atildec * lambdac + gammac * Dot(n, xv - xvt)) / (D * minvv + atildec);
229 SMatrix<ScalarType, 3, 1> dx = dlambda * minvv * n;
230 xv += dx;
231 lambdac += dlambda;
232
233 // Friction constraint (see https://dl.acm.org/doi/10.1145/2601097.2601152)
234 ScalarType const d = Norm(dx);
235 dx = (xv - xvt) - (xf * b - xft * b);
236 dx = dx - n * n.Transpose() * dx;
237 ScalarType const dxd = Norm(dx);
238 if (dxd > muS * d)
239 {
240 using namespace std;
241 dx *= min(muD * d / dxd, ScalarType(1));
242 }
243
244 xv += dx;
245 return true;
246}
247
258template <
259 mini::CMatrix TMatrixXT,
260 mini::CMatrix TMatrixX,
261 class ScalarType = typename TMatrixXT::ScalarType>
262PBAT_HOST_DEVICE mini::SVector<ScalarType, TMatrixXT::kRows>
263IntegrateVelocity(TMatrixXT const& xt, TMatrixX const& x, ScalarType dt)
264{
265 return (x - xt) / dt;
266}
267
268} // namespace kernels
269} // namespace xpbd
270} // namespace sim
271} // namespace pbat
272
273#endif // PBAT_SIM_XPBD_KERNELS_H
This file contains functions to answer closest point queries.
Compile-time for loops.
This file contains functions to answer intersection queries.
This file includes all the mini linear algebra headers.
constexpr void ForRange(F &&f)
Compile-time for loop over a range of values.
Definition ConstexprFor.h:55
Mini linear algebra related functionality.
Definition Assign.h:12
PBAT's (Extended) Position-Based Dynamics (XPBD) bender2015position API.
Definition Data.cpp:13
PBAT simulation algorithms.
The main namespace of the library.
Definition Aliases.h:15