mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 15:23:48 +01:00
193 lines
4.1 KiB
Lua
193 lines
4.1 KiB
Lua
local mt_vector = vector
|
|
local vector = getfenv(1)
|
|
|
|
index_aliases = {
|
|
x = 1,
|
|
y = 2,
|
|
z = 3,
|
|
w = 4
|
|
}
|
|
|
|
modlib.table.add_all(index_aliases, modlib.table.flip(index_aliases))
|
|
|
|
metatable = {
|
|
__index = function(table, key)
|
|
local index = index_aliases[key]
|
|
if index ~= nil then
|
|
return table[index]
|
|
end
|
|
return vector[key]
|
|
end,
|
|
__newindex = function(table, key, value)
|
|
local index = letters[key]
|
|
if index ~= nil then
|
|
return rawset(table, index, value)
|
|
end
|
|
end
|
|
}
|
|
|
|
function new(v)
|
|
return setmetatable(v, metatable)
|
|
end
|
|
|
|
function from_xyzw(v)
|
|
return new{v.x, v.y, v.z, v.w}
|
|
end
|
|
|
|
function from_minetest(v)
|
|
return new{v.x, v.y, v.z}
|
|
end
|
|
|
|
function to_xyzw(v)
|
|
return {x = v[1], y = v[2], z = v[3], w = v[4]}
|
|
end
|
|
|
|
function to_minetest(v)
|
|
return mt_vector.new(unpack(v))
|
|
end
|
|
|
|
function equals(v, other_v)
|
|
for k, v in pairs(v) do
|
|
if v ~= other_v[k] then return false end
|
|
end
|
|
return true
|
|
end
|
|
|
|
metatable.__eq = equals
|
|
|
|
function less_than(v, other_v)
|
|
for k, v in pairs(v) do
|
|
if v >= other_v[k] then return false end
|
|
end
|
|
return true
|
|
end
|
|
|
|
metatable.__lt = less_than
|
|
|
|
function less_or_equal(v, other_v)
|
|
for k, v in pairs(v) do
|
|
if v > other_v[k] then return false end
|
|
end
|
|
return true
|
|
end
|
|
|
|
metatable.__le = less_or_equal
|
|
|
|
function combine(v, other_v, f)
|
|
local new_vector = {}
|
|
for key, value in pairs(v) do
|
|
new_vector[key] = f(value, other_v[key])
|
|
end
|
|
return new(new_vector)
|
|
end
|
|
|
|
function apply(v, f, ...)
|
|
local new_vector = {}
|
|
for key, value in pairs(v) do
|
|
new_vector[key] = f(value, ...)
|
|
end
|
|
return new(new_vector)
|
|
end
|
|
|
|
function combinator(f)
|
|
return function(v, other_v)
|
|
return combine(v, other_v, f)
|
|
end, function(v, ...)
|
|
return apply(v, f, ...)
|
|
end
|
|
end
|
|
|
|
add, add_scalar = combinator(function(a, b) return a + b end)
|
|
subtract, subtract_scalar = combinator(function(a, b) return a - b end)
|
|
multiply, multiply_scalar = combinator(function(a, b) return a * b end)
|
|
divide, divide_scalar = combinator(function(a, b) return a / b end)
|
|
|
|
metatable.__add = add
|
|
metatable.__sub = subtract
|
|
metatable.__mul = multiply
|
|
metatable.__div = divide
|
|
|
|
function norm(v)
|
|
local sum = 0
|
|
for _, c in pairs(v) do
|
|
sum = sum + c*c
|
|
end
|
|
return sum
|
|
end
|
|
|
|
function length(v)
|
|
return math.sqrt(norm(v))
|
|
end
|
|
|
|
function normalize(v)
|
|
return divide_scalar(v, length(v))
|
|
end
|
|
|
|
function floor(v)
|
|
return apply(v, math.floor)
|
|
end
|
|
|
|
function ceil(v)
|
|
return apply(v, math.ceil)
|
|
end
|
|
|
|
function clamp(v, min, max)
|
|
return apply(apply(v, math.max, min), math.min, max)
|
|
end
|
|
|
|
function cross3(v, other_v)
|
|
return new{
|
|
v[2] * other_v[3] - v[3] * other_v[2],
|
|
v[3] * other_v[1] - v[1] * other_v[3],
|
|
v[1] * other_v[2] - v[2] * other_v[1]
|
|
}
|
|
end
|
|
|
|
function dot(v, other_v)
|
|
local sum = 0
|
|
for i, c in pairs(v) do
|
|
sum = sum + c * other_v[i]
|
|
end
|
|
return sum
|
|
end
|
|
|
|
function box_box_collision(diff, box, other_box)
|
|
for index, diff in pairs(diff) do
|
|
if box[index] + diff > other_box[index + 3] or other_box[index] > box[index + 3] + diff then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
--+ Möller-Trumbore
|
|
function ray_triangle_intersection(origin, direction, triangle)
|
|
local point_1, point_2, point_3 = unpack(triangle)
|
|
local edge_1, edge_2 = subtract(point_2, point_1), subtract(point_3, point_1)
|
|
local h = cross3(direction, edge_2)
|
|
local a = dot(edge_1, h)
|
|
if math.abs(a) < 1e-9 then
|
|
return
|
|
end
|
|
local f = 1 / a
|
|
local diff = subtract(origin, point_1)
|
|
local u = f * dot(diff, h)
|
|
if u < 0 or u > 1 then
|
|
return
|
|
end
|
|
local q = cross3(diff, edge_1)
|
|
local v = f * dot(direction, q)
|
|
if v < 0 or u + v > 1 then
|
|
return
|
|
end
|
|
local pos_on_line = f * dot(edge_2, q)
|
|
if pos_on_line >= 0 then
|
|
return pos_on_line
|
|
end
|
|
end
|
|
|
|
function triangle_normal(triangle)
|
|
local point_1, point_2, point_3 = unpack(triangle)
|
|
local edge_1, edge_2 = subtract(point_2, point_1), subtract(point_3, point_1)
|
|
return normalize(cross3(edge_1, edge_2))
|
|
end |