192 lines
No EOL
6.3 KiB
Lua
192 lines
No EOL
6.3 KiB
Lua
local c_air = minetest.get_content_id("air")
|
|
local c_light1 = minetest.get_content_id("cozylights:light1")
|
|
|
|
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
|
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
|
|
|
local gent_total = 0
|
|
local gent_count = 0
|
|
|
|
local remt_total = 0
|
|
local remt_count = 0
|
|
local mf = math.floor
|
|
|
|
local dirfloor = 0.5
|
|
--- raycast but normal
|
|
local function darknesscast(pos, dir, radius,data,param2data, a)
|
|
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
|
local c_light1 = c_lights[1]
|
|
local c_light14 = c_lights[14]
|
|
for i = 1, radius do
|
|
local x = mf(dx*i+dirfloor) + px
|
|
local y = mf(dy*i+dirfloor) + py
|
|
local z = mf(dz*i+dirfloor) + pz
|
|
local idx = a:index(x,y,z)
|
|
local cid = data[idx]
|
|
if cid and (cid == c_air or (cid >= c_light1 and cid <= c_light14+14)) then
|
|
data[idx] = c_air
|
|
param2data[idx] = 0
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function cozylights:draw_node_light(pos,cozy_item,vm,a,data,param2data,fix_edges)
|
|
local t = os.clock()
|
|
local update_needed = 0
|
|
local radius, dim_levels = cozylights:calc_dims(cozy_item)
|
|
--print("cozy_item:"..cozylights:dump(cozy_item))
|
|
--print("dim_levels: "..cozylights:dump(dim_levels))
|
|
--print("spreading light over a sphere with radius of "..radius)
|
|
if vm == nil then
|
|
_,_,vm,data,param2data,a = cozylights:getVoxelManipData(pos,radius)
|
|
update_needed = 1
|
|
end
|
|
local sphere_surface = cozylights:get_sphere_surface(radius)
|
|
local ylvl = 1
|
|
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
|
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
|
if cid and cida then
|
|
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
|
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
|
then
|
|
ylvl = -1
|
|
end
|
|
else
|
|
return
|
|
end
|
|
pos.y = pos.y + ylvl
|
|
fix_edges = fix_edges == nil and cozylights.always_fix_edges or fix_edges
|
|
if fix_edges == true then
|
|
local visited_pos = {}
|
|
for i,pos2 in ipairs(sphere_surface) do
|
|
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
|
cozylights:lightcast_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
|
end
|
|
else
|
|
for i,pos2 in ipairs(sphere_surface) do
|
|
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
|
cozylights.dir = vector.direction(pos, end_pos)
|
|
cozylights:lightcast(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
|
end
|
|
end
|
|
if update_needed == 1 then
|
|
cozylights:setVoxelManipData(vm,data,param2data,true)
|
|
end
|
|
gent_total = gent_total + mf((os.clock() - t) * 1000)
|
|
gent_count = gent_count + 1
|
|
--print("Av illum time " .. mf(gent_total/gent_count) .. " ms. Sample of: "..gent_count)
|
|
end
|
|
|
|
-- handle_async?
|
|
function cozylights:rebuild_light()
|
|
local single_light_queue = cozylights.single_light_queue
|
|
if #single_light_queue == 0 then
|
|
return
|
|
end
|
|
--print("#single_light_queue is: "..#single_light_queue)
|
|
cozylights:draw_node_light(single_light_queue[1].pos, single_light_queue[1].cozy_item)
|
|
table.remove(single_light_queue, 1)
|
|
end
|
|
|
|
function cozylights:destroy_light(pos, cozy_item)
|
|
local t = os.clock()
|
|
local radius = cozylights:calc_dims(cozy_item)
|
|
local _,_,vm,data,param2data,a = cozylights:getVoxelManipData(pos, radius)
|
|
local sphere_surface = cozylights:get_sphere_surface(radius)
|
|
local ylvl = 1
|
|
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
|
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
|
if cid and cida then
|
|
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
|
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
|
then
|
|
ylvl = -1
|
|
end
|
|
else
|
|
return
|
|
end
|
|
pos.y = pos.y + ylvl
|
|
for i,pos2 in ipairs(sphere_surface) do
|
|
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
|
darknesscast(pos, vector.direction(pos, end_pos),radius,data,param2data, a)
|
|
end
|
|
|
|
cozylights:setVoxelManipData(vm,data,param2data)
|
|
|
|
local rebuild_range = 78
|
|
local rebuild_minp = vector.subtract(pos, rebuild_range)
|
|
local rebuild_maxp = vector.add(pos, rebuild_range)
|
|
local posrebuilds = minetest.find_nodes_in_area(
|
|
rebuild_minp,
|
|
rebuild_maxp,
|
|
cozylights.source_nodes
|
|
)
|
|
local pos_hash = pos.x + (pos.y-ylvl)*100 + pos.z*10000
|
|
local sources = {}
|
|
if #posrebuilds > 0 then
|
|
local single_light_queue = cozylights.single_light_queue
|
|
for i=1,#posrebuilds do
|
|
local posrebuild = posrebuilds[i]
|
|
local posrebuild_hash = posrebuild.x + posrebuild.y*100 + posrebuild.z*10000
|
|
if posrebuild_hash ~= pos_hash then
|
|
local node = minetest.get_node(posrebuild)
|
|
local rebuild_radius, _ = cozylights:calc_dims(cozylights.cozy_items[node.name])
|
|
local max_distance = rebuild_radius + radius
|
|
if max_distance > vector.distance(pos,posrebuild) then
|
|
if vector.in_area(vector.subtract(posrebuild,rebuild_radius), rebuild_minp, rebuild_maxp)
|
|
and vector.in_area(vector.add(posrebuild,rebuild_radius), rebuild_minp, rebuild_maxp)
|
|
then
|
|
sources[#sources+1] = {
|
|
pos=posrebuild,
|
|
cozy_item=cozylights.cozy_items[node.name]
|
|
}
|
|
else
|
|
cozylights.single_light_queue[#single_light_queue+1] = {
|
|
pos=posrebuilds[i],
|
|
cozy_item=cozylights.cozy_items[node.name]
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if #sources > 0 then
|
|
cozylights.area_queue[#cozylights.area_queue+1]={
|
|
minp=rebuild_minp,
|
|
maxp=rebuild_maxp,
|
|
sources=sources
|
|
}
|
|
end
|
|
|
|
remt_total = remt_total + mf((os.clock() - t) * 1000)
|
|
remt_count = remt_count + 1
|
|
print("Av light removal time " .. mf(remt_total/remt_count) .. " ms. Sample of: "..remt_count)
|
|
end
|
|
|
|
--[[
|
|
function cozylights:rebuild_light(pos, cozy_item,vm,a,data,param2data)
|
|
local radius, dim_levels = cozylights:calc_dims(cozy_item)
|
|
print("rebuilding light for position "..cozylights:dump(pos))
|
|
local sphere_surface = cozylights:get_sphere_surface(radius)
|
|
local ylvl = 1
|
|
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
|
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
|
if cid and cida then
|
|
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
|
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
|
then
|
|
ylvl = -1
|
|
end
|
|
else
|
|
return
|
|
end
|
|
pos.y = pos.y + ylvl
|
|
for _,pos2 in ipairs(sphere_surface) do
|
|
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
|
if a:containsp(end_pos) then
|
|
cozylights:lightcast(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
|
end
|
|
end
|
|
end]] |