Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Quaternion.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under MIT License. See LICENSE.md for details.
3 //
4 // -----------------------------------------------------------------------------
5 // Original code from SlimMath project. http://code.google.com/p/slimmath/
6 // Greetings to SlimDX Group. Original code published with the following license:
7 // -----------------------------------------------------------------------------
8 /*
9 * Copyright (c) 2007-2011 SlimDX Group
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 */
29 using System;
30 using System.Collections.Generic;
31 using System.Text;
32 using System.Runtime.InteropServices;
33 using System.ComponentModel;
34 using System.Globalization;
35 using SiliconStudio.Core.Serialization;
36 
37 namespace SiliconStudio.Core.Mathematics
38 {
39  /// <summary>
40  /// Represents a four dimensional mathematical quaternion.
41  /// </summary>
42  [DataContract("quaternion")]
43  [DataStyle(DataStyle.Compact)]
44  [StructLayout(LayoutKind.Sequential, Pack = 4)]
45  public struct Quaternion : IEquatable<Quaternion>, IFormattable
46  {
47  /// <summary>
48  /// The size of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> type, in bytes.
49  /// </summary>
50  public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Quaternion));
51 
52  /// <summary>
53  /// A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> with all of its components set to zero.
54  /// </summary>
55  public static readonly Quaternion Zero = new Quaternion();
56 
57  /// <summary>
58  /// A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> with all of its components set to one.
59  /// </summary>
60  public static readonly Quaternion One = new Quaternion(1.0f, 1.0f, 1.0f, 1.0f);
61 
62  /// <summary>
63  /// The identity <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> (0, 0, 0, 1).
64  /// </summary>
65  public static readonly Quaternion Identity = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
66 
67  /// <summary>
68  /// The X component of the quaternion.
69  /// </summary>
70  public float X;
71 
72  /// <summary>
73  /// The Y component of the quaternion.
74  /// </summary>
75  public float Y;
76 
77  /// <summary>
78  /// The Z component of the quaternion.
79  /// </summary>
80  public float Z;
81 
82  /// <summary>
83  /// The W component of the quaternion.
84  /// </summary>
85  public float W;
86 
87  /// <summary>
88  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> struct.
89  /// </summary>
90  /// <param name="value">The value that will be assigned to all components.</param>
91  public Quaternion(float value)
92  {
93  X = value;
94  Y = value;
95  Z = value;
96  W = value;
97  }
98 
99  /// <summary>
100  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> struct.
101  /// </summary>
102  /// <param name="value">A vector containing the values with which to initialize the components.</param>
103  public Quaternion(Vector4 value)
104  {
105  X = value.X;
106  Y = value.Y;
107  Z = value.Z;
108  W = value.W;
109  }
110 
111  /// <summary>
112  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> struct.
113  /// </summary>
114  /// <param name="value">A vector containing the values with which to initialize the X, Y, and Z components.</param>
115  /// <param name="w">Initial value for the W component of the quaternion.</param>
116  public Quaternion(Vector3 value, float w)
117  {
118  X = value.X;
119  Y = value.Y;
120  Z = value.Z;
121  W = w;
122  }
123 
124  /// <summary>
125  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> struct.
126  /// </summary>
127  /// <param name="value">A vector containing the values with which to initialize the X and Y components.</param>
128  /// <param name="z">Initial value for the Z component of the quaternion.</param>
129  /// <param name="w">Initial value for the W component of the quaternion.</param>
130  public Quaternion(Vector2 value, float z, float w)
131  {
132  X = value.X;
133  Y = value.Y;
134  Z = z;
135  W = w;
136  }
137 
138  /// <summary>
139  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> struct.
140  /// </summary>
141  /// <param name="x">Initial value for the X component of the quaternion.</param>
142  /// <param name="y">Initial value for the Y component of the quaternion.</param>
143  /// <param name="z">Initial value for the Z component of the quaternion.</param>
144  /// <param name="w">Initial value for the W component of the quaternion.</param>
145  public Quaternion(float x, float y, float z, float w)
146  {
147  X = x;
148  Y = y;
149  Z = z;
150  W = w;
151  }
152 
153  /// <summary>
154  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> struct.
155  /// </summary>
156  /// <param name="values">The values to assign to the X, Y, Z, and W components of the quaternion. This must be an array with four elements.</param>
157  /// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
158  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than four elements.</exception>
159  public Quaternion(float[] values)
160  {
161  if (values == null)
162  throw new ArgumentNullException("values");
163  if (values.Length != 4)
164  throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Quaternion.");
165 
166  X = values[0];
167  Y = values[1];
168  Z = values[2];
169  W = values[3];
170  }
171 
172  /// <summary>
173  /// Gets a value indicating whether this instance is equivalent to the identity quaternion.
174  /// </summary>
175  /// <value>
176  /// <c>true</c> if this instance is an identity quaternion; otherwise, <c>false</c>.
177  /// </value>
178  public bool IsIdentity
179  {
180  get { return this.Equals(Identity); }
181  }
182 
183  /// <summary>
184  /// Gets a value indicting whether this instance is normalized.
185  /// </summary>
186  public bool IsNormalized
187  {
188  get { return Math.Abs((X * X) + (Y * Y) + (Z * Z) + (W * W) - 1f) < MathUtil.ZeroTolerance; }
189  }
190 
191  /// <summary>
192  /// Gets the angle of the quaternion.
193  /// </summary>
194  /// <value>The quaternion's angle.</value>
195  public float Angle
196  {
197  get
198  {
199  float length = (X * X) + (Y * Y) + (Z * Z);
200  if (length < MathUtil.ZeroTolerance)
201  return 0.0f;
202 
203  return (float)(2.0 * Math.Acos(W));
204  }
205  }
206 
207  /// <summary>
208  /// Gets the axis components of the quaternion.
209  /// </summary>
210  /// <value>The axis components of the quaternion.</value>
211  public Vector3 Axis
212  {
213  get
214  {
215  float length = (X * X) + (Y * Y) + (Z * Z);
216  if (length < MathUtil.ZeroTolerance)
217  return Vector3.UnitX;
218 
219  float inv = 1.0f / length;
220  return new Vector3(X * inv, Y * inv, Z * inv);
221  }
222  }
223 
224  /// <summary>
225  /// Gets or sets the component at the specified index.
226  /// </summary>
227  /// <value>The value of the X, Y, Z, or W component, depending on the index.</value>
228  /// <param name="index">The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component.</param>
229  /// <returns>The value of the component at the specified index.</returns>
230  /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 3].</exception>
231  public float this[int index]
232  {
233  get
234  {
235  switch (index)
236  {
237  case 0: return X;
238  case 1: return Y;
239  case 2: return Z;
240  case 3: return W;
241  }
242 
243  throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive.");
244  }
245 
246  set
247  {
248  switch (index)
249  {
250  case 0: X = value; break;
251  case 1: Y = value; break;
252  case 2: Z = value; break;
253  case 3: W = value; break;
254  default: throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive.");
255  }
256  }
257  }
258 
259  /// <summary>
260  /// Conjugates the quaternion.
261  /// </summary>
262  public void Conjugate()
263  {
264  X = -X;
265  Y = -Y;
266  Z = -Z;
267  }
268 
269  /// <summary>
270  /// Conjugates and renormalizes the quaternion.
271  /// </summary>
272  public void Invert()
273  {
274  float lengthSq = LengthSquared();
275  if (lengthSq > MathUtil.ZeroTolerance)
276  {
277  lengthSq = 1.0f / lengthSq;
278 
279  X = -X * lengthSq;
280  Y = -Y * lengthSq;
281  Z = -Z * lengthSq;
282  W = W * lengthSq;
283  }
284  }
285 
286  /// <summary>
287  /// Calculates the length of the quaternion.
288  /// </summary>
289  /// <returns>The length of the quaternion.</returns>
290  /// <remarks>
291  /// <see cref="SiliconStudio.Core.Mathematics.Quaternion.LengthSquared"/> may be preferred when only the relative length is needed
292  /// and speed is of the essence.
293  /// </remarks>
294  public float Length()
295  {
296  return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W));
297  }
298 
299  /// <summary>
300  /// Calculates the squared length of the quaternion.
301  /// </summary>
302  /// <returns>The squared length of the quaternion.</returns>
303  /// <remarks>
304  /// This method may be preferred to <see cref="SiliconStudio.Core.Mathematics.Quaternion.Length"/> when only a relative length is needed
305  /// and speed is of the essence.
306  /// </remarks>
307  public float LengthSquared()
308  {
309  return (X * X) + (Y * Y) + (Z * Z) + (W * W);
310  }
311 
312  /// <summary>
313  /// Converts the quaternion into a unit quaternion.
314  /// </summary>
315  public void Normalize()
316  {
317  float length = Length();
318  if (length > MathUtil.ZeroTolerance)
319  {
320  float inverse = 1.0f / length;
321  X *= inverse;
322  Y *= inverse;
323  Z *= inverse;
324  W *= inverse;
325  }
326  }
327 
328  /// <summary>
329  /// Creates an array containing the elements of the quaternion.
330  /// </summary>
331  /// <returns>A four-element array containing the components of the quaternion.</returns>
332  public float[] ToArray()
333  {
334  return new float[] { X, Y, Z, W };
335  }
336 
337  /// <summary>
338  /// Adds two quaternions.
339  /// </summary>
340  /// <param name="left">The first quaternion to add.</param>
341  /// <param name="right">The second quaternion to add.</param>
342  /// <param name="result">When the method completes, contains the sum of the two quaternions.</param>
343  public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result)
344  {
345  result.X = left.X + right.X;
346  result.Y = left.Y + right.Y;
347  result.Z = left.Z + right.Z;
348  result.W = left.W + right.W;
349  }
350 
351  /// <summary>
352  /// Adds two quaternions.
353  /// </summary>
354  /// <param name="left">The first quaternion to add.</param>
355  /// <param name="right">The second quaternion to add.</param>
356  /// <returns>The sum of the two quaternions.</returns>
357  public static Quaternion Add(Quaternion left, Quaternion right)
358  {
359  Quaternion result;
360  Add(ref left, ref right, out result);
361  return result;
362  }
363 
364  /// <summary>
365  /// Subtracts two quaternions.
366  /// </summary>
367  /// <param name="left">The first quaternion to subtract.</param>
368  /// <param name="right">The second quaternion to subtract.</param>
369  /// <param name="result">When the method completes, contains the difference of the two quaternions.</param>
370  public static void Subtract(ref Quaternion left, ref Quaternion right, out Quaternion result)
371  {
372  result.X = left.X - right.X;
373  result.Y = left.Y - right.Y;
374  result.Z = left.Z - right.Z;
375  result.W = left.W - right.W;
376  }
377 
378  /// <summary>
379  /// Subtracts two quaternions.
380  /// </summary>
381  /// <param name="left">The first quaternion to subtract.</param>
382  /// <param name="right">The second quaternion to subtract.</param>
383  /// <returns>The difference of the two quaternions.</returns>
384  public static Quaternion Subtract(Quaternion left, Quaternion right)
385  {
386  Quaternion result;
387  Subtract(ref left, ref right, out result);
388  return result;
389  }
390 
391  /// <summary>
392  /// Scales a quaternion by the given value.
393  /// </summary>
394  /// <param name="value">The quaternion to scale.</param>
395  /// <param name="scale">The amount by which to scale the quaternion.</param>
396  /// <param name="result">When the method completes, contains the scaled quaternion.</param>
397  public static void Multiply(ref Quaternion value, float scale, out Quaternion result)
398  {
399  result.X = value.X * scale;
400  result.Y = value.Y * scale;
401  result.Z = value.Z * scale;
402  result.W = value.W * scale;
403  }
404 
405  /// <summary>
406  /// Scales a quaternion by the given value.
407  /// </summary>
408  /// <param name="value">The quaternion to scale.</param>
409  /// <param name="scale">The amount by which to scale the quaternion.</param>
410  /// <returns>The scaled quaternion.</returns>
411  public static Quaternion Multiply(Quaternion value, float scale)
412  {
413  Quaternion result;
414  Multiply(ref value, scale, out result);
415  return result;
416  }
417 
418  /// <summary>
419  /// Modulates a quaternion by another.
420  /// </summary>
421  /// <param name="left">The first quaternion to modulate.</param>
422  /// <param name="right">The second quaternion to modulate.</param>
423  /// <param name="result">When the moethod completes, contains the modulated quaternion.</param>
424  public static void Multiply(ref Quaternion left, ref Quaternion right, out Quaternion result)
425  {
426  float lx = left.X;
427  float ly = left.Y;
428  float lz = left.Z;
429  float lw = left.W;
430  float rx = right.X;
431  float ry = right.Y;
432  float rz = right.Z;
433  float rw = right.W;
434 
435  result.X = (rx * lw + lx * rw + ry * lz) - (rz * ly);
436  result.Y = (ry * lw + ly * rw + rz * lx) - (rx * lz);
437  result.Z = (rz * lw + lz * rw + rx * ly) - (ry * lx);
438  result.W = (rw * lw) - (rx * lx + ry * ly + rz * lz);
439  }
440 
441  /// <summary>
442  /// Modulates a quaternion by another.
443  /// </summary>
444  /// <param name="left">The first quaternion to modulate.</param>
445  /// <param name="right">The second quaternion to modulate.</param>
446  /// <returns>The modulated quaternion.</returns>
447  public static Quaternion Multiply(Quaternion left, Quaternion right)
448  {
449  Quaternion result;
450  Multiply(ref left, ref right, out result);
451  return result;
452  }
453 
454  /// <summary>
455  /// Reverses the direction of a given quaternion.
456  /// </summary>
457  /// <param name="value">The quaternion to negate.</param>
458  /// <param name="result">When the method completes, contains a quaternion facing in the opposite direction.</param>
459  public static void Negate(ref Quaternion value, out Quaternion result)
460  {
461  result.X = -value.X;
462  result.Y = -value.Y;
463  result.Z = -value.Z;
464  result.W = -value.W;
465  }
466 
467  /// <summary>
468  /// Reverses the direction of a given quaternion.
469  /// </summary>
470  /// <param name="value">The quaternion to negate.</param>
471  /// <returns>A quaternion facing in the opposite direction.</returns>
472  public static Quaternion Negate(Quaternion value)
473  {
474  Quaternion result;
475  Negate(ref value, out result);
476  return result;
477  }
478 
479  /// <summary>
480  /// Returns a <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle.
481  /// </summary>
482  /// <param name="value1">A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of vertex 1 of the triangle.</param>
483  /// <param name="value2">A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of vertex 2 of the triangle.</param>
484  /// <param name="value3">A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of vertex 3 of the triangle.</param>
485  /// <param name="amount1">Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in <paramref name="value2"/>).</param>
486  /// <param name="amount2">Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in <paramref name="value3"/>).</param>
487  /// <param name="result">When the method completes, contains a new <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of the specified point.</param>
488  public static void Barycentric(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, float amount1, float amount2, out Quaternion result)
489  {
490  Quaternion start, end;
491  Slerp(ref value1, ref value2, amount1 + amount2, out start);
492  Slerp(ref value1, ref value3, amount1 + amount2, out end);
493  Slerp(ref start, ref end, amount2 / (amount1 + amount2), out result);
494  }
495 
496  /// <summary>
497  /// Returns a <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle.
498  /// </summary>
499  /// <param name="value1">A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of vertex 1 of the triangle.</param>
500  /// <param name="value2">A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of vertex 2 of the triangle.</param>
501  /// <param name="value3">A <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of vertex 3 of the triangle.</param>
502  /// <param name="amount1">Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in <paramref name="value2"/>).</param>
503  /// <param name="amount2">Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in <paramref name="value3"/>).</param>
504  /// <returns>A new <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> containing the 4D Cartesian coordinates of the specified point.</returns>
505  public static Quaternion Barycentric(Quaternion value1, Quaternion value2, Quaternion value3, float amount1, float amount2)
506  {
507  Quaternion result;
508  Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result);
509  return result;
510  }
511 
512  /// <summary>
513  /// Conjugates a quaternion.
514  /// </summary>
515  /// <param name="value">The quaternion to conjugate.</param>
516  /// <param name="result">When the method completes, contains the conjugated quaternion.</param>
517  public static void Conjugate(ref Quaternion value, out Quaternion result)
518  {
519  result.X = -value.X;
520  result.Y = -value.Y;
521  result.Z = -value.Z;
522  result.W = value.W;
523  }
524 
525  /// <summary>
526  /// Conjugates a quaternion.
527  /// </summary>
528  /// <param name="value">The quaternion to conjugate.</param>
529  /// <returns>The conjugated quaternion.</returns>
530  public static Quaternion Conjugate(Quaternion value)
531  {
532  Quaternion result;
533  Conjugate(ref value, out result);
534  return result;
535  }
536 
537  /// <summary>
538  /// Calculates the dot product of two quaternions.
539  /// </summary>
540  /// <param name="left">First source quaternion.</param>
541  /// <param name="right">Second source quaternion.</param>
542  /// <param name="result">When the method completes, contains the dot product of the two quaternions.</param>
543  public static void Dot(ref Quaternion left, ref Quaternion right, out float result)
544  {
545  result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W);
546  }
547 
548  /// <summary>
549  /// Calculates the dot product of two quaternions.
550  /// </summary>
551  /// <param name="left">First source quaternion.</param>
552  /// <param name="right">Second source quaternion.</param>
553  /// <returns>The dot product of the two quaternions.</returns>
554  public static float Dot(Quaternion left, Quaternion right)
555  {
556  return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W);
557  }
558 
559  /// <summary>
560  /// Exponentiates a quaternion.
561  /// </summary>
562  /// <param name="value">The quaternion to exponentiate.</param>
563  /// <param name="result">When the method completes, contains the exponentiated quaternion.</param>
564  public static void Exponential(ref Quaternion value, out Quaternion result)
565  {
566  float angle = (float)Math.Sqrt((value.X * value.X) + (value.Y * value.Y) + (value.Z * value.Z));
567  float sin = (float)Math.Sin(angle);
568 
569  if (Math.Abs(sin) >= MathUtil.ZeroTolerance)
570  {
571  float coeff = sin / angle;
572  result.X = coeff * value.X;
573  result.Y = coeff * value.Y;
574  result.Z = coeff * value.Z;
575  }
576  else
577  {
578  result = value;
579  }
580 
581  result.W = (float)Math.Cos(angle);
582  }
583 
584  /// <summary>
585  /// Exponentiates a quaternion.
586  /// </summary>
587  /// <param name="value">The quaternion to exponentiate.</param>
588  /// <returns>The exponentiated quaternion.</returns>
589  public static Quaternion Exponential(Quaternion value)
590  {
591  Quaternion result;
592  Exponential(ref value, out result);
593  return result;
594  }
595 
596  /// <summary>
597  /// Conjugates and renormalizes the quaternion.
598  /// </summary>
599  /// <param name="value">The quaternion to conjugate and renormalize.</param>
600  /// <param name="result">When the method completes, contains the conjugated and renormalized quaternion.</param>
601  public static void Invert(ref Quaternion value, out Quaternion result)
602  {
603  result = value;
604  result.Invert();
605  }
606 
607  /// <summary>
608  /// Conjugates and renormalizes the quaternion.
609  /// </summary>
610  /// <param name="value">The quaternion to conjugate and renormalize.</param>
611  /// <returns>The conjugated and renormalized quaternion.</returns>
612  public static Quaternion Invert(Quaternion value)
613  {
614  Quaternion result;
615  Invert(ref value, out result);
616  return result;
617  }
618 
619  /// <summary>
620  /// Performs a linear interpolation between two quaternions.
621  /// </summary>
622  /// <param name="start">Start quaternion.</param>
623  /// <param name="end">End quaternion.</param>
624  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
625  /// <param name="result">When the method completes, contains the linear interpolation of the two quaternions.</param>
626  /// <remarks>
627  /// This method performs the linear interpolation based on the following formula.
628  /// <code>start + (end - start) * amount</code>
629  /// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
630  /// </remarks>
631  public static void Lerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result)
632  {
633  float inverse = 1.0f - amount;
634 
635  if (Dot(start, end) >= 0.0f)
636  {
637  result.X = (inverse * start.X) + (amount * end.X);
638  result.Y = (inverse * start.Y) + (amount * end.Y);
639  result.Z = (inverse * start.Z) + (amount * end.Z);
640  result.W = (inverse * start.W) + (amount * end.W);
641  }
642  else
643  {
644  result.X = (inverse * start.X) - (amount * end.X);
645  result.Y = (inverse * start.Y) - (amount * end.Y);
646  result.Z = (inverse * start.Z) - (amount * end.Z);
647  result.W = (inverse * start.W) - (amount * end.W);
648  }
649 
650  result.Normalize();
651  }
652 
653  /// <summary>
654  /// Performs a linear interpolation between two quaternion.
655  /// </summary>
656  /// <param name="start">Start quaternion.</param>
657  /// <param name="end">End quaternion.</param>
658  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
659  /// <returns>The linear interpolation of the two quaternions.</returns>
660  /// <remarks>
661  /// This method performs the linear interpolation based on the following formula.
662  /// <code>start + (end - start) * amount</code>
663  /// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
664  /// </remarks>
665  public static Quaternion Lerp(Quaternion start, Quaternion end, float amount)
666  {
667  Quaternion result;
668  Lerp(ref start, ref end, amount, out result);
669  return result;
670  }
671 
672  /// <summary>
673  /// Calculates the natural logarithm of the specified quaternion.
674  /// </summary>
675  /// <param name="value">The quaternion whose logarithm will be calculated.</param>
676  /// <param name="result">When the method completes, contains the natural logarithm of the quaternion.</param>
677  public static void Logarithm(ref Quaternion value, out Quaternion result)
678  {
679  if (Math.Abs(value.W) < 1.0)
680  {
681  float angle = (float)Math.Acos(value.W);
682  float sin = (float)Math.Sin(angle);
683 
684  if (Math.Abs(sin) >= MathUtil.ZeroTolerance)
685  {
686  float coeff = angle / sin;
687  result.X = value.X * coeff;
688  result.Y = value.Y * coeff;
689  result.Z = value.Z * coeff;
690  }
691  else
692  {
693  result = value;
694  }
695  }
696  else
697  {
698  result = value;
699  }
700 
701  result.W = 0.0f;
702  }
703 
704  /// <summary>
705  /// Calculates the natural logarithm of the specified quaternion.
706  /// </summary>
707  /// <param name="value">The quaternion whose logarithm will be calculated.</param>
708  /// <returns>The natural logarithm of the quaternion.</returns>
709  public static Quaternion Logarithm(Quaternion value)
710  {
711  Quaternion result;
712  Logarithm(ref value, out result);
713  return result;
714  }
715 
716  /// <summary>
717  /// Converts the quaternion into a unit quaternion.
718  /// </summary>
719  /// <param name="value">The quaternion to normalize.</param>
720  /// <param name="result">When the method completes, contains the normalized quaternion.</param>
721  public static void Normalize(ref Quaternion value, out Quaternion result)
722  {
723  Quaternion temp = value;
724  result = temp;
725  result.Normalize();
726  }
727 
728  /// <summary>
729  /// Converts the quaternion into a unit quaternion.
730  /// </summary>
731  /// <param name="value">The quaternion to normalize.</param>
732  /// <returns>The normalized quaternion.</returns>
733  public static Quaternion Normalize(Quaternion value)
734  {
735  value.Normalize();
736  return value;
737  }
738 
739  /// <summary>
740  /// Creates a quaternion given a rotation and an axis.
741  /// </summary>
742  /// <param name="axis">The axis of rotation.</param>
743  /// <param name="angle">The angle of rotation.</param>
744  /// <param name="result">When the method completes, contains the newly created quaternion.</param>
745  public static void RotationAxis(ref Vector3 axis, float angle, out Quaternion result)
746  {
747  Vector3 normalized;
748  Vector3.Normalize(ref axis, out normalized);
749 
750  float half = angle * 0.5f;
751  float sin = (float)Math.Sin(half);
752  float cos = (float)Math.Cos(half);
753 
754  result.X = normalized.X * sin;
755  result.Y = normalized.Y * sin;
756  result.Z = normalized.Z * sin;
757  result.W = cos;
758  }
759 
760  /// <summary>
761  /// Creates a quaternion given a rotation and an axis.
762  /// </summary>
763  /// <param name="axis">The axis of rotation.</param>
764  /// <param name="angle">The angle of rotation.</param>
765  /// <returns>The newly created quaternion.</returns>
766  public static Quaternion RotationAxis(Vector3 axis, float angle)
767  {
768  Quaternion result;
769  RotationAxis(ref axis, angle, out result);
770  return result;
771  }
772 
773  /// <summary>
774  /// Creates a quaternion given a rotation matrix.
775  /// </summary>
776  /// <param name="matrix">The rotation matrix.</param>
777  /// <param name="result">When the method completes, contains the newly created quaternion.</param>
778  public static void RotationMatrix(ref Matrix matrix, out Quaternion result)
779  {
780  float sqrt;
781  float half;
782  float scale = matrix.M11 + matrix.M22 + matrix.M33;
783 
784  if (scale > 0.0f)
785  {
786  sqrt = (float)Math.Sqrt(scale + 1.0f);
787  result.W = sqrt * 0.5f;
788  sqrt = 0.5f / sqrt;
789 
790  result.X = (matrix.M23 - matrix.M32) * sqrt;
791  result.Y = (matrix.M31 - matrix.M13) * sqrt;
792  result.Z = (matrix.M12 - matrix.M21) * sqrt;
793  }
794  else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
795  {
796  sqrt = (float)Math.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33);
797  half = 0.5f / sqrt;
798 
799  result.X = 0.5f * sqrt;
800  result.Y = (matrix.M12 + matrix.M21) * half;
801  result.Z = (matrix.M13 + matrix.M31) * half;
802  result.W = (matrix.M23 - matrix.M32) * half;
803  }
804  else if (matrix.M22 > matrix.M33)
805  {
806  sqrt = (float)Math.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33);
807  half = 0.5f / sqrt;
808 
809  result.X = (matrix.M21 + matrix.M12) * half;
810  result.Y = 0.5f * sqrt;
811  result.Z = (matrix.M32 + matrix.M23) * half;
812  result.W = (matrix.M31 - matrix.M13) * half;
813  }
814  else
815  {
816  sqrt = (float)Math.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22);
817  half = 0.5f / sqrt;
818 
819  result.X = (matrix.M31 + matrix.M13) * half;
820  result.Y = (matrix.M32 + matrix.M23) * half;
821  result.Z = 0.5f * sqrt;
822  result.W = (matrix.M12 - matrix.M21) * half;
823  }
824  }
825 
826  /// <summary>
827  /// Creates a quaternion given a rotation matrix.
828  /// </summary>
829  /// <param name="matrix">The rotation matrix.</param>
830  /// <returns>The newly created quaternion.</returns>
831  public static Quaternion RotationMatrix(Matrix matrix)
832  {
833  Quaternion result;
834  RotationMatrix(ref matrix, out result);
835  return result;
836  }
837 
838  /// <summary>
839  /// Creates a quaternion that rotates around the x-axis.
840  /// </summary>
841  /// <param name="angle">Angle of rotation in radians.</param>
842  /// <param name="result">When the method completes, contains the newly created quaternion.</param>
843  public static void RotationX(float angle, out Quaternion result)
844  {
845  float halfAngle = angle * 0.5f;
846  result = new Quaternion((float)Math.Sin(halfAngle), 0.0f, 0.0f, (float)Math.Cos(halfAngle));
847  }
848 
849  /// <summary>
850  /// Creates a quaternion that rotates around the x-axis.
851  /// </summary>
852  /// <param name="angle">Angle of rotation in radians.</param>
853  /// <returns>The created rotation quaternion.</returns>
854  public static Quaternion RotationX(float angle)
855  {
856  Quaternion result;
857  RotationX(angle, out result);
858  return result;
859  }
860 
861  /// <summary>
862  /// Creates a quaternion that rotates around the x-axis.
863  /// </summary>
864  /// <param name="angle">Angle of rotation in radians.</param>
865  /// <param name="result">When the method completes, contains the newly created quaternion.</param>
866  public static void RotationY(float angle, out Quaternion result)
867  {
868  float halfAngle = angle * 0.5f;
869  result = new Quaternion(0.0f, (float)Math.Sin(halfAngle), 0.0f, (float)Math.Cos(halfAngle));
870  }
871 
872  /// <summary>
873  /// Creates a quaternion that rotates around the x-axis.
874  /// </summary>
875  /// <param name="angle">Angle of rotation in radians.</param>
876  /// <returns>The created rotation quaternion.</returns>
877  public static Quaternion RotationY(float angle)
878  {
879  Quaternion result;
880  RotationY(angle, out result);
881  return result;
882  }
883 
884  /// <summary>
885  /// Creates a quaternion that rotates around the x-axis.
886  /// </summary>
887  /// <param name="angle">Angle of rotation in radians.</param>
888  /// <param name="result">When the method completes, contains the newly created quaternion.</param>
889  public static void RotationZ(float angle, out Quaternion result)
890  {
891  float halfAngle = angle * 0.5f;
892  result = new Quaternion(0.0f, 0.0f, (float)Math.Sin(halfAngle), (float)Math.Cos(halfAngle));
893  }
894 
895  /// <summary>
896  /// Creates a quaternion that rotates around the x-axis.
897  /// </summary>
898  /// <param name="angle">Angle of rotation in radians.</param>
899  /// <returns>The created rotation quaternion.</returns>
900  public static Quaternion RotationZ(float angle)
901  {
902  Quaternion result;
903  RotationZ(angle, out result);
904  return result;
905  }
906 
907  /// <summary>
908  /// Creates a quaternion given a yaw, pitch, and roll value.
909  /// </summary>
910  /// <param name="yaw">The yaw of rotation.</param>
911  /// <param name="pitch">The pitch of rotation.</param>
912  /// <param name="roll">The roll of rotation.</param>
913  /// <param name="result">When the method completes, contains the newly created quaternion.</param>
914  public static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result)
915  {
916  float halfRoll = roll * 0.5f;
917  float halfPitch = pitch * 0.5f;
918  float halfYaw = yaw * 0.5f;
919 
920  float sinRoll = (float)Math.Sin(halfRoll);
921  float cosRoll = (float)Math.Cos(halfRoll);
922  float sinPitch = (float)Math.Sin(halfPitch);
923  float cosPitch = (float)Math.Cos(halfPitch);
924  float sinYaw = (float)Math.Sin(halfYaw);
925  float cosYaw = (float)Math.Cos(halfYaw);
926 
927  result.X = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);
928  result.Y = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);
929  result.Z = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);
930  result.W = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);
931  }
932 
933  /// <summary>
934  /// Creates a quaternion given a yaw, pitch, and roll value.
935  /// </summary>
936  /// <param name="yaw">The yaw of rotation.</param>
937  /// <param name="pitch">The pitch of rotation.</param>
938  /// <param name="roll">The roll of rotation.</param>
939  /// <returns>The newly created quaternion.</returns>
940  public static Quaternion RotationYawPitchRoll(float yaw, float pitch, float roll)
941  {
942  Quaternion result;
943  RotationYawPitchRoll(yaw, pitch, roll, out result);
944  return result;
945  }
946 
947  /// <summary>
948  /// Interpolates between two quaternions, using spherical linear interpolation.
949  /// </summary>
950  /// <param name="start">Start quaternion.</param>
951  /// <param name="end">End quaternion.</param>
952  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
953  /// <param name="result">When the method completes, contains the spherical linear interpolation of the two quaternions.</param>
954  public static void Slerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result)
955  {
956  float opposite;
957  float inverse;
958  float dot = Dot(start, end);
959 
960  if (Math.Abs(dot) > 1.0f - MathUtil.ZeroTolerance)
961  {
962  inverse = 1.0f - amount;
963  opposite = amount * Math.Sign(dot);
964  }
965  else
966  {
967  float acos = (float)Math.Acos(Math.Abs(dot));
968  float invSin = (float)(1.0 / Math.Sin(acos));
969 
970  inverse = (float)Math.Sin((1.0f - amount) * acos) * invSin;
971  opposite = (float)Math.Sin(amount * acos) * invSin * Math.Sign(dot);
972  }
973 
974  result.X = (inverse * start.X) + (opposite * end.X);
975  result.Y = (inverse * start.Y) + (opposite * end.Y);
976  result.Z = (inverse * start.Z) + (opposite * end.Z);
977  result.W = (inverse * start.W) + (opposite * end.W);
978  }
979 
980  /// <summary>
981  /// Interpolates between two quaternions, using spherical linear interpolation.
982  /// </summary>
983  /// <param name="start">Start quaternion.</param>
984  /// <param name="end">End quaternion.</param>
985  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
986  /// <returns>The spherical linear interpolation of the two quaternions.</returns>
987  public static Quaternion Slerp(Quaternion start, Quaternion end, float amount)
988  {
989  Quaternion result;
990  Slerp(ref start, ref end, amount, out result);
991  return result;
992  }
993 
994  /// <summary>
995  /// Interpolates between quaternions, using spherical quadrangle interpolation.
996  /// </summary>
997  /// <param name="value1">First source quaternion.</param>
998  /// <param name="value2">Second source quaternion.</param>
999  /// <param name="value3">Thrid source quaternion.</param>
1000  /// <param name="value4">Fourth source quaternion.</param>
1001  /// <param name="amount">Value between 0 and 1 indicating the weight of interpolation.</param>
1002  /// <param name="result">When the method completes, contains the spherical quadrangle interpolation of the quaternions.</param>
1003  public static void Squad(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, ref Quaternion value4, float amount, out Quaternion result)
1004  {
1005  Quaternion start, end;
1006  Slerp(ref value1, ref value4, amount, out start);
1007  Slerp(ref value2, ref value3, amount, out end);
1008  Slerp(ref start, ref end, 2.0f * amount * (1.0f - amount), out result);
1009  }
1010 
1011  /// <summary>
1012  /// Interpolates between quaternions, using spherical quadrangle interpolation.
1013  /// </summary>
1014  /// <param name="value1">First source quaternion.</param>
1015  /// <param name="value2">Second source quaternion.</param>
1016  /// <param name="value3">Thrid source quaternion.</param>
1017  /// <param name="value4">Fourth source quaternion.</param>
1018  /// <param name="amount">Value between 0 and 1 indicating the weight of interpolation.</param>
1019  /// <returns>The spherical quadrangle interpolation of the quaternions.</returns>
1020  public static Quaternion Squad(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4, float amount)
1021  {
1022  Quaternion result;
1023  Squad(ref value1, ref value2, ref value3, ref value4, amount, out result);
1024  return result;
1025  }
1026 
1027  /// <summary>
1028  /// Sets up control points for spherical quadrangle interpolation.
1029  /// </summary>
1030  /// <param name="value1">First source quaternion.</param>
1031  /// <param name="value2">Second source quaternion.</param>
1032  /// <param name="value3">Third source quaternion.</param>
1033  /// <param name="value4">Fourth source quaternion.</param>
1034  /// <returns>An array of three quaternions that represent control points for spherical quadrangle interpolation.</returns>
1035  public static Quaternion[] SquadSetup(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4)
1036  {
1037  Quaternion q0 = (value1 + value2).LengthSquared() < (value1 - value2).LengthSquared() ? -value1 : value1;
1038  Quaternion q2 = (value2 + value3).LengthSquared() < (value2 - value3).LengthSquared() ? -value3 : value3;
1039  Quaternion q3 = (value3 + value4).LengthSquared() < (value3 - value4).LengthSquared() ? -value4 : value4;
1040  Quaternion q1 = value2;
1041 
1042  Quaternion q1Exp, q2Exp;
1043  Exponential(ref q1, out q1Exp);
1044  Exponential(ref q2, out q2Exp);
1045 
1046  Quaternion[] results = new Quaternion[3];
1047  results[0] = q1 * Exponential(-0.25f * (Logarithm(q1Exp * q2) + Logarithm(q1Exp * q0)));
1048  results[1] = q2 * Exponential(-0.25f * (Logarithm(q2Exp * q3) + Logarithm(q2Exp * q1)));
1049  results[2] = q2;
1050 
1051  return results;
1052  }
1053 
1054  /// <summary>
1055  /// Adds two quaternions.
1056  /// </summary>
1057  /// <param name="left">The first quaternion to add.</param>
1058  /// <param name="right">The second quaternion to add.</param>
1059  /// <returns>The sum of the two quaternions.</returns>
1060  public static Quaternion operator +(Quaternion left, Quaternion right)
1061  {
1062  Quaternion result;
1063  Add(ref left, ref right, out result);
1064  return result;
1065  }
1066 
1067  /// <summary>
1068  /// Subtracts two quaternions.
1069  /// </summary>
1070  /// <param name="left">The first quaternion to subtract.</param>
1071  /// <param name="right">The second quaternion to subtract.</param>
1072  /// <returns>The difference of the two quaternions.</returns>
1073  public static Quaternion operator -(Quaternion left, Quaternion right)
1074  {
1075  Quaternion result;
1076  Subtract(ref left, ref right, out result);
1077  return result;
1078  }
1079 
1080  /// <summary>
1081  /// Reverses the direction of a given quaternion.
1082  /// </summary>
1083  /// <param name="value">The quaternion to negate.</param>
1084  /// <returns>A quaternion facing in the opposite direction.</returns>
1085  public static Quaternion operator -(Quaternion value)
1086  {
1087  Quaternion result;
1088  Negate(ref value, out result);
1089  return result;
1090  }
1091 
1092  /// <summary>
1093  /// Scales a quaternion by the given value.
1094  /// </summary>
1095  /// <param name="value">The quaternion to scale.</param>
1096  /// <param name="scale">The amount by which to scale the quaternion.</param>
1097  /// <returns>The scaled quaternion.</returns>
1098  public static Quaternion operator *(float scale, Quaternion value)
1099  {
1100  Quaternion result;
1101  Multiply(ref value, scale, out result);
1102  return result;
1103  }
1104 
1105  /// <summary>
1106  /// Scales a quaternion by the given value.
1107  /// </summary>
1108  /// <param name="value">The quaternion to scale.</param>
1109  /// <param name="scale">The amount by which to scale the quaternion.</param>
1110  /// <returns>The scaled quaternion.</returns>
1111  public static Quaternion operator *(Quaternion value, float scale)
1112  {
1113  Quaternion result;
1114  Multiply(ref value, scale, out result);
1115  return result;
1116  }
1117 
1118  /// <summary>
1119  /// Multiplies a quaternion by another.
1120  /// </summary>
1121  /// <param name="left">The first quaternion to multiply.</param>
1122  /// <param name="right">The second quaternion to multiply.</param>
1123  /// <returns>The multiplied quaternion.</returns>
1124  public static Quaternion operator *(Quaternion left, Quaternion right)
1125  {
1126  Quaternion result;
1127  Multiply(ref left, ref right, out result);
1128  return result;
1129  }
1130 
1131  /// <summary>
1132  /// Tests for equality between two objects.
1133  /// </summary>
1134  /// <param name="left">The first value to compare.</param>
1135  /// <param name="right">The second value to compare.</param>
1136  /// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
1137  public static bool operator ==(Quaternion left, Quaternion right)
1138  {
1139  return left.Equals(right);
1140  }
1141 
1142  /// <summary>
1143  /// Tests for inequality between two objects.
1144  /// </summary>
1145  /// <param name="left">The first value to compare.</param>
1146  /// <param name="right">The second value to compare.</param>
1147  /// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
1148  public static bool operator !=(Quaternion left, Quaternion right)
1149  {
1150  return !left.Equals(right);
1151  }
1152 
1153  /// <summary>
1154  /// Returns a <see cref="System.String"/> that represents this instance.
1155  /// </summary>
1156  /// <returns>
1157  /// A <see cref="System.String"/> that represents this instance.
1158  /// </returns>
1159  public override string ToString()
1160  {
1161  return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
1162  }
1163 
1164  /// <summary>
1165  /// Returns a <see cref="System.String"/> that represents this instance.
1166  /// </summary>
1167  /// <param name="format">The format.</param>
1168  /// <returns>
1169  /// A <see cref="System.String"/> that represents this instance.
1170  /// </returns>
1171  public string ToString(string format)
1172  {
1173  if (format == null)
1174  return ToString();
1175 
1176  return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, CultureInfo.CurrentCulture),
1177  Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture), W.ToString(format, CultureInfo.CurrentCulture));
1178  }
1179 
1180  /// <summary>
1181  /// Returns a <see cref="System.String"/> that represents this instance.
1182  /// </summary>
1183  /// <param name="formatProvider">The format provider.</param>
1184  /// <returns>
1185  /// A <see cref="System.String"/> that represents this instance.
1186  /// </returns>
1187  public string ToString(IFormatProvider formatProvider)
1188  {
1189  return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
1190  }
1191 
1192  /// <summary>
1193  /// Returns a <see cref="System.String"/> that represents this instance.
1194  /// </summary>
1195  /// <param name="format">The format.</param>
1196  /// <param name="formatProvider">The format provider.</param>
1197  /// <returns>
1198  /// A <see cref="System.String"/> that represents this instance.
1199  /// </returns>
1200  public string ToString(string format, IFormatProvider formatProvider)
1201  {
1202  if (format == null)
1203  return ToString(formatProvider);
1204 
1205  return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider),
1206  Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), W.ToString(format, formatProvider));
1207  }
1208 
1209  /// <summary>
1210  /// Returns a hash code for this instance.
1211  /// </summary>
1212  /// <returns>
1213  /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
1214  /// </returns>
1215  public override int GetHashCode()
1216  {
1217  return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode();
1218  }
1219 
1220  /// <summary>
1221  /// Determines whether the specified <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> is equal to this instance.
1222  /// </summary>
1223  /// <param name="other">The <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> to compare with this instance.</param>
1224  /// <returns>
1225  /// <c>true</c> if the specified <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> is equal to this instance; otherwise, <c>false</c>.
1226  /// </returns>
1227  public bool Equals(Quaternion other)
1228  {
1229  return ((float)Math.Abs(other.X - X) < MathUtil.ZeroTolerance &&
1230  (float)Math.Abs(other.Y - Y) < MathUtil.ZeroTolerance &&
1231  (float)Math.Abs(other.Z - Z) < MathUtil.ZeroTolerance &&
1232  (float)Math.Abs(other.W - W) < MathUtil.ZeroTolerance);
1233  }
1234 
1235  /// <summary>
1236  /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
1237  /// </summary>
1238  /// <param name="value">The <see cref="System.Object"/> to compare with this instance.</param>
1239  /// <returns>
1240  /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
1241  /// </returns>
1242  public override bool Equals(object value)
1243  {
1244  if (value == null)
1245  return false;
1246 
1247  if (value.GetType() != GetType())
1248  return false;
1249 
1250  return Equals((Quaternion)value);
1251  }
1252 
1253 #if SlimDX1xInterop
1254  /// <summary>
1255  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> to <see cref="SlimDX.Quaternion"/>.
1256  /// </summary>
1257  /// <param name="value">The value.</param>
1258  /// <returns>The result of the conversion.</returns>
1259  public static implicit operator SlimDX.Quaternion(Quaternion value)
1260  {
1261  return new SlimDX.Quaternion(value.X, value.Y, value.Z, value.W);
1262  }
1263 
1264  /// <summary>
1265  /// Performs an implicit conversion from <see cref="SlimDX.Quaternion"/> to <see cref="SiliconStudio.Core.Mathematics.Quaternion"/>.
1266  /// </summary>
1267  /// <param name="value">The value.</param>
1268  /// <returns>The result of the conversion.</returns>
1269  public static implicit operator Quaternion(SlimDX.Quaternion value)
1270  {
1271  return new Quaternion(value.X, value.Y, value.Z, value.W);
1272  }
1273 #endif
1274 
1275 #if WPFInterop
1276  /// <summary>
1277  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> to <see cref="System.Windows.Media.Media3D.Quaternion"/>.
1278  /// </summary>
1279  /// <param name="value">The value.</param>
1280  /// <returns>The result of the conversion.</returns>
1281  public static implicit operator System.Windows.Media.Media3D.Quaternion(Quaternion value)
1282  {
1283  return new System.Windows.Media.Media3D.Quaternion(value.X, value.Y, value.Z, value.W);
1284  }
1285 
1286  /// <summary>
1287  /// Performs an explicit conversion from <see cref="System.Windows.Media.Media3D.Quaternion"/> to <see cref="SiliconStudio.Core.Mathematics.Quaternion"/>.
1288  /// </summary>
1289  /// <param name="value">The value.</param>
1290  /// <returns>The result of the conversion.</returns>
1291  public static explicit operator Quaternion(System.Windows.Media.Media3D.Quaternion value)
1292  {
1293  return new Quaternion((float)value.X, (float)value.Y, (float)value.Z, (float)value.W);
1294  }
1295 #endif
1296 
1297 #if XnaInterop
1298  /// <summary>
1299  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> to <see cref="Microsoft.Xna.Framework.Quaternion"/>.
1300  /// </summary>
1301  /// <param name="value">The value.</param>
1302  /// <returns>The result of the conversion.</returns>
1303  public static implicit operator Microsoft.Xna.Framework.Quaternion(Quaternion value)
1304  {
1305  return new Microsoft.Xna.Framework.Quaternion(value.X, value.Y, value.Z, value.W);
1306  }
1307 
1308  /// <summary>
1309  /// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Quaternion"/> to <see cref="SiliconStudio.Core.Mathematics.Quaternion"/>.
1310  /// </summary>
1311  /// <param name="value">The value.</param>
1312  /// <returns>The result of the conversion.</returns>
1313  public static implicit operator Quaternion(Microsoft.Xna.Framework.Quaternion value)
1314  {
1315  return new Quaternion(value.X, value.Y, value.Z, value.W);
1316  }
1317 #endif
1318  }
1319 }
static float Dot(Quaternion left, Quaternion right)
Calculates the dot product of two quaternions.
Definition: Quaternion.cs:554
static void Negate(ref Quaternion value, out Quaternion result)
Reverses the direction of a given quaternion.
Definition: Quaternion.cs:459
static void RotationY(float angle, out Quaternion result)
Creates a quaternion that rotates around the x-axis.
Definition: Quaternion.cs:866
static Quaternion RotationMatrix(Matrix matrix)
Creates a quaternion given a rotation matrix.
Definition: Quaternion.cs:831
FbxDouble3 operator*(double factor, FbxDouble3 vector)
void Conjugate()
Conjugates the quaternion.
Definition: Quaternion.cs:262
string ToString(string format, IFormatProvider formatProvider)
Returns a System.String that represents this instance.
Definition: Quaternion.cs:1200
static void Squad(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, ref Quaternion value4, float amount, out Quaternion result)
Interpolates between quaternions, using spherical quadrangle interpolation.
Definition: Quaternion.cs:1003
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
float Y
The Y component of the quaternion.
Definition: Quaternion.cs:75
static void RotationAxis(ref Vector3 axis, float angle, out Quaternion result)
Creates a quaternion given a rotation and an axis.
Definition: Quaternion.cs:745
static Quaternion RotationX(float angle)
Creates a quaternion that rotates around the x-axis.
Definition: Quaternion.cs:854
static void Conjugate(ref Quaternion value, out Quaternion result)
Conjugates a quaternion.
Definition: Quaternion.cs:517
Quaternion(float[] values)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Quaternion struct.
Definition: Quaternion.cs:159
static void Lerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result)
Performs a linear interpolation between two quaternions.
Definition: Quaternion.cs:631
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
static void Multiply(ref Quaternion value, float scale, out Quaternion result)
Scales a quaternion by the given value.
Definition: Quaternion.cs:397
static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result)
Creates a quaternion given a yaw, pitch, and roll value.
Definition: Quaternion.cs:914
static void RotationMatrix(ref Matrix matrix, out Quaternion result)
Creates a quaternion given a rotation matrix.
Definition: Quaternion.cs:778
static Quaternion RotationAxis(Vector3 axis, float angle)
Creates a quaternion given a rotation and an axis.
Definition: Quaternion.cs:766
static Quaternion Multiply(Quaternion left, Quaternion right)
Modulates a quaternion by another.
Definition: Quaternion.cs:447
float X
The X component of the quaternion.
Definition: Quaternion.cs:70
const float ZeroTolerance
The value for which all absolute numbers smaller than are considered equal to zero.
Definition: MathUtil.cs:38
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
static void Subtract(ref Quaternion left, ref Quaternion right, out Quaternion result)
Subtracts two quaternions.
Definition: Quaternion.cs:370
static Quaternion RotationY(float angle)
Creates a quaternion that rotates around the x-axis.
Definition: Quaternion.cs:877
static void Exponential(ref Quaternion value, out Quaternion result)
Exponentiates a quaternion.
Definition: Quaternion.cs:564
override int GetHashCode()
Returns a hash code for this instance.
Definition: Quaternion.cs:1215
void Invert()
Conjugates and renormalizes the quaternion.
Definition: Quaternion.cs:272
static void Multiply(ref Quaternion left, ref Quaternion right, out Quaternion result)
Modulates a quaternion by another.
Definition: Quaternion.cs:424
bool Equals(Quaternion other)
Determines whether the specified SiliconStudio.Core.Mathematics.Quaternion is equal to this instance...
Definition: Quaternion.cs:1227
static Quaternion Conjugate(Quaternion value)
Conjugates a quaternion.
Definition: Quaternion.cs:530
Quaternion(float x, float y, float z, float w)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Quaternion struct.
Definition: Quaternion.cs:145
static Quaternion[] SquadSetup(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4)
Sets up control points for spherical quadrangle interpolation.
Definition: Quaternion.cs:1035
static void Slerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result)
Interpolates between two quaternions, using spherical linear interpolation.
Definition: Quaternion.cs:954
Quaternion(float value)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Quaternion struct.
Definition: Quaternion.cs:91
Represents a four dimensional mathematical vector.
Definition: Vector4.cs:42
string ToString(IFormatProvider formatProvider)
Returns a System.String that represents this instance.
Definition: Quaternion.cs:1187
Represents a four dimensional mathematical quaternion.
Definition: Quaternion.cs:45
float LengthSquared()
Calculates the squared length of the quaternion.
Definition: Quaternion.cs:307
static void Normalize(ref Quaternion value, out Quaternion result)
Converts the quaternion into a unit quaternion.
Definition: Quaternion.cs:721
void Normalize()
Converts the quaternion into a unit quaternion.
Definition: Quaternion.cs:315
static void Logarithm(ref Quaternion value, out Quaternion result)
Calculates the natural logarithm of the specified quaternion.
Definition: Quaternion.cs:677
static Quaternion Lerp(Quaternion start, Quaternion end, float amount)
Performs a linear interpolation between two quaternion.
Definition: Quaternion.cs:665
string ToString(string format)
Returns a System.String that represents this instance.
Definition: Quaternion.cs:1171
override string ToString()
Returns a System.String that represents this instance.
Definition: Quaternion.cs:1159
SiliconStudio.Core.Mathematics.Quaternion Quaternion
override bool Equals(object value)
Determines whether the specified System.Object is equal to this instance.
Definition: Quaternion.cs:1242
static Quaternion Subtract(Quaternion left, Quaternion right)
Subtracts two quaternions.
Definition: Quaternion.cs:384
float Z
The Z component of the quaternion.
Definition: Quaternion.cs:80
Quaternion(Vector2 value, float z, float w)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Quaternion struct.
Definition: Quaternion.cs:130
static Quaternion Invert(Quaternion value)
Conjugates and renormalizes the quaternion.
Definition: Quaternion.cs:612
static void Barycentric(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, float amount1, float amount2, out Quaternion result)
Returns a SiliconStudio.Core.Mathematics.Quaternion containing the 4D Cartesian coordinates of a poin...
Definition: Quaternion.cs:488
static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result)
Adds two quaternions.
Definition: Quaternion.cs:343
float[] ToArray()
Creates an array containing the elements of the quaternion.
Definition: Quaternion.cs:332
static Quaternion Normalize(Quaternion value)
Converts the quaternion into a unit quaternion.
Definition: Quaternion.cs:733
static void RotationZ(float angle, out Quaternion result)
Creates a quaternion that rotates around the x-axis.
Definition: Quaternion.cs:889
static Quaternion Add(Quaternion left, Quaternion right)
Adds two quaternions.
Definition: Quaternion.cs:357
Quaternion(Vector3 value, float w)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Quaternion struct.
Definition: Quaternion.cs:116
static Quaternion RotationYawPitchRoll(float yaw, float pitch, float roll)
Creates a quaternion given a yaw, pitch, and roll value.
Definition: Quaternion.cs:940
float Length()
Calculates the length of the quaternion.
Definition: Quaternion.cs:294
static Quaternion Exponential(Quaternion value)
Exponentiates a quaternion.
Definition: Quaternion.cs:589
SiliconStudio.Core.Mathematics.Vector3 Vector3
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
static Quaternion RotationZ(float angle)
Creates a quaternion that rotates around the x-axis.
Definition: Quaternion.cs:900
Quaternion(Vector4 value)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Quaternion struct.
Definition: Quaternion.cs:103
static Quaternion Squad(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4, float amount)
Interpolates between quaternions, using spherical quadrangle interpolation.
Definition: Quaternion.cs:1020
static Quaternion Multiply(Quaternion value, float scale)
Scales a quaternion by the given value.
Definition: Quaternion.cs:411
static void Invert(ref Quaternion value, out Quaternion result)
Conjugates and renormalizes the quaternion.
Definition: Quaternion.cs:601
static void Dot(ref Quaternion left, ref Quaternion right, out float result)
Calculates the dot product of two quaternions.
Definition: Quaternion.cs:543
static Quaternion Slerp(Quaternion start, Quaternion end, float amount)
Interpolates between two quaternions, using spherical linear interpolation.
Definition: Quaternion.cs:987
static Quaternion Negate(Quaternion value)
Reverses the direction of a given quaternion.
Definition: Quaternion.cs:472
static Quaternion Logarithm(Quaternion value)
Calculates the natural logarithm of the specified quaternion.
Definition: Quaternion.cs:709
DataStyle
Specifies the style used for textual serialization when an array/list or a dictionary/map must be ser...
Definition: DataStyle.cs:9
static void RotationX(float angle, out Quaternion result)
Creates a quaternion that rotates around the x-axis.
Definition: Quaternion.cs:843
static Quaternion Barycentric(Quaternion value1, Quaternion value2, Quaternion value3, float amount1, float amount2)
Returns a SiliconStudio.Core.Mathematics.Quaternion containing the 4D Cartesian coordinates of a poin...
Definition: Quaternion.cs:505
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t size_t z
Definition: DirectXTexP.h:191
float W
The W component of the quaternion.
Definition: Quaternion.cs:85
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47