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.Xml.Serialization;
28
 
29
namespace OpenTK.Math
30
{
31
    /// <summary>
32
    /// Represents a 3D vector using three double-precision floating-point numbers.
33
    /// </summary>
34
    [Obsolete("OpenTK.Math functions have been moved to the root OpenTK namespace (reason: XNA compatibility")]
35
    [Serializable]
36
    [StructLayout(LayoutKind.Sequential)]
37
    public struct Vector3d : IEquatable<Vector3d>
38
    {
39
        #region Fields
40
 
41
        /// <summary>
42
        /// The X component of the Vector3.
43
        /// </summary>
44
        public double X;
45
 
46
        /// <summary>
47
        /// The Y component of the Vector3.
48
        /// </summary>
49
        public double Y;
50
 
51
        /// <summary>
52
        /// The Z component of the Vector3.
53
        /// </summary>
54
        public double Z;
55
 
56
        #endregion
57
 
58
        #region Constructors
59
 
60
        /// <summary>
61
        /// Constructs a new Vector3.
62
        /// </summary>
63
        /// <param name="x">The x component of the Vector3.</param>
64
        /// <param name="y">The y component of the Vector3.</param>
65
        /// <param name="z">The z component of the Vector3.</param>
66
        public Vector3d(double x, double y, double z)
67
        {
68
            X = x;
69
            Y = y;
70
            Z = z;
71
        }
72
 
73
        /// <summary>
74
        /// Constructs a new instance from the given Vector2d.
75
        /// </summary>
76
        /// <param name="v">The Vector2d to copy components from.</param>
77
        public Vector3d(Vector2d v)
78
        {
79
            X = v.X;
80
            Y = v.Y;
81
            Z = 0.0f;
82
        }
83
 
84
        /// <summary>
85
        /// Constructs a new instance from the given Vector3d.
86
        /// </summary>
87
        /// <param name="v">The Vector3d to copy components from.</param>
88
        public Vector3d(Vector3d v)
89
        {
90
            X = v.X;
91
            Y = v.Y;
92
            Z = v.Z;
93
        }
94
 
95
        /// <summary>
96
        /// Constructs a new instance from the given Vector4d.
97
        /// </summary>
98
        /// <param name="v">The Vector4d to copy components from.</param>
99
        public Vector3d(Vector4d v)
100
        {
101
            X = v.X;
102
            Y = v.Y;
103
            Z = v.Z;
104
        }
105
 
106
 
107
        #endregion
108
 
109
        #region Public Members
110
 
111
        #region Instance
112
 
113
        #region public void Add()
114
 
115
        /// <summary>Add the Vector passed as parameter to this instance.</summary>
116
        /// <param name="right">Right operand. This parameter is only read from.</param>
117
        public void Add(Vector3d right)
118
        {
119
            this.X += right.X;
120
            this.Y += right.Y;
121
            this.Z += right.Z;
122
        }
123
 
124
        /// <summary>Add the Vector passed as parameter to this instance.</summary>
125
        /// <param name="right">Right operand. This parameter is only read from.</param>
126
        [CLSCompliant(false)]
127
        public void Add(ref Vector3d right)
128
        {
129
            this.X += right.X;
130
            this.Y += right.Y;
131
            this.Z += right.Z;
132
        }
133
 
134
        #endregion public void Add()
135
 
136
        #region public void Sub()
137
 
138
        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
139
        /// <param name="right">Right operand. This parameter is only read from.</param>
140
        public void Sub(Vector3d right)
141
        {
142
            this.X -= right.X;
143
            this.Y -= right.Y;
144
            this.Z -= right.Z;
145
        }
146
 
147
        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
148
        /// <param name="right">Right operand. This parameter is only read from.</param>
149
        [CLSCompliant(false)]
150
        public void Sub(ref Vector3d right)
151
        {
152
            this.X -= right.X;
153
            this.Y -= right.Y;
154
            this.Z -= right.Z;
155
        }
156
 
157
        #endregion public void Sub()
158
 
159
        #region public void Mult()
160
 
161
        /// <summary>Multiply this instance by a scalar.</summary>
162
        /// <param name="f">Scalar operand.</param>
163
        public void Mult(double f)
164
        {
165
            this.X *= f;
166
            this.Y *= f;
167
            this.Z *= f;
168
        }
169
 
170
        #endregion public void Mult()
171
 
172
        #region public void Div()
173
 
174
        /// <summary>Divide this instance by a scalar.</summary>
175
        /// <param name="f">Scalar operand.</param>
176
        public void Div(double f)
177
        {
178
            double mult = 1.0 / f;
179
            this.X *= mult;
180
            this.Y *= mult;
181
            this.Z *= mult;
182
        }
183
 
184
        #endregion public void Div()
185
 
186
        #region public double Length
187
 
188
        /// <summary>
189
        /// Gets the length (magnitude) of the vector.
190
        /// </summary>
191
        /// <see cref="LengthFast"/>
192
        /// <seealso cref="LengthSquared"/>
193
        public double Length
194
        {
195
            get
196
            {
197
                return (float)System.Math.Sqrt(X * X + Y * Y + Z * Z);
198
            }
199
        }
200
 
201
        #endregion
202
 
203
        #region public double LengthFast
204
 
205
        /// <summary>
206
        /// Gets an approximation of the vector length (magnitude).
207
        /// </summary>
208
        /// <remarks>
209
        /// This property uses an approximation of the square root function to calculate vector magnitude, with
210
        /// an upper error bound of 0.001.
211
        /// </remarks>
212
        /// <see cref="Length"/>
213
        /// <seealso cref="LengthSquared"/>
214
        public double LengthFast
215
        {
216
            get
217
            {
218
                return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
219
            }
220
        }
221
 
222
        #endregion
223
 
224
        #region public double LengthSquared
225
 
226
        /// <summary>
227
        /// Gets the square of the vector length (magnitude).
228
        /// </summary>
229
        /// <remarks>
230
        /// This property avoids the costly square root operation required by the Length property. This makes it more suitable
231
        /// for comparisons.
232
        /// </remarks>
233
        /// <see cref="Length"/>
234
        /// <seealso cref="LengthFast"/>
235
        public double LengthSquared
236
        {
237
            get
238
            {
239
                return X * X + Y * Y + Z * Z;
240
            }
241
        }
242
 
243
        #endregion
244
 
245
        #region public void Normalize()
246
 
247
        /// <summary>
248
        /// Scales the Vector3d to unit length.
249
        /// </summary>
250
        public void Normalize()
251
        {
252
            double scale = 1.0f / this.Length;
253
            X *= scale;
254
            Y *= scale;
255
            Z *= scale;
256
        }
257
 
258
        #endregion
259
 
260
        #region public void NormalizeFast()
261
 
262
        /// <summary>
263
        /// Scales the Vector3d to approximately unit length.
264
        /// </summary>
265
        public void NormalizeFast()
266
        {
267
            double scale = Functions.InverseSqrtFast(X * X + Y * Y + Z * Z);
268
            X *= scale;
269
            Y *= scale;
270
            Z *= scale;
271
        }
272
 
273
        #endregion
274
 
275
        #region public void Scale()
276
 
277
        /// <summary>
278
        /// Scales the current Vector3d by the given amounts.
279
        /// </summary>
280
        /// <param name="sx">The scale of the X component.</param>
281
        /// <param name="sy">The scale of the Y component.</param>
282
        /// <param name="sz">The scale of the Z component.</param>
283
        public void Scale(double sx, double sy, double sz)
284
        {
285
            this.X = X * sx;
286
            this.Y = Y * sy;
287
            this.Z = Z * sz;
288
        }
289
 
290
        /// <summary>Scales this instance by the given parameter.</summary>
291
        /// <param name="scale">The scaling of the individual components.</param>
292
        public void Scale(Vector3d scale)
293
        {
294
            this.X *= scale.X;
295
            this.Y *= scale.Y;
296
            this.Z *= scale.Z;
297
        }
298
 
299
        /// <summary>Scales this instance by the given parameter.</summary>
300
        /// <param name="scale">The scaling of the individual components.</param>
301
        [CLSCompliant(false)]
302
        public void Scale(ref Vector3d scale)
303
        {
304
            this.X *= scale.X;
305
            this.Y *= scale.Y;
306
            this.Z *= scale.Z;
307
        }
308
 
309
        #endregion public void Scale()
310
 
311
        #endregion
312
 
313
        #region Static
314
 
315
        #region Fields
316
 
317
        /// <summary>
318
        /// Defines a unit-length Vector3d that points towards the X-axis.
319
        /// </summary>
320
        public static readonly Vector3d UnitX = new Vector3d(1, 0, 0);
321
 
322
        /// <summary>
323
        /// Defines a unit-length Vector3d that points towards the Y-axis.
324
        /// </summary>
325
        public static readonly Vector3d UnitY = new Vector3d(0, 1, 0);
326
 
327
        /// <summary>
328
        /// /// Defines a unit-length Vector3d that points towards the Z-axis.
329
        /// </summary>
330
        public static readonly Vector3d UnitZ = new Vector3d(0, 0, 1);
331
 
332
        /// <summary>
333
        /// Defines a zero-length Vector3.
334
        /// </summary>
335
        public static readonly Vector3d Zero = new Vector3d(0, 0, 0);
336
 
337
        /// <summary>
338
        /// Defines an instance with all components set to 1.
339
        /// </summary>
340
        public static readonly Vector3d One = new Vector3d(1, 1, 1);
341
 
342
        /// <summary>
343
        /// Defines the size of the Vector3d struct in bytes.
344
        /// </summary>
345
        public static readonly int SizeInBytes = Marshal.SizeOf(new Vector3d());
346
 
347
        #endregion
348
 
349
        #region Add
350
 
351
        /// <summary>
352
        /// Add two Vectors
353
        /// </summary>
354
        /// <param name="a">First operand</param>
355
        /// <param name="b">Second operand</param>
356
        /// <returns>Result of addition</returns>
357
        public static Vector3d Add(Vector3d a, Vector3d b)
358
        {
359
            a.X += b.X;
360
            a.Y += b.Y;
361
            a.Z += b.Z;
362
            return a;
363
        }
364
 
365
        /// <summary>
366
        /// Add two Vectors
367
        /// </summary>
368
        /// <param name="a">First operand</param>
369
        /// <param name="b">Second operand</param>
370
        /// <param name="result">Result of addition</param>
371
        public static void Add(ref Vector3d a, ref Vector3d b, out Vector3d result)
372
        {
373
            result.X = a.X + b.X;
374
            result.Y = a.Y + b.Y;
375
            result.Z = a.Z + b.Z;
376
        }
377
 
378
        #endregion
379
 
380
        #region Sub
381
 
382
        /// <summary>
383
        /// Subtract one Vector from another
384
        /// </summary>
385
        /// <param name="a">First operand</param>
386
        /// <param name="b">Second operand</param>
387
        /// <returns>Result of subtraction</returns>
388
        public static Vector3d Sub(Vector3d a, Vector3d b)
389
        {
390
            a.X -= b.X;
391
            a.Y -= b.Y;
392
            a.Z -= b.Z;
393
            return a;
394
        }
395
 
396
        /// <summary>
397
        /// Subtract one Vector from another
398
        /// </summary>
399
        /// <param name="a">First operand</param>
400
        /// <param name="b">Second operand</param>
401
        /// <param name="result">Result of subtraction</param>
402
        public static void Sub(ref Vector3d a, ref Vector3d b, out Vector3d result)
403
        {
404
            result.X = a.X - b.X;
405
            result.Y = a.Y - b.Y;
406
            result.Z = a.Z - b.Z;
407
        }
408
 
409
        #endregion
410
 
411
        #region Mult
412
 
413
        /// <summary>
414
        /// Multiply a vector and a scalar
415
        /// </summary>
416
        /// <param name="a">Vector operand</param>
417
        /// <param name="f">Scalar operand</param>
418
        /// <returns>Result of the multiplication</returns>
419
        public static Vector3d Mult(Vector3d a, double f)
420
        {
421
            a.X *= f;
422
            a.Y *= f;
423
            a.Z *= f;
424
            return a;
425
        }
426
 
427
        /// <summary>
428
        /// Multiply a vector and a scalar
429
        /// </summary>
430
        /// <param name="a">Vector operand</param>
431
        /// <param name="f">Scalar operand</param>
432
        /// <param name="result">Result of the multiplication</param>
433
        public static void Mult(ref Vector3d a, double f, out Vector3d result)
434
        {
435
            result.X = a.X * f;
436
            result.Y = a.Y * f;
437
            result.Z = a.Z * f;
438
        }
439
 
440
        #endregion
441
 
442
        #region Div
443
 
444
        /// <summary>
445
        /// Divide a vector by a scalar
446
        /// </summary>
447
        /// <param name="a">Vector operand</param>
448
        /// <param name="f">Scalar operand</param>
449
        /// <returns>Result of the division</returns>
450
        public static Vector3d Div(Vector3d a, double f)
451
        {
452
            double mult = 1.0f / f;
453
            a.X *= mult;
454
            a.Y *= mult;
455
            a.Z *= mult;
456
            return a;
457
        }
458
 
459
        /// <summary>
460
        /// Divide a vector by a scalar
461
        /// </summary>
462
        /// <param name="a">Vector operand</param>
463
        /// <param name="f">Scalar operand</param>
464
        /// <param name="result">Result of the division</param>
465
        public static void Div(ref Vector3d a, double f, out Vector3d result)
466
        {
467
            double mult = 1.0f / f;
468
            result.X = a.X * mult;
469
            result.Y = a.Y * mult;
470
            result.Z = a.Z * mult;
471
        }
472
 
473
        #endregion
474
 
475
        #region ComponentMin
476
 
477
        /// <summary>
478
        /// Calculate the component-wise minimum of two vectors
479
        /// </summary>
480
        /// <param name="a">First operand</param>
481
        /// <param name="b">Second operand</param>
482
        /// <returns>The component-wise minimum</returns>
483
        public static Vector3d ComponentMin(Vector3d a, Vector3d b)
484
        {
485
            a.X = a.X < b.X ? a.X : b.X;
486
            a.Y = a.Y < b.Y ? a.Y : b.Y;
487
            a.Z = a.Z < b.Z ? a.Z : b.Z;
488
            return a;
489
        }
490
 
491
        /// <summary>
492
        /// Calculate the component-wise minimum of two vectors
493
        /// </summary>
494
        /// <param name="a">First operand</param>
495
        /// <param name="b">Second operand</param>
496
        /// <param name="result">The component-wise minimum</param>
497
        public static void ComponentMin(ref Vector3d a, ref Vector3d b, out Vector3d result)
498
        {
499
            result.X = a.X < b.X ? a.X : b.X;
500
            result.Y = a.Y < b.Y ? a.Y : b.Y;
501
            result.Z = a.Z < b.Z ? a.Z : b.Z;
502
        }
503
 
504
        #endregion
505
 
506
        #region ComponentMax
507
 
508
        /// <summary>
509
        /// Calculate the component-wise maximum of two vectors
510
        /// </summary>
511
        /// <param name="a">First operand</param>
512
        /// <param name="b">Second operand</param>
513
        /// <returns>The component-wise maximum</returns>
514
        public static Vector3d ComponentMax(Vector3d a, Vector3d b)
515
        {
516
            a.X = a.X > b.X ? a.X : b.X;
517
            a.Y = a.Y > b.Y ? a.Y : b.Y;
518
            a.Z = a.Z > b.Z ? a.Z : b.Z;
519
            return a;
520
        }
521
 
522
        /// <summary>
523
        /// Calculate the component-wise maximum of two vectors
524
        /// </summary>
525
        /// <param name="a">First operand</param>
526
        /// <param name="b">Second operand</param>
527
        /// <param name="result">The component-wise maximum</param>
528
        public static void ComponentMax(ref Vector3d a, ref Vector3d b, out Vector3d result)
529
        {
530
            result.X = a.X > b.X ? a.X : b.X;
531
            result.Y = a.Y > b.Y ? a.Y : b.Y;
532
            result.Z = a.Z > b.Z ? a.Z : b.Z;
533
        }
534
 
535
        #endregion
536
 
537
        #region Min
538
 
539
        /// <summary>
540
        /// Returns the Vector3d with the minimum magnitude
541
        /// </summary>
542
        /// <param name="left">Left operand</param>
543
        /// <param name="right">Right operand</param>
544
        /// <returns>The minimum Vector3</returns>
545
        public static Vector3d Min(Vector3d left, Vector3d right)
546
        {
547
            return left.LengthSquared < right.LengthSquared ? left : right;
548
        }
549
 
550
        #endregion
551
 
552
        #region Max
553
 
554
        /// <summary>
555
        /// Returns the Vector3d with the minimum magnitude
556
        /// </summary>
557
        /// <param name="left">Left operand</param>
558
        /// <param name="right">Right operand</param>
559
        /// <returns>The minimum Vector3</returns>
560
        public static Vector3d Max(Vector3d left, Vector3d right)
561
        {
562
            return left.LengthSquared >= right.LengthSquared ? left : right;
563
        }
564
 
565
        #endregion
566
 
567
        #region Clamp
568
 
569
        /// <summary>
570
        /// Clamp a vector to the given minimum and maximum vectors
571
        /// </summary>
572
        /// <param name="vec">Input vector</param>
573
        /// <param name="min">Minimum vector</param>
574
        /// <param name="max">Maximum vector</param>
575
        /// <returns>The clamped vector</returns>
576
        public static Vector3d Clamp(Vector3d vec, Vector3d min, Vector3d max)
577
        {
578
            vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
579
            vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
580
            vec.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
581
            return vec;
582
        }
583
 
584
        /// <summary>
585
        /// Clamp a vector to the given minimum and maximum vectors
586
        /// </summary>
587
        /// <param name="vec">Input vector</param>
588
        /// <param name="min">Minimum vector</param>
589
        /// <param name="max">Maximum vector</param>
590
        /// <param name="result">The clamped vector</param>
591
        public static void Clamp(ref Vector3d vec, ref Vector3d min, ref Vector3d max, out Vector3d result)
592
        {
593
            result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
594
            result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
595
            result.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
596
        }
597
 
598
        #endregion
599
 
600
        #region Normalize
601
 
602
        /// <summary>
603
        /// Scale a vector to unit length
604
        /// </summary>
605
        /// <param name="vec">The input vector</param>
606
        /// <returns>The normalized vector</returns>
607
        public static Vector3d Normalize(Vector3d vec)
608
        {
609
            double scale = 1.0f / vec.Length;
610
            vec.X *= scale;
611
            vec.Y *= scale;
612
            vec.Z *= scale;
613
            return vec;
614
        }
615
 
616
        /// <summary>
617
        /// Scale a vector to unit length
618
        /// </summary>
619
        /// <param name="vec">The input vector</param>
620
        /// <param name="result">The normalized vector</param>
621
        public static void Normalize(ref Vector3d vec, out Vector3d result)
622
        {
623
            double scale = 1.0f / vec.Length;
624
            result.X = vec.X * scale;
625
            result.Y = vec.Y * scale;
626
            result.Z = vec.Z * scale;
627
        }
628
 
629
        #endregion
630
 
631
        #region NormalizeFast
632
 
633
        /// <summary>
634
        /// Scale a vector to approximately unit length
635
        /// </summary>
636
        /// <param name="vec">The input vector</param>
637
        /// <returns>The normalized vector</returns>
638
        public static Vector3d NormalizeFast(Vector3d vec)
639
        {
640
            double scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z);
641
            vec.X *= scale;
642
            vec.Y *= scale;
643
            vec.Z *= scale;
644
            return vec;
645
        }
646
 
647
        /// <summary>
648
        /// Scale a vector to approximately unit length
649
        /// </summary>
650
        /// <param name="vec">The input vector</param>
651
        /// <param name="result">The normalized vector</param>
652
        public static void NormalizeFast(ref Vector3d vec, out Vector3d result)
653
        {
654
            double scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z);
655
            result.X = vec.X * scale;
656
            result.Y = vec.Y * scale;
657
            result.Z = vec.Z * scale;
658
        }
