00001 #region --- License ---
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #endregion
00024
00025 using System;
00026 using System.Runtime.InteropServices;
00027 using System.ComponentModel;
00028 using System.Xml.Serialization;
00029
00030 namespace OpenTK
00031 {
00035 [Serializable]
00036 [StructLayout(LayoutKind.Sequential)]
00037 public struct Quaterniond : IEquatable<Quaterniond>
00038 {
00039 #region Fields
00040
00041 Vector3d xyz;
00042 double w;
00043
00044 #endregion
00045
00046 #region Constructors
00047
00053 public Quaterniond(Vector3d v, double w)
00054 {
00055 this.xyz = v;
00056 this.w = w;
00057 }
00058
00066 public Quaterniond(double x, double y, double z, double w)
00067 : this(new Vector3d(x, y, z), w)
00068 { }
00069
00070 #endregion
00071
00072 #region Public Members
00073
00074 #region Properties
00075
00079 [Obsolete("Use Xyz property instead.")]
00080 [CLSCompliant(false)]
00081 [EditorBrowsable(EditorBrowsableState.Never)]
00082 [XmlIgnore]
00083 public Vector3d XYZ { get { return Xyz; } set { Xyz = value; } }
00084
00088 public Vector3d Xyz { get { return xyz; } set { xyz = value; } }
00089
00093 [XmlIgnore]
00094 public double X { get { return xyz.X; } set { xyz.X = value; } }
00095
00099 [XmlIgnore]
00100 public double Y { get { return xyz.Y; } set { xyz.Y = value; } }
00101
00105 [XmlIgnore]
00106 public double Z { get { return xyz.Z; } set { xyz.Z = value; } }
00107
00111 public double W { get { return w; } set { w = value; } }
00112
00113 #endregion
00114
00115 #region Instance
00116
00117 #region ToAxisAngle
00118
00124 public void ToAxisAngle(out Vector3d axis, out double angle)
00125 {
00126 Vector4d result = ToAxisAngle();
00127 axis = result.Xyz;
00128 angle = result.W;
00129 }
00130
00135 public Vector4d ToAxisAngle()
00136 {
00137 Quaterniond q = this;
00138 if (q.W > 1.0f)
00139 q.Normalize();
00140
00141 Vector4d result = new Vector4d();
00142
00143 result.W = 2.0f * (float)System.Math.Acos(q.W);
00144 float den = (float)System.Math.Sqrt(1.0 - q.W * q.W);
00145 if (den > 0.0001f)
00146 {
00147 result.Xyz = q.Xyz / den;
00148 }
00149 else
00150 {
00151
00152
00153 result.Xyz = Vector3d.UnitX;
00154 }
00155
00156 return result;
00157 }
00158
00159 #endregion
00160
00161 #region public double Length
00162
00167 public double Length
00168 {
00169 get
00170 {
00171 return (double)System.Math.Sqrt(W * W + Xyz.LengthSquared);
00172 }
00173 }
00174
00175 #endregion
00176
00177 #region public double LengthSquared
00178
00182 public double LengthSquared
00183 {
00184 get
00185 {
00186 return W * W + Xyz.LengthSquared;
00187 }
00188 }
00189
00190 #endregion
00191
00192 #region public void Normalize()
00193
00197 public void Normalize()
00198 {
00199 double scale = 1.0f / this.Length;
00200 Xyz *= scale;
00201 W *= scale;
00202 }
00203
00204 #endregion
00205
00206 #region public void Conjugate()
00207
00211 public void Conjugate()
00212 {
00213 Xyz = -Xyz;
00214 }
00215
00216 #endregion
00217
00218 #endregion
00219
00220 #region Static
00221
00222 #region Fields
00223
00227 public readonly static Quaterniond Identity = new Quaterniond(0, 0, 0, 1);
00228
00229 #endregion
00230
00231 #region Add
00232
00239 public static Quaterniond Add(Quaterniond left, Quaterniond right)
00240 {
00241 return new Quaterniond(
00242 left.Xyz + right.Xyz,
00243 left.W + right.W);
00244 }
00245
00252 public static void Add(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00253 {
00254 result = new Quaterniond(
00255 left.Xyz + right.Xyz,
00256 left.W + right.W);
00257 }
00258
00259 #endregion
00260
00261 #region Sub
00262
00269 public static Quaterniond Sub(Quaterniond left, Quaterniond right)
00270 {
00271 return new Quaterniond(
00272 left.Xyz - right.Xyz,
00273 left.W - right.W);
00274 }
00275
00282 public static void Sub(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00283 {
00284 result = new Quaterniond(
00285 left.Xyz - right.Xyz,
00286 left.W - right.W);
00287 }
00288
00289 #endregion
00290
00291 #region Mult
00292
00299 [Obsolete("Use Multiply instead.")]
00300 public static Quaterniond Mult(Quaterniond left, Quaterniond right)
00301 {
00302 return new Quaterniond(
00303 right.W * left.Xyz + left.W * right.Xyz + Vector3d.Cross(left.Xyz, right.Xyz),
00304 left.W * right.W - Vector3d.Dot(left.Xyz, right.Xyz));
00305 }
00306
00313 [Obsolete("Use Multiply instead.")]
00314 public static void Mult(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00315 {
00316 result = new Quaterniond(
00317 right.W * left.Xyz + left.W * right.Xyz + Vector3d.Cross(left.Xyz, right.Xyz),
00318 left.W * right.W - Vector3d.Dot(left.Xyz, right.Xyz));
00319 }
00320
00327 public static Quaterniond Multiply(Quaterniond left, Quaterniond right)
00328 {
00329 Quaterniond result;
00330 Multiply(ref left, ref right, out result);
00331 return result;
00332 }
00333
00340 public static void Multiply(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00341 {
00342 result = new Quaterniond(
00343 right.W * left.Xyz + left.W * right.Xyz + Vector3d.Cross(left.Xyz, right.Xyz),
00344 left.W * right.W - Vector3d.Dot(left.Xyz, right.Xyz));
00345 }
00346
00353 public static void Multiply(ref Quaterniond quaternion, double scale, out Quaterniond result)
00354 {
00355 result = new Quaterniond(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
00356 }
00357
00364 public static Quaterniond Multiply(Quaterniond quaternion, double scale)
00365 {
00366 return new Quaterniond(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
00367 }
00368
00369 #endregion
00370
00371 #region Conjugate
00372
00378 public static Quaterniond Conjugate(Quaterniond q)
00379 {
00380 return new Quaterniond(-q.Xyz, q.W);
00381 }
00382
00388 public static void Conjugate(ref Quaterniond q, out Quaterniond result)
00389 {
00390 result = new Quaterniond(-q.Xyz, q.W);
00391 }
00392
00393 #endregion
00394
00395 #region Invert
00396
00402 public static Quaterniond Invert(Quaterniond q)
00403 {
00404 Quaterniond result;
00405 Invert(ref q, out result);
00406 return result;
00407 }
00408
00414 public static void Invert(ref Quaterniond q, out Quaterniond result)
00415 {
00416 double lengthSq = q.LengthSquared;
00417 if (lengthSq != 0.0)
00418 {
00419 double i = 1.0f / lengthSq;
00420 result = new Quaterniond(q.Xyz * -i, q.W * i);
00421 }
00422 else
00423 {
00424 result = q;
00425 }
00426 }
00427
00428 #endregion
00429
00430 #region Normalize
00431
00437 public static Quaterniond Normalize(Quaterniond q)
00438 {
00439 Quaterniond result;
00440 Normalize(ref q, out result);
00441 return result;
00442 }
00443
00449 public static void Normalize(ref Quaterniond q, out Quaterniond result)
00450 {
00451 double scale = 1.0f / q.Length;
00452 result = new Quaterniond(q.Xyz * scale, q.W * scale);
00453 }
00454
00455 #endregion
00456
00457 #region FromAxisAngle
00458
00465 public static Quaterniond FromAxisAngle(Vector3d axis, double angle)
00466 {
00467 if (axis.LengthSquared == 0.0f)
00468 return Identity;
00469
00470 Quaterniond result = Identity;
00471
00472 angle *= 0.5f;
00473 axis.Normalize();
00474 result.Xyz = axis * (double)System.Math.Sin(angle);
00475 result.W = (double)System.Math.Cos(angle);
00476
00477 return Normalize(result);
00478 }
00479
00480 #endregion
00481
00482 #region Slerp
00483
00491 public static Quaterniond Slerp(Quaterniond q1, Quaterniond q2, double blend)
00492 {
00493
00494 if (q1.LengthSquared == 0.0f)
00495 {
00496 if (q2.LengthSquared == 0.0f)
00497 {
00498 return Identity;
00499 }
00500 return q2;
00501 }
00502 else if (q2.LengthSquared == 0.0f)
00503 {
00504 return q1;
00505 }
00506
00507
00508 double cosHalfAngle = q1.W * q2.W + Vector3d.Dot(q1.Xyz, q2.Xyz);
00509
00510 if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
00511 {
00512
00513 return q1;
00514 }
00515 else if (cosHalfAngle < 0.0f)
00516 {
00517 q2.Xyz = -q2.Xyz;
00518 q2.W = -q2.W;
00519 cosHalfAngle = -cosHalfAngle;
00520 }
00521
00522 double blendA;
00523 double blendB;
00524 if (cosHalfAngle < 0.99f)
00525 {
00526
00527 double halfAngle = (double)System.Math.Acos(cosHalfAngle);
00528 double sinHalfAngle = (double)System.Math.Sin(halfAngle);
00529 double oneOverSinHalfAngle = 1.0f / sinHalfAngle;
00530 blendA = (double)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
00531 blendB = (double)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
00532 }
00533 else
00534 {
00535
00536 blendA = 1.0f - blend;
00537 blendB = blend;
00538 }
00539
00540 Quaterniond result = new Quaterniond(blendA * q1.Xyz + blendB * q2.Xyz, blendA * q1.W + blendB * q2.W);
00541 if (result.LengthSquared > 0.0f)
00542 return Normalize(result);
00543 else
00544 return Identity;
00545 }
00546
00547 #endregion
00548
00549 #endregion
00550
00551 #region Operators
00552
00559 public static Quaterniond operator +(Quaterniond left, Quaterniond right)
00560 {
00561 left.Xyz += right.Xyz;
00562 left.W += right.W;
00563 return left;
00564 }
00565
00572 public static Quaterniond operator -(Quaterniond left, Quaterniond right)
00573 {
00574 left.Xyz -= right.Xyz;
00575 left.W -= right.W;
00576 return left;
00577 }
00578
00585 public static Quaterniond operator *(Quaterniond left, Quaterniond right)
00586 {
00587 Multiply(ref left, ref right, out left);
00588 return left;
00589 }
00590
00597 public static Quaterniond operator *(Quaterniond quaternion, double scale)
00598 {
00599 Multiply(ref quaternion, scale, out quaternion);
00600 return quaternion;
00601 }
00602
00609 public static Quaterniond operator *(double scale, Quaterniond quaternion)
00610 {
00611 return new Quaterniond(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
00612 }
00613
00620 public static bool operator ==(Quaterniond left, Quaterniond right)
00621 {
00622 return left.Equals(right);
00623 }
00624
00631 public static bool operator !=(Quaterniond left, Quaterniond right)
00632 {
00633 return !left.Equals(right);
00634 }
00635
00636 #endregion
00637
00638 #region Overrides
00639
00640 #region public override string ToString()
00641
00646 public override string ToString()
00647 {
00648 return String.Format("V: {0}, W: {1}", Xyz, W);
00649 }
00650
00651 #endregion
00652
00653 #region public override bool Equals (object o)
00654
00660 public override bool Equals(object other)
00661 {
00662 if (other is Quaterniond == false) return false;
00663 return this == (Quaterniond)other;
00664 }
00665
00666 #endregion
00667
00668 #region public override int GetHashCode ()
00669
00674 public override int GetHashCode()
00675 {
00676 return Xyz.GetHashCode() ^ W.GetHashCode();
00677 }
00678
00679 #endregion
00680
00681 #endregion
00682
00683 #endregion
00684
00685 #if false
00686
00687 #region Fields
00688
00690 public double W;
00691
00693 public double X;
00694
00696 public double Y;
00697
00699 public double Z;
00700
00701 #endregion
00702
00703 #region Constructors
00704
00707 public Quaterniond(ref Quaterniond Quaterniond) : this(Quaterniond.W, Quaterniond.X, Quaterniond.Y, Quaterniond.Z) { }
00708
00712 public Quaterniond(double w, ref Vector3d vector3d) : this(w, vector3d.X, vector3d.Y, vector3d.Z) { }
00713
00717 public Quaterniond(ref Vector3d axis, double angle)
00718 {
00719 double halfAngle = Functions.DTOR * angle / 2;
00720
00721 this.W = System.Math.Cos(halfAngle);
00722
00723 double sin = System.Math.Sin(halfAngle);
00724 Vector3d axisNormalized;
00725 Vector3d.Normalize(ref axis, out axisNormalized);
00726 this.X = axisNormalized.X * sin;
00727 this.Y = axisNormalized.Y * sin;
00728 this.Z = axisNormalized.Z * sin;
00729 }
00730
00736 public Quaterniond(double w, double x, double y, double z)
00737 {
00738 this.W = w;
00739 this.X = x;
00740 this.Y = y;
00741 this.Z = z;
00742 }
00743
00746 public Quaterniond(double[] doubleArray)
00747 {
00748 if (doubleArray == null || doubleArray.GetLength(0) < 4) throw new MissingFieldException();
00749
00750 this.W = doubleArray[0];
00751 this.X = doubleArray[1];
00752 this.Y = doubleArray[2];
00753 this.Z = doubleArray[3];
00754 }
00755
00758 public Quaterniond(ref Matrix4d matrix)
00759 {
00760 double scale = System.Math.Pow(matrix.Determinant, 1.0d/3.0d);
00761
00762 W = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] + matrix[1, 1] + matrix[2, 2])) / 2;
00763 X = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])) / 2;
00764 Y = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] + matrix[1, 1] - matrix[2, 2])) / 2;
00765 Z = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] - matrix[1, 1] + matrix[2, 2])) / 2;
00766 if( matrix[2,1] - matrix[1,2] < 0 ) X = -X;
00767 if( matrix[0,2] - matrix[2,0] < 0 ) Y = -Y;
00768 if( matrix[1,0] - matrix[0,1] < 0 ) Z = -Z;
00769 }
00770
00771 public Quaterniond(ref Matrix3d matrix)
00772 {
00773 double scale = System.Math.Pow(matrix.Determinant, 1.0d / 3.0d);
00774
00775 W = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] + matrix[1, 1] + matrix[2, 2])) / 2;
00776 X = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])) / 2;
00777 Y = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] + matrix[1, 1] - matrix[2, 2])) / 2;
00778 Z = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] - matrix[1, 1] + matrix[2, 2])) / 2;
00779 if (matrix[2, 1] - matrix[1, 2] < 0) X = -X;
00780 if (matrix[0, 2] - matrix[2, 0] < 0) Y = -Y;
00781 if (matrix[1, 0] - matrix[0, 1] < 0) Z = -Z;
00782 }
00783
00784 #endregion
00785
00786 #region Arithmetic Operators
00787
00788 public void Add(ref Quaterniond Quaterniond)
00789 {
00790 W = W + Quaterniond.W;
00791 X = X + Quaterniond.X;
00792 Y = Y + Quaterniond.Y;
00793 Z = Z + Quaterniond.Z;
00794 }
00795 public void Add(ref Quaterniond Quaterniond, out Quaterniond result)
00796 {
00797 result.W = W + Quaterniond.W;
00798 result.X = X + Quaterniond.X;
00799 result.Y = Y + Quaterniond.Y;
00800 result.Z = Z + Quaterniond.Z;
00801 }
00802 public static void Add(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00803 {
00804 result.W = left.W + right.W;
00805 result.X = left.X + right.X;
00806 result.Y = left.Y + right.Y;
00807 result.Z = left.Z + right.Z;
00808 }
00809
00810 public void Subtract(ref Quaterniond Quaterniond)
00811 {
00812 W = W - Quaterniond.W;
00813 X = X - Quaterniond.X;
00814 Y = Y - Quaterniond.Y;
00815 Z = Z - Quaterniond.Z;
00816 }
00817 public void Subtract(ref Quaterniond Quaterniond, out Quaterniond result)
00818 {
00819 result.W = W - Quaterniond.W;
00820 result.X = X - Quaterniond.X;
00821 result.Y = Y - Quaterniond.Y;
00822 result.Z = Z - Quaterniond.Z;
00823 }
00824 public static void Subtract(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00825 {
00826 result.W = left.W - right.W;
00827 result.X = left.X - right.X;
00828 result.Y = left.Y - right.Y;
00829 result.Z = left.Z - right.Z;
00830 }
00831
00832 public void Multiply(ref Quaterniond Quaterniond)
00833 {
00834 double w = W * Quaterniond.W - X * Quaterniond.X - Y * Quaterniond.Y - Z * Quaterniond.Z;
00835 double x = W * Quaterniond.X + X * Quaterniond.W + Y * Quaterniond.Z - Z * Quaterniond.Y;
00836 double y = W * Quaterniond.Y + Y * Quaterniond.W + Z * Quaterniond.X - X * Quaterniond.Z;
00837 Z = W * Quaterniond.Z + Z * Quaterniond.W + X * Quaterniond.Y - Y * Quaterniond.X;
00838 W = w;
00839 X = x;
00840 Y = y;
00841 }
00842 public void Multiply(ref Quaterniond Quaterniond, out Quaterniond result)
00843 {
00844 result.W = W * Quaterniond.W - X * Quaterniond.X - Y * Quaterniond.Y - Z * Quaterniond.Z;
00845 result.X = W * Quaterniond.X + X * Quaterniond.W + Y * Quaterniond.Z - Z * Quaterniond.Y;
00846 result.Y = W * Quaterniond.Y + Y * Quaterniond.W + Z * Quaterniond.X - X * Quaterniond.Z;
00847 result.Z = W * Quaterniond.Z + Z * Quaterniond.W + X * Quaterniond.Y - Y * Quaterniond.X;
00848 }
00849 public static void Multiply(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
00850 {
00851 result.W = left.W * right.W - left.X * right.X - left.Y * right.Y - left.Z * right.Z;
00852 result.X = left.W * right.X + left.X * right.W + left.Y * right.Z - left.Z * right.Y;
00853 result.Y = left.W * right.Y + left.Y * right.W + left.Z * right.X - left.X * right.Z;
00854 result.Z = left.W * right.Z + left.Z * right.W + left.X * right.Y - left.Y * right.X;
00855 }
00856
00857 public void Multiply(double scalar)
00858 {
00859 W = W * scalar;
00860 X = X * scalar;
00861 Y = Y * scalar;
00862 Z = Z * scalar;
00863 }
00864 public void Multiply(double scalar, out Quaterniond result)
00865 {
00866 result.W = W * scalar;
00867 result.X = X * scalar;
00868 result.Y = Y * scalar;
00869 result.Z = Z * scalar;
00870 }
00871 public static void Multiply(ref Quaterniond Quaterniond, double scalar, out Quaterniond result)
00872 {
00873 result.W = Quaterniond.W * scalar;
00874 result.X = Quaterniond.X * scalar;
00875 result.Y = Quaterniond.Y * scalar;
00876 result.Z = Quaterniond.Z * scalar;
00877 }
00878
00879 public void Divide(double scalar)
00880 {
00881 if (scalar == 0) throw new DivideByZeroException();
00882 W = W / scalar;
00883 X = X / scalar;
00884 Y = Y / scalar;
00885 Z = Z / scalar;
00886 }
00887 public void Divide(double scalar, out Quaterniond result)
00888 {
00889 if (scalar == 0) throw new DivideByZeroException();
00890 result.W = W / scalar;
00891 result.X = X / scalar;
00892 result.Y = Y / scalar;
00893 result.Z = Z / scalar;
00894 }
00895 public static void Divide(ref Quaterniond Quaterniond, double scalar, out Quaterniond result)
00896 {
00897 if (scalar == 0) throw new DivideByZeroException();
00898 result.W = Quaterniond.W / scalar;
00899 result.X = Quaterniond.X / scalar;
00900 result.Y = Quaterniond.Y / scalar;
00901 result.Z = Quaterniond.Z / scalar;
00902 }
00903
00904 #endregion
00905
00906 #region Functions
00907
00908 public double Modulus
00909 {
00910 get
00911 {
00912 return System.Math.Sqrt(W * W + X * X + Y * Y + Z * Z);
00913 }
00914 }
00915 public double ModulusSquared
00916 {
00917 get
00918 {
00919 return W * W + X * X + Y * Y + Z * Z;
00920 }
00921 }
00922
00923 public static double DotProduct(Quaterniond left, Quaterniond right)
00924 {
00925 return left.W * right.W + left.X * right.X + left.Y * right.Y + left.Z * right.Z;
00926 }
00927
00928 public void Normalize()
00929 {
00930 double modulus = System.Math.Sqrt(W * W + X * X + Y * Y + Z * Z);
00931 if (modulus == 0) throw new DivideByZeroException();
00932 W = W / modulus;
00933 X = X / modulus;
00934 Y = Y / modulus;
00935 Z = Z / modulus;
00936 }
00937 public void Normalize( out Quaterniond result )
00938 {
00939 double modulus = System.Math.Sqrt(W * W + X * X + Y * Y + Z * Z);
00940 if (modulus == 0) throw new DivideByZeroException();
00941 result.W = W / modulus;
00942 result.X = X / modulus;
00943 result.Y = Y / modulus;
00944 result.Z = Z / modulus;
00945 }
00946 public static void Normalize(ref Quaterniond Quaterniond, out Quaterniond result)
00947 {
00948 double modulus = System.Math.Sqrt(Quaterniond.W * Quaterniond.W + Quaterniond.X * Quaterniond.X + Quaterniond.Y * Quaterniond.Y + Quaterniond.Z * Quaterniond.Z);
00949 if (modulus == 0) throw new DivideByZeroException();
00950 result.W = Quaterniond.W / modulus;
00951 result.X = Quaterniond.X / modulus;
00952 result.Y = Quaterniond.Y / modulus;
00953 result.Z = Quaterniond.Z / modulus;
00954 }
00955
00956 public void Conjugate()
00957 {
00958 X = -X;
00959 Y = -Y;
00960 Z = -Z;
00961 }
00962 public void Conjugate( out Quaterniond result )
00963 {
00964 result.W = W;
00965 result.X = -X;
00966 result.Y = -Y;
00967 result.Z = -Z;
00968 }
00969 public static void Conjugate(ref Quaterniond Quaterniond, out Quaterniond result)
00970 {
00971 result.W = Quaterniond.W;
00972 result.X = -Quaterniond.X;
00973 result.Y = -Quaterniond.Y;
00974 result.Z = -Quaterniond.Z;
00975 }
00976
00977 public void Inverse()
00978 {
00979 double modulusSquared = W * W + X * X + Y * Y + Z * Z;
00980 if (modulusSquared <= 0) throw new InvalidOperationException();
00981 double inverseModulusSquared = 1.0 / modulusSquared;
00982 W = W * inverseModulusSquared;
00983 X = X * -inverseModulusSquared;
00984 Y = Y * -inverseModulusSquared;
00985 Z = Z * -inverseModulusSquared;
00986 }
00987 public void Inverse( out Quaterniond result )
00988 {
00989 double modulusSquared = W * W + X * X + Y * Y + Z * Z;
00990 if (modulusSquared <= 0) throw new InvalidOperationException();
00991 double inverseModulusSquared = 1.0 / modulusSquared;
00992 result.W = W * inverseModulusSquared;
00993 result.X = X * -inverseModulusSquared;
00994 result.Y = Y * -inverseModulusSquared;
00995 result.Z = Z * -inverseModulusSquared;
00996 }
00997 public static void Inverse(ref Quaterniond Quaterniond, out Quaterniond result)
00998 {
00999 double modulusSquared = Quaterniond.W * Quaterniond.W + Quaterniond.X * Quaterniond.X + Quaterniond.Y * Quaterniond.Y + Quaterniond.Z * Quaterniond.Z;
01000 if (modulusSquared <= 0) throw new InvalidOperationException();
01001 double inverseModulusSquared = 1.0 / modulusSquared;
01002 result.W = Quaterniond.W * inverseModulusSquared;
01003 result.X = Quaterniond.X * -inverseModulusSquared;
01004 result.Y = Quaterniond.Y * -inverseModulusSquared;
01005 result.Z = Quaterniond.Z * -inverseModulusSquared;
01006 }
01007
01008 public void Log()
01009 {
01010 if (System.Math.Abs(W) < 1.0)
01011 {
01012 double angle = System.Math.Acos(W);
01013 double sin = System.Math.Sin(angle);
01014
01015 if (System.Math.Abs(sin) >= 0)
01016 {
01017 double coefficient = angle / sin;
01018 X = X * coefficient;
01019 Y = Y * coefficient;
01020 Z = Z * coefficient;
01021 }
01022 }
01023 else
01024 {
01025 X = 0;
01026 Y = 0;
01027 Z = 0;
01028 }
01029
01030 W = 0;
01031 }
01032 public void Log( out Quaterniond result )
01033 {
01034 if (System.Math.Abs(W) < 1.0)
01035 {
01036 double angle = System.Math.Acos(W);
01037 double sin = System.Math.Sin(angle);
01038
01039 if (System.Math.Abs(sin) >= 0)
01040 {
01041 double coefficient = angle / sin;
01042 result.X = X * coefficient;
01043 result.Y = Y * coefficient;
01044 result.Z = Z * coefficient;
01045 }
01046 else
01047 {
01048 result.X = X;
01049 result.Y = Y;
01050 result.Z = Z;
01051 }
01052 }
01053 else
01054 {
01055 result.X = 0;
01056 result.Y = 0;
01057 result.Z = 0;
01058 }
01059
01060 result.W = 0;
01061 }
01062 public static void Log(ref Quaterniond Quaterniond, out Quaterniond result)
01063 {
01064 if (System.Math.Abs(Quaterniond.W) < 1.0)
01065 {
01066 double angle = System.Math.Acos(Quaterniond.W);
01067 double sin = System.Math.Sin(angle);
01068
01069 if (System.Math.Abs(sin) >= 0)
01070 {
01071 double coefficient = angle / sin;
01072 result.X = Quaterniond.X * coefficient;
01073 result.Y = Quaterniond.Y * coefficient;
01074 result.Z = Quaterniond.Z * coefficient;
01075 }
01076 else
01077 {
01078 result.X = Quaterniond.X;
01079 result.Y = Quaterniond.Y;
01080 result.Z = Quaterniond.Z;
01081 }
01082 }
01083 else
01084 {
01085 result.X = 0;
01086 result.Y = 0;
01087 result.Z = 0;
01088 }
01089
01090 result.W = 0;
01091 }
01092
01093 public void Exp()
01094 {
01095 double angle = System.Math.Sqrt(X * X + Y * Y + Z * Z);
01096 double sin = System.Math.Sin(angle);
01097
01098 if (System.Math.Abs(sin) > 0)
01099 {
01100 double coefficient = angle / sin;
01101 W = 0;
01102 X = X * coefficient;
01103 Y = Y * coefficient;
01104 Z = Z * coefficient;
01105 }
01106 else
01107 {
01108 W = 0;
01109 }
01110 }
01111 public void Exp(out Quaterniond result)
01112 {
01113 double angle = System.Math.Sqrt(X * X + Y * Y + Z * Z);
01114 double sin = System.Math.Sin(angle);
01115
01116 if (System.Math.Abs(sin) > 0)
01117 {
01118 double coefficient = angle / sin;
01119 result.W = 0;
01120 result.X = X * coefficient;
01121 result.Y = Y * coefficient;
01122 result.Z = Z * coefficient;
01123 }
01124 else
01125 {
01126 result.W = 0;
01127 result.X = X;
01128 result.Y = Y;
01129 result.Z = Z;
01130 }
01131 }
01132 public static void Exp(ref Quaterniond Quaterniond, out Quaterniond result)
01133 {
01134 double angle = System.Math.Sqrt(Quaterniond.X * Quaterniond.X + Quaterniond.Y * Quaterniond.Y + Quaterniond.Z * Quaterniond.Z);
01135 double sin = System.Math.Sin(angle);
01136
01137 if (System.Math.Abs(sin) > 0)
01138 {
01139 double coefficient = angle / sin;
01140 result.W = 0;
01141 result.X = Quaterniond.X * coefficient;
01142 result.Y = Quaterniond.Y * coefficient;
01143 result.Z = Quaterniond.Z * coefficient;
01144 }
01145 else
01146 {
01147 result.W = 0;
01148 result.X = Quaterniond.X;
01149 result.Y = Quaterniond.Y;
01150 result.Z = Quaterniond.Z;
01151 }
01152 }
01153
01155 public void Matrix4d(out Matrix4d result)
01156 {
01157
01158 result = new Matrix4d(ref this);
01159 }
01160
01161 public void GetAxisAndAngle(out Vector3d axis, out double angle)
01162 {
01163 Quaterniond Quaterniond;
01164 Normalize(out Quaterniond);
01165 double cos = Quaterniond.W;
01166 angle = System.Math.Acos(cos) * 2 * Functions.RTOD;
01167 double sin = System.Math.Sqrt( 1.0d - cos * cos );
01168 if ( System.Math.Abs( sin ) < 0.0001 ) sin = 1;
01169 axis = new Vector3d(X / sin, Y / sin, Z / sin);
01170 }
01171
01172 public static void Slerp(ref Quaterniond start, ref Quaterniond end, double blend, out Quaterniond result)
01173 {
01174 if (start.W == 0 && start.X == 0 && start.Y == 0 && start.Z == 0)
01175 {
01176 if (end.W == 0 && end.X == 0 && end.Y == 0 && end.Z == 0)
01177 {
01178 result.W = 1;
01179 result.X = 0;
01180 result.Y = 0;
01181 result.Z = 0;
01182 }
01183 else
01184 {
01185 result = end;
01186 }
01187 }
01188 else if (end.W == 0 && end.X == 0 && end.Y == 0 && end.Z == 0)
01189 {
01190 result = start;
01191 }
01192
01193 Vector3d startVector = new Vector3d(start.X, start.Y, start.Z);
01194 Vector3d endVector = new Vector3d(end.X, end.Y, end.Z);
01195 double cosHalfAngle = start.W * end.W + Vector3d.Dot(startVector, endVector);
01196
01197 if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
01198 {
01199
01200 result = start;
01201 }
01202 else if (cosHalfAngle < 0.0f)
01203 {
01204 end.W = -end.W;
01205 end.X = -end.X;
01206 end.Y = -end.Y;
01207 end.Z = -end.Z;
01208 cosHalfAngle = -cosHalfAngle;
01209 }
01210
01211 double blendA;
01212 double blendB;
01213 if (cosHalfAngle < 0.99f)
01214 {
01215
01216 double halfAngle = (double)System.Math.Acos(cosHalfAngle);
01217 double sinHalfAngle = (double)System.Math.Sin(halfAngle);
01218 double oneOverSinHalfAngle = 1.0f / sinHalfAngle;
01219 blendA = (double)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
01220 blendB = (double)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
01221 }
01222 else
01223 {
01224
01225 blendA = 1.0f - blend;
01226 blendB = blend;
01227 }
01228
01229 result.W = blendA * start.W + blendB * end.W;
01230 result.X = blendA * start.X + blendB * end.X;
01231 result.Y = blendA * start.Y + blendB * end.Y;
01232 result.Z = blendA * start.Z + blendB * end.Z;
01233
01234 if (result.W != 0 || result.X != 0 || result.Y != 0 || result.Z != 0)
01235 {
01236 result.Normalize();
01237 }
01238 else
01239 {
01240 result.W = 1;
01241 result.X = 0;
01242 result.Y = 0;
01243 result.Z = 0;
01244 }
01245 }
01246
01247 #endregion
01248
01249 #region HashCode
01250
01253 public override int GetHashCode()
01254 {
01255 base.GetHashCode();
01256 return W.GetHashCode() ^ X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
01257 }
01258
01259 #endregion
01260
01261 #region String and Parse
01262
01265 public override string ToString()
01266 {
01267 return string.Format("({0}, {1}, {2}, {3})", W, X, Y, Z);
01268 }
01269
01273 public static void Parse(string str, out Quaterniond result)
01274 {
01275 Match match = new Regex(@"\((?<w>.*),(?<x>.*),(?<y>.*),(?<z>.*)\)", RegexOptions.None).Match(str);
01276 if (!match.Success) throw new Exception("Parse failed!");
01277
01278 result.W = double.Parse(match.Result("${w}"));
01279 result.X = double.Parse(match.Result("${x}"));
01280 result.Y = double.Parse(match.Result("${y}"));
01281 result.Z = double.Parse(match.Result("${z}"));
01282 }
01283
01284 #endregion
01285
01286 #region Constants
01287
01289 public static readonly Quaterniond Zero = new Quaterniond(0, 0, 0, 0);
01290
01292 public static readonly Quaterniond Identity = new Quaterniond(1, 0, 0, 0);
01293
01295 public static readonly Quaterniond WAxis = new Quaterniond(1, 0, 0, 0);
01296
01298 public static readonly Quaterniond XAxis = new Quaterniond(0, 1, 0, 0);
01299
01301 public static readonly Quaterniond YAxis = new Quaterniond(0, 0, 1, 0);
01302
01304 public static readonly Quaterniond ZAxis = new Quaterniond(0, 0, 0, 1);
01305
01306 #endregion
01307
01308 #endif
01309
01310 #region IEquatable<Quaterniond> Members
01311
01317 public bool Equals(Quaterniond other)
01318 {
01319 return Xyz == other.Xyz && W == other.W;
01320 }
01321
01322 #endregion
01323 }
01324 }