EinsDreiDreiSieben/mods/.cozylights/test/accuracy.lua

95 lines
2.7 KiB
Lua

dofile("../helpers.lua")
dofile("../../../builtin/common/vector.lua")
-- this exists to basically find sweet spot for dirfloor in fastest way i could come up with to spread light.
-- dirfloor should change somehow cheaply according to radius maybe or
-- according to ray angles, or, dirfloor should be split in x,y,z axis equivalents
-- and those should be adjusted.
-- some node misses start to appear from radius 6
local dirfloor = 0.51
local mf = math.floor
-- radius*radius = x*x + y*y + z*z
local function get_full_sphere(radius)
local sphere = {}
local count, offset, rad_pow2, stride_y = 0, 1+radius, radius * (radius + 1), radius+2
local stride_z = stride_y * stride_y
for z = -radius, radius do
for y = -radius, radius do
for x = -radius, radius do
local pow2 = x * x + y * y + z * z
if pow2 <= rad_pow2 then
local i = (z + offset) * stride_z + (y + offset) * stride_y + x + offset + 1
if sphere[i] ~= true then
sphere[i] = true
count = count + 1
end
end
end
end
end
return sphere, count
end
local function get_sphere_surface(radius)
local sphere_surface = {}
local rad_pow2_min, rad_pow2_max = radius * (radius - 1), radius * (radius + 1)
for z = -radius, radius do
for y = -radius, radius do
for x = -radius, radius do
local squared = x * x + y * y + z * z
if squared >= rad_pow2_min and squared <= rad_pow2_max then
sphere_surface[#sphere_surface+1] = {x=x,y=y,z=z}
end
end
end
end
return sphere_surface
end
local function raycast(dir, radius)
local ray = {}
local stride_z, stride_y = (radius+2)*radius+2, radius+2
local dx, dy, dz = dir.x, dir.y, dir.z
for i = 1, radius do
local x = mf(dx*i+dirfloor)
local y = mf(dy*i+dirfloor)
local z = mf(dz*i+dirfloor)
local idx = (z+1+radius)*stride_z+1+(y+1+radius)*stride_y+(x+1+radius)
if not ray[idx] then
ray[idx] = true
end
end
return ray
end
local function reconstruct_sphere(radius)
local pos = {x=0,y=0,z=0}
local sphere, sphere_len = get_full_sphere(radius)
local sphere_surface = get_sphere_surface(radius)
local reconstructed_sphere = {}
local reconstructed_sphere_len = 0
for _,pos2 in ipairs(sphere_surface) do
local ray = raycast(vector.direction(pos, pos2),radius)
for i,_ in pairs(ray) do
if not reconstructed_sphere[i] then
reconstructed_sphere[i] = true
reconstructed_sphere_len = reconstructed_sphere_len + 1
end
end
end
print("#sphere: "..sphere_len)
print("#reconstructed_sphere: "..reconstructed_sphere_len)
--print(cozylights:dump(sphere))
--print(cozylights:dump(reconstructed_sphere))
end
for i=1,1 do
dirfloor = dirfloor - 0.01
print("running with dirfloor: "..dirfloor)
reconstruct_sphere(1)
end