quaternion.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  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. type Quaternion struct {
  6. x float32
  7. y float32
  8. z float32
  9. w float32
  10. }
  11. func NewQuaternion(x, y, z, w float32) *Quaternion {
  12. return &Quaternion{
  13. x: x, y: y, z: z, w: w,
  14. }
  15. }
  16. func (this *Quaternion) X() float32 {
  17. return this.x
  18. }
  19. func (this *Quaternion) SetX(val float32) *Quaternion {
  20. this.x = val
  21. return this
  22. }
  23. func (this *Quaternion) Y() float32 {
  24. return this.y
  25. }
  26. func (this *Quaternion) SetY(val float32) *Quaternion {
  27. this.y = val
  28. return this
  29. }
  30. func (this *Quaternion) Z() float32 {
  31. return this.z
  32. }
  33. func (this *Quaternion) SetZ(val float32) *Quaternion {
  34. this.z = val
  35. return this
  36. }
  37. func (this *Quaternion) W() float32 {
  38. return this.w
  39. }
  40. func (this *Quaternion) SetW(val float32) *Quaternion {
  41. this.w = val
  42. return this
  43. }
  44. func (this *Quaternion) Set(x, y, z, w float32) *Quaternion {
  45. this.x = x
  46. this.y = y
  47. this.z = z
  48. this.w = w
  49. return this
  50. }
  51. func (this *Quaternion) SetIdentity() *Quaternion {
  52. this.x = 0
  53. this.y = 0
  54. this.z = 0
  55. this.w = 1
  56. return this
  57. }
  58. func (q *Quaternion) IsIdentity() bool {
  59. if q.x == 0 && q.y == 0 && q.z == 0 && q.w == 1 {
  60. return true
  61. }
  62. return false
  63. }
  64. // Copy copies the specified quaternion into this one.
  65. func (this *Quaternion) Copy(quaternion *Quaternion) *Quaternion {
  66. *this = *quaternion
  67. return this
  68. }
  69. //func (this *Quaternion) SetFromEuler2(euler *Euler) *Quaternion {
  70. //
  71. // c1 := Cos(euler.X / 2)
  72. // c2 := Cos(euler.Y / 2)
  73. // c3 := Cos(euler.Z / 2)
  74. // s1 := Sin(euler.X / 2)
  75. // s2 := Sin(euler.Y / 2)
  76. // s3 := Sin(euler.Z / 2)
  77. //
  78. // if euler.Order == XYZ {
  79. // this.x = s1*c2*c3 + c1*s2*s3
  80. // this.y = c1*s2*c3 - s1*c2*s3
  81. // this.z = c1*c2*s3 + s1*s2*c3
  82. // this.w = c1*c2*c3 - s1*s2*s3
  83. // } else {
  84. // panic("Unsupported Euler Order")
  85. // }
  86. // return this
  87. //}
  88. // SetFromEuler sets this quaternion from the specified vector with
  89. // euler angles for each axis. It is assumed that the Euler angles
  90. // are in XYZ order.
  91. func (q *Quaternion) SetFromEuler(euler *Vector3) *Quaternion {
  92. c1 := Cos(euler.X / 2)
  93. c2 := Cos(euler.Y / 2)
  94. c3 := Cos(euler.Z / 2)
  95. s1 := Sin(euler.X / 2)
  96. s2 := Sin(euler.Y / 2)
  97. s3 := Sin(euler.Z / 2)
  98. q.x = s1*c2*c3 - c1*s2*s3
  99. q.y = c1*s2*c3 + s1*c2*s3
  100. q.z = c1*c2*s3 - s1*s2*c3
  101. q.w = c1*c2*c3 + s1*s2*s3
  102. return q
  103. }
  104. // SetFromAxisAngle sets this quaternion with the rotation
  105. // specified by the given axis and angle.
  106. func (q *Quaternion) SetFromAxisAngle(axis *Vector3, angle float32) *Quaternion {
  107. halfAngle := angle / 2
  108. s := Sin(halfAngle)
  109. q.x = axis.X * s
  110. q.y = axis.Y * s
  111. q.z = axis.Z * s
  112. q.w = Cos(halfAngle)
  113. return q
  114. }
  115. func (this *Quaternion) SetFromRotationMatrix(m *Matrix4) *Quaternion {
  116. m11 := m[0]
  117. m12 := m[4]
  118. m13 := m[8]
  119. m21 := m[1]
  120. m22 := m[5]
  121. m23 := m[9]
  122. m31 := m[2]
  123. m32 := m[6]
  124. m33 := m[10]
  125. trace := m11 + m22 + m33
  126. var s float32
  127. if trace > 0 {
  128. s = 0.5 / Sqrt(trace+1.0)
  129. this.w = 0.25 / s
  130. this.x = (m32 - m23) * s
  131. this.y = (m13 - m31) * s
  132. this.z = (m21 - m12) * s
  133. } else if m11 > m22 && m11 > m33 {
  134. s = 2.0 * Sqrt(1.0+m11-m22-m33)
  135. this.w = (m32 - m23) / s
  136. this.x = 0.25 * s
  137. this.y = (m12 + m21) / s
  138. this.z = (m13 + m31) / s
  139. } else if m22 > m33 {
  140. s = 2.0 * Sqrt(1.0+m22-m11-m33)
  141. this.w = (m13 - m31) / s
  142. this.x = (m12 + m21) / s
  143. this.y = 0.25 * s
  144. this.z = (m23 + m32) / s
  145. } else {
  146. s = 2.0 * Sqrt(1.0+m33-m11-m22)
  147. this.w = (m21 - m12) / s
  148. this.x = (m13 + m31) / s
  149. this.y = (m23 + m32) / s
  150. this.z = 0.25 * s
  151. }
  152. return this
  153. }
  154. func (this *Quaternion) SetFromUnitVectors(vFrom, vTo *Vector3) *Quaternion {
  155. var v1 Vector3
  156. var EPS float32 = 0.000001
  157. r := vFrom.Dot(vTo) + 1
  158. if r < EPS {
  159. r = 0
  160. if Abs(vFrom.X) > Abs(vFrom.Z) {
  161. v1.Set(-vFrom.Y, vFrom.X, 0)
  162. } else {
  163. v1.Set(0, -vFrom.Z, vFrom.Y)
  164. }
  165. } else {
  166. v1.CrossVectors(vFrom, vTo)
  167. }
  168. this.x = v1.X
  169. this.y = v1.Y
  170. this.z = v1.Z
  171. this.w = r
  172. this.Normalize()
  173. return this
  174. }
  175. func (q *Quaternion) Inverse() *Quaternion {
  176. q.Conjugate().Normalize()
  177. return q
  178. }
  179. func (this *Quaternion) Conjugate() *Quaternion {
  180. this.x *= -1
  181. this.y *= -1
  182. this.z *= -1
  183. return this
  184. }
  185. func (this *Quaternion) Dot(v *Quaternion) float32 {
  186. return this.x*v.x + this.y*v.y + this.z*v.z + this.w*v.w
  187. }
  188. func (this *Quaternion) lengthSq() float32 {
  189. return this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w
  190. }
  191. func (this *Quaternion) Length() float32 {
  192. return Sqrt(this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w)
  193. }
  194. func (this *Quaternion) Normalize() *Quaternion {
  195. l := this.Length()
  196. if l == 0 {
  197. this.x = 0
  198. this.y = 0
  199. this.z = 0
  200. this.w = 1
  201. } else {
  202. l = 1 / l
  203. this.x = this.x * l
  204. this.y = this.y * l
  205. this.z = this.z * l
  206. this.w = this.w * l
  207. }
  208. return this
  209. }
  210. func (this *Quaternion) Multiply(q *Quaternion) *Quaternion {
  211. return this.MultiplyQuaternions(this, q)
  212. }
  213. func (this *Quaternion) MultiplyQuaternions(a, b *Quaternion) *Quaternion {
  214. // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
  215. qax := a.x
  216. qay := a.y
  217. qaz := a.z
  218. qaw := a.w
  219. qbx := b.x
  220. qby := b.y
  221. qbz := b.z
  222. qbw := b.w
  223. this.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby
  224. this.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz
  225. this.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx
  226. this.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz
  227. return this
  228. }
  229. func (this *Quaternion) Slerp(qb *Quaternion, t float32) *Quaternion {
  230. if t == 0 {
  231. return this
  232. }
  233. if t == 1 {
  234. return this.Copy(qb)
  235. }
  236. x := this.x
  237. y := this.y
  238. z := this.z
  239. w := this.w
  240. cosHalfTheta := w*qb.w + x*qb.x + y*qb.y + z*qb.z
  241. if cosHalfTheta < 0 {
  242. this.w = -qb.w
  243. this.x = -qb.x
  244. this.y = -qb.y
  245. this.z = -qb.z
  246. cosHalfTheta = -cosHalfTheta
  247. } else {
  248. this.Copy(qb)
  249. }
  250. if cosHalfTheta >= 1.0 {
  251. this.w = w
  252. this.x = x
  253. this.y = y
  254. this.z = z
  255. return this
  256. }
  257. halfTheta := Acos(cosHalfTheta)
  258. sinHalfTheta := Sqrt(1.0 - cosHalfTheta + cosHalfTheta)
  259. if Abs(sinHalfTheta) < 0.001 {
  260. this.w = 0.5 * (w + this.w)
  261. this.x = 0.5 * (x + this.x)
  262. this.y = 0.5 * (y + this.y)
  263. this.z = 0.5 * (z + this.z)
  264. return this
  265. }
  266. ratioA := Sin((1-t)*halfTheta) / sinHalfTheta
  267. ratioB := Sin(t*halfTheta) / sinHalfTheta
  268. this.w = (w*ratioA + this.w*ratioB)
  269. this.x = (x*ratioA + this.x*ratioB)
  270. this.y = (y*ratioA + this.y*ratioB)
  271. this.z = (z*ratioA + this.z*ratioB)
  272. return this
  273. }
  274. func (this *Quaternion) Equals(quaternion *Quaternion) bool {
  275. return (quaternion.x == this.x) && (quaternion.y == this.y) && (quaternion.z == this.z) && (quaternion.w == this.w)
  276. }
  277. func (this *Quaternion) FromArray(array []float32, offset int) *Quaternion {
  278. this.x = array[offset]
  279. this.y = array[offset+1]
  280. this.z = array[offset+2]
  281. this.w = array[offset+3]
  282. return this
  283. }
  284. func (this *Quaternion) ToArray(array []float32, offset int) []float32 {
  285. if array == nil {
  286. array = make([]float32, 4)
  287. }
  288. array[offset] = this.x
  289. array[offset+1] = this.y
  290. array[offset+2] = this.z
  291. array[offset+3] = this.w
  292. return array
  293. }