No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

affine_transform.cs 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using Unity.IL2CPP.CompilerServices;
  4. using static Unity.Mathematics.math;
  5. namespace Unity.Mathematics
  6. {
  7. /// <summary>
  8. /// An affine transformation type.
  9. /// </summary>
  10. [Il2CppEagerStaticClassConstruction]
  11. [Serializable]
  12. public struct AffineTransform : IEquatable<AffineTransform>, IFormattable
  13. {
  14. /// <summary>
  15. /// The rotation and scale part of the affine transformation.
  16. /// </summary>
  17. public float3x3 rs;
  18. /// <summary>
  19. /// The translation part of the affine transformation.
  20. /// </summary>
  21. public float3 t;
  22. /// <summary>An AffineTransform representing the identity transform.</summary>
  23. public static readonly AffineTransform identity = new AffineTransform(float3.zero, float3x3.identity);
  24. /// <summary>
  25. /// An AffineTransform zero value.
  26. /// </summary>
  27. public static readonly AffineTransform zero;
  28. /// <summary>Constructs an AffineTransform from a translation represented by a float3 vector and rotation represented by a unit quaternion.</summary>
  29. /// <param name="translation">The translation vector.</param>
  30. /// <param name="rotation">The rotation quaternion.</param>
  31. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  32. public AffineTransform(float3 translation, quaternion rotation)
  33. {
  34. rs = float3x3(rotation);
  35. t = translation;
  36. }
  37. /// <summary>Constructs an AffineTransform from a translation represented by a float3 vector, rotation represented by a unit quaternion and scale represented by a float3 vector.</summary>
  38. /// <param name="translation">The translation vector.</param>
  39. /// <param name="rotation">The rotation quaternion.</param>
  40. /// <param name="scale">The scale vector.</param>
  41. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  42. public AffineTransform(float3 translation, quaternion rotation, float3 scale)
  43. {
  44. rs = mulScale(math.float3x3(rotation), scale);
  45. t = translation;
  46. }
  47. /// <summary>Constructs an AffineTransform from a translation represented by float3 vector and a float3x3 matrix representing both rotation and scale.</summary>
  48. /// <param name="translation">The translation vector.</param>
  49. /// <param name="rotationScale">The rotation and scale matrix.</param>
  50. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  51. public AffineTransform(float3 translation, float3x3 rotationScale)
  52. {
  53. rs = rotationScale;
  54. t = translation;
  55. }
  56. /// <summary>Constructs an AffineTransform from float3x3 matrix representating both rotation and scale.</summary>
  57. /// <param name="rotationScale">The rotation and scale matrix.</param>
  58. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  59. public AffineTransform(float3x3 rotationScale)
  60. {
  61. rs = rotationScale;
  62. t = float3.zero;
  63. }
  64. /// <summary>Constructs an AffineTransform from a RigidTransform.</summary>
  65. /// <param name="rigid">The RigidTransform.</param>
  66. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  67. public AffineTransform(RigidTransform rigid)
  68. {
  69. rs = math.float3x3(rigid.rot);
  70. t = rigid.pos;
  71. }
  72. /// <summary>Constructs an AffineTransform from a float3x4 matrix.</summary>
  73. /// <param name="m">The float3x4 matrix.</param>
  74. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  75. public AffineTransform(float3x4 m)
  76. {
  77. rs = math.float3x3(m.c0, m.c1, m.c2);
  78. t = m.c3;
  79. }
  80. /// <summary>Constructs an AffineTransform from a float4x4 matrix.</summary>
  81. /// <param name="m">The float4x4 matrix.</param>
  82. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  83. public AffineTransform(float4x4 m)
  84. {
  85. rs = math.float3x3(m.c0.xyz, m.c1.xyz, m.c2.xyz);
  86. t = m.c3.xyz;
  87. }
  88. /// <summary>Implicit float3x4 cast operator.</summary>
  89. /// <param name="m">The AffineTransform.</param>
  90. /// <returns>The converted AffineTransform.</returns>
  91. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  92. public static implicit operator float3x4(AffineTransform m) { return float3x4(m.rs.c0, m.rs.c1, m.rs.c2, m.t); }
  93. /// <summary>Implicit float4x4 cast operator.</summary>
  94. /// <param name="m">The AffineTransform.</param>
  95. /// <returns>The converted AffineTransform.</returns>
  96. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  97. public static implicit operator float4x4(AffineTransform m) { return float4x4(float4(m.rs.c0, 0f), float4(m.rs.c1, 0f), float4(m.rs.c2, 0f), float4(m.t, 1f)); }
  98. /// <summary>Returns true if the AffineTransform is equal to a given AffineTransform, false otherwise.</summary>
  99. /// <param name="rhs">Right hand side argument to compare equality with.</param>
  100. /// <returns>The result of the equality comparison.</returns>
  101. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  102. public bool Equals(AffineTransform rhs) { return rs.Equals(rhs.rs) && t.Equals(rhs.t); }
  103. /// <summary>Returns true if the AffineTransform is equal to a given AffineTransform, false otherwise.</summary>
  104. /// <param name="o">Right hand side argument to compare equality with.</param>
  105. /// <returns>The result of the equality comparison.</returns>
  106. public override bool Equals(object o) { return o is AffineTransform converted && Equals(converted); }
  107. /// <summary>Returns a hash code for the AffineTransform.</summary>
  108. /// <returns>The computed hash code.</returns>
  109. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  110. public override int GetHashCode() { return (int)hash(this); }
  111. /// <summary>Returns a string representation of the AffineTransform.</summary>
  112. /// <returns>String representation of the value.</returns>
  113. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  114. public override string ToString()
  115. {
  116. return string.Format("AffineTransform(({0}f, {1}f, {2}f, {3}f, {4}f, {5}f, {6}f, {7}f, {8}f), ({9}f, {10}f, {11}f))",
  117. rs.c0.x, rs.c1.x, rs.c2.x, rs.c0.y, rs.c1.y, rs.c2.y, rs.c0.z, rs.c1.z, rs.c2.z, t.x, t.y, t.z
  118. );
  119. }
  120. /// <summary>Returns a string representation of the AffineTransform using a specified format and culture-specific format information.</summary>
  121. /// <param name="format">Format string to use during string formatting.</param>
  122. /// <param name="formatProvider">Format provider to use during string formatting.</param>
  123. /// <returns>String representation of the value.</returns>
  124. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  125. public string ToString(string format, IFormatProvider formatProvider)
  126. {
  127. return string.Format("AffineTransform(({0}f, {1}f, {2}f, {3}f, {4}f, {5}f, {6}f, {7}f, {8}f), ({9}f, {10}f, {11}f))",
  128. rs.c0.x.ToString(format, formatProvider), rs.c1.x.ToString(format, formatProvider), rs.c2.x.ToString(format, formatProvider),
  129. rs.c0.y.ToString(format, formatProvider), rs.c1.y.ToString(format, formatProvider), rs.c2.y.ToString(format, formatProvider),
  130. rs.c0.z.ToString(format, formatProvider), rs.c1.z.ToString(format, formatProvider), rs.c2.z.ToString(format, formatProvider),
  131. t.x.ToString(format, formatProvider), t.y.ToString(format, formatProvider), t.z.ToString(format, formatProvider)
  132. );
  133. }
  134. }
  135. public static partial class math
  136. {
  137. /// <summary>Returns an AffineTransform constructed from a translation represented by a float3 vector and rotation represented by a unit quaternion.</summary>
  138. /// <param name="translation">The AffineTransform translation.</param>
  139. /// <param name="rotation">The AffineTransform rotation.</param>
  140. /// <returns>The AffineTransform given the translation vector and rotation quaternion.</returns>
  141. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  142. public static AffineTransform AffineTransform(float3 translation, quaternion rotation) { return new AffineTransform(translation, rotation); }
  143. /// <summary>Returns an AffineTransform constructed from a translation represented by a float3 vector, rotation represented by a unit quaternion and scale represented by a float3 vector.</summary>
  144. /// <param name="translation">The translation vector.</param>
  145. /// <param name="rotation">The rotation quaternion.</param>
  146. /// <param name="scale">The scale vector.</param>
  147. /// <returns>The AffineTransform given the translation vector, rotation quaternion and scale vector.</returns>
  148. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  149. public static AffineTransform AffineTransform(float3 translation, quaternion rotation, float3 scale) { return new AffineTransform(translation, rotation, scale); }
  150. /// <summary>Returns an AffineTransform constructed from a translation represented by float3 vector and a float3x3 matrix representing both rotation and scale.</summary>
  151. /// <param name="translation">The translation vector.</param>
  152. /// <param name="rotationScale">The rotation and scale matrix.</param>
  153. /// <returns>The AffineTransform given the translation vector and float3x3 matrix.</returns>
  154. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  155. public static AffineTransform AffineTransform(float3 translation, float3x3 rotationScale) { return new AffineTransform(translation, rotationScale); }
  156. /// <summary>Returns an AffineTransform constructed from a float3x3 matrix representing both rotation and scale.</summary>
  157. /// <param name="rotationScale">The rotation and scale matrix.</param>
  158. /// <returns>The AffineTransform given a float3x3 matrix.</returns>
  159. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  160. public static AffineTransform AffineTransform(float3x3 rotationScale) { return new AffineTransform(rotationScale); }
  161. /// <summary>Returns an AffineTransform constructed from a float4x4 matrix.</summary>
  162. /// <param name="m">The float4x4 matrix.</param>
  163. /// <returns>The AffineTransform given a float4x4 matrix.</returns>
  164. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  165. public static AffineTransform AffineTransform(float4x4 m) { return new AffineTransform(m); }
  166. /// <summary>Returns an AffineTransform constructed from a float3x4 matrix.</summary>
  167. /// <param name="m">The float3x4 matrix.</param>
  168. /// <returns>The AffineTransform given a float3x4 matrix.</returns>
  169. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  170. public static AffineTransform AffineTransform(float3x4 m) { return new AffineTransform(m); }
  171. /// <summary>Returns an AffineTransform constructed from a RigidTransform.</summary>
  172. /// <param name="rigid">The RigidTransform.</param>
  173. /// <returns>The AffineTransform given a RigidTransform.</returns>
  174. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  175. public static AffineTransform AffineTransform(RigidTransform rigid) { return new AffineTransform (rigid); }
  176. /// <summary>Returns a float4x4 matrix constructed from an AffineTransform.</summary>
  177. /// <param name="transform">The AffineTransform.</param>
  178. /// <returns>The float4x4 matrix given an AffineTransform.</returns>
  179. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  180. public static float4x4 float4x4(AffineTransform transform) { return float4x4(float4(transform.rs.c0, 0f), float4(transform.rs.c1, 0f), float4(transform.rs.c2, 0f), float4(transform.t, 1f)); }
  181. /// <summary>Returns a float3x4 matrix constructed from an AffineTransform.</summary>
  182. /// <param name="transform">The AffineTransform.</param>
  183. /// <returns>The float3x4 matrix given an AffineTransform.</returns>
  184. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  185. public static float3x4 float3x4(AffineTransform transform) { return float3x4(transform.rs.c0, transform.rs.c1, transform.rs.c2, transform.t); }
  186. /// <summary>Returns the result of transforming the AffineTransform b by the AffineTransform a.</summary>
  187. /// <param name="a">The AffineTransform on the left.</param>
  188. /// <param name="b">The AffineTransform on the right.</param>
  189. /// <returns>The AffineTransform of a transforming b.</returns>
  190. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  191. public static AffineTransform mul(AffineTransform a, AffineTransform b)
  192. {
  193. return new AffineTransform(transform(a, b.t), mul(a.rs, b.rs));
  194. }
  195. /// <summary>Returns the result of transforming the AffineTransform b by a float3x3 matrix a.</summary>
  196. /// <param name="a">The float3x3 matrix on the left.</param>
  197. /// <param name="b">The AffineTransform on the right.</param>
  198. /// <returns>The AffineTransform of a transforming b.</returns>
  199. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  200. public static AffineTransform mul(float3x3 a, AffineTransform b)
  201. {
  202. return new AffineTransform(mul(a, b.t), mul(a, b.rs));
  203. }
  204. /// <summary>Returns the result of transforming the float3x3 b by an AffineTransform a.</summary>
  205. /// <param name="a">The AffineTransform on the left.</param>
  206. /// <param name="b">The float3x3 matrix on the right.</param>
  207. /// <returns>The AffineTransform of a transforming b.</returns>
  208. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  209. public static AffineTransform mul(AffineTransform a, float3x3 b)
  210. {
  211. return new AffineTransform(a.t, mul(b, a.rs));
  212. }
  213. /// <summary>Returns the result of transforming a float4 homogeneous coordinate by an AffineTransform.</summary>
  214. /// <param name="a">The AffineTransform.</param>
  215. /// <param name="pos">The position to be transformed.</param>
  216. /// <returns>The transformed position.</returns>
  217. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  218. public static float4 mul(AffineTransform a, float4 pos)
  219. {
  220. return float4(mul(a.rs, pos.xyz) + a.t * pos.w, pos.w);
  221. }
  222. /// <summary>Returns the result of rotating a float3 vector by an AffineTransform.</summary>
  223. /// <param name="a">The AffineTransform.</param>
  224. /// <param name="dir">The direction vector to rotate.</param>
  225. /// <returns>The rotated direction vector.</returns>
  226. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  227. public static float3 rotate(AffineTransform a, float3 dir)
  228. {
  229. return mul(a.rs, dir);
  230. }
  231. /// <summary>Returns the result of transforming a float3 point by an AffineTransform.</summary>
  232. /// <param name="a">The AffineTransform.</param>
  233. /// <param name="pos">The position to transform.</param>
  234. /// <returns>The transformed position.</returns>
  235. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  236. public static float3 transform(AffineTransform a, float3 pos)
  237. {
  238. return a.t + mul(a.rs, pos);
  239. }
  240. /// <summary>Returns the inverse of an AffineTransform.</summary>
  241. /// <param name="a">The AffineTransform to invert.</param>
  242. /// <returns>The inverse AffineTransform.</returns>
  243. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  244. public static AffineTransform inverse(AffineTransform a)
  245. {
  246. AffineTransform inv;
  247. inv.rs = pseudoinverse(a.rs);
  248. inv.t = mul(inv.rs, -a.t);
  249. return inv;
  250. }
  251. /// <summary>Decomposes the AffineTransform in translation, rotation and scale.</summary>
  252. /// <param name="a">The AffineTransform</param>
  253. /// <param name="translation">The decomposed translation vector of the AffineTransform.</param>
  254. /// <param name="rotation">The decomposed rotation quaternion of the AffineTransform.</param>
  255. /// <param name="scale">The decomposed scale of the AffineTransform.</param>
  256. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  257. public static void decompose(AffineTransform a, out float3 translation, out quaternion rotation, out float3 scale)
  258. {
  259. translation = a.t;
  260. rotation = math.rotation(a.rs);
  261. var sm = mul(float3x3(conjugate(rotation)), a.rs);
  262. scale = float3(sm.c0.x, sm.c1.y, sm.c2.z);
  263. }
  264. /// <summary>Returns a uint hash code of an AffineTransform.</summary>
  265. /// <param name="a">The AffineTransform to hash.</param>
  266. /// <returns>The hash code of the input AffineTransform.</returns>
  267. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  268. public static uint hash(AffineTransform a)
  269. {
  270. return hash(a.rs) + 0xC5C5394Bu * hash(a.t);
  271. }
  272. /// <summary>
  273. /// Returns a uint4 vector hash code of an AffineTransform.
  274. /// When multiple elements are to be hashes together, it can more efficient to calculate and combine wide hash
  275. /// that are only reduced to a narrow uint hash at the very end instead of at every step.
  276. /// </summary>
  277. /// <param name="a">The AffineTransform to hash.</param>
  278. /// <returns>The uint4 wide hash code.</returns>
  279. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  280. public static uint4 hashwide(AffineTransform a)
  281. {
  282. return hashwide(a.rs).xyzz + 0xC5C5394Bu * hashwide(a.t).xyzz;
  283. }
  284. }
  285. }