matrix4.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  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. import "errors"
  6. // Matrix4 is 4x4 matrix organized internally as column matrix.
  7. type Matrix4 [16]float32
  8. // NewMatrix4 creates and returns a pointer to a new Matrix4
  9. // initialized as the identity matrix.
  10. func NewMatrix4() *Matrix4 {
  11. var mat Matrix4
  12. mat.Identity()
  13. return &mat
  14. }
  15. // Set sets all the elements of this matrix row by row starting at row1, column1,
  16. // row1, column2, row1, column3 and so forth.
  17. // Returns pointer to this updated Matrix.
  18. func (m *Matrix4) Set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 float32) *Matrix4 {
  19. m[0] = n11
  20. m[4] = n12
  21. m[8] = n13
  22. m[12] = n14
  23. m[1] = n21
  24. m[5] = n22
  25. m[9] = n23
  26. m[13] = n24
  27. m[2] = n31
  28. m[6] = n32
  29. m[10] = n33
  30. m[14] = n34
  31. m[3] = n41
  32. m[7] = n42
  33. m[11] = n43
  34. m[15] = n44
  35. return m
  36. }
  37. // Identity sets this matrix as the identity matrix.
  38. // Returns pointer to this updated matrix.
  39. func (m *Matrix4) Identity() *Matrix4 {
  40. m.Set(
  41. 1, 0, 0, 0,
  42. 0, 1, 0, 0,
  43. 0, 0, 1, 0,
  44. 0, 0, 0, 1,
  45. )
  46. return m
  47. }
  48. // Zero sets this matrix as the zero matrix.
  49. // Returns the pointer to this updated matrix.
  50. func (m *Matrix4) Zero() *Matrix4 {
  51. m.Set(
  52. 0, 0, 0, 0,
  53. 0, 0, 0, 0,
  54. 0, 0, 0, 0,
  55. 0, 0, 0, 0,
  56. )
  57. return m
  58. }
  59. // Copy copies src matrix into this one.
  60. // Returns pointer to this updated matrix.
  61. func (m *Matrix4) Copy(src *Matrix4) *Matrix4 {
  62. *m = *src
  63. return m
  64. }
  65. // CopyPosition copies the position elements of the src matrix into this one.
  66. // Returns pointer to this updated matrix.
  67. func (m *Matrix4) CopyPosition(src *Matrix4) *Matrix4 {
  68. m[12] = src[12]
  69. m[13] = src[13]
  70. m[14] = src[14]
  71. return m
  72. }
  73. // ExtractBasis updates the specified vectors with the basis vectors of this matrix.
  74. // Returns pointer to this unchanged matrix.
  75. func (m *Matrix4) ExtractBasis(xAxis, yAxis, zAxis *Vector3) *Matrix4 {
  76. xAxis.Set(m[0], m[1], m[2])
  77. yAxis.Set(m[4], m[5], m[6])
  78. zAxis.Set(m[8], m[9], m[10])
  79. return m
  80. }
  81. // MakeBasis sets this matrix basis vectors from the specified vectors.
  82. // Returns pointer to this updated matrix.
  83. func (m *Matrix4) MakeBasis(xAxis, yAxis, zAxis *Vector3) *Matrix4 {
  84. m.Set(
  85. xAxis.X, yAxis.X, zAxis.X, 0,
  86. xAxis.Y, yAxis.Y, zAxis.Y, 0,
  87. xAxis.Z, yAxis.Z, zAxis.Z, 0,
  88. 0, 0, 0, 1,
  89. )
  90. return m
  91. }
  92. // ExtractRotation set this matrix as rotation matrix from the src transformation matrix.
  93. // Returns pointer to this updated matrix.
  94. func (m *Matrix4) ExtractRotation(src *Matrix4) *Matrix4 {
  95. var v1 Vector3
  96. scaleX := 1 / v1.Set(src[0], src[1], src[2]).Length()
  97. scaleY := 1 / v1.Set(src[4], src[5], src[6]).Length()
  98. scaleZ := 1 / v1.Set(src[8], src[9], src[10]).Length()
  99. m[0] = src[0] * scaleX
  100. m[1] = src[1] * scaleX
  101. m[2] = src[2] * scaleX
  102. m[4] = src[4] * scaleY
  103. m[5] = src[5] * scaleY
  104. m[6] = src[6] * scaleY
  105. m[8] = src[8] * scaleZ
  106. m[9] = src[9] * scaleZ
  107. m[10] = src[10] * scaleZ
  108. return m
  109. }
  110. // MakeRotationFromEuler set this a matrix as a rotation matrix from the specified euler angles.
  111. // Returns pointer to this updated matrix.
  112. func (m *Matrix4) MakeRotationFromEuler(euler *Vector3) *Matrix4 {
  113. x := euler.X
  114. y := euler.Y
  115. z := euler.Z
  116. a := Cos(x)
  117. b := Sin(x)
  118. c := Cos(y)
  119. d := Sin(y)
  120. e := Cos(z)
  121. f := Sin(z)
  122. ae := a * e
  123. af := a * f
  124. be := b * e
  125. bf := b * f
  126. m[0] = c * e
  127. m[4] = -c * f
  128. m[8] = d
  129. m[1] = af + be*d
  130. m[5] = ae - bf*d
  131. m[9] = -b * c
  132. m[2] = bf - ae*d
  133. m[6] = be + af*d
  134. m[10] = a * c
  135. // Last column
  136. m[3] = 0
  137. m[7] = 0
  138. m[11] = 0
  139. // Bottom row
  140. m[12] = 0
  141. m[13] = 0
  142. m[14] = 0
  143. m[15] = 1
  144. return m
  145. }
  146. // MakeRotationFromQuaternion sets this matrix as a rotation matrix from the specified quaternion.
  147. // Returns pointer to this updated matrix.
  148. func (m *Matrix4) MakeRotationFromQuaternion(q *Quaternion) *Matrix4 {
  149. x := q.X
  150. y := q.Y
  151. z := q.Z
  152. w := q.W
  153. x2 := x + x
  154. y2 := y + y
  155. z2 := z + z
  156. xx := x * x2
  157. xy := x * y2
  158. xz := x * z2
  159. yy := y * y2
  160. yz := y * z2
  161. zz := z * z2
  162. wx := w * x2
  163. wy := w * y2
  164. wz := w * z2
  165. m[0] = 1 - (yy + zz)
  166. m[4] = xy - wz
  167. m[8] = xz + wy
  168. m[1] = xy + wz
  169. m[5] = 1 - (xx + zz)
  170. m[9] = yz - wx
  171. m[2] = xz - wy
  172. m[6] = yz + wx
  173. m[10] = 1 - (xx + yy)
  174. // last column
  175. m[3] = 0
  176. m[7] = 0
  177. m[11] = 0
  178. // bottom row
  179. m[12] = 0
  180. m[13] = 0
  181. m[14] = 0
  182. m[15] = 1
  183. return m
  184. }
  185. // LookAt sets this matrix as view transform matrix with origin at eye,
  186. // looking at target and using the up vector.
  187. // Returns pointer to this updated matrix.
  188. func (m *Matrix4) LookAt(eye, target, up *Vector3) *Matrix4 {
  189. var f Vector3
  190. var s Vector3
  191. var u Vector3
  192. f.SubVectors(target, eye).Normalize()
  193. s.CrossVectors(&f, up).Normalize()
  194. u.CrossVectors(&s, &f)
  195. m[0] = s.X
  196. m[1] = u.X
  197. m[2] = -f.X
  198. m[3] = 0.0
  199. m[4] = s.Y
  200. m[5] = u.Y
  201. m[6] = -f.Y
  202. m[7] = 0.0
  203. m[8] = s.Z
  204. m[9] = u.Z
  205. m[10] = -f.Z
  206. m[11] = 0.0
  207. m[12] = -s.Dot(eye)
  208. m[13] = -u.Dot(eye)
  209. m[14] = f.Dot(eye)
  210. m[15] = 1.0
  211. return m
  212. }
  213. // Multiply multiply this matrix by the other matrix
  214. // Returns pointer to this updated matrix.
  215. func (m *Matrix4) Multiply(other *Matrix4) *Matrix4 {
  216. return m.MultiplyMatrices(m, other)
  217. }
  218. // MultiplyMatrices multiply matrix a by b storing the result in this matrix.
  219. // Returns pointer to this updated matrix.
  220. func (m *Matrix4) MultiplyMatrices(a, b *Matrix4) *Matrix4 {
  221. a11 := a[0]
  222. a12 := a[4]
  223. a13 := a[8]
  224. a14 := a[12]
  225. a21 := a[1]
  226. a22 := a[5]
  227. a23 := a[9]
  228. a24 := a[13]
  229. a31 := a[2]
  230. a32 := a[6]
  231. a33 := a[10]
  232. a34 := a[14]
  233. a41 := a[3]
  234. a42 := a[7]
  235. a43 := a[11]
  236. a44 := a[15]
  237. b11 := b[0]
  238. b12 := b[4]
  239. b13 := b[8]
  240. b14 := b[12]
  241. b21 := b[1]
  242. b22 := b[5]
  243. b23 := b[9]
  244. b24 := b[13]
  245. b31 := b[2]
  246. b32 := b[6]
  247. b33 := b[10]
  248. b34 := b[14]
  249. b41 := b[3]
  250. b42 := b[7]
  251. b43 := b[11]
  252. b44 := b[15]
  253. m[0] = a11*b11 + a12*b21 + a13*b31 + a14*b41
  254. m[4] = a11*b12 + a12*b22 + a13*b32 + a14*b42
  255. m[8] = a11*b13 + a12*b23 + a13*b33 + a14*b43
  256. m[12] = a11*b14 + a12*b24 + a13*b34 + a14*b44
  257. m[1] = a21*b11 + a22*b21 + a23*b31 + a24*b41
  258. m[5] = a21*b12 + a22*b22 + a23*b32 + a24*b42
  259. m[9] = a21*b13 + a22*b23 + a23*b33 + a24*b43
  260. m[13] = a21*b14 + a22*b24 + a23*b34 + a24*b44
  261. m[2] = a31*b11 + a32*b21 + a33*b31 + a34*b41
  262. m[6] = a31*b12 + a32*b22 + a33*b32 + a34*b42
  263. m[10] = a31*b13 + a32*b23 + a33*b33 + a34*b43
  264. m[14] = a31*b14 + a32*b24 + a33*b34 + a34*b44
  265. m[3] = a41*b11 + a42*b21 + a43*b31 + a44*b41
  266. m[7] = a41*b12 + a42*b22 + a43*b32 + a44*b42
  267. m[11] = a41*b13 + a42*b23 + a43*b33 + a44*b43
  268. m[15] = a41*b14 + a42*b24 + a43*b34 + a44*b44
  269. return m
  270. }
  271. // MultiplyScalar multiplies each element of this matrix by the specified scalar.
  272. // Returns pointer to this updated matrix.
  273. func (m *Matrix4) MultiplyScalar(s float32) *Matrix4 {
  274. m[0] *= s
  275. m[4] *= s
  276. m[8] *= s
  277. m[12] *= s
  278. m[1] *= s
  279. m[5] *= s
  280. m[9] *= s
  281. m[13] *= s
  282. m[2] *= s
  283. m[6] *= s
  284. m[10] *= s
  285. m[14] *= s
  286. m[3] *= s
  287. m[7] *= s
  288. m[11] *= s
  289. m[15] *= s
  290. return m
  291. }
  292. // ApplyToVector3Array multiplies length vectors in the array starting at offset by this matrix.
  293. // Returns pointer to the updated array.
  294. // This matrix is unchanged.
  295. func (m *Matrix4) ApplyToVector3Array(array []float32, offset int, length int) []float32 {
  296. var v1 Vector3
  297. j := offset
  298. for i := 0; i < length; i += 3 {
  299. v1.X = array[j]
  300. v1.Y = array[j+1]
  301. v1.Z = array[j+2]
  302. v1.ApplyMatrix4(m)
  303. array[j] = v1.X
  304. array[j+1] = v1.Y
  305. array[j+2] = v1.Z
  306. j += 3
  307. }
  308. return array
  309. }
  310. // Determinant calculates and returns the determinat of this matrix.
  311. func (m *Matrix4) Determinant() float32 {
  312. n11 := m[0]
  313. n12 := m[4]
  314. n13 := m[8]
  315. n14 := m[12]
  316. n21 := m[1]
  317. n22 := m[5]
  318. n23 := m[9]
  319. n24 := m[13]
  320. n31 := m[2]
  321. n32 := m[6]
  322. n33 := m[10]
  323. n34 := m[14]
  324. n41 := m[3]
  325. n42 := m[7]
  326. n43 := m[11]
  327. n44 := m[15]
  328. return n41*(+n14*n23*n32-n13*n24*n32-n14*n22*n33+n12*n24*n33+n13*n22*n34-n12*n23*n34) +
  329. n42*(+n11*n23*n34-n11*n24*n33+n14*n21*n33-n13*n21*n34+n13*n24*n31-n14*n23*n31) +
  330. n43*(+n11*n24*n32-n11*n22*n34-n14*n21*n32+n12*n21*n34+n14*n22*n31-n12*n24*n31) +
  331. n44*(-n13*n22*n31-n11*n23*n32+n11*n22*n33+n13*n21*n32-n12*n21*n33+n12*n23*n31)
  332. }
  333. // Transpose transposes this matrix.
  334. // Returns pointer to this updated matrix.
  335. func (m *Matrix4) Transpose() *Matrix4 {
  336. var tmp float32
  337. tmp = m[1]
  338. m[1] = m[4]
  339. m[4] = tmp
  340. tmp = m[2]
  341. m[2] = m[8]
  342. m[8] = tmp
  343. tmp = m[6]
  344. m[6] = m[9]
  345. m[9] = tmp
  346. tmp = m[3]
  347. m[3] = m[12]
  348. m[12] = tmp
  349. tmp = m[7]
  350. m[7] = m[13]
  351. m[13] = tmp
  352. tmp = m[11]
  353. m[11] = m[14]
  354. m[14] = tmp
  355. return m
  356. }
  357. // SetPosition sets this transformation matrix position fields from the specified vector v.
  358. // Returns pointer to this updated matrix.
  359. func (m *Matrix4) SetPosition(v *Vector3) *Matrix4 {
  360. m[12] = v.X
  361. m[13] = v.Y
  362. m[14] = v.Z
  363. return m
  364. }
  365. // GetInverse sets this matrix to the inverse of the src matrix.
  366. // If the src matrix cannot be inverted returns error and
  367. // sets this matrix to the identity matrix.
  368. func (m *Matrix4) GetInverse(src *Matrix4) error {
  369. n11 := src[0]
  370. n12 := src[4]
  371. n13 := src[8]
  372. n14 := src[12]
  373. n21 := src[1]
  374. n22 := src[5]
  375. n23 := src[9]
  376. n24 := src[13]
  377. n31 := src[2]
  378. n32 := src[6]
  379. n33 := src[10]
  380. n34 := src[14]
  381. n41 := src[3]
  382. n42 := src[7]
  383. n43 := src[11]
  384. n44 := src[15]
  385. t11 := n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44
  386. t12 := n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44
  387. t13 := n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44
  388. t14 := n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34
  389. det := n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14
  390. if det == 0 {
  391. m.Identity()
  392. return errors.New("Cannot inverse matrix")
  393. }
  394. detInv := 1 / det
  395. m[0] = t11 * detInv
  396. m[1] = ( n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44 ) * detInv
  397. m[2] = ( n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44 ) * detInv
  398. m[3] = ( n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43 ) * detInv
  399. m[4] = t12 * detInv
  400. m[5] = ( n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44 ) * detInv
  401. m[6] = ( n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44 ) * detInv
  402. m[7] = ( n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43 ) * detInv
  403. m[8] = t13 * detInv
  404. m[9] = ( n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44 ) * detInv
  405. m[10] = ( n12*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44 ) * detInv
  406. m[11] = ( n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43 ) * detInv
  407. m[12] = t14 * detInv
  408. m[13] = ( n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34 ) * detInv
  409. m[14] = ( n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34 ) * detInv
  410. m[15] = ( n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33 ) * detInv
  411. return nil
  412. }
  413. // Scale multiply the first column of this matrix by the vector X component,
  414. // the second column by the vector Y component and the third column by
  415. // the vector Z component. The matrix fourth column is unchanged.
  416. // Returns pointer to this updated matrix.
  417. func (m *Matrix4) Scale(v *Vector3) *Matrix4 {
  418. m[0] *= v.X
  419. m[4] *= v.Y
  420. m[8] *= v.Z
  421. m[1] *= v.X
  422. m[5] *= v.Y
  423. m[9] *= v.Z
  424. m[2] *= v.X
  425. m[6] *= v.Y
  426. m[10] *= v.Z
  427. m[3] *= v.X
  428. m[7] *= v.Y
  429. m[11] *= v.Z
  430. return m
  431. }
  432. // GetMaxScaleOnAxis returns the maximum scale value of the 3 axes.
  433. func (m *Matrix4) GetMaxScaleOnAxis() float32 {
  434. scaleXSq := m[0]*m[0] + m[1]*m[1] + m[2]*m[2]
  435. scaleYSq := m[4]*m[4] + m[5]*m[5] + m[6]*m[6]
  436. scaleZSq := m[8]*m[8] + m[9]*m[9] + m[10]*m[10]
  437. return Sqrt(Max(scaleXSq, Max(scaleYSq, scaleZSq)))
  438. }
  439. // MakeTranslation sets this matrix to a translation matrix from the specified x, y and z values.
  440. // Returns pointer to this updated matrix.
  441. func (m *Matrix4) MakeTranslation(x, y, z float32) *Matrix4 {
  442. m.Set(
  443. 1, 0, 0, x,
  444. 0, 1, 0, y,
  445. 0, 0, 1, z,
  446. 0, 0, 0, 1,
  447. )
  448. return m
  449. }
  450. // MakeRotationX sets this matrix to a rotation matrix of angle theta around the X axis.
  451. // Returns pointer to this updated matrix.
  452. func (m *Matrix4) MakeRotationX(theta float32) *Matrix4 {
  453. c := Cos(theta)
  454. s := Sin(theta)
  455. m.Set(
  456. 1, 0, 0, 0,
  457. 0, c, -s, 0,
  458. 0, s, c, 0,
  459. 0, 0, 0, 1,
  460. )
  461. return m
  462. }
  463. // MakeRotationY sets this matrix to a rotation matrix of angle theta around the Y axis.
  464. // Returns pointer to this updated matrix.
  465. func (m *Matrix4) MakeRotationY(theta float32) *Matrix4 {
  466. c := Cos(theta)
  467. s := Sin(theta)
  468. m.Set(
  469. c, 0, s, 0,
  470. 0, 1, 0, 0,
  471. -s, 0, c, 0,
  472. 0, 0, 0, 1,
  473. )
  474. return m
  475. }
  476. // MakeRotationZ sets this matrix to a rotation matrix of angle theta around the Z axis.
  477. // Returns pointer to this updated matrix.
  478. func (m *Matrix4) MakeRotationZ(theta float32) *Matrix4 {
  479. c := Cos(theta)
  480. s := Sin(theta)
  481. m.Set(
  482. c, -s, 0, 0,
  483. s, c, 0, 0,
  484. 0, 0, 1, 0,
  485. 0, 0, 0, 1,
  486. )
  487. return m
  488. }
  489. // MakeRotationAxis sets this matrix to a rotation matrix of the specified angle around the specified axis.
  490. // Returns pointer to this updated matrix.
  491. func (m *Matrix4) MakeRotationAxis(axis *Vector3, angle float32) *Matrix4 {
  492. c := Cos(angle)
  493. s := Sin(angle)
  494. t := 1 - c
  495. x := axis.X
  496. y := axis.Y
  497. z := axis.Z
  498. tx := t * x
  499. ty := t * y
  500. m.Set(
  501. tx*x+c, tx*y-s*z, tx*z+s*y, 0,
  502. tx*y+s*z, ty*y+c, ty*z-s*x, 0,
  503. tx*z-s*y, ty*z+s*x, t*z*z+c, 0,
  504. 0, 0, 0, 1,
  505. )
  506. return m
  507. }
  508. // MakeScale sets this matrix to a scale transformation matrix using the specified x, y and z values.
  509. // Returns pointer to this updated matrix.
  510. func (m *Matrix4) MakeScale(x, y, z float32) *Matrix4 {
  511. m.Set(
  512. x, 0, 0, 0,
  513. 0, y, 0, 0,
  514. 0, 0, z, 0,
  515. 0, 0, 0, 1,
  516. )
  517. return m
  518. }
  519. // Compose sets this matrix to a transformation matrix for the specified position,
  520. // rotation specified by the quaternion and scale.
  521. // Returns pointer to this updated matrix.
  522. func (m *Matrix4) Compose(position *Vector3, quaternion *Quaternion, scale *Vector3) *Matrix4 {
  523. m.MakeRotationFromQuaternion(quaternion)
  524. m.Scale(scale)
  525. m.SetPosition(position)
  526. return m
  527. }
  528. // Decompose updates the position vector, quaternion and scale from this transformation matrix.
  529. // Returns pointer to this unchanged matrix.
  530. func (m *Matrix4) Decompose(position *Vector3, quaternion *Quaternion, scale *Vector3) *Matrix4 {
  531. var vector Vector3
  532. var matrix = *m
  533. sx := vector.Set(m[0], m[1], m[2]).Length()
  534. sy := vector.Set(m[4], m[5], m[6]).Length()
  535. sz := vector.Set(m[8], m[9], m[10]).Length()
  536. // If determinant is negative, we need to invert one scale
  537. det := m.Determinant()
  538. if det < 0 {
  539. sx = -sx
  540. }
  541. position.X = m[12]
  542. position.Y = m[13]
  543. position.Z = m[14]
  544. // Scale the rotation part
  545. invSX := 1 / sx
  546. invSY := 1 / sy
  547. invSZ := 1 / sz
  548. matrix[0] *= invSX
  549. matrix[1] *= invSX
  550. matrix[2] *= invSX
  551. matrix[4] *= invSY
  552. matrix[5] *= invSY
  553. matrix[6] *= invSY
  554. matrix[8] *= invSZ
  555. matrix[9] *= invSZ
  556. matrix[10] *= invSZ
  557. quaternion.SetFromRotationMatrix(&matrix)
  558. scale.X = sx
  559. scale.Y = sy
  560. scale.Z = sz
  561. return m
  562. }
  563. // MakeFrustum sets this matrix to a projection frustum matrix bounded by the specified planes.
  564. // Returns pointer to this updated matrix.
  565. func (m *Matrix4) MakeFrustum(left, right, bottom, top, near, far float32) *Matrix4 {
  566. m[0] = 2 * near / (right - left)
  567. m[1] = 0
  568. m[2] = 0
  569. m[3] = 0
  570. m[4] = 0
  571. m[5] = 2 * near / (top - bottom)
  572. m[6] = 0
  573. m[7] = 0
  574. m[8] = (right + left) / (right - left)
  575. m[9] = (top + bottom) / (top - bottom)
  576. m[10] = -(far + near) / (far - near)
  577. m[11] = -1
  578. m[12] = 0
  579. m[13] = 0
  580. m[14] = -(2 * far * near) / (far - near)
  581. m[15] = 0
  582. return m
  583. }
  584. // MakePerspective sets this matrix to a perspective projection matrix
  585. // with the specified field of view in degrees,
  586. // aspect ratio (width/height) and near and far planes.
  587. // Returns pointer to this updated matrix.
  588. func (m *Matrix4) MakePerspective(fov, aspect, near, far float32) *Matrix4 {
  589. ymax := near * Tan(DegToRad(fov*0.5))
  590. ymin := -ymax
  591. xmin := ymin * aspect
  592. xmax := ymax * aspect
  593. return m.MakeFrustum(xmin, xmax, ymin, ymax, near, far)
  594. }
  595. // MakeOrthographic sets this matrix to an orthographic projection matrix
  596. // bounded by the specified planes.
  597. // Returns pointer to this updated matrix.
  598. func (m *Matrix4) MakeOrthographic(left, right, top, bottom, near, far float32) *Matrix4 {
  599. w := right - left
  600. h := top - bottom
  601. p := far - near
  602. x := (right + left) / w
  603. y := (top + bottom) / h
  604. z := (far + near) / p
  605. m[0] = 2 / w
  606. m[4] = 0
  607. m[8] = 0
  608. m[12] = -x
  609. m[1] = 0
  610. m[5] = 2 / h
  611. m[9] = 0
  612. m[13] = -y
  613. m[2] = 0
  614. m[6] = 0
  615. m[10] = -2 / p
  616. m[14] = -z
  617. m[3] = 0
  618. m[7] = 0
  619. m[11] = 0
  620. m[15] = 1
  621. return m
  622. }
  623. // FromArray set this matrix elements from the array starting at offset.
  624. // Returns pointer to this updated matrix.
  625. func (m *Matrix4) FromArray(array []float32, offset int) *Matrix4 {
  626. copy(m[:], array[offset:offset+16])
  627. return m
  628. }
  629. // ToArray copies this matrix elements to array starting at offset.
  630. // Returns pointer to the updated array.
  631. func (m *Matrix4) ToArray(array []float32, offset int) []float32 {
  632. copy(array[offset:], m[:])
  633. return array
  634. }
  635. // Clone creates and returns a pointer to a copy of this matrix.
  636. func (m *Matrix4) Clone() *Matrix4 {
  637. var cloned Matrix4
  638. cloned = *m
  639. return &cloned
  640. }