Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1452 chris 1
#region --- License ---
2
/*
3
Copyright (c) 2006 - 2008 The Open Toolkit library.
4
 
5
Permission is hereby granted, free of charge, to any person obtaining a copy of
6
this software and associated documentation files (the "Software"), to deal in
7
the Software without restriction, including without limitation the rights to
8
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
of the Software, and to permit persons to whom the Software is furnished to do
10
so, subject to the following conditions:
11
 
12
The above copyright notice and this permission notice shall be included in all
13
copies or substantial portions of the Software.
14
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
SOFTWARE.
22
*/
23
#endregion
24
 
25
using System;
26
using System.Runtime.InteropServices;
27
using System.ComponentModel;
28
using System.Xml.Serialization;
29
 
30
namespace OpenTK
31
{
32
    /// <summary>
33
    /// Represents a double-precision Quaternion.
34
    /// </summary>
35
    [Serializable]
36
    [StructLayout(LayoutKind.Sequential)]
37
    public struct Quaterniond : IEquatable<Quaterniond>
38
    {
39
        #region Fields
40
 
41
        Vector3d xyz;
42
        double w;
43
 
44
        #endregion
45
 
46
        #region Constructors
47
 
48
        /// <summary>
49
        /// Construct a new Quaterniond from vector and w components
50
        /// </summary>
51
        /// <param name="v">The vector part</param>
52
        /// <param name="w">The w part</param>
53
        public Quaterniond(Vector3d v, double w)
54
        {
55
            this.xyz = v;
56
            this.w = w;
57
        }
58
 
59
        /// <summary>
60
        /// Construct a new Quaterniond
61
        /// </summary>
62
        /// <param name="x">The x component</param>
63
        /// <param name="y">The y component</param>
64
        /// <param name="z">The z component</param>
65
        /// <param name="w">The w component</param>
66
        public Quaterniond(double x, double y, double z, double w)
67
            : this(new Vector3d(x, y, z), w)
68
        { }
69
 
70
        #endregion
71
 
72
        #region Public Members
73
 
74
        #region Properties
75
 
76
        /// <summary>
77
        /// Gets or sets an OpenTK.Vector3d with the X, Y and Z components of this instance.
78
        /// </summary>
79
        [Obsolete("Use Xyz property instead.")]
80
        [CLSCompliant(false)]
81
        [EditorBrowsable(EditorBrowsableState.Never)]
82
        [XmlIgnore]
83
        public Vector3d XYZ { get { return Xyz; } set { Xyz = value; } }
84
 
85
        /// <summary>
86
        /// Gets or sets an OpenTK.Vector3d with the X, Y and Z components of this instance.
87
        /// </summary>
88
        public Vector3d Xyz { get { return xyz; } set { xyz = value; } }
89
 
90
        /// <summary>
91
        /// Gets or sets the X component of this instance.
92
        /// </summary>
93
        [XmlIgnore]
94
        public double X { get { return xyz.X; } set { xyz.X = value; } }
95
 
96
        /// <summary>
97
        /// Gets or sets the Y component of this instance.
98
        /// </summary>
99
        [XmlIgnore]
100
        public double Y { get { return xyz.Y; } set { xyz.Y = value; } }
101
 
102
        /// <summary>
103
        /// Gets or sets the Z component of this instance.
104
        /// </summary>
105
        [XmlIgnore]
106
        public double Z { get { return xyz.Z; } set { xyz.Z = value; } }
107
 
108
        /// <summary>
109
        /// Gets or sets the W component of this instance.
110
        /// </summary>
111
        public double W { get { return w; } set { w = value; } }
112
 
113
        #endregion
114
 
115
        #region Instance
116
 
117
        #region ToAxisAngle
118
 
119
        /// <summary>
120
        /// Convert the current quaternion to axis angle representation
121
        /// </summary>
122
        /// <param name="axis">The resultant axis</param>
123
        /// <param name="angle">The resultant angle</param>
124
        public void ToAxisAngle(out Vector3d axis, out double angle)
125
        {
126
            Vector4d result = ToAxisAngle();
127
            axis = result.Xyz;
128
            angle = result.W;
129
        }
130
 
131
        /// <summary>
132
        /// Convert this instance to an axis-angle representation.
133
        /// </summary>
134
        /// <returns>A Vector4 that is the axis-angle representation of this quaternion.</returns>
135
        public Vector4d ToAxisAngle()
136
        {
137
            Quaterniond q = this;
138
            if (q.W > 1.0f)
139
                q.Normalize();
140
 
141
            Vector4d result = new Vector4d();
142
 
143
            result.W = 2.0f * (float)System.Math.Acos(q.W); // angle
144
            float den = (float)System.Math.Sqrt(1.0 - q.W * q.W);
145
            if (den > 0.0001f)
146
            {
147
                result.Xyz = q.Xyz / den;
148
            }
149
            else
150
            {
151
                // This occurs when the angle is zero. 
152
                // Not a problem: just set an arbitrary normalized axis.
153
                result.Xyz = Vector3d.UnitX;
154
            }
155
 
156
            return result;
157
        }
158
 
159
        #endregion
160
 
161
        #region public double Length
162
 
163
        /// <summary>
164
        /// Gets the length (magnitude) of the Quaterniond.
165
        /// </summary>
166
        /// <seealso cref="LengthSquared"/>
167
        public double Length
168
        {
169
            get
170
            {
171
                return (double)System.Math.Sqrt(W * W + Xyz.LengthSquared);
172
            }
173
        }
174
 
175
        #endregion
176
 
177
        #region public double LengthSquared
178
 
179
        /// <summary>
180
        /// Gets the square of the Quaterniond length (magnitude).
181
        /// </summary>
182
        public double LengthSquared
183
        {
184
            get
185
            {
186
                return W * W + Xyz.LengthSquared;
187
            }
188
        }
189
 
190
        #endregion
191
 
192
        #region public void Normalize()
193
 
194
        /// <summary>
195
        /// Scales the Quaterniond to unit length.
196
        /// </summary>
197
        public void Normalize()
198
        {
199
            double scale = 1.0f / this.Length;
200
            Xyz *= scale;
201
            W *= scale;
202
        }
203
 
204
        #endregion
205
 
206
        #region public void Conjugate()
207
 
208
        /// <summary>
209
        /// Convert this Quaterniond to its conjugate
210
        /// </summary>
211
        public void Conjugate()
212
        {
213
            Xyz = -Xyz;
214
        }
215
 
216
        #endregion
217
 
218
        #endregion
219
 
220
        #region Static
221
 
222
        #region Fields
223
 
224
        /// <summary>
225
        /// Defines the identity quaternion.
226
        /// </summary>
227
        public readonly static Quaterniond Identity = new Quaterniond(0, 0, 0, 1);
228
 
229
        #endregion
230
 
231
        #region Add
232
 
233
        /// <summary>
234
        /// Add two quaternions
235
        /// </summary>
236
        /// <param name="left">The first operand</param>
237
        /// <param name="right">The second operand</param>
238
        /// <returns>The result of the addition</returns>
239
        public static Quaterniond Add(Quaterniond left, Quaterniond right)
240
        {
241
            return new Quaterniond(
242
                left.Xyz + right.Xyz,
243
                left.W + right.W);
244
        }
245
 
246
        /// <summary>
247
        /// Add two quaternions
248
        /// </summary>
249
        /// <param name="left">The first operand</param>
250
        /// <param name="right">The second operand</param>
251
        /// <param name="result">The result of the addition</param>
252
        public static void Add(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
253
        {
254
            result = new Quaterniond(
255
                left.Xyz + right.Xyz,
256
                left.W + right.W);
257
        }
258
 
259
        #endregion
260
 
261
        #region Sub
262
 
263
        /// <summary>
264
        /// Subtracts two instances.
265
        /// </summary>
266
        /// <param name="left">The left instance.</param>
267
        /// <param name="right">The right instance.</param>
268
        /// <returns>The result of the operation.</returns>
269
        public static Quaterniond Sub(Quaterniond left, Quaterniond right)
270
        {
271
            return new Quaterniond(
272
                left.Xyz - right.Xyz,
273
                left.W - right.W);
274
        }
275
 
276
        /// <summary>
277
        /// Subtracts two instances.
278
        /// </summary>
279
        /// <param name="left">The left instance.</param>
280
        /// <param name="right">The right instance.</param>
281
        /// <param name="result">The result of the operation.</param>
282
        public static void Sub(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
283
        {
284
            result = new Quaterniond(
285
                left.Xyz - right.Xyz,
286
                left.W - right.W);
287
        }
288
 
289
        #endregion
290
 
291
        #region Mult
292
 
293
        /// <summary>
294
        /// Multiplies two instances.
295
        /// </summary>
296
        /// <param name="left">The first instance.</param>
297
        /// <param name="right">The second instance.</param>
298
        /// <returns>A new instance containing the result of the calculation.</returns>
299
        [Obsolete("Use Multiply instead.")]
300
        public static Quaterniond Mult(Quaterniond left, Quaterniond right)
301
        {
302
            return new Quaterniond(
303
                right.W * left.Xyz + left.W * right.Xyz + Vector3d.Cross(left.Xyz, right.Xyz),
304
                left.W * right.W - Vector3d.Dot(left.Xyz, right.Xyz));
305
        }
306
 
307
        /// <summary>
308
        /// Multiplies two instances.
309
        /// </summary>
310
        /// <param name="left">The first instance.</param>
311
        /// <param name="right">The second instance.</param>
312
        /// <param name="result">A new instance containing the result of the calculation.</param>
313
        [Obsolete("Use Multiply instead.")]
314
        public static void Mult(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
315
        {
316
            result = new Quaterniond(
317
                right.W * left.Xyz + left.W * right.Xyz + Vector3d.Cross(left.Xyz, right.Xyz),
318
                left.W * right.W - Vector3d.Dot(left.Xyz, right.Xyz));
319
        }
320
 
321
        /// <summary>
322
        /// Multiplies two instances.
323
        /// </summary>
324
        /// <param name="left">The first instance.</param>
325
        /// <param name="right">The second instance.</param>
326
        /// <returns>A new instance containing the result of the calculation.</returns>
327
        public static Quaterniond Multiply(Quaterniond left, Quaterniond right)
328
        {
329
            Quaterniond result;
330
            Multiply(ref left, ref right, out result);
331
            return result;
332
        }
333
 
334
        /// <summary>
335
        /// Multiplies two instances.
336
        /// </summary>
337
        /// <param name="left">The first instance.</param>
338
        /// <param name="right">The second instance.</param>
339
        /// <param name="result">A new instance containing the result of the calculation.</param>
340
        public static void Multiply(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
341
        {
342
            result = new Quaterniond(
343
                right.W * left.Xyz + left.W * right.Xyz + Vector3d.Cross(left.Xyz, right.Xyz),
344
                left.W * right.W - Vector3d.Dot(left.Xyz, right.Xyz));
345
        }
346
 
347
        /// <summary>
348
        /// Multiplies an instance by a scalar.
349
        /// </summary>
350
        /// <param name="quaternion">The instance.</param>
351
        /// <param name="scale">The scalar.</param>
352
        /// <param name="result">A new instance containing the result of the calculation.</param>
353
        public static void Multiply(ref Quaterniond quaternion, double scale, out Quaterniond result)
354
        {
355
            result = new Quaterniond(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
356
        }
357
 
358
        /// <summary>
359
        /// Multiplies an instance by a scalar.
360
        /// </summary>
361
        /// <param name="quaternion">The instance.</param>
362
        /// <param name="scale">The scalar.</param>
363
        /// <returns>A new instance containing the result of the calculation.</returns>
364
        public static Quaterniond Multiply(Quaterniond quaternion, double scale)
365
        {
366
            return new Quaterniond(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
367
        }
368
 
369
        #endregion
370
 
371
        #region Conjugate
372
 
373
        /// <summary>
374
        /// Get the conjugate of the given Quaterniond
375
        /// </summary>
376
        /// <param name="q">The Quaterniond</param>
377
        /// <returns>The conjugate of the given Quaterniond</returns>
378
        public static Quaterniond Conjugate(Quaterniond q)
379
        {
380
            return new Quaterniond(-q.Xyz, q.W);
381
        }
382
 
383
        /// <summary>
384
        /// Get the conjugate of the given Quaterniond
385
        /// </summary>
386
        /// <param name="q">The Quaterniond</param>
387
        /// <param name="result">The conjugate of the given Quaterniond</param>
388
        public static void Conjugate(ref Quaterniond q, out Quaterniond result)
389
        {
390
            result = new Quaterniond(-q.Xyz, q.W);
391
        }
392
 
393
        #endregion
394
 
395
        #region Invert
396
 
397
        /// <summary>
398
        /// Get the inverse of the given Quaterniond
399
        /// </summary>
400
        /// <param name="q">The Quaterniond to invert</param>
401
        /// <returns>The inverse of the given Quaterniond</returns>
402
        public static Quaterniond Invert(Quaterniond q)
403
        {
404
            Quaterniond result;
405
            Invert(ref q, out result);
406
            return result;
407
        }
408
 
409
        /// <summary>
410
        /// Get the inverse of the given Quaterniond
411
        /// </summary>
412
        /// <param name="q">The Quaterniond to invert</param>
413
        /// <param name="result">The inverse of the given Quaterniond</param>
414
        public static void Invert(ref Quaterniond q, out Quaterniond result)
415
        {
416
            double lengthSq = q.LengthSquared;
417
            if (lengthSq != 0.0)
418
            {
419
                double i = 1.0f / lengthSq;
420
                result = new Quaterniond(q.Xyz * -i, q.W * i);
421
            }
422
            else
423
            {
424
                result = q;
425
            }
426
        }
427
 
428
        #endregion
429
 
430
        #region Normalize
431
 
432
        /// <summary>
433
        /// Scale the given Quaterniond to unit length
434
        /// </summary>
435
        /// <param name="q">The Quaterniond to normalize</param>
436
        /// <returns>The normalized Quaterniond</returns>
437
        public static Quaterniond Normalize(Quaterniond q)
438
        {
439
            Quaterniond result;
440
            Normalize(ref q, out result);
441
            return result;
442
        }
443
 
444
        /// <summary>
445
        /// Scale the given Quaterniond to unit length
446
        /// </summary>
447
        /// <param name="q">The Quaterniond to normalize</param>
448
        /// <param name="result">The normalized Quaterniond</param>
449
        public static void Normalize(ref Quaterniond q, out Quaterniond result)
450
        {
451
            double scale = 1.0f / q.Length;
452
            result = new Quaterniond(q.Xyz * scale, q.W * scale);
453
        }
454
 
455
        #endregion
456
 
457
        #region FromAxisAngle
458
 
459
        /// <summary>
460
        /// Build a Quaterniond from the given axis and angle
461
        /// </summary>
462
        /// <param name="axis">The axis to rotate about</param>
463
        /// <param name="angle">The rotation angle in radians</param>
464
        /// <returns></returns>
465
        public static Quaterniond FromAxisAngle(Vector3d axis, double angle)
466
        {
467
            if (axis.LengthSquared == 0.0f)
468
                return Identity;
469
 
470
            Quaterniond result = Identity;
471
 
472
            angle *= 0.5f;
473
            axis.Normalize();
474
            result.Xyz = axis * (double)System.Math.Sin(angle);
475
            result.W = (double)System.Math.Cos(angle);
476
 
477
            return Normalize(result);
478
        }
479
 
480
        #endregion
481
 
482
        #region Slerp
483
 
484
        /// <summary>
485
        /// Do Spherical linear interpolation between two quaternions 
486
        /// </summary>
487
        /// <param name="q1">The first Quaterniond</param>
488
        /// <param name="q2">The second Quaterniond</param>
489
        /// <param name="blend">The blend factor</param>
490
        /// <returns>A smooth blend between the given quaternions</returns>
491
        public static Quaterniond Slerp(Quaterniond q1, Quaterniond q2, double blend)
492
        {
493
            // if either input is zero, return the other.
494
            if (q1.LengthSquared == 0.0f)
495
            {
496
                if (q2.LengthSquared == 0.0f)
497
                {
498
                    return Identity;
499
                }
500
                return q2;
501
            }
502
            else if (q2.LengthSquared == 0.0f)
503
            {
504
                return q1;
505
            }
506
 
507
 
508
            double cosHalfAngle = q1.W * q2.W + Vector3d.Dot(q1.Xyz, q2.Xyz);
509
 
510
            if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
511
            {
512
                // angle = 0.0f, so just return one input.
513
                return q1;
514
            }
515
            else if (cosHalfAngle < 0.0f)
516
            {
517
                q2.Xyz = -q2.Xyz;
518
                q2.W = -q2.W;
519
                cosHalfAngle = -cosHalfAngle;
520
            }
521
 
522
            double blendA;
523
            double blendB;
524
            if (cosHalfAngle < 0.99f)
525
            {
526
                // do proper slerp for big angles
527
                double halfAngle = (double)System.Math.Acos(cosHalfAngle);
528
                double sinHalfAngle = (double)System.Math.Sin(halfAngle);
529
                double oneOverSinHalfAngle = 1.0f / sinHalfAngle;
530
                blendA = (double)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
531
                blendB = (double)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
532
            }
533
            else
534
            {
535
                // do lerp if angle is really small.
536
                blendA = 1.0f - blend;
537
                blendB = blend;
538
            }
539
 
540
            Quaterniond result = new Quaterniond(blendA * q1.Xyz + blendB * q2.Xyz, blendA * q1.W + blendB * q2.W);
541
            if (result.LengthSquared > 0.0f)
542
                return Normalize(result);
543
            else
544
                return Identity;
545
        }
546
 
547
        #endregion
548
 
549
        #endregion
550
 
551
        #region Operators
552
 
553
        /// <summary>
554
        /// Adds two instances.
555
        /// </summary>
556
        /// <param name="left">The first instance.</param>
557
        /// <param name="right">The second instance.</param>
558
        /// <returns>The result of the calculation.</returns>
559
        public static Quaterniond operator +(Quaterniond left, Quaterniond right)
560
        {
561
            left.Xyz += right.Xyz;
562
            left.W += right.W;
563
            return left;
564
        }
565
 
566
        /// <summary>
567
        /// Subtracts two instances.
568
        /// </summary>
569
        /// <param name="left">The first instance.</param>
570
        /// <param name="right">The second instance.</param>
571
        /// <returns>The result of the calculation.</returns>
572
        public static Quaterniond operator -(Quaterniond left, Quaterniond right)
573
        {
574
            left.Xyz -= right.Xyz;
575
            left.W -= right.W;
576
            return left;
577
        }
578
 
579
        /// <summary>
580
        /// Multiplies two instances.
581
        /// </summary>
582
        /// <param name="left">The first instance.</param>
583
        /// <param name="right">The second instance.</param>
584
        /// <returns>The result of the calculation.</returns>
585
        public static Quaterniond operator *(Quaterniond left, Quaterniond right)
586
        {
587
            Multiply(ref left, ref right, out left);
588
            return left;
589
        }
590
 
591
        /// <summary>
592
        /// Multiplies an instance by a scalar.
593
        /// </summary>
594
        /// <param name="quaternion">The instance.</param>
595
        /// <param name="scale">The scalar.</param>
596
        /// <returns>A new instance containing the result of the calculation.</returns>
597
        public static Quaterniond operator *(Quaterniond quaternion, double scale)
598
        {
599
            Multiply(ref quaternion, scale, out quaternion);
600
            return quaternion;
601
        }
602
 
603
        /// <summary>
604
        /// Multiplies an instance by a scalar.
605
        /// </summary>
606
        /// <param name="quaternion">The instance.</param>
607
        /// <param name="scale">The scalar.</param>
608
        /// <returns>A new instance containing the result of the calculation.</returns>
609
        public static Quaterniond operator *(double scale, Quaterniond quaternion)
610
        {
611
            return new Quaterniond(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
612
        }
613
 
614
        /// <summary>
615
        /// Compares two instances for equality.
616
        /// </summary>
617
        /// <param name="left">The first instance.</param>
618
        /// <param name="right">The second instance.</param>
619
        /// <returns>True, if left equals right; false otherwise.</returns>
620
        public static bool operator ==(Quaterniond left, Quaterniond right)
621
        {
622
            return left.Equals(right);
623
        }
624
 
625
        /// <summary>
626
        /// Compares two instances for inequality.
627
        /// </summary>
628
        /// <param name="left">The first instance.</param>
629
        /// <param name="right">The second instance.</param>
630
        /// <returns>True, if left does not equal right; false otherwise.</returns>
631
        public static bool operator !=(Quaterniond left, Quaterniond right)
632
        {
633
            return !left.Equals(right);
634
        }
635
 
636
        #endregion
637
 
638
        #region Overrides
639
 
640
        #region public override string ToString()
641
 
642
        /// <summary>
643
        /// Returns a System.String that represents the current Quaterniond.
644
        /// </summary>
645
        /// <returns></returns>
646
        public override string ToString()
647
        {
648
            return String.Format("V: {0}, W: {1}", Xyz, W);
649
        }
650
 
651
        #endregion
652
 
653
        #region public override bool Equals (object o)
654
 
655
        /// <summary>
656
        /// Compares this object instance to another object for equality. 
657
        /// </summary>
658
        /// <param name="other">The other object to be used in the comparison.</param>
659
        /// <returns>True if both objects are Quaternions of equal value. Otherwise it returns false.</returns>
660
        public override bool Equals(object other)
661
        {
662
            if (other is Quaterniond == false) return false;
663
            return this == (Quaterniond)other;
664
        }
665
 
666
        #endregion
667
 
668
        #region public override int GetHashCode ()
669
 
670
        /// <summary>
671
        /// Provides the hash code for this object. 
672
        /// </summary>
673
        /// <returns>A hash code formed from the bitwise XOR of this objects members.</returns>
674
        public override int GetHashCode()
675
        {
676
            return Xyz.GetHashCode() ^ W.GetHashCode();
677
        }
678
 
679
        #endregion
680
 
681
        #endregion
682
 
683
        #endregion
684
 
685
#if false
686
 
687
        #region Fields
688
 
689
        /// <summary>The W component of the Quaterniond.</summary>
690
        public double W;
691
 
692
        /// <summary>The X component of the Quaterniond.</summary>
693
        public double X;
694
 
695
        /// <summary>The Y component of the Quaterniond.</summary>
696
        public double Y;
697
 
698
        /// <summary>The Z component of the Quaterniond.</summary>
699
        public double Z;
700
 
701
        #endregion
702
 
703
        #region Constructors
704
 
705
        /// <summary>Constructs left Quaterniond that is left copy of the given Quaterniond.</summary>
706
        /// <param name="quaterniond">The Quaterniond to copy.</param>
707
        public Quaterniond(ref Quaterniond Quaterniond) : this(Quaterniond.W, Quaterniond.X, Quaterniond.Y, Quaterniond.Z) { }
708
 
709
        /// <summary>Constructs left Quaterniond from the given components.</summary>
710
        /// <param name="w">The W component for the Quaterniond.</param>
711
        /// <param name="vector3d">A Vector representing the X, Y, and Z componets for the quaterion.</param>
712
        public Quaterniond(double w, ref Vector3d vector3d) : this(w, vector3d.X, vector3d.Y, vector3d.Z) { }
713
 
714
        /// <summary>Constructs left Quaterniond from the given axis and angle.</summary>
715
        /// <param name="axis">The axis for the Quaterniond.</param>
716
        /// <param name="angle">The angle for the quaternione.</param>
717
        public Quaterniond(ref Vector3d axis, double angle)
718
        {
719
            double halfAngle = Functions.DTOR * angle / 2;
720
 
721
            this.W = System.Math.Cos(halfAngle);
722
 
723
            double sin = System.Math.Sin(halfAngle);
724
            Vector3d axisNormalized;
725
            Vector3d.Normalize(ref axis, out axisNormalized);
726
            this.X = axisNormalized.X * sin;
727
            this.Y = axisNormalized.Y * sin;
728
            this.Z = axisNormalized.Z * sin;
729
        }
730
 
731
        /// <summary>Constructs left Quaterniond from the given components.</summary>
732
        /// <param name="w">The W component for the Quaterniond.</param>
733
        /// <param name="x">The X component for the Quaterniond.</param>
734
        /// <param name="y">The Y component for the Quaterniond.</param>
735
        /// <param name="z">The Z component for the Quaterniond.</param>
736
        public Quaterniond(double w, double x, double y, double z)
737
        {
738
            this.W = w;
739
            this.X = x;
740
            this.Y = y;
741
            this.Z = z;
742
        }
743
 
744
        /// <summary>Constructs left Quaterniond from the given array of double-precision floating-point numbers.</summary>
745
        /// <param name="doubleArray">The array of doubles for the components of the Quaterniond.</param>
746
        public Quaterniond(double[] doubleArray)
747
        {
748
            if (doubleArray == null || doubleArray.GetLength(0) < 4) throw new MissingFieldException();
749
 
750
            this.W = doubleArray[0];
751
            this.X = doubleArray[1];
752
            this.Y = doubleArray[2];
753
            this.Z = doubleArray[3];
754
        }
755
 
756
        /// <summary>Constructs left Quaterniond from the given matrix.  Only contains rotation information.</summary>
757
        /// <param name="matrix">The matrix for the components of the Quaterniond.</param>
758
        public Quaterniond(ref Matrix4d matrix)
759
        {
760
            double scale = System.Math.Pow(matrix.Determinant, 1.0d/3.0d);
761
 
762
            W = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] + matrix[1, 1] + matrix[2, 2])) / 2;
763
            X = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])) / 2;
764
            Y = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] + matrix[1, 1] - matrix[2, 2])) / 2;
765
            Z = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] - matrix[1, 1] + matrix[2, 2])) / 2;
