diff options
Diffstat (limited to 'v_windows/v/vlib/gg/m4/matrix.v')
-rw-r--r-- | v_windows/v/vlib/gg/m4/matrix.v | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/v_windows/v/vlib/gg/m4/matrix.v b/v_windows/v/vlib/gg/m4/matrix.v new file mode 100644 index 0000000..c839b9d --- /dev/null +++ b/v_windows/v/vlib/gg/m4/matrix.v @@ -0,0 +1,595 @@ +/********************************************************************** +* +* Simply vector/matrix utility +* +* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Use of this source code is governed by an MIT license +* that can be found in the LICENSE file. +* +* TODO: +**********************************************************************/ +module m4 + +import math + +pub union Mat4 { +pub mut: + e [16]f32 + f [4][4]f32 +} + +pub const precision = f32(10e-7) + +// default precision for the module + +/********************************************************************* +* +* Utility +* +*********************************************************************/ +// String representation of the matrix +pub fn (x Mat4) str() string { + unsafe { + return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|\n' + + '|${x.e[4]:-6.3},${x.e[5]:-6.3},${x.e[6]:-6.3},${x.e[7]:-6.3}|\n' + + '|${x.e[8]:-6.3},${x.e[9]:-6.3},${x.e[10]:-6.3},${x.e[11]:-6.3}|\n' + + '|${x.e[12]:-6.3},${x.e[13]:-6.3},${x.e[14]:-6.3},${x.e[15]:-6.3}|' + } +} + +// Remove all the raw zeros +[direct_array_access] +pub fn (a Mat4) clean() Mat4 { + unsafe { + x := Mat4{} + for c, value in a.e { + if f32_abs(value) < m4.precision { + x.e[c] = 0 + } else { + x.e[c] = value + } + } + return x + } +} + +// Sum all the elements of the matrix +pub fn (x Mat4) sum_all() f32 { + mut res := f32(0) + for v in unsafe { x.e } { + res += v + } + return res +} + +// Check if two matrix are equal using module precision +[direct_array_access] +pub fn (x Mat4) is_equal(y Mat4) bool { + unsafe { + for c, value in x.e { + if f32_abs(value - y.e[c]) > m4.precision { + return false + } + } + return true + } +} + +//------------------------------------- +// Set/Get values +//------------------------------------- +// Get an element of the matrix using [0..15] indexes, one dimension +pub fn (x Mat4) get_e(elem_index int) f32 { + unsafe { + return x.e[elem_index] + } +} + +// Get an element of the matrix using [0..3][0..3] indexes, two dimension +pub fn (x Mat4) get_f(index_col int, index_row int) f32 { + unsafe { + return x.e[(index_row << 2) + index_col] + } +} + +// Set an element of the matrix using [0..15] indexes, one dimension +pub fn (mut x Mat4) set_e(index int, value f32) { + unsafe { + x.e[index] = value + } +} + +// Set an element of the matrix using [0..3][0..3] indexes, two dimension +pub fn (mut x Mat4) set_f(index_col int, index_row int, value f32) { + unsafe { + x.e[(index_row << 2) + index_col] = value + } +} + +// Copy a matrix elements from another matrix +pub fn (mut x Mat4) copy(y Mat4) { + unsafe { + x.e = [ + y.e[0 ], y.e[1 ], y.e[2 ], y.e[3 ], + y.e[4 ], y.e[5 ], y.e[6 ], y.e[7 ], + y.e[8 ], y.e[9 ], y.e[10], y.e[11], + y.e[12], y.e[13], y.e[14], y.e[15], + ]! + } +} + +// Set the trace of the matrix using a vec4 +pub fn (mut x Mat4) set_trace(v3 Vec4) { + unsafe { + x.e[0 ] = v3.e[0] + x.e[5 ] = v3.e[1] + x.e[10] = v3.e[2] + x.e[15] = v3.e[3] + } +} + +// Get the trace of the matrix +pub fn (x Mat4) get_trace() Vec4 { + unsafe { + return Vec4{ e: [ x.e[0], x.e[5], x.e[10], x.e[15], ]! } + } +} + +// Set all the matrix elements to value +pub fn (mut x Mat4) set_f32(value f32) { + unsafe { + x.e = [ + value, value, value, value, + value, value, value, value, + value, value, value, value, + value, value, value, value, + ]! + } +} + +//------------------------------------- +// Rows/Column access +//------------------------------------- +// Set the row as the input vec4 +[direct_array_access] +[unsafe] +pub fn (mut x Mat4) set_row(row int, v3 Vec4) { + unsafe { + x.e[row * 4 + 0] = v3.e[0] + x.e[row * 4 + 1] = v3.e[1] + x.e[row * 4 + 2] = v3.e[2] + x.e[row * 4 + 3] = v3.e[3] + } +} + +// Get a row from a matrix +[direct_array_access] +[unsafe] +pub fn (x Mat4) get_row(row int) Vec4 { + unsafe { + return Vec4{ + e: [ + x.e[row * 4 + 0], + x.e[row * 4 + 1], + x.e[row * 4 + 2], + x.e[row * 4 + 3], + ]! + } + } +} + +// Set the column as the input vec4 +[direct_array_access] +[unsafe] +pub fn (mut x Mat4) set_col(col int, v3 Vec4) { + unsafe { + x.e[col] = v3.e[0] + x.e[col + 4 ] = v3.e[1] + x.e[col + 8 ] = v3.e[2] + x.e[col + 12] = v3.e[3] + } +} + +// Get a column from a matrix +[direct_array_access] +[unsafe] +pub fn (x Mat4) get_col(col int) Vec4 { + unsafe { + return Vec4{ + e: [ + x.e[col], + x.e[col + 4 ], + x.e[col + 8 ], + x.e[col + 12], + ]! + } + } +} + +// Swap two columns in the matrix +[direct_array_access] +[unsafe] +pub fn (mut x Mat4) swap_col(col1 int, col2 int) { + unsafe { + v0 := x.e[col1] + v1 := x.e[col1 + 4 ] + v2 := x.e[col1 + 8 ] + v3 := x.e[col1 + 12] + + x.e[col1] = x.e[col2] + x.e[col1 + 4 ] = x.e[col2 + 4 ] + x.e[col1 + 8 ] = x.e[col2 + 8 ] + x.e[col1 + 12] = x.e[col2 + 12] + + x.e[col2] = v0 + x.e[col2 + 4 ] = v1 + x.e[col2 + 8 ] = v2 + x.e[col2 + 12] = v3 + } +} + +// Swap two rows in the matrix +[direct_array_access] +[unsafe] +pub fn (mut x Mat4) swap_row(row1 int, row2 int) { + unsafe { + v0 := x.e[row1 * 4 + 0] + v1 := x.e[row1 * 4 + 1] + v2 := x.e[row1 * 4 + 2] + v3 := x.e[row1 * 4 + 3] + + x.e[row1 * 4 + 0] = x.e[row2 * 4 + 0] + x.e[row1 * 4 + 1] = x.e[row2 * 4 + 1] + x.e[row1 * 4 + 2] = x.e[row2 * 4 + 2] + x.e[row1 * 4 + 3] = x.e[row2 * 4 + 3] + + x.e[row2 * 4 + 0] = v0 + x.e[row2 * 4 + 1] = v1 + x.e[row2 * 4 + 2] = v2 + x.e[row2 * 4 + 3] = v3 + } +} + +//------------------------------------- +// Modify data +//------------------------------------- +// Transpose the matrix +pub fn (x Mat4) transpose() Mat4 { + unsafe { + return Mat4{ e: [ + x.e[0 ], x.e[4 ], x.e[8 ], x.e[12], + x.e[1 ], x.e[5 ], x.e[9 ], x.e[13], + x.e[2 ], x.e[6 ], x.e[10], x.e[14], + x.e[3 ], x.e[7 ], x.e[11], x.e[15], + ]! + } + } +} + +// Multiply the all the elements of the matrix by a scalar +pub fn (x Mat4) mul_scalar(s f32) Mat4 { + unsafe { + return Mat4{ e: [ + x.e[0 ] * s, x.e[1 ] * s, x.e[2 ] * s, x.e[3 ] * s, + x.e[4 ] * s, x.e[5 ] * s, x.e[6 ] * s, x.e[7 ] * s, + x.e[8 ] * s, x.e[9 ] * s, x.e[10] * s, x.e[11] * s, + x.e[12] * s, x.e[13] * s, x.e[14] * s, x.e[15] * s, + ]! + } + } +} + +/********************************************************************* +* +* Init/set +* +*********************************************************************/ +// Return a zero matrix +pub fn zero_m4() Mat4 { + return Mat4{ e: [ + f32(0), 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ]! + } +} + +// Return a unity matrix +pub fn unit_m4() Mat4 { + return Mat4{ e: [ + f32(1), 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ]! + } +} + +// Return a matrix initialized with value +pub fn set_m4(value f32) Mat4 { + return Mat4{ e: [ + value, value, value, value, + value, value, value, value, + value, value, value, value, + value, value, value, value, + ]! + } +} + +/********************************************************************* +* +* Math +* +*********************************************************************/ + +// Sum of matrix, operator + +pub fn (a Mat4) + (b Mat4) Mat4 { + unsafe { + return Mat4{ e: [ + a.e[0 ] + b.e[0 ], a.e[1 ] + b.e[1 ], a.e[2 ] + b.e[2 ], a.e[3 ] + b.e[3 ], + a.e[4 ] + b.e[4 ], a.e[5 ] + b.e[5 ], a.e[6 ] + b.e[6 ], a.e[7 ] + b.e[7 ], + a.e[8 ] + b.e[8 ], a.e[9 ] + b.e[9 ], a.e[10] + b.e[10], a.e[11] + b.e[11], + a.e[12] + b.e[12], a.e[13] + b.e[13], a.e[14] + b.e[14], a.e[15] + b.e[15], + ]! + } + } +} + +// Subtraction of matrix, operator - +pub fn (a Mat4) - (b Mat4) Mat4 { + unsafe { + return Mat4{ e: [ + a.e[0 ] - b.e[0 ], a.e[1 ] - b.e[1 ], a.e[2 ] - b.e[2 ], a.e[3 ] - b.e[3 ], + a.e[4 ] - b.e[4 ], a.e[5 ] - b.e[5 ], a.e[6 ] - b.e[6 ], a.e[7 ] - b.e[7 ], + a.e[8 ] - b.e[8 ], a.e[9 ] - b.e[9 ], a.e[10] - b.e[10], a.e[11] - b.e[11], + a.e[12] - b.e[12], a.e[13] - b.e[13], a.e[14] - b.e[14], a.e[15] - b.e[15], + ]! + } + } +} + +// Multiplication of matrix, operator * +pub fn (a Mat4) * (b Mat4) Mat4 { + unsafe { + return Mat4{ + e: [ + /* [0][0] */ a.f[0][0] * b.f[0][0] + a.f[0][1] * b.f[1][0] + a.f[0][2] * b.f[2][0] + a.f[0][3] * b.f[3][0] + /* [0][1] */, a.f[0][0] * b.f[0][1] + a.f[0][1] * b.f[1][1] + a.f[0][2] * b.f[2][1] + a.f[0][3] * b.f[3][1] + /* [0][2] */, a.f[0][0] * b.f[0][2] + a.f[0][1] * b.f[1][2] + a.f[0][2] * b.f[2][2] + a.f[0][3] * b.f[3][2] + /* [0][3] */, a.f[0][0] * b.f[0][3] + a.f[0][1] * b.f[1][3] + a.f[0][2] * b.f[2][3] + a.f[0][3] * b.f[3][3] + + /* [1][0] */, a.f[1][0] * b.f[0][0] + a.f[1][1] * b.f[1][0] + a.f[1][2] * b.f[2][0] + a.f[1][3] * b.f[3][0] + /* [1][1] */, a.f[1][0] * b.f[0][1] + a.f[1][1] * b.f[1][1] + a.f[1][2] * b.f[2][1] + a.f[1][3] * b.f[3][1] + /* [1][2] */, a.f[1][0] * b.f[0][2] + a.f[1][1] * b.f[1][2] + a.f[1][2] * b.f[2][2] + a.f[1][3] * b.f[3][2] + /* [1][3] */, a.f[1][0] * b.f[0][3] + a.f[1][1] * b.f[1][3] + a.f[1][2] * b.f[2][3] + a.f[1][3] * b.f[3][3] + + /* [2][0] */, a.f[2][0] * b.f[0][0] + a.f[2][1] * b.f[1][0] + a.f[2][2] * b.f[2][0] + a.f[2][3] * b.f[3][0] + /* [2][1] */, a.f[2][0] * b.f[0][1] + a.f[2][1] * b.f[1][1] + a.f[2][2] * b.f[2][1] + a.f[2][3] * b.f[3][1] + /* [2][2] */, a.f[2][0] * b.f[0][2] + a.f[2][1] * b.f[1][2] + a.f[2][2] * b.f[2][2] + a.f[2][3] * b.f[3][2] + /* [2][3] */, a.f[2][0] * b.f[0][3] + a.f[2][1] * b.f[1][3] + a.f[2][2] * b.f[2][3] + a.f[2][3] * b.f[3][3] + + /* [3][0] */, a.f[3][0] * b.f[0][0] + a.f[3][1] * b.f[1][0] + a.f[3][2] * b.f[2][0] + a.f[3][3] * b.f[3][0] + /* [3][1] */, a.f[3][0] * b.f[0][1] + a.f[3][1] * b.f[1][1] + a.f[3][2] * b.f[2][1] + a.f[3][3] * b.f[3][1] + /* [3][2] */, a.f[3][0] * b.f[0][2] + a.f[3][1] * b.f[1][2] + a.f[3][2] * b.f[2][2] + a.f[3][3] * b.f[3][2] + /* [3][3] */, a.f[3][0] * b.f[0][3] + a.f[3][1] * b.f[1][3] + a.f[3][2] * b.f[2][3] + a.f[3][3] * b.f[3][3], + ]! + } + } +} + +// Sum of matrix function +pub fn add(a Mat4, b Mat4) Mat4 { + unsafe { + return a + b + } +} + +// Subtraction of matrix function +pub fn sub(a Mat4, b Mat4) Mat4 { + unsafe { + return a - b + } +} + +// Multiplication of matrix function +pub fn mul(a Mat4, b Mat4) Mat4 { + unsafe { + return a * b + } +} + +// Multiply a Matrix by a vector +pub fn mul_vec(a Mat4, v Vec4) Vec4 { + unsafe { + return Vec4{ e: [ + a.e[0 ] * v.e[0] + a.e[1 ] * v.e[1] + a.e[2 ] * v.e[2] + a.e[3 ] * v.e[3], + a.e[4 ] * v.e[0] + a.e[5 ] * v.e[1] + a.e[6 ] * v.e[2] + a.e[7 ] * v.e[3], + a.e[8 ] * v.e[0] + a.e[9 ] * v.e[1] + a.e[10] * v.e[2] + a.e[11] * v.e[3], + a.e[12] * v.e[0] + a.e[13] * v.e[1] + a.e[14] * v.e[2] + a.e[15] * v.e[3], + ]! + } + } +} + +// Calculate the determinant of the Matrix +pub fn det(x Mat4) f32 { + unsafe { + mut t := [6]f32{} + x00 := x.f[0][0] + x10 := x.f[1][0] + x20 := x.f[2][0] + x30 := x.f[3][0] + x01 := x.f[0][1] + x11 := x.f[1][1] + x21 := x.f[2][1] + x31 := x.f[3][1] + x02 := x.f[0][2] + x12 := x.f[1][2] + x22 := x.f[2][2] + x32 := x.f[3][2] + x03 := x.f[0][3] + x13 := x.f[1][3] + x23 := x.f[2][3] + x33 := x.f[3][3] + + t[0] = x22 * x33 - x23 * x32 + t[1] = x12 * x33 - x13 * x32 + t[2] = x12 * x23 - x13 * x22 + t[3] = x02 * x33 - x03 * x32 + t[4] = x02 * x23 - x03 * x22 + t[5] = x02 * x13 - x03 * x12 + + return 0.0 + + x00 * (x11 * t[0] - x21 * t[1] + x31 * t[2]) - + x10 * (x01 * t[0] - x21 * t[3] + x31 * t[4]) + + x20 * (x01 * t[1] - x11 * t[3] + x31 * t[5]) - + x30 * (x01 * t[2] - x11 * t[4] + x21 * t[5]) + } +} + +// Calculate the inverse of the Matrix +pub fn (x Mat4) inverse() Mat4 { + unsafe { + mut t := [6]f32{} + mut det := f32(0) + + a := x.f[0][0] + b := x.f[1][0] + c := x.f[2][0] + d := x.f[3][0] + e := x.f[0][1] + f := x.f[1][1] + g := x.f[2][1] + h := x.f[3][1] + i := x.f[0][2] + j := x.f[1][2] + k := x.f[2][2] + l := x.f[3][2] + m := x.f[0][3] + n := x.f[1][3] + o := x.f[2][3] + p := x.f[3][3] + + t[0] = k * p - o * l + t[1] = j * p - n * l + t[2] = j * o - n * k + t[3] = i * p - m * l + t[4] = i * o - m * k + t[5] = i * n - m * j + + mut dest := Mat4{} + dest.f[0][0] = f * t[0] - g * t[1] + h * t[2] + dest.f[0][1] = -(e * t[0] - g * t[3] + h * t[4]) + dest.f[0][2] = e * t[1] - f * t[3] + h * t[5] + dest.f[0][3] = -(e * t[2] - f * t[4] + g * t[5]) + + dest.f[1][0] = -(b * t[0] - c * t[1] + d * t[2]) + dest.f[1][1] = a * t[0] - c * t[3] + d * t[4] + dest.f[1][2] = -(a * t[1] - b * t[3] + d * t[5]) + dest.f[1][3] = a * t[2] - b * t[4] + c * t[5] + + t[0] = g * p - o * h + t[1] = f * p - n * h + t[2] = f * o - n * g + t[3] = e * p - m * h + t[4] = e * o - m * g + t[5] = e * n - m * f + + dest.f[2][0] = b * t[0] - c * t[1] + d * t[2] + dest.f[2][1] = -(a * t[0] - c * t[3] + d * t[4]) + dest.f[2][2] = a * t[1] - b * t[3] + d * t[5] + dest.f[2][3] = -(a * t[2] - b * t[4] + c * t[5]) + + t[0] = g * l - k * h + t[1] = f * l - j * h + t[2] = f * k - j * g + t[3] = e * l - i * h + t[4] = e * k - i * g + t[5] = e * j - i * f + + dest.f[3][0] = -(b * t[0] - c * t[1] + d * t[2]) + dest.f[3][1] = a * t[0] - c * t[3] + d * t[4] + dest.f[3][2] = -(a * t[1] - b * t[3] + d * t[5]) + dest.f[3][3] = a * t[2] - b * t[4] + c * t[5] + + tmp := (a * dest.f[0][0] + b * dest.f[0][1] + c * dest.f[0][2] + d * dest.f[0][3]) + if tmp != 0 { + det = f32(1.0) / tmp + } + return dest.mul_scalar(det) + } +} + +/********************************************************************* +* +* Transformations +* +*********************************************************************/ + +// Get a rotation matrix using w as rotation axis vector, the angle is in radians +pub fn rotate(angle f32, w Vec4) Mat4 { + cs := f32(math.cos(angle)) + sn := f32(math.sin(angle)) + cv := f32(1.0) - cs + axis := w.normalize3() + unsafe { + ax := axis.e[0] + ay := axis.e[1] + az := axis.e[2] + + return Mat4{ e: [ + /* [0][0] */ (ax * ax * cv) + cs + /* [0][1] */, (ax * ay * cv) + az * sn + /* [0][2] */, (ax * az * cv) - ay * sn + /* [0][3] */, 0 + + /* [1][0] */, (ay * ax * cv) - az * sn + /* [1][1] */, (ay * ay * cv) + cs + /* [1][2] */, (ay * az * cv) + ax * sn + /* [1][3] */, 0 + + /* [2][0] */, (az * ax * cv) + ay * sn + /* [2][1] */, (az * ay * cv) - ax * sn + /* [2][2] */, (az * az * cv) + cs + /* [2][3] */, 0 + + /* [3][0] */, 0 + /* [3][1] */, 0 + /* [3][2] */, 0 + /* [3][3] */, 1, + ]! + } + } +} + +/********************************************************************* +* +* Graphic +* +*********************************************************************/ +// Get a matrix translated by a vector w +pub fn (x Mat4) translate(w Vec4) Mat4 { + unsafe { + return Mat4{ e: [ + x.e[0], x.e[1], x.e[2 ], x.e[3 ] , + x.e[4], x.e[5], x.e[6 ], x.e[7 ] , + x.e[8], x.e[9], x.e[10], x.e[11] , + x.e[12] + w.e[0], x.e[13] + w.e[1], x.e[14] + w.e[2], x.e[15], + ]! + } + } +} + +// Get a scale matrix, the scale vector is w, only xyz are evaluated. +pub fn scale(w Vec4) Mat4 { + unsafe { + return Mat4{ e: [ + w.e[0], 0, 0, 0, + 0, w.e[1], 0, 0, + 0, 0, w.e[2], 0, + 0, 0, 0, 1, + ]! + } + } +} |