source: 2014/24/EemeliK/Zombieland/Jypeli/AdvanceMath/Vector4D.cs @ 5974

Revision 5974, 45.9 KB checked in by empaheik, 4 years ago (diff)
Line 
1#region MIT License
2/*
3 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#endregion
23
24
25#if UseDouble
26using Scalar = System.Double;
27#else
28using Scalar = System.Single;
29#endif
30using System;
31using System.Runtime.InteropServices;
32using AdvanceMath.Design;
33using System.Xml.Serialization;
34namespace AdvanceMath
35{
36    /// <summary>
37    /// A Vector with 4 dimensions.
38    /// </summary>
39    /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29"/></remarks>
40    //[StructLayout(LayoutKind.Sequential), Serializable]
41    [StructLayout(LayoutKind.Sequential, Size = Vector4D.Size)]
42    [AdvBrowsableOrder("X,Y,Z,W")]
43#if !CompactFramework && !WindowsCE && !PocketPC && !XBOX360 && !SILVERLIGHT && !WINDOWS_PHONE
44    [Serializable]
45    [System.ComponentModel.TypeConverter(typeof(AdvTypeConverter<Vector4D>))]
46#endif
47    public struct Vector4D : IVector<Vector4D>
48    {
49        #region const fields
50        /// <summary>
51        /// The number of Scalar values in the class.
52        /// </summary>
53        public const int Count = 4;
54        /// <summary>
55        /// The Size of the class in bytes;
56        /// </summary>
57        public const int Size = sizeof(Scalar) * Count;
58        #endregion
59        #region readonly fields
60        /// <summary>
61        /// Vector4D(1,1,1,1)
62        /// </summary>
63        public static readonly Vector4D One = new Vector4D(1, 1, 1, 1);
64        /// <summary>
65        /// Vector4D(0,0,0,0)
66        /// </summary>
67        public static readonly Vector4D Zero = new Vector4D();
68        /// <summary>
69        /// Vector4D(1,0,0,0)
70        /// </summary>
71        public static readonly Vector4D XAxis = new Vector4D(1, 0, 0, 0);
72        /// <summary>
73        /// Vector4D(0,1,0,0)
74        /// </summary>
75        public static readonly Vector4D YAxis = new Vector4D(0, 1, 0, 0);
76        /// <summary>
77        /// Vector4D(0,0,1,0)
78        /// </summary>
79        public static readonly Vector4D ZAxis = new Vector4D(0, 0, 1, 0);
80        /// <summary>
81        /// Vector4D(0,0,0,1)
82        /// </summary>
83        public static readonly Vector4D WAxis = new Vector4D(0, 0, 0, 1);
84
85        private static readonly string FormatString = MatrixHelper.CreateVectorFormatString(Count);
86        private readonly static string FormatableString = MatrixHelper.CreateVectorFormatableString(Count);
87
88        #endregion
89        #region static methods
90        public static void Copy(ref Vector4D vector, Scalar[] destArray)
91        {
92            Copy(ref vector, destArray, 0);
93        }
94        public static void Copy(ref Vector4D vector, Scalar[] destArray, int index)
95        {
96            ThrowHelper.CheckCopy(destArray, index, Count);
97
98            destArray[index] = vector.X;
99            destArray[++index] = vector.Y;
100            destArray[++index] = vector.Z;
101            destArray[++index] = vector.W;
102        }
103        public static void Copy(Scalar[] sourceArray, out Vector4D result)
104        {
105            Copy(sourceArray, 0, out result);
106        }
107        public static void Copy(Scalar[] sourceArray, int index, out Vector4D result)
108        {
109            ThrowHelper.CheckCopy(sourceArray, index, Count);
110
111            result.X = sourceArray[index];
112            result.Y = sourceArray[++index];
113            result.Z = sourceArray[++index];
114            result.W = sourceArray[++index];
115        }
116        public static void Copy(ref Vector3D source, ref Vector4D dest)
117        {
118            dest.X = source.X;
119            dest.Y = source.Y;
120            dest.Z = source.Z;
121        }
122        public static void Copy(ref Vector2D source, ref Vector4D dest)
123        {
124            dest.X = source.X;
125            dest.Y = source.Y;
126        }
127
128        public static Vector4D Clamp(Vector4D value, Vector4D min, Vector4D max)
129        {
130            Vector4D result;
131            MathHelper.Clamp(ref value.X, ref  min.X, ref  max.X, out result.X);
132            MathHelper.Clamp(ref value.Y, ref  min.Y, ref  max.Y, out result.Y);
133            MathHelper.Clamp(ref value.Z, ref  min.Z, ref  max.Z, out result.Z);
134            MathHelper.Clamp(ref value.W, ref  min.W, ref  max.W, out result.W);
135            return result;
136        }
137        public static void Clamp(ref Vector4D value, ref Vector4D min, ref Vector4D max, out Vector4D result)
138        {
139            MathHelper.Clamp(ref value.X, ref  min.X, ref  max.X, out result.X);
140            MathHelper.Clamp(ref value.Y, ref  min.Y, ref  max.Y, out result.Y);
141            MathHelper.Clamp(ref value.Z, ref  min.Z, ref  max.Z, out result.Z);
142            MathHelper.Clamp(ref value.W, ref  min.W, ref  max.W, out result.W);
143        }
144
145
146        public static Vector4D Lerp(Vector4D left, Vector4D right, Scalar amount)
147        {
148            Vector4D result;
149            Lerp(ref left, ref right, ref amount, out result);
150            return result;
151        }
152        public static void Lerp(ref Vector4D left, ref Vector4D right, ref Scalar amount, out Vector4D result)
153        {
154            result.X = (right.X - left.X) * amount + left.X;
155            result.Y = (right.Y - left.Y) * amount + left.Y;
156            result.Z = (right.Z - left.Z) * amount + left.Z;
157            result.W = (right.W - left.W) * amount + left.W;
158        }
159        public static Vector4D Lerp(Vector4D left, Vector4D right, Vector4D amount)
160        {
161            Vector4D result;
162            Lerp(ref left, ref right, ref amount, out result);
163            return result;
164        }
165        public static void Lerp(ref Vector4D left, ref Vector4D right, ref Vector4D amount, out Vector4D result)
166        {
167            result.X = (right.X - left.X) * amount.X + left.X;
168            result.Y = (right.Y - left.Y) * amount.Y + left.Y;
169            result.Z = (right.Z - left.Z) * amount.Z + left.Z;
170            result.W = (right.W - left.W) * amount.W + left.W;
171        }
172
173        public static Scalar Distance(Vector4D left, Vector4D right)
174        {
175            Scalar result;
176            Distance(ref left, ref right, out result);
177            return result;
178        }
179        public static void Distance(ref Vector4D left, ref Vector4D right, out Scalar result)
180        {
181            Vector4D diff;
182            Subtract(ref left, ref right, out diff);
183            GetMagnitude(ref diff, out result);
184        }
185        public static Scalar DistanceSq(Vector4D left, Vector4D right)
186        {
187            Scalar result;
188            DistanceSq(ref left, ref right, out result);
189            return result;
190        }
191        public static void DistanceSq(ref Vector4D left, ref Vector4D right, out Scalar result)
192        {
193            Vector4D diff;
194            Subtract(ref left, ref right, out diff);
195            GetMagnitudeSq(ref diff, out result);
196        }
197
198        /// <summary>
199        /// Adds 2 Vectors2Ds.
200        /// </summary>
201        /// <param name="left">The left Vector4D operand.</param>
202        /// <param name="right">The right Vector4D operand.</param>
203        /// <returns>The Sum of the 2 Vector4Ds.</returns>
204        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
205        public static Vector4D Add(Vector4D left, Vector4D right)
206        {
207            Vector4D result;
208            result.X = left.X + right.X;
209            result.Y = left.Y + right.Y;
210            result.Z = left.Z + right.Z;
211            result.W = left.W + right.W;
212            return result;
213        }
214        public static void Add(ref Vector4D left, ref Vector4D right, out Vector4D result)
215        {
216            result.X = left.X + right.X;
217            result.Y = left.Y + right.Y;
218            result.Z = left.Z + right.Z;
219            result.W = left.W + right.W;
220        }
221
222        public static Vector4D Add(Vector3D left, Vector4D right)
223        {
224            Vector4D result;
225            Add(ref left, ref right, out result);
226            return result;
227        }
228        public static void Add(ref Vector3D left, ref Vector4D right, out Vector4D result)
229        {
230            result.X = left.X + right.X;
231            result.Y = left.Y + right.Y;
232            result.Z = left.Z + right.Z;
233            result.W = right.W;
234        }
235        public static Vector4D Add(Vector2D left, Vector4D right)
236        {
237            Vector4D result;
238            Add(ref left, ref right, out result);
239            return result;
240        }
241        public static void Add(ref Vector2D left, ref Vector4D right, out Vector4D result)
242        {
243            result.X = left.X + right.X;
244            result.Y = left.Y + right.Y;
245            result.Z = right.Z;
246            result.W = right.W;
247        }
248        public static Vector4D Add(Vector4D left, Vector3D right)
249        {
250            Vector4D result;
251            Add(ref left, ref right, out result);
252            return result;
253        }
254        public static void Add(ref Vector4D left, ref Vector3D right, out Vector4D result)
255        {
256            result.X = left.X + right.X;
257            result.Y = left.Y + right.Y;
258            result.Z = left.Z + right.Z;
259            result.W = left.W;
260        }
261        public static Vector4D Add(Vector4D left, Vector2D right)
262        {
263            Vector4D result;
264            Add(ref left, ref right, out result);
265            return result;
266        }
267        public static void Add(ref Vector4D left, ref Vector2D right, out Vector4D result)
268        {
269            result.X = left.X + right.X;
270            result.Y = left.Y + right.Y;
271            result.Z = left.Z;
272            result.W = left.W;
273        }
274
275
276
277        /// <summary>
278        /// Subtracts 2 Vector4Ds.
279        /// </summary>
280        /// <param name="left">The left Vector4D operand.</param>
281        /// <param name="right">The right Vector4D operand.</param>
282        /// <returns>The Difference of the 2 Vector4Ds.</returns>
283        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
284        public static Vector4D Subtract(Vector4D left, Vector4D right)
285        {
286            Vector4D result;
287            result.X = left.X - right.X;
288            result.Y = left.Y - right.Y;
289            result.Z = left.Z - right.Z;
290            result.W = left.W - right.W;
291            return result;
292        }
293        public static void Subtract(ref Vector4D left, ref  Vector4D right, out Vector4D result)
294        {
295            result.X = left.X - right.X;
296            result.Y = left.Y - right.Y;
297            result.Z = left.Z - right.Z;
298            result.W = left.W - right.W;
299        }
300
301
302        public static Vector4D Subtract(Vector3D left, Vector4D right)
303        {
304            Vector4D result;
305            Subtract(ref left, ref right, out result);
306            return result;
307        }
308        public static void Subtract(ref Vector3D left, ref Vector4D right, out Vector4D result)
309        {
310            result.X = left.X - right.X;
311            result.Y = left.Y - right.Y;
312            result.Z = left.Z - right.Z;
313            result.W = -right.W;
314        }
315        public static Vector4D Subtract(Vector2D left, Vector4D right)
316        {
317            Vector4D result;
318            Subtract(ref left, ref right, out result);
319            return result;
320        }
321        public static void Subtract(ref Vector2D left, ref Vector4D right, out Vector4D result)
322        {
323            result.X = left.X - right.X;
324            result.Y = left.Y - right.Y;
325            result.Z = -right.Z;
326            result.W = -right.W;
327        }
328        public static Vector4D Subtract(Vector4D left, Vector3D right)
329        {
330            Vector4D result;
331            Subtract(ref left, ref right, out result);
332            return result;
333        }
334        public static void Subtract(ref Vector4D left, ref Vector3D right, out Vector4D result)
335        {
336            result.X = left.X - right.X;
337            result.Y = left.Y - right.Y;
338            result.Z = left.Z - right.Z;
339            result.W = left.W;
340        }
341        public static Vector4D Subtract(Vector4D left, Vector2D right)
342        {
343            Vector4D result;
344            Subtract(ref left, ref right, out result);
345            return result;
346        }
347        public static void Subtract(ref Vector4D left, ref Vector2D right, out Vector4D result)
348        {
349            result.X = left.X - right.X;
350            result.Y = left.Y - right.Y;
351            result.Z = left.Z;
352            result.W = left.W;
353        }
354
355
356        /// <summary>
357        /// Does Scaler Multiplication on a Vector4D.
358        /// </summary>
359        /// <param name="source">The Vector4D to be multiplied.</param>
360        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
361        /// <returns>The Product of the Scaler Multiplication.</returns>
362        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
363        public static Vector4D Multiply(Vector4D source, Scalar scalar)
364        {
365            Vector4D result;
366            result.X = source.X * scalar;
367            result.Y = source.Y * scalar;
368            result.Z = source.Z * scalar;
369            result.W = source.W * scalar;
370            return result;
371        }
372        public static void Multiply(ref Vector4D source, ref Scalar scalar, out Vector4D result)
373        {
374            result.X = source.X * scalar;
375            result.Y = source.Y * scalar;
376            result.Z = source.Z * scalar;
377            result.W = source.W * scalar;
378        }
379        /// <summary>
380        /// Does Scaler Multiplication on a Vector4D.
381        /// </summary>
382        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
383        /// <param name="source">The Vector4D to be multiplied.</param>
384        /// <returns>The Product of the Scaler Multiplication.</returns>
385        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
386        public static Vector4D Multiply(Scalar scalar, Vector4D source)
387        {
388            Vector4D result;
389            result.X = scalar * source.X;
390            result.Y = scalar * source.Y;
391            result.Z = scalar * source.Z;
392            result.W = scalar * source.W;
393            return result;
394        }
395        public static void Multiply(ref Scalar scalar, ref Vector4D source, out Vector4D result)
396        {
397            result.X = scalar * source.X;
398            result.Y = scalar * source.Y;
399            result.Z = scalar * source.Z;
400            result.W = scalar * source.W;
401        }
402
403        public static Vector4D Transform(Matrix4x4 matrix, Vector4D vector)
404        {
405            Vector4D result;
406
407            result.X = vector.X * matrix.m00 + vector.Y * matrix.m01 + vector.Z * matrix.m02 + vector.W * matrix.m03;
408            result.Y = vector.X * matrix.m10 + vector.Y * matrix.m11 + vector.Z * matrix.m12 + vector.W * matrix.m13;
409            result.Z = vector.X * matrix.m20 + vector.Y * matrix.m21 + vector.Z * matrix.m22 + vector.W * matrix.m23;
410            result.W = vector.X * matrix.m30 + vector.Y * matrix.m31 + vector.Z * matrix.m32 + vector.W * matrix.m33;
411
412            return result;
413        }
414        public static void Transform(ref Matrix4x4 matrix, ref Vector4D vector, out Vector4D result)
415        {
416            Scalar X = vector.X;
417            Scalar Y = vector.Y;
418            Scalar Z = vector.Z;
419            result.X = X * matrix.m00 + Y * matrix.m01 + Z * matrix.m02 + vector.W * matrix.m03;
420            result.Y = X * matrix.m10 + Y * matrix.m11 + Z * matrix.m12 + vector.W * matrix.m13;
421            result.Z = X * matrix.m20 + Y * matrix.m21 + Z * matrix.m22 + vector.W * matrix.m23;
422            result.W = X * matrix.m30 + Y * matrix.m31 + Z * matrix.m32 + vector.W * matrix.m33;
423        }
424
425        public static Vector4D Transform(Vector4D vector, Matrix4x4 matrix)
426        {
427            Vector4D result;
428
429            result.X = vector.X * matrix.m00 + vector.Y * matrix.m10 + vector.Z * matrix.m20 + vector.W * matrix.m30;
430            result.Y = vector.X * matrix.m01 + vector.Y * matrix.m11 + vector.Z * matrix.m21 + vector.W * matrix.m31;
431            result.Z = vector.X * matrix.m02 + vector.Y * matrix.m12 + vector.Z * matrix.m22 + vector.W * matrix.m32;
432            result.W = vector.X * matrix.m03 + vector.Y * matrix.m13 + vector.Z * matrix.m23 + vector.W * matrix.m33;
433
434            return result;
435        }
436        public static void Transform(ref Vector4D vector, ref Matrix4x4 matrix, out Vector4D result)
437        {
438            Scalar X = vector.X;
439            Scalar Y = vector.Y;
440            Scalar Z = vector.Z;
441            result.X = X * matrix.m00 + Y * matrix.m10 + Z * matrix.m20 + vector.W * matrix.m30;
442            result.Y = X * matrix.m01 + Y * matrix.m11 + Z * matrix.m21 + vector.W * matrix.m31;
443            result.Z = X * matrix.m02 + Y * matrix.m12 + Z * matrix.m22 + vector.W * matrix.m32;
444            result.W = X * matrix.m03 + Y * matrix.m13 + Z * matrix.m23 + vector.W * matrix.m33;
445        }
446
447        /// <summary>
448        /// Does a Dot Operation Also know as an Inner Product.
449        /// </summary>
450        /// <param name="left">The left Vector4D operand.</param>
451        /// <param name="right">The right Vector4D operand.</param>
452        /// <returns>The Dot Product (Inner Product).</returns>
453        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Dot_product"/></remarks>
454        public static Scalar Dot(Vector4D left, Vector4D right)
455        {
456            return left.Y * right.Y + left.X * right.X + left.Z * right.Z + left.W * right.W;
457        }
458        public static void Dot(ref Vector4D left, ref Vector4D right, out Scalar result)
459        {
460            result = left.Y * right.Y + left.X * right.X + left.Z * right.Z + left.W * right.W;
461        }
462        /// <summary>
463        /// Gets the Squared <see cref="Magnitude"/> of the Vector4D that is passed.
464        /// </summary>
465        /// <param name="source">The Vector4D whos Squared Magnitude is te be returned.</param>
466        /// <returns>The Squared Magnitude.</returns>
467        public static Scalar GetMagnitudeSq(Vector4D source)
468        {
469            return source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W;
470        }
471        public static void GetMagnitudeSq(ref Vector4D source, out Scalar result)
472        {
473            result = source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W;
474        }
475        /// <summary>
476        /// Gets the <see cref="Magnitude"/> of the Vector4D that is passed.
477        /// </summary>
478        /// <param name="source">The Vector4D whos Magnitude is te be returned.</param>
479        /// <returns>The Magnitude.</returns>
480        public static Scalar GetMagnitude(Vector4D source)
481        {
482            return MathHelper.Sqrt(source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W);
483        }
484        public static void GetMagnitude(ref Vector4D source, out Scalar result)
485        {
486            result = MathHelper.Sqrt(source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W);
487        }
488        /// <summary>
489        /// Sets the <see cref="Magnitude"/> of a Vector4D.
490        /// </summary>
491        /// <param name="source">The Vector4D whose Magnitude is to be changed.</param>
492        /// <param name="magnitude">The Magnitude.</param>
493        /// <returns>A Vector4D with the new Magnitude</returns>
494        public static Vector4D SetMagnitude(Vector4D source, Scalar magnitude)
495        {
496            Vector4D result;
497            SetMagnitude(ref source, ref magnitude, out result);
498            return result;
499        }
500        public static void SetMagnitude(ref Vector4D source, ref Scalar magnitude, out Vector4D result)
501        {
502            Scalar oldmagnitude;
503            GetMagnitude(ref source, out oldmagnitude);
504            if (oldmagnitude > 0 && magnitude != 0)
505            {
506                oldmagnitude = (magnitude / oldmagnitude);
507                Multiply(ref source, ref oldmagnitude, out result);
508            }
509            else
510            {
511                result = Zero;
512            }
513        }
514        /// <summary>
515        /// Negates a Vector4D.
516        /// </summary>
517        /// <param name="source">The Vector4D to be Negated.</param>
518        /// <returns>The Negated Vector4D.</returns>
519        public static Vector4D Negate(Vector4D source)
520        {
521            Vector4D result;
522            result.X = -source.X;
523            result.Y = -source.Y;
524            result.Z = -source.Z;
525            result.W = -source.W;
526            return result;
527        }
528        [CLSCompliant(false)]
529        public static void Negate(ref Vector4D source)
530        {
531            Negate(ref source, out source);
532        }
533        public static void Negate(ref Vector4D source, out Vector4D result)
534        {
535            result.X = -source.X;
536            result.Y = -source.Y;
537            result.Z = -source.Z;
538            result.W = -source.W;
539        }
540        /// <summary>
541        /// This returns the Normalized Vector4D that is passed. This is also known as a Unit Vector.
542        /// </summary>
543        /// <param name="source">The Vector4D to be Normalized.</param>
544        /// <returns>The Normalized Vector4D. (Unit Vector)</returns>
545        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
546        public static Vector4D Normalize(Vector4D source)
547        {
548            Scalar oldmagnitude;
549            GetMagnitude(ref source, out oldmagnitude);
550            if (oldmagnitude == 0) { return Zero; }
551            oldmagnitude = (1 / oldmagnitude);
552            Vector4D result;
553            result.X = source.X * oldmagnitude;
554            result.Y = source.Y * oldmagnitude;
555            result.Z = source.Z * oldmagnitude;
556            result.W = source.W * oldmagnitude;
557            return result;
558        }
559        public static void Normalize(ref Vector4D source, out Vector4D result)
560        {
561            Scalar oldmagnitude;
562            GetMagnitude(ref source, out oldmagnitude);
563            if (oldmagnitude == 0) { result = Zero; return; }
564            oldmagnitude = (1 / oldmagnitude);
565            result.X = source.X * oldmagnitude;
566            result.Y = source.Y * oldmagnitude;
567            result.Z = source.Z * oldmagnitude;
568            result.W = source.W * oldmagnitude;
569        }
570        [CLSCompliant(false)]
571        public static void Normalize(ref Vector4D source)
572        {
573            Normalize(ref source, out source);
574        }
575        /// <summary>
576        /// Thie Projects the left Vector4D onto the Right Vector4D.
577        /// </summary>
578        /// <param name="left">The left Vector4D operand.</param>
579        /// <param name="right">The right Vector4D operand.</param>
580        /// <returns>The Projected Vector4D.</returns>
581        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Projection_%28linear_algebra%29"/></remarks>
582        public static Vector4D Project(Vector4D left, Vector4D right)
583        {
584            Vector4D result;
585            Project(ref left, ref right, out result);
586            return result;
587        }
588        public static void Project(ref Vector4D left, ref Vector4D right, out Vector4D result)
589        {
590            Scalar tmp, magsq;
591            Dot(ref left, ref  right, out tmp);
592            GetMagnitudeSq(ref right, out magsq);
593            tmp /= magsq;
594            Multiply(ref right, ref tmp, out result);
595        }
596
597
598
599        public static Vector4D TripleCross(Vector4D top, Vector4D middle, Vector4D bottom)
600        {
601            Vector4D result;
602
603            result.X = Matrix3x3.GetDeterminant(
604                top.Y, top.Z, top.W,
605                 middle.Y, middle.Z, middle.W,
606                 bottom.Y, bottom.Z, bottom.W);
607
608            result.Y = -Matrix3x3.GetDeterminant(
609                top.X, top.Z, top.W,
610                middle.X, middle.Z, middle.W,
611                bottom.X, bottom.Z, bottom.W);
612
613            result.Z = Matrix3x3.GetDeterminant(
614                top.X, top.Y, top.W,
615                middle.X, middle.Y, middle.W,
616                bottom.X, bottom.Y, bottom.W);
617
618            result.W = -Matrix3x3.GetDeterminant(
619                top.X, top.Y, top.Z,
620                middle.X, middle.Y, middle.Z,
621                bottom.X, bottom.Y, bottom.Z);
622
623            return result;
624        }
625
626        public static Vector4D CatmullRom( Vector4D value1,  Vector4D value2,  Vector4D value3,  Vector4D value4, Scalar amount)
627        {
628            Vector4D result;
629            CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result);
630            return result;
631        }
632        public static void CatmullRom(ref Vector4D value1, ref Vector4D value2, ref Vector4D value3, ref Vector4D value4, Scalar amount, out Vector4D result)
633        {
634            Scalar amountSq = amount * amount;
635            Scalar amountCu = amountSq * amount;
636            result.X =
637                0.5f * ((2 * value2.X) +
638                (-value1.X + value3.X) * amount +
639                (2 * value1.X - 5 * value2.X + 4 * value3.X - value4.X) * amountSq +
640                (-value1.X + 3 * value2.X - 3 * value3.X + value4.X) * amountCu);
641            result.Y =
642                0.5f * ((2 * value2.Y) +
643                (-value1.Y + value3.Y) * amount +
644                (2 * value1.Y - 5 * value2.Y + 4 * value3.Y - value4.Y) * amountSq +
645                (-value1.Y + 3 * value2.Y - 3 * value3.Y + value4.Y) * amountCu);
646            result.Z =
647                0.5f * ((2 * value2.Z) +
648                (-value1.Z + value3.Z) * amount +
649                (2 * value1.Z - 5 * value2.Z + 4 * value3.Z - value4.Z) * amountSq +
650                (-value1.Z + 3 * value2.Z - 3 * value3.Z + value4.Z) * amountCu);
651            result.W =
652                0.5f * ((2 * value2.W) +
653                (-value1.W + value3.W) * amount +
654                (2 * value1.W - 5 * value2.W + 4 * value3.W - value4.W) * amountSq +
655                (-value1.W + 3 * value2.W - 3 * value3.W + value4.W) * amountCu);
656        }
657
658        public static Vector4D Max(Vector4D value1, Vector4D value2)
659        {
660            Vector4D result;
661            Max(ref value1, ref value2, out result);
662            return result;
663        }
664        public static void Max(ref Vector4D value1,ref Vector4D value2,out Vector4D result)
665        {
666            result.X = (value1.X < value2.X) ? (value2.X) : (value1.X);
667            result.Y = (value1.Y < value2.Y) ? (value2.Y) : (value1.Y);
668            result.Z = (value1.Z < value2.Z) ? (value2.Z) : (value1.Z);
669            result.W = (value1.W < value2.W) ? (value2.W) : (value1.W);
670        }
671
672        public static Vector4D Min(Vector4D value1, Vector4D value2)
673        {
674            Vector4D result;
675            Min(ref value1, ref value2, out result);
676            return result;
677        }
678        public static void Min(ref Vector4D value1, ref Vector4D value2, out Vector4D result)
679        {
680            result.X = (value1.X > value2.X) ? (value2.X) : (value1.X);
681            result.Y = (value1.Y > value2.Y) ? (value2.Y) : (value1.Y);
682            result.Z = (value1.Z > value2.Z) ? (value2.Z) : (value1.Z);
683            result.W = (value1.W > value2.W) ? (value2.W) : (value1.W);
684        }
685
686        public static Vector4D Hermite(Vector4D value1, Vector4D tangent1, Vector4D value2, Vector4D tangent2, Scalar amount)
687        {
688            Vector4D result;
689            Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result);
690            return result;
691        }
692        public static void Hermite(ref  Vector4D value1, ref Vector4D tangent1, ref Vector4D value2, ref Vector4D tangent2, Scalar amount, out Vector4D result)
693        {
694            Scalar h1, h2, h3, h4;
695            MathHelper.HermiteHelper(amount, out h1, out h2, out h3, out h4);
696            result.X = h1 * value1.X + h2 * value2.X + h3 * tangent1.X + h4 * tangent2.X;
697            result.Y = h1 * value1.Y + h2 * value2.Y + h3 * tangent1.Y + h4 * tangent2.Y;
698            result.Z = h1 * value1.Z + h2 * value2.Z + h3 * tangent1.Z + h4 * tangent2.Z;
699            result.W = h1 * value1.W + h2 * value2.W + h3 * tangent1.W + h4 * tangent2.W;
700        }
701
702        #endregion
703        #region fields
704        /// <summary>
705        /// This is the X value.
706        /// </summary>
707        [AdvBrowsable]
708        [XmlAttribute]
709        [System.ComponentModel.Description("The Magnitude on the X-Axis")]
710        public Scalar X;
711        /// <summary>
712        /// This is the Y value.
713        /// </summary>
714        [AdvBrowsable]
715        [XmlAttribute]
716        [System.ComponentModel.Description("The Magnitude on the Y-Axis")]
717        public Scalar Y;
718        /// <summary>
719        /// This is the Z value.
720        /// </summary>
721        [AdvBrowsable]
722        [XmlAttribute]
723        [System.ComponentModel.Description("The Magnitude on the Z-Axis")]
724        public Scalar Z;
725        /// <summary>
726        /// This is the W value.
727        /// </summary>
728        [AdvBrowsable]
729        [XmlAttribute]
730        [System.ComponentModel.Description("The Magnitude on the W-Axis")]
731        public Scalar W;
732
733        #endregion
734        #region constructors
735        /// <summary>
736        /// Creates a New Vector4D Instance on the Stack.
737        /// </summary>
738        /// <param name="X">The X value.</param>
739        /// <param name="Y">The Y value.</param>
740        /// <param name="Z">The Z value.</param>
741        /// <param name="W">The W value.</param>
742        [InstanceConstructor("X,Y,Z,W")]
743        public Vector4D(Scalar X, Scalar Y, Scalar Z, Scalar W)
744        {
745            this.X = X;
746            this.Y = Y;
747            this.Z = Z;
748            this.W = W;
749        }
750        public Vector4D(Scalar[] vals) : this(vals, 0) { }
751        public Vector4D(Scalar[] vals, int index)
752        {
753            Copy(vals, index, out this);
754        }
755        #endregion
756        #region indexers
757#if UNSAFE
758        /// <summary>
759        ///             Allows the Vector to be accessed linearly (v[0] -> v[Count-1]). 
760        /// </summary>
761        /// <remarks>
762        ///    This indexer is only provided as a convenience, and is <b>not</b> recommended for use in
763        ///    intensive applications. 
764        /// </remarks>
765        public Scalar this[int index]
766        {
767            get
768            {
769                ThrowHelper.CheckIndex("index", index, Count);
770                unsafe
771                {
772                    fixed (Scalar* ptr = &this.X)
773                    {
774                        return ptr[index];
775                    }
776                }
777            }
778            set
779            {
780                ThrowHelper.CheckIndex("index", index, Count);
781                unsafe
782                {
783                    fixed (Scalar* ptr = &this.X)
784                    {
785                        ptr[index] = value;
786                    }
787                }
788            }
789        }
790#endif
791        #endregion
792        #region properties
793
794
795        /// <summary>
796        /// Gets or Sets the Magnitude (Length) of the Vector4D.
797        /// </summary>
798        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Length_of_a_vector"/></remarks>
799        [XmlIgnore]
800        public Scalar Magnitude
801        {
802            get
803            {
804                return MathHelper.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W);
805            }
806            set
807            {
808                this = SetMagnitude(this, value);
809            }
810        }
811        /// <summary>
812        /// Gets the Squared Magnitude of the Vector4D.
813        /// </summary>
814        public Scalar MagnitudeSq
815        {
816            get
817            {
818                return this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W;
819            }
820        }
821        /// <summary>
822        /// Gets the Normalized Vector4D. (Unit Vector)
823        /// </summary>
824        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
825        public Vector4D Normalized
826        {
827            get
828            {
829                return Normalize(this);
830            }
831        }
832        /// <summary>
833        /// The Number of Variables accesable though the indexer.
834        /// </summary>
835        int IAdvanceValueType.Count { get { return Count; } }
836        #endregion
837        #region public methods
838        public Scalar[] ToArray()
839        {
840            Scalar[] array = new Scalar[Count];
841            Copy(ref this, array, 0);
842            return array;
843        }
844        public void CopyFrom(Scalar[] array, int index)
845        {
846            Copy(array, index, out this);
847        }
848        public void CopyTo(Scalar[] array, int index)
849        {
850            Copy(ref this, array, index);
851        }
852        #endregion
853        #region operators
854        /// <summary>
855        /// Adds 2 Vectors2Ds.
856        /// </summary>
857        /// <param name="left">The left Vector4D operand.</param>
858        /// <param name="right">The right Vector4D operand.</param>
859        /// <returns>The Sum of the 2 Vector4Ds.</returns>
860        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
861        public static Vector4D operator +(Vector4D left, Vector4D right)
862        {
863            Vector4D result;
864            result.X = left.X + right.X;
865            result.Y = left.Y + right.Y;
866            result.Z = left.Z + right.Z;
867            result.W = left.W + right.W;
868            return result;
869        }
870        public static Vector4D operator +(Vector3D left, Vector4D right)
871        {
872            Vector4D result;
873            Add(ref left, ref right, out result);
874            return result;
875        }
876        public static Vector4D operator +(Vector2D left, Vector4D right)
877        {
878            Vector4D result;
879            Add(ref left, ref right, out result);
880            return result;
881        }
882        public static Vector4D operator +(Vector4D left, Vector3D right)
883        {
884            Vector4D result;
885            Add(ref left, ref right, out result);
886            return result;
887        }
888        public static Vector4D operator +(Vector4D left, Vector2D right)
889        {
890            Vector4D result;
891            Add(ref left, ref right, out result);
892            return result;
893        }
894        /// <summary>
895        /// Subtracts 2 Vector4Ds.
896        /// </summary>
897        /// <param name="left">The left Vector4D operand.</param>
898        /// <param name="right">The right Vector4D operand.</param>
899        /// <returns>The Difference of the 2 Vector4Ds.</returns>
900        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
901        public static Vector4D operator -(Vector4D left, Vector4D right)
902        {
903            Vector4D result;
904            result.X = left.X - right.X;
905            result.Y = left.Y - right.Y;
906            result.Z = left.Z - right.Z;
907            result.W = left.W - right.W;
908            return result;
909        }
910        public static Vector4D operator -(Vector3D left, Vector4D right)
911        {
912            Vector4D result;
913            Subtract(ref left, ref right, out result);
914            return result;
915        }
916        public static Vector4D operator -(Vector2D left, Vector4D right)
917        {
918            Vector4D result;
919            Subtract(ref left, ref right, out result);
920            return result;
921        }
922        public static Vector4D operator -(Vector4D left, Vector3D right)
923        {
924            Vector4D result;
925            Subtract(ref left, ref right, out result);
926            return result;
927        }
928        public static Vector4D operator -(Vector4D left, Vector2D right)
929        {
930            Vector4D result;
931            Subtract(ref left, ref right, out result);
932            return result;
933        }
934        /// <summary>
935        /// Does Scaler Multiplication on a Vector4D.
936        /// </summary>
937        /// <param name="source">The Vector4D to be multiplied.</param>
938        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
939        /// <returns>The Product of the Scaler Multiplication.</returns>
940        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
941        public static Vector4D operator *(Vector4D source, Scalar scalar)
942        {
943            Vector4D result;
944            result.X = source.X * scalar;
945            result.Y = source.Y * scalar;
946            result.Z = source.Z * scalar;
947            result.W = source.W * scalar;
948            return result;
949        }
950        /// <summary>
951        /// Does Scaler Multiplication on a Vector4D.
952        /// </summary>
953        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
954        /// <param name="source">The Vector4D to be multiplied.</param>
955        /// <returns>The Product of the Scaler Multiplication.</returns>
956        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
957        public static Vector4D operator *(Scalar scalar, Vector4D source)
958        {
959            Vector4D result;
960            result.X = scalar * source.X;
961            result.Y = scalar * source.Y;
962            result.Z = scalar * source.Z;
963            result.W = scalar * source.W;
964            return result;
965        }
966        /// <summary>
967        /// Does a Dot Operation Also know as an Inner Product.
968        /// </summary>
969        /// <param name="left">The left Vector4D operand.</param>
970        /// <param name="right">The right Vector4D operand.</param>
971        /// <returns>The Dot Product (Inner Product).</returns>
972        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Dot_product"/></remarks>
973        public static Scalar operator *(Vector4D left, Vector4D right)
974        {
975            return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
976        }
977
978
979        public static Vector4D operator *(Matrix4x4 matrix, Vector4D vector)
980        {
981            Vector4D result;
982
983            result.X = vector.X * matrix.m00 + vector.Y * matrix.m01 + vector.Z * matrix.m02 + vector.W * matrix.m03;
984            result.Y = vector.X * matrix.m10 + vector.Y * matrix.m11 + vector.Z * matrix.m12 + vector.W * matrix.m13;
985            result.Z = vector.X * matrix.m20 + vector.Y * matrix.m21 + vector.Z * matrix.m22 + vector.W * matrix.m23;
986            result.W = vector.X * matrix.m30 + vector.Y * matrix.m31 + vector.Z * matrix.m32 + vector.W * matrix.m33;
987
988            return result;
989        }
990
991        public static Vector4D operator *(Vector4D vector, Matrix4x4 matrix)
992        {
993            Vector4D result;
994
995            result.X = vector.X * matrix.m00 + vector.Y * matrix.m10 + vector.Z * matrix.m20 + vector.W * matrix.m30;
996            result.Y = vector.X * matrix.m01 + vector.Y * matrix.m11 + vector.Z * matrix.m21 + vector.W * matrix.m31;
997            result.Z = vector.X * matrix.m02 + vector.Y * matrix.m12 + vector.Z * matrix.m22 + vector.W * matrix.m32;
998            result.W = vector.X * matrix.m03 + vector.Y * matrix.m13 + vector.Z * matrix.m23 + vector.W * matrix.m33;
999
1000            return result;
1001        }
1002
1003        /// <summary>
1004        /// Negates a Vector4D.
1005        /// </summary>
1006        /// <param name="source">The Vector4D to be Negated.</param>
1007        /// <returns>The Negated Vector4D.</returns>
1008        public static Vector4D operator -(Vector4D source)
1009        {
1010            Vector4D result;
1011            result.X = -source.X;
1012            result.Y = -source.Y;
1013            result.Z = -source.Z;
1014            result.W = -source.W;
1015            return result;
1016        }
1017        /// <summary>
1018        /// Specifies whether the Vector4Ds contain the same coordinates.
1019        /// </summary>
1020        /// <param name="left">The left Vector4D to test.</param>
1021        /// <param name="right">The right Vector4D to test.</param>
1022        /// <returns>true if the Vector4Ds have the same coordinates; otherwise false</returns>
1023        public static bool operator ==(Vector4D left, Vector4D right)
1024        {
1025            return left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W;
1026        }
1027        /// <summary>
1028        /// Specifies whether the Vector4Ds do not contain the same coordinates.
1029        /// </summary>
1030        /// <param name="left">The left Vector4D to test.</param>
1031        /// <param name="right">The right Vector4D to test.</param>
1032        /// <returns>true if the Vector4Ds do not have the same coordinates; otherwise false</returns>
1033        public static bool operator !=(Vector4D left, Vector4D right)
1034        {
1035            return !(left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W);
1036        }
1037
1038
1039        public static explicit operator Vector4D(Vector3D source)
1040        {
1041            Vector4D result;
1042            result.X = source.X;
1043            result.Y = source.Y;
1044            result.Z = source.Z;
1045            result.W = 1;
1046            return result;
1047        }
1048
1049        #endregion
1050        #region overrides
1051        private string ToStringInternal(string FormatString)
1052        {
1053            return string.Format(FormatString, X, Y, Z, W);
1054        }
1055        public string ToString(string format)
1056        {
1057            return ToStringInternal(string.Format(FormatableString, format));
1058        }
1059        public override string ToString()
1060        {
1061            return ToStringInternal(FormatString);
1062        }
1063
1064
1065#if !CompactFramework && !WindowsCE && !PocketPC && !XBOX360 && !SILVERLIGHT
1066        public static bool TryParse(string s, out Vector4D result)
1067        {
1068            if (s == null)
1069            {
1070                result = Zero;
1071                return false;
1072            }
1073            string[] vals = ParseHelper.SplitStringVector(s);
1074            if (vals.Length != Count)
1075            {
1076                result = Zero;
1077                return false;
1078            }
1079            if (Scalar.TryParse(vals[0], out result.X) &&
1080                Scalar.TryParse(vals[1], out result.Y) &&
1081                Scalar.TryParse(vals[2], out result.Z) &&
1082                Scalar.TryParse(vals[3], out result.W))
1083            {
1084                return true;
1085            }
1086            else
1087            {
1088                result = Zero;
1089                return false;
1090            }
1091        }
1092#endif
1093        [ParseMethod]
1094        public static Vector4D Parse(string s)
1095        {
1096            if (s == null)
1097            {
1098                throw new ArgumentNullException("s");
1099            }
1100            string[] vals = ParseHelper.SplitStringVector(s);
1101            if (vals.Length != Count)
1102            {
1103                ThrowHelper.ThrowVectorFormatException(s, Count, FormatString);
1104            }
1105            Vector4D value;
1106            value.X = Scalar.Parse(vals[0]);
1107            value.Y = Scalar.Parse(vals[1]);
1108            value.Z = Scalar.Parse(vals[2]);
1109            value.W = Scalar.Parse(vals[3]);
1110            return value;
1111        }
1112
1113
1114        /// <summary>
1115        ///             Provides a unique hash code based on the member variables of this
1116        ///             class.  This should be done because the equality operators (==, !=)
1117        ///             have been overriden by this class.
1118        ///             <p/>
1119        ///             The standard implementation is a simple XOR operation between all local
1120        ///             member variables.
1121        /// </summary>
1122        /// <returns></returns>
1123        public override int GetHashCode()
1124        {
1125            return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
1126        }
1127
1128        /// <summary>
1129        ///             Compares this Vector to another object.  This should be done because the
1130        ///             equality operators (==, !=) have been overriden by this class.
1131        /// </summary>
1132        /// <param name="obj"></param>
1133        /// <returns></returns>
1134        public override bool Equals(object obj)
1135        {
1136            return (obj is Vector4D) && Equals((Vector4D)obj);
1137        }
1138        public bool Equals(Vector4D other)
1139        {
1140            return Equals(ref this, ref other);
1141        }
1142        public static bool Equals(Vector4D left, Vector4D right)
1143        {
1144            return
1145                left.X == right.X &&
1146                left.Y == right.Y &&
1147                left.Z == right.Z &&
1148                left.W == right.W;
1149        }
1150        [CLSCompliant(false)]
1151        public static bool Equals(ref Vector4D left, ref Vector4D right)
1152        {
1153            return
1154                left.X == right.X &&
1155                left.Y == right.Y &&
1156                left.Z == right.Z &&
1157                left.W == right.W;
1158        }
1159        #endregion
1160    }
1161}
Note: See TracBrowser for help on using the repository browser.