1#include "PCGConstraintSolver.h"
2#include "SharedFuncsForRigidBody.h"
6 IMPLEMENT_TCLASS(PCGConstraintSolver, TDataType)
8 template<typename TDataType>
9 PCGConstraintSolver<TDataType>::PCGConstraintSolver()
12 this->inContacts()->tagOptional(true);
15 template<typename TDataType>
16 PCGConstraintSolver<TDataType>::~PCGConstraintSolver()
21 template<typename TDataType>
22 void PCGConstraintSolver<TDataType>::initializeJacobian(Real dt)
24 int constraint_size = 0;
25 int contact_size = this->inContacts()->size();
27 auto topo = this->inDiscreteElements()->constDataPtr();
29 int ballAndSocketJoint_size = topo->ballAndSocketJoints().size();
30 int sliderJoint_size = topo->sliderJoints().size();
31 int hingeJoint_size = topo->hingeJoints().size();
32 int fixedJoint_size = topo->fixedJoints().size();
33 int pointJoint_size = topo->pointJoints().size();
35 if (this->varFrictionEnabled()->getData())
37 constraint_size += 3 * contact_size;
41 constraint_size = contact_size;
44 if (ballAndSocketJoint_size != 0)
46 constraint_size += 3 * ballAndSocketJoint_size;
49 if (sliderJoint_size != 0)
51 constraint_size += 8 * sliderJoint_size;
54 if (hingeJoint_size != 0)
56 constraint_size += 8 * hingeJoint_size;
59 if (fixedJoint_size != 0)
61 constraint_size += 6 * fixedJoint_size;
64 if (pointJoint_size != 0)
66 constraint_size += 3 * pointJoint_size;
69 if (constraint_size == 0)
74 mVelocityConstraints.resize(constraint_size);
76 if (contact_size != 0)
78 if (mContactsInLocalFrame.size() != this->inContacts()->size()) {
79 mContactsInLocalFrame.resize(this->inContacts()->size());
82 setUpContactsInLocalFrame(
83 mContactsInLocalFrame,
84 this->inContacts()->getData(),
85 this->inCenter()->getData(),
86 this->inRotationMatrix()->getData()
89 auto& contacts = this->inContacts()->getData();
90 setUpContactAndFrictionConstraints(
92 mContactsInLocalFrame,
93 this->inCenter()->getData(),
94 this->inRotationMatrix()->getData(),
95 this->varFrictionEnabled()->getData()
99 if (ballAndSocketJoint_size != 0)
101 auto& joints = topo->ballAndSocketJoints();
102 int begin_index = contact_size;
104 if (this->varFrictionEnabled()->getData())
106 begin_index += 2 * contact_size;
109 setUpBallAndSocketJointConstraints(
110 mVelocityConstraints,
112 this->inCenter()->getData(),
113 this->inRotationMatrix()->getData(),
118 if (sliderJoint_size != 0)
120 auto& joints = topo->sliderJoints();
121 int begin_index = contact_size;
123 if (this->varFrictionEnabled()->getData())
125 begin_index += 2 * contact_size;
127 begin_index += 3 * ballAndSocketJoint_size;
128 setUpSliderJointConstraints(
129 mVelocityConstraints,
131 this->inCenter()->getData(),
132 this->inRotationMatrix()->getData(),
133 this->inQuaternion()->getData(),
138 if (hingeJoint_size != 0)
140 auto& joints = topo->hingeJoints();
141 int begin_index = contact_size + 3 * ballAndSocketJoint_size + 8 * sliderJoint_size;
142 if (this->varFrictionEnabled()->getData())
144 begin_index += 2 * contact_size;
146 setUpHingeJointConstraints(
147 mVelocityConstraints,
149 this->inCenter()->getData(),
150 this->inRotationMatrix()->getData(),
151 this->inQuaternion()->getData(),
156 if (fixedJoint_size != 0)
158 auto& joints = topo->fixedJoints();
159 int begin_index = contact_size + 3 * ballAndSocketJoint_size + 8 * sliderJoint_size + 8 * hingeJoint_size;
160 if (this->varFrictionEnabled()->getData())
162 begin_index += 2 * contact_size;
164 setUpFixedJointConstraints(
165 mVelocityConstraints,
167 this->inRotationMatrix()->getData(),
168 this->inQuaternion()->getData(),
173 if (pointJoint_size != 0)
175 auto& joints = topo->pointJoints();
176 int begin_index = contact_size + 3 * ballAndSocketJoint_size + 8 * sliderJoint_size + 8 * hingeJoint_size + 6 * fixedJoint_size;
177 if (this->varFrictionEnabled()->getData())
179 begin_index += 2 * contact_size;
181 setUpPointJointConstraints(
182 mVelocityConstraints,
184 this->inCenter()->getData(),
189 auto sizeOfRigids = this->inCenter()->size();
190 mContactNumber.resize(sizeOfRigids);
191 mContactNumber.reset();
193 mJ.resize(4 * constraint_size);
194 mB.resize(4 * constraint_size);
195 mEta.resize(constraint_size);
196 mLambda.resize(constraint_size);
197 mResidual.resize(constraint_size);
198 mP.resize(constraint_size);
199 tmpArray.resize(constraint_size);
200 mAp.resize(constraint_size);
201 mZ.resize(constraint_size);
202 mCFM.resize(constraint_size);
203 mERP.resize(constraint_size);
205 mK_1.resize(constraint_size);
206 mK_2.resize(constraint_size);
207 mK_3.resize(constraint_size);
226 calculateJacobianMatrix(
229 this->inCenter()->getData(),
230 this->inInertia()->getData(),
231 this->inMass()->getData(),
232 this->inRotationMatrix()->getData(),
239 mVelocityConstraints,
242 this->varFrequency()->getValue(),
243 this->varDampingRatio()->getValue(),
248 mErrors.resize(constraint_size);
251 calculateEtaVectorWithERP(
254 this->inVelocity()->getData(),
255 this->inAngularVelocity()->getData(),
256 this->inCenter()->getData(),
257 this->inQuaternion()->getData(),
258 mVelocityConstraints,
260 this->varSlop()->getValue(),
266 mVelocityConstraints,
269 this->inCenter()->getData(),
270 this->inInertia()->getData(),
271 this->inMass()->getData(),
279 if (contact_size != 0)
281 calculateContactPoints(
282 this->inContacts()->getData(),
288 template<typename TDataType>
289 void PCGConstraintSolver<TDataType>::constrain()
291 uint bodyNum = this->inCenter()->size();
293 auto topo = this->inDiscreteElements()->constDataPtr();
295 mImpulseC.resize(bodyNum * 2);
296 mImpulseExt.resize(bodyNum * 2);
300 Real dt = this->inTimeStep()->getData();
302 if (this->varGravityEnabled()->getValue())
306 this->varGravityValue()->getValue(),
312 this->inAttribute()->getData(),
313 this->inVelocity()->getData(),
314 this->inAngularVelocity()->getData(),
316 this->varLinearDamping()->getValue(),
317 this->varAngularDamping()->getValue(),
322 if (!this->inContacts()->isEmpty() || topo->totalJointSize() > 0)
324 float r_norm_old = 0.0;
325 float r_norm_new = 0.0;
329 initializeJacobian(dt);
331 int constraint_size = mVelocityConstraints.size();
332 int contact_size = this->inContacts()->size();
334 if (topo->totalJointSize()!= mJointSize)
336 mJointSize = topo->totalJointSize();
337 mLambdaOldJoint.resize(0);
340 if (mLambdaOldJoint.size() != 0 && topo->totalJointSize() > 0)
342 if (this->varFrictionEnabled()->getValue())
344 mLambda.assign(mLambdaOldJoint, constraint_size - 3 * contact_size, 3 * contact_size, 0);
348 mLambda.assign(mLambdaOldJoint, constraint_size - contact_size, contact_size, 0);
353 if (topo->totalJointSize() > 0)
355 if (this->varFrictionEnabled()->getValue())
357 mLambdaOldJoint.resize(constraint_size - 3 * contact_size);
358 mLambdaOldJoint.assign(mLambda, constraint_size - 3 * contact_size, 0, 3 * contact_size);
362 mLambdaOldJoint.resize(constraint_size - contact_size);
363 mLambdaOldJoint.assign(mLambda, constraint_size - contact_size, 0, 3 * contact_size);
369 calculateLinearSystemLHS(
388 preconditionedResidual(
398 r_norm_old = vectorNorm(mResidual, mP);
399 float r_norm_init = r_norm_old;
402 if (r_norm_old > EPSILON)
404 for (int i = 0; i < this->varIterationNumberForVelocitySolverCG()->getValue(); i++)
408 calculateLinearSystemLHS(
418 alpha = r_norm_old / vectorNorm(mP, mAp);
441 mVelocityConstraints,
442 this->inContacts()->size(),
443 this->varFrictionCoefficient()->getValue()
449 calculateLinearSystemLHS(
469 preconditionedResidual(
478 r_norm_new = vectorNorm(mResidual, mZ);
479 float r_norm_true = vectorNorm(mResidual, mResidual);
480 //printf("%lf\n", r_norm_true);
481 if (r_norm_true <= this->varTolerance()->getValue())
484 float r_norm_spec = vectorNorm(mResidual, mZold);
486 // compute p = r + (r_norm_new / r_norm_old) * p
487 Real r_tmp = r_norm_new - r_norm_spec < 0 ? 0 : r_norm_new - r_norm_spec;
491 (r_tmp / r_norm_old),
498 mVelocityConstraints);
499 r_norm_old = r_norm_new;
503 calculateImpulseByLambda(
505 mVelocityConstraints,
510 if (this->varFrictionEnabled()->getValue())
512 mLambdaOldJoint.assign(mLambda, constraint_size - 3 * contact_size, 0, 3 * contact_size);
516 mLambdaOldJoint.assign(mLambda, constraint_size - contact_size, 0, contact_size);
520 for (int i = 0; i < this->varIterationNumberForVelocitySolverJacobi()->getValue(); i++)
522 JacobiIterationForCFM(
528 mVelocityConstraints,
533 this->inMass()->getData(),
535 this->varFrictionCoefficient()->getData(),
536 this->varGravityValue()->getData(),
543 this->inAttribute()->getData(),
544 this->inVelocity()->getData(),
545 this->inAngularVelocity()->getData(),
547 this->varLinearDamping()->getValue(),
548 this->varAngularDamping()->getValue(),
553 this->inAttribute()->getData(),
554 this->inCenter()->getData(),
555 this->inQuaternion()->getData(),
556 this->inRotationMatrix()->getData(),
557 this->inInertia()->getData(),
558 this->inVelocity()->getData(),
559 this->inAngularVelocity()->getData(),
560 this->inInitialInertia()->getData(),
568 this->inAttribute()->getData(),
569 this->inCenter()->getData(),
570 this->inQuaternion()->getData(),
571 this->inRotationMatrix()->getData(),
572 this->inInertia()->getData(),
573 this->inVelocity()->getData(),
574 this->inAngularVelocity()->getData(),
575 this->inInitialInertia()->getData(),
583 DEFINE_CLASS(PCGConstraintSolver);