659
 
660
        #endregion
661
 
662
        #region Dot
663
 
664
        /// <summary>
665
        /// Calculate the dot (scalar) product of two vectors
666
        /// </summary>
667
        /// <param name="left">First operand</param>
668
        /// <param name="right">Second operand</param>
669
        /// <returns>The dot product of the two inputs</returns>
670
        public static double Dot(Vector3d left, Vector3d right)
671
        {
672
            return left.X * right.X + left.Y * right.Y + left.Z * right.Z;
673
        }
674
 
675
        /// <summary>
676
        /// Calculate the dot (scalar) product of two vectors
677
        /// </summary>
678
        /// <param name="left">First operand</param>
679
        /// <param name="right">Second operand</param>
680
        /// <param name="result">The dot product of the two inputs</param>
681
        public static void Dot(ref Vector3d left, ref Vector3d right, out double result)
682
        {
683
            result = left.X * right.X + left.Y * right.Y + left.Z * right.Z;
684
        }
685
 
686
        #endregion
687
 
688
        #region Cross
689
 
690
        /// <summary>
691
        /// Caclulate the cross (vector) product of two vectors
692
        /// </summary>
693
        /// <param name="left">First operand</param>
694
        /// <param name="right">Second operand</param>
695
        /// <returns>The cross product of the two inputs</returns>
