digtron/geometry.lua
2019-09-02 20:17:51 -06:00

164 lines
5.5 KiB
Lua

local cardinal_dirs = {
{x = 0, y = 0, z = 1},
{x = 1, y = 0, z = 0},
{x = 0, y = 0, z = -1},
{x = -1, y = 0, z = 0},
{x = 0, y = -1, z = 0},
{x = 0, y = 1, z = 0},
}
-- Turn the cardinal directions into a set of integers you can add to a hash to step in that direction.
local cardinal_dirs_hash = {}
local origin_hash = minetest.hash_node_position({x = 0, y = 0, z = 0})
for i, dir in ipairs(cardinal_dirs) do
cardinal_dirs_hash[i] = minetest.hash_node_position(dir) - origin_hash
end
-- Mapping from facedir value to index in cardinal_dirs.
local facedir_to_dir_map = {
[0] = 1, 2, 3, 4,
5, 2, 6, 4,
6, 2, 5, 4,
1, 5, 3, 6,
1, 6, 3, 5,
1, 4, 3, 2,
}
local facedir_to_up_map = {
[0] = 6, 6, 6, 6,
3, 3, 3, 3,
1, 1, 1, 1,
4, 4, 4, 4,
2, 2, 2, 2,
5, 5, 5, 5,
}
local facedir_to_down_map = {
[0] = 5, 5, 5, 5,
1, 1, 1, 1,
3, 3, 3, 3,
2, 2, 2, 2,
4, 4, 4, 4,
6, 6, 6, 6,
}
local facedir_to_right_map = {
[0] = 2, 3, 4, 1,
2, 6, 4, 6,
2, 5, 4, 6,
5, 3, 6, 1,
6, 3, 5, 1,
4, 3, 2, 1,
}
local facedir_to_dir = function(facedir)
return cardinal_dirs[facedir_to_dir_map[facedir % 32]]
end
local facedir_to_dir_hash = function(facedir)
return cardinal_dirs_hash[facedir_to_dir_map[facedir % 32]]
end
local facedir_to_up = function(facedir)
return cardinal_dirs[facedir_to_up_map[facedir % 32]]
end
local facedir_to_up_hash = function(facedir)
return cardinal_dirs_hash[facedir_to_up_map[facedir % 32]]
end
local facedir_to_down = function(facedir)
return cardinal_dirs[facedir_to_down_map[facedir % 32]]
end
local facedir_to_down_hash = function(facedir)
return cardinal_dirs_hash[facedir_to_down_map[facedir % 32]]
end
local facedir_to_right = function(facedir)
return cardinal_dirs[facedir_to_right_map[facedir % 32]]
end
local facedir_to_right_hash = function(facedir)
return cardinal_dirs_hash[facedir_to_right_map[facedir % 32]]
end
-- Rotation
local negative_x = minetest.hash_node_position({x = -1, y = 0, z = 0})
local positive_x = minetest.hash_node_position({x = 1, y = 0, z = 0})
local negative_y = minetest.hash_node_position({x = 0, y = -1, z = 0})
local positive_y = minetest.hash_node_position({x = 0, y = 1, z = 0})
local negative_z = minetest.hash_node_position({x = 0, y = 0, z = -1})
local positive_z = minetest.hash_node_position({x = 0, y = 0, z = 1})
local facedir_rot = {
[negative_x] = {[0] = 4, 5, 6, 7, 22, 23, 20, 21, 0, 1, 2, 3, 13, 14, 15, 12, 19, 16, 17, 18, 10, 11, 8, 9}, -- 270 degrees
[positive_x] = {[0] = 8, 9, 10, 11, 0, 1, 2, 3, 22, 23, 20, 21, 15, 12, 13, 14, 17, 18, 19, 16, 6, 7, 4, 5}, -- 90 degrees
[negative_y] = {[0] = 3, 0, 1, 2, 19, 16, 17, 18, 15, 12, 13, 14, 7, 4, 5, 6, 11, 8, 9, 10, 21, 22, 23, 20}, -- 270 degrees
[positive_y] = {[0] = 1, 2, 3, 0, 13, 14, 15, 12, 17, 18, 19, 16, 9, 10, 11, 8, 5, 6, 7, 4, 23, 20, 21, 22}, -- 90 degrees
[negative_z] = {[0] = 16, 17, 18, 19, 5, 6, 7, 4, 11, 8, 9, 10, 0, 1, 2, 3, 20, 21, 22, 23, 12, 13, 14, 15}, -- 270 degrees
[positive_z] = {[0] = 12, 13, 14, 15, 7, 4, 5, 6, 9, 10, 11, 8, 20, 21, 22, 23, 0, 1, 2, 3, 16, 17, 18, 19}, -- 90 degrees
}
local wallmounted_rot = {
[negative_x] = {[0] = 4, 5, 2, 3, 1, 0}, -- 270 degrees
[positive_x] = {[0] = 5, 4, 2, 3, 0, 1}, -- 90 degrees
[negative_y] = {[0] = 0, 1, 4, 5, 3, 2}, -- 270 degrees
[positive_y] = {[0] = 0, 1, 5, 4, 2, 3}, -- 90 degrees
[negative_z] = {[0] = 3, 2, 0, 1, 4, 5}, -- 270 degrees
[positive_z] = {[0] = 2, 3, 1, 0, 4, 5}, -- 90 degrees
}
local rotate_facedir = function(axis_hash, facedir)
return facedir_rot[axis_hash][facedir]
end
local rotate_wallmounted = function(axis_hash, facedir)
return wallmounted_rot[axis_hash][facedir]
end
--90 degrees CW about x-axis: (x, y, z) -> (x, -z, y)
--90 degrees CCW about x-axis: (x, y, z) -> (x, z, -y)
--90 degrees CW about y-axis: (x, y, z) -> (-z, y, x)
--90 degrees CCW about y-axis: (x, y, z) -> (z, y, -x)
--90 degrees CW about z-axis: (x, y, z) -> (y, -x, z)
--90 degrees CCW about z-axis: (x, y, z) -> (-y, x, z)
-- operates directly on the pos vector
-- Rotates it around origin
local rotate_pos = function(axis_hash, pos)
if axis_hash == negative_x and not (pos.y == 0 and pos.z == 0) then
local temp_z = pos.z
pos.z = pos.y
pos.y = -temp_z
elseif axis_hash == positive_x and not (pos.y == 0 and pos.z == 0) then
local temp_z = pos.z
pos.z = -pos.y
pos.y = temp_z
elseif axis_hash == negative_y and not (pos.x == 0 and pos.z == 0) then
local temp_x = pos.x
pos.x = -pos.z
pos.z = temp_x
elseif axis_hash == positive_y and not (pos.x == 0 and pos.z == 0) then
local temp_x = pos.x
pos.x = pos.z
pos.z = -temp_x
elseif axis_hash == negative_z and not (pos.x == 0 and pos.y == 0) then
local temp_x = pos.x
pos.x = -pos.y
pos.y = temp_x
elseif axis_hash == positive_z and not (pos.x == 0 and pos.y == 0) then
local temp_x = pos.x
pos.x = pos.y
pos.y = -temp_x
end
return pos
end
digtron.cardinal_dirs = cardinal_dirs -- used by builder entities as well
digtron.cardinal_dirs_hash = cardinal_dirs_hash
digtron.facedir_to_dir_map = facedir_to_dir_map -- used by get_controlling_coordinate
digtron.facedir_to_dir = facedir_to_dir
digtron.facedir_to_dir_hash = facedir_to_dir_hash
digtron.facedir_to_up = facedir_to_up
digtron.facedir_to_up_hash = facedir_to_up_hash
digtron.facedir_to_down = facedir_to_down
digtron.facedir_to_down_hash = facedir_to_down_hash
digtron.facedir_to_right = facedir_to_right
digtron.facedir_to_right_hash = facedir_to_right_hash
digtron.rotate_pos = rotate_pos
digtron.rotate_wallmounted = rotate_wallmounted
digtron.rotate_facedir = rotate_facedir