766
            if( matrix[2,1] - matrix[1,2] < 0 ) X = -X;
767
            if( matrix[0,2] - matrix[2,0] < 0 ) Y = -Y;
768
            if( matrix[1,0] - matrix[0,1] < 0 ) Z = -Z;
769
        }
770
 
771
        public Quaterniond(ref Matrix3d matrix)
772
        {
773
            double scale = System.Math.Pow(matrix.Determinant, 1.0d / 3.0d);
774
 
775
            W = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] + matrix[1, 1] + matrix[2, 2])) / 2;
776
            X = System.Math.Sqrt(System.Math.Max(0, scale + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])) / 2;
777
            Y = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] + matrix[1, 1] - matrix[2, 2])) / 2;
778
            Z = System.Math.Sqrt(System.Math.Max(0, scale - matrix[0, 0] - matrix[1, 1] + matrix[2, 2])) / 2;
779
            if (matrix[2, 1] - matrix[1, 2] < 0) X = -X;
780
            if (matrix[0, 2] - matrix[2, 0] < 0) Y = -Y;
781
            if (matrix[1, 0] - matrix[0, 1] < 0) Z = -Z;
782
        }
783
 
784
        #endregion
785
 
786
        #region Arithmetic Operators
787
 
788
        public void Add(ref Quaterniond Quaterniond)
