@@ -1199,7 +1199,6 @@ private static Vector128<T> Permute(Vector128<T> value, byte control)
11991199 }
12001200 }*/
12011201
1202- /*
12031202 /// <summary>Attempts to extract the scale, translation, and rotation components from the given scale/rotation/translation matrix.
12041203 /// If successful, the out parameters will contained the extracted values.</summary>
12051204 /// <param name="matrix">The source matrix.</param>
@@ -1212,193 +1211,137 @@ public static bool Decompose<T>(Matrix4X4<T> matrix, out Vector3D<T> scale, out
12121211 {
12131212 bool result = true ;
12141213
1215- unsafe
1216- {
1217- fixed (Vector3D<T>* scaleBase = &scale)
1218- {
1219- T* pfScales = (T*) scaleBase;
1220- T det;
1221-
1222- VectorBasis<T> vectorBasis;
1223- Vector3D<T>** pVectorBasis = (Vector3D<T>**) &vectorBasis;
1214+ translation = new Vector3D < T > ( matrix . M41 , matrix . M42 , matrix . M43 ) ;
12241215
1225- Matrix4X4<T> matTemp = Matrix4X4<T>.Identity;
1226- CanonicalBasis<T> canonicalBasis = default;
1227- Vector3D<T>* pCanonicalBasis = &canonicalBasis.Row0;
1216+ // Extract basis vectors (rows)
1217+ var basis = new Vector3D < T > [ 3 ] ;
1218+ basis [ 0 ] = new Vector3D < T > ( matrix . M11 , matrix . M12 , matrix . M13 ) ;
1219+ basis [ 1 ] = new Vector3D < T > ( matrix . M21 , matrix . M22 , matrix . M23 ) ;
1220+ basis [ 2 ] = new Vector3D < T > ( matrix . M31 , matrix . M32 , matrix . M33 ) ;
12281221
1229- canonicalBasis.Row0 = new Vector3D<T>(T.One, T.Zero, T.Zero);
1230- canonicalBasis.Row1 = new Vector3D<T>(T.Zero, T.One, T.Zero);
1231- canonicalBasis.Row2 = new Vector3D<T>(T.Zero, T.Zero, T.One);
1222+ // Compute scales
1223+ var scales = new T [ 3 ] ;
1224+ scales [ 0 ] = basis [ 0 ] . Length ;
1225+ scales [ 1 ] = basis [ 1 ] . Length ;
1226+ scales [ 2 ] = basis [ 2 ] . Length ;
12321227
1233- translation = new Vector3D<T>(
1234- matrix.M41,
1235- matrix.M42,
1236- matrix.M43);
1228+ scale = new Vector3D < T > ( scales [ 0 ] , scales [ 1 ] , scales [ 2 ] ) ;
12371229
1238- pVectorBasis[0] = (Vector3D<T>*) &matTemp.Row1;
1239- pVectorBasis[1] = (Vector3D<T>*) &matTemp.Row2;
1240- pVectorBasis[2] = (Vector3D<T>*) &matTemp.Row3;
1241-
1242- *(pVectorBasis[0]) = new Vector3D<T>(matrix.M11, matrix.M12, matrix.M13);
1243- *(pVectorBasis[1]) = new Vector3D<T>(matrix.M21, matrix.M22, matrix.M23);
1244- *(pVectorBasis[2]) = new Vector3D<T>(matrix.M31, matrix.M32, matrix.M33);
1245-
1246- scale.X = pVectorBasis[0]->Length;
1247- scale.Y = pVectorBasis[1]->Length;
1248- scale.Z = pVectorBasis[2]->Length;
1230+ // Rank axes by scale magnitude
1231+ uint a , b , c ;
1232+ {
1233+ T x = scales [ 0 ] , y = scales [ 1 ] , z = scales [ 2 ] ;
12491234
1250- uint a, b, c;
1251- #region Ranking
1252- T x = pfScales[0], y = pfScales[1], z = pfScales[2];
1253- if (!(x >= y))
1235+ if ( ! ( x >= y ) )
1236+ {
1237+ if ( ! ( y >= z ) )
1238+ { a = 2 ; b = 1 ; c = 0 ; }
1239+ else
12541240 {
1255- if (!(y >= z))
1256- {
1257- a = 2;
1258- b = 1;
1259- c = 0;
1260- }
1241+ a = 1 ;
1242+ if ( ! ( x >= z ) )
1243+ { b = 2 ; c = 0 ; }
12611244 else
1262- {
1263- a = 1;
1264-
1265- if (!(x >= z))
1266- {
1267- b = 2;
1268- c = 0;
1269- }
1270- else
1271- {
1272- b = 0;
1273- c = 2;
1274- }
1275- }
1245+ { b = 0 ; c = 2 ; }
12761246 }
1247+ }
1248+ else
1249+ {
1250+ if ( ! ( x >= z ) )
1251+ { a = 2 ; b = 0 ; c = 1 ; }
12771252 else
12781253 {
1279- if (!(x >= z))
1280- {
1281- a = 2;
1282- b = 0;
1283- c = 1;
1284- }
1254+ a = 0 ;
1255+ if ( ! ( y >= z ) )
1256+ { b = 2 ; c = 1 ; }
12851257 else
1286- {
1287- a = 0;
1288-
1289- if (!(y >= z))
1290- {
1291- b = 2;
1292- c = 1;
1293- }
1294- else
1295- {
1296- b = 1;
1297- c = 2;
1298- }
1299- }
1258+ { b = 1 ; c = 2 ; }
13001259 }
1301- #endregion
1260+ }
1261+ }
13021262
1303- if (!(pfScales[a] >= T.CreateTruncating(DecomposeEpsilon)))
1304- {
1305- *(pVectorBasis[a]) = pCanonicalBasis[a];
1306- }
1263+ var canonical = new [ ]
1264+ {
1265+ new Vector3D < T > ( T . One , T . Zero , T . Zero ) ,
1266+ new Vector3D < T > ( T . Zero , T . One , T . Zero ) ,
1267+ new Vector3D < T > ( T . Zero , T . Zero , T . One )
1268+ } ;
13071269
1308- *pVectorBasis[a] = Vector3D.Normalize(*pVectorBasis[a] );
1270+ T eps = T . CreateTruncating ( DecomposeEpsilon ) ;
13091271
1310- if (!(pfScales[b] >= T.CreateTruncating(DecomposeEpsilon)))
1311- {
1312- uint cc;
1313- T fAbsX, fAbsY, fAbsZ;
1314-
1315- fAbsX = T.Abs(pVectorBasis[a]->X);
1316- fAbsY = T.Abs(pVectorBasis[a]->Y);
1317- fAbsZ = T.Abs(pVectorBasis[a]->Z);
1318-
1319- #region Ranking
1320- if (!(fAbsX >= fAbsY))
1321- {
1322- if (!(fAbsY >= fAbsZ))
1323- {
1324- cc = 0;
1325- }
1326- else
1327- {
1328- if (!(fAbsX >= fAbsZ))
1329- {
1330- cc = 0;
1331- }
1332- else
1333- {
1334- cc = 2;
1335- }
1336- }
1337- }
1338- else
1339- {
1340- if (!(fAbsX >= fAbsZ))
1341- {
1342- cc = 1;
1343- }
1344- else
1345- {
1346- if (!(fAbsY >= fAbsZ))
1347- {
1348- cc = 1;
1349- }
1350- else
1351- {
1352- cc = 2;
1353- }
1354- }
1355- }
1356- #endregion
1357-
1358- *pVectorBasis[b] = Vector3D.Cross(*pVectorBasis[a], *(pCanonicalBasis + cc));
1359- }
1272+ if ( ! ( scales [ a ] >= eps ) )
1273+ basis [ a ] = canonical [ a ] ;
13601274
1361- *pVectorBasis[b ] = Vector3D.Normalize(*pVectorBasis[b ]);
1275+ basis [ a ] = Vector3D . Normalize ( basis [ a ] ) ;
13621276
1363- if (!(pfScales[c] >= T.CreateTruncating(DecomposeEpsilon)))
1364- {
1365- *pVectorBasis[c] = Vector3D.Cross(*pVectorBasis[a], *pVectorBasis[b]);
1366- }
1277+ if ( ! ( scales [ b ] >= eps ) )
1278+ {
1279+ T ax = T . Abs ( basis [ a ] . X ) ;
1280+ T ay = T . Abs ( basis [ a ] . Y ) ;
1281+ T az = T . Abs ( basis [ a ] . Z ) ;
13671282
1368- *pVectorBasis[c] = Vector3D.Normalize(*pVectorBasis[c]);
1283+ uint cc ;
1284+ if ( ! ( ax >= ay ) )
1285+ {
1286+ if ( ! ( ay >= az ) )
1287+ cc = 0 ;
1288+ else
1289+ cc = ( ! ( ax >= az ) ) ? 0u : 2u ;
1290+ }
1291+ else
1292+ {
1293+ if ( ! ( ax >= az ) )
1294+ cc = 1 ;
1295+ else
1296+ cc = ( ! ( ay >= az ) ) ? 1u : 2u ;
1297+ }
13691298
1370- det = matTemp.GetDeterminant();
1299+ basis [ b ] = Vector3D . Cross ( basis [ a ] , canonical [ cc ] ) ;
1300+ }
13711301
1372- // use Kramer's rule to check for handedness of coordinate system
1373- if (!(det >= T.Zero))
1374- {
1375- // switch coordinate system by negating the scale and inverting the basis vector on the x-axis
1376- pfScales[a] = -pfScales[a];
1377- *pVectorBasis[a] = -(*pVectorBasis[a]);
1302+ basis [ b ] = Vector3D . Normalize ( basis [ b ] ) ;
13781303
1379- det = -det;
1380- }
1304+ if ( ! ( scales [ c ] >= eps ) )
1305+ basis [ c ] = Vector3D . Cross ( basis [ a ] , basis [ b ] ) ;
13811306
1382- det = det - T.One;
1383- det = det * det;
1307+ basis [ c ] = Vector3D . Normalize ( basis [ c ] ) ;
13841308
1385- if (!(T.CreateTruncating(DecomposeEpsilon) >= det))
1386- {
1387- // Non-SRT matrix encountered
1388- rotation = Quaternion<T>.Identity;
1389- result = false;
1390- }
1391- else
1392- {
1393- // generate the quaternion from the matrix
1394- rotation = Quaternion<T>.CreateFromRotationMatrix(matTemp);
1395- }
1396- }
1309+ // Rebuild orthonormal rotation matrix
1310+ var rotationMatrix = new Matrix4X4 < T > (
1311+ basis [ 0 ] . X , basis [ 0 ] . Y , basis [ 0 ] . Z , T . Zero ,
1312+ basis [ 1 ] . X , basis [ 1 ] . Y , basis [ 1 ] . Z , T . Zero ,
1313+ basis [ 2 ] . X , basis [ 2 ] . Y , basis [ 2 ] . Z , T . Zero ,
1314+ T . Zero , T . Zero , T . Zero , T . Zero ) ;
1315+
1316+ T det = rotationMatrix . GetDeterminant ( ) ;
1317+
1318+ // Fix handedness
1319+ if ( ! ( det >= T . Zero ) )
1320+ {
1321+ scales [ a ] = - scales [ a ] ;
1322+ det = - det ;
1323+
1324+ rotationMatrix . Row1 = - rotationMatrix . Row1 ;
1325+ rotationMatrix . Row2 = - rotationMatrix . Row2 ;
1326+ rotationMatrix . Row3 = - rotationMatrix . Row3 ;
13971327 }
13981328
1329+ T diff = det - T . One ;
1330+ diff *= diff ;
1331+
1332+ if ( ! ( eps >= diff ) )
1333+ {
1334+ rotation = Quaternion < T > . Identity ;
1335+ result = false ;
1336+ }
1337+ else
1338+ {
1339+ rotation = Quaternion < T > . CreateFromRotationMatrix ( rotationMatrix ) ;
1340+ }
1341+
1342+ scale = new Vector3D < T > ( scales [ 0 ] , scales [ 1 ] , scales [ 2 ] ) ;
13991343 return result ;
14001344 }
1401- */
14021345
14031346 /// <summary>Transforms the given matrix by applying the given Quaternion rotation.</summary>
14041347 /// <param name="value">The source matrix to transform.</param>
0 commit comments