quaternion.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package math32
  5. // Quaternion is quaternion with X,Y,Z and W components.
  6. type Quaternion struct {
  7. X float32
  8. Y float32
  9. Z float32
  10. W float32
  11. }
  12. // NewQuaternion creates and returns a pointer to a new quaternion
  13. // from the specified components.
  14. func NewQuaternion(x, y, z, w float32) *Quaternion {
  15. return &Quaternion{
  16. X: x, Y: y, Z: z, W: w,
  17. }
  18. }
  19. // SetX sets this quaternion's X component.
  20. // Returns pointer to this updated quaternion.
  21. func (q *Quaternion) SetX(val float32) *Quaternion {
  22. q.X = val
  23. return q
  24. }
  25. // SetY sets this quaternion's Y component.
  26. // Returns pointer to this updated quaternion.
  27. func (q *Quaternion) SetY(val float32) *Quaternion {
  28. q.Y = val
  29. return q
  30. }
  31. // SetZ sets this quaternion's Z component.
  32. // Returns pointer to this updated quaternion.
  33. func (q *Quaternion) SetZ(val float32) *Quaternion {
  34. q.Z = val
  35. return q
  36. }
  37. // SetW sets this quaternion's W component.
  38. // Returns pointer to this updated quaternion.
  39. func (q *Quaternion) SetW(val float32) *Quaternion {
  40. q.W = val
  41. return q
  42. }
  43. // Set sets this quaternion's components.
  44. // Returns pointer to this updated quaternion.
  45. func (q *Quaternion) Set(x, y, z, w float32) *Quaternion {
  46. q.X = x
  47. q.Y = y
  48. q.Z = z
  49. q.W = w
  50. return q
  51. }
  52. // SetIdentity sets this quanternion to the identity quaternion.
  53. // Returns pointer to this updated quaternion.
  54. func (q *Quaternion) SetIdentity() *Quaternion {
  55. q.X = 0
  56. q.Y = 0
  57. q.Z = 0
  58. q.W = 1
  59. return q
  60. }
  61. // IsIdentity returns it this is an identity quaternion.
  62. func (q *Quaternion) IsIdentity() bool {
  63. if q.X == 0 && q.Y == 0 && q.Z == 0 && q.W == 1 {
  64. return true
  65. }
  66. return false
  67. }
  68. // Copy copies the other quaternion into this one.
  69. // Returns pointer to this updated quaternion.
  70. func (q *Quaternion) Copy(other *Quaternion) *Quaternion {
  71. *q = *other
  72. return q
  73. }
  74. // SetFromEuler sets this quaternion from the specified vector with
  75. // euler angles for each axis. It is assumed that the Euler angles
  76. // are in XYZ order.
  77. // Returns pointer to this updated quaternion.
  78. func (q *Quaternion) SetFromEuler(euler *Vector3) *Quaternion {
  79. c1 := Cos(euler.X / 2)
  80. c2 := Cos(euler.Y / 2)
  81. c3 := Cos(euler.Z / 2)
  82. s1 := Sin(euler.X / 2)
  83. s2 := Sin(euler.Y / 2)
  84. s3 := Sin(euler.Z / 2)
  85. q.X = s1*c2*c3 - c1*s2*s3
  86. q.Y = c1*s2*c3 + s1*c2*s3
  87. q.Z = c1*c2*s3 - s1*s2*c3
  88. q.W = c1*c2*c3 + s1*s2*s3
  89. return q
  90. }
  91. // SetFromAxisAngle sets this quaternion with the rotation
  92. // specified by the given axis and angle.
  93. // Returns pointer to this updated quaternion.
  94. func (q *Quaternion) SetFromAxisAngle(axis *Vector3, angle float32) *Quaternion {
  95. halfAngle := angle / 2
  96. s := Sin(halfAngle)
  97. q.X = axis.X * s
  98. q.Y = axis.Y * s
  99. q.Z = axis.Z * s
  100. q.W = Cos(halfAngle)
  101. return q
  102. }
  103. // SetFromRotationMatrix sets this quaternion from the specified rotation matrix.
  104. // Returns pointer to this updated quaternion.
  105. func (q *Quaternion) SetFromRotationMatrix(m *Matrix4) *Quaternion {
  106. m11 := m[0]
  107. m12 := m[4]
  108. m13 := m[8]
  109. m21 := m[1]
  110. m22 := m[5]
  111. m23 := m[9]
  112. m31 := m[2]
  113. m32 := m[6]
  114. m33 := m[10]
  115. trace := m11 + m22 + m33
  116. var s float32
  117. if trace > 0 {
  118. s = 0.5 / Sqrt(trace+1.0)
  119. q.W = 0.25 / s
  120. q.X = (m32 - m23) * s
  121. q.Y = (m13 - m31) * s
  122. q.Z = (m21 - m12) * s
  123. } else if m11 > m22 && m11 > m33 {
  124. s = 2.0 * Sqrt(1.0+m11-m22-m33)
  125. q.W = (m32 - m23) / s
  126. q.X = 0.25 * s
  127. q.Y = (m12 + m21) / s
  128. q.Z = (m13 + m31) / s
  129. } else if m22 > m33 {
  130. s = 2.0 * Sqrt(1.0+m22-m11-m33)
  131. q.W = (m13 - m31) / s
  132. q.X = (m12 + m21) / s
  133. q.Y = 0.25 * s
  134. q.Z = (m23 + m32) / s
  135. } else {
  136. s = 2.0 * Sqrt(1.0+m33-m11-m22)
  137. q.W = (m21 - m12) / s
  138. q.X = (m13 + m31) / s
  139. q.Y = (m23 + m32) / s
  140. q.Z = 0.25 * s
  141. }
  142. return q
  143. }
  144. // SetFromUnitVectors sets this quaternion to the rotation from vector vFrom to vTo.
  145. // The vectors must be normalized.
  146. // Returns pointer to this updated quaternion.
  147. func (q *Quaternion) SetFromUnitVectors(vFrom, vTo *Vector3) *Quaternion {
  148. var v1 Vector3
  149. var EPS float32 = 0.000001
  150. r := vFrom.Dot(vTo) + 1
  151. if r < EPS {
  152. r = 0
  153. if Abs(vFrom.X) > Abs(vFrom.Z) {
  154. v1.Set(-vFrom.Y, vFrom.X, 0)
  155. } else {
  156. v1.Set(0, -vFrom.Z, vFrom.Y)
  157. }
  158. } else {
  159. v1.CrossVectors(vFrom, vTo)
  160. }
  161. q.X = v1.X
  162. q.Y = v1.Y
  163. q.Z = v1.Z
  164. q.W = r
  165. q.Normalize()
  166. return q
  167. }
  168. // Inverse sets this quaternion to its inverse.
  169. // Returns pointer to this updated quaternion.
  170. func (q *Quaternion) Inverse() *Quaternion {
  171. q.Conjugate().Normalize()
  172. return q
  173. }
  174. // Conjugate sets this quaternion to its conjugate.
  175. // Returns pointer to this updated quaternion.
  176. func (q *Quaternion) Conjugate() *Quaternion {
  177. q.X *= -1
  178. q.Y *= -1
  179. q.Z *= -1
  180. return q
  181. }
  182. // Dot returns the dot products of this quaternion with other.
  183. func (q *Quaternion) Dot(other *Quaternion) float32 {
  184. return q.X*other.X + q.Y*other.Y + q.Z*other.Z + q.W*other.W
  185. }
  186. // LengthSq returns this quanternion's length squared
  187. func (q *Quaternion) lengthSq() float32 {
  188. return q.X*q.X + q.Y*q.Y + q.Z*q.Z + q.W*q.W
  189. }
  190. // Length returns the length of this quaternion
  191. func (q *Quaternion) Length() float32 {
  192. return Sqrt(q.X*q.X + q.Y*q.Y + q.Z*q.Z + q.W*q.W)
  193. }
  194. // Normalize normalizes this quaternion.
  195. // Returns pointer to this updated quaternion.
  196. func (q *Quaternion) Normalize() *Quaternion {
  197. l := q.Length()
  198. if l == 0 {
  199. q.X = 0
  200. q.Y = 0
  201. q.Z = 0
  202. q.W = 1
  203. } else {
  204. l = 1 / l
  205. q.X *= l
  206. q.Y *= l
  207. q.Z *= l
  208. q.W *= l
  209. }
  210. return q
  211. }
  212. // NormalizeFast approximates normalizing this quaternion.
  213. // Works best when the quaternion is already almost-normalized.
  214. // Returns pointer to this updated quaternion.
  215. func (q *Quaternion) NormalizeFast() *Quaternion {
  216. f := (3.0 - (q.X*q.X + q.Y*q.Y + q.Z*q.Z + q.W*q.W)) / 2.0
  217. if f == 0 {
  218. q.X = 0
  219. q.Y = 0
  220. q.Z = 0
  221. q.W = 1
  222. } else {
  223. q.X *= f
  224. q.Y *= f
  225. q.Z *= f
  226. q.W *= f
  227. }
  228. return q
  229. }
  230. // Multiply sets this quaternion to the multiplication of itself by other.
  231. // Returns pointer to this updated quaternion.
  232. func (q *Quaternion) Multiply(other *Quaternion) *Quaternion {
  233. return q.MultiplyQuaternions(q, other)
  234. }
  235. // MultiplyQuaternions set this quaternion to the multiplication of a by b.
  236. // Returns pointer to this updated quaternion.
  237. func (q *Quaternion) MultiplyQuaternions(a, b *Quaternion) *Quaternion {
  238. // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
  239. qax := a.X
  240. qay := a.Y
  241. qaz := a.Z
  242. qaw := a.W
  243. qbx := b.X
  244. qby := b.Y
  245. qbz := b.Z
  246. qbw := b.W
  247. q.X = qax*qbw + qaw*qbx + qay*qbz - qaz*qby
  248. q.Y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz
  249. q.Z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx
  250. q.W = qaw*qbw - qax*qbx - qay*qby - qaz*qbz
  251. return q
  252. }
  253. // Slerp sets this quaternion to another quaternion which is the spherically linear interpolation
  254. // from this quaternion to other using t.
  255. // Returns pointer to this updated quaternion.
  256. func (q *Quaternion) Slerp(other *Quaternion, t float32) *Quaternion {
  257. if t == 0 {
  258. return q
  259. }
  260. if t == 1 {
  261. return q.Copy(other)
  262. }
  263. x := q.X
  264. y := q.Y
  265. z := q.Z
  266. w := q.W
  267. cosHalfTheta := w*other.W + x*other.X + y*other.Y + z*other.Z
  268. if cosHalfTheta < 0 {
  269. q.W = -other.W
  270. q.X = -other.X
  271. q.Y = -other.Y
  272. q.Z = -other.Z
  273. cosHalfTheta = -cosHalfTheta
  274. } else {
  275. q.Copy(other)
  276. }
  277. if cosHalfTheta >= 1.0 {
  278. q.W = w
  279. q.X = x
  280. q.Y = y
  281. q.Z = z
  282. return q
  283. }
  284. sqrSinHalfTheta := 1.0 - cosHalfTheta*cosHalfTheta
  285. if sqrSinHalfTheta < 0.001 {
  286. s := 1 - t
  287. q.W = s*w + t*q.W
  288. q.X = s*x + t*q.X
  289. q.Y = s*y + t*q.Y
  290. q.Z = s*z + t*q.Z
  291. return q.Normalize()
  292. }
  293. sinHalfTheta := Sqrt(sqrSinHalfTheta)
  294. halfTheta := Atan2(sinHalfTheta, cosHalfTheta)
  295. ratioA := Sin((1-t)*halfTheta) / sinHalfTheta
  296. ratioB := Sin(t*halfTheta) / sinHalfTheta
  297. q.W = w*ratioA + q.W*ratioB
  298. q.X = x*ratioA + q.X*ratioB
  299. q.Y = y*ratioA + q.Y*ratioB
  300. q.Z = z*ratioA + q.Z*ratioB
  301. return q
  302. }
  303. // Equals returns if this quaternion is equal to other.
  304. func (q *Quaternion) Equals(other *Quaternion) bool {
  305. return (other.X == q.X) && (other.Y == q.Y) && (other.Z == q.Z) && (other.W == q.W)
  306. }
  307. // FromArray sets this quaternion's components from array starting at offset.
  308. // Returns pointer to this updated quaternion.
  309. func (q *Quaternion) FromArray(array []float32, offset int) *Quaternion {
  310. q.X = array[offset]
  311. q.Y = array[offset+1]
  312. q.Z = array[offset+2]
  313. q.W = array[offset+3]
  314. return q
  315. }
  316. // ToArray copies this quaternions's components to array starting at offset.
  317. // Returns pointer to this updated array.
  318. func (q *Quaternion) ToArray(array []float32, offset int) []float32 {
  319. array[offset] = q.X
  320. array[offset+1] = q.Y
  321. array[offset+2] = q.Z
  322. array[offset+3] = q.W
  323. return array
  324. }
  325. // Clone returns a copy of this quaternion
  326. func (q *Quaternion) Clone() *Quaternion {
  327. return NewQuaternion(q.X, q.Y, q.Z, q.W)
  328. }