TrueSync
TSQuaternion.cs
1 /* Copyright (C) <2009-2011> <Thorben Linneweber, Jitter Physics>
2 *
3 * This software is provided 'as-is', without any express or implied
4 * warranty. In no event will the authors be held liable for any damages
5 * arising from the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 *
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
15 * 2. Altered source versions must be plainly marked as such, and must not be
16 * misrepresented as being the original software.
17 * 3. This notice may not be removed or altered from any source distribution.
18 */
19 
20 using System;
21 
22 namespace TrueSync
23 {
24 
28  [Serializable]
29  public struct TSQuaternion
30  {
31 
33  public FP x;
35  public FP y;
37  public FP z;
39  public FP w;
40 
41  public static readonly TSQuaternion identity;
42 
43  static TSQuaternion() {
44  identity = new TSQuaternion(0, 0, 0, 1);
45  }
46 
54  public TSQuaternion(FP x, FP y, FP z, FP w)
55  {
56  this.x = x;
57  this.y = y;
58  this.z = z;
59  this.w = w;
60  }
61 
62  public void Set(FP new_x, FP new_y, FP new_z, FP new_w) {
63  this.x = new_x;
64  this.y = new_y;
65  this.z = new_z;
66  this.w = new_w;
67  }
68 
69  public void SetFromToRotation(TSVector fromDirection, TSVector toDirection) {
70  TSQuaternion targetRotation = TSQuaternion.FromToRotation(fromDirection, toDirection);
71  this.Set(targetRotation.x, targetRotation.y, targetRotation.z, targetRotation.w);
72  }
73 
74  public TSVector eulerAngles {
75  get {
76  TSVector result = new TSVector();
77 
78  FP ysqr = y * y;
79  FP t0 = -2.0f * (ysqr + z * z) + 1.0f;
80  FP t1 = +2.0f * (x * y - w * z);
81  FP t2 = -2.0f * (x * z + w * y);
82  FP t3 = +2.0f * (y * z - w * x);
83  FP t4 = -2.0f * (x * x + ysqr) + 1.0f;
84 
85  t2 = t2 > 1.0f ? 1.0f : t2;
86  t2 = t2 < -1.0f ? -1.0f : t2;
87 
88  result.x = FP.Atan2(t3, t4) * FP.Rad2Deg;
89  result.y = FP.Asin(t2) * FP.Rad2Deg;
90  result.z = FP.Atan2(t1, t0) * FP.Rad2Deg;
91 
92  return result * -1;
93  }
94  }
95 
96  public static FP Angle(TSQuaternion a, TSQuaternion b) {
97  TSQuaternion aInv = TSQuaternion.Inverse(a);
98  TSQuaternion f = b * aInv;
99 
100  FP angle = FP.Acos(f.w) * 2 * FP.Rad2Deg;
101 
102  if (angle > 180) {
103  angle = 360 - angle;
104  }
105 
106  return angle;
107  }
108 
115  #region public static JQuaternion Add(JQuaternion quaternion1, JQuaternion quaternion2)
116  public static TSQuaternion Add(TSQuaternion quaternion1, TSQuaternion quaternion2)
117  {
118  TSQuaternion result;
119  TSQuaternion.Add(ref quaternion1, ref quaternion2, out result);
120  return result;
121  }
122 
123  public static TSQuaternion Euler(FP x, FP y, FP z) {
124  x *= FP.Deg2Rad;
125  y *= FP.Deg2Rad;
126  z *= FP.Deg2Rad;
127 
128  TSQuaternion rotation;
129  TSQuaternion.CreateFromYawPitchRoll(y, x, z, out rotation);
130 
131  return rotation;
132  }
133 
134  public static TSQuaternion Euler(TSVector eulerAngles) {
135  return Euler(eulerAngles.x, eulerAngles.y, eulerAngles.z);
136  }
137 
138  public static TSQuaternion AngleAxis(FP angle, TSVector axis) {
139  axis = axis * FP.Deg2Rad;
140  axis.Normalize();
141 
142  FP halfAngle = angle * FP.Deg2Rad * FP.Half;
143 
144  TSQuaternion rotation;
145  FP sin = FP.Sin(halfAngle);
146 
147  rotation.x = axis.x * sin;
148  rotation.y = axis.y * sin;
149  rotation.z = axis.z * sin;
150  rotation.w = FP.Cos(halfAngle);
151 
152  return rotation;
153  }
154 
155  public static void CreateFromYawPitchRoll(FP yaw, FP pitch, FP roll, out TSQuaternion result)
156  {
157  FP num9 = roll * FP.Half;
158  FP num6 = FP.Sin(num9);
159  FP num5 = FP.Cos(num9);
160  FP num8 = pitch * FP.Half;
161  FP num4 = FP.Sin(num8);
162  FP num3 = FP.Cos(num8);
163  FP num7 = yaw * FP.Half;
164  FP num2 = FP.Sin(num7);
165  FP num = FP.Cos(num7);
166  result.x = ((num * num4) * num5) + ((num2 * num3) * num6);
167  result.y = ((num2 * num3) * num5) - ((num * num4) * num6);
168  result.z = ((num * num3) * num6) - ((num2 * num4) * num5);
169  result.w = ((num * num3) * num5) + ((num2 * num4) * num6);
170  }
171 
178  public static void Add(ref TSQuaternion quaternion1, ref TSQuaternion quaternion2, out TSQuaternion result)
179  {
180  result.x = quaternion1.x + quaternion2.x;
181  result.y = quaternion1.y + quaternion2.y;
182  result.z = quaternion1.z + quaternion2.z;
183  result.w = quaternion1.w + quaternion2.w;
184  }
185  #endregion
186 
187  public static TSQuaternion Conjugate(TSQuaternion value)
188  {
189  TSQuaternion quaternion;
190  quaternion.x = -value.x;
191  quaternion.y = -value.y;
192  quaternion.z = -value.z;
193  quaternion.w = value.w;
194  return quaternion;
195  }
196 
197  public static FP Dot(TSQuaternion a, TSQuaternion b) {
198  return a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
199  }
200 
201  public static TSQuaternion Inverse(TSQuaternion rotation) {
202  FP invNorm = FP.One / ((rotation.x * rotation.x) + (rotation.y * rotation.y) + (rotation.z * rotation.z) + (rotation.w * rotation.w));
203  return TSQuaternion.Multiply(TSQuaternion.Conjugate(rotation), invNorm);
204  }
205 
206  public static TSQuaternion FromToRotation(TSVector fromVector, TSVector toVector) {
207  TSVector w = TSVector.Cross(fromVector, toVector);
208  TSQuaternion q = new TSQuaternion(w.x, w.y, w.z, TSVector.Dot(fromVector, toVector));
209  q.w += FP.Sqrt(fromVector.sqrMagnitude * toVector.sqrMagnitude);
210  q.Normalize();
211 
212  return q;
213  }
214 
215  public static TSQuaternion Lerp(TSQuaternion a, TSQuaternion b, FP t) {
216  t = TSMath.Clamp(t, FP.Zero, FP.One);
217 
218  return LerpUnclamped(a, b, t);
219  }
220 
221  public static TSQuaternion LerpUnclamped(TSQuaternion a, TSQuaternion b, FP t) {
222  TSQuaternion result = TSQuaternion.Multiply(a, (1 - t)) + TSQuaternion.Multiply(b, t);
223  result.Normalize();
224 
225  return result;
226  }
227 
234  #region public static JQuaternion Subtract(JQuaternion quaternion1, JQuaternion quaternion2)
235  public static TSQuaternion Subtract(TSQuaternion quaternion1, TSQuaternion quaternion2)
236  {
237  TSQuaternion result;
238  TSQuaternion.Subtract(ref quaternion1, ref quaternion2, out result);
239  return result;
240  }
241 
248  public static void Subtract(ref TSQuaternion quaternion1, ref TSQuaternion quaternion2, out TSQuaternion result)
249  {
250  result.x = quaternion1.x - quaternion2.x;
251  result.y = quaternion1.y - quaternion2.y;
252  result.z = quaternion1.z - quaternion2.z;
253  result.w = quaternion1.w - quaternion2.w;
254  }
255  #endregion
256 
263  #region public static JQuaternion Multiply(JQuaternion quaternion1, JQuaternion quaternion2)
264  public static TSQuaternion Multiply(TSQuaternion quaternion1, TSQuaternion quaternion2)
265  {
266  TSQuaternion result;
267  TSQuaternion.Multiply(ref quaternion1, ref quaternion2, out result);
268  return result;
269  }
270 
277  public static void Multiply(ref TSQuaternion quaternion1, ref TSQuaternion quaternion2, out TSQuaternion result)
278  {
279  FP x = quaternion1.x;
280  FP y = quaternion1.y;
281  FP z = quaternion1.z;
282  FP w = quaternion1.w;
283  FP num4 = quaternion2.x;
284  FP num3 = quaternion2.y;
285  FP num2 = quaternion2.z;
286  FP num = quaternion2.w;
287  FP num12 = (y * num2) - (z * num3);
288  FP num11 = (z * num4) - (x * num2);
289  FP num10 = (x * num3) - (y * num4);
290  FP num9 = ((x * num4) + (y * num3)) + (z * num2);
291  result.x = ((x * num) + (num4 * w)) + num12;
292  result.y = ((y * num) + (num3 * w)) + num11;
293  result.z = ((z * num) + (num2 * w)) + num10;
294  result.w = (w * num) - num9;
295  }
296  #endregion
297 
304  #region public static JQuaternion Multiply(JQuaternion quaternion1, FP scaleFactor)
305  public static TSQuaternion Multiply(TSQuaternion quaternion1, FP scaleFactor)
306  {
307  TSQuaternion result;
308  TSQuaternion.Multiply(ref quaternion1, scaleFactor, out result);
309  return result;
310  }
311 
318  public static void Multiply(ref TSQuaternion quaternion1, FP scaleFactor, out TSQuaternion result)
319  {
320  result.x = quaternion1.x * scaleFactor;
321  result.y = quaternion1.y * scaleFactor;
322  result.z = quaternion1.z * scaleFactor;
323  result.w = quaternion1.w * scaleFactor;
324  }
325  #endregion
326 
330  #region public void Normalize()
331  public void Normalize()
332  {
333  FP num2 = (((this.x * this.x) + (this.y * this.y)) + (this.z * this.z)) + (this.w * this.w);
334  FP num = 1 / (FP.Sqrt(num2));
335  this.x *= num;
336  this.y *= num;
337  this.z *= num;
338  this.w *= num;
339  }
340  #endregion
341 
347  #region public static JQuaternion CreateFromMatrix(JMatrix matrix)
348  public static TSQuaternion CreateFromMatrix(TSMatrix matrix)
349  {
350  TSQuaternion result;
351  TSQuaternion.CreateFromMatrix(ref matrix, out result);
352  return result;
353  }
354 
360  public static void CreateFromMatrix(ref TSMatrix matrix, out TSQuaternion result)
361  {
362  FP num8 = (matrix.M11 + matrix.M22) + matrix.M33;
363  if (num8 > FP.Zero)
364  {
365  FP num = FP.Sqrt((num8 + FP.One));
366  result.w = num * FP.Half;
367  num = FP.Half / num;
368  result.x = (matrix.M23 - matrix.M32) * num;
369  result.y = (matrix.M31 - matrix.M13) * num;
370  result.z = (matrix.M12 - matrix.M21) * num;
371  }
372  else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
373  {
374  FP num7 = FP.Sqrt((((FP.One + matrix.M11) - matrix.M22) - matrix.M33));
375  FP num4 = FP.Half / num7;
376  result.x = FP.Half * num7;
377  result.y = (matrix.M12 + matrix.M21) * num4;
378  result.z = (matrix.M13 + matrix.M31) * num4;
379  result.w = (matrix.M23 - matrix.M32) * num4;
380  }
381  else if (matrix.M22 > matrix.M33)
382  {
383  FP num6 = FP.Sqrt((((FP.One + matrix.M22) - matrix.M11) - matrix.M33));
384  FP num3 = FP.Half / num6;
385  result.x = (matrix.M21 + matrix.M12) * num3;
386  result.y = FP.Half * num6;
387  result.z = (matrix.M32 + matrix.M23) * num3;
388  result.w = (matrix.M31 - matrix.M13) * num3;
389  }
390  else
391  {
392  FP num5 = FP.Sqrt((((FP.One + matrix.M33) - matrix.M11) - matrix.M22));
393  FP num2 = FP.Half / num5;
394  result.x = (matrix.M31 + matrix.M13) * num2;
395  result.y = (matrix.M32 + matrix.M23) * num2;
396  result.z = FP.Half * num5;
397  result.w = (matrix.M12 - matrix.M21) * num2;
398  }
399  }
400  #endregion
401 
408  #region public static FP operator *(JQuaternion value1, JQuaternion value2)
409  public static TSQuaternion operator *(TSQuaternion value1, TSQuaternion value2)
410  {
411  TSQuaternion result;
412  TSQuaternion.Multiply(ref value1, ref value2,out result);
413  return result;
414  }
415  #endregion
416 
423  #region public static FP operator +(JQuaternion value1, JQuaternion value2)
424  public static TSQuaternion operator +(TSQuaternion value1, TSQuaternion value2)
425  {
426  TSQuaternion result;
427  TSQuaternion.Add(ref value1, ref value2, out result);
428  return result;
429  }
430  #endregion
431 
438  #region public static FP operator -(JQuaternion value1, JQuaternion value2)
439  public static TSQuaternion operator -(TSQuaternion value1, TSQuaternion value2)
440  {
441  TSQuaternion result;
442  TSQuaternion.Subtract(ref value1, ref value2, out result);
443  return result;
444  }
445  #endregion
446 
450  public static TSVector operator *(TSQuaternion quat, TSVector vec) {
451  FP num = quat.x * 2f;
452  FP num2 = quat.y * 2f;
453  FP num3 = quat.z * 2f;
454  FP num4 = quat.x * num;
455  FP num5 = quat.y * num2;
456  FP num6 = quat.z * num3;
457  FP num7 = quat.x * num2;
458  FP num8 = quat.x * num3;
459  FP num9 = quat.y * num3;
460  FP num10 = quat.w * num;
461  FP num11 = quat.w * num2;
462  FP num12 = quat.w * num3;
463 
464  TSVector result;
465  result.x = (1f - (num5 + num6)) * vec.x + (num7 - num12) * vec.y + (num8 + num11) * vec.z;
466  result.y = (num7 + num12) * vec.x + (1f - (num4 + num6)) * vec.y + (num9 - num10) * vec.z;
467  result.z = (num8 - num11) * vec.x + (num9 + num10) * vec.y + (1f - (num4 + num5)) * vec.z;
468 
469  return result;
470  }
471 
472  public override string ToString() {
473  return string.Format("({0:f1}, {1:f1}, {2:f1}, {3:f1})", x.AsFloat(), y.AsFloat(), z.AsFloat(), w.AsFloat());
474  }
475 
476  }
477 }
static TSQuaternion operator*(TSQuaternion value1, TSQuaternion value2)
Multiply two quaternions.
void Normalize()
Sets the length of the quaternion to one.
FP y
The Y component of the vector.
Definition: TSVector.cs:39
FP y
The Y component of the quaternion.
Definition: TSQuaternion.cs:35
static void CreateFromMatrix(ref TSMatrix matrix, out TSQuaternion result)
Creates a quaternion from a matrix.
static void Subtract(ref TSQuaternion quaternion1, ref TSQuaternion quaternion2, out TSQuaternion result)
Quaternions are subtracted.
static void Multiply(ref TSQuaternion quaternion1, FP scaleFactor, out TSQuaternion result)
Scale a quaternion
A vector structure.
Definition: TSVector.cs:29
static FP Clamp(FP value, FP min, FP max)
Returns a number which is within [min,max]
Definition: TSMath.cs:110
static FP Dot(TSVector vector1, TSVector vector2)
Calculates the dot product of two vectors.
Definition: TSVector.cs:418
static TSQuaternion operator-(TSQuaternion value1, TSQuaternion value2)
Subtract two quaternions.
Contains common math operations.
Definition: TSMath.cs:25
FP z
The Z component of the vector.
Definition: TSVector.cs:41
static TSQuaternion CreateFromMatrix(TSMatrix matrix)
Creates a quaternion from a matrix.
static TSQuaternion Subtract(TSQuaternion quaternion1, TSQuaternion quaternion2)
Quaternions are subtracted.
static TSQuaternion Add(TSQuaternion quaternion1, TSQuaternion quaternion2)
Quaternions are added.
TSQuaternion(FP x, FP y, FP z, FP w)
Initializes a new instance of the JQuaternion structure.
Definition: TSQuaternion.cs:54
FP z
The Z component of the quaternion.
Definition: TSQuaternion.cs:37
static TSQuaternion operator+(TSQuaternion value1, TSQuaternion value2)
Add two quaternions.
static TSVector Cross(TSVector vector1, TSVector vector2)
The cross product of two vectors.
Definition: TSVector.cs:531
FP sqrMagnitude
Gets the squared length of the vector.
Definition: TSVector.cs:114
static TSVector Normalize(TSVector value)
Normalizes the given vector.
Definition: TSVector.cs:612
static void Multiply(ref TSQuaternion quaternion1, ref TSQuaternion quaternion2, out TSQuaternion result)
Multiply two quaternions.
static TSQuaternion Multiply(TSQuaternion quaternion1, FP scaleFactor)
Scale a quaternion
FP x
The X component of the quaternion.
Definition: TSQuaternion.cs:33
3x3 Matrix.
Definition: TSMatrix.cs:26
FP x
The X component of the vector.
Definition: TSVector.cs:37
FP w
The W component of the quaternion.
Definition: TSQuaternion.cs:39
A Quaternion representing an orientation.
Definition: TSQuaternion.cs:29
static void Add(ref TSQuaternion quaternion1, ref TSQuaternion quaternion2, out TSQuaternion result)
Quaternions are added.
static TSQuaternion Multiply(TSQuaternion quaternion1, TSQuaternion quaternion2)
Multiply two quaternions.