696
        public static Vector3d Cross(Vector3d left, Vector3d right)
697
        {
698
            return new Vector3d(left.Y * right.Z - left.Z * right.Y,
699
                                left.Z * right.X - left.X * right.Z,
700
                                left.X * right.Y - left.Y * right.X);
701
        }
702
 
703
        /// <summary>
704
        /// Caclulate the cross (vector) product of two vectors
705
        /// </summary>
706
        /// <param name="left">First operand</param>
707
        /// <param name="right">Second operand</param>
708
        /// <returns>The cross product of the two inputs</returns>
709
        /// <param name="result">The cross product of the two inputs</param>
710
        public static void Cross(ref Vector3d left, ref Vector3d right, out Vector3d result)
711
        {
712
            result.X = left.Y * right.Z - left.Z * right.Y;
713
            result.Y = left.Z * right.X - left.X * right.Z;
714
            result.Z = left.X * right.Y - left.Y * right.X;
715
        }
716
 
717
        #endregion
718
 
719
        #region Lerp
720
 
721
        /// <summary>
722
        /// Returns a new Vector that is the linear blend of the 2 given Vectors
723
        /// </summary>
724
        /// <param name="a">First input vector</param>
725
        /// <param name="b">Second input vector</param>
726
        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
727
        /// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
