Vector3.cs 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. // MIT License - Copyright (C) The Mono.Xna Team
  2. // This file is subject to the terms and conditions defined in
  3. // file 'LICENSE.txt', which is part of this source code package.
  4. using System;
  5. using System.Diagnostics;
  6. using System.Text;
  7. using System.Runtime.Serialization;
  8. namespace CommonLang.Geometry
  9. {
  10. public struct Vector3 : IEquatable<Vector3>
  11. {
  12. #region Private Fields
  13. private static readonly Vector3 zero = new Vector3(0f, 0f, 0f);
  14. private static readonly Vector3 one = new Vector3(1f, 1f, 1f);
  15. private static readonly Vector3 unitX = new Vector3(1f, 0f, 0f);
  16. private static readonly Vector3 unitY = new Vector3(0f, 1f, 0f);
  17. private static readonly Vector3 unitZ = new Vector3(0f, 0f, 1f);
  18. private static readonly Vector3 up = new Vector3(0f, 1f, 0f);
  19. private static readonly Vector3 down = new Vector3(0f, -1f, 0f);
  20. private static readonly Vector3 right = new Vector3(1f, 0f, 0f);
  21. private static readonly Vector3 left = new Vector3(-1f, 0f, 0f);
  22. private static readonly Vector3 forward = new Vector3(0f, 0f, -1f);
  23. private static readonly Vector3 backward = new Vector3(0f, 0f, 1f);
  24. #endregion
  25. #region Public Fields
  26. /// <summary>
  27. /// The x coordinate of this <see cref="Vector3"/>.
  28. /// </summary>
  29. public float X;
  30. /// <summary>
  31. /// The y coordinate of this <see cref="Vector3"/>.
  32. /// </summary>
  33. public float Y;
  34. /// <summary>
  35. /// The z coordinate of this <see cref="Vector3"/>.
  36. /// </summary>
  37. public float Z;
  38. #endregion
  39. #region Public Properties
  40. /// <summary>
  41. /// Returns a <see cref="Vector3"/> with components 0, 0, 0.
  42. /// </summary>
  43. public static Vector3 Zero
  44. {
  45. get { return zero; }
  46. }
  47. /// <summary>
  48. /// Returns a <see cref="Vector3"/> with components 1, 1, 1.
  49. /// </summary>
  50. public static Vector3 One
  51. {
  52. get { return one; }
  53. }
  54. /// <summary>
  55. /// Returns a <see cref="Vector3"/> with components 1, 0, 0.
  56. /// </summary>
  57. public static Vector3 UnitX
  58. {
  59. get { return unitX; }
  60. }
  61. /// <summary>
  62. /// Returns a <see cref="Vector3"/> with components 0, 1, 0.
  63. /// </summary>
  64. public static Vector3 UnitY
  65. {
  66. get { return unitY; }
  67. }
  68. /// <summary>
  69. /// Returns a <see cref="Vector3"/> with components 0, 0, 1.
  70. /// </summary>
  71. public static Vector3 UnitZ
  72. {
  73. get { return unitZ; }
  74. }
  75. /// <summary>
  76. /// Returns a <see cref="Vector3"/> with components 0, 1, 0.
  77. /// </summary>
  78. public static Vector3 Up
  79. {
  80. get { return up; }
  81. }
  82. /// <summary>
  83. /// Returns a <see cref="Vector3"/> with components 0, -1, 0.
  84. /// </summary>
  85. public static Vector3 Down
  86. {
  87. get { return down; }
  88. }
  89. /// <summary>
  90. /// Returns a <see cref="Vector3"/> with components 1, 0, 0.
  91. /// </summary>
  92. public static Vector3 Right
  93. {
  94. get { return right; }
  95. }
  96. /// <summary>
  97. /// Returns a <see cref="Vector3"/> with components -1, 0, 0.
  98. /// </summary>
  99. public static Vector3 Left
  100. {
  101. get { return left; }
  102. }
  103. /// <summary>
  104. /// Returns a <see cref="Vector3"/> with components 0, 0, -1.
  105. /// </summary>
  106. public static Vector3 Forward
  107. {
  108. get { return forward; }
  109. }
  110. /// <summary>
  111. /// Returns a <see cref="Vector3"/> with components 0, 0, 1.
  112. /// </summary>
  113. public static Vector3 Backward
  114. {
  115. get { return backward; }
  116. }
  117. #endregion
  118. #region Internal Properties
  119. internal string DebugDisplayString
  120. {
  121. get
  122. {
  123. return string.Concat(
  124. this.X.ToString(), " ",
  125. this.Y.ToString(), " ",
  126. this.Z.ToString()
  127. );
  128. }
  129. }
  130. #endregion
  131. #region Constructors
  132. /// <summary>
  133. /// Constructs a 3d vector with X, Y and Z from three values.
  134. /// </summary>
  135. /// <param name="x">The x coordinate in 3d-space.</param>
  136. /// <param name="y">The y coordinate in 3d-space.</param>
  137. /// <param name="z">The z coordinate in 3d-space.</param>
  138. public Vector3(float x, float y, float z)
  139. {
  140. this.X = x;
  141. this.Y = y;
  142. this.Z = z;
  143. }
  144. /// <summary>
  145. /// Constructs a 3d vector with X, Y and Z set to the same value.
  146. /// </summary>
  147. /// <param name="value">The x, y and z coordinates in 3d-space.</param>
  148. public Vector3(float value)
  149. {
  150. this.X = value;
  151. this.Y = value;
  152. this.Z = value;
  153. }
  154. /// <summary>
  155. /// Constructs a 3d vector with X, Y from <see cref="Vector2"/> and Z from a scalar.
  156. /// </summary>
  157. /// <param name="value">The x and y coordinates in 3d-space.</param>
  158. /// <param name="z">The z coordinate in 3d-space.</param>
  159. public Vector3(Vector2 value, float z)
  160. {
  161. this.X = value.X;
  162. this.Y = value.Y;
  163. this.Z = z;
  164. }
  165. #endregion
  166. #region Public Methods
  167. public void Set(float x, float y, float z)
  168. {
  169. this.X = x;
  170. this.Y = y;
  171. this.Z = z;
  172. }
  173. public void Set(Vector3 vec)
  174. {
  175. this.X = vec.X;
  176. this.Y = vec.Y;
  177. this.Z = vec.Z;
  178. }
  179. /// <summary>
  180. /// Performs vector addition on <paramref name="value1"/> and <paramref name="value2"/>.
  181. /// </summary>
  182. /// <param name="value1">The first vector to add.</param>
  183. /// <param name="value2">The second vector to add.</param>
  184. /// <returns>The result of the vector addition.</returns>
  185. public static Vector3 Add(Vector3 value1, Vector3 value2)
  186. {
  187. value1.X += value2.X;
  188. value1.Y += value2.Y;
  189. value1.Z += value2.Z;
  190. return value1;
  191. }
  192. /// <summary>
  193. /// Performs vector addition on <paramref name="value1"/> and
  194. /// <paramref name="value2"/>, storing the result of the
  195. /// addition in <paramref name="result"/>.
  196. /// </summary>
  197. /// <param name="value1">The first vector to add.</param>
  198. /// <param name="value2">The second vector to add.</param>
  199. /// <param name="result">The result of the vector addition.</param>
  200. public static void Add(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
  201. {
  202. result.X = value1.X + value2.X;
  203. result.Y = value1.Y + value2.Y;
  204. result.Z = value1.Z + value2.Z;
  205. }
  206. /// <summary>
  207. /// Creates a new <see cref="Vector3"/> that contains the cartesian coordinates of a vector specified in barycentric coordinates and relative to 3d-triangle.
  208. /// </summary>
  209. /// <param name="value1">The first vector of 3d-triangle.</param>
  210. /// <param name="value2">The second vector of 3d-triangle.</param>
  211. /// <param name="value3">The third vector of 3d-triangle.</param>
  212. /// <param name="amount1">Barycentric scalar <c>b2</c> which represents a weighting factor towards second vector of 3d-triangle.</param>
  213. /// <param name="amount2">Barycentric scalar <c>b3</c> which represents a weighting factor towards third vector of 3d-triangle.</param>
  214. /// <returns>The cartesian translation of barycentric coordinates.</returns>
  215. public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2)
  216. {
  217. return new Vector3(
  218. MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
  219. MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
  220. MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
  221. }
  222. /// <summary>
  223. /// Creates a new <see cref="Vector3"/> that contains the cartesian coordinates of a vector specified in barycentric coordinates and relative to 3d-triangle.
  224. /// </summary>
  225. /// <param name="value1">The first vector of 3d-triangle.</param>
  226. /// <param name="value2">The second vector of 3d-triangle.</param>
  227. /// <param name="value3">The third vector of 3d-triangle.</param>
  228. /// <param name="amount1">Barycentric scalar <c>b2</c> which represents a weighting factor towards second vector of 3d-triangle.</param>
  229. /// <param name="amount2">Barycentric scalar <c>b3</c> which represents a weighting factor towards third vector of 3d-triangle.</param>
  230. /// <param name="result">The cartesian translation of barycentric coordinates as an output parameter.</param>
  231. public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result)
  232. {
  233. result.X = MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2);
  234. result.Y = MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2);
  235. result.Z = MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2);
  236. }
  237. /// <summary>
  238. /// Creates a new <see cref="Vector3"/> that contains CatmullRom interpolation of the specified vectors.
  239. /// </summary>
  240. /// <param name="value1">The first vector in interpolation.</param>
  241. /// <param name="value2">The second vector in interpolation.</param>
  242. /// <param name="value3">The third vector in interpolation.</param>
  243. /// <param name="value4">The fourth vector in interpolation.</param>
  244. /// <param name="amount">Weighting factor.</param>
  245. /// <returns>The result of CatmullRom interpolation.</returns>
  246. public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount)
  247. {
  248. return new Vector3(
  249. MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
  250. MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
  251. MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
  252. }
  253. /// <summary>
  254. /// Creates a new <see cref="Vector3"/> that contains CatmullRom interpolation of the specified vectors.
  255. /// </summary>
  256. /// <param name="value1">The first vector in interpolation.</param>
  257. /// <param name="value2">The second vector in interpolation.</param>
  258. /// <param name="value3">The third vector in interpolation.</param>
  259. /// <param name="value4">The fourth vector in interpolation.</param>
  260. /// <param name="amount">Weighting factor.</param>
  261. /// <param name="result">The result of CatmullRom interpolation as an output parameter.</param>
  262. public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result)
  263. {
  264. result.X = MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount);
  265. result.Y = MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount);
  266. result.Z = MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount);
  267. }
  268. /// <summary>
  269. /// Clamps the specified value within a range.
  270. /// </summary>
  271. /// <param name="value1">The value to clamp.</param>
  272. /// <param name="min">The min value.</param>
  273. /// <param name="max">The max value.</param>
  274. /// <returns>The clamped value.</returns>
  275. public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max)
  276. {
  277. return new Vector3(
  278. MathHelper.Clamp(value1.X, min.X, max.X),
  279. MathHelper.Clamp(value1.Y, min.Y, max.Y),
  280. MathHelper.Clamp(value1.Z, min.Z, max.Z));
  281. }
  282. /// <summary>
  283. /// Clamps the specified value within a range.
  284. /// </summary>
  285. /// <param name="value1">The value to clamp.</param>
  286. /// <param name="min">The min value.</param>
  287. /// <param name="max">The max value.</param>
  288. /// <param name="result">The clamped value as an output parameter.</param>
  289. public static void Clamp(ref Vector3 value1, ref Vector3 min, ref Vector3 max, out Vector3 result)
  290. {
  291. result.X = MathHelper.Clamp(value1.X, min.X, max.X);
  292. result.Y = MathHelper.Clamp(value1.Y, min.Y, max.Y);
  293. result.Z = MathHelper.Clamp(value1.Z, min.Z, max.Z);
  294. }
  295. /// <summary>
  296. /// Computes the cross product of two vectors.
  297. /// </summary>
  298. /// <param name="vector1">The first vector.</param>
  299. /// <param name="vector2">The second vector.</param>
  300. /// <returns>The cross product of two vectors.</returns>
  301. public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
  302. {
  303. Cross(ref vector1, ref vector2, out vector1);
  304. return vector1;
  305. }
  306. /// <summary>
  307. /// Computes the cross product of two vectors.
  308. /// </summary>
  309. /// <param name="vector1">The first vector.</param>
  310. /// <param name="vector2">The second vector.</param>
  311. /// <param name="result">The cross product of two vectors as an output parameter.</param>
  312. public static void Cross(ref Vector3 vector1, ref Vector3 vector2, out Vector3 result)
  313. {
  314. var x = vector1.Y * vector2.Z - vector2.Y * vector1.Z;
  315. var y = -(vector1.X * vector2.Z - vector2.X * vector1.Z);
  316. var z = vector1.X * vector2.Y - vector2.X * vector1.Y;
  317. result.X = x;
  318. result.Y = y;
  319. result.Z = z;
  320. }
  321. /// <summary>
  322. /// Returns the distance between two vectors.
  323. /// </summary>
  324. /// <param name="value1">The first vector.</param>
  325. /// <param name="value2">The second vector.</param>
  326. /// <returns>The distance between two vectors.</returns>
  327. public static float Distance(Vector3 value1, Vector3 value2)
  328. {
  329. float result;
  330. DistanceSquared(ref value1, ref value2, out result);
  331. return (float)Math.Sqrt(result);
  332. }
  333. /// <summary>
  334. /// Returns the distance between two vectors.
  335. /// </summary>
  336. /// <param name="value1">The first vector.</param>
  337. /// <param name="value2">The second vector.</param>
  338. /// <param name="result">The distance between two vectors as an output parameter.</param>
  339. public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result)
  340. {
  341. DistanceSquared(ref value1, ref value2, out result);
  342. result = (float)Math.Sqrt(result);
  343. }
  344. /// <summary>
  345. /// Returns the squared distance between two vectors.
  346. /// </summary>
  347. /// <param name="value1">The first vector.</param>
  348. /// <param name="value2">The second vector.</param>
  349. /// <returns>The squared distance between two vectors.</returns>
  350. public static float DistanceSquared(Vector3 value1, Vector3 value2)
  351. {
  352. float result;
  353. DistanceSquared(ref value1, ref value2, out result);
  354. return result;
  355. }
  356. /// <summary>
  357. /// Returns the squared distance between two vectors.
  358. /// </summary>
  359. /// <param name="value1">The first vector.</param>
  360. /// <param name="value2">The second vector.</param>
  361. /// <param name="result">The squared distance between two vectors as an output parameter.</param>
  362. public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result)
  363. {
  364. result = (value1.X - value2.X) * (value1.X - value2.X) +
  365. (value1.Y - value2.Y) * (value1.Y - value2.Y) +
  366. (value1.Z - value2.Z) * (value1.Z - value2.Z);
  367. }
  368. /// <summary>
  369. /// Divides the components of a <see cref="Vector3"/> by the components of another <see cref="Vector3"/>.
  370. /// </summary>
  371. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  372. /// <param name="value2">Divisor <see cref="Vector3"/>.</param>
  373. /// <returns>The result of dividing the vectors.</returns>
  374. public static Vector3 Divide(Vector3 value1, Vector3 value2)
  375. {
  376. value1.X /= value2.X;
  377. value1.Y /= value2.Y;
  378. value1.Z /= value2.Z;
  379. return value1;
  380. }
  381. /// <summary>
  382. /// Divides the components of a <see cref="Vector3"/> by a scalar.
  383. /// </summary>
  384. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  385. /// <param name="divider">Divisor scalar.</param>
  386. /// <returns>The result of dividing a vector by a scalar.</returns>
  387. public static Vector3 Divide(Vector3 value1, float divider)
  388. {
  389. float factor = 1 / divider;
  390. value1.X *= factor;
  391. value1.Y *= factor;
  392. value1.Z *= factor;
  393. return value1;
  394. }
  395. /// <summary>
  396. /// Divides the components of a <see cref="Vector3"/> by a scalar.
  397. /// </summary>
  398. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  399. /// <param name="divider">Divisor scalar.</param>
  400. /// <param name="result">The result of dividing a vector by a scalar as an output parameter.</param>
  401. public static void Divide(ref Vector3 value1, float divider, out Vector3 result)
  402. {
  403. float factor = 1 / divider;
  404. result.X = value1.X * factor;
  405. result.Y = value1.Y * factor;
  406. result.Z = value1.Z * factor;
  407. }
  408. /// <summary>
  409. /// Divides the components of a <see cref="Vector3"/> by the components of another <see cref="Vector3"/>.
  410. /// </summary>
  411. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  412. /// <param name="value2">Divisor <see cref="Vector3"/>.</param>
  413. /// <param name="result">The result of dividing the vectors as an output parameter.</param>
  414. public static void Divide(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
  415. {
  416. result.X = value1.X / value2.X;
  417. result.Y = value1.Y / value2.Y;
  418. result.Z = value1.Z / value2.Z;
  419. }
  420. /// <summary>
  421. /// Returns a dot product of two vectors.
  422. /// </summary>
  423. /// <param name="value1">The first vector.</param>
  424. /// <param name="value2">The second vector.</param>
  425. /// <returns>The dot product of two vectors.</returns>
  426. public static float Dot(Vector3 value1, Vector3 value2)
  427. {
  428. return value1.X * value2.X + value1.Y * value2.Y + value1.Z * value2.Z;
  429. }
  430. /// <summary>
  431. /// Returns a dot product of two vectors.
  432. /// </summary>
  433. /// <param name="value1">The first vector.</param>
  434. /// <param name="value2">The second vector.</param>
  435. /// <param name="result">The dot product of two vectors as an output parameter.</param>
  436. public static void Dot(ref Vector3 value1, ref Vector3 value2, out float result)
  437. {
  438. result = value1.X * value2.X + value1.Y * value2.Y + value1.Z * value2.Z;
  439. }
  440. /// <summary>
  441. /// Compares whether current instance is equal to specified <see cref="Object"/>.
  442. /// </summary>
  443. /// <param name="obj">The <see cref="Object"/> to compare.</param>
  444. /// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
  445. public override bool Equals(object obj)
  446. {
  447. if (!(obj is Vector3))
  448. return false;
  449. var other = (Vector3)obj;
  450. return X == other.X &&
  451. Y == other.Y &&
  452. Z == other.Z;
  453. }
  454. /// <summary>
  455. /// Compares whether current instance is equal to specified <see cref="Vector3"/>.
  456. /// </summary>
  457. /// <param name="other">The <see cref="Vector3"/> to compare.</param>
  458. /// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
  459. public bool Equals(Vector3 other)
  460. {
  461. return X == other.X &&
  462. Y == other.Y &&
  463. Z == other.Z;
  464. }
  465. public bool Equal(Vector3 other, float precision)
  466. {
  467. return Math.Abs(X - other.X) < precision && Math.Abs(Y - other.Y) < precision && Math.Abs(Z - other.Z) < precision;
  468. }
  469. /// <summary>
  470. /// Gets the hash code of this <see cref="Vector3"/>.
  471. /// </summary>
  472. /// <returns>Hash code of this <see cref="Vector3"/>.</returns>
  473. public override int GetHashCode()
  474. {
  475. return (int)(this.X + this.Y + this.Z);
  476. }
  477. /// <summary>
  478. /// Creates a new <see cref="Vector3"/> that contains hermite spline interpolation.
  479. /// </summary>
  480. /// <param name="value1">The first position vector.</param>
  481. /// <param name="tangent1">The first tangent vector.</param>
  482. /// <param name="value2">The second position vector.</param>
  483. /// <param name="tangent2">The second tangent vector.</param>
  484. /// <param name="amount">Weighting factor.</param>
  485. /// <returns>The hermite spline interpolation vector.</returns>
  486. public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount)
  487. {
  488. return new Vector3(MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount),
  489. MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount),
  490. MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount));
  491. }
  492. /// <summary>
  493. /// Creates a new <see cref="Vector3"/> that contains hermite spline interpolation.
  494. /// </summary>
  495. /// <param name="value1">The first position vector.</param>
  496. /// <param name="tangent1">The first tangent vector.</param>
  497. /// <param name="value2">The second position vector.</param>
  498. /// <param name="tangent2">The second tangent vector.</param>
  499. /// <param name="amount">Weighting factor.</param>
  500. /// <param name="result">The hermite spline interpolation vector as an output parameter.</param>
  501. public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result)
  502. {
  503. result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
  504. result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
  505. result.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
  506. }
  507. /// <summary>
  508. /// Returns the length of this <see cref="Vector3"/>.
  509. /// </summary>
  510. /// <returns>The length of this <see cref="Vector3"/>.</returns>
  511. public float Length()
  512. {
  513. float result = DistanceSquared(this, zero);
  514. return (float)Math.Sqrt(result);
  515. }
  516. /// <summary>
  517. /// Returns the squared length of this <see cref="Vector3"/>.
  518. /// </summary>
  519. /// <returns>The squared length of this <see cref="Vector3"/>.</returns>
  520. public float LengthSquared()
  521. {
  522. return DistanceSquared(this, zero);
  523. }
  524. /// <summary>
  525. /// Creates a new <see cref="Vector3"/> that contains linear interpolation of the specified vectors.
  526. /// </summary>
  527. /// <param name="value1">The first vector.</param>
  528. /// <param name="value2">The second vector.</param>
  529. /// <param name="amount">Weighting value(between 0.0 and 1.0).</param>
  530. /// <returns>The result of linear interpolation of the specified vectors.</returns>
  531. public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
  532. {
  533. return new Vector3(
  534. MathHelper.Lerp(value1.X, value2.X, amount),
  535. MathHelper.Lerp(value1.Y, value2.Y, amount),
  536. MathHelper.Lerp(value1.Z, value2.Z, amount));
  537. }
  538. /// <summary>
  539. /// Creates a new <see cref="Vector3"/> that contains linear interpolation of the specified vectors.
  540. /// </summary>
  541. /// <param name="value1">The first vector.</param>
  542. /// <param name="value2">The second vector.</param>
  543. /// <param name="amount">Weighting value(between 0.0 and 1.0).</param>
  544. /// <param name="result">The result of linear interpolation of the specified vectors as an output parameter.</param>
  545. public static void Lerp(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
  546. {
  547. result.X = MathHelper.Lerp(value1.X, value2.X, amount);
  548. result.Y = MathHelper.Lerp(value1.Y, value2.Y, amount);
  549. result.Z = MathHelper.Lerp(value1.Z, value2.Z, amount);
  550. }
  551. /// <summary>
  552. /// Creates a new <see cref="Vector3"/> that contains a maximal values from the two vectors.
  553. /// </summary>
  554. /// <param name="value1">The first vector.</param>
  555. /// <param name="value2">The second vector.</param>
  556. /// <returns>The <see cref="Vector3"/> with maximal values from the two vectors.</returns>
  557. public static Vector3 Max(Vector3 value1, Vector3 value2)
  558. {
  559. return new Vector3(
  560. MathHelper.Max(value1.X, value2.X),
  561. MathHelper.Max(value1.Y, value2.Y),
  562. MathHelper.Max(value1.Z, value2.Z));
  563. }
  564. /// <summary>
  565. /// Creates a new <see cref="Vector3"/> that contains a maximal values from the two vectors.
  566. /// </summary>
  567. /// <param name="value1">The first vector.</param>
  568. /// <param name="value2">The second vector.</param>
  569. /// <param name="result">The <see cref="Vector3"/> with maximal values from the two vectors as an output parameter.</param>
  570. public static void Max(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
  571. {
  572. result.X = MathHelper.Max(value1.X, value2.X);
  573. result.Y = MathHelper.Max(value1.Y, value2.Y);
  574. result.Z = MathHelper.Max(value1.Z, value2.Z);
  575. }
  576. /// <summary>
  577. /// Creates a new <see cref="Vector3"/> that contains a minimal values from the two vectors.
  578. /// </summary>
  579. /// <param name="value1">The first vector.</param>
  580. /// <param name="value2">The second vector.</param>
  581. /// <returns>The <see cref="Vector3"/> with minimal values from the two vectors.</returns>
  582. public static Vector3 Min(Vector3 value1, Vector3 value2)
  583. {
  584. return new Vector3(
  585. MathHelper.Min(value1.X, value2.X),
  586. MathHelper.Min(value1.Y, value2.Y),
  587. MathHelper.Min(value1.Z, value2.Z));
  588. }
  589. /// <summary>
  590. /// Creates a new <see cref="Vector3"/> that contains a minimal values from the two vectors.
  591. /// </summary>
  592. /// <param name="value1">The first vector.</param>
  593. /// <param name="value2">The second vector.</param>
  594. /// <param name="result">The <see cref="Vector3"/> with minimal values from the two vectors as an output parameter.</param>
  595. public static void Min(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
  596. {
  597. result.X = MathHelper.Min(value1.X, value2.X);
  598. result.Y = MathHelper.Min(value1.Y, value2.Y);
  599. result.Z = MathHelper.Min(value1.Z, value2.Z);
  600. }
  601. /// <summary>
  602. /// Creates a new <see cref="Vector3"/> that contains a multiplication of two vectors.
  603. /// </summary>
  604. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  605. /// <param name="value2">Source <see cref="Vector3"/>.</param>
  606. /// <returns>The result of the vector multiplication.</returns>
  607. public static Vector3 Multiply(Vector3 value1, Vector3 value2)
  608. {
  609. value1.X *= value2.X;
  610. value1.Y *= value2.Y;
  611. value1.Z *= value2.Z;
  612. return value1;
  613. }
  614. /// <summary>
  615. /// Creates a new <see cref="Vector3"/> that contains a multiplication of <see cref="Vector3"/> and a scalar.
  616. /// </summary>
  617. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  618. /// <param name="scaleFactor">Scalar value.</param>
  619. /// <returns>The result of the vector multiplication with a scalar.</returns>
  620. public static Vector3 Multiply(Vector3 value1, float scaleFactor)
  621. {
  622. value1.X *= scaleFactor;
  623. value1.Y *= scaleFactor;
  624. value1.Z *= scaleFactor;
  625. return value1;
  626. }
  627. /// <summary>
  628. /// Creates a new <see cref="Vector3"/> that contains a multiplication of <see cref="Vector3"/> and a scalar.
  629. /// </summary>
  630. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  631. /// <param name="scaleFactor">Scalar value.</param>
  632. /// <param name="result">The result of the multiplication with a scalar as an output parameter.</param>
  633. public static void Multiply(ref Vector3 value1, float scaleFactor, out Vector3 result)
  634. {
  635. result.X = value1.X * scaleFactor;
  636. result.Y = value1.Y * scaleFactor;
  637. result.Z = value1.Z * scaleFactor;
  638. }
  639. /// <summary>
  640. /// Creates a new <see cref="Vector3"/> that contains a multiplication of two vectors.
  641. /// </summary>
  642. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  643. /// <param name="value2">Source <see cref="Vector3"/>.</param>
  644. /// <param name="result">The result of the vector multiplication as an output parameter.</param>
  645. public static void Multiply(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
  646. {
  647. result.X = value1.X * value2.X;
  648. result.Y = value1.Y * value2.Y;
  649. result.Z = value1.Z * value2.Z;
  650. }
  651. /// <summary>
  652. /// Creates a new <see cref="Vector3"/> that contains the specified vector inversion.
  653. /// </summary>
  654. /// <param name="value">Source <see cref="Vector3"/>.</param>
  655. /// <returns>The result of the vector inversion.</returns>
  656. public static Vector3 Negate(Vector3 value)
  657. {
  658. value = new Vector3(-value.X, -value.Y, -value.Z);
  659. return value;
  660. }
  661. /// <summary>
  662. /// Creates a new <see cref="Vector3"/> that contains the specified vector inversion.
  663. /// </summary>
  664. /// <param name="value">Source <see cref="Vector3"/>.</param>
  665. /// <param name="result">The result of the vector inversion as an output parameter.</param>
  666. public static void Negate(ref Vector3 value, out Vector3 result)
  667. {
  668. result.X = -value.X;
  669. result.Y = -value.Y;
  670. result.Z = -value.Z;
  671. }
  672. /// <summary>
  673. /// Turns this <see cref="Vector3"/> to a unit vector with the same direction.
  674. /// </summary>
  675. public void Normalize()
  676. {
  677. Normalize(ref this, out this);
  678. }
  679. /// <summary>
  680. /// Creates a new <see cref="Vector3"/> that contains a normalized values from another vector.
  681. /// </summary>
  682. /// <param name="value">Source <see cref="Vector3"/>.</param>
  683. /// <returns>Unit vector.</returns>
  684. public static Vector3 Normalize(Vector3 value)
  685. {
  686. Normalize(ref value, out value);
  687. return value;
  688. }
  689. /// <summary>
  690. /// Creates a new <see cref="Vector3"/> that contains a normalized values from another vector.
  691. /// </summary>
  692. /// <param name="value">Source <see cref="Vector3"/>.</param>
  693. /// <param name="result">Unit vector as an output parameter.</param>
  694. public static void Normalize(ref Vector3 value, out Vector3 result)
  695. {
  696. float factor = Distance(value, zero);
  697. factor = 1f / factor;
  698. result.X = value.X * factor;
  699. result.Y = value.Y * factor;
  700. result.Z = value.Z * factor;
  701. }
  702. /// <summary>
  703. /// Creates a new <see cref="Vector3"/> that contains reflect vector of the given vector and normal.
  704. /// </summary>
  705. /// <param name="vector">Source <see cref="Vector3"/>.</param>
  706. /// <param name="normal">Reflection normal.</param>
  707. /// <returns>Reflected vector.</returns>
  708. public static Vector3 Reflect(Vector3 vector, Vector3 normal)
  709. {
  710. // I is the original array
  711. // N is the normal of the incident plane
  712. // R = I - (2 * N * ( DotProduct[ I,N] ))
  713. Vector3 reflectedVector;
  714. // inline the dotProduct here instead of calling method
  715. float dotProduct = ((vector.X * normal.X) + (vector.Y * normal.Y)) + (vector.Z * normal.Z);
  716. reflectedVector.X = vector.X - (2.0f * normal.X) * dotProduct;
  717. reflectedVector.Y = vector.Y - (2.0f * normal.Y) * dotProduct;
  718. reflectedVector.Z = vector.Z - (2.0f * normal.Z) * dotProduct;
  719. return reflectedVector;
  720. }
  721. /// <summary>
  722. /// Creates a new <see cref="Vector3"/> that contains reflect vector of the given vector and normal.
  723. /// </summary>
  724. /// <param name="vector">Source <see cref="Vector3"/>.</param>
  725. /// <param name="normal">Reflection normal.</param>
  726. /// <param name="result">Reflected vector as an output parameter.</param>
  727. public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result)
  728. {
  729. // I is the original array
  730. // N is the normal of the incident plane
  731. // R = I - (2 * N * ( DotProduct[ I,N] ))
  732. // inline the dotProduct here instead of calling method
  733. float dotProduct = ((vector.X * normal.X) + (vector.Y * normal.Y)) + (vector.Z * normal.Z);
  734. result.X = vector.X - (2.0f * normal.X) * dotProduct;
  735. result.Y = vector.Y - (2.0f * normal.Y) * dotProduct;
  736. result.Z = vector.Z - (2.0f * normal.Z) * dotProduct;
  737. }
  738. /// <summary>
  739. /// Creates a new <see cref="Vector3"/> that contains cubic interpolation of the specified vectors.
  740. /// </summary>
  741. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  742. /// <param name="value2">Source <see cref="Vector3"/>.</param>
  743. /// <param name="amount">Weighting value.</param>
  744. /// <returns>Cubic interpolation of the specified vectors.</returns>
  745. public static Vector3 SmoothStep(Vector3 value1, Vector3 value2, float amount)
  746. {
  747. return new Vector3(
  748. MathHelper.SmoothStep(value1.X, value2.X, amount),
  749. MathHelper.SmoothStep(value1.Y, value2.Y, amount),
  750. MathHelper.SmoothStep(value1.Z, value2.Z, amount));
  751. }
  752. /// <summary>
  753. /// Creates a new <see cref="Vector3"/> that contains cubic interpolation of the specified vectors.
  754. /// </summary>
  755. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  756. /// <param name="value2">Source <see cref="Vector3"/>.</param>
  757. /// <param name="amount">Weighting value.</param>
  758. /// <param name="result">Cubic interpolation of the specified vectors as an output parameter.</param>
  759. public static void SmoothStep(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
  760. {
  761. result.X = MathHelper.SmoothStep(value1.X, value2.X, amount);
  762. result.Y = MathHelper.SmoothStep(value1.Y, value2.Y, amount);
  763. result.Z = MathHelper.SmoothStep(value1.Z, value2.Z, amount);
  764. }
  765. /// <summary>
  766. /// Creates a new <see cref="Vector3"/> that contains subtraction of on <see cref="Vector3"/> from a another.
  767. /// </summary>
  768. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  769. /// <param name="value2">Source <see cref="Vector3"/>.</param>
  770. /// <returns>The result of the vector subtraction.</returns>
  771. public static Vector3 Subtract(Vector3 value1, Vector3 value2)
  772. {
  773. value1.X -= value2.X;
  774. value1.Y -= value2.Y;
  775. value1.Z -= value2.Z;
  776. return value1;
  777. }
  778. /// <summary>
  779. /// Creates a new <see cref="Vector3"/> that contains subtraction of on <see cref="Vector3"/> from a another.
  780. /// </summary>
  781. /// <param name="value1">Source <see cref="Vector3"/>.</param>
  782. /// <param name="value2">Source <see cref="Vector3"/>.</param>
  783. /// <param name="result">The result of the vector subtraction as an output parameter.</param>
  784. public static void Subtract(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
  785. {
  786. result.X = value1.X - value2.X;
  787. result.Y = value1.Y - value2.Y;
  788. result.Z = value1.Z - value2.Z;
  789. }
  790. /// <summary>
  791. /// Returns a <see cref="String"/> representation of this <see cref="Vector3"/> in the format:
  792. /// {X:[<see cref="X"/>] Y:[<see cref="Y"/>] Z:[<see cref="Z"/>]}
  793. /// </summary>
  794. /// <returns>A <see cref="String"/> representation of this <see cref="Vector3"/>.</returns>
  795. public override string ToString()
  796. {
  797. StringBuilder sb = new StringBuilder(32);
  798. sb.Append("{X:");
  799. sb.Append(this.X);
  800. sb.Append(" Y:");
  801. sb.Append(this.Y);
  802. sb.Append(" Z:");
  803. sb.Append(this.Z);
  804. sb.Append("}");
  805. return sb.ToString();
  806. }
  807. #region Transform
  808. /// <summary>
  809. /// Creates a new <see cref="Vector3"/> that contains a transformation of vector(position.X,position.Y,position.Z,1) by the specified <see cref="Matrix"/>.
  810. /// </summary>
  811. /// <param name="position">Source <see cref="Vector3"/>.</param>
  812. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  813. /// <returns>Transformed <see cref="Vector3"/>.</returns>
  814. public static Vector3 Transform(Vector3 position, Matrix matrix)
  815. {
  816. Transform(ref position, ref matrix, out position);
  817. return position;
  818. }
  819. /// <summary>
  820. /// Creates a new <see cref="Vector3"/> that contains a transformation of vector(position.X,position.Y,position.Z,1) by the specified <see cref="Matrix"/>.
  821. /// </summary>
  822. /// <param name="position">Source <see cref="Vector3"/>.</param>
  823. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  824. /// <param name="result">Transformed <see cref="Vector3"/> as an output parameter.</param>
  825. public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result)
  826. {
  827. var x = (position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41;
  828. var y = (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42;
  829. var z = (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43;
  830. result.X = x;
  831. result.Y = y;
  832. result.Z = z;
  833. }
  834. /// <summary>
  835. /// Creates a new <see cref="Vector3"/> that contains a transformation of vector(position.X,position.Y,position.Z,0) by the specified <see cref="Quaternion"/>, representing the rotation.
  836. /// </summary>
  837. /// <param name="value">Source <see cref="Vector3"/>.</param>
  838. /// <param name="rotation">The <see cref="Quaternion"/> which contains rotation transformation.</param>
  839. /// <returns>Transformed <see cref="Vector3"/>.</returns>
  840. public static Vector3 Transform(Vector3 value, Quaternion rotation)
  841. {
  842. Vector3 result;
  843. Transform(ref value, ref rotation, out result);
  844. return result;
  845. }
  846. /// <summary>
  847. /// Creates a new <see cref="Vector3"/> that contains a transformation of vector(position.X,position.Y,position.Z,0) by the specified <see cref="Quaternion"/>, representing the rotation.
  848. /// </summary>
  849. /// <param name="value">Source <see cref="Vector3"/>.</param>
  850. /// <param name="rotation">The <see cref="Quaternion"/> which contains rotation transformation.</param>
  851. /// <param name="result">Transformed <see cref="Vector3"/> as an output parameter.</param>
  852. public static void Transform(ref Vector3 value, ref Quaternion rotation, out Vector3 result)
  853. {
  854. float x = 2 * (rotation.Y * value.Z - rotation.Z * value.Y);
  855. float y = 2 * (rotation.Z * value.X - rotation.X * value.Z);
  856. float z = 2 * (rotation.X * value.Y - rotation.Y * value.X);
  857. result.X = value.X + x * rotation.W + (rotation.Y * z - rotation.Z * y);
  858. result.Y = value.Y + y * rotation.W + (rotation.Z * x - rotation.X * z);
  859. result.Z = value.Z + z * rotation.W + (rotation.X * y - rotation.Y * x);
  860. }
  861. /// <summary>
  862. /// Apply transformation on vectors within array of <see cref="Vector3"/> by the specified <see cref="Matrix"/> and places the results in an another array.
  863. /// </summary>
  864. /// <param name="sourceArray">Source array.</param>
  865. /// <param name="sourceIndex">The starting index of transformation in the source array.</param>
  866. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  867. /// <param name="destinationArray">Destination array.</param>
  868. /// <param name="destinationIndex">The starting index in the destination array, where the first <see cref="Vector3"/> should be written.</param>
  869. /// <param name="length">The number of vectors to be transformed.</param>
  870. public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix, Vector3[] destinationArray, int destinationIndex, int length)
  871. {
  872. if (sourceArray == null)
  873. throw new ArgumentNullException("sourceArray");
  874. if (destinationArray == null)
  875. throw new ArgumentNullException("destinationArray");
  876. if (sourceArray.Length < sourceIndex + length)
  877. throw new ArgumentException("Source array length is lesser than sourceIndex + length");
  878. if (destinationArray.Length < destinationIndex + length)
  879. throw new ArgumentException("Destination array length is lesser than destinationIndex + length");
  880. // TODO: Are there options on some platforms to implement a vectorized version of this?
  881. for (var i = 0; i < length; i++)
  882. {
  883. var position = sourceArray[sourceIndex + i];
  884. destinationArray[destinationIndex + i] =
  885. new Vector3(
  886. (position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
  887. (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
  888. (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43);
  889. }
  890. }
  891. /// <summary>
  892. /// Apply transformation on vectors within array of <see cref="Vector3"/> by the specified <see cref="Quaternion"/> and places the results in an another array.
  893. /// </summary>
  894. /// <param name="sourceArray">Source array.</param>
  895. /// <param name="sourceIndex">The starting index of transformation in the source array.</param>
  896. /// <param name="rotation">The <see cref="Quaternion"/> which contains rotation transformation.</param>
  897. /// <param name="destinationArray">Destination array.</param>
  898. /// <param name="destinationIndex">The starting index in the destination array, where the first <see cref="Vector3"/> should be written.</param>
  899. /// <param name="length">The number of vectors to be transformed.</param>
  900. public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector3[] destinationArray, int destinationIndex, int length)
  901. {
  902. if (sourceArray == null)
  903. throw new ArgumentNullException("sourceArray");
  904. if (destinationArray == null)
  905. throw new ArgumentNullException("destinationArray");
  906. if (sourceArray.Length < sourceIndex + length)
  907. throw new ArgumentException("Source array length is lesser than sourceIndex + length");
  908. if (destinationArray.Length < destinationIndex + length)
  909. throw new ArgumentException("Destination array length is lesser than destinationIndex + length");
  910. // TODO: Are there options on some platforms to implement a vectorized version of this?
  911. for (var i = 0; i < length; i++)
  912. {
  913. var position = sourceArray[sourceIndex + i];
  914. float x = 2 * (rotation.Y * position.Z - rotation.Z * position.Y);
  915. float y = 2 * (rotation.Z * position.X - rotation.X * position.Z);
  916. float z = 2 * (rotation.X * position.Y - rotation.Y * position.X);
  917. destinationArray[destinationIndex + i] =
  918. new Vector3(
  919. position.X + x * rotation.W + (rotation.Y * z - rotation.Z * y),
  920. position.Y + y * rotation.W + (rotation.Z * x - rotation.X * z),
  921. position.Z + z * rotation.W + (rotation.X * y - rotation.Y * x));
  922. }
  923. }
  924. /// <summary>
  925. /// Apply transformation on all vectors within array of <see cref="Vector3"/> by the specified <see cref="Matrix"/> and places the results in an another array.
  926. /// </summary>
  927. /// <param name="sourceArray">Source array.</param>
  928. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  929. /// <param name="destinationArray">Destination array.</param>
  930. public static void Transform(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
  931. {
  932. if (sourceArray == null)
  933. throw new ArgumentNullException("sourceArray");
  934. if (destinationArray == null)
  935. throw new ArgumentNullException("destinationArray");
  936. if (destinationArray.Length < sourceArray.Length)
  937. throw new ArgumentException("Destination array length is lesser than source array length");
  938. // TODO: Are there options on some platforms to implement a vectorized version of this?
  939. for (var i = 0; i < sourceArray.Length; i++)
  940. {
  941. var position = sourceArray[i];
  942. destinationArray[i] =
  943. new Vector3(
  944. (position.X*matrix.M11) + (position.Y*matrix.M21) + (position.Z*matrix.M31) + matrix.M41,
  945. (position.X*matrix.M12) + (position.Y*matrix.M22) + (position.Z*matrix.M32) + matrix.M42,
  946. (position.X*matrix.M13) + (position.Y*matrix.M23) + (position.Z*matrix.M33) + matrix.M43);
  947. }
  948. }
  949. /// <summary>
  950. /// Apply transformation on all vectors within array of <see cref="Vector3"/> by the specified <see cref="Quaternion"/> and places the results in an another array.
  951. /// </summary>
  952. /// <param name="sourceArray">Source array.</param>
  953. /// <param name="rotation">The <see cref="Quaternion"/> which contains rotation transformation.</param>
  954. /// <param name="destinationArray">Destination array.</param>
  955. public static void Transform(Vector3[] sourceArray, ref Quaternion rotation, Vector3[] destinationArray)
  956. {
  957. if (sourceArray == null)
  958. throw new ArgumentNullException("sourceArray");
  959. if (destinationArray == null)
  960. throw new ArgumentNullException("destinationArray");
  961. if (destinationArray.Length < sourceArray.Length)
  962. throw new ArgumentException("Destination array length is lesser than source array length");
  963. // TODO: Are there options on some platforms to implement a vectorized version of this?
  964. for (var i = 0; i < sourceArray.Length; i++)
  965. {
  966. var position = sourceArray[i];
  967. float x = 2 * (rotation.Y * position.Z - rotation.Z * position.Y);
  968. float y = 2 * (rotation.Z * position.X - rotation.X * position.Z);
  969. float z = 2 * (rotation.X * position.Y - rotation.Y * position.X);
  970. destinationArray[i] =
  971. new Vector3(
  972. position.X + x * rotation.W + (rotation.Y * z - rotation.Z * y),
  973. position.Y + y * rotation.W + (rotation.Z * x - rotation.X * z),
  974. position.Z + z * rotation.W + (rotation.X * y - rotation.Y * x));
  975. }
  976. }
  977. #endregion
  978. #region TransformNormal
  979. /// <summary>
  980. /// Creates a new <see cref="Vector3"/> that contains a transformation of the specified normal by the specified <see cref="Matrix"/>.
  981. /// </summary>
  982. /// <param name="normal">Source <see cref="Vector3"/> which represents a normal vector.</param>
  983. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  984. /// <returns>Transformed normal.</returns>
  985. public static Vector3 TransformNormal(Vector3 normal, Matrix matrix)
  986. {
  987. TransformNormal(ref normal, ref matrix, out normal);
  988. return normal;
  989. }
  990. /// <summary>
  991. /// Creates a new <see cref="Vector3"/> that contains a transformation of the specified normal by the specified <see cref="Matrix"/>.
  992. /// </summary>
  993. /// <param name="normal">Source <see cref="Vector3"/> which represents a normal vector.</param>
  994. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  995. /// <param name="result">Transformed normal as an output parameter.</param>
  996. public static void TransformNormal(ref Vector3 normal, ref Matrix matrix, out Vector3 result)
  997. {
  998. var x = (normal.X * matrix.M11) + (normal.Y * matrix.M21) + (normal.Z * matrix.M31);
  999. var y = (normal.X * matrix.M12) + (normal.Y * matrix.M22) + (normal.Z * matrix.M32);
  1000. var z = (normal.X * matrix.M13) + (normal.Y * matrix.M23) + (normal.Z * matrix.M33);
  1001. result.X = x;
  1002. result.Y = y;
  1003. result.Z = z;
  1004. }
  1005. /// <summary>
  1006. /// Apply transformation on normals within array of <see cref="Vector3"/> by the specified <see cref="Matrix"/> and places the results in an another array.
  1007. /// </summary>
  1008. /// <param name="sourceArray">Source array.</param>
  1009. /// <param name="sourceIndex">The starting index of transformation in the source array.</param>
  1010. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  1011. /// <param name="destinationArray">Destination array.</param>
  1012. /// <param name="destinationIndex">The starting index in the destination array, where the first <see cref="Vector3"/> should be written.</param>
  1013. /// <param name="length">The number of normals to be transformed.</param>
  1014. public static void TransformNormal(Vector3[] sourceArray,
  1015. int sourceIndex,
  1016. ref Matrix matrix,
  1017. Vector3[] destinationArray,
  1018. int destinationIndex,
  1019. int length)
  1020. {
  1021. if (sourceArray == null)
  1022. throw new ArgumentNullException("sourceArray");
  1023. if (destinationArray == null)
  1024. throw new ArgumentNullException("destinationArray");
  1025. if(sourceArray.Length < sourceIndex + length)
  1026. throw new ArgumentException("Source array length is lesser than sourceIndex + length");
  1027. if (destinationArray.Length < destinationIndex + length)
  1028. throw new ArgumentException("Destination array length is lesser than destinationIndex + length");
  1029. for (int x = 0; x < length; x++)
  1030. {
  1031. var normal = sourceArray[sourceIndex + x];
  1032. destinationArray[destinationIndex + x] =
  1033. new Vector3(
  1034. (normal.X * matrix.M11) + (normal.Y * matrix.M21) + (normal.Z * matrix.M31),
  1035. (normal.X * matrix.M12) + (normal.Y * matrix.M22) + (normal.Z * matrix.M32),
  1036. (normal.X * matrix.M13) + (normal.Y * matrix.M23) + (normal.Z * matrix.M33));
  1037. }
  1038. }
  1039. /// <summary>
  1040. /// Apply transformation on all normals within array of <see cref="Vector3"/> by the specified <see cref="Matrix"/> and places the results in an another array.
  1041. /// </summary>
  1042. /// <param name="sourceArray">Source array.</param>
  1043. /// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
  1044. /// <param name="destinationArray">Destination array.</param>
  1045. public static void TransformNormal(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
  1046. {
  1047. if(sourceArray == null)
  1048. throw new ArgumentNullException("sourceArray");
  1049. if (destinationArray == null)
  1050. throw new ArgumentNullException("destinationArray");
  1051. if (destinationArray.Length < sourceArray.Length)
  1052. throw new ArgumentException("Destination array length is lesser than source array length");
  1053. for (var i = 0; i < sourceArray.Length; i++)
  1054. {
  1055. var normal = sourceArray[i];
  1056. destinationArray[i] =
  1057. new Vector3(
  1058. (normal.X*matrix.M11) + (normal.Y*matrix.M21) + (normal.Z*matrix.M31),
  1059. (normal.X*matrix.M12) + (normal.Y*matrix.M22) + (normal.Z*matrix.M32),
  1060. (normal.X*matrix.M13) + (normal.Y*matrix.M23) + (normal.Z*matrix.M33));
  1061. }
  1062. }
  1063. #endregion
  1064. #endregion
  1065. #region Operators
  1066. /// <summary>
  1067. /// Compares whether two <see cref="Vector3"/> instances are equal.
  1068. /// </summary>
  1069. /// <param name="value1"><see cref="Vector3"/> instance on the left of the equal sign.</param>
  1070. /// <param name="value2"><see cref="Vector3"/> instance on the right of the equal sign.</param>
  1071. /// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
  1072. public static bool operator ==(Vector3 value1, Vector3 value2)
  1073. {
  1074. return value1.X == value2.X
  1075. && value1.Y == value2.Y
  1076. && value1.Z == value2.Z;
  1077. }
  1078. /// <summary>
  1079. /// Compares whether two <see cref="Vector3"/> instances are not equal.
  1080. /// </summary>
  1081. /// <param name="value1"><see cref="Vector3"/> instance on the left of the not equal sign.</param>
  1082. /// <param name="value2"><see cref="Vector3"/> instance on the right of the not equal sign.</param>
  1083. /// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
  1084. public static bool operator !=(Vector3 value1, Vector3 value2)
  1085. {
  1086. return !(value1 == value2);
  1087. }
  1088. /// <summary>
  1089. /// Adds two vectors.
  1090. /// </summary>
  1091. /// <param name="value1">Source <see cref="Vector3"/> on the left of the add sign.</param>
  1092. /// <param name="value2">Source <see cref="Vector3"/> on the right of the add sign.</param>
  1093. /// <returns>Sum of the vectors.</returns>
  1094. public static Vector3 operator +(Vector3 value1, Vector3 value2)
  1095. {
  1096. value1.X += value2.X;
  1097. value1.Y += value2.Y;
  1098. value1.Z += value2.Z;
  1099. return value1;
  1100. }
  1101. /// <summary>
  1102. /// Inverts values in the specified <see cref="Vector3"/>.
  1103. /// </summary>
  1104. /// <param name="value">Source <see cref="Vector3"/> on the right of the sub sign.</param>
  1105. /// <returns>Result of the inversion.</returns>
  1106. public static Vector3 operator -(Vector3 value)
  1107. {
  1108. value = new Vector3(-value.X, -value.Y, -value.Z);
  1109. return value;
  1110. }
  1111. /// <summary>
  1112. /// Subtracts a <see cref="Vector3"/> from a <see cref="Vector3"/>.
  1113. /// </summary>
  1114. /// <param name="value1">Source <see cref="Vector3"/> on the left of the sub sign.</param>
  1115. /// <param name="value2">Source <see cref="Vector3"/> on the right of the sub sign.</param>
  1116. /// <returns>Result of the vector subtraction.</returns>
  1117. public static Vector3 operator -(Vector3 value1, Vector3 value2)
  1118. {
  1119. value1.X -= value2.X;
  1120. value1.Y -= value2.Y;
  1121. value1.Z -= value2.Z;
  1122. return value1;
  1123. }
  1124. /// <summary>
  1125. /// Multiplies the components of two vectors by each other.
  1126. /// </summary>
  1127. /// <param name="value1">Source <see cref="Vector3"/> on the left of the mul sign.</param>
  1128. /// <param name="value2">Source <see cref="Vector3"/> on the right of the mul sign.</param>
  1129. /// <returns>Result of the vector multiplication.</returns>
  1130. public static Vector3 operator *(Vector3 value1, Vector3 value2)
  1131. {
  1132. value1.X *= value2.X;
  1133. value1.Y *= value2.Y;
  1134. value1.Z *= value2.Z;
  1135. return value1;
  1136. }
  1137. /// <summary>
  1138. /// Multiplies the components of vector by a scalar.
  1139. /// </summary>
  1140. /// <param name="value">Source <see cref="Vector3"/> on the left of the mul sign.</param>
  1141. /// <param name="scaleFactor">Scalar value on the right of the mul sign.</param>
  1142. /// <returns>Result of the vector multiplication with a scalar.</returns>
  1143. public static Vector3 operator *(Vector3 value, float scaleFactor)
  1144. {
  1145. value.X *= scaleFactor;
  1146. value.Y *= scaleFactor;
  1147. value.Z *= scaleFactor;
  1148. return value;
  1149. }
  1150. /// <summary>
  1151. /// Multiplies the components of vector by a scalar.
  1152. /// </summary>
  1153. /// <param name="scaleFactor">Scalar value on the left of the mul sign.</param>
  1154. /// <param name="value">Source <see cref="Vector3"/> on the right of the mul sign.</param>
  1155. /// <returns>Result of the vector multiplication with a scalar.</returns>
  1156. public static Vector3 operator *(float scaleFactor, Vector3 value)
  1157. {
  1158. value.X *= scaleFactor;
  1159. value.Y *= scaleFactor;
  1160. value.Z *= scaleFactor;
  1161. return value;
  1162. }
  1163. /// <summary>
  1164. /// Divides the components of a <see cref="Vector3"/> by the components of another <see cref="Vector3"/>.
  1165. /// </summary>
  1166. /// <param name="value1">Source <see cref="Vector3"/> on the left of the div sign.</param>
  1167. /// <param name="value2">Divisor <see cref="Vector3"/> on the right of the div sign.</param>
  1168. /// <returns>The result of dividing the vectors.</returns>
  1169. public static Vector3 operator /(Vector3 value1, Vector3 value2)
  1170. {
  1171. value1.X /= value2.X;
  1172. value1.Y /= value2.Y;
  1173. value1.Z /= value2.Z;
  1174. return value1;
  1175. }
  1176. /// <summary>
  1177. /// Divides the components of a <see cref="Vector3"/> by a scalar.
  1178. /// </summary>
  1179. /// <param name="value1">Source <see cref="Vector3"/> on the left of the div sign.</param>
  1180. /// <param name="divider">Divisor scalar on the right of the div sign.</param>
  1181. /// <returns>The result of dividing a vector by a scalar.</returns>
  1182. public static Vector3 operator /(Vector3 value1, float divider)
  1183. {
  1184. float factor = 1 / divider;
  1185. value1.X *= factor;
  1186. value1.Y *= factor;
  1187. value1.Z *= factor;
  1188. return value1;
  1189. }
  1190. #endregion
  1191. }
  1192. }