TurtleBrains  0.3.5
High quality, portable, C++ framework for rapid 2D game development.
tb_matrix_quaternion.hpp
1 
9 #ifndef TurtleBrains_MatrixQuaternion_hpp
10 #define TurtleBrains_MatrixQuaternion_hpp
11 
12 #include <turtle_brains/math/tb_matrix.hpp>
13 #include <turtle_brains/math/tb_quaternion.hpp>
14 
15 //
16 // This needs more unit testing to confirm it -really- works, but, I find it odd that I had to transpose the resource
17 // during FromMatrix, and _NOT_ transpose from the resource during FromQuaternion. Doing the transpose could make sense
18 // if they used ColumnMajor and TurtleBrains used RowMajor (or opposite), but then I'd expect to have done the same
19 // transposition in both functions...
20 //
21 
24 { //http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
25  //https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf
26  if (matrix(2, 2) < Type(0.0))
27  {
28  if (matrix(0, 0) > matrix(1, 1))
29  {
30  const Type t = (Type(1.0) + matrix(0, 0) - matrix(1, 1) - matrix(2, 2));
31  TypedQuaternion<Type> q(t, matrix(1, 0) + matrix(0, 1), matrix(0, 2) + matrix(2, 0), matrix(2, 1) - matrix(1, 2));
32  q *= (Type(0.5) / std::sqrt(t));
33  return q;
34  }
35  else
36  {
37  const Type t = (Type(1.0) - matrix(0, 0) + matrix(1, 1) - matrix(2, 2));
38  TypedQuaternion<Type> q(matrix(1, 0) + matrix(0, 1), t, matrix(2, 1) + matrix(1, 2), matrix(0, 2) - matrix(2, 0));
39  q *= (Type(0.5) / std::sqrt(t));
40  return q;
41  }
42  }
43  else
44  {
45  if (matrix(0, 0) < -matrix(1, 1))
46  {
47  const Type t = (Type(1.0) - matrix(0, 0) - matrix(1, 1) + matrix(2, 2));
48  TypedQuaternion<Type> q(matrix(0, 2) + matrix(2, 0), matrix(2, 1) + matrix(1, 2), t, matrix(1, 0) - matrix(0, 1));
49  q *= (Type(0.5) / std::sqrt(t));
50  return q;
51  }
52  else
53  {
54  const Type t = (Type(1.0) + matrix(0, 0) + matrix(1, 1) + matrix(2, 2));
55  TypedQuaternion<Type> q(matrix(2, 1) - matrix(1, 2), matrix(0, 2) - matrix(2, 0), matrix(1, 0) - matrix(0, 1), t);
56  q *= (Type(0.5) / std::sqrt(t));
57  return q;
58  }
59  }
60 }
61 
64 {
65  TurtleBrains::Math::TypedMatrix4<Type> matrix = realMatrix.GetTransposed();
66 
67  Type fourXSquaredMinus1 = matrix(0, 0) - matrix(1, 1) - matrix(2, 2);
68  Type fourYSquaredMinus1 = matrix(1, 1) - matrix(0, 0) - matrix(2, 2);
69  Type fourZSquaredMinus1 = matrix(2, 2) - matrix(0, 0) - matrix(1, 1);
70  Type fourWSquaredMinus1 = matrix(0, 0) + matrix(1, 1) + matrix(2, 2);
71 
72  int biggestIndex = 0;
73  Type fourBiggestSquaredMinus1 = fourWSquaredMinus1;
74  if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)
75  {
76  fourBiggestSquaredMinus1 = fourXSquaredMinus1;
77  biggestIndex = 1;
78  }
79  if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)
80  {
81  fourBiggestSquaredMinus1 = fourYSquaredMinus1;
82  biggestIndex = 2;
83  }
84  if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)
85  {
86  fourBiggestSquaredMinus1 = fourZSquaredMinus1;
87  biggestIndex = 3;
88  }
89 
90  Type biggestVal = std::sqrt(fourBiggestSquaredMinus1 + static_cast<Type>(1)) * static_cast<Type>(0.5);
91  Type mult = static_cast<Type>(0.25) / biggestVal;
92 
93  switch (biggestIndex)
94  {
95  case 0:
96  return TypedQuaternion<Type>((matrix(1, 2) - matrix(2, 1)) * mult, (matrix(2, 0) - matrix(0, 2)) * mult, (matrix(0, 1) - matrix(1, 0)) * mult, biggestVal);
97  case 1:
98  return TypedQuaternion<Type>(biggestVal, (matrix(0, 1) + matrix(1, 0)) * mult, (matrix(2, 0) + matrix(0, 2)) * mult, (matrix(1, 2) - matrix(2, 1)) * mult);
99  case 2:
100  return TypedQuaternion<Type>((matrix(0, 1) + matrix(1, 0)) * mult, biggestVal, (matrix(1, 2) + matrix(2, 1)) * mult, (matrix(2, 0) - matrix(0, 2)) * mult);
101  case 3:
102  return TypedQuaternion<Type>((matrix(2, 0) + matrix(0, 2)) * mult, (matrix(1, 2) + matrix(2, 1)) * mult, biggestVal, (matrix(0, 1) - matrix(1, 0)) * mult);
103  default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity.
104  tb_error("Something went bad with quat from matrix.");
105  return TypedQuaternion<Type>(Type(0.0), Type(0.0), Type(0.0), Type(1.0));
106  }
107 
108 
109 
110 
111 
112 
113 
114  //if (matrix(2, 2) < 0.0f)
115  //{
116  // if (matrix(0, 0) > matrix(1, 1))
117  // {
118  // const Type trace = (Type(1.0) + matrix(0, 0) - matrix(1, 1) - matrix(2, 2));
119  // TypedQuaternion<Type> q(trace, matrix(1, 0) + matrix(0, 1), matrix(0, 2) + matrix(2, 0), matrix(2, 1) - matrix(1, 2));
120  // q *= Type(0.5) / std::sqrt(trace);
121  // return q;
122  // }
123  // else
124  // {
125  // const Type trace = (Type(1.0) - matrix(0, 0) + matrix(1, 1) - matrix(2, 2));
126  // TypedQuaternion<Type> q(matrix(1, 0) + matrix(0, 1), trace, matrix(2, 1) + matrix(1, 2), matrix(0, 2) - matrix(2, 0));
127  // q *= Type(0.5) / std::sqrt(trace);
128  // return q;
129  // }
130  //}
131  //else
132  //{
133  // if (matrix(0, 0) < -matrix(1, 1))
134  // {
135  // const Type trace = (Type(1.0) - matrix(0, 0) - matrix(1, 1) + matrix(2, 2));
136  // TypedQuaternion<Type> q(matrix(0, 2) + matrix(2, 0), matrix(2, 1) + matrix(1, 2), trace, matrix(1, 0) - matrix(0, 1));
137  // q *= Type(0.5) / std::sqrt(trace);
138  // return q;
139  // }
140  // else
141  // {
142  // const Type trace = (Type(1.0) + matrix(0, 0) + matrix(1, 1) + matrix(2, 2));
143  // TypedQuaternion q(matrix(2, 1) - matrix(1, 2), matrix(0, 2) - matrix(2, 0), matrix(1, 0) - matrix(0, 1), trace);
144  // q *= Type(0.5) / std::sqrt(trace);
145  // return q;
146  // }
147  //}
148 }
149 
152 { //http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
153  const Type& qx(quaternion.x);
154  const Type& qy(quaternion.y);
155  const Type& qz(quaternion.z);
156  const Type& qw(quaternion.w);
157 
158  const Type qxSq(quaternion.x * quaternion.x);
159  const Type qySq(quaternion.y * quaternion.y);
160  const Type qzSq(quaternion.z * quaternion.z);
161 
162  //The resource mentioned this expected the quaternion to be normalized; thought if it is not normalized
163  //the sqrt can be thrown away by performing the normalization after calculating the products..
164  return TypedMatrix3<Type>(
165  Type(1.0) - Type(2.0) * qySq - Type(2.0) * qzSq, Type(2.0) * qx * qy - Type(2.0) * qz * qw, Type(2.0) * qx * qz + Type(2.0) * qy * qw,
166  Type(2.0) * qx * qy + Type(2.0) * qz * qw, Type(1.0) - Type(2.0) * qxSq - Type(2.0) * qzSq, Type(2.0) * qy * qz - Type(2.0) * qx * qw,
167  Type(2.0) * qx * qz - Type(2.0) * qy * qw, Type(2.0) * qy * qz + Type(2.0) * qx * qw, Type(1.0) - Type(2.0) * qxSq - Type(2.0) * qySq);
168 
169  //This is actually the expected values, but it fails the tests and the above passes. Keeping this block around
170  //until such a time comes that Matrix3 gets some attention. Note: This IS the correct block, 2019-01-01
171  //return Matrix3(
172  // 1.0f - 2.0f * qySq - 2.0f * qzSq, 2.0f * qx * qy + 2.0f * qz * qw, 2.0f * qx * qz - 2.0f * qy * qw,
173  // 2.0f * qx * qy - 2.0f * qz * qw, 1.0f - 2.0f * qxSq - 2.0f * qzSq, 2.0f * qy * qz + 2.0f * qx * qw,
174  // 2.0f * qx * qz + 2.0f * qy * qw, 2.0f * qy * qz - 2.0f * qx * qw, 1.0f - 2.0f * qxSq - 2.0f * qySq);
175 }
176 
179 {
180  const Type& qx(quaternion.x);
181  const Type& qy(quaternion.y);
182  const Type& qz(quaternion.z);
183  const Type& qw(quaternion.w);
184 
185  const Type qxSq(quaternion.x * quaternion.x);
186  const Type qySq(quaternion.y * quaternion.y);
187  const Type qzSq(quaternion.z * quaternion.z);
188 
189  //The resource mentioned this expected the quaternion to be normalized; thought if it is not normalized
190  //the sqrt can be thrown away by performing the normalization after calculating the products...
191  return TypedMatrix4<Type>(
192  Type(1.0) - Type(2.0) * qySq - Type(2.0) * qzSq, Type(2.0) * qx * qy + Type(2.0) * qz * qw, Type(2.0) * qx * qz - Type(2.0) * qy * qw, Type(0.0),
193  Type(2.0) * qx * qy - Type(2.0) * qz * qw, Type(1.0) - Type(2.0) * qxSq - Type(2.0) * qzSq, Type(2.0) * qy * qz + Type(2.0) * qx * qw, Type(0.0),
194  Type(2.0) * qx * qz + Type(2.0) * qy * qw, Type(2.0) * qy * qz - Type(2.0) * qx * qw, Type(1.0) - Type(2.0) * qxSq - Type(2.0) * qySq, Type(0.0),
195  translation.x, translation.y, translation.z, Type(1.0));
196 }
197 
198 #endif /* TurtleBrains_MatrixQuaternion_hpp */
Definition: tb_matrix.hpp:156
Definition: tb_matrix.hpp:596
Definition: tb_quaternion.hpp:41
Definition: tb_vector.hpp:472
#define tb_error(message,...)
Definition: tb_error.hpp:23