728
        public static Vector3d Lerp(Vector3d a, Vector3d b, double blend)
729
        {
730
            a.X = blend * (b.X - a.X) + a.X;
731
            a.Y = blend * (b.Y - a.Y) + a.Y;
732
            a.Z = blend * (b.Z - a.Z) + a.Z;
733
            return a;
734
        }
735
 
736
        /// <summary>
737
        /// Returns a new Vector that is the linear blend of the 2 given Vectors
738
        /// </summary>
739
        /// <param name="a">First input vector</param>
740
        /// <param name="b">Second input vector</param>
741
        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
742
        /// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
743
        public static void Lerp(ref Vector3d a, ref Vector3d b, double blend, out Vector3d result)
744
        {
745
            result.X = blend * (b.X - a.X) + a.X;
746
            result.Y = blend * (b.Y - a.Y) + a.Y;
747
            result.Z = blend * (b.Z - a.Z) + a.Z;
748
        }
749
 
750
        #endregion
751
 
752
        #region Barycentric
753
 
754
        /// <summary>
755
        /// Interpolate 3 Vectors using Barycentric coordinates
756
        /// </summary>
757
        /// <param name="a">First input Vector</param>
758
        /// <param name="b">Second input Vector</param>
759
        /// <param name="c">Third input Vector</param>
