95 lines
2.7 KiB
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
|
|
|
|
|