// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module glm import math /* #flag -lmyglm # f32* myglm_ortho(f32, f32, f32, f32); # f32* myglm_translate(f32, f32, f32); */ // # f32* myglm_rotate(f32 *m, f32 angle, f32, f32, f32); // # f32* myglm_perspective(f32, f32, f32, f32); // # f32* myglm_look_at(glm__Vec3, glm__Vec3, glm__Vec3); // # glm__Vec3 myglm_mult(glm__Vec3, glm__Vec3); // # glm__Vec3 myglm_cross(glm__Vec3, glm__Vec3); // # glm__Vec3 myglm_normalize(glm__Vec3); pub struct Mat4 { pub: data &f32 } struct Vec2 { x f32 y f32 } struct Vec3 { x f32 y f32 z f32 } pub fn vec3(x f32, y f32, z f32) Vec3 { res := Vec3{ x: x y: y z: z } return res } fn mat4(f &f32) Mat4 { res := Mat4{ data: f } return res } pub fn (v Vec3) str() string { return 'Vec3{ $v.x, $v.y, $v.z }' } pub fn (v Vec2) str() string { return 'Vec3{ $v.x, $v.y }' } pub fn (m Mat4) str() string { mut s := '[ ' for i in 0 .. 4 { if i != 0 { s += ' ' } for j in 0 .. 4 { val := unsafe {m.data[i * 4 + j]} s += '${val:5.2f} ' } if i != 3 { s += '\n' } } s += ']' return s } fn vec2(x int, y int) Vec2 { res := Vec2{ x: f32(x) y: f32(y) } return res } fn (a Vec3) add(b Vec3) Vec3 { res := Vec3{ x: a.x + b.x y: a.y + b.y z: a.z + b.z } return res } fn (a Vec3) sub(b Vec3) Vec3 { res := Vec3{ x: a.x - b.x y: a.y - b.y z: a.z - b.z } return res } // fn (a Vec3) mult(b Vec3) Vec3 { // # return myglm_mult(a,b); // } fn (a Vec3) mult_scalar(b f32) Vec3 { res := Vec3{ x: a.x * b y: a.y * b z: a.z * b } return res } fn (a Vec3) print() { x := a.x y := a.y z := a.z C.printf('vec3{%f,%f,%f}\n', x, y, z) // println('vec3{$x,$y,$z}') } /* fn rotate(m Mat4, angle f32, vec Vec3) Mat4 { // # t_mat4 m; // println('rotate done') # return glm__mat4( myglm_rotate(m.data, angle, vec.x,vec.y,vec.z) ); return Mat4{} } */ fn f32_calloc(n int) &f32 { return voidptr(vcalloc(n * int(sizeof(f32)))) } // fn translate(vec Vec3) *f32 { pub fn translate(m Mat4, v Vec3) Mat4 { // # return glm__mat4(myglm_translate(vec.x,vec.y,vec.z) ); a := m.data mut out := f32_calloc(16) x := v.x y := v.y z := v.z unsafe { a00 := a[0] a01 := a[1] a02 := a[2] a03 := a[3] a10 := a[4] a11 := a[5] a12 := a[6] a13 := a[7] a20 := a[8] a21 := a[9] a22 := a[10] a23 := a[11] out[0] = a00 out[1] = a01 out[2] = a02 out[3] = a03 out[4] = a10 out[5] = a11 out[6] = a12 out[7] = a13 out[8] = a20 out[9] = a21 out[10] = a22 out[11] = a23 out[12] = a00 * x + a10 * y + a20 * z + a[12] out[13] = a01 * x + a11 * y + a21 * z + a[13] out[14] = a02 * x + a12 * y + a22 * z + a[14] out[15] = a03 * x + a13 * y + a23 * z + a[15] } return mat4(out) } /* fn normalize(vec Vec3) Vec3 { # return myglm_normalize(vec); return Vec3{} } */ // https://github.com/g-truc/glm/blob/0ceb2b755fb155d593854aefe3e45d416ce153a4/glm/ext/matrix_clip_space.inl pub fn ortho(left f32, right f32, bottom f32, top f32) Mat4 { // println('glm ortho($left, $right, $bottom, $top)') // mat<4, 4, T, defaultp> Result(static_cast(1)); n := 16 mut res := f32_calloc(n) unsafe { res[0] = 2.0 / (right - left) res[5] = 2.0 / (top - bottom) res[10] = 1.0 res[12] = -(right + left) / (right - left) res[13] = -(top + bottom) / (top - bottom) res[15] = 1.0 } return mat4(res) } // https://github.com/g-truc/glm/blob/0ceb2b755fb155d593854aefe3e45d416ce153a4/glm/ext/matrix_clip_space.inl pub fn ortho_zo(left f32, right f32, bottom f32, top f32, zNear f32, zFar f32) Mat4 { // println('glm ortho($left, $right, $bottom, $top)') // mat<4, 4, T, defaultp> Result(static_cast(1)); n := 16 mut res := f32_calloc(n) unsafe { res[0] = 2.0 / (right - left) res[5] = 2.0 / (top - bottom) res[10] = 1.0 res[12] = -(right + left) / (right - left) res[13] = -(top + bottom) / (top - bottom) res[14] = -zNear / (zFar - zNear) res[15] = 1.0 } return mat4(res) } // fn scale(a *f32, v Vec3) *f32 { pub fn scale(m Mat4, v Vec3) Mat4 { a := m.data mut out := f32_calloc(16) x := v.x y := v.y z := v.z unsafe { out[0] = a[0] * v.x out[1] = a[1] * x out[2] = a[2] * x out[3] = a[3] * x out[4] = a[4] * y out[5] = a[5] * y out[6] = a[6] * y out[7] = a[7] * y out[8] = a[8] * z out[9] = a[9] * z out[10] = a[10] * z out[11] = a[11] * z out[12] = a[12] out[13] = a[13] out[14] = a[14] out[15] = a[15] } return mat4(out) } // multiplicates two matrices pub fn mult(a Mat4, b Mat4) Mat4 { mut out := f32_calloc(16) for i in 0 .. 4 { for r in 0 .. 4 { mut prod := f32(0) for c in 0 .. 4 { prod += unsafe {a.data[c * 4 + r] * b.data[i * 4 + c]} } unsafe { out[i * 4 + r] = prod } } } return mat4(out) } pub fn rotate(angle f32, axis Vec3, src Mat4) Mat4 { c := f32(math.cos(angle)) s := f32(math.sin(angle)) oneminusc := f32(1.0) - c xy := axis.x * axis.y yz := axis.y * axis.z xz := axis.x * axis.z xs := axis.x * s ys := axis.y * s zs := axis.z * s f00 := axis.x * axis.x * oneminusc + c f01 := xy * oneminusc + zs f02 := xz * oneminusc - ys f10 := xy * oneminusc - zs f11 := axis.y * axis.y * oneminusc + c f12 := yz * oneminusc + xs f20 := xz * oneminusc + ys f21 := yz * oneminusc - xs f22 := axis.z * axis.z * oneminusc + c data := src.data unsafe { t00 := data[0] * f00 + data[4] * f01 + data[8] * f02 t01 := data[1] * f00 + data[5] * f01 + data[9] * f02 t02 := data[2] * f00 + data[6] * f01 + data[10] * f02 t03 := data[3] * f00 + data[7] * f01 + data[11] * f02 t10 := data[0] * f10 + data[4] * f11 + data[8] * f12 t11 := data[1] * f10 + data[5] * f11 + data[9] * f12 t12 := data[2] * f10 + data[6] * f11 + data[10] * f12 t13 := data[3] * f10 + data[7] * f11 + data[11] * f12 mut dest := src.data dest[8] = data[0] * f20 + data[4] * f21 + data[8] * f22 dest[9] = data[1] * f20 + data[5] * f21 + data[9] * f22 dest[10] = data[2] * f20 + data[6] * f21 + data[10] * f22 dest[11] = data[3] * f20 + data[7] * f21 + data[11] * f22 dest[0] = t00 dest[1] = t01 dest[2] = t02 dest[3] = t03 dest[4] = t10 dest[5] = t11 dest[6] = t12 dest[7] = t13 return mat4(dest) } } // fn rotate_z(a *f32, rad f32) *f32 { pub fn rotate_z(m Mat4, rad f32) Mat4 { a := m.data mut out := f32_calloc(16) s := f32(math.sin(rad)) c := f32(math.cos(rad)) unsafe { a00 := a[0] a01 := a[1] a02 := a[2] a03 := a[3] a10 := a[4] a11 := a[5] a12 := a[6] a13 := a[7] out[8] = a[8] out[9] = a[9] out[10] = a[10] out[11] = a[11] out[12] = a[12] out[13] = a[13] out[14] = a[14] out[15] = a[15] // Perform axis-specific matrix multiplication out[0] = a00 * c + a10 * s out[1] = a01 * c + a11 * s out[2] = a02 * c + a12 * s out[3] = a03 * c + a13 * s out[4] = a10 * c - a00 * s out[5] = a11 * c - a01 * s out[6] = a12 * c - a02 * s out[7] = a13 * c - a03 * s } return mat4(out) } pub fn identity() Mat4 { // 1 0 0 0 // 0 1 0 0 // 0 0 1 0 // 0 0 0 1 n := 16 mut res := f32_calloc(int(sizeof(f32)) * n) unsafe { res[0] = 1 res[5] = 1 res[10] = 1 res[15] = 1 } return mat4(res) } // returns *f32 without allocation pub fn identity2(mut res &f32) { res[0] = 1 res[5] = 1 res[10] = 1 res[15] = 1 // # f32 f[16]={0};// for (int i =0;i<16;i++) // # printf("!!%d\n", f[0]); // # glm__identity2(&f); // # gl__Shader_set_mat4(shader, tos2("projection"), f) ; } pub fn identity3() []f32 { res := [f32(1.0), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] return res } // https://github.com/toji/gl-matrix/blob/1549cf21dfa14a2bc845993485343d519cf064fe/src/gl-matrix/mat4.js fn ortho_js(left f32, right f32, bottom f32, top f32) &f32 { // mynear := 1 // myfar := 1 lr := 1.0 / (left - right) bt := 1.0 / (bottom - top) nf := f32(1.0) / 1.0 // (mynear -myfar) unsafe { mut out := &f32(malloc(int(sizeof(f32) * 16))) out[0] = -2.0 * lr out[1] = 0 out[2] = 0 out[3] = 0 out[4] = 0 out[5] = -2.0 * bt out[6] = 0 out[7] = 0 out[8] = 0 out[9] = 0 out[10] = 2.0 * nf out[11] = 0 out[12] = (left + right) * lr out[13] = (top + bottom) * bt out[14] = 1.0 * nf // (far + near) * nf; out[15] = 1 return out } // f := 0.0 // return &f } // fn ortho_old(a, b, c, d f32) *f32 { // # return myglm_ortho(a,b,c,d); // } fn cross(a Vec3, b Vec3) Vec3 { // # return myglm_cross(a,b); return Vec3{} } /* fn perspective(degrees f32, ratio f32, a, b f32) Mat4 { // println('lang per degrees=$degrees ratio=$ratio a=$a b=$b') // # printf("lang pers degrees=%f ratio=%f a=%f b=%f\n", degrees, ratio, a,b); # return glm__mat4( myglm_perspective(degrees, ratio, a,b) ) ; return Mat4{} } fn look_at(eye, center, up Vec3) Mat4 { # return glm__mat4( myglm_look_at(eye, center, up) ) ; return Mat4{} } */