760
        /// <param name="u">First Barycentric Coordinate</param>
761
        /// <param name="v">Second Barycentric Coordinate</param>
762
        /// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
763
        public static Vector3d BaryCentric(Vector3d a, Vector3d b, Vector3d c, double u, double v)
764
        {
765
            return a + u * (b - a) + v * (c - a);
766
        }
767
 
768
        /// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
769
        /// <param name="a">First input Vector.</param>
770
        /// <param name="b">Second input Vector.</param>
771
        /// <param name="c">Third input Vector.</param>
772
        /// <param name="u">First Barycentric Coordinate.</param>
773
        /// <param name="v">Second Barycentric Coordinate.</param>
774
        /// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
775
        public static void BaryCentric(ref Vector3d a, ref Vector3d b, ref Vector3d c, float u, float v, out Vector3d result)
776
        {
777
            result = a; // copy
778
 
779
            Vector3d temp = b; // copy
780
            temp.Sub(ref a);
781
            temp.Mult(u);
782
            result.Add(ref temp);
783
 
784
            temp = c; // copy
785
            temp.Sub(ref a);
786
            temp.Mult(v);
787
            result.Add(ref temp);
788
        }
789
 
790
        #endregion
791
 
792
        #region Transform
793
 
794
        /// <summary>Transform a direction vector by the given Matrix
