changeset 1287:bc03dc1efe6e

fix: mat4 inverse
author sam <sam@basx.dev>
date Tue, 30 Jul 2024 16:13:31 +0700
parents ad9091fde244
children 8abddbe609ce
files semicongine/core/matrix.nim
diffstat 1 files changed, 41 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/core/matrix.nim	Tue Jul 30 14:48:30 2024 +0700
+++ b/semicongine/core/matrix.nim	Tue Jul 30 16:13:31 2024 +0700
@@ -392,11 +392,12 @@
 func scale*[T: TVec3](v: T): TMat4[float32] = scale(v[0], v[1], v[2])
 func rotate*(angle: float32, a: Vec3f): Mat4 =
   let
+    axis = a.normalized()
     cosa = cos(angle)
     sina = sin(angle)
-    x = a[0]
-    y = a[1]
-    z = a[2]
+    x = axis.x
+    y = axis.y
+    z = axis.z
   Mat4(data: [
     x * x * (1 - cosa) + cosa, y * x * (1 - cosa) - z * sina, z * x * (1 - cosa) + y * sina, 0'f32,
     x * y * (1 - cosa) + z * sina, y * y * (1 - cosa) + cosa, z * y * (1 - cosa) - x * sina, 0'f32,
@@ -412,20 +413,44 @@
   ])
 
 
-func inversed*(m: Mat4): Mat4 =
-  # TODO: is this correct?
-  var m3 = m.asMat3.transposed
-  m3[0, 0] = 1'f32 / m3[0, 0]
-  m3[1, 1] = 1'f32 / m3[1, 1]
-  m3[2, 2] = 1'f32 / m3[2, 2]
-  let col3 = -(m3 * m.col(3).xyz)
-  return Mat4(data: [
-        m3[0, 0], m3[0, 1], m3[0, 2], col3.x,
-        m3[1, 0], m3[1, 1], m3[1, 2], col3.y,
-        m3[2, 0], m3[2, 1], m3[2, 2], col3.z,
-               0, 0, 0, 1,
-  ])
+func inversed*(a: Mat4): Mat4 =
+  # from: https://stackoverflow.com/a/9614511
+  var
+    s0 = a[0, 0] * a[1, 1] - a[1, 0] * a[0, 1]
+    s1 = a[0, 0] * a[1, 2] - a[1, 0] * a[0, 2]
+    s2 = a[0, 0] * a[1, 3] - a[1, 0] * a[0, 3]
+    s3 = a[0, 1] * a[1, 2] - a[1, 1] * a[0, 2]
+    s4 = a[0, 1] * a[1, 3] - a[1, 1] * a[0, 3]
+    s5 = a[0, 2] * a[1, 3] - a[1, 2] * a[0, 3]
+    c5 = a[2, 2] * a[3, 3] - a[3, 2] * a[2, 3]
+    c4 = a[2, 1] * a[3, 3] - a[3, 1] * a[2, 3]
+    c3 = a[2, 1] * a[3, 2] - a[3, 1] * a[2, 2]
+    c2 = a[2, 0] * a[3, 3] - a[3, 0] * a[2, 3]
+    c1 = a[2, 0] * a[3, 2] - a[3, 0] * a[2, 2]
+    c0 = a[2, 0] * a[3, 1] - a[3, 0] * a[2, 1]
+
+  # Should check for 0 determinant
+  var invdet = 1.0 / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0);
 
+  result[0, 0] = ( a[1, 1] * c5 - a[1, 2] * c4 + a[1, 3] * c3) * invdet;
+  result[0, 1] = (-a[0, 1] * c5 + a[0, 2] * c4 - a[0, 3] * c3) * invdet;
+  result[0, 2] = ( a[3, 1] * s5 - a[3, 2] * s4 + a[3, 3] * s3) * invdet;
+  result[0, 3] = (-a[2, 1] * s5 + a[2, 2] * s4 - a[2, 3] * s3) * invdet;
+
+  result[1, 0] = (-a[1, 0] * c5 + a[1, 2] * c2 - a[1, 3] * c1) * invdet;
+  result[1, 1] = ( a[0, 0] * c5 - a[0, 2] * c2 + a[0, 3] * c1) * invdet;
+  result[1, 2] = (-a[3, 0] * s5 + a[3, 2] * s2 - a[3, 3] * s1) * invdet;
+  result[1, 3] = ( a[2, 0] * s5 - a[2, 2] * s2 + a[2, 3] * s1) * invdet;
+
+  result[2, 0] = ( a[1, 0] * c4 - a[1, 1] * c2 + a[1, 3] * c0) * invdet;
+  result[2, 1] = (-a[0, 0] * c4 + a[0, 1] * c2 - a[0, 3] * c0) * invdet;
+  result[2, 2] = ( a[3, 0] * s4 - a[3, 1] * s2 + a[3, 3] * s0) * invdet;
+  result[2, 3] = (-a[2, 0] * s4 + a[2, 1] * s2 - a[2, 3] * s0) * invdet;
+
+  result[3, 0] = (-a[1, 0] * c3 + a[1, 1] * c1 - a[1, 2] * c0) * invdet;
+  result[3, 1] = ( a[0, 0] * c3 - a[0, 1] * c1 + a[0, 2] * c0) * invdet;
+  result[3, 2] = (-a[3, 0] * s3 + a[3, 1] * s1 - a[3, 2] * s0) * invdet;
+  result[3, 3] = ( a[2, 0] * s3 - a[2, 1] * s1 + a[2, 2] * s0) * invdet;
 
 # call e.g. TMat32[int]().randomized() to get a random matrix
 template makeRandomMatrixInit(mattype: typedesc) =