added unit tests
This commit is contained in:
parent
2c7a244aa2
commit
f8b83a8450
147
unit_tests/irrlicht_luanti_tests.lua
Normal file
147
unit_tests/irrlicht_luanti_tests.lua
Normal file
@ -0,0 +1,147 @@
|
||||
local cos = math.cos
|
||||
local sin = math.sin
|
||||
local m = mtul.math
|
||||
local mat4 = mtul.math.mat4
|
||||
|
||||
local pitch_ZY = function(a)
|
||||
local temp = mat4.new()
|
||||
temp[6] = cos(a)
|
||||
temp[7] = sin(a)
|
||||
temp[10] = -sin(a)
|
||||
temp[11] = cos(a)
|
||||
return temp
|
||||
end
|
||||
local pitch_ZY2 = function(a)
|
||||
local temp = mat4.new()
|
||||
temp[6] = cos(a)
|
||||
temp[7] = -sin(a)
|
||||
temp[10] = sin(a)
|
||||
temp[11] = cos(a)
|
||||
return temp
|
||||
end
|
||||
|
||||
local roll_XY = function(a)
|
||||
local temp = mat4.new()
|
||||
temp[1] = cos(a)
|
||||
temp[2] = sin(a)
|
||||
temp[5] = -sin(a)
|
||||
temp[6] = cos(a)
|
||||
return temp
|
||||
end
|
||||
local roll_XY2 = function(a)
|
||||
local temp = mat4.new()
|
||||
temp[1] = cos(a)
|
||||
temp[2] = -sin(a)
|
||||
temp[5] = sin(a)
|
||||
temp[6] = cos(a)
|
||||
return temp
|
||||
end
|
||||
local yaw_ZX = function(a)
|
||||
local temp = mat4.new()
|
||||
temp[1] = cos(a)
|
||||
temp[3] = -sin(a)
|
||||
temp[9] = sin(a)
|
||||
temp[11] = cos(a)
|
||||
return temp
|
||||
end
|
||||
local yaw_ZX2 = function(a)
|
||||
local temp = mat4.new()
|
||||
temp[1] = cos(a)
|
||||
temp[3] = sin(a)
|
||||
temp[9] = -sin(a)
|
||||
temp[11] = cos(a)
|
||||
return temp
|
||||
end
|
||||
local pitch_transforms = {
|
||||
pitch = pitch_ZY,
|
||||
pitch_cw = pitch_ZY2,
|
||||
}
|
||||
local roll_transforms = {
|
||||
roll = roll_XY,
|
||||
roll_cw = roll_XY2
|
||||
}
|
||||
local yaw_transforms = {
|
||||
yaw = yaw_ZX,
|
||||
yaw_cw = yaw_ZX2
|
||||
}
|
||||
local possible_orders = {
|
||||
{1,2,3},
|
||||
{1,3,2},
|
||||
|
||||
{2,3,1},
|
||||
{2,1,3},
|
||||
|
||||
{3,2,1},
|
||||
{3,1,2}
|
||||
}
|
||||
local matrix_tolerance = .00001
|
||||
local function check_matrix_equality(m1,m2)
|
||||
for i = 1,16 do
|
||||
if math.abs(m1[i]-m2[i]) > 0.001 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function make_funcs_human_readable(str)
|
||||
for i, v in pairs(pitch_transforms) do
|
||||
str=string.gsub(str, tostring(v), i)
|
||||
end
|
||||
for i, v in pairs(roll_transforms) do
|
||||
str=string.gsub(str, tostring(v), i )
|
||||
end
|
||||
for i, v in pairs(yaw_transforms) do
|
||||
str=string.gsub(str, tostring(v), i)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
function mtul.math.find_matrix_rotation_order(check_func)
|
||||
--x,y,z
|
||||
local euler = {(math.random()-.5)*math.pi*4, (math.random()-.5)*math.pi*4, (math.random()-.5)*math.pi*4}
|
||||
local output = check_func(mat4.new(), euler[1],euler[2],euler[3])
|
||||
local iter = 0
|
||||
local running_order
|
||||
for _, p_tf in pairs(pitch_transforms) do
|
||||
for _, y_tf in pairs(yaw_transforms) do
|
||||
for _, r_tf in pairs(roll_transforms) do
|
||||
--now that we have every combination, get every order of every combination. this is disusting by the way.
|
||||
for _, order in pairs(possible_orders) do
|
||||
iter = iter + 1
|
||||
--intrinsic order is pitch yaw roll for this check, meaning that 1 is assigned to pitch and so fourth.
|
||||
local matrices = {p_tf, y_tf, r_tf}
|
||||
local active_mat = mat4.new()
|
||||
running_order = nil
|
||||
for i=1,3 do
|
||||
local func = matrices[order[i]]
|
||||
running_order = (running_order and running_order .." * "..tostring(func)) or tostring(func)
|
||||
active_mat = active_mat*func(euler[order[i]])
|
||||
end
|
||||
--print("#"..iter, make_funcs_human_readable(running_order))
|
||||
if check_matrix_equality(output, active_mat) then
|
||||
print(make_funcs_human_readable(running_order))
|
||||
--return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return running_order
|
||||
end
|
||||
print("================== BEGINNING LUANTI AND IRRLICHT UNIT TESTs =======================")
|
||||
|
||||
local find_rot_order = mtul.math.find_matrix_rotation_order
|
||||
print("\n checking sanity of tests:")
|
||||
local _tempeuler = {(math.random()-.5)*math.pi*4, (math.random()-.5)*math.pi*4, (math.random()-.5)*math.pi*4}
|
||||
local _testmatrix = mtul.math.mat4.set_rot_zxy(mat4.new(), _tempeuler[1],_tempeuler[2],_tempeuler[3])
|
||||
print("matrix equality check func is sane:", check_matrix_equality(_testmatrix,_testmatrix))
|
||||
print("matrix equality check func tolerance:", matrix_tolerance)
|
||||
|
||||
print("\n Checking rotation orders. Rotation application order is in reverse, these are the literal matrix multiplication order. ")
|
||||
print("checking rotation matrix `set_rot_luanti_entity`")
|
||||
find_rot_order(mtul.math.mat4.set_rot_luanti_entity)
|
||||
print("checking `set_rot_irrlicht_bone`")
|
||||
find_rot_order(mtul.math.mat4.set_rot_irrlicht_bone)
|
||||
|
||||
print("================== ENDING LUANTI AND IRRLICHT UNIT TESTs =======================")
|
115
unit_tests/matrix_unit_test.lua
Normal file
115
unit_tests/matrix_unit_test.lua
Normal file
@ -0,0 +1,115 @@
|
||||
local mat4 = mtul.math.mat4
|
||||
local matrix_tolerance = .00001
|
||||
local function check_matrix_equality(m1,m2)
|
||||
for i = 1,16 do
|
||||
if math.abs(m1[i]-m2[i]) > 0.001 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local tau = math.pi*2
|
||||
local function santitize_angle(a)
|
||||
if a > tau then
|
||||
local co = math.floor(math.abs(a/tau))
|
||||
a = a-(co*tau)
|
||||
end
|
||||
if a < 0 then
|
||||
local co = math.ceil(math.abs(a/tau))
|
||||
a = a+(co*tau)
|
||||
end
|
||||
return a
|
||||
end
|
||||
local function equals(a,b)
|
||||
if math.abs(a-b) < .0001 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
local function santitize_angles_unpack(x,y,z)
|
||||
return santitize_angle(x), santitize_angle(y), santitize_angle(z)
|
||||
end
|
||||
--[[for i=1,10 do
|
||||
find_irr_order()
|
||||
end]]
|
||||
print("================== BEGINNING MATRIX UNIT TESTs =======================")
|
||||
local find_rot_order = mtul.math.find_matrix_rotation_order
|
||||
print("\n checking sanity of tests:")
|
||||
local _tempeuler = {(math.random()-.5)*math.pi*4, (math.random()-.5)*math.pi*4, (math.random()-.5)*math.pi*4}
|
||||
local _testmatrix = mtul.math.mat4.set_rot_zxy(mat4.new(), _tempeuler[1],_tempeuler[2],_tempeuler[3])
|
||||
print("matrix equality check func is sane:", check_matrix_equality(_testmatrix,_testmatrix))
|
||||
print("matrix equality check func tolerance:", matrix_tolerance)
|
||||
local ran_ang = math.random()*math.pi*2
|
||||
print("santitize_angle is sane:", equals(1.60947655802, santitize_angle(7.8926618652)), equals(ran_ang, santitize_angle(ran_ang-tau)))
|
||||
--print("checking irrlicht setRotationRadians")
|
||||
--print(find_rot_order(irrlicht_matrix_setRotationRadians).." iterations")
|
||||
|
||||
print("\n checking MTUL's luanti and irrlicht matrix rotation orders. Rotation application order is in reverse, these are the literal matrix multiplication order. ")
|
||||
print("checking rotation matrix `set_rot_luanti_entity`")
|
||||
find_rot_order(mtul.math.mat4.set_rot_luanti_entity)
|
||||
print("checking `set_rot_irrlicht_bone`")
|
||||
find_rot_order(mtul.math.mat4.set_rot_irrlicht_bone)
|
||||
|
||||
--[[print("check in euler out euler for minetest entitiy matrix rotations")
|
||||
local x,y,z =(math.random()-.5)*math.pi*4,(math.random()-.5)*math.pi*4,(math.random()-.5)*math.pi*4
|
||||
local new_mat = mat4.set_rot_luanti_entity(mat4.new(), x,y,z)
|
||||
print(santitize_angles_unpack(x,y,z))
|
||||
print(santitize_angles_unpack(new_mat:get_rot_luanti_entity()))]]
|
||||
|
||||
|
||||
--============================ ENTITY MATRICES =======================================
|
||||
|
||||
--random check to see if angles output correctly
|
||||
print("\n Checking to euler and out euler. Verifying that `matrix1` and `matrix2` matches in `euler->matrix1->euler?->matrix2` for the following euler conversions")
|
||||
|
||||
local x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
local new_mat = mat4.set_rot_luanti_entity(mat4.new(), x,y,z)
|
||||
local x2,y2,z2 = new_mat:get_rot_luanti_entity()
|
||||
print("luanti_entity (random angle) matrices are equivelant: ", check_matrix_equality(new_mat, mat4.set_rot_luanti_entity(mat4.new(), x2,y2,z2)))
|
||||
|
||||
--repeat for irrlicht bones
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
new_mat = mat4.set_rot_irrlicht_bone(mat4.identity(), x,y,z)
|
||||
x2,y2,z2 = new_mat:get_rot_irrlicht_bone()
|
||||
print("irrlicht_bone (random angle) matrices are equivelant: ", check_matrix_equality(new_mat, mat4.set_rot_irrlicht_bone(mat4.new(), x2,y2,z2)))
|
||||
|
||||
print("\n Checking edge cases for euler (where gimbal lock occours)")
|
||||
--check if edge cases work properly
|
||||
x,y,z = math.pi/2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
new_mat = mat4.set_rot_luanti_entity(mat4.identity(), x,y,z)
|
||||
x2,y2,z2 = new_mat:get_rot_luanti_entity()
|
||||
print("luanti_entity matrices are equivelant at `x=math.pi/2 or -math.pi/2:` ", check_matrix_equality(new_mat, mat4.set_rot_luanti_entity(mat4.new(), x2,y2,z2)))
|
||||
|
||||
--check if edge cases work properly
|
||||
x,y,z = math.random()*math.pi*2, math.pi/2, math.random()*math.pi*2
|
||||
new_mat = mat4.set_rot_irrlicht_bone(mat4.new(), x,y,z)
|
||||
x2,y2,z2 = new_mat:get_rot_irrlicht_bone()
|
||||
-- euler1->matrix->euler2; check euler1==euler2
|
||||
print("irrlicht_bone matrices are equivelant at `y=math.pi/2 or -math.pi/2`: ", check_matrix_equality(new_mat, mat4.set_rot_irrlicht_bone(mat4.new(), x2,y2,z2)))
|
||||
|
||||
print("\n==================== END OF MATRIX UNIT TESTs =============================")
|
||||
|
||||
|
||||
--[[local m00 = new_mat[1]
|
||||
local m12 = new_mat[7]
|
||||
local m22 =
|
||||
local m02 = , , new_mat[11]
|
||||
x = math.atan2(m12, m22);
|
||||
y = math.atan2(-m02, math.sqrt(1.0 - m02 * m02));
|
||||
z = math.atan2(m01, m00);
|
||||
print()]]
|
||||
|
||||
|
||||
|
||||
--[[local quat = mtul.math.quat
|
||||
print("\n comparing `euler to matrix` & `euler to quaternion` matrix outputs")
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
local mat1 = mat4.set_rot_zxy(mat4.new(), x,y,z)
|
||||
local new_quat = quat.new():from_euler_zxy(x,y,z)
|
||||
local mat2 = mat4.set_rot_from_quaternion(mat4.new(), new_quat)
|
||||
--local new_quat = mtul.quat.from_euler_
|
||||
print(mat1)
|
||||
print(mat2)
|
||||
print(check_matrix_equality(mat1,mat2))]]
|
124
unit_tests/quat_unit_test.lua
Normal file
124
unit_tests/quat_unit_test.lua
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
|
||||
local mat4 = mtul.math.mat4
|
||||
local quat = mtul.math.quat
|
||||
local vec3 = mtul.math.vec3
|
||||
local function check_matrix_equality(m1,m2)
|
||||
for i = 1,16 do
|
||||
if math.abs(m1[i]-m2[i]) > 0.001 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
print("================== BEGINNING QUATERNION UNIT TESTs =======================")
|
||||
|
||||
--print("\n comparing mul_vec3 and rotate_vec3 with random quat on forward facing unit dir")
|
||||
--[[local new_quat = mtul.math.quat.from_angle_axis((math.random()-.5)*math.pi*4, mtul.math.vec3.new(math.random(), math.random(), math.random())):normalize()
|
||||
local forward = vec3.new(0,0,1)
|
||||
print(new_quat:mul_vec3(forward))
|
||||
print(new_quat:rotate_vec3(forward))
|
||||
print("identity quat:")
|
||||
new_quat = quat.new(0,0,0,1)
|
||||
print(new_quat:mul_vec3(forward))
|
||||
print(new_quat:rotate_vec3(forward))]]
|
||||
|
||||
|
||||
|
||||
local new_quat = mtul.math.quat.from_angle_axis((math.random()-.5)*math.pi*4, mtul.math.vec3.new(math.random(), math.random(), math.random())):normalize()
|
||||
local to_mat_from_quat = mtul.math.mat4.from_quaternion(new_quat)
|
||||
local to_mat_from_axis_from_quat = mat4.from_angle_axis(new_quat:to_angle_axis())
|
||||
--should tell us that quat to matrix is working fine... trusting the original creators anyway...
|
||||
print("\n comparing `quat->matrix` to old `quat->angle_axis->matrix`. Matches:",
|
||||
check_matrix_equality(
|
||||
to_mat_from_quat, --new mthod which generates a matrix
|
||||
to_mat_from_axis_from_quat --old CPML method of from quaternion that just hooks through angle axis
|
||||
)
|
||||
)
|
||||
if not check_matrix_equality(to_mat_from_quat, to_mat_from_axis_from_quat) then
|
||||
print(to_mat_from_quat)
|
||||
print(to_mat_from_axis_from_quat)
|
||||
end
|
||||
|
||||
--double check (I dont trust the old method of converting to axis angle.)
|
||||
local x = vec3.new(1,0,0); x=new_quat:mul_vec3(x)
|
||||
local y = vec3.new(0,1,0); y=new_quat:mul_vec3(y)
|
||||
local z = vec3.new(0,0,1); z=new_quat:mul_vec3(z)
|
||||
local rotated_mat = mat4.new({ --this probably is confusing, each row her is a column.
|
||||
x.x, x.y, x.z, 0,
|
||||
y.x, y.y, y.z, 0,
|
||||
z.x, z.y, z.z, 0,
|
||||
0, 0, 0, 1
|
||||
})
|
||||
local equal = check_matrix_equality(rotated_mat, to_mat_from_quat)
|
||||
print("comparing matrix generated from rotating basis vectors to `quat->matrix`. Matches:", equal)
|
||||
if not equal then
|
||||
print(to_mat_from_quat)
|
||||
print(rotated_mat)
|
||||
end
|
||||
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
local matrix1 = mat4.set_rot_irrlicht_bone(mat4.identity(), x,y,z) --sample random matrix, what it is shouldn't matter as long as its special orthogonal (aka a rotation matrix)
|
||||
|
||||
new_quat = mat4.to_quaternion(matrix1) --this is the independent variable in which we are testing- wether this code works.
|
||||
local matrix2 = mat4.from_quaternion(new_quat)
|
||||
print("checking `matrix1=matrix2` in `matrix1->quaternion->matrix2`. Matches:", check_matrix_equality(matrix1, matrix2))
|
||||
if not check_matrix_equality(matrix1, matrix2) then
|
||||
print(matrix1)
|
||||
print(matrix2)
|
||||
end
|
||||
|
||||
print("\n checking euler functions")
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
matrix1 = mat4.set_rot_luanti_entity(mat4.identity(), x,y,z)
|
||||
new_quat = quat.from_matrix(matrix1)
|
||||
local x2,y2,z2 = new_quat:get_euler_luanti_entity()
|
||||
matrix2 = mat4.set_rot_luanti_entity(mat4.identity(), x2,y2,z2)
|
||||
|
||||
print("(quat->euler) checking `matrix1=matrix2` in `euler->matrix1->quat->euler->matrix2 (ZXY/luanti entity)`. Matrices match:", check_matrix_equality(matrix1, matrix2))
|
||||
if not check_matrix_equality(matrix1, matrix2) then
|
||||
print(matrix1)
|
||||
print(matrix2)
|
||||
print(x,y,z)
|
||||
print(x2,y2,z2)
|
||||
end
|
||||
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
matrix1 = mat4.set_rot_irrlicht_bone(mat4.identity(), x,y,z)
|
||||
new_quat = quat.from_matrix(matrix1)
|
||||
x2,y2,z2 = new_quat:get_euler_irrlicht_bone()
|
||||
matrix2 = mat4.set_rot_irrlicht_bone(mat4.identity(), x2,y2,z2)
|
||||
|
||||
print("(quat->euler) checking `matrix1=matrix2` in `euler->matrix1->quat->euler->matrix2 (XYZ/irrlicht bone)`. Matrices match:", check_matrix_equality(matrix1, matrix2))
|
||||
if not check_matrix_equality(matrix1, matrix2) then
|
||||
print(matrix1)
|
||||
print(matrix2)
|
||||
print(x,y,z)
|
||||
print(x2,y2,z2)
|
||||
end
|
||||
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
matrix2 = mat4.set_rot_luanti_entity(mat4.identity(), x,y,z)
|
||||
new_quat = quat.from_euler_luanti_entity(x,y,z)
|
||||
matrix1 = mat4.from_quaternion(new_quat)
|
||||
print("(euler->quat) checking `matrix1=matrix2` in `euler->quat->matrix1, euler->matrix2 (ZXY/luanti entity)`, Matches:", check_matrix_equality(matrix1, matrix2))
|
||||
if not check_matrix_equality(matrix1, matrix2) then
|
||||
print(x,y,z)
|
||||
print(matrix1)
|
||||
print(matrix2)
|
||||
end
|
||||
|
||||
x,y,z = math.random()*math.pi*2, math.random()*math.pi*2, math.random()*math.pi*2
|
||||
matrix2 = mat4.set_rot_irrlicht_bone(mat4.identity(), x,y,z)
|
||||
new_quat = quat.from_euler_irrlicht_bone(x,y,z)
|
||||
matrix1 = mat4.from_quaternion(new_quat)
|
||||
print("(euler->quat) checking `matrix1=matrix2` in `euler->quat->matrix1, euler->matrix2 (XYZ/irrlicht bone)`, Matches:", check_matrix_equality(matrix1, matrix2))
|
||||
if not check_matrix_equality(matrix1, matrix2) then
|
||||
print(x,y,z)
|
||||
print(matrix1)
|
||||
print(matrix2)
|
||||
end
|
||||
|
||||
print("(eulur->quat->euler)")
|
||||
print("\n==================== END OF QUATERNION UNIT TESTs =============================")
|
Loading…
x
Reference in New Issue
Block a user