795
        /// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
796
        /// </summary>
797
        /// <param name="vec">The vector to transform</param>
798
        /// <param name="mat">The desired transformation</param>
799
        /// <returns>The transformed vector</returns>
800
        public static Vector3d TransformVector(Vector3d vec, Matrix4d mat)
801
        {
802
            return new Vector3d(
803
                Vector3d.Dot(vec, new Vector3d(mat.Column0)),
804
                Vector3d.Dot(vec, new Vector3d(mat.Column1)),
805
                Vector3d.Dot(vec, new Vector3d(mat.Column2)));
806
        }
807
 
808
        /// <summary>Transform a direction vector by the given Matrix
809
        /// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
810
        /// </summary>
811
        /// <param name="vec">The vector to transform</param>
812
        /// <param name="mat">The desired transformation</param>
813
        /// <param name="result">The transformed vector</param>
814
        public static void TransformVector(ref Vector3d vec, ref Matrix4d mat, out Vector3d result)
815
        {
816
            result.X = vec.X * mat.Row0.X +
817
                       vec.Y * mat.Row1.X +
818
                       vec.Z * mat.Row2.X;
819
 
820
            result.Y = vec.X * mat.Row0.Y +
821
                       vec.Y * mat.Row1.Y +
822
                       vec.Z * mat.Row2.Y;
823
 
824
            result.Z = vec.X * mat.Row0.Z +
825
                       vec.Y * mat.Row1.Z +
826
                       vec.Z * mat.Row2.Z;
827
        }
828
 
829
        /// <summary>Transform a Normal by the given Matrix</summary>
830
        /// <remarks>
831
        /// This calculates the inverse of the given matrix, use TransformNormalInverse if you
832
        /// already have the inverse to avoid this extra calculation
833
        /// </remarks>
834
        /// <param name="norm">The normal to transform</param>
835
        /// <param name="mat">The desired transformation</param>
836
        /// <returns>The transformed normal</returns>
837
        public static Vector3d TransformNormal(Vector3d norm, Matrix4d mat)
838
        {
839
            mat.Invert();
840
            return TransformNormalInverse(norm, mat);
841
        }
842
 
843
        /// <summary>Transform a Normal by the given Matrix</summary>
844
        /// <remarks>
845
        /// This calculates the inverse of the given matrix, use TransformNormalInverse if you
846
        /// already have the inverse to avoid this extra calculation
847
        /// </remarks>
848
        /// <param name="norm">The normal to transform</param>
849
        /// <param name="mat">The desired transformation</param>
850
        /// <param name="result">The transformed normal</param>
851
        public static void TransformNormal(ref Vector3d norm, ref Matrix4d mat, out Vector3d result)
852
        {
853
            Matrix4d Inverse = Matrix4d.Invert(mat);
854
            Vector3d.TransformNormalInverse(ref norm, ref Inverse, out result);
855
        }
856
 
857
        /// <summary>Transform a Normal by the (transpose of the) given Matrix</summary>
858
        /// <remarks>
859
        /// This version doesn't calculate the inverse matrix.
860
        /// Use this version if you already have the inverse of the desired transform to hand
861
        /// </remarks>
862
        /// <param name="norm">The normal to transform</param>
863
        /// <param name="invMat">The inverse of the desired transformation</param>
864
        /// <returns>The transformed normal</returns>
865
        public static Vector3d TransformNormalInverse(Vector3d norm, Matrix4d invMat)
866
        {
867
            return new Vector3d(
868
                Vector3d.Dot(norm, new Vector3d(invMat.Row0)),
869
                Vector3d.Dot(norm, new Vector3d(invMat.Row1)),
870
                Vector3d.Dot(norm, new Vector3d(invMat.Row2)));
871
        }
872
 
873
        /// <summary>Transform a Normal by the (transpose of the) given Matrix</summary>
874
        /// <remarks>
875
        /// This version doesn't calculate the inverse matrix.
876
        /// Use this version if you already have the inverse of the desired transform to hand
877
        /// </remarks>
878
        /// <param name="norm">The normal to transform</param>
879
        /// <param name="invMat">The inverse of the desired transformation</param>
880
        /// <param name="result">The transformed normal</param>
881
        public static void TransformNormalInverse(ref Vector3d norm, ref Matrix4d invMat, out Vector3d result)
882
        {
883
            result.X = norm.X * invMat.Row0.X +
884
                       norm.Y * invMat.Row0.Y +
885
                       norm.Z * invMat.Row0.Z;
886
 
887
            result.Y = norm.X * invMat.Row1.X +
888
                       norm.Y * invMat.Row1.Y +
889
                       norm.Z * invMat.Row1.Z;
890
 
891
            result.Z = norm.X * invMat.Row2.X +
892
                       norm.Y * invMat.Row2.Y +
893
                       norm.Z * invMat.Row2.Z;
894
        }
895
 
896
        /// <summary>Transform a Position by the given Matrix</summary>
897
        /// <param name="pos">The position to transform</param>
898
        /// <param name="mat">The desired transformation</param>
899
        /// <returns>The transformed position</returns>
900
        public static Vector3d TransformPosition(Vector3d pos, Matrix4d mat)
