Fix create Rotation from scaled matrix

Support for creation of Rotation from matrices which is a combination of non uniform scale and a rotation
Fixes according to review
Scale -1 is Uniform, Not NoScaling
Fix hasScale() when negative scale
This commit is contained in:
Jolbas
2023-02-17 17:05:12 +01:00
committed by Chris Hennes
parent bdb6e1bd55
commit 6c3efbdb3b
3 changed files with 88 additions and 20 deletions

View File

@@ -833,34 +833,43 @@ ScaleType Matrix4D::hasScale(double tol) const
if (tol == 0.0)
tol = 1e-9;
// check if the absolute values are proportionally close or equal
auto closeAbs = [&](double a, double b) {
double c = fabs(a);
double d = fabs(b);
if (d>c) return (d-c)/d <= tol;
else if (c>d) return (c-d)/c <= tol;
return true;
};
// get column vectors
double dx = Vector3d(dMtrx4D[0][0],dMtrx4D[1][0],dMtrx4D[2][0]).Sqr();
double dy = Vector3d(dMtrx4D[0][1],dMtrx4D[1][1],dMtrx4D[2][1]).Sqr();
double dz = Vector3d(dMtrx4D[0][2],dMtrx4D[1][2],dMtrx4D[2][2]).Sqr();
double dx = getCol(0).Sqr();
double dy = getCol(1).Sqr();
double dz = getCol(2).Sqr();
double dxyz = sqrt(dx * dy * dz);
// get row vectors
double du = Vector3d(dMtrx4D[0][0],dMtrx4D[0][1],dMtrx4D[0][2]).Sqr();
double dv = Vector3d(dMtrx4D[1][0],dMtrx4D[1][1],dMtrx4D[1][2]).Sqr();
double dw = Vector3d(dMtrx4D[2][0],dMtrx4D[2][1],dMtrx4D[2][2]).Sqr();
double du = getRow(0).Sqr();
double dv = getRow(1).Sqr();
double dw = getRow(2).Sqr();
double duvw = sqrt(du * dv * dw);
double d3 = determinant3();
// This could be e.g. a projection, a shearing,... matrix
if (fabs(dxyz - d3) > tol && fabs(duvw - d3) > tol) {
if (!closeAbs(dxyz, d3) && !closeAbs(duvw, d3)) {
return ScaleType::Other;
}
if (fabs(duvw - d3) <= tol && (fabs(du - dv) > tol || fabs(dv - dw) > tol)) {
if (closeAbs(duvw, d3) && (!closeAbs(du, dv) || !closeAbs(dv, dw))) {
return ScaleType::NonUniformLeft;
}
if (fabs(dxyz - d3) <= tol && (fabs(dx - dy) > tol || fabs(dy - dz) > tol)) {
if (closeAbs(dxyz, d3) && (!closeAbs(dx, dy) || !closeAbs(dy, dz))) {
return ScaleType::NonUniformRight;
}
if (fabs(dx - 1.0) > tol) {
if (fabs(d3 - 1.0) > tol) {
return ScaleType::Uniform;
}