love-demo/_math.lua

1052 lines
26 KiB
Lua

local ffi = require 'ffi'
local sin = math.sin
local cos = math.cos
local sqrt = math.sqrt
local abs = math.abs
local mat4
local vec2
local vec3
local vec4
local scalar
local mat4_t
local vec2_t
local vec3_t
local vec4_t
ffi.cdef [[
typedef struct { float m00, m01, m02, m03;
float m10, m11, m12, m13;
float m20, m21, m22, m23;
float m30, m31, m32, m33; } mat4;
typedef struct { float x, y; } vec2;
typedef struct { float x, y, z; } vec3;
typedef struct { float x, y, z, w; } vec4;
]]
scalar = {
near_equal = function(s1, s2, epsilon)
local d = abs(s1 - s2)
return d <= epsilon
end,
convert_to_radians = function(degrees)
return degrees * (math.pi / 180.0)
end,
convert_to_degrees = function(radians)
return radians * (180.0 / math.pi)
end,
}
mat4 = {
__call = function(_t)
return mat4_t(0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0)
end,
load_table = function(t)
assert(#t == 16)
assert(t[1] ~= nil)
assert(t[2] ~= nil)
assert(t[3] ~= nil)
assert(t[4] ~= nil)
assert(t[5] ~= nil)
assert(t[6] ~= nil)
assert(t[7] ~= nil)
assert(t[8] ~= nil)
assert(t[9] ~= nil)
assert(t[10] ~= nil)
assert(t[11] ~= nil)
assert(t[12] ~= nil)
assert(t[13] ~= nil)
assert(t[14] ~= nil)
assert(t[15] ~= nil)
assert(t[16] ~= nil)
return mat4.set(t[1], t[2], t[3], t[4],
t[5], t[6], t[7], t[8],
t[9], t[10], t[11], t[12],
t[13], t[14], t[15], t[16])
end,
store_table = function(M)
return {
M.m[0], M.m[1], M.m[2], M.m[3],
M.m[4], M.m[5], M.m[6], M.m[7],
M.m[8], M.m[9], M.m[10], M.m[11],
M.m[12], M.m[13], M.m[14], M.m[15],
}
end,
set = function(m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m32, m33)
local M = mat4()
M.m00 = m00
M.m01 = m01
M.m02 = m02
M.m03 = m03
M.m10 = m10
M.m11 = m11
M.m12 = m12
M.m13 = m13
M.m20 = m20
M.m21 = m21
M.m22 = m22
M.m23 = m23
M.m30 = m30
M.m31 = m31
M.m32 = m32
M.m33 = m33
return M
end,
identity = function()
local M = mat4()
M.m00 = 1.0
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = 1.0
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = 1.0
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
--M.m32 = 0.0
M.m33 = 1.0
return M
end,
translation = function(x, y, z)
local M = mat4()
M.m00 = 1.0
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = 1.0
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = 1.0
--M.m23 = 0.0
M.m30 = x
M.m31 = y
M.m32 = z
M.m33 = 1.0
return M
end,
translation_from_vector = function(v)
return mat4.translation(v.x, v.y, v.z)
end,
scaling = function(x, y, z)
local M = mat4()
M.m00 = x
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = y
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = z
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
--M.m32 = 0.0
M.m33 = 1.0
return M
end,
scaling_from_vector = function(v)
return mat4.scaling(v.x, v.y, v.z)
end,
rotation_x = function(angle)
local sin_angle = sin(angle)
local cos_angle = cos(angle)
local M = mat4()
M.m00 = 1.0
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = cos_angle
M.m12 = sin_angle
--M.m13 = 0.0
--M.m20 = 0.0
M.m21 = -sin_angle
M.m22 = cos_angle
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
--M.m32 = 0.0
M.m33 = 1.0
return M
end,
rotation_y = function(angle)
local sin_angle = sin(angle)
local cos_angle = cos(angle)
local M = mat4()
M.m00 = cos_angle
--M.m01 = 0.0
M.m02 = -sin_angle
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = 1.0
--M.m12 = 0.0
--M.m13 = 0.0
M.m20 = sin_angle
--M.m21 = 0.0
M.m22 = cos_angle
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
--M.m32 = 0.0
M.m33 = 1.0
return M
end,
rotation_z = function(angle)
local sin_angle = sin(angle)
local cos_angle = cos(angle)
local M = mat4()
M.m00 = cos_angle
M.m01 = sin_angle
--M.m02 = 0.0
--M.m03 = 0.0
M.m10 = -sin_angle
M.m11 = cos_angle
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = 1.0
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
--M.m32 = 0.0
M.m33 = 1.0
return M
end,
transpose = function(M)
local MT = mat4()
--MT.m00 = M.m00
MT.m01 = M.m10
MT.m02 = M.m20
MT.m03 = M.m30
MT.m10 = M.m01
--MT.m11 = M.m11
MT.m12 = M.m21
MT.m13 = M.m31
MT.m20 = M.m02
MT.m21 = M.m12
--MT.m22 = M.m22
MT.m23 = M.m32
MT.m30 = M.m03
MT.m31 = M.m13
MT.m32 = M.m23
--MT.m33 = M.m33
return MT
end,
multiply = function(M1, M2)
local M = mat4()
local x = M1.m00
local y = M1.m01
local z = M1.m02
local w = M1.m03
M.m00 = (M2.m00 * x) + (M2.m10 * y) + (M2.m20 * z) + (M2.m30 * w)
M.m01 = (M2.m01 * x) + (M2.m11 * y) + (M2.m21 * z) + (M2.m31 * w)
M.m02 = (M2.m02 * x) + (M2.m12 * y) + (M2.m22 * z) + (M2.m32 * w)
M.m03 = (M2.m03 * x) + (M2.m13 * y) + (M2.m23 * z) + (M2.m33 * w)
x = M1.m10
y = M1.m11
z = M1.m12
w = M1.m13
M.m10 = (M2.m00 * x) + (M2.m10 * y) + (M2.m20 * z) + (M2.m30 * w)
M.m11 = (M2.m01 * x) + (M2.m11 * y) + (M2.m21 * z) + (M2.m31 * w)
M.m12 = (M2.m02 * x) + (M2.m12 * y) + (M2.m22 * z) + (M2.m32 * w)
M.m13 = (M2.m03 * x) + (M2.m13 * y) + (M2.m23 * z) + (M2.m33 * w)
x = M1.m20
y = M1.m21
z = M1.m22
w = M1.m23
M.m20 = (M2.m00 * x) + (M2.m10 * y) + (M2.m20 * z) + (M2.m30 * w)
M.m21 = (M2.m01 * x) + (M2.m11 * y) + (M2.m21 * z) + (M2.m31 * w)
M.m22 = (M2.m02 * x) + (M2.m12 * y) + (M2.m22 * z) + (M2.m32 * w)
M.m23 = (M2.m03 * x) + (M2.m13 * y) + (M2.m23 * z) + (M2.m33 * w)
x = M1.m30
y = M1.m31
z = M1.m32
w = M1.m33
M.m30 = (M2.m00 * x) + (M2.m10 * y) + (M2.m20 * z) + (M2.m30 * w)
M.m31 = (M2.m01 * x) + (M2.m11 * y) + (M2.m21 * z) + (M2.m31 * w)
M.m32 = (M2.m02 * x) + (M2.m12 * y) + (M2.m22 * z) + (M2.m32 * w)
M.m33 = (M2.m03 * x) + (M2.m13 * y) + (M2.m23 * z) + (M2.m33 * w)
return M
end,
rotation_normal = function(normal_axis, angle)
local sin_angle = sin(angle)
local cos_angle = cos(angle)
local c2 = vec3.replicate(1.0 - cos_angle)
local c1 = vec3.replicate(cos_angle)
local c0 = vec3.replicate(sin_angle)
local n0 = vec3(normal_axis.y, normal_axis.z, normal_axis.x)
local n1 = vec3(normal_axis.z, normal_axis.x, normal_axis.y)
local v0 = vec3.multiply(c2, n0)
v0 = vec3.multiply(v0, n1)
local r0 = vec3.multiply(c2, normal_axis)
r0 = vec3.multiply_add(r0, normal_axis, c1)
local r1 = vec3.multiply_add(c0, normal_axis, v0)
local r2 = vec3.negative_multiply_subtract(c0, normal_axis, v0)
local M = mat4()
M.m00 = r0.x
M.m01 = r1.z
M.m02 = r2.y
--M.m03 = 0.0
M.m10 = r2.z
M.m11 = r0.y
M.m12 = r1.x
--M.m13 = 0.0
M.m20 = r1.y
M.m21 = r2.x
M.m22 = r0.z
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
--M.m32 = 0.0
M.m33 = 1.0
return M
end,
rotation_axis = function(axis, angle)
assert(not vec3.equal(axis, vec3._zero))
assert(not vec3.isinfinite(axis))
local normal = vec3.normalize(axis)
return mat4.rotation_normal(normal, angle)
end,
look_to_lh = function(eye_position, eye_direction, up_direction)
assert(not vec3.equal(eye_direction, vec3._zero))
assert(not vec3.isinfinite(eye_direction))
assert(not vec3.equal(up_direction, vec3._zero))
assert(not vec3.isinfinite(up_direction))
local r2 = vec3.normalize(eye_direction)
local r0 = vec3.cross(up_direction, r2)
r0 = vec3.normalize(r0)
local r1 = vec3.cross(r2, r0)
local neg_eye_position = vec3.negate(eye_position)
local d0 = vec3.dot(r0, neg_eye_position)
local d1 = vec3.dot(r1, neg_eye_position)
local d2 = vec3.dot(r2, neg_eye_position)
local M = mat4()
M.m00 = r0.x
M.m10 = r0.y
M.m20 = r0.z
M.m30 = d0
M.m01 = r1.x
M.m11 = r1.y
M.m21 = r1.z
M.m31 = d1
M.m02 = r2.x
M.m12 = r2.y
M.m22 = r2.z
M.m32 = d2
--M.m03 = 0
--M.m13 = 0
--M.m23 = 0
M.m33 = 1
return M
end,
look_at_lh = function(eye_position, focus_position, up_direction)
local eye_direction = vec3.subtract(focus_position, eye_position)
return mat4.look_to_lh(eye_position, eye_direction, up_direction)
end,
look_at_rh = function(eye_position, focus_position, up_direction)
local neg_eye_direction = vec3.subtract(eye_position, focus_position)
return mat4.look_to_lh(eye_position, neg_eye_direction, up_direction)
end,
perspective_rh = function(view_width, view_height, near_z, far_z)
assert(near_z > 0.0 and far_z > 0.0)
assert(not scalar.near_equal(view_width, 0.0, 0.00001))
assert(not scalar.near_equal(view_height, 0.0, 0.00001))
assert(not scalar.near_equal(far_z, near_z, 0.00001))
local two_near_z = near_z + near_z;
local f_range = far_z / (near_z - far_z);
local M = mat4()
M.m00 = two_near_z / view_width
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = two_near_z / view_height
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = f_range
M.m23 = -1.0
--M.m30 = 0.0
--M.m31 = 0.0
M.m32 = f_range * near_z
--M.m33 = 0.0
return M
end,
perspective_fov_rh = function(fov_angle_y, aspect_ratio, near_z, far_z)
assert(near_z > 0.0 and far_z > 0.0)
assert(not scalar.near_equal(fov_angle_y, 0.0, 0.00001 * 2.0))
assert(not scalar.near_equal(aspect_ratio, 0.0, 0.00001))
assert(not scalar.near_equal(far_z, near_z, 0.00001))
local sin_fov = sin(fov_angle_y)
local cos_fov = cos(fov_angle_y)
local height = cos_fov / sin_fov
local width = height / aspect_ratio
local f_range = far_z / (near_z - far_z)
local M = mat4()
M.m00 = width
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = height
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = f_range
M.m23 = -1.0
--M.m30 = 0.0
--M.m31 = 0.0
M.m32 = f_range * near_z
--M.m33 = 0.0
return M
end,
orthographic_rh = function(view_width, view_height, near_z, far_z)
assert(not scalar.near_equal(view_width, 0.0, 0.00001))
assert(not scalar.near_equal(view_height, 0.0, 0.00001))
assert(not scalar.near_equal(far_z, near_z, 0.00001))
local f_range = 1.0 / (near_z - far_z)
local M = mat4()
M.m00 = 2.0 / view_width
--M.m01 = 0.0
--M.m02 = 0.0
--M.m03 = 0.0
--M.m10 = 0.0
M.m11 = 2.0 / view_height
--M.m12 = 0.0
--M.m13 = 0.0
--M.m20 = 0.0
--M.m21 = 0.0
M.m22 = f_range
--M.m23 = 0.0
--M.m30 = 0.0
--M.m31 = 0.0
M.m32 = f_range * near_z
M.m33 = 1.0
return M
end,
near_equal = function(M1, M2, epsilon)
local d00 = abs(M1.m00 - M2.m00)
local d01 = abs(M1.m01 - M2.m01)
local d02 = abs(M1.m02 - M2.m02)
local d03 = abs(M1.m03 - M2.m03)
local d10 = abs(M1.m10 - M2.m10)
local d11 = abs(M1.m11 - M2.m11)
local d12 = abs(M1.m12 - M2.m12)
local d13 = abs(M1.m13 - M2.m13)
local d20 = abs(M1.m20 - M2.m20)
local d21 = abs(M1.m21 - M2.m21)
local d22 = abs(M1.m22 - M2.m22)
local d23 = abs(M1.m23 - M2.m23)
local d30 = abs(M1.m30 - M2.m30)
local d31 = abs(M1.m31 - M2.m31)
local d32 = abs(M1.m32 - M2.m32)
local d33 = abs(M1.m33 - M2.m33)
return (
(d00 <= epsilon) and (d01 <= epsilon) and (d02 <= epsilon) and (d03 <= epsilon) and
(d10 <= epsilon) and (d11 <= epsilon) and (d12 <= epsilon) and (d13 <= epsilon) and
(d20 <= epsilon) and (d21 <= epsilon) and (d22 <= epsilon) and (d23 <= epsilon) and
(d30 <= epsilon) and (d31 <= epsilon) and (d32 <= epsilon) and (d33 <= epsilon)
)
end,
equal = function(M1, M2)
return (
M1.m00 == M2.m00 and
M1.m01 == M2.m01 and
M1.m02 == M2.m02 and
M1.m03 == M2.m03 and
M1.m10 == M2.m10 and
M1.m11 == M2.m11 and
M1.m12 == M2.m12 and
M1.m13 == M2.m13 and
M1.m20 == M2.m20 and
M1.m21 == M2.m21 and
M1.m22 == M2.m22 and
M1.m23 == M2.m23 and
M1.m30 == M2.m30 and
M1.m31 == M2.m31 and
M1.m32 == M2.m32 and
M1.m33 == M2.m33
)
end,
print = function(M)
for i = 0, 15 do
io.write(tostring(M.m[i]))
io.write(" ")
if i % 4 == 3 then
io.write("\n")
end
end
end
}
vec2 = {
__call = function(_, x, y)
return vec2_t(x, y)
end,
load_table = function(t)
assert(#t == 2)
assert(t[1] ~= nil)
assert(t[2] ~= nil)
return vec2(t[1], t[2])
end,
add = function(v1, v2)
local result = vec2(
v1.x + v2.x,
v1.y + v2.y
)
return result
end,
multiply = function(v1, v2)
local result = vec2(
v1.x * v2.x,
v1.y * v2.y
)
return result
end,
set_x = function(v, value)
return vec2(value, v.y)
end,
set_y = function(v, value)
return vec2(v.x, value)
end,
get_x = function(v)
return v.x
end,
get_y = function(v)
return v.y
end,
print = function(v)
print(tostring(v.x) .. " " .. tostring(v.y))
end,
}
vec3 = {
__call = function(_, x, y, z)
return vec3_t(x, y, z)
end,
load_table = function(t)
assert(#t == 3)
assert(t[1] ~= nil)
assert(t[2] ~= nil)
assert(t[3] ~= nil)
return vec3(t[1], t[2], t[3])
end,
set_x = function(v, value)
return vec3(value, v.y, v.z)
end,
set_y = function(v, value)
return vec3(v.x, value, v.z)
end,
set_z = function(v, value)
return vec3(v.x, v.y, value)
end,
replicate = function(value)
return vec3(value, value, value)
end,
dot = function(v1, v2)
local value = (
v1.x * v2.x +
v1.y * v2.y +
v1.z * v2.z
)
return value
end,
length_sq = function(v)
return vec3.dot(v, v)
end,
reciprocal_length = function(v)
local result
result = vec3.length_sq(v)
result = 1.0 / sqrt(result)
return result
end,
length = function(v)
local result
result = vec3.length_sq(v)
result = sqrt(result)
return result
end,
add = function(v1, v2)
local result = vec3(
v1.x + v2.x,
v1.y + v2.y,
v1.z + v2.z
)
return result
end,
subtract = function(v1, v2)
local result = vec3(
v1.x - v2.x,
v1.y - v2.y,
v1.z - v2.z
)
return result
end,
multiply = function(v1, v2)
local result = vec3(
v1.x * v2.x,
v1.y * v2.y,
v1.z * v2.z
)
return result
end,
multiply_scalar = function(v1, s)
local result = vec3(
v1.x * s,
v1.y * s,
v1.z * s
)
return result
end,
multiply_add = function(v1, v2, v3)
local result = vec3(
v1.x * v2.x + v3.x,
v1.y * v2.y + v3.y,
v1.z * v2.z + v3.z
)
return result
end,
negative_multiply_subtract = function(v1, v2, v3)
local result = vec3(
v3.x - (v1.x * v2.x),
v3.y - (v1.y * v2.y),
v3.z - (v1.z * v2.z)
)
return result
end,
normalize = function(v)
local length = vec3.reciprocal_length(v)
local result = vec3(
v.x * length,
v.y * length,
v.z * length
)
return result
end,
cross = function(v1, v2)
local result = vec3(
(v1.y * v2.z) - (v1.z * v2.y),
(v1.z * v2.x) - (v1.x * v2.z),
(v1.x * v2.y) - (v1.y * v2.x)
)
return result
end,
negate = function(v)
local result = vec3(
-v.x,
-v.y,
-v.z
)
return result
end,
transform = function(v, M)
local x = ((M.m00 * v.x)
+ (M.m10 * v.y)
+ (M.m20 * v.z)
+ (M.m30))
local y = ((M.m01 * v.x)
+ (M.m11 * v.y)
+ (M.m21 * v.z)
+ (M.m31))
local z = ((M.m02 * v.x)
+ (M.m12 * v.y)
+ (M.m22 * v.z)
+ (M.m32))
return vec4(x, y, z, 1)
end,
transform_normal = function(v, M)
local x = ((M.m00 * v.x)
+ (M.m10 * v.y)
+ (M.m20 * v.z))
local y = ((M.m01 * v.x)
+ (M.m11 * v.y)
+ (M.m21 * v.z))
local z = ((M.m02 * v.x)
+ (M.m12 * v.y)
+ (M.m22 * v.z))
return vec4(x, y, z, 0)
end,
equal = function(v1, v2)
return (
(v1.x == v2.x) and
(v1.y == v2.y) and
(v1.z == v2.z)
)
end,
near_equal = function(v1, v2, epsilon)
local dx = abs(v1.x - v2.x)
local dy = abs(v1.y - v2.y)
local dz = abs(v1.z - v2.z)
return (dx <= epsilon) and (dy <= epsilon) and (dz <= epsilon)
end,
isinfinite = function(v)
return (
(v.x == -math.huge or v.x == math.huge) or
(v.y == -math.huge or v.y == math.huge) or
(v.z == -math.huge or v.z == math.huge)
)
end,
print = function(v)
print(tostring(v.x) .. " " .. tostring(v.y) .. " " .. tostring(v.z))
end,
}
vec4 = {
__call = function(_, x, y, z, w)
return vec4_t(x, y, z, w)
end,
load_table = function(t)
assert(#t == 4)
assert(t[1] ~= nil)
assert(t[2] ~= nil)
assert(t[3] ~= nil)
assert(t[4] ~= nil)
return vec4(t[1], t[2], t[3], t[4])
end,
set_x = function(v, value)
return vec4(value, v.y, v.z, v.w)
end,
set_y = function(v, value)
return vec4(v.x, value, v.z, v.w)
end,
set_z = function(v, value)
return vec4(v.x, v.y, value, v.w)
end,
set_w = function(v, value)
return vec4(v.x, v.y, v.z, value)
end,
print = function(v)
print(tostring(v.x) .. " " .. tostring(v.y) .. " " .. tostring(v.z) .. " " .. tostring(v.w))
end,
}
----------------------------------------------------------------------
-- types
----------------------------------------------------------------------
setmetatable(scalar, scalar)
setmetatable(mat4, mat4)
setmetatable(vec2, vec2)
setmetatable(vec3, vec3)
setmetatable(vec4, vec4)
local mat4_metatable = {
__mul = mat4.multiply,
__index = {
data = function(v)
local data = love.data.newByteData(16 * 4)
local f = ffi.cast('float*', data:getFFIPointer())
ffi.copy(f, v, 16 * 4)
return data
end,
}
}
local vec2_metatable = {
__add = vec2.add,
__mul = vec2.multiply,
__index = {
data = function(v)
local data = love.data.newByteData(2 * 4)
local f = ffi.cast('float*', data:getFFIPointer())
ffi.copy(f, v, 2 * 4)
return data
end,
}
}
local vec3_metatable = {
__index = {
data = function(v)
local data = love.data.newByteData(3 * 4)
local f = ffi.cast('float*', data:getFFIPointer())
ffi.copy(f, v, 3 * 4)
return data
end,
}
}
local vec4_metatable = {
__index = {
data = function(v)
local data = love.data.newByteData(4 * 4)
local f = ffi.cast('float*', data:getFFIPointer())
ffi.copy(f, v, 4 * 4)
return data
end,
}
}
mat4_t = ffi.metatype("mat4", mat4_metatable)
vec2_t = ffi.metatype("vec2", vec2_metatable)
vec3_t = ffi.metatype("vec3", vec3_metatable)
vec4_t = ffi.metatype("vec4", vec4_metatable)
vec3._zero = vec3_t(0, 0, 0)
----------------------------------------------------------------------
-- tests
----------------------------------------------------------------------
assert(vec3.dot(vec3(1, 3, -5), vec3(4, -2, -1)) == 3)
assert(vec3.dot(vec3(1, 3, -5), vec3(1, 3, -5)) == 35)
assert(vec3.length_sq(vec3(1, 3, -5)) == 35)
assert(vec3.equal(vec3.multiply(vec3(1, 3, -5), vec3(2, 3, 4)), vec3(2, 9, -20)))
assert(vec3.near_equal(vec3.normalize(vec3(1, 3, -5)), vec3(0.16903, 0.50709, -0.84515), 0.0001))
assert(vec3.equal(vec3.cross(vec3(1, 2, 3), vec3(4, 5, 6)), vec3(-3, 6, -3)))
assert(vec3.equal(vec3.load_table({1, 2, 3}),
vec3(1, 2, 3)))
assert(mat4.near_equal(mat4.look_to_lh(vec3(1, 2, 3),
vec3(5, 6, 7),
vec3(9, 10, 11)),
mat4.set( 0.408249, 0.778499, 0.476731, 0.000000,
-0.816496, 0.077850, 0.572078, 0.000000,
0.408248, -0.622799, 0.667424, 0.000000,
-0.000001, 0.934199, -3.623158, 1.000000),
0.00001))
assert(mat4.near_equal(mat4.perspective_rh(2, 3, 4, 5),
mat4.set(4.000000, 0.000000, 0.000000, 0.000000,
0.000000, 2.666667, 0.000000, 0.000000,
0.000000, 0.000000, -5.000000, -1.000000,
0.000000, 0.000000, -20.000000, 0.000000),
0.00001))
assert(mat4.equal(mat4.multiply(mat4.set(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16),
mat4.set(17, 18, 19, 20,
21, 22, 23, 24,
25, 26, 27, 29,
30, 31, 32, 33)),
mat4.set(254, 264, 274, 287,
626, 652, 678, 711,
998, 1040, 1082, 1135,
1370, 1428, 1486, 1559)))
assert(mat4.equal(mat4.set(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16)
*
mat4.set(17, 18, 19, 20,
21, 22, 23, 24,
25, 26, 27, 29,
30, 31, 32, 33),
mat4.set(254, 264, 274, 287,
626, 652, 678, 711,
998, 1040, 1082, 1135,
1370, 1428, 1486, 1559)))
assert(mat4.equal(mat4.load_table({1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16}),
mat4.set(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16)))
assert(mat4.near_equal(mat4.rotation_normal(vec3(1, 0, 0), 33.0),
mat4.set(1.000000, 0.000000, 0.000000, 0.000000,
0.000000, -0.013275, 0.999912, 0.000000,
0.000000, -0.999912, -0.013275, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000),
0.00001))
assert(mat4.near_equal(mat4.rotation_normal(vec3(0, 1, 0), 78.0),
mat4.set(-0.857803, 0.000000, -0.513979, 0.000000,
0.000000, 1.000000, 0.000000, 0.000000,
0.513979, 0.000000, -0.857803, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000),
0.00001))
assert(mat4.near_equal(mat4.rotation_normal(vec3(0, 0, 1), 135.0),
mat4.set(-0.996087, 0.088377, 0.000000, 0.000000,
-0.088377, -0.996087, 0.000000, 0.000000,
0.000000, 0.000000, 1.000000, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000),
0.00001))
assert(mat4.near_equal(mat4.rotation_axis(vec3(1, 2, 3), 17.0),
mat4.set(-0.184080, -0.588667, 0.787138, 0.000000,
0.952999, 0.089169, 0.289554, 0.000000,
-0.240639, 0.803443, 0.544584, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000),
0.00001))
return {
scalar = scalar,
mat4 = mat4,
vec3 = vec3,
vec4 = vec4,
}