789
        {
790
            W = W + Quaterniond.W;
791
            X = X + Quaterniond.X;
792
            Y = Y + Quaterniond.Y;
793
            Z = Z + Quaterniond.Z;
794
        }
795
        public void Add(ref Quaterniond Quaterniond, out Quaterniond result)
796
        {
797
            result.W = W + Quaterniond.W;
798
            result.X = X + Quaterniond.X;
799
            result.Y = Y + Quaterniond.Y;
800
            result.Z = Z + Quaterniond.Z;
801
        }
802
        public static void Add(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
803
        {
804
            result.W = left.W + right.W;
805
            result.X = left.X + right.X;
806
            result.Y = left.Y + right.Y;
807
            result.Z = left.Z + right.Z;
808
        }
809
 
810
        public void Subtract(ref Quaterniond Quaterniond)
811
        {
812
            W = W - Quaterniond.W;
813
            X = X - Quaterniond.X;
814
            Y = Y - Quaterniond.Y;
815
            Z = Z - Quaterniond.Z;
816
        }
817
        public void Subtract(ref Quaterniond Quaterniond, out Quaterniond result)
818
        {
819
            result.W = W - Quaterniond.W;
820
            result.X = X - Quaterniond.X;
821
            result.Y = Y - Quaterniond.Y;
822
            result.Z = Z - Quaterniond.Z;
823
        }
824
        public static void Subtract(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
825
        {
826
            result.W = left.W - right.W;
827
            result.X = left.X - right.X;
828
            result.Y = left.Y - right.Y;
829
            result.Z = left.Z - right.Z;
830
        }
831
 
832
        public void Multiply(ref Quaterniond Quaterniond)
833
        {
834
            double w = W * Quaterniond.W - X * Quaterniond.X - Y * Quaterniond.Y - Z * Quaterniond.Z;
835
            double x = W * Quaterniond.X + X * Quaterniond.W + Y * Quaterniond.Z - Z * Quaterniond.Y;
836
            double y = W * Quaterniond.Y + Y * Quaterniond.W + Z * Quaterniond.X - X * Quaterniond.Z;
837
            Z = W * Quaterniond.Z + Z * Quaterniond.W + X * Quaterniond.Y - Y * Quaterniond.X;
838
            W = w;
839
            X = x;
840
            Y = y;
841
        }
842
        public void Multiply(ref Quaterniond Quaterniond, out Quaterniond result)
843
        {
844
            result.W = W * Quaterniond.W - X * Quaterniond.X - Y * Quaterniond.Y - Z * Quaterniond.Z;
845
            result.X = W * Quaterniond.X + X * Quaterniond.W + Y * Quaterniond.Z - Z * Quaterniond.Y;
846
            result.Y = W * Quaterniond.Y + Y * Quaterniond.W + Z * Quaterniond.X - X * Quaterniond.Z;
847
            result.Z = W * Quaterniond.Z + Z * Quaterniond.W + X * Quaterniond.Y - Y * Quaterniond.X;
848
        }
849
        public static void Multiply(ref Quaterniond left, ref Quaterniond right, out Quaterniond result)
850
        {
851
            result.W = left.W * right.W - left.X * right.X - left.Y * right.Y - left.Z * right.Z;
852
            result.X = left.W * right.X + left.X * right.W + left.Y * right.Z - left.Z * right.Y;
853
            result.Y = left.W * right.Y + left.Y * right.W + left.Z * right.X - left.X * right.Z;
854
            result.Z = left.W * right.Z + left.Z * right.W + left.X * right.Y - left.Y * right.X;
855
        }
856
 
857
        public void Multiply(double scalar)
858
        {
859
            W = W * scalar;
860
            X = X * scalar;
861
            Y = Y * scalar;
862
            Z = Z * scalar;
863
        }
864
        public void Multiply(double scalar, out Quaterniond result)
865
        {
866
            result.W = W * scalar;
867
            result.X = X * scalar;
868
            result.Y = Y * scalar;
869
            result.Z = Z * scalar;
870
        }
871
        public static void Multiply(ref Quaterniond Quaterniond, double scalar, out Quaterniond result)
872
        {
873
            result.W = Quaterniond.W * scalar;
874
            result.X = Quaterniond.X * scalar;
875
            result.Y = Quaterniond.Y * scalar;
876
            result.Z = Quaterniond.Z * scalar;
877
        }
878
 
879
        public void Divide(double scalar)
880
        {
881
            if (scalar == 0) throw new DivideByZeroException();
882
            W = W / scalar;
883
            X = X / scalar;
884
            Y = Y / scalar;
885
            Z = Z / scalar;
886
        }
887
        public void Divide(double scalar, out Quaterniond result)
888
        {
889
            if (scalar == 0) throw new DivideByZeroException();
890
            result.W = W / scalar;
891
            result.X = X / scalar;
892
            result.Y = Y / scalar;
893
            result.Z = Z / scalar;
894
        }
895
        public static void Divide(ref Quaterniond Quaterniond, double scalar, out Quaterniond result)
896
        {
897
            if (scalar == 0) throw new DivideByZeroException();
898
            result.W = Quaterniond.W / scalar;
899
            result.X = Quaterniond.X / scalar;
900
            result.Y = Quaterniond.Y / scalar;
901
            result.Z = Quaterniond.Z / scalar;
902
        }
903
 
904
        #endregion
905
 
906
        #region Functions
907
 
908
        public double Modulus
909
        {
910
            get
911
            {
912
                return System.Math.Sqrt(W * W + X * X + Y * Y + Z * Z);
913
            }
914
        }
915
        public double ModulusSquared
916
        {
917
            get
918
            {
919
                return W * W + X * X + Y * Y + Z * Z;
920
            }
921
        }
922
 
923
        public static double DotProduct(Quaterniond left, Quaterniond right)
924
        {
925
            return left.W * right.W + left.X * right.X + left.Y * right.Y + left.Z * right.Z;
926
        }
927
 
928
        public void Normalize()
929
        {
930
            double modulus = System.Math.Sqrt(W * W + X * X + Y * Y + Z * Z);
931
            if (modulus == 0) throw new DivideByZeroException();
932
            W = W / modulus;
933
            X = X / modulus;
934
            Y = Y / modulus;
935
            Z = Z / modulus;
936
        }
937
        public void Normalize( out Quaterniond result )
938
        {
939
            double modulus = System.Math.Sqrt(W * W + X * X + Y * Y + Z * Z);
940
            if (modulus == 0) throw new DivideByZeroException();
941
            result.W = W / modulus;
942
            result.X = X / modulus;
943
            result.Y = Y / modulus;
944
            result.Z = Z / modulus;
945
        }
946
        public static void Normalize(ref Quaterniond Quaterniond, out Quaterniond result)
947
        {
948
            double modulus = System.Math.Sqrt(Quaterniond.W * Quaterniond.W + Quaterniond.X * Quaterniond.X + Quaterniond.Y * Quaterniond.Y + Quaterniond.Z * Quaterniond.Z);
949
            if (modulus == 0) throw new DivideByZeroException();
950
            result.W = Quaterniond.W / modulus;
951
            result.X = Quaterniond.X / modulus;
952
            result.Y = Quaterniond.Y / modulus;
953
            result.Z = Quaterniond.Z / modulus;
954
        }
955
 
956
        public void Conjugate()
957
        {
958
            X = -X;
959
            Y = -Y;
960
            Z = -Z;
961
        }
962
        public void Conjugate( out Quaterniond result )
963
        {
964
            result.W = W;
965
            result.X = -X;
966
            result.Y = -Y;
967
            result.Z = -Z;
968
        }
969
        public static void Conjugate(ref Quaterniond Quaterniond, out Quaterniond result)
970
        {
971
            result.W = Quaterniond.W;
972
            result.X = -Quaterniond.X;
973
            result.Y = -Quaterniond.Y;
974
            result.Z = -Quaterniond.Z;
975
        }
976
 
977
        public void Inverse()
978
        {
979
            double modulusSquared = W * W + X * X + Y * Y + Z * Z;
980
            if (modulusSquared <= 0) throw new InvalidOperationException();
981
            double inverseModulusSquared = 1.0 / modulusSquared;
982
            W = W * inverseModulusSquared;
983
            X = X * -inverseModulusSquared;
984
            Y = Y * -inverseModulusSquared;
985
            Z = Z * -inverseModulusSquared;
986
        }
987
        public void Inverse( out Quaterniond result )
988
        {
989
            double modulusSquared = W * W + X * X + Y * Y + Z * Z;
990
            if (modulusSquared <= 0) throw new InvalidOperationException();
991
            double inverseModulusSquared = 1.0 / modulusSquared;
992
            result.W = W * inverseModulusSquared;
993
            result.X = X * -inverseModulusSquared;
994
            result.Y = Y * -inverseModulusSquared;
995
            result.Z = Z * -inverseModulusSquared;
996
        }
997
        public static void Inverse(ref Quaterniond Quaterniond, out Quaterniond result)
998
        {
999
            double modulusSquared = Quaterniond.W * Quaterniond.W + Quaterniond.X * Quaterniond.X + Quaterniond.Y * Quaterniond.Y + Quaterniond.Z * Quaterniond.Z;
1000
            if (modulusSquared <= 0) throw new InvalidOperationException();
1001
            double inverseModulusSquared = 1.0 / modulusSquared;
1002
            result.W = Quaterniond.W * inverseModulusSquared;
1003
            result.X = Quaterniond.X * -inverseModulusSquared;
1004
            result.Y = Quaterniond.Y * -inverseModulusSquared;
1005
            result.Z = Quaterniond.Z * -inverseModulusSquared;
1006
        }
1007
 
1008
        public void Log()
1009
        {
1010
            if (System.Math.Abs(W) < 1.0)
1011
            {
1012
                double angle = System.Math.Acos(W);
1013
                double sin = System.Math.Sin(angle);
1014
 
1015
                if (System.Math.Abs(sin) >= 0)
1016
                {
1017
                    double coefficient = angle / sin;
1018
                    X = X * coefficient;
1019
                    Y = Y * coefficient;
1020
                    Z = Z * coefficient;
1021
                }
1022
            }
1023
            else
1024
            {
1025
                X = 0;
1026
                Y = 0;
1027
                Z = 0;
1028
            }
1029
 
1030
            W = 0;
1031
        }
1032
        public void Log( out Quaterniond result )
1033
        {
1034
            if (System.Math.Abs(W) < 1.0)
1035
            {
1036
                double angle = System.Math.Acos(W);
1037
                double sin = System.Math.Sin(angle);
1038
 
1039
                if (System.Math.Abs(sin) >= 0)
1040
                {
1041
                    double coefficient = angle / sin;
1042
                    result.X = X * coefficient;
1043
                    result.Y = Y * coefficient;
1044
                    result.Z = Z * coefficient;
1045
                }
1046
                else
1047
                {
1048
                    result.X = X;
1049
                    result.Y = Y;
1050
                    result.Z = Z;
1051
                }
1052
            }
1053
            else
1054
            {
1055
                result.X = 0;
1056
                result.Y = 0;
1057
                result.Z = 0;
1058
            }
1059
 
1060
            result.W = 0;
1061
        }
1062
        public static void Log(ref Quaterniond Quaterniond, out Quaterniond result)
1063
        {
1064
            if (System.Math.Abs(Quaterniond.W) < 1.0)
1065
            {
1066
                double angle = System.Math.Acos(Quaterniond.W);
1067
                double sin = System.Math.Sin(angle);
1068
 
1069
                if (System.Math.Abs(sin) >= 0)
1070
                {
1071
                    double coefficient = angle / sin;
1072
                    result.X = Quaterniond.X * coefficient;
1073
                    result.Y = Quaterniond.Y * coefficient;
1074
                    result.Z = Quaterniond.Z * coefficient;
1075
                }
1076
                else
1077
                {
1078
                    result.X = Quaterniond.X;
1079
                    result.Y = Quaterniond.Y;
1080
                    result.Z = Quaterniond.Z;
1081
                }
1082
            }
1083
            else
1084
            {
1085
                result.X = 0;
1086
                result.Y = 0;
1087
                result.Z = 0;
1088
            }
1089
 
1090
            result.W = 0;
1091
        }
1092
 
1093
        public void Exp()
1094
        {
1095
            double angle = System.Math.Sqrt(X * X + Y * Y + Z * Z);
1096
            double sin = System.Math.Sin(angle);
1097
 
1098
            if (System.Math.Abs(sin) > 0)
1099
            {
1100
                double coefficient = angle / sin;
1101
                W = 0;
1102
                X = X * coefficient;
1103
                Y = Y * coefficient;
1104
                Z = Z * coefficient;
1105
            }
1106
            else
1107
            {
1108
                W = 0;
1109
            }
1110
        }
1111
        public void Exp(out Quaterniond result)
1112
        {
1113
            double angle = System.Math.Sqrt(X * X + Y * Y + Z * Z);
1114
            double sin = System.Math.Sin(angle);
1115
 
1116
            if (System.Math.Abs(sin) > 0)
1117
            {
1118
                double coefficient = angle / sin;
1119
                result.W = 0;
1120
                result.X = X * coefficient;
1121
                result.Y = Y * coefficient;
1122
                result.Z = Z * coefficient;
1123
            }
1124
            else
1125
            {
1126
                result.W = 0;
1127
                result.X = X;
1128
                result.Y = Y;
1129
                result.Z = Z;
1130
            }
1131
        }
1132
        public static void Exp(ref Quaterniond Quaterniond, out Quaterniond result)
1133
        {
1134
            double angle = System.Math.Sqrt(Quaterniond.X * Quaterniond.X + Quaterniond.Y * Quaterniond.Y + Quaterniond.Z * Quaterniond.Z);
1135
            double sin = System.Math.Sin(angle);
1136
 
1137
            if (System.Math.Abs(sin) > 0)
1138
            {
1139
                double coefficient = angle / sin;
1140
                result.W = 0;
1141
                result.X = Quaterniond.X * coefficient;
1142
                result.Y = Quaterniond.Y * coefficient;
1143
                result.Z = Quaterniond.Z * coefficient;
1144
            }
1145
            else
1146
            {
1147
                result.W = 0;
1148
                result.X = Quaterniond.X;
1149
                result.Y = Quaterniond.Y;
1150
                result.Z = Quaterniond.Z;
1151
            }
1152
        }
1153
 
1154
        /// <summary>Returns left matrix for this Quaterniond.</summary>
1155
        public void Matrix4d(out Matrix4d result)
1156
        {
1157
            // TODO Expand
1158
            result = new Matrix4d(ref this);
1159
        }
1160
 
1161
        public void GetAxisAndAngle(out Vector3d axis, out double angle)
1162
        {
1163
            Quaterniond Quaterniond;
1164
            Normalize(out Quaterniond);
1165
            double cos = Quaterniond.W;
1166
            angle = System.Math.Acos(cos) * 2 * Functions.RTOD;
1167
            double sin = System.Math.Sqrt( 1.0d - cos * cos );
1168
            if ( System.Math.Abs( sin ) < 0.0001 ) sin = 1;
1169
            axis = new Vector3d(X / sin, Y / sin, Z / sin);
1170
        }
1171
 
1172
        public static void Slerp(ref Quaterniond start, ref Quaterniond end, double blend, out Quaterniond result)
1173
        {
1174
            if (start.W == 0 && start.X == 0 && start.Y == 0 && start.Z == 0)
1175
            {
1176
                if (end.W == 0 && end.X == 0 && end.Y == 0 && end.Z == 0)
1177
                {
1178
                    result.W = 1;
1179
                    result.X = 0;
1180
                    result.Y = 0;
1181
                    result.Z = 0;
1182
                }
1183
                else
1184
                {
1185
                    result = end;
1186
                }
1187
            }
1188
            else if (end.W == 0 && end.X == 0 && end.Y == 0 && end.Z == 0)
1189
            {
1190
                result = start;
1191
            }
1192
 
1193
            Vector3d startVector = new Vector3d(start.X, start.Y, start.Z);
1194
            Vector3d endVector = new Vector3d(end.X, end.Y, end.Z);
1195
            double cosHalfAngle = start.W * end.W + Vector3d.Dot(startVector, endVector);
1196
 
1197
            if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
1198
            {
1199
                // angle = 0.0f, so just return one input.
1200
                result = start;
1201
            }
1202
            else if (cosHalfAngle < 0.0f)
1203
            {
1204
                end.W = -end.W;
1205
                end.X = -end.X;
1206
                end.Y = -end.Y;
1207
                end.Z = -end.Z;
1208
                cosHalfAngle = -cosHalfAngle;
1209
            }
1210
 
1211
            double blendA;
1212
            double blendB;
1213
            if (cosHalfAngle < 0.99f)
1214
            {
1215
                // do proper slerp for big angles
1216
                double halfAngle = (double)System.Math.Acos(cosHalfAngle);
1217
                double sinHalfAngle = (double)System.Math.Sin(halfAngle);
1218
                double oneOverSinHalfAngle = 1.0f / sinHalfAngle;
1219
                blendA = (double)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
1220
                blendB = (double)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
1221
            }
1222
            else
1223
            {
1224
                // do lerp if angle is really small.
1225
                blendA = 1.0f - blend;
1226
                blendB = blend;
1227
            }
1228
 
1229
            result.W = blendA * start.W + blendB * end.W;
1230
            result.X = blendA * start.X + blendB * end.X;
1231
            result.Y = blendA * start.Y + blendB * end.Y;
1232
            result.Z = blendA * start.Z + blendB * end.Z;
1233
 
1234
            if (result.W != 0 || result.X != 0 || result.Y != 0 || result.Z != 0)
1235
            {
1236
                result.Normalize();
1237
            }
1238
            else
1239
            {
1240
                result.W = 1;
1241
                result.X = 0;
1242
                result.Y = 0;
1243
                result.Z = 0;
1244
            }
1245
        }
1246
 
1247
        #endregion
1248
 
1249
        #region HashCode
1250
 
1251
        /// <summary>Returns the hash code for this instance.</summary>
1252
        /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
1253
        public override int GetHashCode()
1254
        {
1255
            base.GetHashCode();
1256
            return W.GetHashCode() ^ X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
1257
        }
1258
 
1259
        #endregion
1260
 
1261
        #region String and Parse
1262
 
1263
        /// <summary>Returns the fully qualified type name of this instance.</summary>
1264
        /// <returns>A System.String containing left fully qualified type name.</returns>
1265
        public override string ToString()
1266
        {
1267
            return string.Format("({0}, {1}, {2}, {3})", W, X, Y, Z);
1268
        }
1269
 
1270
        /// <summary>Parses left string, converting it to left Quaterniond.</summary>
1271
        /// <param name="str">The string to parse.</param>
1272
        /// <returns>The Quaterniond represented by the string.</returns>
1273
        public static void Parse(string str, out Quaterniond result)
1274
        {
1275
            Match match = new Regex(@"\((?<w>.*),(?<x>.*),(?<y>.*),(?<z>.*)\)", RegexOptions.None).Match(str);
1276
            if (!match.Success) throw new Exception("Parse failed!");
1277
 
1278
            result.W = double.Parse(match.Result("${w}"));
1279
            result.X = double.Parse(match.Result("${x}"));
1280
            result.Y = double.Parse(match.Result("${y}"));
1281
            result.Z = double.Parse(match.Result("${z}"));
1282
        }
1283
 
1284
        #endregion
1285
 
1286
        #region Constants
1287
 
1288
        /// <summary>A quaterion with all zero components.</summary>
1289
        public static readonly Quaterniond Zero = new Quaterniond(0, 0, 0, 0);
1290
 
1291
        /// <summary>A quaterion representing an identity.</summary>
1292
        public static readonly Quaterniond Identity = new Quaterniond(1, 0, 0, 0);
1293
 
1294
        /// <summary>A quaterion representing the W axis.</summary>
1295
        public static readonly Quaterniond WAxis = new Quaterniond(1, 0, 0, 0);
1296
 
1297
        /// <summary>A quaterion representing the X axis.</summary>
1298
        public static readonly Quaterniond XAxis = new Quaterniond(0, 1, 0, 0);
1299
 
1300
        /// <summary>A quaterion representing the Y axis.</summary>
1301
        public static readonly Quaterniond YAxis = new Quaterniond(0, 0, 1, 0);
1302
 
1303
        /// <summary>A quaterion representing the Z axis.</summary>
1304
        public static readonly Quaterniond ZAxis = new Quaterniond(0, 0, 0, 1);
1305
 
1306
        #endregion
1307
 
1308
#endif
1309
 
1310
        #region IEquatable<Quaterniond> Members
1311
 
1312
        /// <summary>
1313
        /// Compares this Quaterniond instance to another Quaterniond for equality. 
1314
        /// </summary>
1315
        /// <param name="other">The other Quaterniond to be used in the comparison.</param>
1316
        /// <returns>True if both instances are equal; false otherwise.</returns>
1317
        public bool Equals(Quaterniond other)
1318
        {
1319
            return Xyz == other.Xyz && W == other.W;
1320
        }
1321
 
1322
        #endregion
1323
    }
1324
}