Vector3.cs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534
  1. #region --- License ---
  2. /*
  3. Copyright (c) 2006 - 2008 The Open Toolkit library.
  4. Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. this software and associated documentation files (the "Software"), to deal in
  6. the Software without restriction, including without limitation the rights to
  7. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  8. of the Software, and to permit persons to whom the Software is furnished to do
  9. so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in all
  11. copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18. SOFTWARE.
  19. */
  20. #endregion --- License ---
  21. using System;
  22. using System.Runtime.InteropServices;
  23. using System.Linq;
  24. using System.Collections.Generic;
  25. namespace MatterHackers.VectorMath
  26. {
  27. /// <summary>
  28. /// Represents a 3D vector using three double-precision floating-point numbers.
  29. /// </summary>
  30. [Serializable]
  31. [StructLayout(LayoutKind.Sequential)]
  32. public struct Vector3 : IEquatable<Vector3>
  33. {
  34. #region Fields
  35. /// <summary>
  36. /// The X component of the Vector3.
  37. /// </summary>
  38. public double X;
  39. /// <summary>
  40. /// The Y component of the Vector3.
  41. /// </summary>
  42. public double Y;
  43. /// <summary>
  44. /// The Z component of the Vector3.
  45. /// </summary>
  46. public double Z;
  47. #endregion Fields
  48. #region Constructors
  49. /// <summary>
  50. /// Constructs a new Vector3.
  51. /// </summary>
  52. /// <param name="x">The x component of the Vector3.</param>
  53. /// <param name="y">The y component of the Vector3.</param>
  54. /// <param name="z">The z component of the Vector3.</param>
  55. public Vector3(double x, double y, double z)
  56. {
  57. this.X = x;
  58. this.Y = y;
  59. this.Z = z;
  60. }
  61. /// <summary>
  62. /// Constructs a new instance from the given Vector2d.
  63. /// </summary>
  64. /// <param name="v">The Vector2d to copy components from.</param>
  65. public Vector3(Vector2 v, double z = 0)
  66. {
  67. X = v.X;
  68. Y = v.Y;
  69. this.Z = z;
  70. }
  71. /// <summary>
  72. /// Constructs a new instance from the given Vector3d.
  73. /// </summary>
  74. /// <param name="v">The Vector3d to copy components from.</param>
  75. public Vector3(Vector3 v)
  76. {
  77. X = v.X;
  78. Y = v.Y;
  79. Z = v.Z;
  80. }
  81. public Vector3(Vector3Float v)
  82. {
  83. X = v.X;
  84. Y = v.Y;
  85. Z = v.Z;
  86. }
  87. public Vector3(double[] doubleArray)
  88. {
  89. X = doubleArray[0];
  90. Y = doubleArray[1];
  91. Z = doubleArray[2];
  92. }
  93. /// <summary>
  94. /// Constructs a new instance from the given Vector4d.
  95. /// </summary>
  96. /// <param name="v">The Vector4d to copy components from.</param>
  97. public Vector3(Vector4 v)
  98. {
  99. X = v.X;
  100. Y = v.Y;
  101. Z = v.Z;
  102. }
  103. #endregion Constructors
  104. #region Properties
  105. public double this[int index]
  106. {
  107. get
  108. {
  109. switch (index)
  110. {
  111. case 0:
  112. return X;
  113. case 1:
  114. return Y;
  115. case 2:
  116. return Z;
  117. default:
  118. return 0;
  119. }
  120. }
  121. set
  122. {
  123. switch (index)
  124. {
  125. case 0:
  126. X = value;
  127. break;
  128. case 1:
  129. Y = value;
  130. break;
  131. case 2:
  132. Z = value;
  133. break;
  134. default:
  135. throw new Exception();
  136. }
  137. }
  138. }
  139. public void Set(double x, double y, double z)
  140. {
  141. X = x;
  142. Y = y;
  143. Z = z;
  144. }
  145. #endregion Properties
  146. #region Public Members
  147. #region Instance
  148. #region public double Length
  149. /// <summary>
  150. /// Gets the length (magnitude) of the vector.
  151. /// </summary>
  152. /// <see cref="LengthFast"/>
  153. /// <seealso cref="LengthSquared"/>
  154. public double Length
  155. {
  156. get
  157. {
  158. return System.Math.Sqrt(X * X + Y * Y + Z * Z);
  159. }
  160. }
  161. public double DistanceToSegment(Vector3 start, Vector3 end)
  162. {
  163. var segmentDelta = end - start;
  164. var segmentLength = segmentDelta.Length;
  165. var segmentNormal = segmentDelta.GetNormal();
  166. var deltaToStart = this - start;
  167. var distanceFromStart = segmentNormal.Dot(deltaToStart);
  168. if (distanceFromStart >= 0 && distanceFromStart < segmentLength)
  169. {
  170. var perpendicular = segmentNormal.GetPerpendicular(new Vector3(0, 0, 1));
  171. var distanceFromLine = Math.Abs(deltaToStart.Dot(perpendicular));
  172. return distanceFromLine;
  173. }
  174. if (distanceFromStart < 0)
  175. {
  176. return deltaToStart.Length;
  177. }
  178. var deltaToEnd = this - end;
  179. return deltaToEnd.Length;
  180. }
  181. #endregion public double Length
  182. #region public double LengthSquared
  183. /// <summary>
  184. /// Gets the square of the vector length (magnitude).
  185. /// </summary>
  186. /// <remarks>
  187. /// This property avoids the costly square root operation required by the Length property. This makes it more suitable
  188. /// for comparisons.
  189. /// </remarks>
  190. /// <see cref="Length"/>
  191. /// <seealso cref="LengthFast"/>
  192. public double LengthSquared
  193. {
  194. get
  195. {
  196. return X * X + Y * Y + Z * Z;
  197. }
  198. }
  199. #endregion public double LengthSquared
  200. #region public void Normalize()
  201. /// <summary>
  202. /// Returns a normalized Vector of this.
  203. /// </summary>
  204. /// <returns></returns>
  205. public Vector3 GetNormal()
  206. {
  207. Vector3 temp = this;
  208. temp.Normalize();
  209. return temp;
  210. }
  211. /// <summary>
  212. /// Scales the Vector3d to unit length.
  213. /// </summary>
  214. public void Normalize()
  215. {
  216. double length = this.Length;
  217. if (length != 0)
  218. {
  219. double scale = 1.0 / this.Length;
  220. X *= scale;
  221. Y *= scale;
  222. Z *= scale;
  223. }
  224. }
  225. #endregion public void Normalize()
  226. public bool IsValid()
  227. {
  228. if (double.IsNaN(X) || double.IsInfinity(X)
  229. || double.IsNaN(Y) || double.IsInfinity(Y)
  230. || double.IsNaN(Z) || double.IsInfinity(Z))
  231. {
  232. return false;
  233. }
  234. return true;
  235. }
  236. #region public double[] ToArray()
  237. public double[] ToArray()
  238. {
  239. return new double[] { X, Y, Z };
  240. }
  241. #endregion public double[] ToArray()
  242. #endregion Instance
  243. #region Static
  244. #region Fields
  245. /// <summary>
  246. /// Defines a unit-length Vector3d that points towards the X-axis.
  247. /// </summary>
  248. public static readonly Vector3 UnitX = new Vector3(1, 0, 0);
  249. /// <summary>
  250. /// Defines a unit-length Vector3d that points towards the Y-axis.
  251. /// </summary>
  252. public static readonly Vector3 UnitY = new Vector3(0, 1, 0);
  253. /// <summary>
  254. /// /// Defines a unit-length Vector3d that points towards the Z-axis.
  255. /// </summary>
  256. public static readonly Vector3 UnitZ = new Vector3(0, 0, 1);
  257. /// <summary>
  258. /// Defines a zero-length Vector3.
  259. /// </summary>
  260. public static readonly Vector3 Zero = new Vector3(0, 0, 0);
  261. /// <summary>
  262. /// Defines an instance with all components set to 1.
  263. /// </summary>
  264. public static readonly Vector3 One = new Vector3(1, 1, 1);
  265. /// <summary>
  266. /// Defines an instance with all components set to positive infinity.
  267. /// </summary>
  268. public static readonly Vector3 PositiveInfinity = new Vector3(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity);
  269. /// <summary>
  270. /// Defines an instance with all components set to negative infinity.
  271. /// </summary>
  272. public static readonly Vector3 NegativeInfinity = new Vector3(double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity);
  273. /// <summary>
  274. /// Defines the size of the Vector3d struct in bytes.
  275. /// </summary>
  276. public static readonly int SizeInBytes = Marshal.SizeOf(new Vector3());
  277. #endregion Fields
  278. #region Add
  279. /// <summary>
  280. /// Adds two vectors.
  281. /// </summary>
  282. /// <param name="a">Left operand.</param>
  283. /// <param name="b">Right operand.</param>
  284. /// <returns>Result of operation.</returns>
  285. public static Vector3 Add(Vector3 a, Vector3 b)
  286. {
  287. Add(ref a, ref b, out a);
  288. return a;
  289. }
  290. /// <summary>
  291. /// Adds two vectors.
  292. /// </summary>
  293. /// <param name="a">Left operand.</param>
  294. /// <param name="b">Right operand.</param>
  295. /// <param name="result">Result of operation.</param>
  296. public static void Add(ref Vector3 a, ref Vector3 b, out Vector3 result)
  297. {
  298. result = new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
  299. }
  300. #endregion Add
  301. #region Subtract
  302. /// <summary>
  303. /// Subtract one Vector from another
  304. /// </summary>
  305. /// <param name="a">First operand</param>
  306. /// <param name="b">Second operand</param>
  307. /// <returns>Result of subtraction</returns>
  308. public static Vector3 Subtract(Vector3 a, Vector3 b)
  309. {
  310. Subtract(ref a, ref b, out a);
  311. return a;
  312. }
  313. /// <summary>
  314. /// Subtract one Vector from another
  315. /// </summary>
  316. /// <param name="a">First operand</param>
  317. /// <param name="b">Second operand</param>
  318. /// <param name="result">Result of subtraction</param>
  319. public static void Subtract(ref Vector3 a, ref Vector3 b, out Vector3 result)
  320. {
  321. result = new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
  322. }
  323. #endregion Subtract
  324. #region Multiply
  325. /// <summary>
  326. /// Multiplies a vector by a scalar.
  327. /// </summary>
  328. /// <param name="vector">Left operand.</param>
  329. /// <param name="scale">Right operand.</param>
  330. /// <returns>Result of the operation.</returns>
  331. public static Vector3 Multiply(Vector3 vector, double scale)
  332. {
  333. Multiply(ref vector, scale, out vector);
  334. return vector;
  335. }
  336. /// <summary>
  337. /// Multiplies a vector by a scalar.
  338. /// </summary>
  339. /// <param name="vector">Left operand.</param>
  340. /// <param name="scale">Right operand.</param>
  341. /// <param name="result">Result of the operation.</param>
  342. public static void Multiply(ref Vector3 vector, double scale, out Vector3 result)
  343. {
  344. result = new Vector3(vector.X * scale, vector.Y * scale, vector.Z * scale);
  345. }
  346. /// <summary>
  347. /// Multiplies a vector by the components a vector (scale).
  348. /// </summary>
  349. /// <param name="vector">Left operand.</param>
  350. /// <param name="scale">Right operand.</param>
  351. /// <returns>Result of the operation.</returns>
  352. public static Vector3 Multiply(Vector3 vector, Vector3 scale)
  353. {
  354. Multiply(ref vector, ref scale, out vector);
  355. return vector;
  356. }
  357. /// <summary>
  358. /// Multiplies a vector by the components of a vector (scale).
  359. /// </summary>
  360. /// <param name="vector">Left operand.</param>
  361. /// <param name="scale">Right operand.</param>
  362. /// <param name="result">Result of the operation.</param>
  363. public static void Multiply(ref Vector3 vector, ref Vector3 scale, out Vector3 result)
  364. {
  365. result = new Vector3(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);
  366. }
  367. #endregion Multiply
  368. #region Divide
  369. /// <summary>
  370. /// Divides a vector by a scalar.
  371. /// </summary>
  372. /// <param name="vector">Left operand.</param>
  373. /// <param name="scale">Right operand.</param>
  374. /// <returns>Result of the operation.</returns>
  375. public static Vector3 Divide(Vector3 vector, double scale)
  376. {
  377. Divide(ref vector, scale, out vector);
  378. return vector;
  379. }
  380. /// <summary>
  381. /// Divides a vector by a scalar.
  382. /// </summary>
  383. /// <param name="vector">Left operand.</param>
  384. /// <param name="scale">Right operand.</param>
  385. /// <param name="result">Result of the operation.</param>
  386. public static void Divide(ref Vector3 vector, double scale, out Vector3 result)
  387. {
  388. Multiply(ref vector, 1 / scale, out result);
  389. }
  390. /// <summary>
  391. /// Divides a vector by the components of a vector (scale).
  392. /// </summary>
  393. /// <param name="vector">Left operand.</param>
  394. /// <param name="scale">Right operand.</param>
  395. /// <returns>Result of the operation.</returns>
  396. public static Vector3 Divide(Vector3 vector, Vector3 scale)
  397. {
  398. Divide(ref vector, ref scale, out vector);
  399. return vector;
  400. }
  401. /// <summary>
  402. /// Divide a vector by the components of a vector (scale).
  403. /// </summary>
  404. /// <param name="vector">Left operand.</param>
  405. /// <param name="scale">Right operand.</param>
  406. /// <param name="result">Result of the operation.</param>
  407. public static void Divide(ref Vector3 vector, ref Vector3 scale, out Vector3 result)
  408. {
  409. result = new Vector3(vector.X / scale.X, vector.Y / scale.Y, vector.Z / scale.Z);
  410. }
  411. #endregion Divide
  412. #region ComponentMin
  413. /// <summary>
  414. /// Calculate the component-wise minimum of two vectors
  415. /// </summary>
  416. /// <param name="a">First operand</param>
  417. /// <param name="b">Second operand</param>
  418. /// <returns>The component-wise minimum</returns>
  419. public static Vector3 ComponentMin(Vector3 a, Vector3 b)
  420. {
  421. a.X = a.X < b.X ? a.X : b.X;
  422. a.Y = a.Y < b.Y ? a.Y : b.Y;
  423. a.Z = a.Z < b.Z ? a.Z : b.Z;
  424. return a;
  425. }
  426. public static Vector3 Parse(string s)
  427. {
  428. var result = Vector3.Zero;
  429. var values = s.Split(',').Select(sValue =>
  430. {
  431. double.TryParse(sValue, out double number);
  432. return number;
  433. }).ToArray();
  434. for (int i = 0; i < Math.Min(3, values.Length); i++)
  435. {
  436. result[i] = values[i];
  437. }
  438. return result;
  439. }
  440. /// <summary>
  441. /// Calculate the component-wise minimum of two vectors
  442. /// </summary>
  443. /// <param name="a">First operand</param>
  444. /// <param name="b">Second operand</param>
  445. /// <param name="result">The component-wise minimum</param>
  446. public static void ComponentMin(ref Vector3 a, ref Vector3 b, out Vector3 result)
  447. {
  448. result.X = a.X < b.X ? a.X : b.X;
  449. result.Y = a.Y < b.Y ? a.Y : b.Y;
  450. result.Z = a.Z < b.Z ? a.Z : b.Z;
  451. }
  452. #endregion ComponentMin
  453. #region ComponentMax
  454. /// <summary>
  455. /// Calculate the component-wise maximum of two vectors
  456. /// </summary>
  457. /// <param name="a">First operand</param>
  458. /// <param name="b">Second operand</param>
  459. /// <returns>The component-wise maximum</returns>
  460. public static Vector3 ComponentMax(Vector3 a, Vector3 b)
  461. {
  462. a.X = a.X > b.X ? a.X : b.X;
  463. a.Y = a.Y > b.Y ? a.Y : b.Y;
  464. a.Z = a.Z > b.Z ? a.Z : b.Z;
  465. return a;
  466. }
  467. public static Vector3 ComponentMax(Vector3 a, double b)
  468. {
  469. a.X = a.X > b ? a.X : b;
  470. a.Y = a.Y > b ? a.Y : b;
  471. a.Z = a.Z > b ? a.Z : b;
  472. return a;
  473. }
  474. /// <summary>
  475. /// Calculate the component-wise maximum of two vectors
  476. /// </summary>
  477. /// <param name="a">First operand</param>
  478. /// <param name="b">Second operand</param>
  479. /// <param name="result">The component-wise maximum</param>
  480. public static void ComponentMax(ref Vector3 a, ref Vector3 b, out Vector3 result)
  481. {
  482. result.X = a.X > b.X ? a.X : b.X;
  483. result.Y = a.Y > b.Y ? a.Y : b.Y;
  484. result.Z = a.Z > b.Z ? a.Z : b.Z;
  485. }
  486. #endregion ComponentMax
  487. #region Min
  488. /// <summary>
  489. /// Returns the Vector3d with the minimum magnitude
  490. /// </summary>
  491. /// <param name="left">Left operand</param>
  492. /// <param name="right">Right operand</param>
  493. /// <returns>The minimum Vector3</returns>
  494. public static Vector3 Min(Vector3 left, Vector3 right)
  495. {
  496. return left.LengthSquared < right.LengthSquared ? left : right;
  497. }
  498. #endregion Min
  499. #region Max
  500. /// <summary>
  501. /// Returns the Vector3d with the minimum magnitude
  502. /// </summary>
  503. /// <param name="left">Left operand</param>
  504. /// <param name="right">Right operand</param>
  505. /// <returns>The minimum Vector3</returns>
  506. public static Vector3 Max(Vector3 left, Vector3 right)
  507. {
  508. return left.LengthSquared >= right.LengthSquared ? left : right;
  509. }
  510. #endregion Max
  511. #region Clamp
  512. /// <summary>
  513. /// Clamp a vector to the given minimum and maximum vectors
  514. /// </summary>
  515. /// <param name="vec">Input vector</param>
  516. /// <param name="min">Minimum vector</param>
  517. /// <param name="max">Maximum vector</param>
  518. /// <returns>The clamped vector</returns>
  519. public static Vector3 Clamp(Vector3 vec, Vector3 min, Vector3 max)
  520. {
  521. vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
  522. vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
  523. vec.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
  524. return vec;
  525. }
  526. /// <summary>
  527. /// Clamp a vector to the given minimum and maximum vectors
  528. /// </summary>
  529. /// <param name="vec">Input vector</param>
  530. /// <param name="min">Minimum vector</param>
  531. /// <param name="max">Maximum vector</param>
  532. /// <param name="result">The clamped vector</param>
  533. public static void Clamp(ref Vector3 vec, ref Vector3 min, ref Vector3 max, out Vector3 result)
  534. {
  535. result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
  536. result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
  537. result.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
  538. }
  539. #endregion Clamp
  540. #region Normalize
  541. /// <summary>
  542. /// Scale a vector to unit length
  543. /// </summary>
  544. /// <param name="vec">The input vector</param>
  545. /// <returns>The normalized vector</returns>
  546. public static Vector3 Normalize(Vector3 vec)
  547. {
  548. double scale = 1.0 / vec.Length;
  549. vec.X *= scale;
  550. vec.Y *= scale;
  551. vec.Z *= scale;
  552. return vec;
  553. }
  554. /// <summary>
  555. /// Scale a vector to unit length
  556. /// </summary>
  557. /// <param name="vec">The input vector</param>
  558. /// <param name="result">The normalized vector</param>
  559. public static void Normalize(ref Vector3 vec, out Vector3 result)
  560. {
  561. double scale = 1.0 / vec.Length;
  562. result.X = vec.X * scale;
  563. result.Y = vec.Y * scale;
  564. result.Z = vec.Z * scale;
  565. }
  566. #endregion Normalize
  567. #region Utility
  568. /// <summary>
  569. /// Checks if 3 points are collinear (all lie on the same line).
  570. /// </summary>
  571. /// <param name="a"></param>
  572. /// <param name="b"></param>
  573. /// <param name="c"></param>
  574. /// <param name="epsilon"></param>
  575. /// <returns></returns>
  576. public static bool Collinear(Vector3 a, Vector3 b, Vector3 c, double epsilon = .000001)
  577. {
  578. // Return true if a, b, and c all lie on the same line.
  579. return Math.Abs((b - a).Cross(c - a).Length) < epsilon;
  580. }
  581. public static Vector3 Abs(Vector3 a)
  582. {
  583. return new Vector3(Math.Abs(a.X), Math.Abs(a.Y), Math.Abs(a.Z));
  584. }
  585. /// <summary>
  586. /// Given an arbitrary vector find a perpendicular from the infinite perpendiculars that are available
  587. /// </summary>
  588. /// <param name="a">The vector to find a perpendicular for</param>
  589. /// <returns>A perpendicular vector to a</returns>
  590. public Vector3 GetPerpendicular()
  591. {
  592. if (this.X != 0)
  593. {
  594. return new Vector3(-(this.Y + this.Z) / this.X, 1, 1);
  595. }
  596. else if (this.Y != 0)
  597. {
  598. return new Vector3(1, -(this.X + this.Z) / this.Y, 1);
  599. }
  600. else if (this.Z != 0)
  601. {
  602. return new Vector3(1, 1, -(this.X + this.Y) / this.Z);
  603. }
  604. // the input vector has no length (no vector is perpendicular to it)
  605. return default(Vector3);
  606. }
  607. public Vector3 GetPerpendicular(Vector3 b)
  608. {
  609. return GetPerpendicular(this, b);
  610. }
  611. public static Vector3 GetPerpendicular(Vector3 a, Vector3 b)
  612. {
  613. if (!Collinear(a, b, Zero))
  614. {
  615. return a.Cross(b);
  616. }
  617. else
  618. {
  619. Vector3 zOne = new Vector3(0, 0, 100000);
  620. if (!Collinear(a, b, zOne))
  621. {
  622. return Vector3Ex.Cross(a - zOne, b - zOne);
  623. }
  624. else
  625. {
  626. Vector3 xOne = new Vector3(1000000, 0, 0);
  627. return Vector3Ex.Cross(a - xOne, b - xOne);
  628. }
  629. }
  630. }
  631. #endregion Utility
  632. #region Lerp
  633. /// <summary>
  634. /// Returns a new Vector that is the linear blend of the 2 given Vectors
  635. /// </summary>
  636. /// <param name="a">First input vector</param>
  637. /// <param name="b">Second input vector</param>
  638. /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
  639. /// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
  640. public static Vector3 Lerp(Vector3 a, Vector3 b, double blend)
  641. {
  642. if (blend == 0)
  643. {
  644. return a;
  645. }
  646. if (blend == 1)
  647. {
  648. return b;
  649. }
  650. a.X = blend * (b.X - a.X) + a.X;
  651. a.Y = blend * (b.Y - a.Y) + a.Y;
  652. a.Z = blend * (b.Z - a.Z) + a.Z;
  653. return a;
  654. }
  655. /// <summary>
  656. /// Returns a new Vector that is the linear blend of the 2 given Vectors
  657. /// </summary>
  658. /// <param name="a">First input vector</param>
  659. /// <param name="b">Second input vector</param>
  660. /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
  661. /// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
  662. public static void Lerp(ref Vector3 a, ref Vector3 b, double blend, out Vector3 result)
  663. {
  664. result.X = blend * (b.X - a.X) + a.X;
  665. result.Y = blend * (b.Y - a.Y) + a.Y;
  666. result.Z = blend * (b.Z - a.Z) + a.Z;
  667. }
  668. #endregion Lerp
  669. #region Barycentric
  670. /// <summary>
  671. /// Interpolate 3 Vectors using Barycentric coordinates
  672. /// </summary>
  673. /// <param name="a">First input Vector</param>
  674. /// <param name="b">Second input Vector</param>
  675. /// <param name="c">Third input Vector</param>
  676. /// <param name="u">First Barycentric Coordinate</param>
  677. /// <param name="v">Second Barycentric Coordinate</param>
  678. /// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
  679. public static Vector3 BaryCentric(Vector3 a, Vector3 b, Vector3 c, double u, double v)
  680. {
  681. return a + u * (b - a) + v * (c - a);
  682. }
  683. /// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
  684. /// <param name="a">First input Vector.</param>
  685. /// <param name="b">Second input Vector.</param>
  686. /// <param name="c">Third input Vector.</param>
  687. /// <param name="u">First Barycentric Coordinate.</param>
  688. /// <param name="v">Second Barycentric Coordinate.</param>
  689. /// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
  690. public static void BaryCentric(ref Vector3 a, ref Vector3 b, ref Vector3 c, double u, double v, out Vector3 result)
  691. {
  692. result = a; // copy
  693. Vector3 temp = b; // copy
  694. Subtract(ref temp, ref a, out temp);
  695. Multiply(ref temp, u, out temp);
  696. Add(ref result, ref temp, out result);
  697. temp = c; // copy
  698. Subtract(ref temp, ref a, out temp);
  699. Multiply(ref temp, v, out temp);
  700. Add(ref result, ref temp, out result);
  701. }
  702. #endregion Barycentric
  703. #region CalculateAngle
  704. /// <summary>
  705. /// Calculates the angle (in radians) between two vectors.
  706. /// </summary>
  707. /// <param name="first">The first vector.</param>
  708. /// <param name="second">The second vector.</param>
  709. /// <returns>Angle (in radians) between the vectors.</returns>
  710. /// <remarks>Note that the returned angle is never bigger than the constant Pi.</remarks>
  711. public static double CalculateAngle(Vector3 first, Vector3 second)
  712. {
  713. return System.Math.Acos((first.Dot(second)) / (first.Length * second.Length));
  714. }
  715. /// <summary>Calculates the angle (in radians) between two vectors.</summary>
  716. /// <param name="first">The first vector.</param>
  717. /// <param name="second">The second vector.</param>
  718. /// <param name="result">Angle (in radians) between the vectors.</param>
  719. /// <remarks>Note that the returned angle is never bigger than the constant Pi.</remarks>
  720. public static void CalculateAngle(ref Vector3 first, ref Vector3 second, out double result)
  721. {
  722. double temp;
  723. first.Dot(ref second, out temp);
  724. result = System.Math.Acos(temp / (first.Length * second.Length));
  725. }
  726. #endregion CalculateAngle
  727. #endregion Static
  728. #region Swizzle
  729. /// <summary>
  730. /// Gets or sets an OpenTK.Vector2d with the X and Y components of this instance.
  731. /// </summary>
  732. public Vector2 Xy { get { return new Vector2(X, Y); } set { X = value.X; Y = value.Y; } }
  733. #endregion Swizzle
  734. #region Operators
  735. /// <summary>
  736. /// Adds two instances.
  737. /// </summary>
  738. /// <param name="left">The first instance.</param>
  739. /// <param name="right">The second instance.</param>
  740. /// <returns>The result of the calculation.</returns>
  741. public static Vector3 operator +(Vector3 left, Vector3 right)
  742. {
  743. left.X += right.X;
  744. left.Y += right.Y;
  745. left.Z += right.Z;
  746. return left;
  747. }
  748. /// <summary>
  749. /// Subtracts two instances.
  750. /// </summary>
  751. /// <param name="left">The first instance.</param>
  752. /// <param name="right">The second instance.</param>
  753. /// <returns>The result of the calculation.</returns>
  754. public static Vector3 operator -(Vector3 left, Vector3 right)
  755. {
  756. left.X -= right.X;
  757. left.Y -= right.Y;
  758. left.Z -= right.Z;
  759. return left;
  760. }
  761. /// <summary>
  762. /// Negates an instance.
  763. /// </summary>
  764. /// <param name="vec">The instance.</param>
  765. /// <returns>The result of the calculation.</returns>
  766. public static Vector3 operator -(Vector3 vec)
  767. {
  768. vec.X = -vec.X;
  769. vec.Y = -vec.Y;
  770. vec.Z = -vec.Z;
  771. return vec;
  772. }
  773. /// <summary>
  774. /// Component wise multiply two vectors together, x*x, y*y, z*z.
  775. /// </summary>
  776. /// <param name="vecA"></param>
  777. /// <param name="vecB"></param>
  778. /// <returns></returns>
  779. public static Vector3 operator *(Vector3 vecA, Vector3 vecB)
  780. {
  781. vecA.X *= vecB.X;
  782. vecA.Y *= vecB.Y;
  783. vecA.Z *= vecB.Z;
  784. return vecA;
  785. }
  786. /// <summary>
  787. /// Multiplies an instance by a scalar.
  788. /// </summary>
  789. /// <param name="vec">The instance.</param>
  790. /// <param name="scale">The scalar.</param>
  791. /// <returns>The result of the calculation.</returns>
  792. public static Vector3 operator *(Vector3 vec, double scale)
  793. {
  794. vec.X *= scale;
  795. vec.Y *= scale;
  796. vec.Z *= scale;
  797. return vec;
  798. }
  799. /// <summary>
  800. /// Multiplies an instance by a scalar.
  801. /// </summary>
  802. /// <param name="scale">The scalar.</param>
  803. /// <param name="vec">The instance.</param>
  804. /// <returns>The result of the calculation.</returns>
  805. public static Vector3 operator *(double scale, Vector3 vec)
  806. {
  807. vec.X *= scale;
  808. vec.Y *= scale;
  809. vec.Z *= scale;
  810. return vec;
  811. }
  812. /// <summary>
  813. /// Creates a new vector which is the numerator divide by each component of the vector.
  814. /// </summary>
  815. /// <param name="numerator"></param>
  816. /// <param name="vec"></param>
  817. /// <returns>The result of the calculation.</returns>
  818. public static Vector3 operator /(double numerator, Vector3 vec)
  819. {
  820. return new Vector3((numerator / vec.X), (numerator / vec.Y), (numerator / vec.Z));
  821. }
  822. /// <summary>
  823. /// Divides an instance by a scalar.
  824. /// </summary>
  825. /// <param name="vec">The instance.</param>
  826. /// <param name="scale">The scalar.</param>
  827. /// <returns>The result of the calculation.</returns>
  828. public static Vector3 operator /(Vector3 vec, double scale)
  829. {
  830. double mult = 1 / scale;
  831. vec.X *= mult;
  832. vec.Y *= mult;
  833. vec.Z *= mult;
  834. return vec;
  835. }
  836. /// <summary>
  837. /// Compares two instances for equality.
  838. /// </summary>
  839. /// <param name="left">The first instance.</param>
  840. /// <param name="right">The second instance.</param>
  841. /// <returns>True, if left equals right; false otherwise.</returns>
  842. public static bool operator ==(Vector3 left, Vector3 right)
  843. {
  844. return left.Equals(right);
  845. }
  846. /// <summary>
  847. /// Compares two instances for inequality.
  848. /// </summary>
  849. /// <param name="left">The first instance.</param>
  850. /// <param name="right">The second instance.</param>
  851. /// <returns>True, if left does not equa lright; false otherwise.</returns>
  852. public static bool operator !=(Vector3 left, Vector3 right)
  853. {
  854. return !left.Equals(right);
  855. }
  856. #endregion Operators
  857. #region Overrides
  858. #region public override string ToString()
  859. /// <summary>
  860. /// Returns a System.String that represents the current Vector3.
  861. /// </summary>
  862. /// <returns></returns>
  863. public override string ToString()
  864. {
  865. return String.Format($"[{X:0.####}, {Y:0.####}, {Z:0.####}]");
  866. }
  867. #endregion public override string ToString()
  868. #region public override int GetHashCode()
  869. /// <summary>
  870. /// Returns the hashcode for this instance.
  871. /// </summary>
  872. /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
  873. public override int GetHashCode()
  874. {
  875. return new { X, Y, Z }.GetHashCode();
  876. }
  877. /// <summary>
  878. /// return a 64 bit hash code proposed by Jon Skeet
  879. // http://stackoverflow.com/questions/8094867/good-gethashcode-override-for-list-of-foo-objects-respecting-the-order
  880. /// </summary>
  881. /// <returns></returns>
  882. public ulong GetLongHashCode(ulong hash = 14695981039346656037)
  883. {
  884. hash = Vector4.GetLongHashCode(X, hash);
  885. hash = Vector4.GetLongHashCode(Y, hash);
  886. hash = Vector4.GetLongHashCode(Z, hash);
  887. return hash;
  888. }
  889. #endregion public override int GetHashCode()
  890. #region public override bool Equals(object obj)
  891. /// <summary>
  892. /// Indicates whether this instance and a specified object are equal.
  893. /// </summary>
  894. /// <param name="obj">The object to compare to.</param>
  895. /// <returns>True if the instances are equal; false otherwise.</returns>
  896. public override bool Equals(object obj)
  897. {
  898. if (!(obj is Vector3))
  899. return false;
  900. return this.Equals((Vector3)obj);
  901. }
  902. /// <summary>
  903. /// Indicates whether this instance and a specified object are equal within an error range.
  904. /// </summary>
  905. /// <param name="OtherVector"></param>
  906. /// <param name="ErrorValue"></param>
  907. /// <returns>True if the instances are equal; false otherwise.</returns>
  908. public bool Equals(Vector3 OtherVector, double ErrorValue)
  909. {
  910. if ((X < OtherVector.X + ErrorValue && X > OtherVector.X - ErrorValue) &&
  911. (Y < OtherVector.Y + ErrorValue && Y > OtherVector.Y - ErrorValue) &&
  912. (Z < OtherVector.Z + ErrorValue && Z > OtherVector.Z - ErrorValue))
  913. {
  914. return true;
  915. }
  916. return false;
  917. }
  918. #endregion public override bool Equals(object obj)
  919. #endregion Overrides
  920. #endregion Public Members
  921. #region IEquatable<Vector3> Members
  922. /// <summary>Indicates whether the current vector is equal to another vector.</summary>
  923. /// <param name="other">A vector to compare with this vector.</param>
  924. /// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
  925. public bool Equals(Vector3 other)
  926. {
  927. return
  928. X == other.X &&
  929. Y == other.Y &&
  930. Z == other.Z;
  931. }
  932. #endregion IEquatable<Vector3> Members
  933. #region IConvertable
  934. public TypeCode GetTypeCode()
  935. {
  936. throw new NotImplementedException();
  937. }
  938. public bool ToBoolean(IFormatProvider provider)
  939. {
  940. throw new NotImplementedException();
  941. }
  942. public char ToChar(IFormatProvider provider)
  943. {
  944. throw new NotImplementedException();
  945. }
  946. public sbyte ToSByte(IFormatProvider provider)
  947. {
  948. throw new NotImplementedException();
  949. }
  950. public byte ToByte(IFormatProvider provider)
  951. {
  952. throw new NotImplementedException();
  953. }
  954. public short ToInt16(IFormatProvider provider)
  955. {
  956. throw new NotImplementedException();
  957. }
  958. public ushort ToUInt16(IFormatProvider provider)
  959. {
  960. throw new NotImplementedException();
  961. }
  962. public int ToInt32(IFormatProvider provider)
  963. {
  964. throw new NotImplementedException();
  965. }
  966. public uint ToUInt32(IFormatProvider provider)
  967. {
  968. throw new NotImplementedException();
  969. }
  970. public long ToInt64(IFormatProvider provider)
  971. {
  972. throw new NotImplementedException();
  973. }
  974. public ulong ToUInt64(IFormatProvider provider)
  975. {
  976. throw new NotImplementedException();
  977. }
  978. public float ToSingle(IFormatProvider provider)
  979. {
  980. throw new NotImplementedException();
  981. }
  982. public double ToDouble(IFormatProvider provider)
  983. {
  984. throw new NotImplementedException();
  985. }
  986. public decimal ToDecimal(IFormatProvider provider)
  987. {
  988. throw new NotImplementedException();
  989. }
  990. public DateTime ToDateTime(IFormatProvider provider)
  991. {
  992. throw new NotImplementedException();
  993. }
  994. public string ToString(IFormatProvider provider)
  995. {
  996. throw new NotImplementedException();
  997. }
  998. public object ToType(Type conversionType, IFormatProvider provider)
  999. {
  1000. throw new NotImplementedException();
  1001. }
  1002. #endregion IConvertable
  1003. public static double ComponentMax(Vector3 vector3)
  1004. {
  1005. return Math.Max(vector3.X, Math.Max(vector3.Y, vector3.Z));
  1006. }
  1007. public static double ComponentMin(Vector3 vector3)
  1008. {
  1009. return Math.Min(vector3.X, Math.Min(vector3.Y, vector3.Z));
  1010. }
  1011. }
  1012. public static class Vector3Ex
  1013. {
  1014. #region Dot
  1015. /// <summary>
  1016. /// Calculate the dot (scalar) product of two vectors
  1017. /// </summary>
  1018. /// <param name="left">First operand</param>
  1019. /// <param name="right">Second operand</param>
  1020. /// <returns>The dot product of the two inputs</returns>
  1021. public static double Dot(this Vector3 left, Vector3 right)
  1022. {
  1023. return left.X * right.X + left.Y * right.Y + left.Z * right.Z;
  1024. }
  1025. public static float[] ToFloatArray(this List<Vector3> list)
  1026. {
  1027. var array = new float[list.Count * 3];
  1028. for (var i=0; i<list.Count; i++)
  1029. {
  1030. array[i * 3 + 0] = (float)list[i].X;
  1031. array[i * 3 + 1] = (float)list[i].Y;
  1032. array[i * 3 + 2] = (float)list[i].Z;
  1033. }
  1034. return array;
  1035. }
  1036. /// <summary>
  1037. /// Calculate the dot (scalar) product of two vectors
  1038. /// </summary>
  1039. /// <param name="left">First operand</param>
  1040. /// <param name="right">Second operand</param>
  1041. /// <param name="result">The dot product of the two inputs</param>
  1042. public static void Dot(this Vector3 left, ref Vector3 right, out double result)
  1043. {
  1044. result = left.X * right.X + left.Y * right.Y + left.Z * right.Z;
  1045. }
  1046. #endregion Dot
  1047. #region Cross
  1048. /// <summary>
  1049. /// Calculate the cross (vector) product of two vectors
  1050. /// </summary>
  1051. /// <param name="left">First operand</param>
  1052. /// <param name="right">Second operand</param>
  1053. /// <returns>The cross product of the two inputs</returns>
  1054. public static Vector3 Cross(this Vector3 left, Vector3 right)
  1055. {
  1056. Vector3 result;
  1057. left.Cross(ref right, out result);
  1058. return result;
  1059. }
  1060. /// <summary>
  1061. /// Calculate the cross (vector) product of two vectors
  1062. /// </summary>
  1063. /// <param name="left">First operand</param>
  1064. /// <param name="right">Second operand</param>
  1065. /// <returns>The cross product of the two inputs</returns>
  1066. /// <param name="result">The cross product of the two inputs</param>
  1067. public static void Cross(this Vector3 left, ref Vector3 right, out Vector3 result)
  1068. {
  1069. result = new Vector3(left.Y * right.Z - left.Z * right.Y,
  1070. left.Z * right.X - left.X * right.Z,
  1071. left.X * right.Y - left.Y * right.X);
  1072. }
  1073. #endregion Cross
  1074. #region Transform
  1075. /// <summary>Transform a direction vector by the given Matrix
  1076. /// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
  1077. /// </summary>
  1078. /// <param name="vec">The vector to transform</param>
  1079. /// <param name="mat">The desired transformation</param>
  1080. /// <returns>The transformed vector</returns>
  1081. public static Vector3 TransformVector(this Vector3 vec, Matrix4X4 mat)
  1082. {
  1083. return new Vector3(
  1084. vec.Dot(new Vector3(mat.Column0)),
  1085. vec.Dot(new Vector3(mat.Column1)),
  1086. vec.Dot(new Vector3(mat.Column2)));
  1087. }
  1088. /// <summary>Transform a direction vector by the given Matrix
  1089. /// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
  1090. /// </summary>
  1091. /// <param name="vec">The vector to transform</param>
  1092. /// <param name="mat">The desired transformation</param>
  1093. /// <param name="result">The transformed vector</param>
  1094. public static void TransformVector(this Vector3 vec, ref Matrix4X4 mat, out Vector3 result)
  1095. {
  1096. result.X = vec.X * mat.Row0.X +
  1097. vec.Y * mat.Row1.X +
  1098. vec.Z * mat.Row2.X;
  1099. result.Y = vec.X * mat.Row0.Y +
  1100. vec.Y * mat.Row1.Y +
  1101. vec.Z * mat.Row2.Y;
  1102. result.Z = vec.X * mat.Row0.Z +
  1103. vec.Y * mat.Row1.Z +
  1104. vec.Z * mat.Row2.Z;
  1105. }
  1106. /// This calculates the inverse of the given matrix, use TransformNormalInverse if you
  1107. /// already have the inverse to avoid this extra calculation
  1108. /// <param name="normal">The normal to transform</param>
  1109. /// <param name="mat">The desired transformation</param>
  1110. /// <returns>The transformed normal</returns>
  1111. public static Vector3 TransformNormal(this Vector3 normal, Matrix4X4 mat)
  1112. {
  1113. Vector3 result;
  1114. TransformNormal(normal, ref mat, out result);
  1115. return result;
  1116. }
  1117. /// <summary>Transform a Normal by the given Matrix</summary>
  1118. /// <remarks>
  1119. /// This calculates the inverse of the given matrix, use TransformNormal if you have
  1120. /// a point on the plane (fastest) or TransformNormalInverse if you
  1121. /// have the inverse but not a point on the plane - to avoid this extra calculation
  1122. /// </remarks>
  1123. /// <param name="normal">The normal to transform</param>
  1124. /// <param name="mat">The desired transformation</param>
  1125. /// <param name="result">The transformed normal</param>
  1126. public static void TransformNormal(this Vector3 normal, ref Matrix4X4 mat, out Vector3 result)
  1127. {
  1128. Matrix4X4 Inverse = Matrix4X4.Invert(mat);
  1129. TransformNormalInverse(normal, ref Inverse, out result);
  1130. }
  1131. /// <summary>Transform a Normal by the (transpose of the) given Matrix</summary>
  1132. /// <remarks>
  1133. /// This version doesn't calculate the inverse matrix.
  1134. /// Use this version if you already have the inverse of the desired transform to hand
  1135. /// </remarks>
  1136. /// <param name="normal">The normal to transform</param>
  1137. /// <param name="invMat">The inverse of the desired transformation</param>
  1138. /// <returns>The transformed normal</returns>
  1139. public static Vector3 TransformNormalInverse(this Vector3 normal, Matrix4X4 invMat)
  1140. {
  1141. return new Vector3(
  1142. normal.Dot(new Vector3(invMat.Row0)),
  1143. normal.Dot(new Vector3(invMat.Row1)),
  1144. normal.Dot(new Vector3(invMat.Row2)));
  1145. }
  1146. /// <summary>Transform a Normal by the (transpose of the) given Matrix</summary>
  1147. /// <remarks>
  1148. /// This version doesn't calculate the inverse matrix.
  1149. /// Use this version if you already have the inverse of the desired transform to hand
  1150. /// </remarks>
  1151. /// <param name="normal">The normal to transform</param>
  1152. /// <param name="invMat">The inverse of the desired transformation</param>
  1153. /// <param name="result">The transformed normal</param>
  1154. public static void TransformNormalInverse(this Vector3 normal, ref Matrix4X4 invMat, out Vector3 result)
  1155. {
  1156. result.X = normal.X * invMat.Row0.X +
  1157. normal.Y * invMat.Row0.Y +
  1158. normal.Z * invMat.Row0.Z;
  1159. result.Y = normal.X * invMat.Row1.X +
  1160. normal.Y * invMat.Row1.Y +
  1161. normal.Z * invMat.Row1.Z;
  1162. result.Z = normal.X * invMat.Row2.X +
  1163. normal.Y * invMat.Row2.Y +
  1164. normal.Z * invMat.Row2.Z;
  1165. }
  1166. /// <summary>Transform a Position by the given Matrix</summary>
  1167. /// <param name="pos">The position to transform</param>
  1168. /// <param name="mat">The desired transformation</param>
  1169. /// <returns>The transformed position</returns>
  1170. public static Vector3 TransformPosition(this Vector3 pos, Matrix4X4 mat)
  1171. {
  1172. return new Vector3(
  1173. pos.Dot(new Vector3(mat.Column0)) + mat.Row3.X,
  1174. pos.Dot(new Vector3(mat.Column1)) + mat.Row3.Y,
  1175. pos.Dot(new Vector3(mat.Column2)) + mat.Row3.Z);
  1176. }
  1177. /// <summary>Transform a Position by the given Matrix</summary>
  1178. /// <param name="pos">The position to transform</param>
  1179. /// <param name="mat">The desired transformation</param>
  1180. /// <param name="result">The transformed position</param>
  1181. public static void TransformPosition(this Vector3 pos, ref Matrix4X4 mat, out Vector3 result)
  1182. {
  1183. result.X = pos.X * mat.Row0.X +
  1184. pos.Y * mat.Row1.X +
  1185. pos.Z * mat.Row2.X +
  1186. mat.Row3.X;
  1187. result.Y = pos.X * mat.Row0.Y +
  1188. pos.Y * mat.Row1.Y +
  1189. pos.Z * mat.Row2.Y +
  1190. mat.Row3.Y;
  1191. result.Z = pos.X * mat.Row0.Z +
  1192. pos.Y * mat.Row1.Z +
  1193. pos.Z * mat.Row2.Z +
  1194. mat.Row3.Z;
  1195. }
  1196. /// <summary>
  1197. /// Transform all the vectors in the array by the given Matrix.
  1198. /// </summary>
  1199. /// <param name="boundsVerts"></param>
  1200. /// <param name="rotationQuaternion"></param>
  1201. public static void Transform(this Vector3[] vecArray, Matrix4X4 mat)
  1202. {
  1203. for (int i = 0; i < vecArray.Length; i++)
  1204. {
  1205. vecArray[i] = Transform(vecArray[i], mat);
  1206. }
  1207. }
  1208. /// <summary>Transform a Vector by the given Matrix</summary>
  1209. /// <param name="vec">The vector to transform</param>
  1210. /// <param name="mat">The desired transformation</param>
  1211. /// <returns>The transformed vector</returns>
  1212. public static Vector3 Transform(this Vector3 vec, Matrix4X4 mat)
  1213. {
  1214. return new Vector3(
  1215. vec.X * mat.Row0.X + vec.Y * mat.Row1.X + vec.Z * mat.Row2.X + mat.Row3.X,
  1216. vec.X * mat.Row0.Y + vec.Y * mat.Row1.Y + vec.Z * mat.Row2.Y + mat.Row3.Y,
  1217. vec.X * mat.Row0.Z + vec.Y * mat.Row1.Z + vec.Z * mat.Row2.Z + mat.Row3.Z);
  1218. }
  1219. /// <summary>Transform a Vector by the given Matrix</summary>
  1220. /// <param name="vec">The vector to transform</param>
  1221. /// <param name="mat">The desired transformation</param>
  1222. /// <param name="result">The transformed vector</param>
  1223. public static void Transform(this Vector3 vec, ref Matrix4X4 mat, out Vector3 result)
  1224. {
  1225. result = new Vector3(
  1226. vec.X * mat.Row0.X + vec.Y * mat.Row1.X + vec.Z * mat.Row2.X + mat.Row3.X,
  1227. vec.X * mat.Row0.Y + vec.Y * mat.Row1.Y + vec.Z * mat.Row2.Y + mat.Row3.Y,
  1228. vec.X * mat.Row0.Z + vec.Y * mat.Row1.Z + vec.Z * mat.Row2.Z + mat.Row3.Z);
  1229. }
  1230. /// <summary>
  1231. /// Transforms a vector by a quaternion rotation.
  1232. /// </summary>
  1233. /// <param name="vec">The vector to transform.</param>
  1234. /// <param name="quat">The quaternion to rotate the vector by.</param>
  1235. /// <returns>The result of the operation.</returns>
  1236. public static Vector3 Transform(this Vector3 vec, Quaternion quat)
  1237. {
  1238. Vector3 result;
  1239. Transform(vec, ref quat, out result);
  1240. return result;
  1241. }
  1242. /// <summary>
  1243. /// Transforms a vector by a quaternion rotation.
  1244. /// </summary>
  1245. /// <param name="vec">The vector to transform.</param>
  1246. /// <param name="quat">The quaternion to rotate the vector by.</param>
  1247. /// <param name="result">The result of the operation.</param>
  1248. public static void Transform(this Vector3 vec, ref Quaternion quat, out Vector3 result)
  1249. {
  1250. // Since vec.W == 0, we can optimize quat * vec * quat^-1 as follows:
  1251. // vec + 2.0 * cross(quat.xyz, cross(quat.xyz, vec) + quat.w * vec)
  1252. Vector3 xyz = quat.Xyz, temp, temp2;
  1253. xyz.Cross(ref vec, out temp);
  1254. Vector3.Multiply(ref vec, quat.W, out temp2);
  1255. Vector3.Add(ref temp, ref temp2, out temp);
  1256. xyz.Cross(ref temp, out temp);
  1257. Vector3.Multiply(ref temp, 2, out temp);
  1258. Vector3.Add(ref vec, ref temp, out result);
  1259. }
  1260. /// <summary>
  1261. /// Transform all the vectors in the array by the quaternion rotation.
  1262. /// </summary>
  1263. /// <param name="boundsVerts"></param>
  1264. /// <param name="rotationQuaternion"></param>
  1265. public static void Transform(this Vector3[] vecArray, Quaternion rotationQuaternion)
  1266. {
  1267. for (int i = 0; i < vecArray.Length; i++)
  1268. {
  1269. vecArray[i] = Transform(vecArray[i], rotationQuaternion);
  1270. }
  1271. }
  1272. /// <summary>
  1273. /// Transform a Vector3d by the given Matrix, and project the resulting Vector4 back to a Vector3
  1274. /// </summary>
  1275. /// <param name="vec">The vector to transform</param>
  1276. /// <param name="mat">The desired transformation</param>
  1277. /// <returns>The transformed vector</returns>
  1278. public static Vector3 TransformPerspective(this Vector3 vec, Matrix4X4 mat)
  1279. {
  1280. Vector3 result;
  1281. TransformPerspective(vec, ref mat, out result);
  1282. return result;
  1283. }
  1284. /// <summary>Transform a Vector3d by the given Matrix, and project the resulting Vector4d back to a Vector3d</summary>
  1285. /// <param name="vec">The vector to transform</param>
  1286. /// <param name="mat">The desired transformation</param>
  1287. /// <param name="result">The transformed vector</param>
  1288. public static void TransformPerspective(this Vector3 vec, ref Matrix4X4 mat, out Vector3 result)
  1289. {
  1290. Vector4 v = new Vector4(vec);
  1291. Vector4.Transform(v, ref mat, out v);
  1292. result.X = v.X / v.W;
  1293. result.Y = v.Y / v.W;
  1294. result.Z = v.Z / v.W;
  1295. }
  1296. #endregion Transform
  1297. public static Vector3 Abs(this Vector3 a)
  1298. {
  1299. return Vector3.Abs(a);
  1300. }
  1301. }
  1302. }