mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 15:23:48 +01:00
Raycast: Improve code quality
This commit is contained in:
parent
6cc39ef023
commit
0f6f325aa8
@ -16,124 +16,126 @@ function raycast(_pos1, _pos2, objects, liquids)
|
|||||||
local direction = modlib.vector.from_minetest(_direction)
|
local direction = modlib.vector.from_minetest(_direction)
|
||||||
local length = vector.distance(_pos1, _pos2)
|
local length = vector.distance(_pos1, _pos2)
|
||||||
local function next()
|
local function next()
|
||||||
for pointed_thing in raycast do
|
local pointed_thing = raycast:next()
|
||||||
if pointed_thing.type ~= "node" then
|
if (not pointed_thing) or pointed_thing.type ~= "node" then
|
||||||
return pointed_thing
|
return pointed_thing
|
||||||
|
end
|
||||||
|
local _pos = pointed_thing.under
|
||||||
|
local pos = modlib.vector.from_minetest(_pos)
|
||||||
|
local node = minetest.get_node(_pos)
|
||||||
|
local def = minetest.registered_nodes[node.name]
|
||||||
|
if not (def and def.drawtype == "flowingliquid") then
|
||||||
|
return pointed_thing
|
||||||
|
end
|
||||||
|
local corner_levels = get_liquid_corner_levels(_pos)
|
||||||
|
local full_corner_levels = true
|
||||||
|
for _, corner_level in pairs(corner_levels) do
|
||||||
|
if corner_level[2] < 0.5 then
|
||||||
|
full_corner_levels = false
|
||||||
|
break
|
||||||
end
|
end
|
||||||
local _pos = pointed_thing.under
|
end
|
||||||
local pos = modlib.vector.from_minetest(_pos)
|
if full_corner_levels then
|
||||||
local node = minetest.get_node(_pos)
|
return pointed_thing
|
||||||
local def = minetest.registered_nodes[node.name]
|
end
|
||||||
if not (def and def.drawtype == "flowingliquid") then return pointed_thing end
|
local relative = pos1 - pos
|
||||||
local corner_levels = get_liquid_corner_levels(_pos)
|
local inside = true
|
||||||
local full_corner_levels = true
|
for _, prop in pairs(relative) do
|
||||||
for _, corner_level in pairs(corner_levels) do
|
if prop <= -0.5 or prop >= 0.5 then
|
||||||
if corner_level[2] < 0.5 then
|
inside = false
|
||||||
full_corner_levels = false
|
break
|
||||||
break
|
end
|
||||||
|
end
|
||||||
|
local function level(x, z)
|
||||||
|
local function distance_squared(corner)
|
||||||
|
return (x - corner[1]) ^ 2 + (z - corner[3]) ^ 2
|
||||||
|
end
|
||||||
|
local irrelevant_corner, distance = 1, distance_squared(corner_levels[1])
|
||||||
|
for index = 2, 4 do
|
||||||
|
local other_distance = distance_squared(corner_levels[index])
|
||||||
|
if other_distance > distance then
|
||||||
|
irrelevant_corner, distance = index, other_distance
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if full_corner_levels then
|
local function corner(off)
|
||||||
return pointed_thing
|
return corner_levels[((irrelevant_corner + off) % 4) + 1]
|
||||||
end
|
end
|
||||||
local relative = pos1 - pos
|
local base = corner(2)
|
||||||
local inside = true
|
local edge_1, edge_2 = corner(1) - base, corner(3) - base
|
||||||
for _, prop in pairs(relative) do
|
-- Properly selected edges will have a total length of 2
|
||||||
if prop <= -0.5 or prop >= 0.5 then
|
assert(math.abs(edge_1[1] + edge_1[3]) + math.abs(edge_2[1] + edge_2[3]) == 2)
|
||||||
inside = false
|
if edge_1[1] == 0 then
|
||||||
break
|
edge_1, edge_2 = edge_2, edge_1
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local function level(x, z)
|
local level = base[2] + (edge_1[2] * ((x - base[1]) / edge_1[1])) + (edge_2[2] * ((z - base[3]) / edge_2[3]))
|
||||||
local function distance_squared(corner)
|
assert(level >= -0.5 and level <= 0.5)
|
||||||
return (x - corner[1]) ^ 2 + (z - corner[3]) ^ 2
|
return level
|
||||||
end
|
end
|
||||||
local irrelevant_corner, distance = 1, distance_squared(corner_levels[1])
|
inside = inside and (relative[2] < level(relative[1], relative[3]))
|
||||||
for index = 2, 4 do
|
if inside then
|
||||||
local other_distance = distance_squared(corner_levels[index])
|
-- pos1 is inside the liquid node
|
||||||
if other_distance > distance then
|
pointed_thing.intersection_point = _pos1
|
||||||
irrelevant_corner, distance = index, other_distance
|
pointed_thing.intersection_normal = vector.new(0, 0, 0)
|
||||||
|
return pointed_thing
|
||||||
|
end
|
||||||
|
local function intersection_normal(axis, dir)
|
||||||
|
return {x = 0, y = 0, z = 0, [axis] = dir}
|
||||||
|
end
|
||||||
|
local function plane(axis, dir)
|
||||||
|
local offset = dir * 0.5
|
||||||
|
local diff_axis = (relative[axis] - offset) / -direction[axis]
|
||||||
|
local intersection_point = {}
|
||||||
|
for plane_axis = 1, 3 do
|
||||||
|
if plane_axis ~= axis then
|
||||||
|
local value = direction[plane_axis] * diff_axis + relative[plane_axis]
|
||||||
|
if value < -0.5 or value > 0.5 then
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
intersection_point[plane_axis] = value
|
||||||
end
|
end
|
||||||
local function corner(off)
|
|
||||||
return corner_levels[((irrelevant_corner + off) % 4) + 1]
|
|
||||||
end
|
|
||||||
local base = corner(2)
|
|
||||||
local edge_1, edge_2 = corner(1) - base, corner(3) - base
|
|
||||||
-- Properly selected edges will have a total length of 2
|
|
||||||
assert(math.abs(edge_1[1] + edge_1[3]) + math.abs(edge_2[1] + edge_2[3]) == 2)
|
|
||||||
if edge_1[1] == 0 then
|
|
||||||
edge_1, edge_2 = edge_2, edge_1
|
|
||||||
end
|
|
||||||
local level = base[2] + (edge_1[2] * ((x - base[1]) / edge_1[1])) + (edge_2[2] * ((z - base[3]) / edge_2[3]))
|
|
||||||
assert(level >= -0.5 and level <= 0.5)
|
|
||||||
return level
|
|
||||||
end
|
end
|
||||||
inside = inside and (relative[2] < level(relative[1], relative[3]))
|
intersection_point[axis] = offset
|
||||||
if inside then
|
return intersection_point
|
||||||
-- pos1 is inside the liquid node
|
end
|
||||||
pointed_thing.intersection_point = _pos1
|
if direction[2] > 0 then
|
||||||
pointed_thing.intersection_normal = vector.new(0, 0, 0)
|
local intersection_point = plane(2, -1)
|
||||||
|
if intersection_point then
|
||||||
|
pointed_thing.intersection_point = (intersection_point + pos):to_minetest()
|
||||||
|
pointed_thing.intersection_normal = intersection_normal("y", -1)
|
||||||
return pointed_thing
|
return pointed_thing
|
||||||
end
|
end
|
||||||
local function intersection_normal(axis, dir)
|
end
|
||||||
return {x = 0, y = 0, z = 0, [axis] = dir}
|
for coord, other in pairs{[1] = 3, [3] = 1} do
|
||||||
end
|
if direction[coord] ~= 0 then
|
||||||
local function plane(axis, dir)
|
local dir = direction[coord] > 0 and -1 or 1
|
||||||
local offset = dir * 0.5
|
local intersection_point = plane(coord, dir)
|
||||||
local diff_axis = (relative[axis] - offset) / -direction[axis]
|
|
||||||
local intersection_point = {}
|
|
||||||
for plane_axis = 1, 3 do
|
|
||||||
if plane_axis ~= axis then
|
|
||||||
local value = direction[plane_axis] * diff_axis + relative[plane_axis]
|
|
||||||
if value < -0.5 or value > 0.5 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
intersection_point[plane_axis] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
intersection_point[axis] = offset
|
|
||||||
return intersection_point
|
|
||||||
end
|
|
||||||
if direction[2] > 0 then
|
|
||||||
local intersection_point = plane(2, -1)
|
|
||||||
if intersection_point then
|
if intersection_point then
|
||||||
pointed_thing.intersection_point = (intersection_point + pos):to_minetest()
|
local height = 0
|
||||||
pointed_thing.intersection_normal = intersection_normal("y", -1)
|
for _, corner in pairs(corner_levels) do
|
||||||
return pointed_thing
|
if corner[coord] == dir * 0.5 then
|
||||||
end
|
height = height + (math.abs(intersection_point[other] + corner[other])) * corner[2]
|
||||||
end
|
|
||||||
for coord, other in pairs{[1] = 3, [3] = 1} do
|
|
||||||
if direction[coord] ~= 0 then
|
|
||||||
local dir = direction[coord] > 0 and -1 or 1
|
|
||||||
local intersection_point = plane(coord, dir)
|
|
||||||
if intersection_point then
|
|
||||||
local height = 0
|
|
||||||
for _, corner in pairs(corner_levels) do
|
|
||||||
if corner[coord] == dir * 0.5 then
|
|
||||||
height = height + (math.abs(intersection_point[other] + corner[other])) * corner[2]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if intersection_point[2] <= height then
|
|
||||||
pointed_thing.intersection_point = (intersection_point + pos):to_minetest()
|
|
||||||
pointed_thing.intersection_normal = intersection_normal(modlib.vector.index_aliases[coord], dir)
|
|
||||||
return pointed_thing
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
if intersection_point[2] <= height then
|
||||||
end
|
pointed_thing.intersection_point = (intersection_point + pos):to_minetest()
|
||||||
for _, triangle in pairs{
|
pointed_thing.intersection_normal = intersection_normal(modlib.vector.index_aliases[coord], dir)
|
||||||
{corner_levels[3], corner_levels[2], corner_levels[1]},
|
return pointed_thing
|
||||||
{corner_levels[4], corner_levels[3], corner_levels[1]}
|
end
|
||||||
} do
|
|
||||||
local pos_on_ray = modlib.vector.ray_triangle_intersection(relative, direction, triangle)
|
|
||||||
if pos_on_ray and pos_on_ray <= length then
|
|
||||||
pointed_thing.intersection_point = (pos1 + modlib.vector.multiply_scalar(direction, pos_on_ray)):to_minetest()
|
|
||||||
pointed_thing.intersection_normal = modlib.vector.triangle_normal(triangle):to_minetest()
|
|
||||||
return pointed_thing
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for _, triangle in pairs{
|
||||||
|
{corner_levels[3], corner_levels[2], corner_levels[1]},
|
||||||
|
{corner_levels[4], corner_levels[3], corner_levels[1]}
|
||||||
|
} do
|
||||||
|
local pos_on_ray = modlib.vector.ray_triangle_intersection(relative, direction, triangle)
|
||||||
|
if pos_on_ray and pos_on_ray <= length then
|
||||||
|
pointed_thing.intersection_point = (pos1 + modlib.vector.multiply_scalar(direction, pos_on_ray)):to_minetest()
|
||||||
|
pointed_thing.intersection_normal = modlib.vector.triangle_normal(triangle):to_minetest()
|
||||||
|
return pointed_thing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return next()
|
||||||
end
|
end
|
||||||
return setmetatable({next = next}, {__call = next})
|
return setmetatable({next = next}, {__call = next})
|
||||||
end
|
end
|
Loading…
Reference in New Issue
Block a user