901
        {
902
            return new Vector3d(
903
                Vector3d.Dot(pos, new Vector3d(mat.Column0)) + mat.Row3.X,
904
                Vector3d.Dot(pos, new Vector3d(mat.Column1)) + mat.Row3.Y,
905
                Vector3d.Dot(pos, new Vector3d(mat.Column2)) + mat.Row3.Z);
906
        }
907
 
908
        /// <summary>Transform a Position by the given Matrix</summary>
909
        /// <param name="pos">The position to transform</param>
910
        /// <param name="mat">The desired transformation</param>
911
        /// <param name="result">The transformed position</param>
912
        public static void TransformPosition(ref Vector3d pos, ref Matrix4d mat, out Vector3d result)
913
        {
914
            result.X = pos.X * mat.Row0.X +
915
                       pos.Y * mat.Row1.X +
916
                       pos.Z * mat.Row2.X +
917
                       mat.Row3.X;
918
 
919
            result.Y = pos.X * mat.Row0.Y +
920
                       pos.Y * mat.Row1.Y +
921
                       pos.Z * mat.Row2.Y +
922
                       mat.Row3.Y;
923
 
924
            result.Z = pos.X * mat.Row0.Z +
925
                       pos.Y * mat.Row1.Z +
926
                       pos.Z * mat.Row2.Z +
927
                       mat.Row3.Z;
928
        }
929
 
930
        /// <summary>Transform a Vector by the given Matrix</summary>
931
        /// <param name="vec">The vector to transform</param>
932
        /// <param name="mat">The desired transformation</param>
933
        /// <returns>The transformed vector</returns>
934
        public static Vector4d Transform(Vector3d vec, Matrix4d mat)
935
        {
936
            Vector4d v4 = new Vector4d(vec.X, vec.Y, vec.Z, 1.0f);
937
            return new Vector4d(
938
                Vector4d.Dot(v4, mat.Column0),
939
                Vector4d.Dot(v4, mat.Column1),
940
                Vector4d.Dot(v4, mat.Column2),
941
                Vector4d.Dot(v4, mat.Column3));
942
        }
943
 
944
        /// <summary>Transform a Vector by the given Matrix</summary>
945
        /// <param name="vec">The vector to transform</param>
946
        /// <param name="mat">The desired transformation</param>
947
        /// <param name="result">The transformed vector</param>
948
        public static void Transform(ref Vector3d vec, ref Matrix4d mat, out Vector4d result)
949
        {
950
            Vector4d v4 = new Vector4d(vec.X, vec.Y, vec.Z, 1.0f);
951
            Vector4d.Transform(ref v4, ref mat, out result);
952
        }
953
 
954
        /// <summary>
955
        /// Transform a Vector3d by the given Matrix, and project the resulting Vector4 back to a Vector3
956
        /// </summary>
957
        /// <param name="vec">The vector to transform</param>
958
        /// <param name="mat">The desired transformation</param>
959
        /// <returns>The transformed vector</returns>
960
        public static Vector3d TransformPerspective(Vector3d vec, Matrix4d mat)
961
        {
962
            Vector4d h = Transform(vec, mat);
963
            return new Vector3d(h.X / h.W, h.Y / h.W, h.Z / h.W);
964
        }
965
 
966
        /// <summary>Transform a Vector3d by the given Matrix, and project the resulting Vector4d back to a Vector3d</summary>
967
        /// <param name="vec">The vector to transform</param>
968
        /// <param name="mat">The desired transformation</param>
969
        /// <param name="result">The transformed vector</param>
970
        public static void TransformPerspective(ref Vector3d vec, ref Matrix4d mat, out Vector3d result)
971
        {
972
            Vector4d h;
973
            Vector3d.Transform(ref vec, ref mat, out h);
974
            result.X = h.X / h.W;
975
            result.Y = h.Y / h.W;
976
            result.Z = h.Z / h.W;
977
        }
978
 
979
        #endregion
980
 
981
        #region CalculateAngle
982
 
983
        /// <summary>
984
        /// Calculates the angle (in radians) between two vectors.
985
        /// </summary>
986
        /// <param name="first">The first vector.</param>
987
        /// <param name="second">The second vector.</param>
988
        /// <returns>Angle (in radians) between the vectors.</returns>
989
        /// <remarks>Note that the returned angle is never bigger than the constant Pi.</remarks>
990
        public static double CalculateAngle(Vector3d first, Vector3d second)
991
        {
992
            return System.Math.Acos((Vector3d.Dot(first, second)) / (first.Length * second.Length));
993
        }
994
 
995
        /// <summary>Calculates the angle (in radians) between two vectors.</summary>
996
        /// <param name="first">The first vector.</param>
997
        /// <param name="second">The second vector.</param>
998
        /// <param name="result">Angle (in radians) between the vectors.</param>
999
        /// <remarks>Note that the returned angle is never bigger than the constant Pi.</remarks>
1000
        public static void CalculateAngle(ref Vector3d first, ref Vector3d second, out double result)
1001
        {
1002
            double temp;
1003
            Vector3d.Dot(ref first, ref second, out temp);
1004
            result = System.Math.Acos(temp / (first.Length * second.Length));
1005
        }
