@@ -140,6 +140,114 @@ static void polarDecomposition(const Eigen::Matrix3f &A, Eigen::Matrix3f &R, Eig
140140 R.col (2 ) = c2;
141141}
142142
143+ /* * Return the one norm of the matrix.
144+ */
145+ static float oneNorm (const Eigen::Matrix3f &A)
146+ {
147+ const float sum1 = fabs (A (0 ,0 )) + fabs (A (1 ,0 )) + fabs (A (2 ,0 ));
148+ const float sum2 = fabs (A (0 ,1 )) + fabs (A (1 ,1 )) + fabs (A (2 ,1 ));
149+ const float sum3 = fabs (A (0 ,2 )) + fabs (A (1 ,2 )) + fabs (A (2 ,2 ));
150+ float maxSum = sum1;
151+ if (sum2 > maxSum)
152+ maxSum = sum2;
153+ if (sum3 > maxSum)
154+ maxSum = sum3;
155+ return maxSum;
156+ }
157+
158+ /* * Return the inf norm of the matrix.
159+ */
160+ static float infNorm (const Eigen::Matrix3f &A)
161+ {
162+ const float sum1 = fabs (A (0 , 0 )) + fabs (A (0 , 1 )) + fabs (A (0 , 2 ));
163+ const float sum2 = fabs (A (1 , 0 )) + fabs (A (1 , 1 )) + fabs (A (1 , 2 ));
164+ const float sum3 = fabs (A (2 , 0 )) + fabs (A (2 , 1 )) + fabs (A (2 , 2 ));
165+ float maxSum = sum1;
166+ if (sum2 > maxSum)
167+ maxSum = sum2;
168+ if (sum3 > maxSum)
169+ maxSum = sum3;
170+ return maxSum;
171+ }
172+
173+ /* * Perform a polar decomposition of matrix M and return the rotation matrix R. This method handles the degenerated cases.
174+ */
175+ static void polarDecomposition2 (const Eigen::Matrix3f &M, const float tolerance, Eigen::Matrix3f &R)
176+ {
177+ Eigen::Matrix3f Mt = M.transpose ();
178+ float Mone = oneNorm (M);
179+ float Minf = infNorm (M);
180+ float Eone;
181+ Eigen::Matrix3f MadjTt, Et;
182+ do
183+ {
184+ MadjTt.row (0 ) = Mt.row (1 ).cross (Mt.row (2 ));
185+ MadjTt.row (1 ) = Mt.row (2 ).cross (Mt.row (0 ));
186+ MadjTt.row (2 ) = Mt.row (0 ).cross (Mt.row (1 ));
187+
188+ float det = Mt (0 ,0 ) * MadjTt (0 ,0 ) + Mt (0 ,1 ) * MadjTt (0 ,1 ) + Mt (0 ,2 ) * MadjTt (0 ,2 );
189+
190+ if (fabs (det) < 1.0e-12 )
191+ {
192+ Eigen::Vector3f len;
193+ unsigned int index = 0xffffffff ;
194+ for (unsigned int i = 0 ; i < 3 ; i++)
195+ {
196+ len[i] = MadjTt.row (i).squaredNorm ();
197+ if (len[i] > 1.0e-12 )
198+ {
199+ // index of valid cross product
200+ // => is also the index of the vector in Mt that must be exchanged
201+ index = i;
202+ break ;
203+ }
204+ }
205+ if (index == 0xffffffff )
206+ {
207+ R.setIdentity ();
208+ return ;
209+ }
210+ else
211+ {
212+ Mt.row (index) = Mt.row ((index + 1 ) % 3 ).cross (Mt.row ((index + 2 ) % 3 ));
213+ MadjTt.row ((index + 1 ) % 3 ) = Mt.row ((index + 2 ) % 3 ).cross (Mt.row (index));
214+ MadjTt.row ((index + 2 ) % 3 ) = Mt.row (index).cross (Mt.row ((index + 1 ) % 3 ));
215+ Eigen::Matrix3f M2 = Mt.transpose ();
216+ Mone = oneNorm (M2);
217+ Minf = infNorm (M2);
218+ det = Mt (0 ,0 ) * MadjTt (0 ,0 ) + Mt (0 ,1 ) * MadjTt (0 ,1 ) + Mt (0 ,2 ) * MadjTt (0 ,2 );
219+ }
220+ }
221+
222+ const float MadjTone = oneNorm (MadjTt);
223+ const float MadjTinf = infNorm (MadjTt);
224+
225+ const float gamma = sqrt (sqrt ((MadjTone*MadjTinf) / (Mone*Minf)) / fabs (det));
226+
227+ const float g1 = gamma*0 .5f ;
228+ const float g2 = 0 .5f / (gamma*det);
229+
230+ for (unsigned char i = 0 ; i < 3 ; i++)
231+ {
232+ for (unsigned char j = 0 ; j < 3 ; j++)
233+ {
234+ Et (i,j) = Mt (i,j);
235+ Mt (i,j) = g1*Mt (i,j) + g2*MadjTt (i,j);
236+ Et (i,j) -= Mt (i,j);
237+ }
238+ }
239+
240+ Eone = oneNorm (Et);
241+
242+ Mone = oneNorm (Mt);
243+ Minf = infNorm (Mt);
244+ } while (Eone > Mone * tolerance);
245+
246+ // Q = Mt^T
247+ R = Mt.transpose ();
248+ }
249+
250+
143251// ----------------------------------------------------------------------------------------------
144252bool PositionBasedDynamics::solveDistanceConstraint (
145253 const Eigen::Vector3f &p0, float invMass0,
@@ -653,7 +761,8 @@ bool PositionBasedDynamics::computeShapeMatchingRestInfo(
653761 restCm /= wsum;
654762
655763 // A
656- invRestMat.setZero ();
764+ Eigen::Matrix3f A;
765+ A.setZero ();
657766 for (int i = 0 ; i < numPoints; i++) {
658767 const Eigen::Vector3f qi = x0[i] - restCm;
659768 float wi = 1 .0f / (invMasses[i] + eps);
@@ -663,21 +772,21 @@ bool PositionBasedDynamics::computeShapeMatchingRestInfo(
663772 float xy = wi * qi[0 ] * qi[1 ];
664773 float xz = wi * qi[0 ] * qi[2 ];
665774 float yz = wi * qi[1 ] * qi[2 ];
666- invRestMat (0 , 0 ) += x2; invRestMat (0 , 1 ) += xy; invRestMat (0 , 2 ) += xz;
667- invRestMat (1 , 0 ) += xy; invRestMat (1 , 1 ) += y2; invRestMat (1 , 2 ) += yz;
668- invRestMat (2 , 0 ) += xz; invRestMat (2 , 1 ) += yz; invRestMat (2 , 2 ) += z2;
775+ A (0 , 0 ) += x2; A (0 , 1 ) += xy; A (0 , 2 ) += xz;
776+ A (1 , 0 ) += xy; A (1 , 1 ) += y2; A (1 , 2 ) += yz;
777+ A (2 , 0 ) += xz; A (2 , 1 ) += yz; A (2 , 2 ) += z2;
669778 }
670- float det = invRestMat .determinant ();
779+ float det = A .determinant ();
671780 if (fabs (det) > 1.0e-9 )
672781 {
673- invRestMat = invRestMat .inverse ();
782+ invRestMat = A .inverse ();
674783 return true ;
675784 }
676785 return false ;
677786}
678787
679788// ----------------------------------------------------------------------------------------------
680- bool PositionBasedDynamics::shapeMatchingConstraint (
789+ bool PositionBasedDynamics::solveShapeMatchingConstraint (
681790 const Eigen::Vector3f x0[], const Eigen::Vector3f x[], const float invMasses[], int numPoints,
682791 Eigen::Vector3f &restCm, const Eigen::Matrix3f &invRestMat,
683792 float stiffness,
@@ -692,7 +801,8 @@ bool PositionBasedDynamics::shapeMatchingConstraint(
692801 // center of mass
693802 Eigen::Vector3f cm (0 .0f , 0 .0f , 0 .0f );
694803 float wsum = 0 .0f ;
695- for (int i = 0 ; i < numPoints; i++) {
804+ for (int i = 0 ; i < numPoints; i++)
805+ {
696806 float wi = 1 .0f / (invMasses[i] + eps);
697807 cm += x[i] * wi;
698808 wsum += wi;
@@ -723,7 +833,8 @@ bool PositionBasedDynamics::shapeMatchingConstraint(
723833 if (allowStretch)
724834 R = mat;
725835 else
726- polarDecomposition (mat, R, U, D);
836+ // polarDecomposition(mat, R, U, D);
837+ polarDecomposition2 (mat, 1e-6f , R);
727838
728839 for (int i = 0 ; i < numPoints; i++) {
729840 Eigen::Vector3f goal = cm + R * (x0[i] - restCm);
0 commit comments