Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Vector3.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under MIT License. See LICENSE.md for details.
3 //
4 // -----------------------------------------------------------------------------
5 // Original code from SlimMath project. http://code.google.com/p/slimmath/
6 // Greetings to SlimDX Group. Original code published with the following license:
7 // -----------------------------------------------------------------------------
8 /*
9 * Copyright (c) 2007-2011 SlimDX Group
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 */
29 using System;
30 using System.Globalization;
31 using System.Runtime.InteropServices;
32 using System.ComponentModel;
33 
34 namespace SiliconStudio.Core.Mathematics
35 {
36  /// <summary>
37  /// Represents a three dimensional mathematical vector.
38  /// </summary>
39  [DataContract("float3")]
40  [DataStyle(DataStyle.Compact)]
41  [StructLayout(LayoutKind.Sequential, Pack = 4)]
42  public struct Vector3 : IEquatable<Vector3>, IFormattable
43  {
44  /// <summary>
45  /// The size of the <see cref="SiliconStudio.Core.Mathematics.Vector3"/> type, in bytes.
46  /// </summary>
47  public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector3));
48 
49  /// <summary>
50  /// A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> with all of its components set to zero.
51  /// </summary>
52  public static readonly Vector3 Zero = new Vector3();
53 
54  /// <summary>
55  /// The X unit <see cref="SiliconStudio.Core.Mathematics.Vector3"/> (1, 0, 0).
56  /// </summary>
57  public static readonly Vector3 UnitX = new Vector3(1.0f, 0.0f, 0.0f);
58 
59  /// <summary>
60  /// The Y unit <see cref="SiliconStudio.Core.Mathematics.Vector3"/> (0, 1, 0).
61  /// </summary>
62  public static readonly Vector3 UnitY = new Vector3(0.0f, 1.0f, 0.0f);
63 
64  /// <summary>
65  /// The Z unit <see cref="SiliconStudio.Core.Mathematics.Vector3"/> (0, 0, 1).
66  /// </summary>
67  public static readonly Vector3 UnitZ = new Vector3(0.0f, 0.0f, 1.0f);
68 
69  /// <summary>
70  /// A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> with all of its components set to one.
71  /// </summary>
72  public static readonly Vector3 One = new Vector3(1.0f, 1.0f, 1.0f);
73 
74  /// <summary>
75  /// The X component of the vector.
76  /// </summary>
77  [DataMember(0)]
78  public float X;
79 
80  /// <summary>
81  /// The Y component of the vector.
82  /// </summary>
83  [DataMember(1)]
84  public float Y;
85 
86  /// <summary>
87  /// The Z component of the vector.
88  /// </summary>
89  [DataMember(2)]
90  public float Z;
91 
92  /// <summary>
93  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Vector3"/> struct.
94  /// </summary>
95  /// <param name="value">The value that will be assigned to all components.</param>
96  public Vector3(float value)
97  {
98  X = value;
99  Y = value;
100  Z = value;
101  }
102 
103  /// <summary>
104  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Vector3"/> struct.
105  /// </summary>
106  /// <param name="x">Initial value for the X component of the vector.</param>
107  /// <param name="y">Initial value for the Y component of the vector.</param>
108  /// <param name="z">Initial value for the Z component of the vector.</param>
109  public Vector3(float x, float y, float z)
110  {
111  X = x;
112  Y = y;
113  Z = z;
114  }
115 
116  /// <summary>
117  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Vector3"/> struct.
118  /// </summary>
119  /// <param name="value">A vector containing the values with which to initialize the X and Y components.</param>
120  /// <param name="z">Initial value for the Z component of the vector.</param>
121  public Vector3(Vector2 value, float z)
122  {
123  X = value.X;
124  Y = value.Y;
125  Z = z;
126  }
127 
128  /// <summary>
129  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Vector3"/> struct.
130  /// </summary>
131  /// <param name="values">The values to assign to the X, Y, and Z components of the vector. This must be an array with three elements.</param>
132  /// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
133  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than three elements.</exception>
134  public Vector3(float[] values)
135  {
136  if (values == null)
137  throw new ArgumentNullException("values");
138  if (values.Length != 3)
139  throw new ArgumentOutOfRangeException("values", "There must be three and only three input values for Vector3.");
140 
141  X = values[0];
142  Y = values[1];
143  Z = values[2];
144  }
145 
146  /// <summary>
147  /// Gets a value indicting whether this instance is normalized.
148  /// </summary>
149  public bool IsNormalized
150  {
151  get { return Math.Abs((X * X) + (Y * Y) + (Z * Z) - 1f) < MathUtil.ZeroTolerance; }
152  }
153 
154  /// <summary>
155  /// Gets or sets the component at the specified index.
156  /// </summary>
157  /// <value>The value of the X, Y, or Z component, depending on the index.</value>
158  /// <param name="index">The index of the component to access. Use 0 for the X component, 1 for the Y component, and 2 for the Z component.</param>
159  /// <returns>The value of the component at the specified index.</returns>
160  /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 2].</exception>
161  public float this[int index]
162  {
163  get
164  {
165  switch (index)
166  {
167  case 0: return X;
168  case 1: return Y;
169  case 2: return Z;
170  }
171 
172  throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive.");
173  }
174 
175  set
176  {
177  switch (index)
178  {
179  case 0: X = value; break;
180  case 1: Y = value; break;
181  case 2: Z = value; break;
182  default: throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive.");
183  }
184  }
185  }
186 
187  /// <summary>
188  /// Calculates the length of the vector.
189  /// </summary>
190  /// <returns>The length of the vector.</returns>
191  /// <remarks>
192  /// <see cref="SiliconStudio.Core.Mathematics.Vector3.LengthSquared"/> may be preferred when only the relative length is needed
193  /// and speed is of the essence.
194  /// </remarks>
195  public float Length()
196  {
197  return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
198  }
199 
200  /// <summary>
201  /// Calculates the squared length of the vector.
202  /// </summary>
203  /// <returns>The squared length of the vector.</returns>
204  /// <remarks>
205  /// This method may be preferred to <see cref="SiliconStudio.Core.Mathematics.Vector3.Length"/> when only a relative length is needed
206  /// and speed is of the essence.
207  /// </remarks>
208  public float LengthSquared()
209  {
210  return (X * X) + (Y * Y) + (Z * Z);
211  }
212 
213  /// <summary>
214  /// Converts the vector into a unit vector.
215  /// </summary>
216  public void Normalize()
217  {
218  float length = Length();
219  if (length > MathUtil.ZeroTolerance)
220  {
221  float inv = 1.0f / length;
222  X *= inv;
223  Y *= inv;
224  Z *= inv;
225  }
226  }
227 
228  /// <summary>
229  /// Raises the exponent for each components.
230  /// </summary>
231  /// <param name="exponent">The exponent.</param>
232  public void Pow(float exponent)
233  {
234  X = (float)Math.Pow(X, exponent);
235  Y = (float)Math.Pow(Y, exponent);
236  Z = (float)Math.Pow(Z, exponent);
237  }
238 
239  /// <summary>
240  /// Creates an array containing the elements of the vector.
241  /// </summary>
242  /// <returns>A three-element array containing the components of the vector.</returns>
243  public float[] ToArray()
244  {
245  return new float[] { X, Y, Z };
246  }
247 
248  /// <summary>
249  /// Adds two vectors.
250  /// </summary>
251  /// <param name="left">The first vector to add.</param>
252  /// <param name="right">The second vector to add.</param>
253  /// <param name="result">When the method completes, contains the sum of the two vectors.</param>
254  public static void Add(ref Vector3 left, ref Vector3 right, out Vector3 result)
255  {
256  result = new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
257  }
258 
259  /// <summary>
260  /// Adds two vectors.
261  /// </summary>
262  /// <param name="left">The first vector to add.</param>
263  /// <param name="right">The second vector to add.</param>
264  /// <returns>The sum of the two vectors.</returns>
265  public static Vector3 Add(Vector3 left, Vector3 right)
266  {
267  return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
268  }
269 
270  /// <summary>
271  /// Subtracts two vectors.
272  /// </summary>
273  /// <param name="left">The first vector to subtract.</param>
274  /// <param name="right">The second vector to subtract.</param>
275  /// <param name="result">When the method completes, contains the difference of the two vectors.</param>
276  public static void Subtract(ref Vector3 left, ref Vector3 right, out Vector3 result)
277  {
278  result = new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
279  }
280 
281  /// <summary>
282  /// Subtracts two vectors.
283  /// </summary>
284  /// <param name="left">The first vector to subtract.</param>
285  /// <param name="right">The second vector to subtract.</param>
286  /// <returns>The difference of the two vectors.</returns>
287  public static Vector3 Subtract(Vector3 left, Vector3 right)
288  {
289  return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
290  }
291 
292  /// <summary>
293  /// Scales a vector by the given value.
294  /// </summary>
295  /// <param name="value">The vector to scale.</param>
296  /// <param name="scale">The amount by which to scale the vector.</param>
297  /// <param name="result">When the method completes, contains the scaled vector.</param>
298  public static void Multiply(ref Vector3 value, float scale, out Vector3 result)
299  {
300  result = new Vector3(value.X * scale, value.Y * scale, value.Z * scale);
301  }
302 
303  /// <summary>
304  /// Scales a vector by the given value.
305  /// </summary>
306  /// <param name="value">The vector to scale.</param>
307  /// <param name="scale">The amount by which to scale the vector.</param>
308  /// <returns>The scaled vector.</returns>
309  public static Vector3 Multiply(Vector3 value, float scale)
310  {
311  return new Vector3(value.X * scale, value.Y * scale, value.Z * scale);
312  }
313 
314  /// <summary>
315  /// Modulates a vector with another by performing component-wise multiplication.
316  /// </summary>
317  /// <param name="left">The first vector to modulate.</param>
318  /// <param name="right">The second vector to modulate.</param>
319  /// <param name="result">When the method completes, contains the modulated vector.</param>
320  public static void Modulate(ref Vector3 left, ref Vector3 right, out Vector3 result)
321  {
322  result = new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
323  }
324 
325  /// <summary>
326  /// Modulates a vector with another by performing component-wise multiplication.
327  /// </summary>
328  /// <param name="left">The first vector to modulate.</param>
329  /// <param name="right">The second vector to modulate.</param>
330  /// <returns>The modulated vector.</returns>
331  public static Vector3 Modulate(Vector3 left, Vector3 right)
332  {
333  return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
334  }
335 
336  /// <summary>
337  /// Scales a vector by the given value.
338  /// </summary>
339  /// <param name="value">The vector to scale.</param>
340  /// <param name="scale">The amount by which to scale the vector.</param>
341  /// <param name="result">When the method completes, contains the scaled vector.</param>
342  public static void Divide(ref Vector3 value, float scale, out Vector3 result)
343  {
344  result = new Vector3(value.X / scale, value.Y / scale, value.Z / scale);
345  }
346 
347  /// <summary>
348  /// Scales a vector by the given value.
349  /// </summary>
350  /// <param name="value">The vector to scale.</param>
351  /// <param name="scale">The amount by which to scale the vector.</param>
352  /// <returns>The scaled vector.</returns>
353  public static Vector3 Divide(Vector3 value, float scale)
354  {
355  return new Vector3(value.X / scale, value.Y / scale, value.Z / scale);
356  }
357 
358  /// <summary>
359  /// Demodulates a vector with another by performing component-wise division.
360  /// </summary>
361  /// <param name="left">The first vector to demodulate.</param>
362  /// <param name="right">The second vector to demodulate.</param>
363  /// <param name="result">When the method completes, contains the demodulated vector.</param>
364  public static void Demodulate(ref Vector3 left, ref Vector3 right, out Vector3 result)
365  {
366  result = new Vector3(left.X / right.X, left.Y / right.Y, left.Z / right.Z);
367  }
368 
369  /// <summary>
370  /// Demodulates a vector with another by performing component-wise division.
371  /// </summary>
372  /// <param name="left">The first vector to demodulate.</param>
373  /// <param name="right">The second vector to demodulate.</param>
374  /// <returns>The demodulated vector.</returns>
375  public static Vector3 Demodulate(Vector3 left, Vector3 right)
376  {
377  return new Vector3(left.X / right.X, left.Y / right.Y, left.Z / right.Z);
378  }
379 
380  /// <summary>
381  /// Reverses the direction of a given vector.
382  /// </summary>
383  /// <param name="value">The vector to negate.</param>
384  /// <param name="result">When the method completes, contains a vector facing in the opposite direction.</param>
385  public static void Negate(ref Vector3 value, out Vector3 result)
386  {
387  result = new Vector3(-value.X, -value.Y, -value.Z);
388  }
389 
390  /// <summary>
391  /// Reverses the direction of a given vector.
392  /// </summary>
393  /// <param name="value">The vector to negate.</param>
394  /// <returns>A vector facing in the opposite direction.</returns>
395  public static Vector3 Negate(Vector3 value)
396  {
397  return new Vector3(-value.X, -value.Y, -value.Z);
398  }
399 
400  /// <summary>
401  /// Returns a <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle.
402  /// </summary>
403  /// <param name="value1">A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of vertex 1 of the triangle.</param>
404  /// <param name="value2">A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of vertex 2 of the triangle.</param>
405  /// <param name="value3">A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of vertex 3 of the triangle.</param>
406  /// <param name="amount1">Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in <paramref name="value2"/>).</param>
407  /// <param name="amount2">Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in <paramref name="value3"/>).</param>
408  /// <param name="result">When the method completes, contains the 3D Cartesian coordinates of the specified point.</param>
409  public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result)
410  {
411  result = new Vector3((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)),
412  (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y)),
413  (value1.Z + (amount1 * (value2.Z - value1.Z))) + (amount2 * (value3.Z - value1.Z)));
414  }
415 
416  /// <summary>
417  /// Returns a <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle.
418  /// </summary>
419  /// <param name="value1">A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of vertex 1 of the triangle.</param>
420  /// <param name="value2">A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of vertex 2 of the triangle.</param>
421  /// <param name="value3">A <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of vertex 3 of the triangle.</param>
422  /// <param name="amount1">Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in <paramref name="value2"/>).</param>
423  /// <param name="amount2">Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in <paramref name="value3"/>).</param>
424  /// <returns>A new <see cref="SiliconStudio.Core.Mathematics.Vector3"/> containing the 3D Cartesian coordinates of the specified point.</returns>
425  public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2)
426  {
427  Vector3 result;
428  Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result);
429  return result;
430  }
431 
432  /// <summary>
433  /// Restricts a value to be within a specified range.
434  /// </summary>
435  /// <param name="value">The value to clamp.</param>
436  /// <param name="min">The minimum value.</param>
437  /// <param name="max">The maximum value.</param>
438  /// <param name="result">When the method completes, contains the clamped value.</param>
439  public static void Clamp(ref Vector3 value, ref Vector3 min, ref Vector3 max, out Vector3 result)
440  {
441  float x = value.X;
442  x = (x > max.X) ? max.X : x;
443  x = (x < min.X) ? min.X : x;
444 
445  float y = value.Y;
446  y = (y > max.Y) ? max.Y : y;
447  y = (y < min.Y) ? min.Y : y;
448 
449  float z = value.Z;
450  z = (z > max.Z) ? max.Z : z;
451  z = (z < min.Z) ? min.Z : z;
452 
453  result = new Vector3(x, y, z);
454  }
455 
456  /// <summary>
457  /// Restricts a value to be within a specified range.
458  /// </summary>
459  /// <param name="value">The value to clamp.</param>
460  /// <param name="min">The minimum value.</param>
461  /// <param name="max">The maximum value.</param>
462  /// <returns>The clamped value.</returns>
463  public static Vector3 Clamp(Vector3 value, Vector3 min, Vector3 max)
464  {
465  Vector3 result;
466  Clamp(ref value, ref min, ref max, out result);
467  return result;
468  }
469 
470  /// <summary>
471  /// Calculates the cross product of two vectors.
472  /// </summary>
473  /// <param name="left">First source vector.</param>
474  /// <param name="right">Second source vector.</param>
475  /// <param name="result">When the method completes, contains he cross product of the two vectors.</param>
476  public static void Cross(ref Vector3 left, ref Vector3 right, out Vector3 result)
477  {
478  result = new Vector3(
479  (left.Y * right.Z) - (left.Z * right.Y),
480  (left.Z * right.X) - (left.X * right.Z),
481  (left.X * right.Y) - (left.Y * right.X));
482  }
483 
484  /// <summary>
485  /// Calculates the cross product of two vectors.
486  /// </summary>
487  /// <param name="left">First source vector.</param>
488  /// <param name="right">Second source vector.</param>
489  /// <returns>The cross product of the two vectors.</returns>
490  public static Vector3 Cross(Vector3 left, Vector3 right)
491  {
492  Vector3 result;
493  Cross(ref left, ref right, out result);
494  return result;
495  }
496 
497  /// <summary>
498  /// Calculates the distance between two vectors.
499  /// </summary>
500  /// <param name="value1">The first vector.</param>
501  /// <param name="value2">The second vector.</param>
502  /// <param name="result">When the method completes, contains the distance between the two vectors.</param>
503  /// <remarks>
504  /// <see cref="SiliconStudio.Core.Mathematics.Vector3.DistanceSquared(ref Vector3, ref Vector3, out float)"/> may be preferred when only the relative distance is needed
505  /// and speed is of the essence.
506  /// </remarks>
507  public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result)
508  {
509  float x = value1.X - value2.X;
510  float y = value1.Y - value2.Y;
511  float z = value1.Z - value2.Z;
512 
513  result = (float)Math.Sqrt((x * x) + (y * y) + (z * z));
514  }
515 
516  /// <summary>
517  /// Calculates the distance between two vectors.
518  /// </summary>
519  /// <param name="value1">The first vector.</param>
520  /// <param name="value2">The second vector.</param>
521  /// <returns>The distance between the two vectors.</returns>
522  /// <remarks>
523  /// <see cref="SiliconStudio.Core.Mathematics.Vector3.DistanceSquared(Vector3, Vector3)"/> may be preferred when only the relative distance is needed
524  /// and speed is of the essence.
525  /// </remarks>
526  public static float Distance(Vector3 value1, Vector3 value2)
527  {
528  float x = value1.X - value2.X;
529  float y = value1.Y - value2.Y;
530  float z = value1.Z - value2.Z;
531 
532  return (float)Math.Sqrt((x * x) + (y * y) + (z * z));
533  }
534 
535  /// <summary>
536  /// Calculates the squared distance between two vectors.
537  /// </summary>
538  /// <param name="value1">The first vector.</param>
539  /// <param name="value2">The second vector.</param>
540  /// <param name="result">When the method completes, contains the squared distance between the two vectors.</param>
541  /// <remarks>Distance squared is the value before taking the square root.
542  /// Distance squared can often be used in place of distance if relative comparisons are being made.
543  /// For example, consider three points A, B, and C. To determine whether B or C is further from A,
544  /// compare the distance between A and B to the distance between A and C. Calculating the two distances
545  /// involves two square roots, which are computationally expensive. However, using distance squared
546  /// provides the same information and avoids calculating two square roots.
547  /// </remarks>
548  public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result)
549  {
550  float x = value1.X - value2.X;
551  float y = value1.Y - value2.Y;
552  float z = value1.Z - value2.Z;
553 
554  result = (x * x) + (y * y) + (z * z);
555  }
556 
557  /// <summary>
558  /// Calculates the squared distance between two vectors.
559  /// </summary>
560  /// <param name="value1">The first vector.</param>
561  /// <param name="value2">The second vector.</param>
562  /// <returns>The squared distance between the two vectors.</returns>
563  /// <remarks>Distance squared is the value before taking the square root.
564  /// Distance squared can often be used in place of distance if relative comparisons are being made.
565  /// For example, consider three points A, B, and C. To determine whether B or C is further from A,
566  /// compare the distance between A and B to the distance between A and C. Calculating the two distances
567  /// involves two square roots, which are computationally expensive. However, using distance squared
568  /// provides the same information and avoids calculating two square roots.
569  /// </remarks>
570  public static float DistanceSquared(Vector3 value1, Vector3 value2)
571  {
572  float x = value1.X - value2.X;
573  float y = value1.Y - value2.Y;
574  float z = value1.Z - value2.Z;
575 
576  return (x * x) + (y * y) + (z * z);
577  }
578 
579  /// <summary>
580  /// Calculates the dot product of two vectors.
581  /// </summary>
582  /// <param name="left">First source vector.</param>
583  /// <param name="right">Second source vector.</param>
584  /// <param name="result">When the method completes, contains the dot product of the two vectors.</param>
585  public static void Dot(ref Vector3 left, ref Vector3 right, out float result)
586  {
587  result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z);
588  }
589 
590  /// <summary>
591  /// Calculates the dot product of two vectors.
592  /// </summary>
593  /// <param name="left">First source vector.</param>
594  /// <param name="right">Second source vector.</param>
595  /// <returns>The dot product of the two vectors.</returns>
596  public static float Dot(Vector3 left, Vector3 right)
597  {
598  return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z);
599  }
600 
601  /// <summary>
602  /// Converts the vector into a unit vector.
603  /// </summary>
604  /// <param name="value">The vector to normalize.</param>
605  /// <param name="result">When the method completes, contains the normalized vector.</param>
606  public static void Normalize(ref Vector3 value, out Vector3 result)
607  {
608  result = value;
609  result.Normalize();
610  }
611 
612  /// <summary>
613  /// Converts the vector into a unit vector.
614  /// </summary>
615  /// <param name="value">The vector to normalize.</param>
616  /// <returns>The normalized vector.</returns>
617  public static Vector3 Normalize(Vector3 value)
618  {
619  value.Normalize();
620  return value;
621  }
622 
623  /// <summary>
624  /// Performs a linear interpolation between two vectors.
625  /// </summary>
626  /// <param name="start">Start vector.</param>
627  /// <param name="end">End vector.</param>
628  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
629  /// <param name="result">When the method completes, contains the linear interpolation of the two vectors.</param>
630  /// <remarks>
631  /// This method performs the linear interpolation based on the following formula.
632  /// <code>start + (end - start) * amount</code>
633  /// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
634  /// </remarks>
635  public static void Lerp(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result)
636  {
637  result.X = start.X + ((end.X - start.X) * amount);
638  result.Y = start.Y + ((end.Y - start.Y) * amount);
639  result.Z = start.Z + ((end.Z - start.Z) * amount);
640  }
641 
642  /// <summary>
643  /// Performs a linear interpolation between two vectors.
644  /// </summary>
645  /// <param name="start">Start vector.</param>
646  /// <param name="end">End vector.</param>
647  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
648  /// <returns>The linear interpolation of the two vectors.</returns>
649  /// <remarks>
650  /// This method performs the linear interpolation based on the following formula.
651  /// <code>start + (end - start) * amount</code>
652  /// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
653  /// </remarks>
654  public static Vector3 Lerp(Vector3 start, Vector3 end, float amount)
655  {
656  Vector3 result;
657  Lerp(ref start, ref end, amount, out result);
658  return result;
659  }
660 
661  /// <summary>
662  /// Performs a cubic interpolation between two vectors.
663  /// </summary>
664  /// <param name="start">Start vector.</param>
665  /// <param name="end">End vector.</param>
666  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
667  /// <param name="result">When the method completes, contains the cubic interpolation of the two vectors.</param>
668  public static void SmoothStep(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result)
669  {
670  amount = (amount > 1.0f) ? 1.0f : ((amount < 0.0f) ? 0.0f : amount);
671  amount = (amount * amount) * (3.0f - (2.0f * amount));
672 
673  result.X = start.X + ((end.X - start.X) * amount);
674  result.Y = start.Y + ((end.Y - start.Y) * amount);
675  result.Z = start.Z + ((end.Z - start.Z) * amount);
676  }
677 
678  /// <summary>
679  /// Performs a cubic interpolation between two vectors.
680  /// </summary>
681  /// <param name="start">Start vector.</param>
682  /// <param name="end">End vector.</param>
683  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
684  /// <returns>The cubic interpolation of the two vectors.</returns>
685  public static Vector3 SmoothStep(Vector3 start, Vector3 end, float amount)
686  {
687  Vector3 result;
688  SmoothStep(ref start, ref end, amount, out result);
689  return result;
690  }
691 
692  /// <summary>
693  /// Performs a Hermite spline interpolation.
694  /// </summary>
695  /// <param name="value1">First source position vector.</param>
696  /// <param name="tangent1">First source tangent vector.</param>
697  /// <param name="value2">Second source position vector.</param>
698  /// <param name="tangent2">Second source tangent vector.</param>
699  /// <param name="amount">Weighting factor.</param>
700  /// <param name="result">When the method completes, contains the result of the Hermite spline interpolation.</param>
701  public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result)
702  {
703  float squared = amount * amount;
704  float cubed = amount * squared;
705  float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f;
706  float part2 = (-2.0f * cubed) + (3.0f * squared);
707  float part3 = (cubed - (2.0f * squared)) + amount;
708  float part4 = cubed - squared;
709 
710  result.X = (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4);
711  result.Y = (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4);
712  result.Z = (((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * part4);
713  }
714 
715  /// <summary>
716  /// Performs a Hermite spline interpolation.
717  /// </summary>
718  /// <param name="value1">First source position vector.</param>
719  /// <param name="tangent1">First source tangent vector.</param>
720  /// <param name="value2">Second source position vector.</param>
721  /// <param name="tangent2">Second source tangent vector.</param>
722  /// <param name="amount">Weighting factor.</param>
723  /// <returns>The result of the Hermite spline interpolation.</returns>
724  public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount)
725  {
726  Vector3 result;
727  Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result);
728  return result;
729  }
730 
731  /// <summary>
732  /// Performs a Catmull-Rom interpolation using the specified positions.
733  /// </summary>
734  /// <param name="value1">The first position in the interpolation.</param>
735  /// <param name="value2">The second position in the interpolation.</param>
736  /// <param name="value3">The third position in the interpolation.</param>
737  /// <param name="value4">The fourth position in the interpolation.</param>
738  /// <param name="amount">Weighting factor.</param>
739  /// <param name="result">When the method completes, contains the result of the Catmull-Rom interpolation.</param>
740  public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result)
741  {
742  float squared = amount * amount;
743  float cubed = amount * squared;
744 
745  result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) +
746  (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) +
747  ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed));
748 
749  result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) +
750  (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) +
751  ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed));
752 
753  result.Z = 0.5f * ((((2.0f * value2.Z) + ((-value1.Z + value3.Z) * amount)) +
754  (((((2.0f * value1.Z) - (5.0f * value2.Z)) + (4.0f * value3.Z)) - value4.Z) * squared)) +
755  ((((-value1.Z + (3.0f * value2.Z)) - (3.0f * value3.Z)) + value4.Z) * cubed));
756  }
757 
758  /// <summary>
759  /// Performs a Catmull-Rom interpolation using the specified positions.
760  /// </summary>
761  /// <param name="value1">The first position in the interpolation.</param>
762  /// <param name="value2">The second position in the interpolation.</param>
763  /// <param name="value3">The third position in the interpolation.</param>
764  /// <param name="value4">The fourth position in the interpolation.</param>
765  /// <param name="amount">Weighting factor.</param>
766  /// <returns>A vector that is the result of the Catmull-Rom interpolation.</returns>
767  public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount)
768  {
769  Vector3 result;
770  CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result);
771  return result;
772  }
773 
774  /// <summary>
775  /// Returns a vector containing the smallest components of the specified vectors.
776  /// </summary>
777  /// <param name="left">The first source vector.</param>
778  /// <param name="right">The second source vector.</param>
779  /// <param name="result">When the method completes, contains an new vector composed of the largest components of the source vectors.</param>
780  public static void Max(ref Vector3 left, ref Vector3 right, out Vector3 result)
781  {
782  result.X = (left.X > right.X) ? left.X : right.X;
783  result.Y = (left.Y > right.Y) ? left.Y : right.Y;
784  result.Z = (left.Z > right.Z) ? left.Z : right.Z;
785  }
786 
787  /// <summary>
788  /// Returns a vector containing the largest components of the specified vectors.
789  /// </summary>
790  /// <param name="left">The first source vector.</param>
791  /// <param name="right">The second source vector.</param>
792  /// <returns>A vector containing the largest components of the source vectors.</returns>
793  public static Vector3 Max(Vector3 left, Vector3 right)
794  {
795  Vector3 result;
796  Max(ref left, ref right, out result);
797  return result;
798  }
799 
800  /// <summary>
801  /// Returns a vector containing the smallest components of the specified vectors.
802  /// </summary>
803  /// <param name="left">The first source vector.</param>
804  /// <param name="right">The second source vector.</param>
805  /// <param name="result">When the method completes, contains an new vector composed of the smallest components of the source vectors.</param>
806  public static void Min(ref Vector3 left, ref Vector3 right, out Vector3 result)
807  {
808  result.X = (left.X < right.X) ? left.X : right.X;
809  result.Y = (left.Y < right.Y) ? left.Y : right.Y;
810  result.Z = (left.Z < right.Z) ? left.Z : right.Z;
811  }
812 
813  /// <summary>
814  /// Returns a vector containing the smallest components of the specified vectors.
815  /// </summary>
816  /// <param name="left">The first source vector.</param>
817  /// <param name="right">The second source vector.</param>
818  /// <returns>A vector containing the smallest components of the source vectors.</returns>
819  public static Vector3 Min(Vector3 left, Vector3 right)
820  {
821  Vector3 result;
822  Min(ref left, ref right, out result);
823  return result;
824  }
825 
826  /// <summary>
827  /// Projects a 3D vector from object space into screen space.
828  /// </summary>
829  /// <param name="vector">The vector to project.</param>
830  /// <param name="x">The X position of the viewport.</param>
831  /// <param name="y">The Y position of the viewport.</param>
832  /// <param name="width">The width of the viewport.</param>
833  /// <param name="height">The height of the viewport.</param>
834  /// <param name="minZ">The minimum depth of the viewport.</param>
835  /// <param name="maxZ">The maximum depth of the viewport.</param>
836  /// <param name="worldViewProjection">The combined world-view-projection matrix.</param>
837  /// <param name="result">When the method completes, contains the vector in screen space.</param>
838  public static void Project(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result)
839  {
840  Vector3 v = new Vector3();
841  TransformCoordinate(ref vector, ref worldViewProjection, out v);
842 
843  result = new Vector3(((1.0f + v.X) * 0.5f * width) + x, ((1.0f - v.Y) * 0.5f * height) + y, (v.Z * (maxZ - minZ)) + minZ);
844  }
845 
846  /// <summary>
847  /// Projects a 3D vector from object space into screen space.
848  /// </summary>
849  /// <param name="vector">The vector to project.</param>
850  /// <param name="x">The X position of the viewport.</param>
851  /// <param name="y">The Y position of the viewport.</param>
852  /// <param name="width">The width of the viewport.</param>
853  /// <param name="height">The height of the viewport.</param>
854  /// <param name="minZ">The minimum depth of the viewport.</param>
855  /// <param name="maxZ">The maximum depth of the viewport.</param>
856  /// <param name="worldViewProjection">The combined world-view-projection matrix.</param>
857  /// <returns>The vector in screen space.</returns>
858  public static Vector3 Project(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection)
859  {
860  Vector3 result;
861  Project(ref vector, x, y, width, height, minZ, maxZ, ref worldViewProjection, out result);
862  return result;
863  }
864 
865  /// <summary>
866  /// Projects a 3D vector from screen space into object space.
867  /// </summary>
868  /// <param name="vector">The vector to project.</param>
869  /// <param name="x">The X position of the viewport.</param>
870  /// <param name="y">The Y position of the viewport.</param>
871  /// <param name="width">The width of the viewport.</param>
872  /// <param name="height">The height of the viewport.</param>
873  /// <param name="minZ">The minimum depth of the viewport.</param>
874  /// <param name="maxZ">The maximum depth of the viewport.</param>
875  /// <param name="worldViewProjection">The combined world-view-projection matrix.</param>
876  /// <param name="result">When the method completes, contains the vector in object space.</param>
877  public static void Unproject(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result)
878  {
879  Vector3 v = new Vector3();
880  Matrix matrix = new Matrix();
881  Matrix.Invert(ref worldViewProjection, out matrix);
882 
883  v.X = (((vector.X - x) / width) * 2.0f) - 1.0f;
884  v.Y = -((((vector.Y - y) / height) * 2.0f) - 1.0f);
885  v.Z = (vector.Z - minZ) / (maxZ - minZ);
886 
887  TransformCoordinate(ref v, ref matrix, out result);
888  }
889 
890  /// <summary>
891  /// Projects a 3D vector from screen space into object space.
892  /// </summary>
893  /// <param name="vector">The vector to project.</param>
894  /// <param name="x">The X position of the viewport.</param>
895  /// <param name="y">The Y position of the viewport.</param>
896  /// <param name="width">The width of the viewport.</param>
897  /// <param name="height">The height of the viewport.</param>
898  /// <param name="minZ">The minimum depth of the viewport.</param>
899  /// <param name="maxZ">The maximum depth of the viewport.</param>
900  /// <param name="worldViewProjection">The combined world-view-projection matrix.</param>
901  /// <returns>The vector in object space.</returns>
902  public static Vector3 Unproject(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection)
903  {
904  Vector3 result;
905  Unproject(ref vector, x, y, width, height, minZ, maxZ, ref worldViewProjection, out result);
906  return result;
907  }
908 
909  /// <summary>
910  /// Returns the reflection of a vector off a surface that has the specified normal.
911  /// </summary>
912  /// <param name="vector">The source vector.</param>
913  /// <param name="normal">Normal of the surface.</param>
914  /// <param name="result">When the method completes, contains the reflected vector.</param>
915  /// <remarks>Reflect only gives the direction of a reflection off a surface, it does not determine
916  /// whether the original vector was close enough to the surface to hit it.</remarks>
917  public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result)
918  {
919  float dot = (vector.X * normal.X) + (vector.Y * normal.Y) + (vector.Z * normal.Z);
920 
921  result.X = vector.X - ((2.0f * dot) * normal.X);
922  result.Y = vector.Y - ((2.0f * dot) * normal.Y);
923  result.Z = vector.Z - ((2.0f * dot) * normal.Z);
924  }
925 
926  /// <summary>
927  /// Returns the reflection of a vector off a surface that has the specified normal.
928  /// </summary>
929  /// <param name="vector">The source vector.</param>
930  /// <param name="normal">Normal of the surface.</param>
931  /// <returns>The reflected vector.</returns>
932  /// <remarks>Reflect only gives the direction of a reflection off a surface, it does not determine
933  /// whether the original vector was close enough to the surface to hit it.</remarks>
934  public static Vector3 Reflect(Vector3 vector, Vector3 normal)
935  {
936  Vector3 result;
937  Reflect(ref vector, ref normal, out result);
938  return result;
939  }
940 
941  /// <summary>
942  /// Orthogonalizes a list of vectors.
943  /// </summary>
944  /// <param name="destination">The list of orthogonalized vectors.</param>
945  /// <param name="source">The list of vectors to orthogonalize.</param>
946  /// <remarks>
947  /// <para>Orthogonalization is the process of making all vectors orthogonal to each other. This
948  /// means that any given vector in the list will be orthogonal to any other given vector in the
949  /// list.</para>
950  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting vectors
951  /// tend to be numerically unstable. The numeric stability decreases according to the vectors
952  /// position in the list so that the first vector is the most stable and the last vector is the
953  /// least stable.</para>
954  /// </remarks>
955  /// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> or <paramref name="destination"/> is <c>null</c>.</exception>
956  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination"/> is shorter in length than <paramref name="source"/>.</exception>
957  public static void Orthogonalize(Vector3[] destination, params Vector3[] source)
958  {
959  //Uses the modified Gram-Schmidt process.
960  //q1 = m1
961  //q2 = m2 - ((q1 â‹… m2) / (q1 â‹… q1)) * q1
962  //q3 = m3 - ((q1 â‹… m3) / (q1 â‹… q1)) * q1 - ((q2 â‹… m3) / (q2 â‹… q2)) * q2
963  //q4 = m4 - ((q1 â‹… m4) / (q1 â‹… q1)) * q1 - ((q2 â‹… m4) / (q2 â‹… q2)) * q2 - ((q3 â‹… m4) / (q3 â‹… q3)) * q3
964  //q5 = ...
965 
966  if (source == null)
967  throw new ArgumentNullException("source");
968  if (destination == null)
969  throw new ArgumentNullException("destination");
970  if (destination.Length < source.Length)
971  throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array.");
972 
973  for (int i = 0; i < source.Length; ++i)
974  {
975  Vector3 newvector = source[i];
976 
977  for (int r = 0; r < i; ++r)
978  {
979  newvector -= (Vector3.Dot(destination[r], newvector) / Vector3.Dot(destination[r], destination[r])) * destination[r];
980  }
981 
982  destination[i] = newvector;
983  }
984  }
985 
986  /// <summary>
987  /// Orthonormalizes a list of vectors.
988  /// </summary>
989  /// <param name="destination">The list of orthonormalized vectors.</param>
990  /// <param name="source">The list of vectors to orthonormalize.</param>
991  /// <remarks>
992  /// <para>Orthonormalization is the process of making all vectors orthogonal to each
993  /// other and making all vectors of unit length. This means that any given vector will
994  /// be orthogonal to any other given vector in the list.</para>
995  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting vectors
996  /// tend to be numerically unstable. The numeric stability decreases according to the vectors
997  /// position in the list so that the first vector is the most stable and the last vector is the
998  /// least stable.</para>
999  /// </remarks>
1000  /// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> or <paramref name="destination"/> is <c>null</c>.</exception>
1001  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination"/> is shorter in length than <paramref name="source"/>.</exception>
1002  public static void Orthonormalize(Vector3[] destination, params Vector3[] source)
1003  {
1004  //Uses the modified Gram-Schmidt process.
1005  //Because we are making unit vectors, we can optimize the math for orthogonalization
1006  //and simplify the projection operation to remove the division.
1007  //q1 = m1 / |m1|
1008  //q2 = (m2 - (q1 â‹… m2) * q1) / |m2 - (q1 â‹… m2) * q1|
1009  //q3 = (m3 - (q1 â‹… m3) * q1 - (q2 â‹… m3) * q2) / |m3 - (q1 â‹… m3) * q1 - (q2 â‹… m3) * q2|
1010  //q4 = (m4 - (q1 â‹… m4) * q1 - (q2 â‹… m4) * q2 - (q3 â‹… m4) * q3) / |m4 - (q1 â‹… m4) * q1 - (q2 â‹… m4) * q2 - (q3 â‹… m4) * q3|
1011  //q5 = ...
1012 
1013  if (source == null)
1014  throw new ArgumentNullException("source");
1015  if (destination == null)
1016  throw new ArgumentNullException("destination");
1017  if (destination.Length < source.Length)
1018  throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array.");
1019 
1020  for (int i = 0; i < source.Length; ++i)
1021  {
1022  Vector3 newvector = source[i];
1023 
1024  for (int r = 0; r < i; ++r)
1025  {
1026  newvector -= Vector3.Dot(destination[r], newvector) * destination[r];
1027  }
1028 
1029  newvector.Normalize();
1030  destination[i] = newvector;
1031  }
1032  }
1033 
1034  /// <summary>
1035  /// Transforms a 3D vector by the given <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> rotation.
1036  /// </summary>
1037  /// <param name="vector">The vector to rotate.</param>
1038  /// <param name="rotation">The <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> rotation to apply.</param>
1039  /// <param name="result">When the method completes, contains the transformed <see cref="SiliconStudio.Core.Mathematics.Vector4"/>.</param>
1040  public static void Transform(ref Vector3 vector, ref Quaternion rotation, out Vector3 result)
1041  {
1042  float x = rotation.X + rotation.X;
1043  float y = rotation.Y + rotation.Y;
1044  float z = rotation.Z + rotation.Z;
1045  float wx = rotation.W * x;
1046  float wy = rotation.W * y;
1047  float wz = rotation.W * z;
1048  float xx = rotation.X * x;
1049  float xy = rotation.X * y;
1050  float xz = rotation.X * z;
1051  float yy = rotation.Y * y;
1052  float yz = rotation.Y * z;
1053  float zz = rotation.Z * z;
1054 
1055  result = new Vector3(
1056  ((vector.X * ((1.0f - yy) - zz)) + (vector.Y * (xy - wz))) + (vector.Z * (xz + wy)),
1057  ((vector.X * (xy + wz)) + (vector.Y * ((1.0f - xx) - zz))) + (vector.Z * (yz - wx)),
1058  ((vector.X * (xz - wy)) + (vector.Y * (yz + wx))) + (vector.Z * ((1.0f - xx) - yy)));
1059  }
1060 
1061  /// <summary>
1062  /// Transforms a 3D vector by the given <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> rotation.
1063  /// </summary>
1064  /// <param name="vector">The vector to rotate.</param>
1065  /// <param name="rotation">The <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> rotation to apply.</param>
1066  /// <returns>The transformed <see cref="SiliconStudio.Core.Mathematics.Vector4"/>.</returns>
1067  public static Vector3 Transform(Vector3 vector, Quaternion rotation)
1068  {
1069  Vector3 result;
1070  Transform(ref vector, ref rotation, out result);
1071  return result;
1072  }
1073 
1074  /// <summary>
1075  /// Transforms an array of vectors by the given <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> rotation.
1076  /// </summary>
1077  /// <param name="source">The array of vectors to transform.</param>
1078  /// <param name="rotation">The <see cref="SiliconStudio.Core.Mathematics.Quaternion"/> rotation to apply.</param>
1079  /// <param name="destination">The array for which the transformed vectors are stored.
1080  /// This array may be the same array as <paramref name="source"/>.</param>
1081  /// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> or <paramref name="destination"/> is <c>null</c>.</exception>
1082  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination"/> is shorter in length than <paramref name="source"/>.</exception>
1083  public static void Transform(Vector3[] source, ref Quaternion rotation, Vector3[] destination)
1084  {
1085  if (source == null)
1086  throw new ArgumentNullException("source");
1087  if (destination == null)
1088  throw new ArgumentNullException("destination");
1089  if (destination.Length < source.Length)
1090  throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array.");
1091 
1092  float x = rotation.X + rotation.X;
1093  float y = rotation.Y + rotation.Y;
1094  float z = rotation.Z + rotation.Z;
1095  float wx = rotation.W * x;
1096  float wy = rotation.W * y;
1097  float wz = rotation.W * z;
1098  float xx = rotation.X * x;
1099  float xy = rotation.X * y;
1100  float xz = rotation.X * z;
1101  float yy = rotation.Y * y;
1102  float yz = rotation.Y * z;
1103  float zz = rotation.Z * z;
1104 
1105  float num1 = ((1.0f - yy) - zz);
1106  float num2 = (xy - wz);
1107  float num3 = (xz + wy);
1108  float num4 = (xy + wz);
1109  float num5 = ((1.0f - xx) - zz);
1110  float num6 = (yz - wx);
1111  float num7 = (xz - wy);
1112  float num8 = (yz + wx);
1113  float num9 = ((1.0f - xx) - yy);
1114 
1115  for (int i = 0; i < source.Length; ++i)
1116  {
1117  destination[i] = new Vector3(
1118  ((source[i].X * num1) + (source[i].Y * num2)) + (source[i].Z * num3),
1119  ((source[i].X * num4) + (source[i].Y * num5)) + (source[i].Z * num6),
1120  ((source[i].X * num7) + (source[i].Y * num8)) + (source[i].Z * num9));
1121  }
1122  }
1123 
1124  /// <summary>
1125  /// Transforms a 3D vector by the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1126  /// </summary>
1127  /// <param name="vector">The source vector.</param>
1128  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1129  /// <param name="result">When the method completes, contains the transformed <see cref="SiliconStudio.Core.Mathematics.Vector4"/>.</param>
1130  public static void Transform(ref Vector3 vector, ref Matrix transform, out Vector4 result)
1131  {
1132  result = new Vector4(
1133  (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + transform.M41,
1134  (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + transform.M42,
1135  (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + transform.M43,
1136  (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + transform.M44);
1137  }
1138 
1139  /// <summary>
1140  /// Transforms a 3D vector by the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1141  /// </summary>
1142  /// <param name="vector">The source vector.</param>
1143  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1144  /// <returns>The transformed <see cref="SiliconStudio.Core.Mathematics.Vector4"/>.</returns>
1145  public static Vector4 Transform(Vector3 vector, Matrix transform)
1146  {
1147  Vector4 result;
1148  Transform(ref vector, ref transform, out result);
1149  return result;
1150  }
1151 
1152  /// <summary>
1153  /// Transforms an array of 3D vectors by the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1154  /// </summary>
1155  /// <param name="source">The array of vectors to transform.</param>
1156  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1157  /// <param name="destination">The array for which the transformed vectors are stored.</param>
1158  /// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> or <paramref name="destination"/> is <c>null</c>.</exception>
1159  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination"/> is shorter in length than <paramref name="source"/>.</exception>
1160  public static void Transform(Vector3[] source, ref Matrix transform, Vector4[] destination)
1161  {
1162  if (source == null)
1163  throw new ArgumentNullException("source");
1164  if (destination == null)
1165  throw new ArgumentNullException("destination");
1166  if (destination.Length < source.Length)
1167  throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array.");
1168 
1169  for (int i = 0; i < source.Length; ++i)
1170  {
1171  Transform(ref source[i], ref transform, out destination[i]);
1172  }
1173  }
1174 
1175  /// <summary>
1176  /// Performs a coordinate transformation using the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1177  /// </summary>
1178  /// <param name="coordinate">The coordinate vector to transform.</param>
1179  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1180  /// <param name="result">When the method completes, contains the transformed coordinates.</param>
1181  /// <remarks>
1182  /// A coordinate transform performs the transformation with the assumption that the w component
1183  /// is one. The four dimensional vector obtained from the transformation operation has each
1184  /// component in the vector divided by the w component. This forces the wcomponent to be one and
1185  /// therefore makes the vector homogeneous. The homogeneous vector is often prefered when working
1186  /// with coordinates as the w component can safely be ignored.
1187  /// </remarks>
1188  public static void TransformCoordinate(ref Vector3 coordinate, ref Matrix transform, out Vector3 result)
1189  {
1190  Vector4 vector = new Vector4();
1191  vector.X = (coordinate.X * transform.M11) + (coordinate.Y * transform.M21) + (coordinate.Z * transform.M31) + transform.M41;
1192  vector.Y = (coordinate.X * transform.M12) + (coordinate.Y * transform.M22) + (coordinate.Z * transform.M32) + transform.M42;
1193  vector.Z = (coordinate.X * transform.M13) + (coordinate.Y * transform.M23) + (coordinate.Z * transform.M33) + transform.M43;
1194  vector.W = 1f / ((coordinate.X * transform.M14) + (coordinate.Y * transform.M24) + (coordinate.Z * transform.M34) + transform.M44);
1195 
1196  result = new Vector3(vector.X * vector.W, vector.Y * vector.W, vector.Z * vector.W);
1197  }
1198 
1199  /// <summary>
1200  /// Performs a coordinate transformation using the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1201  /// </summary>
1202  /// <param name="coordinate">The coordinate vector to transform.</param>
1203  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1204  /// <returns>The transformed coordinates.</returns>
1205  /// <remarks>
1206  /// A coordinate transform performs the transformation with the assumption that the w component
1207  /// is one. The four dimensional vector obtained from the transformation operation has each
1208  /// component in the vector divided by the w component. This forces the wcomponent to be one and
1209  /// therefore makes the vector homogeneous. The homogeneous vector is often prefered when working
1210  /// with coordinates as the w component can safely be ignored.
1211  /// </remarks>
1212  public static Vector3 TransformCoordinate(Vector3 coordinate, Matrix transform)
1213  {
1214  Vector3 result;
1215  TransformCoordinate(ref coordinate, ref transform, out result);
1216  return result;
1217  }
1218 
1219  /// <summary>
1220  /// Performs a coordinate transformation on an array of vectors using the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1221  /// </summary>
1222  /// <param name="source">The array of coordinate vectors to trasnform.</param>
1223  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1224  /// <param name="destination">The array for which the transformed vectors are stored.
1225  /// This array may be the same array as <paramref name="source"/>.</param>
1226  /// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> or <paramref name="destination"/> is <c>null</c>.</exception>
1227  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination"/> is shorter in length than <paramref name="source"/>.</exception>
1228  /// <remarks>
1229  /// A coordinate transform performs the transformation with the assumption that the w component
1230  /// is one. The four dimensional vector obtained from the transformation operation has each
1231  /// component in the vector divided by the w component. This forces the wcomponent to be one and
1232  /// therefore makes the vector homogeneous. The homogeneous vector is often prefered when working
1233  /// with coordinates as the w component can safely be ignored.
1234  /// </remarks>
1235  public static void TransformCoordinate(Vector3[] source, ref Matrix transform, Vector3[] destination)
1236  {
1237  if (source == null)
1238  throw new ArgumentNullException("source");
1239  if (destination == null)
1240  throw new ArgumentNullException("destination");
1241  if (destination.Length < source.Length)
1242  throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array.");
1243 
1244  for (int i = 0; i < source.Length; ++i)
1245  {
1246  TransformCoordinate(ref source[i], ref transform, out destination[i]);
1247  }
1248  }
1249 
1250  /// <summary>
1251  /// Performs a normal transformation using the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1252  /// </summary>
1253  /// <param name="normal">The normal vector to transform.</param>
1254  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1255  /// <param name="result">When the method completes, contains the transformed normal.</param>
1256  /// <remarks>
1257  /// A normal transform performs the transformation with the assumption that the w component
1258  /// is zero. This causes the fourth row and fourth collumn of the matrix to be unused. The
1259  /// end result is a vector that is not translated, but all other transformation properties
1260  /// apply. This is often prefered for normal vectors as normals purely represent direction
1261  /// rather than location because normal vectors should not be translated.
1262  /// </remarks>
1263  public static void TransformNormal(ref Vector3 normal, ref Matrix transform, out Vector3 result)
1264  {
1265  result = new Vector3(
1266  (normal.X * transform.M11) + (normal.Y * transform.M21) + (normal.Z * transform.M31),
1267  (normal.X * transform.M12) + (normal.Y * transform.M22) + (normal.Z * transform.M32),
1268  (normal.X * transform.M13) + (normal.Y * transform.M23) + (normal.Z * transform.M33));
1269  }
1270 
1271  /// <summary>
1272  /// Performs a normal transformation using the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1273  /// </summary>
1274  /// <param name="normal">The normal vector to transform.</param>
1275  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1276  /// <returns>The transformed normal.</returns>
1277  /// <remarks>
1278  /// A normal transform performs the transformation with the assumption that the w component
1279  /// is zero. This causes the fourth row and fourth collumn of the matrix to be unused. The
1280  /// end result is a vector that is not translated, but all other transformation properties
1281  /// apply. This is often prefered for normal vectors as normals purely represent direction
1282  /// rather than location because normal vectors should not be translated.
1283  /// </remarks>
1284  public static Vector3 TransformNormal(Vector3 normal, Matrix transform)
1285  {
1286  Vector3 result;
1287  TransformNormal(ref normal, ref transform, out result);
1288  return result;
1289  }
1290 
1291  /// <summary>
1292  /// Performs a normal transformation on an array of vectors using the given <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
1293  /// </summary>
1294  /// <param name="source">The array of normal vectors to transform.</param>
1295  /// <param name="transform">The transformation <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.</param>
1296  /// <param name="destination">The array for which the transformed vectors are stored.
1297  /// This array may be the same array as <paramref name="source"/>.</param>
1298  /// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> or <paramref name="destination"/> is <c>null</c>.</exception>
1299  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination"/> is shorter in length than <paramref name="source"/>.</exception>
1300  /// <remarks>
1301  /// A normal transform performs the transformation with the assumption that the w component
1302  /// is zero. This causes the fourth row and fourth collumn of the matrix to be unused. The
1303  /// end result is a vector that is not translated, but all other transformation properties
1304  /// apply. This is often prefered for normal vectors as normals purely represent direction
1305  /// rather than location because normal vectors should not be translated.
1306  /// </remarks>
1307  public static void TransformNormal(Vector3[] source, ref Matrix transform, Vector3[] destination)
1308  {
1309  if (source == null)
1310  throw new ArgumentNullException("source");
1311  if (destination == null)
1312  throw new ArgumentNullException("destination");
1313  if (destination.Length < source.Length)
1314  throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array.");
1315 
1316  for (int i = 0; i < source.Length; ++i)
1317  {
1318  TransformNormal(ref source[i], ref transform, out destination[i]);
1319  }
1320  }
1321 
1322  /// <summary>
1323  /// Adds two vectors.
1324  /// </summary>
1325  /// <param name="left">The first vector to add.</param>
1326  /// <param name="right">The second vector to add.</param>
1327  /// <returns>The sum of the two vectors.</returns>
1328  public static Vector3 operator +(Vector3 left, Vector3 right)
1329  {
1330  return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
1331  }
1332 
1333  /// <summary>
1334  /// Assert a vector (return it unchanged).
1335  /// </summary>
1336  /// <param name="value">The vector to assert (unchange).</param>
1337  /// <returns>The asserted (unchanged) vector.</returns>
1338  public static Vector3 operator +(Vector3 value)
1339  {
1340  return value;
1341  }
1342 
1343  /// <summary>
1344  /// Subtracts two vectors.
1345  /// </summary>
1346  /// <param name="left">The first vector to subtract.</param>
1347  /// <param name="right">The second vector to subtract.</param>
1348  /// <returns>The difference of the two vectors.</returns>
1349  public static Vector3 operator -(Vector3 left, Vector3 right)
1350  {
1351  return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
1352  }
1353 
1354  /// <summary>
1355  /// Modulates a vector with another by performing component-wise multiplication.
1356  /// </summary>
1357  /// <param name="left">The first vector to multiply.</param>
1358  /// <param name="right">The second vector to multiply.</param>
1359  /// <returns>The multiplication of the two vectors.</returns>
1360  public static Vector3 operator *(Vector3 left, Vector3 right)
1361  {
1362  return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
1363  }
1364 
1365  /// <summary>
1366  /// Reverses the direction of a given vector.
1367  /// </summary>
1368  /// <param name="value">The vector to negate.</param>
1369  /// <returns>A vector facing in the opposite direction.</returns>
1370  public static Vector3 operator -(Vector3 value)
1371  {
1372  return new Vector3(-value.X, -value.Y, -value.Z);
1373  }
1374 
1375  /// <summary>
1376  /// Scales a vector by the given value.
1377  /// </summary>
1378  /// <param name="value">The vector to scale.</param>
1379  /// <param name="scale">The amount by which to scale the vector.</param>
1380  /// <returns>The scaled vector.</returns>
1381  public static Vector3 operator *(float scale, Vector3 value)
1382  {
1383  return new Vector3(value.X * scale, value.Y * scale, value.Z * scale);
1384  }
1385 
1386  /// <summary>
1387  /// Scales a vector by the given value.
1388  /// </summary>
1389  /// <param name="value">The vector to scale.</param>
1390  /// <param name="scale">The amount by which to scale the vector.</param>
1391  /// <returns>The scaled vector.</returns>
1392  public static Vector3 operator *(Vector3 value, float scale)
1393  {
1394  return new Vector3(value.X * scale, value.Y * scale, value.Z * scale);
1395  }
1396 
1397  /// <summary>
1398  /// Scales a vector by the given value.
1399  /// </summary>
1400  /// <param name="value">The vector to scale.</param>
1401  /// <param name="scale">The amount by which to scale the vector.</param>
1402  /// <returns>The scaled vector.</returns>
1403  public static Vector3 operator /(Vector3 value, float scale)
1404  {
1405  return new Vector3(value.X / scale, value.Y / scale, value.Z / scale);
1406  }
1407 
1408  /// <summary>
1409  /// Tests for equality between two objects.
1410  /// </summary>
1411  /// <param name="left">The first value to compare.</param>
1412  /// <param name="right">The second value to compare.</param>
1413  /// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
1414  public static bool operator ==(Vector3 left, Vector3 right)
1415  {
1416  return left.Equals(right);
1417  }
1418 
1419  /// <summary>
1420  /// Tests for inequality between two objects.
1421  /// </summary>
1422  /// <param name="left">The first value to compare.</param>
1423  /// <param name="right">The second value to compare.</param>
1424  /// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
1425  public static bool operator !=(Vector3 left, Vector3 right)
1426  {
1427  return !left.Equals(right);
1428  }
1429 
1430  /// <summary>
1431  /// Performs an explicit conversion from <see cref="SiliconStudio.Core.Mathematics.Vector3"/> to <see cref="SiliconStudio.Core.Mathematics.Vector2"/>.
1432  /// </summary>
1433  /// <param name="value">The value.</param>
1434  /// <returns>The result of the conversion.</returns>
1435  public static explicit operator Vector2(Vector3 value)
1436  {
1437  return new Vector2(value.X, value.Y);
1438  }
1439 
1440  /// <summary>
1441  /// Performs an explicit conversion from <see cref="SiliconStudio.Core.Mathematics.Vector3"/> to <see cref="SiliconStudio.Core.Mathematics.Vector4"/>.
1442  /// </summary>
1443  /// <param name="value">The value.</param>
1444  /// <returns>The result of the conversion.</returns>
1445  public static explicit operator Vector4(Vector3 value)
1446  {
1447  return new Vector4(value, 0.0f);
1448  }
1449 
1450  /// <summary>
1451  /// Tests whether one 3D vector is near another 3D vector.
1452  /// </summary>
1453  /// <param name="left">The left vector.</param>
1454  /// <param name="right">The right vector.</param>
1455  /// <param name="epsilon">The epsilon.</param>
1456  /// <returns><c>true</c> if left and right are near another 3D, <c>false</c> otherwise</returns>
1457  public static bool NearEqual(Vector3 left, Vector3 right, Vector3 epsilon)
1458  {
1459  return NearEqual(ref left, ref right, ref epsilon);
1460  }
1461 
1462  /// <summary>
1463  /// Tests whether one 3D vector is near another 3D vector.
1464  /// </summary>
1465  /// <param name="left">The left vector.</param>
1466  /// <param name="right">The right vector.</param>
1467  /// <param name="epsilon">The epsilon.</param>
1468  /// <returns><c>true</c> if left and right are near another 3D, <c>false</c> otherwise</returns>
1469  public static bool NearEqual(ref Vector3 left, ref Vector3 right, ref Vector3 epsilon)
1470  {
1471  return MathUtil.WithinEpsilon(left.X, right.X, epsilon.X) &&
1472  MathUtil.WithinEpsilon(left.Y, right.Y, epsilon.Y) &&
1473  MathUtil.WithinEpsilon(left.Z, right.Z, epsilon.Z);
1474  }
1475 
1476  /// <summary>
1477  /// Returns a <see cref="System.String"/> that represents this instance.
1478  /// </summary>
1479  /// <returns>
1480  /// A <see cref="System.String"/> that represents this instance.
1481  /// </returns>
1482  public override string ToString()
1483  {
1484  return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X, Y, Z);
1485  }
1486 
1487  /// <summary>
1488  /// Returns a <see cref="System.String"/> that represents this instance.
1489  /// </summary>
1490  /// <param name="format">The format.</param>
1491  /// <returns>
1492  /// A <see cref="System.String"/> that represents this instance.
1493  /// </returns>
1494  public string ToString(string format)
1495  {
1496  if (format == null)
1497  return ToString();
1498 
1499  return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X.ToString(format, CultureInfo.CurrentCulture),
1500  Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture));
1501  }
1502 
1503  /// <summary>
1504  /// Returns a <see cref="System.String"/> that represents this instance.
1505  /// </summary>
1506  /// <param name="formatProvider">The format provider.</param>
1507  /// <returns>
1508  /// A <see cref="System.String"/> that represents this instance.
1509  /// </returns>
1510  public string ToString(IFormatProvider formatProvider)
1511  {
1512  return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X, Y, Z);
1513  }
1514 
1515  /// <summary>
1516  /// Returns a <see cref="System.String"/> that represents this instance.
1517  /// </summary>
1518  /// <param name="format">The format.</param>
1519  /// <param name="formatProvider">The format provider.</param>
1520  /// <returns>
1521  /// A <see cref="System.String"/> that represents this instance.
1522  /// </returns>
1523  public string ToString(string format, IFormatProvider formatProvider)
1524  {
1525  if (format == null)
1526  return ToString(formatProvider);
1527 
1528  return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X.ToString(format, formatProvider),
1529  Y.ToString(format, formatProvider), Z.ToString(format, formatProvider));
1530  }
1531 
1532  /// <summary>
1533  /// Returns a hash code for this instance.
1534  /// </summary>
1535  /// <returns>
1536  /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
1537  /// </returns>
1538  public override int GetHashCode()
1539  {
1540  return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode();
1541  }
1542 
1543  /// <summary>
1544  /// Determines whether the specified <see cref="SiliconStudio.Core.Mathematics.Vector3"/> is equal to this instance.
1545  /// </summary>
1546  /// <param name="other">The <see cref="SiliconStudio.Core.Mathematics.Vector3"/> to compare with this instance.</param>
1547  /// <returns>
1548  /// <c>true</c> if the specified <see cref="SiliconStudio.Core.Mathematics.Vector3"/> is equal to this instance; otherwise, <c>false</c>.
1549  /// </returns>
1550  public bool Equals(Vector3 other)
1551  {
1552  return ((float)Math.Abs(other.X - X) < MathUtil.ZeroTolerance &&
1553  (float)Math.Abs(other.Y - Y) < MathUtil.ZeroTolerance &&
1554  (float)Math.Abs(other.Z - Z) < MathUtil.ZeroTolerance);
1555  }
1556 
1557  /// <summary>
1558  /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
1559  /// </summary>
1560  /// <param name="value">The <see cref="System.Object"/> to compare with this instance.</param>
1561  /// <returns>
1562  /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
1563  /// </returns>
1564  public override bool Equals(object value)
1565  {
1566  if (value == null)
1567  return false;
1568 
1569  if (value.GetType() != GetType())
1570  return false;
1571 
1572  return Equals((Vector3)value);
1573  }
1574 #if WPFInterop
1575  /// <summary>
1576  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Vector3"/> to <see cref="System.Windows.Media.Media3D.Vector3D"/>.
1577  /// </summary>
1578  /// <param name="value">The value.</param>
1579  /// <returns>The result of the conversion.</returns>
1580  public static implicit operator System.Windows.Media.Media3D.Vector3D(Vector3 value)
1581  {
1582  return new System.Windows.Media.Media3D.Vector3D(value.X, value.Y, value.Z);
1583  }
1584 
1585  /// <summary>
1586  /// Performs an explicit conversion from <see cref="System.Windows.Media.Media3D.Vector3D"/> to <see cref="SiliconStudio.Core.Mathematics.Vector3"/>.
1587  /// </summary>
1588  /// <param name="value">The value.</param>
1589  /// <returns>The result of the conversion.</returns>
1590  public static explicit operator Vector3(System.Windows.Media.Media3D.Vector3D value)
1591  {
1592  return new Vector3((float)value.X, (float)value.Y, (float)value.Z);
1593  }
1594 #endif
1595 
1596 #if XnaInterop
1597  /// <summary>
1598  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Vector3"/> to <see cref="Microsoft.Xna.Framework.Vector3"/>.
1599  /// </summary>
1600  /// <param name="value">The value.</param>
1601  /// <returns>The result of the conversion.</returns>
1602  public static implicit operator Microsoft.Xna.Framework.Vector3(Vector3 value)
1603  {
1604  return new Microsoft.Xna.Framework.Vector3(value.X, value.Y, value.Z);
1605  }
1606 
1607  /// <summary>
1608  /// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Vector3"/> to <see cref="SiliconStudio.Core.Mathematics.Vector3"/>.
1609  /// </summary>
1610  /// <param name="value">The value.</param>
1611  /// <returns>The result of the conversion.</returns>
1612  public static implicit operator Vector3(Microsoft.Xna.Framework.Vector3 value)
1613  {
1614  return new Vector3(value.X, value.Y, value.Z);
1615  }
1616 #endif
1617  }
1618 }
static void Lerp(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result)
Performs a linear interpolation between two vectors.
Definition: Vector3.cs:635
static Vector3 Clamp(Vector3 value, Vector3 min, Vector3 max)
Restricts a value to be within a specified range.
Definition: Vector3.cs:463
static void Cross(ref Vector3 left, ref Vector3 right, out Vector3 result)
Calculates the cross product of two vectors.
Definition: Vector3.cs:476
static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount)
Performs a Catmull-Rom interpolation using the specified positions.
Definition: Vector3.cs:767
static void Max(ref Vector3 left, ref Vector3 right, out Vector3 result)
Returns a vector containing the smallest components of the specified vectors.
Definition: Vector3.cs:780
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
FbxDouble3 operator*(double factor, FbxDouble3 vector)
float Y
The Y component of the vector.
Definition: Vector3.cs:84
float W
The W component of the vector.
Definition: Vector4.cs:101
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
static void Dot(ref Vector3 left, ref Vector3 right, out float result)
Calculates the dot product of two vectors.
Definition: Vector3.cs:585
static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result)
Performs a Hermite spline interpolation.
Definition: Vector3.cs:701
static Vector3 Unproject(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection)
Projects a 3D vector from screen space into object space.
Definition: Vector3.cs:902
static Vector3 Modulate(Vector3 left, Vector3 right)
Modulates a vector with another by performing component-wise multiplication.
Definition: Vector3.cs:331
static Vector3 TransformNormal(Vector3 normal, Matrix transform)
Performs a normal transformation using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1284
static float Dot(Vector3 left, Vector3 right)
Calculates the dot product of two vectors.
Definition: Vector3.cs:596
float X
The X component of the vector.
Definition: Vector4.cs:83
static Vector3 Divide(Vector3 value, float scale)
Scales a vector by the given value.
Definition: Vector3.cs:353
static void Orthogonalize(Vector3[] destination, params Vector3[] source)
Orthogonalizes a list of vectors.
Definition: Vector3.cs:957
float[] ToArray()
Creates an array containing the elements of the vector.
Definition: Vector3.cs:243
static Vector3 Negate(Vector3 value)
Reverses the direction of a given vector.
Definition: Vector3.cs:395
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
static float Distance(Vector3 value1, Vector3 value2)
Calculates the distance between two vectors.
Definition: Vector3.cs:526
string ToString(IFormatProvider formatProvider)
Returns a System.String that represents this instance.
Definition: Vector3.cs:1510
string ToString(string format)
Returns a System.String that represents this instance.
Definition: Vector3.cs:1494
float X
The X component of the vector.
Definition: Vector3.cs:78
static void Subtract(ref Vector3 left, ref Vector3 right, out Vector3 result)
Subtracts two vectors.
Definition: Vector3.cs:276
static void Clamp(ref Vector3 value, ref Vector3 min, ref Vector3 max, out Vector3 result)
Restricts a value to be within a specified range.
Definition: Vector3.cs:439
const float ZeroTolerance
The value for which all absolute numbers smaller than are considered equal to zero.
Definition: MathUtil.cs:38
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
float Length()
Calculates the length of the vector.
Definition: Vector3.cs:195
static void Orthonormalize(Vector3[] destination, params Vector3[] source)
Orthonormalizes a list of vectors.
Definition: Vector3.cs:1002
static Vector3 Subtract(Vector3 left, Vector3 right)
Subtracts two vectors.
Definition: Vector3.cs:287
static void Transform(Vector3[] source, ref Quaternion rotation, Vector3[] destination)
Transforms an array of vectors by the given SiliconStudio.Core.Mathematics.Quaternion rotation...
Definition: Vector3.cs:1083
static void Demodulate(ref Vector3 left, ref Vector3 right, out Vector3 result)
Demodulates a vector with another by performing component-wise division.
Definition: Vector3.cs:364
static void Min(ref Vector3 left, ref Vector3 right, out Vector3 result)
Returns a vector containing the smallest components of the specified vectors.
Definition: Vector3.cs:806
bool Equals(Vector3 other)
Determines whether the specified SiliconStudio.Core.Mathematics.Vector3 is equal to this instance...
Definition: Vector3.cs:1550
static void Transform(ref Vector3 vector, ref Matrix transform, out Vector4 result)
Transforms a 3D vector by the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1130
static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount)
Performs a Hermite spline interpolation.
Definition: Vector3.cs:724
static void Unproject(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result)
Projects a 3D vector from screen space into object space.
Definition: Vector3.cs:877
static void Divide(ref Vector3 value, float scale, out Vector3 result)
Scales a vector by the given value.
Definition: Vector3.cs:342
void Pow(float exponent)
Raises the exponent for each components.
Definition: Vector3.cs:232
static bool WithinEpsilon(float a, float b, float epsilon)
Checks if a - b are almost equals within a float epsilon.
Definition: MathUtil.cs:137
static void TransformNormal(ref Vector3 normal, ref Matrix transform, out Vector3 result)
Performs a normal transformation using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1263
static float DistanceSquared(Vector3 value1, Vector3 value2)
Calculates the squared distance between two vectors.
Definition: Vector3.cs:570
static Vector3 Project(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection)
Projects a 3D vector from object space into screen space.
Definition: Vector3.cs:858
Vector3(Vector2 value, float z)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Vector3 struct.
Definition: Vector3.cs:121
override string ToString()
Returns a System.String that represents this instance.
Definition: Vector3.cs:1482
static Vector3 SmoothStep(Vector3 start, Vector3 end, float amount)
Performs a cubic interpolation between two vectors.
Definition: Vector3.cs:685
static Vector3 Lerp(Vector3 start, Vector3 end, float amount)
Performs a linear interpolation between two vectors.
Definition: Vector3.cs:654
static void Negate(ref Vector3 value, out Vector3 result)
Reverses the direction of a given vector.
Definition: Vector3.cs:385
Represents a four dimensional mathematical vector.
Definition: Vector4.cs:42
static Vector4 Transform(Vector3 vector, Matrix transform)
Transforms a 3D vector by the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1145
static void Add(ref Vector3 left, ref Vector3 right, out Vector3 result)
Adds two vectors.
Definition: Vector3.cs:254
override int GetHashCode()
Returns a hash code for this instance.
Definition: Vector3.cs:1538
Represents a four dimensional mathematical quaternion.
Definition: Quaternion.cs:45
static Vector3 TransformCoordinate(Vector3 coordinate, Matrix transform)
Performs a coordinate transformation using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1212
static void Distance(ref Vector3 value1, ref Vector3 value2, out float result)
Calculates the distance between two vectors.
Definition: Vector3.cs:507
Vector3(float x, float y, float z)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Vector3 struct.
Definition: Vector3.cs:109
static Vector3 Min(Vector3 left, Vector3 right)
Returns a vector containing the smallest components of the specified vectors.
Definition: Vector3.cs:819
static void Transform(ref Vector3 vector, ref Quaternion rotation, out Vector3 result)
Transforms a 3D vector by the given SiliconStudio.Core.Mathematics.Quaternion rotation.
Definition: Vector3.cs:1040
EnvDTE.Project Project
static bool NearEqual(Vector3 left, Vector3 right, Vector3 epsilon)
Tests whether one 3D vector is near another 3D vector.
Definition: Vector3.cs:1457
float Length()
Calculates the length of the vector.
Definition: Vector4.cs:227
static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result)
Performs a Catmull-Rom interpolation using the specified positions.
Definition: Vector3.cs:740
float LengthSquared()
Calculates the squared length of the vector.
Definition: Vector3.cs:208
static void Transform(Vector3[] source, ref Matrix transform, Vector4[] destination)
Transforms an array of 3D vectors by the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1160
static void Multiply(ref Vector3 value, float scale, out Vector3 result)
Scales a vector by the given value.
Definition: Vector3.cs:298
static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result)
Returns the reflection of a vector off a surface that has the specified normal.
Definition: Vector3.cs:917
static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2)
Returns a SiliconStudio.Core.Mathematics.Vector3 containing the 3D Cartesian coordinates of a point s...
Definition: Vector3.cs:425
float Y
The Y component of the vector.
Definition: Vector4.cs:89
Vector3(float value)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Vector3 struct.
Definition: Vector3.cs:96
static Vector3 Normalize(Vector3 value)
Converts the vector into a unit vector.
Definition: Vector3.cs:617
static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result)
Calculates the squared distance between two vectors.
Definition: Vector3.cs:548
Vector3(float[] values)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Vector3 struct.
Definition: Vector3.cs:134
static void Modulate(ref Vector3 left, ref Vector3 right, out Vector3 result)
Modulates a vector with another by performing component-wise multiplication.
Definition: Vector3.cs:320
string ToString(string format, IFormatProvider formatProvider)
Returns a System.String that represents this instance.
Definition: Vector3.cs:1523
static Vector3 Reflect(Vector3 vector, Vector3 normal)
Returns the reflection of a vector off a surface that has the specified normal.
Definition: Vector3.cs:934
SiliconStudio.Core.Mathematics.Vector3 Vector3
static Vector3 Transform(Vector3 vector, Quaternion rotation)
Transforms a 3D vector by the given SiliconStudio.Core.Mathematics.Quaternion rotation.
Definition: Vector3.cs:1067
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
float Z
The Z component of the vector.
Definition: Vector4.cs:95
override bool Equals(object value)
Determines whether the specified System.Object is equal to this instance.
Definition: Vector3.cs:1564
static void Project(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result)
Projects a 3D vector from object space into screen space.
Definition: Vector3.cs:838
static Vector3 Add(Vector3 left, Vector3 right)
Adds two vectors.
Definition: Vector3.cs:265
void Normalize()
Converts the vector into a unit vector.
Definition: Vector3.cs:216
float Z
The Z component of the vector.
Definition: Vector3.cs:90
static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result)
Returns a SiliconStudio.Core.Mathematics.Vector3 containing the 3D Cartesian coordinates of a point s...
Definition: Vector3.cs:409
static void TransformCoordinate(ref Vector3 coordinate, ref Matrix transform, out Vector3 result)
Performs a coordinate transformation using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1188
static bool NearEqual(ref Vector3 left, ref Vector3 right, ref Vector3 epsilon)
Tests whether one 3D vector is near another 3D vector.
Definition: Vector3.cs:1469
static Vector3 Cross(Vector3 left, Vector3 right)
Calculates the cross product of two vectors.
Definition: Vector3.cs:490
static void Normalize(ref Vector3 value, out Vector3 result)
Converts the vector into a unit vector.
Definition: Vector3.cs:606
static void SmoothStep(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result)
Performs a cubic interpolation between two vectors.
Definition: Vector3.cs:668
static Vector3 Multiply(Vector3 value, float scale)
Scales a vector by the given value.
Definition: Vector3.cs:309
static void TransformNormal(Vector3[] source, ref Matrix transform, Vector3[] destination)
Performs a normal transformation on an array of vectors using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1307
DataStyle
Specifies the style used for textual serialization when an array/list or a dictionary/map must be ser...
Definition: DataStyle.cs:9
static void TransformCoordinate(Vector3[] source, ref Matrix transform, Vector3[] destination)
Performs a coordinate transformation on an array of vectors using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1235
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t size_t z
Definition: DirectXTexP.h:191
static Vector3 Max(Vector3 left, Vector3 right)
Returns a vector containing the largest components of the specified vectors.
Definition: Vector3.cs:793
static Vector3 Demodulate(Vector3 left, Vector3 right)
Demodulates a vector with another by performing component-wise division.
Definition: Vector3.cs:375
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47