/********************************************************************** * * 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 struct Vec4 { pub mut: e [4]f32 } /********************************************************************* * * Utility * *********************************************************************/ // str returns a `string` representation of `Vec4`. 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}|' } // 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 Vec4{ e: [x, y, z, 1]! } } // Remove all the raw zeros [direct_array_access] pub fn (a Vec4) clean() Vec4 { mut x := Vec4{} for c, value in a.e { if f32_abs(value) < precision { x.e[c] = 0 } else { x.e[c] = value } } return x } // Set all elements to value pub fn (mut x Vec4) copy(value f32) { x.e = [value, value, value, value]! } // Scale the vector using a scalar pub fn (x Vec4) mul_scalar(value f32) Vec4 { return Vec4{ e: [x.e[0] * value, x.e[1] * value, x.e[2] * value, x.e[3] * value]! } } // Reciprocal of the vector pub fn (x Vec4) inv() Vec4 { return Vec4{ e: [ if x.e[0] != 0 { 1.0 / x.e[0] } else { f32(0) }, if x.e[1] != 0 { 1.0 / x.e[1] } else { f32(0) }, if x.e[2] != 0 { 1.0 / x.e[2] } else { f32(0) }, if x.e[3] != 0 { 1.0 / x.e[3] } else { f32(0) }, ]! } } // Normalize the vector pub fn (x Vec4) normalize() Vec4 { m := x.mod() if m == 0 { return zero_v4() } return Vec4{ e: [ x.e[0] * (1 / m), x.e[1] * (1 / m), x.e[2] * (1 / m), x.e[3] * (1 / m), ]! } } // Normalize only xyz, w set to 0 pub fn (x Vec4) normalize3() Vec4 { m := x.mod3() if m == 0 { return zero_v4() } return Vec4{ e: [ x.e[0] * (1 / m), x.e[1] * (1 / m), x.e[2] * (1 / m), 0, ]! } } // Module of the vector xyzw pub fn (x Vec4) mod() f32 { return f32(math.sqrt(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2] + x.e[3] * x.e[3])) } // Module for 3d vector xyz, w ignored pub fn (x Vec4) mod3() f32 { return f32(math.sqrt(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2])) } /********************************************************************* * * Math * *********************************************************************/ // Return a zero vector pub fn zero_v4() Vec4 { return Vec4{ e: [ f32(0), 0, 0, 0, ]! } } // Return all one vector pub fn one_v4() Vec4 { return Vec4{ e: [ f32(1), 1, 1, 1, ]! } } // Return a blank vector pub fn blank_v4() Vec4 { return Vec4{ e: [ f32(0), 0, 0, 1, ]! } } // Set all elements to value pub fn set_v4(value f32) Vec4 { return Vec4{ e: [ value, value, value, value, ]! } } // Sum of all the elements pub fn (x Vec4) sum() f32 { return x.e[0] + x.e[1] + x.e[2] + x.e[3] } /********************************************************************* * * Operators * *********************************************************************/ // Addition pub fn (a Vec4) + (b Vec4) Vec4 { return Vec4{ 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], ]! } } // Subtraction pub fn (a Vec4) - (b Vec4) Vec4 { return Vec4{ 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], ]! } } // Dot product pub fn (a Vec4) * (b Vec4) f32 { return a.e[0] * b.e[0] + a.e[1] * b.e[1] + a.e[2] * b.e[2] + a.e[3] * b.e[3] } // Cross product pub fn (a Vec4) % (b Vec4) Vec4 { return Vec4{ e: [ (a.e[1] * b.e[2]) - (a.e[2] * b.e[1]), (a.e[2] * b.e[0]) - (a.e[0] * b.e[2]), (a.e[0] * b.e[1]) - (a.e[1] * b.e[0]), 0, ]! } } // Components multiplication pub fn (x Vec4) mul_vec4(y Vec4) Vec4 { return Vec4{ e: [ x.e[0] * y.e[0], x.e[1] * y.e[1], x.e[2] * y.e[2], x.e[3] * y.e[3], ]! } }