From 270df580570c9c9ce389e6e0a545575ece7f3834 Mon Sep 17 00:00:00 2001 From: penguindark <57967770+penguindark@users.noreply.github.com> Date: Sat, 6 Mar 2021 11:14:43 +0100 Subject: [PATCH] gg.m4: fixed some bugs, added ortho projection (#9140) --- vlib/gg/m4/graphic.v | 51 +++++++++++++++++++++++++++----------------- vlib/gg/m4/m4_test.v | 25 ++++++++++++++++++---- vlib/gg/m4/matrix.v | 11 +++++++++- vlib/gg/m4/vector.v | 7 +++++- 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/vlib/gg/m4/graphic.v b/vlib/gg/m4/graphic.v index 05015ecafc..e134e80478 100644 --- a/vlib/gg/m4/graphic.v +++ b/vlib/gg/m4/graphic.v @@ -24,14 +24,40 @@ pub fn deg(grad f32) f32 { return (180.0 / math.pi) * grad } -// Calculate the perspective matrix +// calculate the Orthographic projection matrix +pub fn ortho(left f32, right f32, bottom f32, top f32, z_near f32, z_far f32) Mat4 { + rml := right - left + rpl := right + left + tmb := top - bottom + tpb := top + bottom + fmn := z_far - z_near + fpn := z_far + z_near + if fmn != 0 { + return Mat4{ e: [ + 2 / rml, 0 , 0, -(rpl / rml), + 0 , 2 / tmb, 0, -(tpb / tmb), + 0 , 0, 2 / fmn, -(fpn / fmn), + 0 , 0, 0, 1, + ]! + } + } + return Mat4{ e: [ + 2 / rml, 0 , 0, -(rpl / rml), + 0 , 2 / tmb, 0, -(tpb / tmb), + 0 , 0, 0, 0, + 0 , 0, 0, 1, + ]! + } +} + +// Calculate the perspective matrix using (fov:fov, ar:aspect_ratio ,n:near_pane, f:far_plane) as parameters pub fn perspective(fov f32, ar f32, n f32, f f32) Mat4 { ctan := f32(1.0 / math.tan(fov * (f32(math.pi) / 360.0))) // for the FOV we use 360 instead 180 return Mat4{ e: [ - ctan / ar, 0, 0, 0, - 0, ctan, 0, 0, - 0, 0, (n + f) / (n - f), -1.0, - 0, 0, (2.0 * n * f) / (n - f), 0, + ctan / ar, 0, 0, 0, + 0, ctan, 0, 0, + 0, 0, (n + f) / (n - f), -1.0, + 0, 0, (2.0 * n * f) / (n - f), 0, ]! } } @@ -66,21 +92,6 @@ pub fn look_at(eye Vec4, center Vec4, up Vec4) Mat4 { } } -/* -hmm_mat4 proj = HMM_Perspective(60.0f, w/h, 0.01f, 10.0f); - hmm_mat4 view = HMM_LookAt(HMM_Vec3(0.0f, 1.5f, 6.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f)); - hmm_mat4 view_proj = HMM_MultiplyMat4(proj, view); - //state.rx += 1.0f; state.ry += 2.0f; - - - hmm_mat4 rxm = HMM_Rotate(rx, HMM_Vec3(1.0f, 0.0f, 0.0f)); - hmm_mat4 rym = HMM_Rotate(ry, HMM_Vec3(0.0f, 1.0f, 0.0f)); - - hmm_mat4 model = HMM_MultiplyMat4(rxm, rym); - hmm_mat4 scale_mx = HMM_Scale(HMM_Vec3(scale, scale, scale)); - model = HMM_MultiplyMat4(model, scale_mx); - hmm_mat4 tmp_res = HMM_MultiplyMat4(view_proj, model); -*/ // Get the complete transformation matrix for GLSL demos pub fn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) Mat4 { diff --git a/vlib/gg/m4/m4_test.v b/vlib/gg/m4/m4_test.v index 02f27f97e4..6c1b04bfd8 100644 --- a/vlib/gg/m4/m4_test.v +++ b/vlib/gg/m4/m4_test.v @@ -185,6 +185,7 @@ fn test_det() { fn test_vec4() { // Test Vec4 // println("*** Vector4 ****") + assert m4.vec3(1,2,3) == m4.Vec4{[f32(1), 2, 3, 1]!} mut v := m4.Vec4{[f32(1), 2, 3, 4]!} assert v * v.inv() == 4 assert v.mul_scalar(1.0 / v.mod()).mod() == 1 @@ -195,13 +196,22 @@ fn test_vec4() { v = m4.Vec4{[f32(1), 2, 3, 0]!} assert m4.abs(v.normalize3().mod3() - 1) < m4.precision assert m4.abs(v.normalize3().mod() - 1) < m4.precision + // cross product // x y z // 1 2 3 ==> -3 6 -3 0 // 4 5 6 // println(m4.Vec4{[f32(1),2,3,2]!} % m4.Vec4{[f32(4),5,6,2]!}) assert m4.Vec4{[f32(1), 2, 3, 0]!} % m4.Vec4{[f32(4), 5, 6, 0]!} == m4.Vec4{[ f32(-3), 6, -3, 0, ]!} assert m4.Vec4{[f32(1), 2, 3, 13]!} % m4.Vec4{[f32(4), 5, 6, 11]!} == m4.Vec4{[ f32(-3), 6, -3, 0, ]!} - + // matrix * vector + a := m4.Mat4{ e: [ + f32(1),2,3,4 + 5,6,7,8 + 9,10,11,12 + 13,14,15,16 + ]! + } + assert m4.mul_vec(a, m4.Vec4{[f32(1), 2, 3, 4]!}) == m4.Vec4{[ f32(30), 70, 110,150, ]!} // Rotation // println("*** Rotation ****") rotx := m4.rotate(m4.rad(-90), m4.Vec4{ e: [f32(1.0), 0, 0, 0]! }).clean() @@ -211,8 +221,15 @@ fn test_vec4() { // println( roty ) // println( rotz ) // println( m4.mul_vec(rotx, m4.Vec4{e:[f32(0),0,1,0]!}).clean()) - assert m4.mul_vec(roty, m4.Vec4{ e: [f32(1.0), 0.0, 0, 0]! }).clean() == m4.Vec4{ e: [f32(0), 0.0, 1, 0]! } - assert m4.mul_vec(rotz, m4.Vec4{ e: [f32(1.0), 0.0, 0, 0]! }).clean() == m4.Vec4{ e: [f32(0), -1, 0, 0]! } - assert m4.mul_vec(rotx, m4.Vec4{ e: [f32(0), 0, 1, 0]! }).clean() == m4.Vec4{ e: [f32(0), 1, 0, 0]! } + assert m4.mul_vec(roty, m4.Vec4{ e: [f32(1.0), 0.0, 0, 0]! }).clean() == m4.Vec4{ e: [f32(0), 0.0, -1, 0]! } + assert m4.mul_vec(rotz, m4.Vec4{ e: [f32(1.0), 0.0, 0, 0]! }).clean() == m4.Vec4{ e: [f32(0), 1, 0, 0]! } + assert m4.mul_vec(rotx, m4.Vec4{ e: [f32(0), 0, 1, 0]! }).clean() == m4.Vec4{ e: [f32(0), -1, 0, 0]! } // println("****************") } + +fn test_proj() { + ort := m4.ortho(0,300,0,200,0,0) + assert m4.mul_vec(ort, m4.Vec4{[ f32(150), 100, 0, 1]!}) == m4.Vec4{[ f32(0), 0, 0, 1]!} + assert m4.mul_vec(ort, m4.Vec4{[ f32(0), 0, 0, 1]!}) == m4.Vec4{[ f32(-1), -1, 0, 1]!} + assert m4.mul_vec(ort, m4.Vec4{[ f32(300), 200, 0, 1]!}) == m4.Vec4{[ f32(1), 1, 0, 1]!} +} \ No newline at end of file diff --git a/vlib/gg/m4/matrix.v b/vlib/gg/m4/matrix.v index f4bfe8a4ae..7698ba268b 100644 --- a/vlib/gg/m4/matrix.v +++ b/vlib/gg/m4/matrix.v @@ -41,7 +41,7 @@ pub fn (x Mat4) str() string { 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}|\n' + '|${x.e[12]:-6.3},${x.e[13]:-6.3},${x.e[14]:-6.3},${x.e[15]:-6.3}|' } } @@ -410,6 +410,7 @@ pub fn mul(a Mat4, b Mat4) Mat4 { // 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[4] * v.e[1] + a.e[8] * v.e[2] + a.e[12] * v.e[3], a.e[1] * v.e[0] + a.e[5] * v.e[1] + a.e[9] * v.e[2] + a.e[13] * v.e[3], @@ -417,6 +418,14 @@ pub fn mul_vec(a Mat4, v Vec4) Vec4 { a.e[3] * v.e[0] + a.e[7] * v.e[1] + a.e[11] * v.e[2] + a.e[15] * v.e[3], ]! } +*/ + 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], + ]! + } } } diff --git a/vlib/gg/m4/vector.v b/vlib/gg/m4/vector.v index cf98ceb0f2..d8a55c6297 100644 --- a/vlib/gg/m4/vector.v +++ b/vlib/gg/m4/vector.v @@ -23,7 +23,12 @@ pub mut: * *********************************************************************/ pub fn (x Vec4) str() string { - return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|\n' + return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|' +} + +// create a Vec4 function passing x,y,z as parameteres. w is set to 1 +pub fn vec3(x f32, y f32, z f32) Vec4 { + return m4.Vec4{e:[x, y, z, 1]!} } // Remove all the raw zeros