|
|
@@ -125,6 +125,81 @@ unwind_yup_rotation(LMatrix3<NumType> &mat, LVecBase3<NumType> &hpr) {
|
|
|
hpr[2] = roll;
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: unwind_yup_rotation
|
|
|
+// Description: Extracts the rotation about the x, y, and z axes from
|
|
|
+// the given hpr & scale matrix, given the indicated
|
|
|
+// roll amount as a hint. Adjusts the matrix to
|
|
|
+// eliminate the rotation.
|
|
|
+//
|
|
|
+// This function assumes the matrix is stored in a
|
|
|
+// right-handed Y-up coordinate system.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+template<class NumType>
|
|
|
+static void
|
|
|
+unwind_yup_rotation(LMatrix3<NumType> &mat, LVecBase3<NumType> &hpr,
|
|
|
+ NumType roll) {
|
|
|
+ typedef LMatrix3<NumType> Matrix;
|
|
|
+
|
|
|
+ // Extract the axes from the matrix.
|
|
|
+ LVector3<NumType> x, y, z;
|
|
|
+ x = mat.get_row(0);
|
|
|
+ y = mat.get_row(1);
|
|
|
+ z = mat.get_row(2);
|
|
|
+
|
|
|
+ // Unwind the roll from the axes, and continue.
|
|
|
+ Matrix rot_z;
|
|
|
+ rot_z = Matrix::rotate_mat(-roll, LVector3<NumType>(0.0, 0.0, 1.0),
|
|
|
+ CS_yup_right);
|
|
|
+
|
|
|
+ x = x * rot_z;
|
|
|
+ y = y * rot_z;
|
|
|
+ z = z * rot_z;
|
|
|
+
|
|
|
+ // Project the rotated X into the XZ plane.
|
|
|
+ LVector2<NumType> xz(x[0], x[2]);
|
|
|
+ xz = normalize(xz);
|
|
|
+
|
|
|
+ // Compute the rotation about the +Y (up) axis. This is yaw, or
|
|
|
+ // "heading".
|
|
|
+ NumType heading = rad_2_deg(-atan2(xz[1], xz[0]));
|
|
|
+
|
|
|
+ // Unwind the heading, and continue.
|
|
|
+ Matrix rot_y;
|
|
|
+ rot_y = Matrix::rotate_mat(-heading, LVector3<NumType>(0.0, 1.0, 0.0),
|
|
|
+ CS_yup_right);
|
|
|
+
|
|
|
+ x = x * rot_y;
|
|
|
+ y = y * rot_y;
|
|
|
+ z = z * rot_y;
|
|
|
+
|
|
|
+ // Project the rotated Z into the YZ plane.
|
|
|
+ LVector2<NumType> yz(z[1], z[2]);
|
|
|
+ yz = normalize(yz);
|
|
|
+
|
|
|
+ // Compute the rotation about the +X (right) axis. This is pitch.
|
|
|
+ NumType pitch = rad_2_deg(-atan2(yz[0], yz[1]));
|
|
|
+
|
|
|
+ // Unwind the pitch.
|
|
|
+ Matrix rot_x;
|
|
|
+ rot_x = Matrix::rotate_mat(-pitch, LVector3<NumType>(1.0, 0.0, 0.0),
|
|
|
+ CS_yup_right);
|
|
|
+
|
|
|
+ x = x * rot_x;
|
|
|
+ y = y * rot_x;
|
|
|
+ z = z * rot_x;
|
|
|
+
|
|
|
+ // Reset the matrix to reflect the unwinding.
|
|
|
+ mat.set_row(0, x);
|
|
|
+ mat.set_row(1, y);
|
|
|
+ mat.set_row(2, z);
|
|
|
+
|
|
|
+ // Return the three rotation components.
|
|
|
+ hpr[0] = heading;
|
|
|
+ hpr[1] = pitch;
|
|
|
+ hpr[2] = roll;
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: unwind_zup_rotation
|
|
|
// Description: Extracts the rotation about the x, y, and z axes from
|
|
|
@@ -169,7 +244,6 @@ unwind_zup_rotation(LMatrix3<NumType> &mat, LVecBase3<NumType> &hpr) {
|
|
|
x = x * rot_y;
|
|
|
y = y * rot_y;
|
|
|
z = z * rot_y;
|
|
|
-
|
|
|
|
|
|
// Project the rotated X into the XY plane.
|
|
|
LVector2<NumType> xy(x[0], x[1]);
|
|
|
@@ -188,7 +262,6 @@ unwind_zup_rotation(LMatrix3<NumType> &mat, LVecBase3<NumType> &hpr) {
|
|
|
y = y * rot_z;
|
|
|
z = z * rot_z;
|
|
|
|
|
|
-
|
|
|
// Project the rotated Y into the YZ plane.
|
|
|
LVector2<NumType> yz(y[1], y[2]);
|
|
|
yz = normalize(yz);
|
|
|
@@ -205,6 +278,80 @@ unwind_zup_rotation(LMatrix3<NumType> &mat, LVecBase3<NumType> &hpr) {
|
|
|
y = y * rot_x;
|
|
|
z = z * rot_x;
|
|
|
|
|
|
+ // Reset the matrix to reflect the unwinding.
|
|
|
+ mat.set_row(0, x);
|
|
|
+ mat.set_row(1, y);
|
|
|
+ mat.set_row(2, z);
|
|
|
+
|
|
|
+ // Return the three rotation components.
|
|
|
+ hpr[0] = heading;
|
|
|
+ hpr[1] = pitch;
|
|
|
+ hpr[2] = roll;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: unwind_zup_rotation
|
|
|
+// Description: Extracts the rotation about the x, y, and z axes from
|
|
|
+// the given hpr & scale matrix, given the indicated
|
|
|
+// roll amount as a hint. Adjusts the matrix to
|
|
|
+// eliminate the rotation.
|
|
|
+//
|
|
|
+// This function assumes the matrix is stored in a
|
|
|
+// right-handed Z-up coordinate system.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+template<class NumType>
|
|
|
+static void
|
|
|
+unwind_zup_rotation(LMatrix3<NumType> &mat, LVecBase3<NumType> &hpr,
|
|
|
+ NumType roll) {
|
|
|
+ typedef LMatrix3<NumType> Matrix;
|
|
|
+
|
|
|
+ // Extract the axes from the matrix.
|
|
|
+ LVector3<NumType> x, y, z;
|
|
|
+ x = mat.get_row(0);
|
|
|
+ y = mat.get_row(1);
|
|
|
+ z = mat.get_row(2);
|
|
|
+
|
|
|
+ // Unwind the roll from the axes, and continue.
|
|
|
+ Matrix rot_y;
|
|
|
+ rot_y = Matrix::rotate_mat(roll, LVector3<NumType>(0.0, 1.0, 0.0),
|
|
|
+ CS_zup_right);
|
|
|
+
|
|
|
+ x = x * rot_y;
|
|
|
+ y = y * rot_y;
|
|
|
+ z = z * rot_y;
|
|
|
+
|
|
|
+ // Project the rotated X into the XY plane.
|
|
|
+ LVector2<NumType> xy(x[0], x[1]);
|
|
|
+ xy = normalize(xy);
|
|
|
+
|
|
|
+ // Compute the rotation about the +Z (up) axis. This is yaw, or
|
|
|
+ // "heading".
|
|
|
+ NumType heading = rad_2_deg(atan2(xy[1], xy[0]));
|
|
|
+
|
|
|
+ // Unwind the heading, and continue.
|
|
|
+ Matrix rot_z;
|
|
|
+ rot_z = Matrix::rotate_mat(-heading, LVector3<NumType>(0.0, 0.0, 1.0),
|
|
|
+ CS_zup_right);
|
|
|
+
|
|
|
+ x = x * rot_z;
|
|
|
+ y = y * rot_z;
|
|
|
+ z = z * rot_z;
|
|
|
+
|
|
|
+ // Project the rotated Y into the YZ plane.
|
|
|
+ LVector2<NumType> yz(y[1], y[2]);
|
|
|
+ yz = normalize(yz);
|
|
|
+
|
|
|
+ // Compute the rotation about the +X (right) axis. This is pitch.
|
|
|
+ NumType pitch = rad_2_deg(atan2(yz[1], yz[0]));
|
|
|
+
|
|
|
+ // Unwind the pitch.
|
|
|
+ Matrix rot_x;
|
|
|
+ rot_x = Matrix::rotate_mat(-pitch, LVector3<NumType>(1.0, 0.0, 0.0),
|
|
|
+ CS_zup_right);
|
|
|
+
|
|
|
+ x = x * rot_x;
|
|
|
+ y = y * rot_x;
|
|
|
+ z = z * rot_x;
|
|
|
|
|
|
// Reset the matrix to reflect the unwinding.
|
|
|
mat.set_row(0, x);
|
|
|
@@ -308,6 +455,104 @@ _decompose_matrix(const LMatrix3<NumType> &mat,
|
|
|
return !shear;
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: decompose_matrix
|
|
|
+// Description: Extracts out the components of a 3x3 rotation matrix.
|
|
|
+// Returns true if the scale and hpr completely describe
|
|
|
+// the matrix, or false if there is also a shear
|
|
|
+// component or if the matrix is not affine.
|
|
|
+//
|
|
|
+// This flavor of the function accepts an expected roll
|
|
|
+// amount. This amount will be used as the roll
|
|
|
+// component, rather than attempting to determine roll
|
|
|
+// by examining the matrix; this helps alleviate roll
|
|
|
+// instability due to roundoff errors or gimbal lock.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+template<class NumType>
|
|
|
+static bool
|
|
|
+_decompose_matrix(const LMatrix3<NumType> &mat,
|
|
|
+ LVecBase3<NumType> &scale,
|
|
|
+ LVecBase3<NumType> &hpr,
|
|
|
+ NumType roll,
|
|
|
+ CoordinateSystem cs) {
|
|
|
+ if (cs == CS_default) {
|
|
|
+ cs = default_coordinate_system;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Extract the rotation and scale, according to the coordinate
|
|
|
+ // system of choice.
|
|
|
+ bool shear;
|
|
|
+
|
|
|
+ switch (cs) {
|
|
|
+ case CS_zup_right:
|
|
|
+ {
|
|
|
+ LMatrix3<NumType> rm(mat);
|
|
|
+ unwind_zup_rotation(rm, hpr, roll);
|
|
|
+ scale[0] = rm(0, 0);
|
|
|
+ scale[1] = rm(1, 1);
|
|
|
+ scale[2] = rm(2, 2);
|
|
|
+ shear =
|
|
|
+ (fabs(rm(0, 1)) + fabs(rm(0, 2)) +
|
|
|
+ fabs(rm(1, 0)) + fabs(rm(1, 2)) +
|
|
|
+ fabs(rm(2, 0)) + fabs(rm(2, 1))) >= 0.0001;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case CS_yup_right:
|
|
|
+ {
|
|
|
+ LMatrix3<NumType> rm(mat);
|
|
|
+ unwind_yup_rotation(rm, hpr, roll);
|
|
|
+ scale[0] = rm(0, 0);
|
|
|
+ scale[1] = rm(1, 1);
|
|
|
+ scale[2] = rm(2, 2);
|
|
|
+ shear =
|
|
|
+ (fabs(rm(0, 1)) + fabs(rm(0, 2)) +
|
|
|
+ fabs(rm(1, 0)) + fabs(rm(1, 2)) +
|
|
|
+ fabs(rm(2, 0)) + fabs(rm(2, 1))) >= 0.0001;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case CS_zup_left:
|
|
|
+ {
|
|
|
+ LMatrix3<NumType> lm(mat(0, 0), mat(0, 1), -mat(0, 2),
|
|
|
+ mat(1, 0), mat(1, 1), -mat(1, 2),
|
|
|
+ -mat(2, 0), -mat(2, 1), mat(2, 2));
|
|
|
+ unwind_zup_rotation(lm, hpr, roll);
|
|
|
+ scale[0] = -lm(0, 0);
|
|
|
+ scale[1] = -lm(1, 1);
|
|
|
+ scale[2] = lm(2, 2);
|
|
|
+ shear =
|
|
|
+ (fabs(lm(0, 1)) + fabs(lm(0, 2)) +
|
|
|
+ fabs(lm(1, 0)) + fabs(lm(1, 2)) +
|
|
|
+ fabs(lm(2, 0)) + fabs(lm(2, 1))) >= 0.0001;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case CS_yup_left:
|
|
|
+ {
|
|
|
+ LMatrix3<NumType> lm(mat(0, 0), mat(0, 1), -mat(0, 2),
|
|
|
+ mat(1, 0), mat(1, 1), -mat(1, 2),
|
|
|
+ -mat(2, 0), -mat(2, 1), mat(2, 2));
|
|
|
+ unwind_yup_rotation(lm, hpr, roll);
|
|
|
+ scale[0] = -lm(0, 0);
|
|
|
+ scale[1] = -lm(1, 1);
|
|
|
+ scale[2] = lm(2, 2);
|
|
|
+ shear =
|
|
|
+ (fabs(lm(0, 1)) + fabs(lm(0, 2)) +
|
|
|
+ fabs(lm(1, 0)) + fabs(lm(1, 2)) +
|
|
|
+ fabs(lm(2, 0)) + fabs(lm(2, 1))) >= 0.0001;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ linmath_cat.error()
|
|
|
+ << "Unexpected coordinate system!\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return !shear;
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: decompose_matrix
|
|
|
// Description: Extracts out the components of an affine matrix.
|
|
|
@@ -328,6 +573,33 @@ _decompose_matrix(const LMatrix4<NumType> &mat,
|
|
|
return _decompose_matrix(mat.get_upper_3(), scale, hpr, cs);
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: decompose_matrix
|
|
|
+// Description: Extracts out the components of an affine matrix.
|
|
|
+// Returns true if the scale, hpr, translate
|
|
|
+// completely describe the matrix, or false if there is
|
|
|
+// also a shear component or if the matrix is not
|
|
|
+// affine.
|
|
|
+//
|
|
|
+// This flavor of the function accepts an expected roll
|
|
|
+// amount. This amount will be used as the roll
|
|
|
+// component, rather than attempting to determine roll
|
|
|
+// by examining the matrix; this helps alleviate roll
|
|
|
+// instability due to roundoff errors or gimbal lock.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+template<class NumType>
|
|
|
+INLINE bool
|
|
|
+_decompose_matrix(const LMatrix4<NumType> &mat,
|
|
|
+ LVecBase3<NumType> &scale,
|
|
|
+ LVecBase3<NumType> &hpr,
|
|
|
+ LVecBase3<NumType> &translate,
|
|
|
+ NumType roll,
|
|
|
+ CoordinateSystem cs) {
|
|
|
+ // Get the translation first.
|
|
|
+ translate = mat.get_row3(3);
|
|
|
+ return _decompose_matrix(mat.get_upper_3(), scale, hpr, roll, cs);
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
compose_matrix(LMatrix3f &mat,
|
|
|
const LVecBase3f &scale,
|
|
|
@@ -344,6 +616,15 @@ decompose_matrix(const LMatrix3f &mat,
|
|
|
return _decompose_matrix(mat, scale, hpr, cs);
|
|
|
}
|
|
|
|
|
|
+bool
|
|
|
+decompose_matrix(const LMatrix3f &mat,
|
|
|
+ LVecBase3f &scale,
|
|
|
+ LVecBase3f &hpr,
|
|
|
+ float roll,
|
|
|
+ CoordinateSystem cs) {
|
|
|
+ return _decompose_matrix(mat, scale, hpr, roll, cs);
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
compose_matrix(LMatrix3d &mat,
|
|
|
const LVecBase3d &scale,
|
|
|
@@ -360,6 +641,15 @@ decompose_matrix(const LMatrix3d &mat,
|
|
|
return _decompose_matrix(mat, scale, hpr, cs);
|
|
|
}
|
|
|
|
|
|
+bool
|
|
|
+decompose_matrix(const LMatrix3d &mat,
|
|
|
+ LVecBase3d &scale,
|
|
|
+ LVecBase3d &hpr,
|
|
|
+ double roll,
|
|
|
+ CoordinateSystem cs) {
|
|
|
+ return _decompose_matrix(mat, scale, hpr, roll, cs);
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
compose_matrix(LMatrix4f &mat,
|
|
|
const LVecBase3f &scale,
|
|
|
@@ -378,6 +668,16 @@ decompose_matrix(const LMatrix4f &mat,
|
|
|
return _decompose_matrix(mat, scale, hpr, translate, cs);
|
|
|
}
|
|
|
|
|
|
+bool
|
|
|
+decompose_matrix(const LMatrix4f &mat,
|
|
|
+ LVecBase3f &scale,
|
|
|
+ LVecBase3f &hpr,
|
|
|
+ LVecBase3f &translate,
|
|
|
+ float roll,
|
|
|
+ CoordinateSystem cs) {
|
|
|
+ return _decompose_matrix(mat, scale, hpr, translate, roll, cs);
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
compose_matrix(LMatrix4d &mat,
|
|
|
const LVecBase3d &scale,
|
|
|
@@ -396,3 +696,13 @@ decompose_matrix(const LMatrix4d &mat,
|
|
|
return _decompose_matrix(mat, scale, hpr, translate, cs);
|
|
|
}
|
|
|
|
|
|
+bool
|
|
|
+decompose_matrix(const LMatrix4d &mat,
|
|
|
+ LVecBase3d &scale,
|
|
|
+ LVecBase3d &hpr,
|
|
|
+ LVecBase3d &translate,
|
|
|
+ double roll,
|
|
|
+ CoordinateSystem cs) {
|
|
|
+ return _decompose_matrix(mat, scale, hpr, translate, roll, cs);
|
|
|
+}
|
|
|
+
|