2
0

Transform.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System;
  2. using System.Runtime.InteropServices;
  3. #if REAL_T_IS_DOUBLE
  4. using real_t = System.Double;
  5. #else
  6. using real_t = System.Single;
  7. #endif
  8. namespace Godot
  9. {
  10. [StructLayout(LayoutKind.Sequential)]
  11. public struct Transform : IEquatable<Transform>
  12. {
  13. public Basis basis;
  14. public Vector3 origin;
  15. public Transform AffineInverse()
  16. {
  17. Basis basisInv = basis.Inverse();
  18. return new Transform(basisInv, basisInv.Xform(-origin));
  19. }
  20. public Transform InterpolateWith(Transform transform, real_t c)
  21. {
  22. /* not sure if very "efficient" but good enough? */
  23. Vector3 sourceScale = basis.Scale;
  24. Quat sourceRotation = basis.RotationQuat();
  25. Vector3 sourceLocation = origin;
  26. Vector3 destinationScale = transform.basis.Scale;
  27. Quat destinationRotation = transform.basis.RotationQuat();
  28. Vector3 destinationLocation = transform.origin;
  29. var interpolated = new Transform();
  30. interpolated.basis.SetQuantScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c));
  31. interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, c);
  32. return interpolated;
  33. }
  34. public Transform Inverse()
  35. {
  36. Basis basisTr = basis.Transposed();
  37. return new Transform(basisTr, basisTr.Xform(-origin));
  38. }
  39. public Transform LookingAt(Vector3 target, Vector3 up)
  40. {
  41. var t = this;
  42. t.SetLookAt(origin, target, up);
  43. return t;
  44. }
  45. public Transform Orthonormalized()
  46. {
  47. return new Transform(basis.Orthonormalized(), origin);
  48. }
  49. public Transform Rotated(Vector3 axis, real_t phi)
  50. {
  51. return new Transform(new Basis(axis, phi), new Vector3()) * this;
  52. }
  53. public Transform Scaled(Vector3 scale)
  54. {
  55. return new Transform(basis.Scaled(scale), origin * scale);
  56. }
  57. public void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
  58. {
  59. // Make rotation matrix
  60. // Z vector
  61. Vector3 column2 = eye - target;
  62. column2.Normalize();
  63. Vector3 column1 = up;
  64. Vector3 column0 = column1.Cross(column2);
  65. // Recompute Y = Z cross X
  66. column1 = column2.Cross(column0);
  67. column0.Normalize();
  68. column1.Normalize();
  69. basis = new Basis(column0, column1, column2);
  70. origin = eye;
  71. }
  72. public Transform Translated(Vector3 ofs)
  73. {
  74. return new Transform(basis, new Vector3
  75. (
  76. origin[0] += basis.Row0.Dot(ofs),
  77. origin[1] += basis.Row1.Dot(ofs),
  78. origin[2] += basis.Row2.Dot(ofs)
  79. ));
  80. }
  81. public Vector3 Xform(Vector3 v)
  82. {
  83. return new Vector3
  84. (
  85. basis.Row0.Dot(v) + origin.x,
  86. basis.Row1.Dot(v) + origin.y,
  87. basis.Row2.Dot(v) + origin.z
  88. );
  89. }
  90. public Vector3 XformInv(Vector3 v)
  91. {
  92. Vector3 vInv = v - origin;
  93. return new Vector3
  94. (
  95. basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z,
  96. basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z,
  97. basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z
  98. );
  99. }
  100. // Constants
  101. private static readonly Transform _identity = new Transform(Basis.Identity, Vector3.Zero);
  102. private static readonly Transform _flipX = new Transform(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
  103. private static readonly Transform _flipY = new Transform(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
  104. private static readonly Transform _flipZ = new Transform(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
  105. public static Transform Identity { get { return _identity; } }
  106. public static Transform FlipX { get { return _flipX; } }
  107. public static Transform FlipY { get { return _flipY; } }
  108. public static Transform FlipZ { get { return _flipZ; } }
  109. // Constructors
  110. public Transform(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
  111. {
  112. basis = new Basis(column0, column1, column2);
  113. this.origin = origin;
  114. }
  115. public Transform(Quat quat, Vector3 origin)
  116. {
  117. basis = new Basis(quat);
  118. this.origin = origin;
  119. }
  120. public Transform(Basis basis, Vector3 origin)
  121. {
  122. this.basis = basis;
  123. this.origin = origin;
  124. }
  125. public static Transform operator *(Transform left, Transform right)
  126. {
  127. left.origin = left.Xform(right.origin);
  128. left.basis *= right.basis;
  129. return left;
  130. }
  131. public static bool operator ==(Transform left, Transform right)
  132. {
  133. return left.Equals(right);
  134. }
  135. public static bool operator !=(Transform left, Transform right)
  136. {
  137. return !left.Equals(right);
  138. }
  139. public override bool Equals(object obj)
  140. {
  141. if (obj is Transform)
  142. {
  143. return Equals((Transform)obj);
  144. }
  145. return false;
  146. }
  147. public bool Equals(Transform other)
  148. {
  149. return basis.Equals(other.basis) && origin.Equals(other.origin);
  150. }
  151. public override int GetHashCode()
  152. {
  153. return basis.GetHashCode() ^ origin.GetHashCode();
  154. }
  155. public override string ToString()
  156. {
  157. return String.Format("{0} - {1}", new object[]
  158. {
  159. basis.ToString(),
  160. origin.ToString()
  161. });
  162. }
  163. public string ToString(string format)
  164. {
  165. return String.Format("{0} - {1}", new object[]
  166. {
  167. basis.ToString(format),
  168. origin.ToString(format)
  169. });
  170. }
  171. }
  172. }