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