7 #include "imstkPbdContactConstraint.h" 8 #include "imstkCollisionUtils.h" 45 case (SolverType::PBD):
48 case (SolverType::xPBD):
51 dlambda = -(c + alpha *
m_lambda) / (w + alpha);
58 const double invMass = bodies.getInvMass(
m_particles[i]);
62 const Vec3d p = dlambda *
m_dcdx[i];
63 const Vec3d dx = p * invMass;
66 if (bodies.getBodyType(
m_particles[i]) == PbdBody::Type::RIGID)
69 const Mat3d& invInteria = bodies.getInvInertia(
m_particles[i]);
71 Vec3d rot = m_r[i].cross(p);
73 rot = q.inverse()._transformVector(rot);
74 rot = invInteria * rot;
75 rot = q._transformVector(rot);
80 const double phi = rot.norm();
86 const Quatd dq = Quatd(0.0,
90 q.coeffs() += dq.coeffs() * 0.5;
100 if (!m_correctVelocity)
106 const Vec3d contactNormal =
m_dcdx[0].normalized();
109 const Vec3d relativeVelocity = computeRelativeVelocity(bodies);
110 const double vNMag = contactNormal.dot(relativeVelocity);
111 const Vec3d vN = vNMag * contactNormal;
112 const Vec3d vT = relativeVelocity - vN;
113 const double vTMag = vT.norm();
123 const Vec3d dV = (vT / vTMag) * std::min(m_friction *
getForce(dt) * dt, vTMag) +
124 contactNormal * (-vNMag + std::min(-m_restitution * vNMag, 0.0));
137 const Vec3d p = dV / w;
140 const double invMass = bodies.getInvMass(
m_particles[i]);
143 bodies.getVelocity(
m_particles[i]) += p * invMass * m_weights[i];
145 if (bodies.getBodyType(
m_particles[i]) == PbdBody::Type::RIGID)
147 const Mat3d& invInteria = bodies.getInvInertia(
m_particles[i]);
148 const Quatd& orientation = bodies.getOrientation(
m_particles[i]);
151 Vec3d rot = m_r[i].cross(p);
152 rot = orientation.inverse()._transformVector(rot);
153 rot = invInteria * rot;
154 rot = orientation._transformVector(rot);
165 const Vec3d contactPtOnBody,
167 const double compliance)
171 m_r[0] = contactPtOnBody - state.getPosition(bodyId);
176 setCompliance(compliance);
180 PbdTriangleToBodyConstraint::computeInterpolantsAndContact(
const PbdState& bodies,
181 std::vector<double>& weights, Vec3d& contactNormal,
double& depth)
const 183 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
184 const Vec3d& x1 = bodies.getPosition(
m_particles[1]);
185 const Vec3d& x2 = bodies.getPosition(
m_particles[2]);
186 const Vec3d& x3 = bodies.getPosition(
m_particles[3]);
189 const Vec3d p = bodyPos + m_r[0];
192 const Vec3d bary = baryCentric(p, x1, x2, x3);
200 weights[1] = bary[0];
201 weights[2] = bary[1];
202 weights[3] = bary[2];
205 if (weights[1] < 0.0 || weights[2] < 0.0 || weights[3] < 0.0)
211 contactNormal = (x2 - x1).cross(x3 - x1).normalized();
213 depth = (p - x1).dot(contactNormal);
221 std::vector<Vec3d>& n)
223 Vec3d normal = Vec3d::Zero();
225 if (!computeInterpolantsAndContact(bodies, m_weights, normal, depth))
240 n[1] = -m_weights[1] * normal;
241 n[2] = -m_weights[2] * normal;
242 n[3] = -m_weights[3] * normal;
250 PbdTriangleToBodyConstraint::computeRelativeVelocity(
PbdState& bodies)
252 Vec3d normal = Vec3d::Zero();
254 if (!computeInterpolantsAndContact(bodies, m_weights, normal, depth))
256 return Vec3d::Zero();
258 m_weights[0] = -m_weights[0];
260 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
262 const Vec3d contactPt = bodyPos + m_r[0];
266 const Vec3d& v1 = bodies.getPosition(
m_particles[1]);
268 const Vec3d& v2 = bodies.getPosition(
m_particles[2]);
270 const Vec3d& v3 = bodies.getPosition(
m_particles[3]);
271 const Vec3d v123 = v1 * m_weights[1] + v2 * m_weights[2] + v3 * m_weights[3];
281 const Vec3d contactPtOnBody,
283 const double compliance)
287 m_r[0] = contactPtOnBody - state.getPosition(bodyId);
291 setCompliance(compliance);
297 std::vector<Vec3d>& n)
299 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
302 const Vec3d p = bodyPos + m_r[0];
305 const Vec3d& x1 = bodies.getPosition(
m_particles[1]);
307 const Vec3d diff = x1 - p;
315 const Vec3d normal = diff / c;
326 PbdVertexToBodyConstraint::computeRelativeVelocity(
PbdState& bodies)
328 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
330 const Vec3d contactPt = bodyPos + m_r[0];
337 const Vec3d& v1 = bodies.getVelocity(
m_particles[1]);
345 const Vec3d contactPtOnBody,
347 const double compliance)
351 m_r[0] = contactPtOnBody - state.getPosition(bodyId);
355 setCompliance(compliance);
359 PbdEdgeToBodyConstraint::computeInterpolantsAndContact(
const PbdState& bodies,
360 std::vector<double>& weights, Vec3d& normal,
double& depth)
const 362 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
365 const Vec3d p = bodyPos + m_r[0];
368 const Vec3d& x1 = bodies.getPosition(
m_particles[1]);
369 const Vec3d& x2 = bodies.getPosition(
m_particles[2]);
371 const Vec3d ab = x2 - x1;
372 const double length = ab.norm();
377 const Vec3d dir1 = ab / length;
380 const Vec3d diff = p - x1;
381 const double p1 = dir1.dot(diff);
382 if (p1 < 0.0 || p1 > length)
387 const Vec3d diff1 = diff - p1 * dir1;
388 const double l = diff1.norm();
394 const double u = p1 / length;
399 weights[1] = (1.0 - u);
409 std::vector<Vec3d>& n)
411 Vec3d normal = Vec3d::Zero();
413 if (!computeInterpolantsAndContact(bodies, m_weights, normal, depth))
422 n[1] = -m_weights[1] * normal;
423 n[2] = -m_weights[2] * normal;
431 PbdEdgeToBodyConstraint::computeRelativeVelocity(
PbdState& bodies)
433 Vec3d normal = Vec3d::Zero();
435 if (!computeInterpolantsAndContact(bodies, m_weights, normal, depth))
437 return Vec3d::Zero();
439 m_weights[0] = -m_weights[0];
441 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
443 const Vec3d contactPt = bodyPos + m_r[0];
447 const Vec3d& v1 = bodies.getPosition(
m_particles[1]);
449 const Vec3d& v2 = bodies.getPosition(
m_particles[2]);
450 const Vec3d v12 = v1 * m_weights[1] + v2 * m_weights[2];
457 std::vector<Vec3d>& n)
460 const Vec3d& bodyPos0 = bodies.getPosition(
m_particles[0]);
462 if (bodies.getBodyType(
m_particles[0]) != PbdBody::Type::DEFORMABLE)
464 m_r[0] = bodies.getOrientation(
m_particles[0])._transformVector(m_rest_r[0]);
468 const Vec3d& bodyPos1 = bodies.getPosition(
m_particles[1]);
470 if (bodies.getBodyType(
m_particles[1]) != PbdBody::Type::DEFORMABLE)
472 m_r[1] = bodies.getOrientation(
m_particles[1])._transformVector(m_rest_r[1]);
477 Vec3d diff = p1 - p0;
478 const double length = diff.norm();
486 n[0] = diff.normalized();
498 std::vector<Vec3d>& n)
500 const Vec3d& bodyPos0 = bodies.getPosition(
m_particles[0]);
501 m_r[0] = bodies.getOrientation(
m_particles[0])._transformVector(m_rest_r[0]);
502 const Vec3d p0 = bodyPos0 + m_r[0];
504 const Vec3d& bodyPos1 = bodies.getPosition(
m_particles[1]);
505 m_r[1] = bodies.getOrientation(
m_particles[1])._transformVector(m_rest_r[1]);
506 const Vec3d p1 = bodyPos1 + m_r[1];
508 const Vec3d diff = p1 - p0;
510 c = diff.dot(m_contactNormal);
513 n[0] = -m_contactNormal;
515 n[1] = m_contactNormal;
522 double& c, std::vector<Vec3d>& n)
524 const Vec3d& bodyPos = bodies.getPosition(
m_particles[0]);
525 const Quatd& bodyOrientation = bodies.getOrientation(
m_particles[0]);
526 const Vec3d p = bodyPos + bodyOrientation._transformVector(m_p_rest);
527 const Vec3d q = bodyPos + bodyOrientation._transformVector(m_q_rest);
530 const Vec3d dir = (q - p).normalized();
532 const Vec3d& pt = bodies.getPosition(
m_particles[1]);
534 const Vec3d diff = pt - q;
535 const double l = diff.dot(dir);
536 const Vec3d dist = diff - l * dir;
538 n[1] = dist.normalized();
541 m_r[0] = (pt - dist) - bodyPos;
std::vector< Vec3d > m_dcdx
Normalized constraint gradients (per particle)
void initConstraint(const PbdState &state, const PbdParticleId &bodyId, const Vec3d contactPtOnBody, const PbdParticleId &x0, const PbdParticleId &x1, const double compliance=0.0)
Initialize the constraint.
std::pair< int, int > PbdParticleId
Index pair that refers to a particle in a PbdState. Index 0 is the body id, Index 1 is the particle i...
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &n) override
Compute value and gradient of the constraint.
double m_lambda
Lagrange multiplier.
std::vector< PbdParticleId > m_particles
body, particle index
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &n) override
Compute value and gradient of the constraint.
void projectConstraint(PbdState &bodies, const double dt, const SolverType &type) override
Update positions by projecting constraints.
double computeGeneralizedInvMass(const PbdState &bodies, const size_t particleIndex) const
Compute generalized inverse mass of the particle. Note perf sensitive function. It has been intention...
void correctVelocity(PbdState &bodies, const double dt) override
Solve the velocities given to the constraint.
double m_compliance
used in xPBD, inverse of Stiffness
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &n) override
Compute value and gradient of the constraint.
void initConstraint(const PbdState &state, const PbdParticleId &bodyId, const Vec3d contactPtOnBody, const PbdParticleId &x0, const PbdParticleId &x1, const PbdParticleId &x2, const double compliance=0.0)
Initialize the constraint.
virtual bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &dcdx)=0
Compute value and gradient of the constraint.
double getForce(const double dt) const
Get the force magnitude, valid after solving lambda Only valid with xpbd.
double m_stiffness
used in PBD, [0, 1]
void initConstraint(const PbdState &state, const PbdParticleId &bodyId, const Vec3d contactPtOnBody, const PbdParticleId &x0, const double compliance=0.0)
Initialize the constraint.
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &n) override
Compute value and gradient of the constraint.
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &n) override
Compute value and gradient of the constraint.
SolverType
Type of solvers.
Vec3d getVelocityOnRigidBody(PbdState &bodies, const int bodyId, const Vec3d &pt)
Returns the velocity at the given point on body Either body in collision could be rigid body...
Provides interface for accessing particles from a 2d array of PbdBody,Particles.
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &n) override
Compute value and gradient of the constraint.