1006
 
1007
        #endregion
1008
 
1009
        #endregion
1010
 
1011
        #region Swizzle
1012
 
1013
        /// <summary>
1014
        /// Gets or sets an OpenTK.Vector2d with the X and Y components of this instance.
1015
        /// </summary>
1016
        [XmlIgnore]
1017
        public Vector2d Xy { get { return new Vector2d(X, Y); } set { X = value.X; Y = value.Y; } }
1018
 
1019
        #endregion
1020
 
1021
        #region Operators
1022
 
1023
        public static Vector3d operator +(Vector3d left, Vector3d right)
1024
        {
1025
            left.X += right.X;
1026
            left.Y += right.Y;
1027
            left.Z += right.Z;
1028
            return left;
1029
        }
1030
 
1031
        public static Vector3d operator -(Vector3d left, Vector3d right)
1032
        {
1033
            left.X -= right.X;
1034
            left.Y -= right.Y;
1035
            left.Z -= right.Z;
1036
            return left;
1037
        }
1038
 
1039
        public static Vector3d operator -(Vector3d vec)
1040
        {
1041
            vec.X = -vec.X;
1042
            vec.Y = -vec.Y;
1043
            vec.Z = -vec.Z;
1044
            return vec;
1045
        }
1046
 
1047
        public static Vector3d operator *(Vector3d vec, double f)
1048
        {
1049
            vec.X *= f;
1050
            vec.Y *= f;
1051
            vec.Z *= f;
1052
            return vec;
1053
        }
1054
 
1055
        public static Vector3d operator *(double f, Vector3d vec)
1056
        {
1057
            vec.X *= f;
1058
            vec.Y *= f;
1059
            vec.Z *= f;
1060
            return vec;
1061
        }
1062
 
1063
        public static Vector3d operator /(Vector3d vec, double f)
1064
        {
1065
            double mult = 1.0f / f;
1066
            vec.X *= mult;
1067
            vec.Y *= mult;
1068
            vec.Z *= mult;
1069
            return vec;
1070
        }
1071
 
1072
        public static bool operator ==(Vector3d left, Vector3d right)
1073
        {
1074
            return left.Equals(right);
1075
        }
1076
 
1077
        public static bool operator !=(Vector3d left, Vector3d right)
1078
        {
1079
            return !left.Equals(right);
1080
        }
1081
 
1082
        /// <summary>Converts OpenTK.Vector3 to OpenTK.Vector3d.</summary>
1083
        /// <param name="v3">The Vector3 to convert.</param>
1084
        /// <returns>The resulting Vector3d.</returns>
1085
        public static explicit operator Vector3d(Vector3 v3)
1086
        {
1087
            return new Vector3d(v3.X, v3.Y, v3.Z);
1088
        }
1089
 
1090
        /// <summary>Converts OpenTK.Vector3d to OpenTK.Vector3.</summary>
1091
        /// <param name="v3d">The Vector3d to convert.</param>
1092
        /// <returns>The resulting Vector3.</returns>
1093
        public static explicit operator Vector3(Vector3d v3d)
1094
        {
1095
            return new Vector3((float)v3d.X, (float)v3d.Y, (float)v3d.Z);
1096
        }
1097
 
1098
        #endregion
1099
 
1100
        #region Overrides
1101
 
1102
        #region public override string ToString()
1103
 
1104
        /// <summary>
1105
        /// Returns a System.String that represents the current Vector3.
1106
        /// </summary>
1107
        /// <returns></returns>
1108
        public override string ToString()
1109
        {
1110
            return String.Format("({0}, {1}, {2})", X, Y, Z);
1111
        }
1112
 
1113
        #endregion
1114
 
1115
        #region public override int GetHashCode()
1116
 
1117
        /// <summary>
1118
        /// Returns the hashcode for this instance.
1119
        /// </summary>
1120
        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
1121
        public override int GetHashCode()
1122
        {
1123
            return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
1124
        }
1125
 
1126
        #endregion
1127
 
1128
        #region public override bool Equals(object obj)
1129
 
1130
        /// <summary>
1131
        /// Indicates whether this instance and a specified object are equal.
1132
        /// </summary>
1133
        /// <param name="obj">The object to compare to.</param>
1134
        /// <returns>True if the instances are equal; false otherwise.</returns>
1135
        public override bool Equals(object obj)
1136
        {
1137
            if (!(obj is Vector3))
1138
                return false;
1139
 
1140
            return this.Equals((Vector3)obj);
1141
        }
1142
 
1143
        #endregion
1144
 
1145
        #endregion
1146
 
1147
        #endregion
1148
 
1149
        #region IEquatable<Vector3> Members
1150
 
1151
        /// <summary>Indicates whether the current vector is equal to another vector.</summary>
1152
        /// <param name="other">A vector to compare with this vector.</param>
1153
        /// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
1154
        public bool Equals(Vector3d other)
1155
        {
1156
            return
1157
                X == other.X &&
1158
                Y == other.Y &&
1159
                Z == other.Z;
1160
        }
1161
 
1162
        #endregion
1163
    }
1164
}