Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Matrix.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.Collections.Generic;
31 using System.Runtime.CompilerServices;
32 using System.Security;
33 using System.Text;
34 using System.Runtime.InteropServices;
35 using System.ComponentModel;
36 using System.Globalization;
37 using SiliconStudio.Core.Serialization;
38 
39 namespace SiliconStudio.Core.Mathematics
40 {
41  /// <summary>
42  /// Represents a 4x4 mathematical matrix.
43  /// </summary>
44  [DataContract("float4x4")]
45  [DataStyle(DataStyle.Compact)]
46  [StructLayout(LayoutKind.Sequential, Pack = 4)]
47  public struct Matrix : IEquatable<Matrix>, IFormattable
48  {
49 #if SILICONSTUDIO_PLATFORM_ANDROID
50  [DllImport(NativeLibrary.LibraryName, CallingConvention = NativeLibrary.CallConvention), SuppressUnmanagedCodeSecurity]
51  private static extern void NEON_Matrix4Mul(ref Matrix a, ref Matrix b, out Matrix output);
52 #endif
53 
54  /// <summary>
55  /// The size of the <see cref="SiliconStudio.Core.Mathematics.Matrix"/> type, in bytes.
56  /// </summary>
57  public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Matrix));
58 
59  /// <summary>
60  /// A <see cref="SiliconStudio.Core.Mathematics.Matrix"/> with all of its components set to zero.
61  /// </summary>
62  public static readonly Matrix Zero = new Matrix();
63 
64  /// <summary>
65  /// The identity <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
66  /// </summary>
67  public static readonly Matrix Identity = new Matrix() { M11 = 1.0f, M22 = 1.0f, M33 = 1.0f, M44 = 1.0f };
68 
69  /// <summary>
70  /// Value at row 1 column 1 of the matrix.
71  /// </summary>
72  public float M11;
73 
74  /// <summary>
75  /// Value at row 2 column 1 of the matrix.
76  /// </summary>
77  public float M21;
78 
79  /// <summary>
80  /// Value at row 3 column 1 of the matrix.
81  /// </summary>
82  public float M31;
83 
84  /// <summary>
85  /// Value at row 4 column 1 of the matrix.
86  /// </summary>
87  public float M41;
88 
89  /// <summary>
90  /// Value at row 1 column 2 of the matrix.
91  /// </summary>
92  public float M12;
93 
94  /// <summary>
95  /// Value at row 2 column 2 of the matrix.
96  /// </summary>
97  public float M22;
98 
99  /// <summary>
100  /// Value at row 3 column 2 of the matrix.
101  /// </summary>
102  public float M32;
103 
104  /// <summary>
105  /// Value at row 4 column 2 of the matrix.
106  /// </summary>
107  public float M42;
108 
109  /// <summary>
110  /// Value at row 1 column 3 of the matrix.
111  /// </summary>
112  public float M13;
113 
114  /// <summary>
115  /// Value at row 2 column 3 of the matrix.
116  /// </summary>
117  public float M23;
118 
119  /// <summary>
120  /// Value at row 3 column 3 of the matrix.
121  /// </summary>
122  public float M33;
123 
124  /// <summary>
125  /// Value at row 4 column 3 of the matrix.
126  /// </summary>
127  public float M43;
128 
129  /// <summary>
130  /// Value at row 1 column 4 of the matrix.
131  /// </summary>
132  public float M14;
133 
134  /// <summary>
135  /// Value at row 2 column 4 of the matrix.
136  /// </summary>
137  public float M24;
138 
139  /// <summary>
140  /// Value at row 3 column 4 of the matrix.
141  /// </summary>
142  public float M34;
143 
144  /// <summary>
145  /// Value at row 4 column 4 of the matrix.
146  /// </summary>
147  public float M44;
148 
149  /// <summary>
150  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Matrix"/> struct.
151  /// </summary>
152  /// <param name="value">The value that will be assigned to all components.</param>
153  public Matrix(float value)
154  {
155  M11 = M21 = M31 = M41 =
156  M12 = M22 = M32 = M42 =
157  M13 = M23 = M33 = M43 =
158  M14 = M24 = M34 = M44 = value;
159  }
160 
161  /// <summary>
162  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Matrix"/> struct.
163  /// </summary>
164  /// <param name="M11">The value to assign at row 1 column 1 of the matrix.</param>
165  /// <param name="M12">The value to assign at row 1 column 2 of the matrix.</param>
166  /// <param name="M13">The value to assign at row 1 column 3 of the matrix.</param>
167  /// <param name="M14">The value to assign at row 1 column 4 of the matrix.</param>
168  /// <param name="M21">The value to assign at row 2 column 1 of the matrix.</param>
169  /// <param name="M22">The value to assign at row 2 column 2 of the matrix.</param>
170  /// <param name="M23">The value to assign at row 2 column 3 of the matrix.</param>
171  /// <param name="M24">The value to assign at row 2 column 4 of the matrix.</param>
172  /// <param name="M31">The value to assign at row 3 column 1 of the matrix.</param>
173  /// <param name="M32">The value to assign at row 3 column 2 of the matrix.</param>
174  /// <param name="M33">The value to assign at row 3 column 3 of the matrix.</param>
175  /// <param name="M34">The value to assign at row 3 column 4 of the matrix.</param>
176  /// <param name="M41">The value to assign at row 4 column 1 of the matrix.</param>
177  /// <param name="M42">The value to assign at row 4 column 2 of the matrix.</param>
178  /// <param name="M43">The value to assign at row 4 column 3 of the matrix.</param>
179  /// <param name="M44">The value to assign at row 4 column 4 of the matrix.</param>
180  public Matrix(float M11, float M12, float M13, float M14,
181  float M21, float M22, float M23, float M24,
182  float M31, float M32, float M33, float M34,
183  float M41, float M42, float M43, float M44)
184  {
185  this.M11 = M11; this.M12 = M12; this.M13 = M13; this.M14 = M14;
186  this.M21 = M21; this.M22 = M22; this.M23 = M23; this.M24 = M24;
187  this.M31 = M31; this.M32 = M32; this.M33 = M33; this.M34 = M34;
188  this.M41 = M41; this.M42 = M42; this.M43 = M43; this.M44 = M44;
189  }
190 
191  /// <summary>
192  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.Matrix"/> struct.
193  /// </summary>
194  /// <param name="values">The values to assign to the components of the matrix. This must be an array with sixteen elements.</param>
195  /// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
196  /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than sixteen elements.</exception>
197  public Matrix(float[] values)
198  {
199  if (values == null)
200  throw new ArgumentNullException("values");
201  if (values.Length != 16)
202  throw new ArgumentOutOfRangeException("values", "There must be sixteen and only sixteen input values for Matrix.");
203 
204  M11 = values[0];
205  M12 = values[1];
206  M13 = values[2];
207  M14 = values[3];
208 
209  M21 = values[4];
210  M22 = values[5];
211  M23 = values[6];
212  M24 = values[7];
213 
214  M31 = values[8];
215  M32 = values[9];
216  M33 = values[10];
217  M34 = values[11];
218 
219  M41 = values[12];
220  M42 = values[13];
221  M43 = values[14];
222  M44 = values[15];
223  }
224 
225  /// <summary>
226  /// Gets or sets the first row in the matrix; that is M11, M12, M13, and M14.
227  /// </summary>
228  [DataMemberIgnore]
229  public Vector4 Row1
230  {
231  get { return new Vector4(M11, M12, M13, M14); }
232  set { M11 = value.X; M12 = value.Y; M13 = value.Z; M14 = value.W; }
233  }
234 
235  /// <summary>
236  /// Gets or sets the second row in the matrix; that is M21, M22, M23, and M24.
237  /// </summary>
238  [DataMemberIgnore]
239  public Vector4 Row2
240  {
241  get { return new Vector4(M21, M22, M23, M24); }
242  set { M21 = value.X; M22 = value.Y; M23 = value.Z; M24 = value.W; }
243  }
244 
245  /// <summary>
246  /// Gets or sets the third row in the matrix; that is M31, M32, M33, and M34.
247  /// </summary>
248  [DataMemberIgnore]
249  public Vector4 Row3
250  {
251  get { return new Vector4(M31, M32, M33, M34); }
252  set { M31 = value.X; M32 = value.Y; M33 = value.Z; M34 = value.W; }
253  }
254 
255  /// <summary>
256  /// Gets or sets the fourth row in the matrix; that is M41, M42, M43, and M44.
257  /// </summary>
258  [DataMemberIgnore]
259  public Vector4 Row4
260  {
261  get { return new Vector4(M41, M42, M43, M44); }
262  set { M41 = value.X; M42 = value.Y; M43 = value.Z; M44 = value.W; }
263  }
264 
265  /// <summary>
266  /// Gets or sets the first column in the matrix; that is M11, M21, M31, and M41.
267  /// </summary>
268  [DataMemberIgnore]
269  public Vector4 Column1
270  {
271  get { return new Vector4(M11, M21, M31, M41); }
272  set { M11 = value.X; M21 = value.Y; M31 = value.Z; M41 = value.W; }
273  }
274 
275  /// <summary>
276  /// Gets or sets the second column in the matrix; that is M12, M22, M32, and M42.
277  /// </summary>
278  [DataMemberIgnore]
279  public Vector4 Column2
280  {
281  get { return new Vector4(M12, M22, M32, M42); }
282  set { M12 = value.X; M22 = value.Y; M32 = value.Z; M42 = value.W; }
283  }
284 
285  /// <summary>
286  /// Gets or sets the third column in the matrix; that is M13, M23, M33, and M43.
287  /// </summary>
288  [DataMemberIgnore]
289  public Vector4 Column3
290  {
291  get { return new Vector4(M13, M23, M33, M43); }
292  set { M13 = value.X; M23 = value.Y; M33 = value.Z; M43 = value.W; }
293  }
294 
295  /// <summary>
296  /// Gets or sets the fourth column in the matrix; that is M14, M24, M34, and M44.
297  /// </summary>
298  [DataMemberIgnore]
299  public Vector4 Column4
300  {
301  get { return new Vector4(M14, M24, M34, M44); }
302  set { M14 = value.X; M24 = value.Y; M34 = value.Z; M44 = value.W; }
303  }
304 
305  /// <summary>
306  /// Gets or sets the translation of the matrix; that is M41, M42, and M43.
307  /// </summary>
308  [DataMemberIgnore]
309  public Vector3 TranslationVector
310  {
311  get { return new Vector3(M41, M42, M43); }
312  set { M41 = value.X; M42 = value.Y; M43 = value.Z; }
313  }
314 
315  /// <summary>
316  /// Gets or sets the scale of the matrix; that is M11, M22, and M33.
317  /// </summary>
318  [DataMemberIgnore]
319  public Vector3 ScaleVector
320  {
321  get { return new Vector3(M11, M22, M33); }
322  set { M11 = value.X; M22 = value.Y; M33 = value.Z; }
323  }
324 
325  /// <summary>
326  /// Gets a value indicating whether this instance is an identity matrix.
327  /// </summary>
328  /// <value>
329  /// <c>true</c> if this instance is an identity matrix; otherwise, <c>false</c>.
330  /// </value>
331  public bool IsIdentity
332  {
333  get { return this.Equals(Identity); }
334  }
335 
336  /// <summary>
337  /// Gets or sets the component at the specified index.
338  /// </summary>
339  /// <value>The value of the matrix component, depending on the index.</value>
340  /// <param name="index">The zero-based index of the component to access.</param>
341  /// <returns>The value of the component at the specified index.</returns>
342  /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 15].</exception>
343  public float this[int index]
344  {
345  get
346  {
347  switch (index)
348  {
349  case 0: return M11;
350  case 1: return M12;
351  case 2: return M13;
352  case 3: return M14;
353  case 4: return M21;
354  case 5: return M22;
355  case 6: return M23;
356  case 7: return M24;
357  case 8: return M31;
358  case 9: return M32;
359  case 10: return M33;
360  case 11: return M34;
361  case 12: return M41;
362  case 13: return M42;
363  case 14: return M43;
364  case 15: return M44;
365  }
366 
367  throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive.");
368  }
369 
370  set
371  {
372  switch (index)
373  {
374  case 0: M11 = value; break;
375  case 1: M12 = value; break;
376  case 2: M13 = value; break;
377  case 3: M14 = value; break;
378  case 4: M21 = value; break;
379  case 5: M22 = value; break;
380  case 6: M23 = value; break;
381  case 7: M24 = value; break;
382  case 8: M31 = value; break;
383  case 9: M32 = value; break;
384  case 10: M33 = value; break;
385  case 11: M34 = value; break;
386  case 12: M41 = value; break;
387  case 13: M42 = value; break;
388  case 14: M43 = value; break;
389  case 15: M44 = value; break;
390  default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive.");
391  }
392  }
393  }
394 
395  /// <summary>
396  /// Gets or sets the component at the specified index.
397  /// </summary>
398  /// <value>The value of the matrix component, depending on the index.</value>
399  /// <param name="row">The row of the matrix to access.</param>
400  /// <param name="column">The column of the matrix to access.</param>
401  /// <returns>The value of the component at the specified index.</returns>
402  /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="row"/> or <paramref name="column"/>is out of the range [0, 3].</exception>
403  public float this[int row, int column]
404  {
405  get
406  {
407  if (row < 0 || row > 3)
408  throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 3, inclusive.");
409  if (column < 0 || column > 3)
410  throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 3, inclusive.");
411 
412  return this[(row * 4) + column];
413  }
414 
415  set
416  {
417  if (row < 0 || row > 3)
418  throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 3, inclusive.");
419  if (column < 0 || column > 3)
420  throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 3, inclusive.");
421 
422  this[(row * 4) + column] = value;
423  }
424  }
425 
426  /// <summary>
427  /// Calculates the determinant of the matrix.
428  /// </summary>
429  /// <returns>The determinant of the matrix.</returns>
430  public float Determinant()
431  {
432  float temp1 = (M33 * M44) - (M34 * M43);
433  float temp2 = (M32 * M44) - (M34 * M42);
434  float temp3 = (M32 * M43) - (M33 * M42);
435  float temp4 = (M31 * M44) - (M34 * M41);
436  float temp5 = (M31 * M43) - (M33 * M41);
437  float temp6 = (M31 * M42) - (M32 * M41);
438 
439  return ((((M11 * (((M22 * temp1) - (M23 * temp2)) + (M24 * temp3))) - (M12 * (((M21 * temp1) -
440  (M23 * temp4)) + (M24 * temp5)))) + (M13 * (((M21 * temp2) - (M22 * temp4)) + (M24 * temp6)))) -
441  (M14 * (((M21 * temp3) - (M22 * temp5)) + (M23 * temp6))));
442  }
443 
444  /// <summary>
445  /// Inverts the matrix.
446  /// </summary>
447  public void Invert()
448  {
449  Invert(ref this, out this);
450  }
451 
452  /// <summary>
453  /// Transposes the matrix.
454  /// </summary>
455  public void Transpose()
456  {
457  Transpose(ref this, out this);
458  }
459 
460  /// <summary>
461  /// Orthogonalizes the specified matrix.
462  /// </summary>
463  /// <remarks>
464  /// <para>Orthogonalization is the process of making all rows orthogonal to each other. This
465  /// means that any given row in the matrix will be orthogonal to any other given row in the
466  /// matrix.</para>
467  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting matrix
468  /// tends to be numerically unstable. The numeric stability decreases according to the rows
469  /// so that the first row is the most stable and the last row is the least stable.</para>
470  /// <para>This operation is performed on the rows of the matrix rather than the columns.
471  /// If you wish for this operation to be performed on the columns, first transpose the
472  /// input and than transpose the output.</para>
473  /// </remarks>
474  public void Orthogonalize()
475  {
476  Orthogonalize(ref this, out this);
477  }
478 
479  /// <summary>
480  /// Orthonormalizes the specified matrix.
481  /// </summary>
482  /// <remarks>
483  /// <para>Orthonormalization is the process of making all rows and columns orthogonal to each
484  /// other and making all rows and columns of unit length. This means that any given row will
485  /// be orthogonal to any other given row and any given column will be orthogonal to any other
486  /// given column. Any given row will not be orthogonal to any given column. Every row and every
487  /// column will be of unit length.</para>
488  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting matrix
489  /// tends to be numerically unstable. The numeric stability decreases according to the rows
490  /// so that the first row is the most stable and the last row is the least stable.</para>
491  /// <para>This operation is performed on the rows of the matrix rather than the columns.
492  /// If you wish for this operation to be performed on the columns, first transpose the
493  /// input and than transpose the output.</para>
494  /// </remarks>
495  public void Orthonormalize()
496  {
497  Orthonormalize(ref this, out this);
498  }
499 
500  /// <summary>
501  /// Decomposes a matrix into an orthonormalized matrix Q and a right traingular matrix R.
502  /// </summary>
503  /// <param name="Q">When the method completes, contains the orthonormalized matrix of the decomposition.</param>
504  /// <param name="R">When the method completes, contains the right triangular matrix of the decomposition.</param>
505  public void DecomposeQR(out Matrix Q, out Matrix R)
506  {
507  Matrix temp = this;
508  temp.Transpose();
509  Orthonormalize(ref temp, out Q);
510  Q.Transpose();
511 
512  R = new Matrix();
513  R.M11 = Vector4.Dot(Q.Column1, Column1);
514  R.M12 = Vector4.Dot(Q.Column1, Column2);
515  R.M13 = Vector4.Dot(Q.Column1, Column3);
516  R.M14 = Vector4.Dot(Q.Column1, Column4);
517 
518  R.M22 = Vector4.Dot(Q.Column2, Column2);
519  R.M23 = Vector4.Dot(Q.Column2, Column3);
520  R.M24 = Vector4.Dot(Q.Column2, Column4);
521 
522  R.M33 = Vector4.Dot(Q.Column3, Column3);
523  R.M34 = Vector4.Dot(Q.Column3, Column4);
524 
525  R.M44 = Vector4.Dot(Q.Column4, Column4);
526  }
527 
528  /// <summary>
529  /// Decomposes a matrix into a lower triangular matrix L and an orthonormalized matrix Q.
530  /// </summary>
531  /// <param name="L">When the method completes, contains the lower triangular matrix of the decomposition.</param>
532  /// <param name="Q">When the method completes, contains the orthonormalized matrix of the decomposition.</param>
533  public void DecomposeLQ(out Matrix L, out Matrix Q)
534  {
535  Orthonormalize(ref this, out Q);
536 
537  L = new Matrix();
538  L.M11 = Vector4.Dot(Q.Row1, Row1);
539 
540  L.M21 = Vector4.Dot(Q.Row1, Row2);
541  L.M22 = Vector4.Dot(Q.Row2, Row2);
542 
543  L.M31 = Vector4.Dot(Q.Row1, Row3);
544  L.M32 = Vector4.Dot(Q.Row2, Row3);
545  L.M33 = Vector4.Dot(Q.Row3, Row3);
546 
547  L.M41 = Vector4.Dot(Q.Row1, Row4);
548  L.M42 = Vector4.Dot(Q.Row2, Row4);
549  L.M43 = Vector4.Dot(Q.Row3, Row4);
550  L.M44 = Vector4.Dot(Q.Row4, Row4);
551  }
552 
553  /// <summary>
554  /// Decomposes a rotation matrix with the specified yaw, pitch, roll
555  /// </summary>
556  /// <param name="yaw">The yaw.</param>
557  /// <param name="pitch">The pitch.</param>
558  /// <param name="roll">The roll.</param>
559  public void Decompose(out float yaw, out float pitch, out float roll)
560  {
561  pitch = (float)Math.Asin(-M32);
562  // Hardcoded constant - burn him, he's a witch
563  // double threshold = 0.001;
564  double test = Math.Cos(pitch);
565  if (test > MathUtil.ZeroTolerance)
566  {
567  roll = (float)Math.Atan2(M12, M22);
568  yaw = (float)Math.Atan2(M31, M33);
569  }
570  else
571  {
572  roll = (float)Math.Atan2(-M21, M11);
573  yaw = 0.0f;
574  }
575  }
576 
577  /// <summary>
578  /// Decomposes a rotation matrix with the specified X, Y and Z euler angles.
579  /// Matrix.RotationX(rotation.X) * Matrix.RotationY(rotation.Y) * Matrix.RotationZ(rotation.Z) should represent the same rotation.
580  /// </summary>
581  /// <param name="rotation">The vector containing the 3 rotations angles to be applied in order.</param>
582  public void DecomposeXYZ(out Vector3 rotation)
583  {
584  rotation.Y = (float)Math.Asin(-M13);
585  double test = Math.Cos(rotation.Y);
586  if (test > 1e-6f)
587  {
588  rotation.Z = (float)Math.Atan2(M12, M11);
589  rotation.X = (float)Math.Atan2(M23, M33);
590  }
591  else
592  {
593  rotation.Z = (float)Math.Atan2(-M21, M31);
594  rotation.X = 0.0f;
595  }
596  }
597 
598  /// <summary>
599  /// Decomposes a matrix into a scale, rotation, and translation.
600  /// </summary>
601  /// <param name="scale">When the method completes, contains the scaling component of the decomposed matrix.</param>
602  /// <param name="rotation">When the method completes, contains the rtoation component of the decomposed matrix.</param>
603  /// <param name="translation">When the method completes, contains the translation component of the decomposed matrix.</param>
604  /// <remarks>
605  /// This method is designed to decompose an SRT transformation matrix only.
606  /// </remarks>
607  public bool Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation)
608  {
609  //Source: Unknown
610  //References: http://www.gamedev.net/community/forums/topic.asp?topic_id=441695
611 
612  //Get the translation.
613  translation.X = this.M41;
614  translation.Y = this.M42;
615  translation.Z = this.M43;
616 
617  //Scaling is the length of the rows.
618  scale.X = (float)Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13));
619  scale.Y = (float)Math.Sqrt((M21 * M21) + (M22 * M22) + (M23 * M23));
620  scale.Z = (float)Math.Sqrt((M31 * M31) + (M32 * M32) + (M33 * M33));
621 
622  //If any of the scaling factors are zero, than the rotation matrix can not exist.
623  if (Math.Abs(scale.X) < MathUtil.ZeroTolerance ||
624  Math.Abs(scale.Y) < MathUtil.ZeroTolerance ||
625  Math.Abs(scale.Z) < MathUtil.ZeroTolerance)
626  {
627  rotation = Quaternion.Identity;
628  return false;
629  }
630 
631  //The rotation is the left over matrix after dividing out the scaling.
632  Matrix rotationmatrix = new Matrix();
633  rotationmatrix.M11 = M11 / scale.X;
634  rotationmatrix.M12 = M12 / scale.X;
635  rotationmatrix.M13 = M13 / scale.X;
636 
637  rotationmatrix.M21 = M21 / scale.Y;
638  rotationmatrix.M22 = M22 / scale.Y;
639  rotationmatrix.M23 = M23 / scale.Y;
640 
641  rotationmatrix.M31 = M31 / scale.Z;
642  rotationmatrix.M32 = M32 / scale.Z;
643  rotationmatrix.M33 = M33 / scale.Z;
644 
645  rotationmatrix.M44 = 1f;
646 
647  Quaternion.RotationMatrix(ref rotationmatrix, out rotation);
648  return true;
649  }
650 
651  /// <summary>
652  /// Exchanges two rows in the matrix.
653  /// </summary>
654  /// <param name="firstRow">The first row to exchange. This is an index of the row starting at zero.</param>
655  /// <param name="secondRow">The second row to exchange. This is an index of the row starting at zero.</param>
656  public void ExchangeRows(int firstRow, int secondRow)
657  {
658  if (firstRow < 0)
659  throw new ArgumentOutOfRangeException("firstRow", "The parameter firstRow must be greater than or equal to zero.");
660  if (firstRow > 3)
661  throw new ArgumentOutOfRangeException("firstRow", "The parameter firstRow must be less than or equal to three.");
662  if (secondRow < 0)
663  throw new ArgumentOutOfRangeException("secondRow", "The parameter secondRow must be greater than or equal to zero.");
664  if (secondRow > 3)
665  throw new ArgumentOutOfRangeException("secondRow", "The parameter secondRow must be less than or equal to three.");
666 
667  if (firstRow == secondRow)
668  return;
669 
670  float temp0 = this[secondRow, 0];
671  float temp1 = this[secondRow, 1];
672  float temp2 = this[secondRow, 2];
673  float temp3 = this[secondRow, 3];
674 
675  this[secondRow, 0] = this[firstRow, 0];
676  this[secondRow, 1] = this[firstRow, 1];
677  this[secondRow, 2] = this[firstRow, 2];
678  this[secondRow, 3] = this[firstRow, 3];
679 
680  this[firstRow, 0] = temp0;
681  this[firstRow, 1] = temp1;
682  this[firstRow, 2] = temp2;
683  this[firstRow, 3] = temp3;
684  }
685 
686  /// <summary>
687  ///
688  /// </summary>
689  /// <param name="firstColumn"></param>
690  /// <param name="secondColumn"></param>
691  public void ExchangeColumns(int firstColumn, int secondColumn)
692  {
693  if (firstColumn < 0)
694  throw new ArgumentOutOfRangeException("firstColumn", "The parameter firstColumn must be greater than or equal to zero.");
695  if (firstColumn > 3)
696  throw new ArgumentOutOfRangeException("firstColumn", "The parameter firstColumn must be less than or equal to three.");
697  if (secondColumn < 0)
698  throw new ArgumentOutOfRangeException("secondColumn", "The parameter secondColumn must be greater than or equal to zero.");
699  if (secondColumn > 3)
700  throw new ArgumentOutOfRangeException("secondColumn", "The parameter secondColumn must be less than or equal to three.");
701 
702  if (firstColumn == secondColumn)
703  return;
704 
705  float temp0 = this[0, secondColumn];
706  float temp1 = this[1, secondColumn];
707  float temp2 = this[2, secondColumn];
708  float temp3 = this[3, secondColumn];
709 
710  this[0, secondColumn] = this[0, firstColumn];
711  this[1, secondColumn] = this[1, firstColumn];
712  this[2, secondColumn] = this[2, firstColumn];
713  this[3, secondColumn] = this[3, firstColumn];
714 
715  this[0, firstColumn] = temp0;
716  this[1, firstColumn] = temp1;
717  this[2, firstColumn] = temp2;
718  this[3, firstColumn] = temp3;
719  }
720 
721  /// <summary>
722  /// Creates an array containing the elements of the matrix.
723  /// </summary>
724  /// <returns>A sixteen-element array containing the components of the matrix.</returns>
725  public float[] ToArray()
726  {
727  return new[] { M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44 };
728  }
729 
730  /// <summary>
731  /// Determines the sum of two matrices.
732  /// </summary>
733  /// <param name="left">The first matrix to add.</param>
734  /// <param name="right">The second matrix to add.</param>
735  /// <param name="result">When the method completes, contains the sum of the two matrices.</param>
736  public static void Add(ref Matrix left, ref Matrix right, out Matrix result)
737  {
738  result.M11 = left.M11 + right.M11;
739  result.M21 = left.M21 + right.M21;
740  result.M31 = left.M31 + right.M31;
741  result.M41 = left.M41 + right.M41;
742  result.M12 = left.M12 + right.M12;
743  result.M22 = left.M22 + right.M22;
744  result.M32 = left.M32 + right.M32;
745  result.M42 = left.M42 + right.M42;
746  result.M13 = left.M13 + right.M13;
747  result.M23 = left.M23 + right.M23;
748  result.M33 = left.M33 + right.M33;
749  result.M43 = left.M43 + right.M43;
750  result.M14 = left.M14 + right.M14;
751  result.M24 = left.M24 + right.M24;
752  result.M34 = left.M34 + right.M34;
753  result.M44 = left.M44 + right.M44;
754  }
755 
756  /// <summary>
757  /// Determines the sum of two matrices.
758  /// </summary>
759  /// <param name="left">The first matrix to add.</param>
760  /// <param name="right">The second matrix to add.</param>
761  /// <returns>The sum of the two matrices.</returns>
762  public static Matrix Add(Matrix left, Matrix right)
763  {
764  Matrix result;
765  Add(ref left, ref right, out result);
766  return result;
767  }
768 
769  /// <summary>
770  /// Determines the difference between two matrices.
771  /// </summary>
772  /// <param name="left">The first matrix to subtract.</param>
773  /// <param name="right">The second matrix to subtract.</param>
774  /// <param name="result">When the method completes, contains the difference between the two matrices.</param>
775  public static void Subtract(ref Matrix left, ref Matrix right, out Matrix result)
776  {
777  result.M11 = left.M11 - right.M11;
778  result.M21 = left.M21 - right.M21;
779  result.M31 = left.M31 - right.M31;
780  result.M41 = left.M41 - right.M41;
781  result.M12 = left.M12 - right.M12;
782  result.M22 = left.M22 - right.M22;
783  result.M32 = left.M32 - right.M32;
784  result.M42 = left.M42 - right.M42;
785  result.M13 = left.M13 - right.M13;
786  result.M23 = left.M23 - right.M23;
787  result.M33 = left.M33 - right.M33;
788  result.M43 = left.M43 - right.M43;
789  result.M14 = left.M14 - right.M14;
790  result.M24 = left.M24 - right.M24;
791  result.M34 = left.M34 - right.M34;
792  result.M44 = left.M44 - right.M44;
793  }
794 
795  /// <summary>
796  /// Determines the difference between two matrices.
797  /// </summary>
798  /// <param name="left">The first matrix to subtract.</param>
799  /// <param name="right">The second matrix to subtract.</param>
800  /// <returns>The difference between the two matrices.</returns>
801  public static Matrix Subtract(Matrix left, Matrix right)
802  {
803  Matrix result;
804  Subtract(ref left, ref right, out result);
805  return result;
806  }
807 
808  /// <summary>
809  /// Scales a matrix by the given value.
810  /// </summary>
811  /// <param name="left">The matrix to scale.</param>
812  /// <param name="right">The amount by which to scale.</param>
813  /// <param name="result">When the method completes, contains the scaled matrix.</param>
814  public static void Multiply(ref Matrix left, float right, out Matrix result)
815  {
816  result.M11 = left.M11 * right;
817  result.M21 = left.M21 * right;
818  result.M31 = left.M31 * right;
819  result.M41 = left.M41 * right;
820  result.M12 = left.M12 * right;
821  result.M22 = left.M22 * right;
822  result.M32 = left.M32 * right;
823  result.M42 = left.M42 * right;
824  result.M13 = left.M13 * right;
825  result.M23 = left.M23 * right;
826  result.M33 = left.M33 * right;
827  result.M43 = left.M43 * right;
828  result.M14 = left.M14 * right;
829  result.M24 = left.M24 * right;
830  result.M34 = left.M34 * right;
831  result.M44 = left.M44 * right;
832  }
833 
834  /// <summary>
835  /// Scales a matrix by the given value.
836  /// </summary>
837  /// <param name="left">The matrix to scale.</param>
838  /// <param name="right">The amount by which to scale.</param>
839  /// <returns>The scaled matrix.</returns>
840  public static Matrix Multiply(Matrix left, float right)
841  {
842  Matrix result;
843  Multiply(ref left, right, out result);
844  return result;
845  }
846 
847  /// <summary>
848  /// Determines the product of two matrices.
849  /// </summary>
850  /// <param name="left">The first matrix to multiply.</param>
851  /// <param name="right">The second matrix to multiply.</param>
852  /// <param name="result">The product of the two matrices.</param>
853  public static void MultiplyTo(ref Matrix left, ref Matrix right, out Matrix result)
854  {
855  result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41);
856  result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41);
857  result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41);
858  result.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41);
859  result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42);
860  result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42);
861  result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42);
862  result.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42);
863  result.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43);
864  result.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43);
865  result.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43);
866  result.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43);
867  result.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44);
868  result.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44);
869  result.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44);
870  result.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44);
871  }
872 
873  /// <summary>
874  /// Determines the product of two matrices.
875  /// </summary>
876  /// <param name="left">The first matrix to multiply.</param>
877  /// <param name="right">The second matrix to multiply.</param>
878  /// <param name="result">The product of the two matrices.</param>
879 #if SILICONSTUDIO_PLATFORM_ANDROID
880  [MethodImpl(MethodImplOptions.AggressiveInlining)]
881 #endif
882  public static void Multiply(ref Matrix left, ref Matrix right, out Matrix result)
883  {
884 #if SILICONSTUDIO_PLATFORM_ANDROID
885  NEON_Matrix4Mul(ref left, ref right, out result);
886 #else
887  result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41);
888  result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41);
889  result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41);
890  result.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41);
891  result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42);
892  result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42);
893  result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42);
894  result.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42);
895  result.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43);
896  result.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43);
897  result.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43);
898  result.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43);
899  result.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44);
900  result.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44);
901  result.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44);
902  result.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44);
903 #endif
904  }
905 
906  /// <summary>
907  /// Determines the product of two matrices.
908  /// </summary>
909  /// <param name="left">The first matrix to multiply.</param>
910  /// <param name="right">The second matrix to multiply.</param>
911  /// <param name="result">The product of the two matrices.</param>
912  public static void MultiplyRef(ref Matrix left, ref Matrix right, ref Matrix result)
913  {
914  result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41);
915  result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41);
916  result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41);
917  result.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41);
918  result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42);
919  result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42);
920  result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42);
921  result.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42);
922  result.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43);
923  result.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43);
924  result.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43);
925  result.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43);
926  result.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44);
927  result.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44);
928  result.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44);
929  result.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44);
930  }
931 
932  /// <summary>
933  /// Determines the product of two matrices.
934  /// </summary>
935  /// <param name="left">The first matrix to multiply.</param>
936  /// <param name="right">The second matrix to multiply.</param>
937  /// <returns>The product of the two matrices.</returns>
938  public static Matrix Multiply(Matrix left, Matrix right)
939  {
940  Matrix result;
941  Multiply(ref left, ref right, out result);
942  return result;
943  }
944 
945  /// <summary>
946  /// Scales a matrix by the given value.
947  /// </summary>
948  /// <param name="left">The matrix to scale.</param>
949  /// <param name="right">The amount by which to scale.</param>
950  /// <param name="result">When the method completes, contains the scaled matrix.</param>
951  public static void Divide(ref Matrix left, float right, out Matrix result)
952  {
953  float inv = 1.0f / right;
954 
955  result.M11 = left.M11 * inv;
956  result.M21 = left.M21 * inv;
957  result.M31 = left.M31 * inv;
958  result.M41 = left.M41 * inv;
959  result.M12 = left.M12 * inv;
960  result.M22 = left.M22 * inv;
961  result.M32 = left.M32 * inv;
962  result.M42 = left.M42 * inv;
963  result.M13 = left.M13 * inv;
964  result.M23 = left.M23 * inv;
965  result.M33 = left.M33 * inv;
966  result.M43 = left.M43 * inv;
967  result.M14 = left.M14 * inv;
968  result.M24 = left.M24 * inv;
969  result.M34 = left.M34 * inv;
970  result.M44 = left.M44 * inv;
971  }
972 
973  /// <summary>
974  /// Scales a matrix by the given value.
975  /// </summary>
976  /// <param name="left">The matrix to scale.</param>
977  /// <param name="right">The amount by which to scale.</param>
978  /// <returns>The scaled matrix.</returns>
979  public static Matrix Divide(Matrix left, float right)
980  {
981  Matrix result;
982  Divide(ref left, right, out result);
983  return result;
984  }
985 
986  /// <summary>
987  /// Determines the quotient of two matrices.
988  /// </summary>
989  /// <param name="left">The first matrix to divide.</param>
990  /// <param name="right">The second matrix to divide.</param>
991  /// <param name="result">When the method completes, contains the quotient of the two matrices.</param>
992  public static void Divide(ref Matrix left, ref Matrix right, out Matrix result)
993  {
994  result.M11 = left.M11 / right.M11;
995  result.M21 = left.M21 / right.M21;
996  result.M31 = left.M31 / right.M31;
997  result.M41 = left.M41 / right.M41;
998  result.M12 = left.M12 / right.M12;
999  result.M22 = left.M22 / right.M22;
1000  result.M32 = left.M32 / right.M32;
1001  result.M42 = left.M42 / right.M42;
1002  result.M13 = left.M13 / right.M13;
1003  result.M23 = left.M23 / right.M23;
1004  result.M33 = left.M33 / right.M33;
1005  result.M43 = left.M43 / right.M43;
1006  result.M14 = left.M14 / right.M14;
1007  result.M24 = left.M24 / right.M24;
1008  result.M34 = left.M34 / right.M34;
1009  result.M44 = left.M44 / right.M44;
1010  }
1011 
1012  /// <summary>
1013  /// Determines the quotient of two matrices.
1014  /// </summary>
1015  /// <param name="left">The first matrix to divide.</param>
1016  /// <param name="right">The second matrix to divide.</param>
1017  /// <returns>The quotient of the two matrices.</returns>
1018  public static Matrix Divide(Matrix left, Matrix right)
1019  {
1020  Matrix result;
1021  Divide(ref left, ref right, out result);
1022  return result;
1023  }
1024 
1025  /// <summary>
1026  /// Performs the exponential operation on a matrix.
1027  /// </summary>
1028  /// <param name="value">The matrix to perform the operation on.</param>
1029  /// <param name="exponent">The exponent to raise the matrix to.</param>
1030  /// <param name="result">When the method completes, contains the exponential matrix.</param>
1031  /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="exponent"/> is negative.</exception>
1032  public static void Exponent(ref Matrix value, int exponent, out Matrix result)
1033  {
1034  //Source: http://rosettacode.org
1035  //Refrence: http://rosettacode.org/wiki/Matrix-exponentiation_operator
1036 
1037  if (exponent < 0)
1038  throw new ArgumentOutOfRangeException("exponent", "The exponent can not be negative.");
1039 
1040  if (exponent == 0)
1041  {
1042  result = Matrix.Identity;
1043  return;
1044  }
1045 
1046  if (exponent == 1)
1047  {
1048  result = value;
1049  return;
1050  }
1051 
1052  Matrix identity = Matrix.Identity;
1053  Matrix temp = value;
1054 
1055  while (true)
1056  {
1057  if ((exponent & 1) != 0)
1058  identity = identity * temp;
1059 
1060  exponent /= 2;
1061 
1062  if (exponent > 0)
1063  temp *= temp;
1064  else
1065  break;
1066  }
1067 
1068  result = identity;
1069  }
1070 
1071  /// <summary>
1072  /// Performs the exponential operation on a matrix.
1073  /// </summary>
1074  /// <param name="value">The matrix to perform the operation on.</param>
1075  /// <param name="exponent">The exponent to raise the matrix to.</param>
1076  /// <returns>The exponential matrix.</returns>
1077  /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="exponent"/> is negative.</exception>
1078  public static Matrix Exponent(Matrix value, int exponent)
1079  {
1080  Matrix result;
1081  Exponent(ref value, exponent, out result);
1082  return result;
1083  }
1084 
1085  /// <summary>
1086  /// Negates a matrix.
1087  /// </summary>
1088  /// <param name="value">The matrix to be negated.</param>
1089  /// <param name="result">When the method completes, contains the negated matrix.</param>
1090  public static void Negate(ref Matrix value, out Matrix result)
1091  {
1092  result.M11 = -value.M11;
1093  result.M21 = -value.M21;
1094  result.M31 = -value.M31;
1095  result.M41 = -value.M41;
1096  result.M12 = -value.M12;
1097  result.M22 = -value.M22;
1098  result.M32 = -value.M32;
1099  result.M42 = -value.M42;
1100  result.M13 = -value.M13;
1101  result.M23 = -value.M23;
1102  result.M33 = -value.M33;
1103  result.M43 = -value.M43;
1104  result.M14 = -value.M14;
1105  result.M24 = -value.M24;
1106  result.M34 = -value.M34;
1107  result.M44 = -value.M44;
1108  }
1109 
1110  /// <summary>
1111  /// Negates a matrix.
1112  /// </summary>
1113  /// <param name="value">The matrix to be negated.</param>
1114  /// <returns>The negated matrix.</returns>
1115  public static Matrix Negate(Matrix value)
1116  {
1117  Matrix result;
1118  Negate(ref value, out result);
1119  return result;
1120  }
1121 
1122  /// <summary>
1123  /// Performs a linear interpolation between two matricies.
1124  /// </summary>
1125  /// <param name="start">Start matrix.</param>
1126  /// <param name="end">End matrix.</param>
1127  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
1128  /// <param name="result">When the method completes, contains the linear interpolation of the two matricies.</param>
1129  /// <remarks>
1130  /// This method performs the linear interpolation based on the following formula.
1131  /// <code>start + (end - start) * amount</code>
1132  /// 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.
1133  /// </remarks>
1134  public static void Lerp(ref Matrix start, ref Matrix end, float amount, out Matrix result)
1135  {
1136  result.M11 = start.M11 + ((end.M11 - start.M11) * amount);
1137  result.M21 = start.M21 + ((end.M21 - start.M21) * amount);
1138  result.M31 = start.M31 + ((end.M31 - start.M31) * amount);
1139  result.M41 = start.M41 + ((end.M41 - start.M41) * amount);
1140  result.M12 = start.M12 + ((end.M12 - start.M12) * amount);
1141  result.M22 = start.M22 + ((end.M22 - start.M22) * amount);
1142  result.M32 = start.M32 + ((end.M32 - start.M32) * amount);
1143  result.M42 = start.M42 + ((end.M42 - start.M42) * amount);
1144  result.M13 = start.M13 + ((end.M13 - start.M13) * amount);
1145  result.M23 = start.M23 + ((end.M23 - start.M23) * amount);
1146  result.M33 = start.M33 + ((end.M33 - start.M33) * amount);
1147  result.M43 = start.M43 + ((end.M43 - start.M43) * amount);
1148  result.M14 = start.M14 + ((end.M14 - start.M14) * amount);
1149  result.M24 = start.M24 + ((end.M24 - start.M24) * amount);
1150  result.M34 = start.M34 + ((end.M34 - start.M34) * amount);
1151  result.M44 = start.M44 + ((end.M44 - start.M44) * amount);
1152  }
1153 
1154  /// <summary>
1155  /// Performs a linear interpolation between two matricies.
1156  /// </summary>
1157  /// <param name="start">Start matrix.</param>
1158  /// <param name="end">End matrix.</param>
1159  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
1160  /// <returns>The linear interpolation of the two matrices.</returns>
1161  /// <remarks>
1162  /// This method performs the linear interpolation based on the following formula.
1163  /// <code>start + (end - start) * amount</code>
1164  /// 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.
1165  /// </remarks>
1166  public static Matrix Lerp(Matrix start, Matrix end, float amount)
1167  {
1168  Matrix result;
1169  Lerp(ref start, ref end, amount, out result);
1170  return result;
1171  }
1172 
1173  /// <summary>
1174  /// Performs a cubic interpolation between two matricies.
1175  /// </summary>
1176  /// <param name="start">Start matrix.</param>
1177  /// <param name="end">End matrix.</param>
1178  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
1179  /// <param name="result">When the method completes, contains the cubic interpolation of the two matrices.</param>
1180  public static void SmoothStep(ref Matrix start, ref Matrix end, float amount, out Matrix result)
1181  {
1182  amount = (amount > 1.0f) ? 1.0f : ((amount < 0.0f) ? 0.0f : amount);
1183  amount = (amount * amount) * (3.0f - (2.0f * amount));
1184 
1185  result.M11 = start.M11 + ((end.M11 - start.M11) * amount);
1186  result.M21 = start.M21 + ((end.M21 - start.M21) * amount);
1187  result.M31 = start.M31 + ((end.M31 - start.M31) * amount);
1188  result.M41 = start.M41 + ((end.M41 - start.M41) * amount);
1189  result.M12 = start.M12 + ((end.M12 - start.M12) * amount);
1190  result.M22 = start.M22 + ((end.M22 - start.M22) * amount);
1191  result.M32 = start.M32 + ((end.M32 - start.M32) * amount);
1192  result.M42 = start.M42 + ((end.M42 - start.M42) * amount);
1193  result.M13 = start.M13 + ((end.M13 - start.M13) * amount);
1194  result.M23 = start.M23 + ((end.M23 - start.M23) * amount);
1195  result.M33 = start.M33 + ((end.M33 - start.M33) * amount);
1196  result.M43 = start.M43 + ((end.M43 - start.M43) * amount);
1197  result.M14 = start.M14 + ((end.M14 - start.M14) * amount);
1198  result.M24 = start.M24 + ((end.M24 - start.M24) * amount);
1199  result.M34 = start.M34 + ((end.M34 - start.M34) * amount);
1200  result.M44 = start.M44 + ((end.M44 - start.M44) * amount);
1201  }
1202 
1203  /// <summary>
1204  /// Performs a cubic interpolation between two matrices.
1205  /// </summary>
1206  /// <param name="start">Start matrix.</param>
1207  /// <param name="end">End matrix.</param>
1208  /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
1209  /// <returns>The cubic interpolation of the two matrices.</returns>
1210  public static Matrix SmoothStep(Matrix start, Matrix end, float amount)
1211  {
1212  Matrix result;
1213  SmoothStep(ref start, ref end, amount, out result);
1214  return result;
1215  }
1216 
1217  /// <summary>
1218  /// Calculates the transpose of the specified matrix.
1219  /// </summary>
1220  /// <param name="value">The matrix whose transpose is to be calculated.</param>
1221  /// <param name="result">When the method completes, contains the transpose of the specified matrix.</param>
1222  public static void Transpose(ref Matrix value, out Matrix result)
1223  {
1224  Matrix temp = new Matrix();
1225  temp.M11 = value.M11;
1226  temp.M21 = value.M12;
1227  temp.M31 = value.M13;
1228  temp.M41 = value.M14;
1229  temp.M12 = value.M21;
1230  temp.M22 = value.M22;
1231  temp.M32 = value.M23;
1232  temp.M42 = value.M24;
1233  temp.M13 = value.M31;
1234  temp.M23 = value.M32;
1235  temp.M33 = value.M33;
1236  temp.M43 = value.M34;
1237  temp.M14 = value.M41;
1238  temp.M24 = value.M42;
1239  temp.M34 = value.M43;
1240  temp.M44 = value.M44;
1241 
1242  result = temp;
1243  }
1244 
1245  /// <summary>
1246  /// Calculates the transpose of the specified matrix.
1247  /// </summary>
1248  /// <param name="value">The matrix whose transpose is to be calculated.</param>
1249  /// <returns>The transpose of the specified matrix.</returns>
1250  public static Matrix Transpose(Matrix value)
1251  {
1252  Matrix result;
1253  Transpose(ref value, out result);
1254  return result;
1255  }
1256 
1257  /// <summary>
1258  /// Calculates the inverse of the specified matrix.
1259  /// </summary>
1260  /// <param name="value">The matrix whose inverse is to be calculated.</param>
1261  /// <param name="result">When the method completes, contains the inverse of the specified matrix.</param>
1262  public static void Invert(ref Matrix value, out Matrix result)
1263  {
1264  float b0 = (value.M31 * value.M42) - (value.M32 * value.M41);
1265  float b1 = (value.M31 * value.M43) - (value.M33 * value.M41);
1266  float b2 = (value.M34 * value.M41) - (value.M31 * value.M44);
1267  float b3 = (value.M32 * value.M43) - (value.M33 * value.M42);
1268  float b4 = (value.M34 * value.M42) - (value.M32 * value.M44);
1269  float b5 = (value.M33 * value.M44) - (value.M34 * value.M43);
1270 
1271  float d11 = value.M22 * b5 + value.M23 * b4 + value.M24 * b3;
1272  float d12 = value.M21 * b5 + value.M23 * b2 + value.M24 * b1;
1273  float d13 = value.M21 * -b4 + value.M22 * b2 + value.M24 * b0;
1274  float d14 = value.M21 * b3 + value.M22 * -b1 + value.M23 * b0;
1275 
1276  float det = value.M11 * d11 - value.M12 * d12 + value.M13 * d13 - value.M14 * d14;
1277  if (Math.Abs(det) <= MathUtil.ZeroTolerance)
1278  {
1279  result = Matrix.Zero;
1280  return;
1281  }
1282 
1283  det = 1f / det;
1284 
1285  float a0 = (value.M11 * value.M22) - (value.M12 * value.M21);
1286  float a1 = (value.M11 * value.M23) - (value.M13 * value.M21);
1287  float a2 = (value.M14 * value.M21) - (value.M11 * value.M24);
1288  float a3 = (value.M12 * value.M23) - (value.M13 * value.M22);
1289  float a4 = (value.M14 * value.M22) - (value.M12 * value.M24);
1290  float a5 = (value.M13 * value.M24) - (value.M14 * value.M23);
1291 
1292  float d21 = value.M12 * b5 + value.M13 * b4 + value.M14 * b3;
1293  float d22 = value.M11 * b5 + value.M13 * b2 + value.M14 * b1;
1294  float d23 = value.M11 * -b4 + value.M12 * b2 + value.M14 * b0;
1295  float d24 = value.M11 * b3 + value.M12 * -b1 + value.M13 * b0;
1296 
1297  float d31 = value.M42 * a5 + value.M43 * a4 + value.M44 * a3;
1298  float d32 = value.M41 * a5 + value.M43 * a2 + value.M44 * a1;
1299  float d33 = value.M41 * -a4 + value.M42 * a2 + value.M44 * a0;
1300  float d34 = value.M41 * a3 + value.M42 * -a1 + value.M43 * a0;
1301 
1302  float d41 = value.M32 * a5 + value.M33 * a4 + value.M34 * a3;
1303  float d42 = value.M31 * a5 + value.M33 * a2 + value.M34 * a1;
1304  float d43 = value.M31 * -a4 + value.M32 * a2 + value.M34 * a0;
1305  float d44 = value.M31 * a3 + value.M32 * -a1 + value.M33 * a0;
1306 
1307  result.M11 = +d11 * det; result.M12 = -d21 * det; result.M13 = +d31 * det; result.M14 = -d41 * det;
1308  result.M21 = -d12 * det; result.M22 = +d22 * det; result.M23 = -d32 * det; result.M24 = +d42 * det;
1309  result.M31 = +d13 * det; result.M32 = -d23 * det; result.M33 = +d33 * det; result.M34 = -d43 * det;
1310  result.M41 = -d14 * det; result.M42 = +d24 * det; result.M43 = -d34 * det; result.M44 = +d44 * det;
1311  }
1312 
1313  /// <summary>
1314  /// Calculates the inverse of the specified matrix.
1315  /// </summary>
1316  /// <param name="value">The matrix whose inverse is to be calculated.</param>
1317  /// <returns>The inverse of the specified matrix.</returns>
1318  public static Matrix Invert(Matrix value)
1319  {
1320  value.Invert();
1321  return value;
1322  }
1323 
1324  /// <summary>
1325  /// Orthogonalizes the specified matrix.
1326  /// </summary>
1327  /// <param name="value">The matrix to orthogonalize.</param>
1328  /// <param name="result">When the method completes, contains the orthogonalized matrix.</param>
1329  /// <remarks>
1330  /// <para>Orthogonalization is the process of making all rows orthogonal to each other. This
1331  /// means that any given row in the matrix will be orthogonal to any other given row in the
1332  /// matrix.</para>
1333  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting matrix
1334  /// tends to be numerically unstable. The numeric stability decreases according to the rows
1335  /// so that the first row is the most stable and the last row is the least stable.</para>
1336  /// <para>This operation is performed on the rows of the matrix rather than the columns.
1337  /// If you wish for this operation to be performed on the columns, first transpose the
1338  /// input and than transpose the output.</para>
1339  /// </remarks>
1340  public static void Orthogonalize(ref Matrix value, out Matrix result)
1341  {
1342  //Uses the modified Gram-Schmidt process.
1343  //q1 = m1
1344  //q2 = m2 - ((q1 â‹… m2) / (q1 â‹… q1)) * q1
1345  //q3 = m3 - ((q1 â‹… m3) / (q1 â‹… q1)) * q1 - ((q2 â‹… m3) / (q2 â‹… q2)) * q2
1346  //q4 = m4 - ((q1 â‹… m4) / (q1 â‹… q1)) * q1 - ((q2 â‹… m4) / (q2 â‹… q2)) * q2 - ((q3 â‹… m4) / (q3 â‹… q3)) * q3
1347 
1348  //By separating the above algorithm into multiple lines, we actually increase accuracy.
1349  result = value;
1350 
1351  result.Row2 = result.Row2 - (Vector4.Dot(result.Row1, result.Row2) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1;
1352 
1353  result.Row3 = result.Row3 - (Vector4.Dot(result.Row1, result.Row3) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1;
1354  result.Row3 = result.Row3 - (Vector4.Dot(result.Row2, result.Row3) / Vector4.Dot(result.Row2, result.Row2)) * result.Row2;
1355 
1356  result.Row4 = result.Row4 - (Vector4.Dot(result.Row1, result.Row4) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1;
1357  result.Row4 = result.Row4 - (Vector4.Dot(result.Row2, result.Row4) / Vector4.Dot(result.Row2, result.Row2)) * result.Row2;
1358  result.Row4 = result.Row4 - (Vector4.Dot(result.Row3, result.Row4) / Vector4.Dot(result.Row3, result.Row3)) * result.Row3;
1359  }
1360 
1361  /// <summary>
1362  /// Orthogonalizes the specified matrix.
1363  /// </summary>
1364  /// <param name="value">The matrix to orthogonalize.</param>
1365  /// <returns>The orthogonalized matrix.</returns>
1366  /// <remarks>
1367  /// <para>Orthogonalization is the process of making all rows orthogonal to each other. This
1368  /// means that any given row in the matrix will be orthogonal to any other given row in the
1369  /// matrix.</para>
1370  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting matrix
1371  /// tends to be numerically unstable. The numeric stability decreases according to the rows
1372  /// so that the first row is the most stable and the last row is the least stable.</para>
1373  /// <para>This operation is performed on the rows of the matrix rather than the columns.
1374  /// If you wish for this operation to be performed on the columns, first transpose the
1375  /// input and than transpose the output.</para>
1376  /// </remarks>
1377  public static Matrix Orthogonalize(Matrix value)
1378  {
1379  Matrix result;
1380  Orthogonalize(ref value, out result);
1381  return result;
1382  }
1383 
1384  /// <summary>
1385  /// Orthonormalizes the specified matrix.
1386  /// </summary>
1387  /// <param name="value">The matrix to orthonormalize.</param>
1388  /// <param name="result">When the method completes, contains the orthonormalized matrix.</param>
1389  /// <remarks>
1390  /// <para>Orthonormalization is the process of making all rows and columns orthogonal to each
1391  /// other and making all rows and columns of unit length. This means that any given row will
1392  /// be orthogonal to any other given row and any given column will be orthogonal to any other
1393  /// given column. Any given row will not be orthogonal to any given column. Every row and every
1394  /// column will be of unit length.</para>
1395  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting matrix
1396  /// tends to be numerically unstable. The numeric stability decreases according to the rows
1397  /// so that the first row is the most stable and the last row is the least stable.</para>
1398  /// <para>This operation is performed on the rows of the matrix rather than the columns.
1399  /// If you wish for this operation to be performed on the columns, first transpose the
1400  /// input and than transpose the output.</para>
1401  /// </remarks>
1402  public static void Orthonormalize(ref Matrix value, out Matrix result)
1403  {
1404  //Uses the modified Gram-Schmidt process.
1405  //Because we are making unit vectors, we can optimize the math for orthogonalization
1406  //and simplify the projection operation to remove the division.
1407  //q1 = m1 / |m1|
1408  //q2 = (m2 - (q1 â‹… m2) * q1) / |m2 - (q1 â‹… m2) * q1|
1409  //q3 = (m3 - (q1 â‹… m3) * q1 - (q2 â‹… m3) * q2) / |m3 - (q1 â‹… m3) * q1 - (q2 â‹… m3) * q2|
1410  //q4 = (m4 - (q1 â‹… m4) * q1 - (q2 â‹… m4) * q2 - (q3 â‹… m4) * q3) / |m4 - (q1 â‹… m4) * q1 - (q2 â‹… m4) * q2 - (q3 â‹… m4) * q3|
1411 
1412  //By separating the above algorithm into multiple lines, we actually increase accuracy.
1413  result = value;
1414 
1415  result.Row1 = Vector4.Normalize(result.Row1);
1416 
1417  result.Row2 = result.Row2 - Vector4.Dot(result.Row1, result.Row2) * result.Row1;
1418  result.Row2 = Vector4.Normalize(result.Row2);
1419 
1420  result.Row3 = result.Row3 - Vector4.Dot(result.Row1, result.Row3) * result.Row1;
1421  result.Row3 = result.Row3 - Vector4.Dot(result.Row2, result.Row3) * result.Row2;
1422  result.Row3 = Vector4.Normalize(result.Row3);
1423 
1424  result.Row4 = result.Row4 - Vector4.Dot(result.Row1, result.Row4) * result.Row1;
1425  result.Row4 = result.Row4 - Vector4.Dot(result.Row2, result.Row4) * result.Row2;
1426  result.Row4 = result.Row4 - Vector4.Dot(result.Row3, result.Row4) * result.Row3;
1427  result.Row4 = Vector4.Normalize(result.Row4);
1428  }
1429 
1430  /// <summary>
1431  /// Orthonormalizes the specified matrix.
1432  /// </summary>
1433  /// <param name="value">The matrix to orthonormalize.</param>
1434  /// <returns>The orthonormalized matrix.</returns>
1435  /// <remarks>
1436  /// <para>Orthonormalization is the process of making all rows and columns orthogonal to each
1437  /// other and making all rows and columns of unit length. This means that any given row will
1438  /// be orthogonal to any other given row and any given column will be orthogonal to any other
1439  /// given column. Any given row will not be orthogonal to any given column. Every row and every
1440  /// column will be of unit length.</para>
1441  /// <para>Because this method uses the modified Gram-Schmidt process, the resulting matrix
1442  /// tends to be numerically unstable. The numeric stability decreases according to the rows
1443  /// so that the first row is the most stable and the last row is the least stable.</para>
1444  /// <para>This operation is performed on the rows of the matrix rather than the columns.
1445  /// If you wish for this operation to be performed on the columns, first transpose the
1446  /// input and than transpose the output.</para>
1447  /// </remarks>
1448  public static Matrix Orthonormalize(Matrix value)
1449  {
1450  Matrix result;
1451  Orthonormalize(ref value, out result);
1452  return result;
1453  }
1454 
1455  /// <summary>
1456  /// Brings the matrix into upper triangular form using elementry row operations.
1457  /// </summary>
1458  /// <param name="value">The matrix to put into upper triangular form.</param>
1459  /// <param name="result">When the method completes, contains the upper triangular matrix.</param>
1460  /// <remarks>
1461  /// If the matrix is not invertable (i.e. its determinant is zero) than the result of this
1462  /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system
1463  /// of linear equations, than this often means that either no solution exists or an infinite
1464  /// number of solutions exist.
1465  /// </remarks>
1466  public static void UpperTriangularForm(ref Matrix value, out Matrix result)
1467  {
1468  //Adapted from the row echelon code.
1469  result = value;
1470  int lead = 0;
1471  int rowcount = 4;
1472  int columncount = 4;
1473 
1474  for (int r = 0; r < rowcount; ++r)
1475  {
1476  if (columncount <= lead)
1477  return;
1478 
1479  int i = r;
1480 
1481  while (Math.Abs(result[i, lead]) < MathUtil.ZeroTolerance)
1482  {
1483  i++;
1484 
1485  if (i == rowcount)
1486  {
1487  i = r;
1488  lead++;
1489 
1490  if (lead == columncount)
1491  return;
1492  }
1493  }
1494 
1495  if (i != r)
1496  {
1497  result.ExchangeRows(i, r);
1498  }
1499 
1500  float multiplier = 1f / result[r, lead];
1501 
1502  for (; i < rowcount; ++i)
1503  {
1504  if (i != r)
1505  {
1506  result[i, 0] -= result[r, 0] * multiplier * result[i, lead];
1507  result[i, 1] -= result[r, 1] * multiplier * result[i, lead];
1508  result[i, 2] -= result[r, 2] * multiplier * result[i, lead];
1509  result[i, 3] -= result[r, 3] * multiplier * result[i, lead];
1510  }
1511  }
1512 
1513  lead++;
1514  }
1515  }
1516 
1517  /// <summary>
1518  /// Brings the matrix into upper triangular form using elementry row operations.
1519  /// </summary>
1520  /// <param name="value">The matrix to put into upper triangular form.</param>
1521  /// <returns>The upper triangular matrix.</returns>
1522  /// <remarks>
1523  /// If the matrix is not invertable (i.e. its determinant is zero) than the result of this
1524  /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system
1525  /// of linear equations, than this often means that either no solution exists or an infinite
1526  /// number of solutions exist.
1527  /// </remarks>
1528  public static Matrix UpperTriangularForm(Matrix value)
1529  {
1530  Matrix result;
1531  UpperTriangularForm(ref value, out result);
1532  return result;
1533  }
1534 
1535  /// <summary>
1536  /// Brings the matrix into lower triangular form using elementry row operations.
1537  /// </summary>
1538  /// <param name="value">The matrix to put into lower triangular form.</param>
1539  /// <param name="result">When the method completes, contains the lower triangular matrix.</param>
1540  /// <remarks>
1541  /// If the matrix is not invertable (i.e. its determinant is zero) than the result of this
1542  /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system
1543  /// of linear equations, than this often means that either no solution exists or an infinite
1544  /// number of solutions exist.
1545  /// </remarks>
1546  public static void LowerTriangularForm(ref Matrix value, out Matrix result)
1547  {
1548  //Adapted from the row echelon code.
1549  Matrix temp = value;
1550  Matrix.Transpose(ref temp, out result);
1551 
1552  int lead = 0;
1553  int rowcount = 4;
1554  int columncount = 4;
1555 
1556  for (int r = 0; r < rowcount; ++r)
1557  {
1558  if (columncount <= lead)
1559  return;
1560 
1561  int i = r;
1562 
1563  while (Math.Abs(result[i, lead]) < MathUtil.ZeroTolerance)
1564  {
1565  i++;
1566 
1567  if (i == rowcount)
1568  {
1569  i = r;
1570  lead++;
1571 
1572  if (lead == columncount)
1573  return;
1574  }
1575  }
1576 
1577  if (i != r)
1578  {
1579  result.ExchangeRows(i, r);
1580  }
1581 
1582  float multiplier = 1f / result[r, lead];
1583 
1584  for (; i < rowcount; ++i)
1585  {
1586  if (i != r)
1587  {
1588  result[i, 0] -= result[r, 0] * multiplier * result[i, lead];
1589  result[i, 1] -= result[r, 1] * multiplier * result[i, lead];
1590  result[i, 2] -= result[r, 2] * multiplier * result[i, lead];
1591  result[i, 3] -= result[r, 3] * multiplier * result[i, lead];
1592  }
1593  }
1594 
1595  lead++;
1596  }
1597 
1598  Matrix.Transpose(ref result, out result);
1599  }
1600 
1601  /// <summary>
1602  /// Brings the matrix into lower triangular form using elementry row operations.
1603  /// </summary>
1604  /// <param name="value">The matrix to put into lower triangular form.</param>
1605  /// <returns>The lower triangular matrix.</returns>
1606  /// <remarks>
1607  /// If the matrix is not invertable (i.e. its determinant is zero) than the result of this
1608  /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system
1609  /// of linear equations, than this often means that either no solution exists or an infinite
1610  /// number of solutions exist.
1611  /// </remarks>
1612  public static Matrix LowerTriangularForm(Matrix value)
1613  {
1614  Matrix result;
1615  LowerTriangularForm(ref value, out result);
1616  return result;
1617  }
1618 
1619  /// <summary>
1620  /// Brings the matrix into row echelon form using elementry row operations;
1621  /// </summary>
1622  /// <param name="value">The matrix to put into row echelon form.</param>
1623  /// <param name="result">When the method completes, contains the row echelon form of the matrix.</param>
1624  public static void RowEchelonForm(ref Matrix value, out Matrix result)
1625  {
1626  //Source: Wikipedia psuedo code
1627  //Reference: http://en.wikipedia.org/wiki/Row_echelon_form#Pseudocode
1628 
1629  result = value;
1630  int lead = 0;
1631  int rowcount = 4;
1632  int columncount = 4;
1633 
1634  for (int r = 0; r < rowcount; ++r)
1635  {
1636  if (columncount <= lead)
1637  return;
1638 
1639  int i = r;
1640 
1641  while (Math.Abs(result[i, lead]) < MathUtil.ZeroTolerance)
1642  {
1643  i++;
1644 
1645  if (i == rowcount)
1646  {
1647  i = r;
1648  lead++;
1649 
1650  if (lead == columncount)
1651  return;
1652  }
1653  }
1654 
1655  if (i != r)
1656  {
1657  result.ExchangeRows(i, r);
1658  }
1659 
1660  float multiplier = 1f / result[r, lead];
1661  result[r, 0] *= multiplier;
1662  result[r, 1] *= multiplier;
1663  result[r, 2] *= multiplier;
1664  result[r, 3] *= multiplier;
1665 
1666  for (; i < rowcount; ++i)
1667  {
1668  if (i != r)
1669  {
1670  result[i, 0] -= result[r, 0] * result[i, lead];
1671  result[i, 1] -= result[r, 1] * result[i, lead];
1672  result[i, 2] -= result[r, 2] * result[i, lead];
1673  result[i, 3] -= result[r, 3] * result[i, lead];
1674  }
1675  }
1676 
1677  lead++;
1678  }
1679  }
1680 
1681  /// <summary>
1682  /// Brings the matrix into row echelon form using elementry row operations;
1683  /// </summary>
1684  /// <param name="value">The matrix to put into row echelon form.</param>
1685  /// <returns>When the method completes, contains the row echelon form of the matrix.</returns>
1686  public static Matrix RowEchelonForm(Matrix value)
1687  {
1688  Matrix result;
1689  RowEchelonForm(ref value, out result);
1690  return result;
1691  }
1692 
1693  /// <summary>
1694  /// Brings the matrix into reduced row echelon form using elementry row operations.
1695  /// </summary>
1696  /// <param name="value">The matrix to put into reduced row echelon form.</param>
1697  /// <param name="augment">The fifth column of the matrix.</param>
1698  /// <param name="result">When the method completes, contains the resultant matrix after the operation.</param>
1699  /// <param name="augmentResult">When the method completes, contains the resultant fifth column of the matrix.</param>
1700  /// <remarks>
1701  /// <para>The fifth column is often called the agumented part of the matrix. This is because the fifth
1702  /// column is really just an extension of the matrix so that there is a place to put all of the
1703  /// non-zero components after the operation is complete.</para>
1704  /// <para>Often times the resultant matrix will the identity matrix or a matrix similar to the identity
1705  /// matrix. Sometimes, however, that is not possible and numbers other than zero and one may appear.</para>
1706  /// <para>This method can be used to solve systems of linear equations. Upon completion of this method,
1707  /// the <paramref name="augmentResult"/> will contain the solution for the system. It is up to the user
1708  /// to analyze both the input and the result to determine if a solution really exists.</para>
1709  /// </remarks>
1710  public static void ReducedRowEchelonForm(ref Matrix value, ref Vector4 augment, out Matrix result, out Vector4 augmentResult)
1711  {
1712  //Source: http://rosettacode.org
1713  //Reference: http://rosettacode.org/wiki/Reduced_row_echelon_form
1714 
1715  float[,] matrix = new float[4, 5];
1716 
1717  matrix[0, 0] = value[0, 0];
1718  matrix[0, 1] = value[0, 1];
1719  matrix[0, 2] = value[0, 2];
1720  matrix[0, 3] = value[0, 3];
1721  matrix[0, 4] = augment[0];
1722 
1723  matrix[1, 0] = value[1, 0];
1724  matrix[1, 1] = value[1, 1];
1725  matrix[1, 2] = value[1, 2];
1726  matrix[1, 3] = value[1, 3];
1727  matrix[1, 4] = augment[1];
1728 
1729  matrix[2, 0] = value[2, 0];
1730  matrix[2, 1] = value[2, 1];
1731  matrix[2, 2] = value[2, 2];
1732  matrix[2, 3] = value[2, 3];
1733  matrix[2, 4] = augment[2];
1734 
1735  matrix[3, 0] = value[3, 0];
1736  matrix[3, 1] = value[3, 1];
1737  matrix[3, 2] = value[3, 2];
1738  matrix[3, 3] = value[3, 3];
1739  matrix[3, 4] = augment[3];
1740 
1741  int lead = 0;
1742  int rowcount = 4;
1743  int columncount = 5;
1744 
1745  for (int r = 0; r < rowcount; r++)
1746  {
1747  if (columncount <= lead)
1748  break;
1749 
1750  int i = r;
1751 
1752  while (matrix[i, lead] == 0)
1753  {
1754  i++;
1755 
1756  if (i == rowcount)
1757  {
1758  i = r;
1759  lead++;
1760 
1761  if (columncount == lead)
1762  break;
1763  }
1764  }
1765 
1766  for (int j = 0; j < columncount; j++)
1767  {
1768  float temp = matrix[r, j];
1769  matrix[r, j] = matrix[i, j];
1770  matrix[i, j] = temp;
1771  }
1772 
1773  float div = matrix[r, lead];
1774 
1775  for (int j = 0; j < columncount; j++)
1776  {
1777  matrix[r, j] /= div;
1778  }
1779 
1780  for (int j = 0; j < rowcount; j++)
1781  {
1782  if (j != r)
1783  {
1784  float sub = matrix[j, lead];
1785  for (int k = 0; k < columncount; k++) matrix[j, k] -= (sub * matrix[r, k]);
1786  }
1787  }
1788 
1789  lead++;
1790  }
1791 
1792  result.M11 = matrix[0, 0];
1793  result.M12 = matrix[0, 1];
1794  result.M13 = matrix[0, 2];
1795  result.M14 = matrix[0, 3];
1796 
1797  result.M21 = matrix[1, 0];
1798  result.M22 = matrix[1, 1];
1799  result.M23 = matrix[1, 2];
1800  result.M24 = matrix[1, 3];
1801 
1802  result.M31 = matrix[2, 0];
1803  result.M32 = matrix[2, 1];
1804  result.M33 = matrix[2, 2];
1805  result.M34 = matrix[2, 3];
1806 
1807  result.M41 = matrix[3, 0];
1808  result.M42 = matrix[3, 1];
1809  result.M43 = matrix[3, 2];
1810  result.M44 = matrix[3, 3];
1811 
1812  augmentResult.X = matrix[0, 4];
1813  augmentResult.Y = matrix[1, 4];
1814  augmentResult.Z = matrix[2, 4];
1815  augmentResult.W = matrix[3, 4];
1816  }
1817 
1818  /// <summary>
1819  /// Creates a spherical billboard that rotates around a specified object position.
1820  /// </summary>
1821  /// <param name="objectPosition">The position of the object around which the billboard will rotate.</param>
1822  /// <param name="cameraPosition">The position of the camera.</param>
1823  /// <param name="cameraUpVector">The up vector of the camera.</param>
1824  /// <param name="cameraForwardVector">The forward vector of the camera.</param>
1825  /// <param name="result">When the method completes, contains the created billboard matrix.</param>
1826  public static void Billboard(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Matrix result)
1827  {
1828  Vector3 crossed;
1829  Vector3 final;
1830  Vector3 difference = objectPosition - cameraPosition;
1831 
1832  float lengthSq = difference.LengthSquared();
1833  if (lengthSq < MathUtil.ZeroTolerance)
1834  difference = -cameraForwardVector;
1835  else
1836  difference *= (float)(1.0 / Math.Sqrt(lengthSq));
1837 
1838  Vector3.Cross(ref cameraUpVector, ref difference, out crossed);
1839  crossed.Normalize();
1840  Vector3.Cross(ref difference, ref crossed, out final);
1841 
1842  result.M11 = crossed.X;
1843  result.M12 = crossed.Y;
1844  result.M13 = crossed.Z;
1845  result.M14 = 0.0f;
1846  result.M21 = final.X;
1847  result.M22 = final.Y;
1848  result.M23 = final.Z;
1849  result.M24 = 0.0f;
1850  result.M31 = difference.X;
1851  result.M32 = difference.Y;
1852  result.M33 = difference.Z;
1853  result.M34 = 0.0f;
1854  result.M41 = objectPosition.X;
1855  result.M42 = objectPosition.Y;
1856  result.M43 = objectPosition.Z;
1857  result.M44 = 1.0f;
1858  }
1859 
1860  /// <summary>
1861  /// Creates a spherical billboard that rotates around a specified object position.
1862  /// </summary>
1863  /// <param name="objectPosition">The position of the object around which the billboard will rotate.</param>
1864  /// <param name="cameraPosition">The position of the camera.</param>
1865  /// <param name="cameraUpVector">The up vector of the camera.</param>
1866  /// <param name="cameraForwardVector">The forward vector of the camera.</param>
1867  /// <returns>The created billboard matrix.</returns>
1868  public static Matrix Billboard(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector)
1869  {
1870  Matrix result;
1871  Billboard(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result);
1872  return result;
1873  }
1874 
1875  /// <summary>
1876  /// Creates a left-handed, look-at matrix.
1877  /// </summary>
1878  /// <param name="eye">The position of the viewer's eye.</param>
1879  /// <param name="target">The camera look-at target.</param>
1880  /// <param name="up">The camera's up vector.</param>
1881  /// <param name="result">When the method completes, contains the created look-at matrix.</param>
1882  public static void LookAtLH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result)
1883  {
1884  Vector3 xaxis, yaxis, zaxis;
1885  Vector3.Subtract(ref target, ref eye, out zaxis); zaxis.Normalize();
1886  Vector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize();
1887  Vector3.Cross(ref zaxis, ref xaxis, out yaxis);
1888 
1889  result = Matrix.Identity;
1890  result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z;
1891  result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z;
1892  result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z;
1893 
1894  Vector3.Dot(ref xaxis, ref eye, out result.M41);
1895  Vector3.Dot(ref yaxis, ref eye, out result.M42);
1896  Vector3.Dot(ref zaxis, ref eye, out result.M43);
1897 
1898  result.M41 = -result.M41;
1899  result.M42 = -result.M42;
1900  result.M43 = -result.M43;
1901  }
1902 
1903  /// <summary>
1904  /// Creates a left-handed, look-at matrix.
1905  /// </summary>
1906  /// <param name="eye">The position of the viewer's eye.</param>
1907  /// <param name="target">The camera look-at target.</param>
1908  /// <param name="up">The camera's up vector.</param>
1909  /// <returns>The created look-at matrix.</returns>
1910  public static Matrix LookAtLH(Vector3 eye, Vector3 target, Vector3 up)
1911  {
1912  Matrix result;
1913  LookAtLH(ref eye, ref target, ref up, out result);
1914  return result;
1915  }
1916 
1917  /// <summary>
1918  /// Creates a right-handed, look-at matrix.
1919  /// </summary>
1920  /// <param name="eye">The position of the viewer's eye.</param>
1921  /// <param name="target">The camera look-at target.</param>
1922  /// <param name="up">The camera's up vector.</param>
1923  /// <param name="result">When the method completes, contains the created look-at matrix.</param>
1924  public static void LookAtRH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result)
1925  {
1926  Vector3 xaxis, yaxis, zaxis;
1927  Vector3.Subtract(ref eye, ref target, out zaxis); zaxis.Normalize();
1928  Vector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize();
1929  Vector3.Cross(ref zaxis, ref xaxis, out yaxis);
1930 
1931  result = Matrix.Identity;
1932  result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z;
1933  result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z;
1934  result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z;
1935 
1936  Vector3.Dot(ref xaxis, ref eye, out result.M41);
1937  Vector3.Dot(ref yaxis, ref eye, out result.M42);
1938  Vector3.Dot(ref zaxis, ref eye, out result.M43);
1939 
1940  result.M41 = -result.M41;
1941  result.M42 = -result.M42;
1942  result.M43 = -result.M43;
1943  }
1944 
1945  /// <summary>
1946  /// Creates a right-handed, look-at matrix.
1947  /// </summary>
1948  /// <param name="eye">The position of the viewer's eye.</param>
1949  /// <param name="target">The camera look-at target.</param>
1950  /// <param name="up">The camera's up vector.</param>
1951  /// <returns>The created look-at matrix.</returns>
1952  public static Matrix LookAtRH(Vector3 eye, Vector3 target, Vector3 up)
1953  {
1954  Matrix result;
1955  LookAtRH(ref eye, ref target, ref up, out result);
1956  return result;
1957  }
1958 
1959  /// <summary>
1960  /// Creates a left-handed, orthographic projection matrix.
1961  /// </summary>
1962  /// <param name="width">Width of the viewing volume.</param>
1963  /// <param name="height">Height of the viewing volume.</param>
1964  /// <param name="znear">Minimum z-value of the viewing volume.</param>
1965  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
1966  /// <param name="result">When the method completes, contains the created projection matrix.</param>
1967  public static void OrthoLH(float width, float height, float znear, float zfar, out Matrix result)
1968  {
1969  float halfWidth = width * 0.5f;
1970  float halfHeight = height * 0.5f;
1971 
1972  OrthoOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result);
1973  }
1974 
1975  /// <summary>
1976  /// Creates a left-handed, orthographic projection matrix.
1977  /// </summary>
1978  /// <param name="width">Width of the viewing volume.</param>
1979  /// <param name="height">Height of the viewing volume.</param>
1980  /// <param name="znear">Minimum z-value of the viewing volume.</param>
1981  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
1982  /// <returns>The created projection matrix.</returns>
1983  public static Matrix OrthoLH(float width, float height, float znear, float zfar)
1984  {
1985  Matrix result;
1986  OrthoLH(width, height, znear, zfar, out result);
1987  return result;
1988  }
1989 
1990  /// <summary>
1991  /// Creates a right-handed, orthographic projection matrix.
1992  /// </summary>
1993  /// <param name="width">Width of the viewing volume.</param>
1994  /// <param name="height">Height of the viewing volume.</param>
1995  /// <param name="znear">Minimum z-value of the viewing volume.</param>
1996  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
1997  /// <param name="result">When the method completes, contains the created projection matrix.</param>
1998  public static void OrthoRH(float width, float height, float znear, float zfar, out Matrix result)
1999  {
2000  float halfWidth = width * 0.5f;
2001  float halfHeight = height * 0.5f;
2002 
2003  OrthoOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result);
2004  }
2005 
2006  /// <summary>
2007  /// Creates a right-handed, orthographic projection matrix.
2008  /// </summary>
2009  /// <param name="width">Width of the viewing volume.</param>
2010  /// <param name="height">Height of the viewing volume.</param>
2011  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2012  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2013  /// <returns>The created projection matrix.</returns>
2014  public static Matrix OrthoRH(float width, float height, float znear, float zfar)
2015  {
2016  Matrix result;
2017  OrthoRH(width, height, znear, zfar, out result);
2018  return result;
2019  }
2020 
2021  /// <summary>
2022  /// Creates a left-handed, customized orthographic projection matrix.
2023  /// </summary>
2024  /// <param name="left">Minimum x-value of the viewing volume.</param>
2025  /// <param name="right">Maximum x-value of the viewing volume.</param>
2026  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2027  /// <param name="top">Maximum y-value of the viewing volume.</param>
2028  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2029  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2030  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2031  public static void OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
2032  {
2033  float zRange = 1.0f / (zfar - znear);
2034 
2035  result = Matrix.Identity;
2036  result.M11 = 2.0f / (right - left);
2037  result.M22 = 2.0f / (top - bottom);
2038  result.M33 = zRange;
2039  result.M41 = (left + right) / (left - right);
2040  result.M42 = (top + bottom) / (bottom - top);
2041  result.M43 = -znear * zRange;
2042  }
2043 
2044  /// <summary>
2045  /// Creates a left-handed, customized orthographic projection matrix.
2046  /// </summary>
2047  /// <param name="left">Minimum x-value of the viewing volume.</param>
2048  /// <param name="right">Maximum x-value of the viewing volume.</param>
2049  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2050  /// <param name="top">Maximum y-value of the viewing volume.</param>
2051  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2052  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2053  /// <returns>The created projection matrix.</returns>
2054  public static Matrix OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar)
2055  {
2056  Matrix result;
2057  OrthoOffCenterLH(left, right, bottom, top, znear, zfar, out result);
2058  return result;
2059  }
2060 
2061  /// <summary>
2062  /// Creates a right-handed, customized orthographic projection matrix.
2063  /// </summary>
2064  /// <param name="left">Minimum x-value of the viewing volume.</param>
2065  /// <param name="right">Maximum x-value of the viewing volume.</param>
2066  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2067  /// <param name="top">Maximum y-value of the viewing volume.</param>
2068  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2069  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2070  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2071  public static void OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
2072  {
2073  OrthoOffCenterLH(left, right, bottom, top, znear, zfar, out result);
2074  result.M33 *= -1.0f;
2075  }
2076 
2077  /// <summary>
2078  /// Creates a right-handed, customized orthographic projection matrix.
2079  /// </summary>
2080  /// <param name="left">Minimum x-value of the viewing volume.</param>
2081  /// <param name="right">Maximum x-value of the viewing volume.</param>
2082  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2083  /// <param name="top">Maximum y-value of the viewing volume.</param>
2084  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2085  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2086  /// <returns>The created projection matrix.</returns>
2087  public static Matrix OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar)
2088  {
2089  Matrix result;
2090  OrthoOffCenterRH(left, right, bottom, top, znear, zfar, out result);
2091  return result;
2092  }
2093 
2094  /// <summary>
2095  /// Creates a left-handed, perspective projection matrix.
2096  /// </summary>
2097  /// <param name="width">Width of the viewing volume.</param>
2098  /// <param name="height">Height of the viewing volume.</param>
2099  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2100  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2101  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2102  public static void PerspectiveLH(float width, float height, float znear, float zfar, out Matrix result)
2103  {
2104  float halfWidth = width * 0.5f;
2105  float halfHeight = height * 0.5f;
2106 
2107  PerspectiveOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result);
2108  }
2109 
2110  /// <summary>
2111  /// Creates a left-handed, perspective projection matrix.
2112  /// </summary>
2113  /// <param name="width">Width of the viewing volume.</param>
2114  /// <param name="height">Height of the viewing volume.</param>
2115  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2116  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2117  /// <returns>The created projection matrix.</returns>
2118  public static Matrix PerspectiveLH(float width, float height, float znear, float zfar)
2119  {
2120  Matrix result;
2121  PerspectiveLH(width, height, znear, zfar, out result);
2122  return result;
2123  }
2124 
2125  /// <summary>
2126  /// Creates a right-handed, perspective projection matrix.
2127  /// </summary>
2128  /// <param name="width">Width of the viewing volume.</param>
2129  /// <param name="height">Height of the viewing volume.</param>
2130  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2131  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2132  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2133  public static void PerspectiveRH(float width, float height, float znear, float zfar, out Matrix result)
2134  {
2135  float halfWidth = width * 0.5f;
2136  float halfHeight = height * 0.5f;
2137 
2138  PerspectiveOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result);
2139  }
2140 
2141  /// <summary>
2142  /// Creates a right-handed, perspective projection matrix.
2143  /// </summary>
2144  /// <param name="width">Width of the viewing volume.</param>
2145  /// <param name="height">Height of the viewing volume.</param>
2146  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2147  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2148  /// <returns>The created projection matrix.</returns>
2149  public static Matrix PerspectiveRH(float width, float height, float znear, float zfar)
2150  {
2151  Matrix result;
2152  PerspectiveRH(width, height, znear, zfar, out result);
2153  return result;
2154  }
2155 
2156  /// <summary>
2157  /// Creates a left-handed, perspective projection matrix based on a field of view.
2158  /// </summary>
2159  /// <param name="fov">Field of view in the y direction, in radians.</param>
2160  /// <param name="aspect">Aspect ratio, defined as view space width divided by height.</param>
2161  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2162  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2163  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2164  public static void PerspectiveFovLH(float fov, float aspect, float znear, float zfar, out Matrix result)
2165  {
2166  float yScale = (float)(1.0 / Math.Tan(fov * 0.5f));
2167  float xScale = yScale / aspect;
2168 
2169  float halfWidth = znear / xScale;
2170  float halfHeight = znear / yScale;
2171 
2172  PerspectiveOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result);
2173  }
2174 
2175  /// <summary>
2176  /// Creates a left-handed, perspective projection matrix based on a field of view.
2177  /// </summary>
2178  /// <param name="fov">Field of view in the y direction, in radians.</param>
2179  /// <param name="aspect">Aspect ratio, defined as view space width divided by height.</param>
2180  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2181  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2182  /// <returns>The created projection matrix.</returns>
2183  public static Matrix PerspectiveFovLH(float fov, float aspect, float znear, float zfar)
2184  {
2185  Matrix result;
2186  PerspectiveFovLH(fov, aspect, znear, zfar, out result);
2187  return result;
2188  }
2189 
2190  /// <summary>
2191  /// Creates a right-handed, perspective projection matrix based on a field of view.
2192  /// </summary>
2193  /// <param name="fov">Field of view in the y direction, in radians.</param>
2194  /// <param name="aspect">Aspect ratio, defined as view space width divided by height.</param>
2195  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2196  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2197  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2198  public static void PerspectiveFovRH(float fov, float aspect, float znear, float zfar, out Matrix result)
2199  {
2200  float yScale = (float)(1.0 / Math.Tan(fov * 0.5f));
2201  float xScale = yScale / aspect;
2202 
2203  float halfWidth = znear / xScale;
2204  float halfHeight = znear / yScale;
2205 
2206  PerspectiveOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result);
2207  }
2208 
2209  /// <summary>
2210  /// Creates a right-handed, perspective projection matrix based on a field of view.
2211  /// </summary>
2212  /// <param name="fov">Field of view in the y direction, in radians.</param>
2213  /// <param name="aspect">Aspect ratio, defined as view space width divided by height.</param>
2214  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2215  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2216  /// <returns>The created projection matrix.</returns>
2217  public static Matrix PerspectiveFovRH(float fov, float aspect, float znear, float zfar)
2218  {
2219  Matrix result;
2220  PerspectiveFovRH(fov, aspect, znear, zfar, out result);
2221  return result;
2222  }
2223 
2224  /// <summary>
2225  /// Creates a left-handed, customized perspective projection matrix.
2226  /// </summary>
2227  /// <param name="left">Minimum x-value of the viewing volume.</param>
2228  /// <param name="right">Maximum x-value of the viewing volume.</param>
2229  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2230  /// <param name="top">Maximum y-value of the viewing volume.</param>
2231  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2232  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2233  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2234  public static void PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
2235  {
2236  float zRange = zfar / (zfar - znear);
2237 
2238  result = new Matrix();
2239  result.M11 = 2.0f * znear / (right - left);
2240  result.M22 = 2.0f * znear / (top - bottom);
2241  result.M31 = (left + right) / (left - right);
2242  result.M32 = (top + bottom) / (bottom - top);
2243  result.M33 = zRange;
2244  result.M34 = 1.0f;
2245  result.M43 = -znear * zRange;
2246  }
2247 
2248  /// <summary>
2249  /// Creates a left-handed, customized perspective projection matrix.
2250  /// </summary>
2251  /// <param name="left">Minimum x-value of the viewing volume.</param>
2252  /// <param name="right">Maximum x-value of the viewing volume.</param>
2253  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2254  /// <param name="top">Maximum y-value of the viewing volume.</param>
2255  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2256  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2257  /// <returns>The created projection matrix.</returns>
2258  public static Matrix PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar)
2259  {
2260  Matrix result;
2261  PerspectiveOffCenterLH(left, right, bottom, top, znear, zfar, out result);
2262  return result;
2263  }
2264 
2265  /// <summary>
2266  /// Creates a right-handed, customized perspective projection matrix.
2267  /// </summary>
2268  /// <param name="left">Minimum x-value of the viewing volume.</param>
2269  /// <param name="right">Maximum x-value of the viewing volume.</param>
2270  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2271  /// <param name="top">Maximum y-value of the viewing volume.</param>
2272  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2273  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2274  /// <param name="result">When the method completes, contains the created projection matrix.</param>
2275  public static void PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
2276  {
2277  PerspectiveOffCenterLH(left, right, bottom, top, znear, zfar, out result);
2278  result.M31 *= -1.0f;
2279  result.M32 *= -1.0f;
2280  result.M33 *= -1.0f;
2281  result.M34 *= -1.0f;
2282  }
2283 
2284  /// <summary>
2285  /// Creates a right-handed, customized perspective projection matrix.
2286  /// </summary>
2287  /// <param name="left">Minimum x-value of the viewing volume.</param>
2288  /// <param name="right">Maximum x-value of the viewing volume.</param>
2289  /// <param name="bottom">Minimum y-value of the viewing volume.</param>
2290  /// <param name="top">Maximum y-value of the viewing volume.</param>
2291  /// <param name="znear">Minimum z-value of the viewing volume.</param>
2292  /// <param name="zfar">Maximum z-value of the viewing volume.</param>
2293  /// <returns>The created projection matrix.</returns>
2294  public static Matrix PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar)
2295  {
2296  Matrix result;
2297  PerspectiveOffCenterRH(left, right, bottom, top, znear, zfar, out result);
2298  return result;
2299  }
2300 
2301  /// <summary>
2302  /// Builds a matrix that can be used to reflect vectors about a plane.
2303  /// </summary>
2304  /// <param name="plane">The plane for which the reflection occurs. This parameter is assumed to be normalized.</param>
2305  /// <param name="result">When the method completes, contains the reflection matrix.</param>
2306  public static void Reflection(ref Plane plane, out Matrix result)
2307  {
2308  float x = plane.Normal.X;
2309  float y = plane.Normal.Y;
2310  float z = plane.Normal.Z;
2311  float x2 = -2.0f * x;
2312  float y2 = -2.0f * y;
2313  float z2 = -2.0f * z;
2314 
2315  result.M11 = (x2 * x) + 1.0f;
2316  result.M12 = y2 * x;
2317  result.M13 = z2 * x;
2318  result.M14 = 0.0f;
2319  result.M21 = x2 * y;
2320  result.M22 = (y2 * y) + 1.0f;
2321  result.M23 = z2 * y;
2322  result.M24 = 0.0f;
2323  result.M31 = x2 * z;
2324  result.M32 = y2 * z;
2325  result.M33 = (z2 * z) + 1.0f;
2326  result.M34 = 0.0f;
2327  result.M41 = x2 * plane.D;
2328  result.M42 = y2 * plane.D;
2329  result.M43 = z2 * plane.D;
2330  result.M44 = 1.0f;
2331  }
2332 
2333  /// <summary>
2334  /// Builds a matrix that can be used to reflect vectors about a plane.
2335  /// </summary>
2336  /// <param name="plane">The plane for which the reflection occurs. This parameter is assumed to be normalized.</param>
2337  /// <returns>The reflection matrix.</returns>
2338  public static Matrix Reflection(Plane plane)
2339  {
2340  Matrix result;
2341  Reflection(ref plane, out result);
2342  return result;
2343  }
2344 
2345  /// <summary>
2346  /// Creates a matrix that flattens geometry into a shadow.
2347  /// </summary>
2348  /// <param name="light">The light direction. If the W component is 0, the light is directional light; if the
2349  /// W component is 1, the light is a point light.</param>
2350  /// <param name="plane">The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized.</param>
2351  /// <param name="result">When the method completes, contains the shadow matrix.</param>
2352  public static void Shadow(ref Vector4 light, ref Plane plane, out Matrix result)
2353  {
2354  float dot = (plane.Normal.X * light.X) + (plane.Normal.Y * light.Y) + (plane.Normal.Z * light.Z) + (plane.D * light.W);
2355  float x = -plane.Normal.X;
2356  float y = -plane.Normal.Y;
2357  float z = -plane.Normal.Z;
2358  float d = -plane.D;
2359 
2360  result.M11 = (x * light.X) + dot;
2361  result.M21 = y * light.X;
2362  result.M31 = z * light.X;
2363  result.M41 = d * light.X;
2364  result.M12 = x * light.Y;
2365  result.M22 = (y * light.Y) + dot;
2366  result.M32 = z * light.Y;
2367  result.M42 = d * light.Y;
2368  result.M13 = x * light.Z;
2369  result.M23 = y * light.Z;
2370  result.M33 = (z * light.Z) + dot;
2371  result.M43 = d * light.Z;
2372  result.M14 = x * light.W;
2373  result.M24 = y * light.W;
2374  result.M34 = z * light.W;
2375  result.M44 = (d * light.W) + dot;
2376  }
2377 
2378  /// <summary>
2379  /// Creates a matrix that flattens geometry into a shadow.
2380  /// </summary>
2381  /// <param name="light">The light direction. If the W component is 0, the light is directional light; if the
2382  /// W component is 1, the light is a point light.</param>
2383  /// <param name="plane">The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized.</param>
2384  /// <returns>The shadow matrix.</returns>
2385  public static Matrix Shadow(Vector4 light, Plane plane)
2386  {
2387  Matrix result;
2388  Shadow(ref light, ref plane, out result);
2389  return result;
2390  }
2391 
2392  /// <summary>
2393  /// Creates a matrix that scales along the x-axis, y-axis, and y-axis.
2394  /// </summary>
2395  /// <param name="scale">Scaling factor for all three axes.</param>
2396  /// <param name="result">When the method completes, contains the created scaling matrix.</param>
2397  public static void Scaling(ref Vector3 scale, out Matrix result)
2398  {
2399  Scaling(scale.X, scale.Y, scale.Z, out result);
2400  }
2401 
2402  /// <summary>
2403  /// Creates a matrix that scales along the x-axis, y-axis, and y-axis.
2404  /// </summary>
2405  /// <param name="scale">Scaling factor for all three axes.</param>
2406  /// <returns>The created scaling matrix.</returns>
2407  public static Matrix Scaling(Vector3 scale)
2408  {
2409  Matrix result;
2410  Scaling(ref scale, out result);
2411  return result;
2412  }
2413 
2414  /// <summary>
2415  /// Creates a matrix that scales along the x-axis, y-axis, and y-axis.
2416  /// </summary>
2417  /// <param name="x">Scaling factor that is applied along the x-axis.</param>
2418  /// <param name="y">Scaling factor that is applied along the y-axis.</param>
2419  /// <param name="z">Scaling factor that is applied along the z-axis.</param>
2420  /// <param name="result">When the method completes, contains the created scaling matrix.</param>
2421  public static void Scaling(float x, float y, float z, out Matrix result)
2422  {
2423  result = Matrix.Identity;
2424  result.M11 = x;
2425  result.M22 = y;
2426  result.M33 = z;
2427  }
2428 
2429  /// <summary>
2430  /// Creates a matrix that scales along the x-axis, y-axis, and y-axis.
2431  /// </summary>
2432  /// <param name="x">Scaling factor that is applied along the x-axis.</param>
2433  /// <param name="y">Scaling factor that is applied along the y-axis.</param>
2434  /// <param name="z">Scaling factor that is applied along the z-axis.</param>
2435  /// <returns>The created scaling matrix.</returns>
2436  public static Matrix Scaling(float x, float y, float z)
2437  {
2438  Matrix result;
2439  Scaling(x, y, z, out result);
2440  return result;
2441  }
2442 
2443  /// <summary>
2444  /// Creates a matrix that uniformally scales along all three axis.
2445  /// </summary>
2446  /// <param name="scale">The uniform scale that is applied along all axis.</param>
2447  /// <param name="result">When the method completes, contains the created scaling matrix.</param>
2448  public static void Scaling(float scale, out Matrix result)
2449  {
2450  result = Matrix.Identity;
2451  result.M11 = result.M22 = result.M33 = scale;
2452  }
2453 
2454  /// <summary>
2455  /// Creates a matrix that uniformally scales along all three axis.
2456  /// </summary>
2457  /// <param name="scale">The uniform scale that is applied along all axis.</param>
2458  /// <returns>The created scaling matrix.</returns>
2459  public static Matrix Scaling(float scale)
2460  {
2461  Matrix result;
2462  Scaling(scale, out result);
2463  return result;
2464  }
2465 
2466  /// <summary>
2467  /// Creates a matrix that rotates around the x-axis.
2468  /// </summary>
2469  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2470  /// <param name="result">When the method completes, contains the created rotation matrix.</param>
2471  public static void RotationX(float angle, out Matrix result)
2472  {
2473  float cos = (float)Math.Cos(angle);
2474  float sin = (float)Math.Sin(angle);
2475 
2476  result = Matrix.Identity;
2477  result.M22 = cos;
2478  result.M23 = sin;
2479  result.M32 = -sin;
2480  result.M33 = cos;
2481  }
2482 
2483  /// <summary>
2484  /// Creates a matrix that rotates around the x-axis.
2485  /// </summary>
2486  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2487  /// <returns>The created rotation matrix.</returns>
2488  public static Matrix RotationX(float angle)
2489  {
2490  Matrix result;
2491  RotationX(angle, out result);
2492  return result;
2493  }
2494 
2495  /// <summary>
2496  /// Creates a matrix that rotates around the y-axis.
2497  /// </summary>
2498  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2499  /// <param name="result">When the method completes, contains the created rotation matrix.</param>
2500  public static void RotationY(float angle, out Matrix result)
2501  {
2502  float cos = (float)Math.Cos(angle);
2503  float sin = (float)Math.Sin(angle);
2504 
2505  result = Matrix.Identity;
2506  result.M11 = cos;
2507  result.M13 = -sin;
2508  result.M31 = sin;
2509  result.M33 = cos;
2510  }
2511 
2512  /// <summary>
2513  /// Creates a matrix that rotates around the y-axis.
2514  /// </summary>
2515  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2516  /// <returns>The created rotation matrix.</returns>
2517  public static Matrix RotationY(float angle)
2518  {
2519  Matrix result;
2520  RotationY(angle, out result);
2521  return result;
2522  }
2523 
2524  /// <summary>
2525  /// Creates a matrix that rotates around the z-axis.
2526  /// </summary>
2527  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2528  /// <param name="result">When the method completes, contains the created rotation matrix.</param>
2529  public static void RotationZ(float angle, out Matrix result)
2530  {
2531  float cos = (float)Math.Cos(angle);
2532  float sin = (float)Math.Sin(angle);
2533 
2534  result = Matrix.Identity;
2535  result.M11 = cos;
2536  result.M12 = sin;
2537  result.M21 = -sin;
2538  result.M22 = cos;
2539  }
2540 
2541  /// <summary>
2542  /// Creates a matrix that rotates around the z-axis.
2543  /// </summary>
2544  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2545  /// <returns>The created rotation matrix.</returns>
2546  public static Matrix RotationZ(float angle)
2547  {
2548  Matrix result;
2549  RotationZ(angle, out result);
2550  return result;
2551  }
2552 
2553  /// <summary>
2554  /// Creates a matrix that rotates around an arbitary axis.
2555  /// </summary>
2556  /// <param name="axis">The axis around which to rotate. This parameter is assumed to be normalized.</param>
2557  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2558  /// <param name="result">When the method completes, contains the created rotation matrix.</param>
2559  public static void RotationAxis(ref Vector3 axis, float angle, out Matrix result)
2560  {
2561  float x = axis.X;
2562  float y = axis.Y;
2563  float z = axis.Z;
2564  float cos = (float)Math.Cos(angle);
2565  float sin = (float)Math.Sin(angle);
2566  float xx = x * x;
2567  float yy = y * y;
2568  float zz = z * z;
2569  float xy = x * y;
2570  float xz = x * z;
2571  float yz = y * z;
2572 
2573  result = Matrix.Identity;
2574  result.M11 = xx + (cos * (1.0f - xx));
2575  result.M12 = (xy - (cos * xy)) + (sin * z);
2576  result.M13 = (xz - (cos * xz)) - (sin * y);
2577  result.M21 = (xy - (cos * xy)) - (sin * z);
2578  result.M22 = yy + (cos * (1.0f - yy));
2579  result.M23 = (yz - (cos * yz)) + (sin * x);
2580  result.M31 = (xz - (cos * xz)) + (sin * y);
2581  result.M32 = (yz - (cos * yz)) - (sin * x);
2582  result.M33 = zz + (cos * (1.0f - zz));
2583  }
2584 
2585  /// <summary>
2586  /// Creates a matrix that rotates around an arbitary axis.
2587  /// </summary>
2588  /// <param name="axis">The axis around which to rotate. This parameter is assumed to be normalized.</param>
2589  /// <param name="angle">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
2590  /// <returns>The created rotation matrix.</returns>
2591  public static Matrix RotationAxis(Vector3 axis, float angle)
2592  {
2593  Matrix result;
2594  RotationAxis(ref axis, angle, out result);
2595  return result;
2596  }
2597 
2598  /// <summary>
2599  /// Creates a rotation matrix from a quaternion.
2600  /// </summary>
2601  /// <param name="rotation">The quaternion to use to build the matrix.</param>
2602  /// <param name="result">The created rotation matrix.</param>
2603  public static void RotationQuaternion(ref Quaternion rotation, out Matrix result)
2604  {
2605  float xx = rotation.X * rotation.X;
2606  float yy = rotation.Y * rotation.Y;
2607  float zz = rotation.Z * rotation.Z;
2608  float xy = rotation.X * rotation.Y;
2609  float zw = rotation.Z * rotation.W;
2610  float zx = rotation.Z * rotation.X;
2611  float yw = rotation.Y * rotation.W;
2612  float yz = rotation.Y * rotation.Z;
2613  float xw = rotation.X * rotation.W;
2614 
2615  result = Matrix.Identity;
2616  result.M11 = 1.0f - (2.0f * (yy + zz));
2617  result.M12 = 2.0f * (xy + zw);
2618  result.M13 = 2.0f * (zx - yw);
2619  result.M21 = 2.0f * (xy - zw);
2620  result.M22 = 1.0f - (2.0f * (zz + xx));
2621  result.M23 = 2.0f * (yz + xw);
2622  result.M31 = 2.0f * (zx + yw);
2623  result.M32 = 2.0f * (yz - xw);
2624  result.M33 = 1.0f - (2.0f * (yy + xx));
2625  }
2626 
2627  /// <summary>
2628  /// Creates a rotation matrix from a quaternion.
2629  /// </summary>
2630  /// <param name="rotation">The quaternion to use to build the matrix.</param>
2631  /// <returns>The created rotation matrix.</returns>
2632  public static Matrix RotationQuaternion(Quaternion rotation)
2633  {
2634  Matrix result;
2635  RotationQuaternion(ref rotation, out result);
2636  return result;
2637  }
2638 
2639  /// <summary>
2640  /// Creates a rotation matrix with a specified yaw, pitch, and roll.
2641  /// </summary>
2642  /// <param name="yaw">Yaw around the y-axis, in radians.</param>
2643  /// <param name="pitch">Pitch around the x-axis, in radians.</param>
2644  /// <param name="roll">Roll around the z-axis, in radians.</param>
2645  /// <param name="result">When the method completes, contains the created rotation matrix.</param>
2646  public static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Matrix result)
2647  {
2648  Quaternion quaternion = new Quaternion();
2649  Quaternion.RotationYawPitchRoll(yaw, pitch, roll, out quaternion);
2650  RotationQuaternion(ref quaternion, out result);
2651  }
2652 
2653  /// <summary>
2654  /// Creates a rotation matrix with a specified yaw, pitch, and roll.
2655  /// </summary>
2656  /// <param name="yaw">Yaw around the y-axis, in radians.</param>
2657  /// <param name="pitch">Pitch around the x-axis, in radians.</param>
2658  /// <param name="roll">Roll around the z-axis, in radians.</param>
2659  /// <returns>The created rotation matrix.</returns>
2660  public static Matrix RotationYawPitchRoll(float yaw, float pitch, float roll)
2661  {
2662  Matrix result;
2663  RotationYawPitchRoll(yaw, pitch, roll, out result);
2664  return result;
2665  }
2666 
2667  /// <summary>
2668  /// Creates a translation matrix using the specified offsets.
2669  /// </summary>
2670  /// <param name="value">The offset for all three coordinate planes.</param>
2671  /// <param name="result">When the method completes, contains the created translation matrix.</param>
2672  public static void Translation(ref Vector3 value, out Matrix result)
2673  {
2674  Translation(value.X, value.Y, value.Z, out result);
2675  }
2676 
2677  /// <summary>
2678  /// Creates a translation matrix using the specified offsets.
2679  /// </summary>
2680  /// <param name="value">The offset for all three coordinate planes.</param>
2681  /// <returns>The created translation matrix.</returns>
2682  public static Matrix Translation(Vector3 value)
2683  {
2684  Matrix result;
2685  Translation(ref value, out result);
2686  return result;
2687  }
2688 
2689  /// <summary>
2690  /// Creates a translation matrix using the specified offsets.
2691  /// </summary>
2692  /// <param name="x">X-coordinate offset.</param>
2693  /// <param name="y">Y-coordinate offset.</param>
2694  /// <param name="z">Z-coordinate offset.</param>
2695  /// <param name="result">When the method completes, contains the created translation matrix.</param>
2696  public static void Translation(float x, float y, float z, out Matrix result)
2697  {
2698  result = Matrix.Identity;
2699  result.M41 = x;
2700  result.M42 = y;
2701  result.M43 = z;
2702  }
2703 
2704  /// <summary>
2705  /// Creates a translation matrix using the specified offsets.
2706  /// </summary>
2707  /// <param name="x">X-coordinate offset.</param>
2708  /// <param name="y">Y-coordinate offset.</param>
2709  /// <param name="z">Z-coordinate offset.</param>
2710  /// <returns>The created translation matrix.</returns>
2711  public static Matrix Translation(float x, float y, float z)
2712  {
2713  Matrix result;
2714  Translation(x, y, z, out result);
2715  return result;
2716  }
2717 
2718  /// <summary>
2719  /// Creates a 3D affine transformation matrix.
2720  /// </summary>
2721  /// <param name="scaling">Scaling factor.</param>
2722  /// <param name="rotation">The rotation of the transformation.</param>
2723  /// <param name="translation">The translation factor of the transformation.</param>
2724  /// <param name="result">When the method completes, contains the created affine transformation matrix.</param>
2725  public static void AffineTransformation(float scaling, ref Quaternion rotation, ref Vector3 translation, out Matrix result)
2726  {
2727  result = Scaling(scaling) * RotationQuaternion(rotation) * Translation(translation);
2728  }
2729 
2730  /// <summary>
2731  /// Creates a 3D affine transformation matrix.
2732  /// </summary>
2733  /// <param name="scaling">Scaling factor.</param>
2734  /// <param name="rotation">The rotation of the transformation.</param>
2735  /// <param name="translation">The translation factor of the transformation.</param>
2736  /// <returns>The created affine transformation matrix.</returns>
2737  public static Matrix AffineTransformation(float scaling, Quaternion rotation, Vector3 translation)
2738  {
2739  Matrix result;
2740  AffineTransformation(scaling, ref rotation, ref translation, out result);
2741  return result;
2742  }
2743 
2744  /// <summary>
2745  /// Creates a 3D affine transformation matrix.
2746  /// </summary>
2747  /// <param name="scaling">Scaling factor.</param>
2748  /// <param name="rotationCenter">The center of the rotation.</param>
2749  /// <param name="rotation">The rotation of the transformation.</param>
2750  /// <param name="translation">The translation factor of the transformation.</param>
2751  /// <param name="result">When the method completes, contains the created affine transformation matrix.</param>
2752  public static void AffineTransformation(float scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result)
2753  {
2754  result = Scaling(scaling) * Translation(-rotationCenter) * RotationQuaternion(rotation) *
2755  Translation(rotationCenter) * Translation(translation);
2756  }
2757 
2758  /// <summary>
2759  /// Creates a 3D affine transformation matrix.
2760  /// </summary>
2761  /// <param name="scaling">Scaling factor.</param>
2762  /// <param name="rotationCenter">The center of the rotation.</param>
2763  /// <param name="rotation">The rotation of the transformation.</param>
2764  /// <param name="translation">The translation factor of the transformation.</param>
2765  /// <returns>The created affine transformation matrix.</returns>
2766  public static Matrix AffineTransformation(float scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation)
2767  {
2768  Matrix result;
2769  AffineTransformation(scaling, ref rotationCenter, ref rotation, ref translation, out result);
2770  return result;
2771  }
2772 
2773  /// <summary>
2774  /// Creates a 2D affine transformation matrix.
2775  /// </summary>
2776  /// <param name="scaling">Scaling factor.</param>
2777  /// <param name="rotation">The rotation of the transformation.</param>
2778  /// <param name="translation">The translation factor of the transformation.</param>
2779  /// <param name="result">When the method completes, contains the created affine transformation matrix.</param>
2780  public static void AffineTransformation2D(float scaling, float rotation, ref Vector2 translation, out Matrix result)
2781  {
2782  result = Scaling(scaling, scaling, 1.0f) * RotationZ(rotation) * Translation((Vector3)translation);
2783  }
2784 
2785  /// <summary>
2786  /// Creates a 2D affine transformation matrix.
2787  /// </summary>
2788  /// <param name="scaling">Scaling factor.</param>
2789  /// <param name="rotation">The rotation of the transformation.</param>
2790  /// <param name="translation">The translation factor of the transformation.</param>
2791  /// <returns>The created affine transformation matrix.</returns>
2792  public static Matrix AffineTransformation2D(float scaling, float rotation, Vector2 translation)
2793  {
2794  Matrix result;
2795  AffineTransformation2D(scaling, rotation, ref translation, out result);
2796  return result;
2797  }
2798 
2799  /// <summary>
2800  /// Creates a 2D affine transformation matrix.
2801  /// </summary>
2802  /// <param name="scaling">Scaling factor.</param>
2803  /// <param name="rotationCenter">The center of the rotation.</param>
2804  /// <param name="rotation">The rotation of the transformation.</param>
2805  /// <param name="translation">The translation factor of the transformation.</param>
2806  /// <param name="result">When the method completes, contains the created affine transformation matrix.</param>
2807  public static void AffineTransformation2D(float scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result)
2808  {
2809  result = Scaling(scaling, scaling, 1.0f) * Translation((Vector3)(-rotationCenter)) * RotationZ(rotation) *
2810  Translation((Vector3)rotationCenter) * Translation((Vector3)translation);
2811  }
2812 
2813  /// <summary>
2814  /// Creates a 2D affine transformation matrix.
2815  /// </summary>
2816  /// <param name="scaling">Scaling factor.</param>
2817  /// <param name="rotationCenter">The center of the rotation.</param>
2818  /// <param name="rotation">The rotation of the transformation.</param>
2819  /// <param name="translation">The translation factor of the transformation.</param>
2820  /// <returns>The created affine transformation matrix.</returns>
2821  public static Matrix AffineTransformation2D(float scaling, Vector2 rotationCenter, float rotation, Vector2 translation)
2822  {
2823  Matrix result;
2824  AffineTransformation2D(scaling, ref rotationCenter, rotation, ref translation, out result);
2825  return result;
2826  }
2827 
2828  /// <summary>
2829  /// Creates a transformation matrix.
2830  /// </summary>
2831  /// <param name="scalingCenter">Center point of the scaling operation.</param>
2832  /// <param name="scalingRotation">Scaling rotation amount.</param>
2833  /// <param name="scaling">Scaling factor.</param>
2834  /// <param name="rotationCenter">The center of the rotation.</param>
2835  /// <param name="rotation">The rotation of the transformation.</param>
2836  /// <param name="translation">The translation factor of the transformation.</param>
2837  /// <param name="result">When the method completes, contains the created transformation matrix.</param>
2838  public static void Transformation(ref Vector3 scalingCenter, ref Quaternion scalingRotation, ref Vector3 scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result)
2839  {
2840  Matrix sr = RotationQuaternion(scalingRotation);
2841 
2842  result = Translation(-scalingCenter) * Transpose(sr) * Scaling(scaling) * sr * Translation(scalingCenter) * Translation(-rotationCenter) *
2843  RotationQuaternion(rotation) * Translation(rotationCenter) * Translation(translation);
2844  }
2845 
2846  /// <summary>
2847  /// Creates a transformation matrix.
2848  /// </summary>
2849  /// <param name="scalingCenter">Center point of the scaling operation.</param>
2850  /// <param name="scalingRotation">Scaling rotation amount.</param>
2851  /// <param name="scaling">Scaling factor.</param>
2852  /// <param name="rotationCenter">The center of the rotation.</param>
2853  /// <param name="rotation">The rotation of the transformation.</param>
2854  /// <param name="translation">The translation factor of the transformation.</param>
2855  /// <returns>The created transformation matrix.</returns>
2856  public static Matrix Transformation(Vector3 scalingCenter, Quaternion scalingRotation, Vector3 scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation)
2857  {
2858  Matrix result;
2859  Transformation(ref scalingCenter, ref scalingRotation, ref scaling, ref rotationCenter, ref rotation, ref translation, out result);
2860  return result;
2861  }
2862 
2863  /// <summary>
2864  /// Creates a 2D transformation matrix.
2865  /// </summary>
2866  /// <param name="scalingCenter">Center point of the scaling operation.</param>
2867  /// <param name="scalingRotation">Scaling rotation amount.</param>
2868  /// <param name="scaling">Scaling factor.</param>
2869  /// <param name="rotationCenter">The center of the rotation.</param>
2870  /// <param name="rotation">The rotation of the transformation.</param>
2871  /// <param name="translation">The translation factor of the transformation.</param>
2872  /// <param name="result">When the method completes, contains the created transformation matrix.</param>
2873  public static void Transformation2D(ref Vector2 scalingCenter, float scalingRotation, ref Vector2 scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result)
2874  {
2875  result = Translation((Vector3)(-scalingCenter)) * RotationZ(-scalingRotation) * Scaling((Vector3)scaling) * RotationZ(scalingRotation) * Translation((Vector3)scalingCenter) *
2876  Translation((Vector3)(-rotationCenter)) * RotationZ(rotation) * Translation((Vector3)rotationCenter) * Translation((Vector3)translation);
2877 
2878  result.M33 = 1f;
2879  result.M44 = 1f;
2880  }
2881 
2882  /// <summary>
2883  /// Creates a 2D transformation matrix.
2884  /// </summary>
2885  /// <param name="scalingCenter">Center point of the scaling operation.</param>
2886  /// <param name="scalingRotation">Scaling rotation amount.</param>
2887  /// <param name="scaling">Scaling factor.</param>
2888  /// <param name="rotationCenter">The center of the rotation.</param>
2889  /// <param name="rotation">The rotation of the transformation.</param>
2890  /// <param name="translation">The translation factor of the transformation.</param>
2891  /// <returns>The created transformation matrix.</returns>
2892  public static Matrix Transformation2D(Vector2 scalingCenter, float scalingRotation, Vector2 scaling, Vector2 rotationCenter, float rotation, Vector2 translation)
2893  {
2894  Matrix result;
2895  Transformation2D(ref scalingCenter, scalingRotation, ref scaling, ref rotationCenter, rotation, ref translation, out result);
2896  return result;
2897  }
2898 
2899  /// <summary>
2900  /// Copies a nxm matrix to this instance.
2901  /// </summary>
2902  /// <param name="src">The source matrix.</param>
2903  /// <param name="columns">The number of columns.</param>
2904  /// <param name="rows">The number of rows.</param>
2905  public unsafe void CopyMatrixFrom(float* src, int columns, int rows)
2906  {
2907  fixed (void* pDest = &this)
2908  {
2909  var dest = (float*)pDest;
2910  for (int i = 0; i < rows; ++i)
2911  {
2912  for (int j = 0; j < columns; ++j)
2913  {
2914  dest[j] = src[j];
2915  }
2916  dest += 4;
2917  src += rows;
2918  }
2919  }
2920  }
2921 
2922  /// <summary>
2923  /// Transposes a nmx matrix to this instance.
2924  /// </summary>
2925  /// <param name="src">The SRC.</param>
2926  /// <param name="columns">The columns.</param>
2927  /// <param name="rows">The rows.</param>
2928  public unsafe void TransposeMatrixFrom(float* src, int columns, int rows)
2929  {
2930  fixed(void* pDest = &this)
2931  {
2932  var dest = (float*) pDest;
2933  for (int i = 0; i < rows; ++i)
2934  {
2935  int sourceIndex = i;
2936  for (int j = 0; j < columns; ++j)
2937  {
2938  dest[j] = src[sourceIndex];
2939  sourceIndex += rows;
2940  }
2941  dest += 4;
2942  }
2943  }
2944  }
2945 
2946  /// <summary>
2947  /// Adds two matricies.
2948  /// </summary>
2949  /// <param name="left">The first matrix to add.</param>
2950  /// <param name="right">The second matrix to add.</param>
2951  /// <returns>The sum of the two matricies.</returns>
2952  public static Matrix operator +(Matrix left, Matrix right)
2953  {
2954  Matrix result;
2955  Add(ref left, ref right, out result);
2956  return result;
2957  }
2958 
2959  /// <summary>
2960  /// Assert a matrix (return it unchanged).
2961  /// </summary>
2962  /// <param name="value">The matrix to assert (unchange).</param>
2963  /// <returns>The asserted (unchanged) matrix.</returns>
2964  public static Matrix operator +(Matrix value)
2965  {
2966  return value;
2967  }
2968 
2969  /// <summary>
2970  /// Subtracts two matricies.
2971  /// </summary>
2972  /// <param name="left">The first matrix to subtract.</param>
2973  /// <param name="right">The second matrix to subtract.</param>
2974  /// <returns>The difference between the two matricies.</returns>
2975  public static Matrix operator -(Matrix left, Matrix right)
2976  {
2977  Matrix result;
2978  Subtract(ref left, ref right, out result);
2979  return result;
2980  }
2981 
2982  /// <summary>
2983  /// Negates a matrix.
2984  /// </summary>
2985  /// <param name="value">The matrix to negate.</param>
2986  /// <returns>The negated matrix.</returns>
2987  public static Matrix operator -(Matrix value)
2988  {
2989  Matrix result;
2990  Negate(ref value, out result);
2991  return result;
2992  }
2993 
2994  /// <summary>
2995  /// Scales a matrix by a given value.
2996  /// </summary>
2997  /// <param name="right">The matrix to scale.</param>
2998  /// <param name="left">The amount by which to scale.</param>
2999  /// <returns>The scaled matrix.</returns>
3000  public static Matrix operator *(float left, Matrix right)
3001  {
3002  Matrix result;
3003  Multiply(ref right, left, out result);
3004  return result;
3005  }
3006 
3007  /// <summary>
3008  /// Scales a matrix by a given value.
3009  /// </summary>
3010  /// <param name="left">The matrix to scale.</param>
3011  /// <param name="right">The amount by which to scale.</param>
3012  /// <returns>The scaled matrix.</returns>
3013  public static Matrix operator *(Matrix left, float right)
3014  {
3015  Matrix result;
3016  Multiply(ref left, right, out result);
3017  return result;
3018  }
3019 
3020  /// <summary>
3021  /// Multiplies two matrices.
3022  /// </summary>
3023  /// <param name="left">The first matrix to multiply.</param>
3024  /// <param name="right">The second matrix to multiply.</param>
3025  /// <returns>The product of the two matricies.</returns>
3026  public static Matrix operator *(Matrix left, Matrix right)
3027  {
3028  Matrix result;
3029  Multiply(ref left, ref right, out result);
3030  return result;
3031  }
3032 
3033  /// <summary>
3034  /// Scales a matrix by a given value.
3035  /// </summary>
3036  /// <param name="left">The matrix to scale.</param>
3037  /// <param name="right">The amount by which to scale.</param>
3038  /// <returns>The scaled matrix.</returns>
3039  public static Matrix operator /(Matrix left, float right)
3040  {
3041  Matrix result;
3042  Divide(ref left, right, out result);
3043  return result;
3044  }
3045 
3046  /// <summary>
3047  /// Divides two matricies.
3048  /// </summary>
3049  /// <param name="left">The first matrix to divide.</param>
3050  /// <param name="right">The second matrix to divide.</param>
3051  /// <returns>The quotient of the two matricies.</returns>
3052  public static Matrix operator /(Matrix left, Matrix right)
3053  {
3054  Matrix result;
3055  Divide(ref left, ref right, out result);
3056  return result;
3057  }
3058 
3059  /// <summary>
3060  /// Tests for equality between two objects.
3061  /// </summary>
3062  /// <param name="left">The first value to compare.</param>
3063  /// <param name="right">The second value to compare.</param>
3064  /// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
3065  public static bool operator ==(Matrix left, Matrix right)
3066  {
3067  return left.Equals(right);
3068  }
3069 
3070  /// <summary>
3071  /// Tests for inequality between two objects.
3072  /// </summary>
3073  /// <param name="left">The first value to compare.</param>
3074  /// <param name="right">The second value to compare.</param>
3075  /// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
3076  public static bool operator !=(Matrix left, Matrix right)
3077  {
3078  return !left.Equals(right);
3079  }
3080 
3081  /// <summary>
3082  /// Returns a <see cref="System.String"/> that represents this instance.
3083  /// </summary>
3084  /// <returns>
3085  /// A <see cref="System.String"/> that represents this instance.
3086  /// </returns>
3087  public override string ToString()
3088  {
3089  return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]",
3090  M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44);
3091  }
3092 
3093  /// <summary>
3094  /// Returns a <see cref="System.String"/> that represents this instance.
3095  /// </summary>
3096  /// <param name="format">The format.</param>
3097  /// <returns>
3098  /// A <see cref="System.String"/> that represents this instance.
3099  /// </returns>
3100  public string ToString(string format)
3101  {
3102  if (format == null)
3103  return ToString();
3104 
3105  return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]",
3106  M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), M13.ToString(format, CultureInfo.CurrentCulture), M14.ToString(format, CultureInfo.CurrentCulture),
3107  M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), M23.ToString(format, CultureInfo.CurrentCulture), M24.ToString(format, CultureInfo.CurrentCulture),
3108  M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture), M33.ToString(format, CultureInfo.CurrentCulture), M34.ToString(format, CultureInfo.CurrentCulture),
3109  M41.ToString(format, CultureInfo.CurrentCulture), M42.ToString(format, CultureInfo.CurrentCulture), M43.ToString(format, CultureInfo.CurrentCulture), M44.ToString(format, CultureInfo.CurrentCulture));
3110  }
3111 
3112  /// <summary>
3113  /// Returns a <see cref="System.String"/> that represents this instance.
3114  /// </summary>
3115  /// <param name="formatProvider">The format provider.</param>
3116  /// <returns>
3117  /// A <see cref="System.String"/> that represents this instance.
3118  /// </returns>
3119  public string ToString(IFormatProvider formatProvider)
3120  {
3121  return string.Format(formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]",
3122  M11.ToString(formatProvider), M12.ToString(formatProvider), M13.ToString(formatProvider), M14.ToString(formatProvider),
3123  M21.ToString(formatProvider), M22.ToString(formatProvider), M23.ToString(formatProvider), M24.ToString(formatProvider),
3124  M31.ToString(formatProvider), M32.ToString(formatProvider), M33.ToString(formatProvider), M34.ToString(formatProvider),
3125  M41.ToString(formatProvider), M42.ToString(formatProvider), M43.ToString(formatProvider), M44.ToString(formatProvider));
3126  }
3127 
3128  /// <summary>
3129  /// Returns a <see cref="System.String"/> that represents this instance.
3130  /// </summary>
3131  /// <param name="format">The format.</param>
3132  /// <param name="formatProvider">The format provider.</param>
3133  /// <returns>
3134  /// A <see cref="System.String"/> that represents this instance.
3135  /// </returns>
3136  public string ToString(string format, IFormatProvider formatProvider)
3137  {
3138  if (format == null)
3139  return ToString(formatProvider);
3140 
3141  return string.Format(format, formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]",
3142  M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), M13.ToString(format, formatProvider), M14.ToString(format, formatProvider),
3143  M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), M23.ToString(format, formatProvider), M24.ToString(format, formatProvider),
3144  M31.ToString(format, formatProvider), M32.ToString(format, formatProvider), M33.ToString(format, formatProvider), M34.ToString(format, formatProvider),
3145  M41.ToString(format, formatProvider), M42.ToString(format, formatProvider), M43.ToString(format, formatProvider), M44.ToString(format, formatProvider));
3146  }
3147 
3148  /// <summary>
3149  /// Returns a hash code for this instance.
3150  /// </summary>
3151  /// <returns>
3152  /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
3153  /// </returns>
3154  public override int GetHashCode()
3155  {
3156  return M11.GetHashCode() + M12.GetHashCode() + M13.GetHashCode() + M14.GetHashCode() +
3157  M21.GetHashCode() + M22.GetHashCode() + M23.GetHashCode() + M24.GetHashCode() +
3158  M31.GetHashCode() + M32.GetHashCode() + M33.GetHashCode() + M34.GetHashCode() +
3159  M41.GetHashCode() + M42.GetHashCode() + M43.GetHashCode() + M44.GetHashCode();
3160  }
3161 
3162  /// <summary>
3163  /// Determines whether the specified <see cref="SiliconStudio.Core.Mathematics.Matrix"/> is equal to this instance.
3164  /// </summary>
3165  /// <param name="other">The <see cref="SiliconStudio.Core.Mathematics.Matrix"/> to compare with this instance.</param>
3166  /// <returns>
3167  /// <c>true</c> if the specified <see cref="SiliconStudio.Core.Mathematics.Matrix"/> is equal to this instance; otherwise, <c>false</c>.
3168  /// </returns>
3169  public bool Equals(Matrix other)
3170  {
3171  return (Math.Abs(other.M11 - M11) < MathUtil.ZeroTolerance &&
3172  Math.Abs(other.M12 - M12) < MathUtil.ZeroTolerance &&
3173  Math.Abs(other.M13 - M13) < MathUtil.ZeroTolerance &&
3174  Math.Abs(other.M14 - M14) < MathUtil.ZeroTolerance &&
3175 
3176  Math.Abs(other.M21 - M21) < MathUtil.ZeroTolerance &&
3177  Math.Abs(other.M22 - M22) < MathUtil.ZeroTolerance &&
3178  Math.Abs(other.M23 - M23) < MathUtil.ZeroTolerance &&
3179  Math.Abs(other.M24 - M24) < MathUtil.ZeroTolerance &&
3180 
3181  Math.Abs(other.M31 - M31) < MathUtil.ZeroTolerance &&
3182  Math.Abs(other.M32 - M32) < MathUtil.ZeroTolerance &&
3183  Math.Abs(other.M33 - M33) < MathUtil.ZeroTolerance &&
3184  Math.Abs(other.M34 - M34) < MathUtil.ZeroTolerance &&
3185 
3186  Math.Abs(other.M41 - M41) < MathUtil.ZeroTolerance &&
3187  Math.Abs(other.M42 - M42) < MathUtil.ZeroTolerance &&
3188  Math.Abs(other.M43 - M43) < MathUtil.ZeroTolerance &&
3189  Math.Abs(other.M44 - M44) < MathUtil.ZeroTolerance);
3190  }
3191 
3192  /// <summary>
3193  /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
3194  /// </summary>
3195  /// <param name="value">The <see cref="System.Object"/> to compare with this instance.</param>
3196  /// <returns>
3197  /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
3198  /// </returns>
3199  public override bool Equals(object value)
3200  {
3201  if (value == null)
3202  return false;
3203 
3204  if (value.GetType() != GetType())
3205  return false;
3206 
3207  return Equals((Matrix)value);
3208  }
3209 
3210 #if SlimDX1xInterop
3211  /// <summary>
3212  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Matrix"/> to <see cref="SlimDX.Matrix"/>.
3213  /// </summary>
3214  /// <param name="value">The value.</param>
3215  /// <returns>The result of the conversion.</returns>
3216  public static implicit operator SlimDX.Matrix(Matrix value)
3217  {
3218  return new SlimDX.Matrix()
3219  {
3220  M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14,
3221  M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24,
3222  M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34,
3223  M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44
3224  };
3225  }
3226 
3227  /// <summary>
3228  /// Performs an implicit conversion from <see cref="SlimDX.Matrix"/> to <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
3229  /// </summary>
3230  /// <param name="value">The value.</param>
3231  /// <returns>The result of the conversion.</returns>
3232  public static implicit operator Matrix(SlimDX.Matrix value)
3233  {
3234  return new Matrix()
3235  {
3236  M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14,
3237  M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24,
3238  M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34,
3239  M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44
3240  };
3241  }
3242 #endif
3243 
3244 #if WPFInterop
3245  /// <summary>
3246  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Matrix"/> to <see cref="System.Windows.Media.Media3D.Matrix3D"/>.
3247  /// </summary>
3248  /// <param name="value">The value.</param>
3249  /// <returns>The result of the conversion.</returns>
3250  public static implicit operator System.Windows.Media.Media3D.Matrix3D(Matrix value)
3251  {
3252  return new System.Windows.Media.Media3D.Matrix3D()
3253  {
3254  M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14,
3255  M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24,
3256  M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34,
3257  OffsetX = value.M41, OffsetY = value.M42, OffsetZ = value.M43, M44 = value.M44
3258  };
3259  }
3260 
3261  /// <summary>
3262  /// Performs an explicit conversion from <see cref="System.Windows.Media.Media3D.Matrix3D"/> to <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
3263  /// </summary>
3264  /// <param name="value">The value.</param>
3265  /// <returns>The result of the conversion.</returns>
3266  public static explicit operator Matrix(System.Windows.Media.Media3D.Matrix3D value)
3267  {
3268  return new Matrix()
3269  {
3270  M11 = (float)value.M11, M12 = (float)value.M12, M13 = (float)value.M13, M14 = (float)value.M14,
3271  M21 = (float)value.M21, M22 = (float)value.M22, M23 = (float)value.M23, M24 = (float)value.M24,
3272  M31 = (float)value.M31, M32 = (float)value.M32, M33 = (float)value.M33, M34 = (float)value.M34,
3273  M41 = (float)value.OffsetX, M42 = (float)value.OffsetY, M43 = (float)value.OffsetZ, M44 = (float)value.M44
3274  };
3275  }
3276 #endif
3277 
3278 #if XnaInterop
3279  /// <summary>
3280  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.Matrix"/> to <see cref="Microsoft.Xna.Framework.Matrix"/>.
3281  /// </summary>
3282  /// <param name="value">The value.</param>
3283  /// <returns>The result of the conversion.</returns>
3284  public static implicit operator Microsoft.Xna.Framework.Matrix(Matrix value)
3285  {
3286  return new Microsoft.Xna.Framework.Matrix()
3287  {
3288  M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14,
3289  M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24,
3290  M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34,
3291  M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44
3292  };
3293  }
3294 
3295  /// <summary>
3296  /// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Matrix"/> to <see cref="SiliconStudio.Core.Mathematics.Matrix"/>.
3297  /// </summary>
3298  /// <param name="value">The value.</param>
3299  /// <returns>The result of the conversion.</returns>
3300  public static implicit operator Matrix(Microsoft.Xna.Framework.Matrix value)
3301  {
3302  return new Matrix()
3303  {
3304  M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14,
3305  M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24,
3306  M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34,
3307  M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44
3308  };
3309  }
3310 #endif
3311  }
3312 }
static Matrix RotationZ(float angle)
Creates a matrix that rotates around the z-axis.
Definition: Matrix.cs:2546
void Normalize()
Converts the vector into a unit vector.
Definition: Vector4.cs:248
static void RotationQuaternion(ref Quaternion rotation, out Matrix result)
Creates a rotation matrix from a quaternion.
Definition: Matrix.cs:2603
unsafe void CopyMatrixFrom(float *src, int columns, int rows)
Copies a nxm matrix to this instance.
Definition: Matrix.cs:2905
void DecomposeXYZ(out Vector3 rotation)
Decomposes a rotation matrix with the specified X, Y and Z euler angles. Matrix.RotationX(rotation.X) * Matrix.RotationY(rotation.Y) * Matrix.RotationZ(rotation.Z) should represent the same rotation.
Definition: Matrix.cs:582
static Matrix OrthoLH(float width, float height, float znear, float zfar)
Creates a left-handed, orthographic projection matrix.
Definition: Matrix.cs:1983
FbxDouble3 operator*(double factor, FbxDouble3 vector)
bool Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation)
Decomposes a matrix into a scale, rotation, and translation.
Definition: Matrix.cs:607
static void Translation(float x, float y, float z, out Matrix result)
Creates a translation matrix using the specified offsets.
Definition: Matrix.cs:2696
float M22
Value at row 2 column 2 of the matrix.
Definition: Matrix.cs:97
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
function b
static void LowerTriangularForm(ref Matrix value, out Matrix result)
Brings the matrix into lower triangular form using elementry row operations.
Definition: Matrix.cs:1546
static Matrix PerspectiveFovLH(float fov, float aspect, float znear, float zfar)
Creates a left-handed, perspective projection matrix based on a field of view.
Definition: Matrix.cs:2183
static Matrix Scaling(float scale)
Creates a matrix that uniformally scales along all three axis.
Definition: Matrix.cs:2459
function a
static void RowEchelonForm(ref Matrix value, out Matrix result)
Brings the matrix into row echelon form using elementry row operations;
Definition: Matrix.cs:1624
static void PerspectiveFovRH(float fov, float aspect, float znear, float zfar, out Matrix result)
Creates a right-handed, perspective projection matrix based on a field of view.
Definition: Matrix.cs:2198
float[] ToArray()
Creates an array containing the elements of the matrix.
Definition: Matrix.cs:725
static void Scaling(ref Vector3 scale, out Matrix result)
Creates a matrix that scales along the x-axis, y-axis, and y-axis.
Definition: Matrix.cs:2397
static void RotationAxis(ref Vector3 axis, float angle, out Matrix result)
Creates a matrix that rotates around an arbitary axis.
Definition: Matrix.cs:2559
static void Orthogonalize(ref Matrix value, out Matrix result)
Orthogonalizes the specified matrix.
Definition: Matrix.cs:1340
float M21
Value at row 2 column 1 of the matrix.
Definition: Matrix.cs:77
static void PerspectiveLH(float width, float height, float znear, float zfar, out Matrix result)
Creates a left-handed, perspective projection matrix.
Definition: Matrix.cs:2102
static void Negate(ref Matrix value, out Matrix result)
Negates a matrix.
Definition: Matrix.cs:1090
void Invert()
Inverts the matrix.
Definition: Matrix.cs:447
static Matrix Scaling(float x, float y, float z)
Creates a matrix that scales along the x-axis, y-axis, and y-axis.
Definition: Matrix.cs:2436
static void OrthoLH(float width, float height, float znear, float zfar, out Matrix result)
Creates a left-handed, orthographic projection matrix.
Definition: Matrix.cs:1967
Matrix(float[] values)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Matrix struct.
Definition: Matrix.cs:197
static void Billboard(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Matrix result)
Creates a spherical billboard that rotates around a specified object position.
Definition: Matrix.cs:1826
static void Subtract(ref Matrix left, ref Matrix right, out Matrix result)
Determines the difference between two matrices.
Definition: Matrix.cs:775
static Matrix Reflection(Plane plane)
Builds a matrix that can be used to reflect vectors about a plane.
Definition: Matrix.cs:2338
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
static void Divide(ref Matrix left, float right, out Matrix result)
Scales a matrix by the given value.
Definition: Matrix.cs:951
static Matrix PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar)
Creates a left-handed, customized perspective projection matrix.
Definition: Matrix.cs:2258
override int GetHashCode()
Returns a hash code for this instance.
Definition: Matrix.cs:3154
static Matrix Exponent(Matrix value, int exponent)
Performs the exponential operation on a matrix.
Definition: Matrix.cs:1078
string ToString(string format)
Returns a System.String that represents this instance.
Definition: Matrix.cs:3100
static Matrix Transformation(Vector3 scalingCenter, Quaternion scalingRotation, Vector3 scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation)
Creates a transformation matrix.
Definition: Matrix.cs:2856
static void RotationZ(float angle, out Matrix result)
Creates a matrix that rotates around the z-axis.
Definition: Matrix.cs:2529
override string ToString()
Returns a System.String that represents this instance.
Definition: Matrix.cs:3087
static void PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
Creates a right-handed, customized perspective projection matrix.
Definition: Matrix.cs:2275
float M13
Value at row 1 column 3 of the matrix.
Definition: Matrix.cs:112
static void PerspectiveFovLH(float fov, float aspect, float znear, float zfar, out Matrix result)
Creates a left-handed, perspective projection matrix based on a field of view.
Definition: Matrix.cs:2164
static void Dot(ref Vector4 left, ref Vector4 right, out float result)
Calculates the dot product of two vectors.
Definition: Vector4.cs:601
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
string ToString(IFormatProvider formatProvider)
Returns a System.String that represents this instance.
Definition: Matrix.cs:3119
static Matrix LookAtLH(Vector3 eye, Vector3 target, Vector3 up)
Creates a left-handed, look-at matrix.
Definition: Matrix.cs:1910
static void PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
Creates a left-handed, customized perspective projection matrix.
Definition: Matrix.cs:2234
float M23
Value at row 2 column 3 of the matrix.
Definition: Matrix.cs:117
static Matrix LowerTriangularForm(Matrix value)
Brings the matrix into lower triangular form using elementry row operations.
Definition: Matrix.cs:1612
float M42
Value at row 4 column 2 of the matrix.
Definition: Matrix.cs:107
static void RotationX(float angle, out Matrix result)
Creates a matrix that rotates around the x-axis.
Definition: Matrix.cs:2471
static void MultiplyTo(ref Matrix left, ref Matrix right, out Matrix result)
Determines the product of two matrices.
Definition: Matrix.cs:853
static void Shadow(ref Vector4 light, ref Plane plane, out Matrix result)
Creates a matrix that flattens geometry into a shadow.
Definition: Matrix.cs:2352
unsafe void TransposeMatrixFrom(float *src, int columns, int rows)
Transposes a nmx matrix to this instance.
Definition: Matrix.cs:2928
static void Translation(ref Vector3 value, out Matrix result)
Creates a translation matrix using the specified offsets.
Definition: Matrix.cs:2672
void ExchangeRows(int firstRow, int secondRow)
Exchanges two rows in the matrix.
Definition: Matrix.cs:656
static void RotationY(float angle, out Matrix result)
Creates a matrix that rotates around the y-axis.
Definition: Matrix.cs:2500
static Matrix Orthonormalize(Matrix value)
Orthonormalizes the specified matrix.
Definition: Matrix.cs:1448
static void AffineTransformation2D(float scaling, float rotation, ref Vector2 translation, out Matrix result)
Creates a 2D affine transformation matrix.
Definition: Matrix.cs:2780
static Matrix SmoothStep(Matrix start, Matrix end, float amount)
Performs a cubic interpolation between two matrices.
Definition: Matrix.cs:1210
string ToString(string format, IFormatProvider formatProvider)
Returns a System.String that represents this instance.
Definition: Matrix.cs:3136
void DecomposeQR(out Matrix Q, out Matrix R)
Decomposes a matrix into an orthonormalized matrix Q and a right traingular matrix R...
Definition: Matrix.cs:505
static void LookAtRH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result)
Creates a right-handed, look-at matrix.
Definition: Matrix.cs:1924
static Matrix RowEchelonForm(Matrix value)
Brings the matrix into row echelon form using elementry row operations;
Definition: Matrix.cs:1686
static Matrix RotationX(float angle)
Creates a matrix that rotates around the x-axis.
Definition: Matrix.cs:2488
static Matrix Transpose(Matrix value)
Calculates the transpose of the specified matrix.
Definition: Matrix.cs:1250
float M31
Value at row 3 column 1 of the matrix.
Definition: Matrix.cs:82
static Matrix PerspectiveRH(float width, float height, float znear, float zfar)
Creates a right-handed, perspective projection matrix.
Definition: Matrix.cs:2149
static Matrix OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar)
Creates a left-handed, customized orthographic projection matrix.
Definition: Matrix.cs:2054
static Matrix Lerp(Matrix start, Matrix end, float amount)
Performs a linear interpolation between two matricies.
Definition: Matrix.cs:1166
float M44
Value at row 4 column 4 of the matrix.
Definition: Matrix.cs:147
const CallingConvention CallConvention
Defines the calling convention for P/Invoking the native core methods.
static Matrix Translation(float x, float y, float z)
Creates a translation matrix using the specified offsets.
Definition: Matrix.cs:2711
static void OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
Creates a left-handed, customized orthographic projection matrix.
Definition: Matrix.cs:2031
Represents a plane in three dimensional space.
Definition: Plane.cs:42
void Decompose(out float yaw, out float pitch, out float roll)
Decomposes a rotation matrix with the specified yaw, pitch, roll
Definition: Matrix.cs:559
static void Add(ref Matrix left, ref Matrix right, out Matrix result)
Determines the sum of two matrices.
Definition: Matrix.cs:736
static void Scaling(float scale, out Matrix result)
Creates a matrix that uniformally scales along all three axis.
Definition: Matrix.cs:2448
static Matrix Shadow(Vector4 light, Plane plane)
Creates a matrix that flattens geometry into a shadow.
Definition: Matrix.cs:2385
static void MultiplyRef(ref Matrix left, ref Matrix right, ref Matrix result)
Determines the product of two matrices.
Definition: Matrix.cs:912
Matrix(float M11, float M12, float M13, float M14, float M21, float M22, float M23, float M24, float M31, float M32, float M33, float M34, float M41, float M42, float M43, float M44)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Matrix struct.
Definition: Matrix.cs:180
static void UpperTriangularForm(ref Matrix value, out Matrix result)
Brings the matrix into upper triangular form using elementry row operations.
Definition: Matrix.cs:1466
static Matrix RotationY(float angle)
Creates a matrix that rotates around the y-axis.
Definition: Matrix.cs:2517
void DecomposeLQ(out Matrix L, out Matrix Q)
Decomposes a matrix into a lower triangular matrix L and an orthonormalized matrix Q...
Definition: Matrix.cs:533
static void LookAtLH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result)
Creates a left-handed, look-at matrix.
Definition: Matrix.cs:1882
Represents a four dimensional mathematical vector.
Definition: Vector4.cs:42
float M14
Value at row 1 column 4 of the matrix.
Definition: Matrix.cs:132
static void SmoothStep(ref Matrix start, ref Matrix end, float amount, out Matrix result)
Performs a cubic interpolation between two matricies.
Definition: Matrix.cs:1180
static void PerspectiveRH(float width, float height, float znear, float zfar, out Matrix result)
Creates a right-handed, perspective projection matrix.
Definition: Matrix.cs:2133
Represents a four dimensional mathematical quaternion.
Definition: Quaternion.cs:45
static void AffineTransformation(float scaling, ref Quaternion rotation, ref Vector3 translation, out Matrix result)
Creates a 3D affine transformation matrix.
Definition: Matrix.cs:2725
float M11
Value at row 1 column 1 of the matrix.
Definition: Matrix.cs:72
static Matrix PerspectiveLH(float width, float height, float znear, float zfar)
Creates a left-handed, perspective projection matrix.
Definition: Matrix.cs:2118
float M41
Value at row 4 column 1 of the matrix.
Definition: Matrix.cs:87
static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Matrix result)
Creates a rotation matrix with a specified yaw, pitch, and roll.
Definition: Matrix.cs:2646
SiliconStudio.Core.Mathematics.Quaternion Quaternion
override bool Equals(object value)
Determines whether the specified System.Object is equal to this instance.
Definition: Matrix.cs:3199
Matrix(float value)
Initializes a new instance of the SiliconStudio.Core.Mathematics.Matrix struct.
Definition: Matrix.cs:153
static Matrix RotationAxis(Vector3 axis, float angle)
Creates a matrix that rotates around an arbitary axis.
Definition: Matrix.cs:2591
bool Equals(Matrix other)
Determines whether the specified SiliconStudio.Core.Mathematics.Matrix is equal to this instance...
Definition: Matrix.cs:3169
static void Transpose(ref Matrix value, out Matrix result)
Calculates the transpose of the specified matrix.
Definition: Matrix.cs:1222
static Matrix OrthoRH(float width, float height, float znear, float zfar)
Creates a right-handed, orthographic projection matrix.
Definition: Matrix.cs:2014
static void Orthonormalize(ref Matrix value, out Matrix result)
Orthonormalizes the specified matrix.
Definition: Matrix.cs:1402
static Matrix Scaling(Vector3 scale)
Creates a matrix that scales along the x-axis, y-axis, and y-axis.
Definition: Matrix.cs:2407
static void ReducedRowEchelonForm(ref Matrix value, ref Vector4 augment, out Matrix result, out Vector4 augmentResult)
Brings the matrix into reduced row echelon form using elementry row operations.
Definition: Matrix.cs:1710
static Matrix AffineTransformation2D(float scaling, float rotation, Vector2 translation)
Creates a 2D affine transformation matrix.
Definition: Matrix.cs:2792
static Matrix RotationYawPitchRoll(float yaw, float pitch, float roll)
Creates a rotation matrix with a specified yaw, pitch, and roll.
Definition: Matrix.cs:2660
static Matrix Divide(Matrix left, Matrix right)
Determines the quotient of two matrices.
Definition: Matrix.cs:1018
float M12
Value at row 1 column 2 of the matrix.
Definition: Matrix.cs:92
static Matrix Transformation2D(Vector2 scalingCenter, float scalingRotation, Vector2 scaling, Vector2 rotationCenter, float rotation, Vector2 translation)
Creates a 2D transformation matrix.
Definition: Matrix.cs:2892
static void Reflection(ref Plane plane, out Matrix result)
Builds a matrix that can be used to reflect vectors about a plane.
Definition: Matrix.cs:2306
static void Multiply(ref Matrix left, ref Matrix right, out Matrix result)
Determines the product of two matrices.
Definition: Matrix.cs:882
const string LibraryName
Defines the location of the core native DLL.
static Matrix RotationQuaternion(Quaternion rotation)
Creates a rotation matrix from a quaternion.
Definition: Matrix.cs:2632
static Matrix PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar)
Creates a right-handed, customized perspective projection matrix.
Definition: Matrix.cs:2294
static Matrix LookAtRH(Vector3 eye, Vector3 target, Vector3 up)
Creates a right-handed, look-at matrix.
Definition: Matrix.cs:1952
static void Exponent(ref Matrix value, int exponent, out Matrix result)
Performs the exponential operation on a matrix.
Definition: Matrix.cs:1032
static void Invert(ref Matrix value, out Matrix result)
Calculates the inverse of the specified matrix.
Definition: Matrix.cs:1262
static Matrix PerspectiveFovRH(float fov, float aspect, float znear, float zfar)
Creates a right-handed, perspective projection matrix based on a field of view.
Definition: Matrix.cs:2217
char * dest
Definition: lz4.h:61
static Matrix AffineTransformation(float scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation)
Creates a 3D affine transformation matrix.
Definition: Matrix.cs:2766
float M34
Value at row 3 column 4 of the matrix.
Definition: Matrix.cs:142
static void Divide(ref Matrix left, ref Matrix right, out Matrix result)
Determines the quotient of two matrices.
Definition: Matrix.cs:992
static Matrix Subtract(Matrix left, Matrix right)
Determines the difference between two matrices.
Definition: Matrix.cs:801
static Matrix AffineTransformation(float scaling, Quaternion rotation, Vector3 translation)
Creates a 3D affine transformation matrix.
Definition: Matrix.cs:2737
static Matrix Multiply(Matrix left, float right)
Scales a matrix by the given value.
Definition: Matrix.cs:840
void Transpose()
Transposes the matrix.
Definition: Matrix.cs:455
SiliconStudio.Core.Mathematics.Vector3 Vector3
static void OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
Creates a right-handed, customized orthographic projection matrix.
Definition: Matrix.cs:2071
static Matrix Multiply(Matrix left, Matrix right)
Determines the product of two matrices.
Definition: Matrix.cs:938
float M33
Value at row 3 column 3 of the matrix.
Definition: Matrix.cs:122
static Matrix UpperTriangularForm(Matrix value)
Brings the matrix into upper triangular form using elementry row operations.
Definition: Matrix.cs:1528
float M43
Value at row 4 column 3 of the matrix.
Definition: Matrix.cs:127
static void AffineTransformation2D(float scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result)
Creates a 2D affine transformation matrix.
Definition: Matrix.cs:2807
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
static void Transformation(ref Vector3 scalingCenter, ref Quaternion scalingRotation, ref Vector3 scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result)
Creates a transformation matrix.
Definition: Matrix.cs:2838
static Matrix Translation(Vector3 value)
Creates a translation matrix using the specified offsets.
Definition: Matrix.cs:2682
void ExchangeColumns(int firstColumn, int secondColumn)
Definition: Matrix.cs:691
static Matrix Invert(Matrix value)
Calculates the inverse of the specified matrix.
Definition: Matrix.cs:1318
static Matrix AffineTransformation2D(float scaling, Vector2 rotationCenter, float rotation, Vector2 translation)
Creates a 2D affine transformation matrix.
Definition: Matrix.cs:2821
static void OrthoRH(float width, float height, float znear, float zfar, out Matrix result)
Creates a right-handed, orthographic projection matrix.
Definition: Matrix.cs:1998
void Orthonormalize()
Orthonormalizes the specified matrix.
Definition: Matrix.cs:495
static Matrix Divide(Matrix left, float right)
Scales a matrix by the given value.
Definition: Matrix.cs:979
static void Lerp(ref Matrix start, ref Matrix end, float amount, out Matrix result)
Performs a linear interpolation between two matricies.
Definition: Matrix.cs:1134
static Matrix Negate(Matrix value)
Negates a matrix.
Definition: Matrix.cs:1115
static Matrix Add(Matrix left, Matrix right)
Determines the sum of two matrices.
Definition: Matrix.cs:762
static void AffineTransformation(float scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result)
Creates a 3D affine transformation matrix.
Definition: Matrix.cs:2752
float M32
Value at row 3 column 2 of the matrix.
Definition: Matrix.cs:102
DataStyle
Specifies the style used for textual serialization when an array/list or a dictionary/map must be ser...
Definition: DataStyle.cs:9
float Determinant()
Calculates the determinant of the matrix.
Definition: Matrix.cs:430
static Matrix OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar)
Creates a right-handed, customized orthographic projection matrix.
Definition: Matrix.cs:2087
static void Scaling(float x, float y, float z, out Matrix result)
Creates a matrix that scales along the x-axis, y-axis, and y-axis.
Definition: Matrix.cs:2421
static void Multiply(ref Matrix left, float right, out Matrix result)
Scales a matrix by the given value.
Definition: Matrix.cs:814
static void Transformation2D(ref Vector2 scalingCenter, float scalingRotation, ref Vector2 scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result)
Creates a 2D transformation matrix.
Definition: Matrix.cs:2873
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t size_t z
Definition: DirectXTexP.h:191
static Matrix Orthogonalize(Matrix value)
Orthogonalizes the specified matrix.
Definition: Matrix.cs:1377
void Orthogonalize()
Orthogonalizes the specified matrix.
Definition: Matrix.cs:474
static Matrix Billboard(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector)
Creates a spherical billboard that rotates around a specified object position.
Definition: Matrix.cs:1868
float M24
Value at row 2 column 4 of the matrix.
Definition: Matrix.cs:137
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47