2014-10-20 11:47:41 +03:00
|
|
|
-- Buildat: builtin/ground_plane_lighting/client_lua/module.lua
|
|
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
-- Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
|
|
|
local dump = buildat.dump
|
|
|
|
local log = buildat.Logger("ground_plane_lighting")
|
|
|
|
local magic = require("buildat/extension/urho3d")
|
|
|
|
local replicate = require("buildat/extension/replicate")
|
2014-10-20 17:15:32 +03:00
|
|
|
local cereal = require("buildat/extension/cereal")
|
2014-10-20 11:47:41 +03:00
|
|
|
local voxelworld = require("buildat/module/voxelworld")
|
|
|
|
local M = {}
|
|
|
|
|
2014-10-21 01:47:51 +03:00
|
|
|
-- NOTE: This should actually be always equal to the voxelworld chunk size
|
|
|
|
-- because each chunk will be rendered as a whole according to the zone its
|
|
|
|
-- center position is in
|
|
|
|
--local ideal_zone_size = 32
|
2014-10-21 12:57:57 +03:00
|
|
|
-- NOTE: Actually, when zone overrides are used, this can be lower; but it will
|
|
|
|
-- require more processing as all renderable things are in the same octree
|
2014-10-20 17:15:32 +03:00
|
|
|
local ideal_zone_size = 16
|
|
|
|
|
|
|
|
M.sector_size = buildat.Vector2(0, 0)
|
|
|
|
M.zone_div = buildat.Vector2(0, 0)
|
|
|
|
M.zone_size = buildat.Vector2(0, 0)
|
|
|
|
|
|
|
|
local function setup_sizes(sector_size)
|
|
|
|
M.sector_size = sector_size
|
|
|
|
M.zone_div = (M.sector_size / ideal_zone_size):floor()
|
|
|
|
M.zone_size = buildat.Vector2(ideal_zone_size, ideal_zone_size)
|
|
|
|
log:info("sector_size: "..M.sector_size:dump())
|
|
|
|
log:info("zone_div: "..M.zone_div:dump())
|
|
|
|
log:info("zone_size: "..M.zone_size:dump())
|
|
|
|
end
|
|
|
|
|
|
|
|
buildat.sub_packet("ground_plane_lighting:init", function(data)
|
|
|
|
local values = cereal.binary_input(data, {"object",
|
|
|
|
{"sector_size", {"object",
|
|
|
|
{"x", "int16_t"},
|
|
|
|
{"y", "int16_t"},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
log:info("ground_plane_lighting:init: "..dump(values))
|
|
|
|
setup_sizes(buildat.Vector2(values.sector_size))
|
|
|
|
end)
|
|
|
|
|
|
|
|
local dark_zones = {} -- {sector_y: {sector_x: {zone nodes}}}
|
|
|
|
|
|
|
|
local function get_sector_zones(x, y)
|
|
|
|
local ytable = dark_zones[y]
|
|
|
|
if ytable == nil then
|
|
|
|
ytable = {}
|
|
|
|
dark_zones[y] = ytable
|
|
|
|
end
|
|
|
|
local xtable = ytable[x]
|
|
|
|
if xtable == nil then
|
|
|
|
xtable = {}
|
|
|
|
ytable[x] = xtable
|
|
|
|
end
|
|
|
|
return xtable
|
|
|
|
end
|
|
|
|
|
|
|
|
local function set_dark_zones(sector_p, yst_volume)
|
2014-10-21 01:47:51 +03:00
|
|
|
log:debug("set_dark_zones(): sector_p="..sector_p:dump())
|
2014-10-20 17:15:32 +03:00
|
|
|
local scene = replicate.main_scene -- TODO: More flexibility
|
|
|
|
local sector_zones = get_sector_zones(sector_p.x, sector_p.y)
|
|
|
|
local zone_i = 1
|
|
|
|
for y_div = 0, M.zone_div.y - 1 do
|
|
|
|
for x_div = 0, M.zone_div.x - 1 do
|
|
|
|
local zone_node = sector_zones[zone_i]
|
|
|
|
if zone_node == nil then
|
|
|
|
zone_node = scene:CreateChild("GPLZone")
|
|
|
|
zone_node:CreateComponent("Zone")
|
|
|
|
sector_zones[zone_i] = zone_node
|
|
|
|
end
|
|
|
|
local zone = zone_node:GetComponent("Zone")
|
|
|
|
do
|
|
|
|
local yst_min = 1000000
|
2014-10-21 01:47:51 +03:00
|
|
|
for y0 = 0, M.zone_size.y - 1 do
|
|
|
|
for x0 = 0, M.zone_size.x - 1 do
|
|
|
|
-- NOTE: yst_volume uses global coordinates
|
|
|
|
local x = sector_p.x * M.sector_size.x +
|
|
|
|
x_div * M.zone_size.x + x0
|
|
|
|
local y = sector_p.y * M.sector_size.y +
|
|
|
|
y_div * M.zone_size.y + y0
|
|
|
|
local v = yst_volume:get_voxel_at(x, 0, y)
|
2014-10-20 17:15:32 +03:00
|
|
|
if v.int32 < yst_min then
|
|
|
|
yst_min = v.int32
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local y_min = -10000
|
2014-10-21 01:47:51 +03:00
|
|
|
local y_max = yst_min - 1
|
2014-10-20 17:15:32 +03:00
|
|
|
local lc = magic.Vector3(
|
|
|
|
sector_p.x * M.sector_size.x + x_div * M.zone_size.x,
|
|
|
|
y_min,
|
|
|
|
sector_p.y * M.sector_size.y + y_div * M.zone_size.y
|
|
|
|
)
|
|
|
|
local uc = magic.Vector3(
|
|
|
|
lc.x + M.zone_size.x,
|
|
|
|
y_max,
|
|
|
|
lc.z + M.zone_size.y
|
|
|
|
)
|
2014-10-21 01:47:51 +03:00
|
|
|
log:debug("Dark zone at lc=("..lc.x..", "..lc.y..", "..lc.z..
|
2014-10-20 17:15:32 +03:00
|
|
|
"), uc=("..uc.x..", "..uc.y..", "..uc.z..")")
|
|
|
|
zone.boundingBox = magic.BoundingBox(lc, uc)
|
|
|
|
zone.ambientColor = magic.Color(0, 0, 0)
|
|
|
|
zone.fogColor = magic.Color(0.6, 0.7, 0.8)
|
|
|
|
zone.fogStart = 10
|
|
|
|
zone.fogEnd = voxelworld.camera_far_clip * 1.2
|
2014-10-21 01:47:51 +03:00
|
|
|
zone.override = true
|
2014-10-20 17:15:32 +03:00
|
|
|
end
|
|
|
|
zone_i = zone_i + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
buildat.sub_packet("ground_plane_lighting:update", function(data)
|
|
|
|
log:debug("ground_plane_lighting:update: #data="..#data)
|
|
|
|
local values = cereal.binary_input(data, {"object",
|
|
|
|
{"p", {"object",
|
|
|
|
{"x", "int16_t"},
|
|
|
|
{"y", "int16_t"},
|
|
|
|
}},
|
|
|
|
{"data", "string"},
|
|
|
|
})
|
|
|
|
--log:verbose("ground_plane_lighting:update: values="..dump(values))
|
|
|
|
log:verbose("ground_plane_lighting:update: #data="..#values.data..
|
|
|
|
", p=("..values.p.x..", "..values.p.y..")")
|
|
|
|
|
|
|
|
--log:verbose("values.data="..dump(buildat.bytes(values.data)))
|
|
|
|
local volume = buildat.deserialize_volume_int32(values.data)
|
|
|
|
local region = volume:get_enclosing_region()
|
2014-10-21 01:47:51 +03:00
|
|
|
log:debug("region: ("..region.x0..", "..region.y0..", "..region.z0..", "..
|
2014-10-20 17:15:32 +03:00
|
|
|
region.x1..", "..region.y1..", "..region.z1..")")
|
|
|
|
|
|
|
|
local sector_p = buildat.Vector2(values.p)
|
|
|
|
set_dark_zones(sector_p, volume)
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- TODO: Remove
|
2014-10-20 11:47:41 +03:00
|
|
|
voxelworld.sub_geometry_update(function(node)
|
2014-10-20 17:15:32 +03:00
|
|
|
--[[
|
2014-10-20 14:05:58 +03:00
|
|
|
local cs = voxelworld.chunk_size_voxels
|
|
|
|
local node_p = node:GetWorldPosition()
|
|
|
|
local scene = node.scene
|
|
|
|
|
|
|
|
local has_sunlight = false
|
|
|
|
|
|
|
|
local zone_node = scene:CreateChild("Zone")
|
|
|
|
local zone = zone_node:CreateComponent("Zone")
|
|
|
|
zone.boundingBox = magic.BoundingBox(
|
|
|
|
node_p - magic.Vector3(cs.x, cs.y, cs.z)/2,
|
|
|
|
node_p + magic.Vector3(cs.x, cs.y, cs.z)/2
|
|
|
|
)
|
|
|
|
if has_sunlight then
|
|
|
|
zone.ambientColor = magic.Color(0.1, 0.1, 0.1)
|
|
|
|
zone.fogColor = magic.Color(0.6, 0.7, 0.8)
|
|
|
|
else
|
|
|
|
zone.ambientColor = magic.Color(0, 0, 0)
|
|
|
|
--zone.fogColor = magic.Color(0, 0, 0)
|
|
|
|
zone.fogColor = magic.Color(0.6, 0.7, 0.8)
|
|
|
|
end
|
|
|
|
--zone.ambientColor = magic.Color(
|
|
|
|
-- math.random(), math.random(), math.random())
|
|
|
|
--zone.fogEnd = 10 + math.random() * 50
|
|
|
|
zone.fogStart = 10
|
|
|
|
zone.fogEnd = voxelworld.camera_far_clip * 1.2
|
|
|
|
--zone.ambientGradient = true
|
|
|
|
--]]
|
|
|
|
--[[
|
2014-10-20 11:47:41 +03:00
|
|
|
local yst_data = node:GetVar("gpl_voxel_yst_data"):GetBuffer()
|
|
|
|
log:verbose("#yst_data="..yst_data:GetSize())
|
|
|
|
local yst_volume = buildat.deserialize_volume_8bit(yst_data)
|
|
|
|
|
|
|
|
local cs = voxelworld.chunk_size_voxels
|
|
|
|
|
|
|
|
local v_min = cs.y + 1
|
|
|
|
|
|
|
|
for x = 0, cs.x - 1 do
|
|
|
|
for z = 0, cs.z - 1 do
|
2014-10-20 14:05:58 +03:00
|
|
|
local v = yst_volume:get_voxel_at(x, 0, z)
|
2014-10-20 11:47:41 +03:00
|
|
|
--log:verbose("voxel at ("..x..",0,"..z.."): "..v.id)
|
|
|
|
if v.data < v_min then
|
|
|
|
v_min = v.data
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--local v_avg = v_sum / cs.x / cs.z
|
|
|
|
--log:verbose("v_avg: "..v_avg)
|
|
|
|
|
|
|
|
--local has_sunlight = buildat.voxel_heuristic_has_sunlight(
|
|
|
|
-- data, voxel_reg)
|
|
|
|
-- TODO: This is a hack that doesn't even work properly
|
2014-10-20 14:05:58 +03:00
|
|
|
--local has_sunlight = (v_min < cs.y + 1)
|
|
|
|
local has_sunlight = (v_min < cs.y + 0)
|
2014-10-20 11:47:41 +03:00
|
|
|
|
|
|
|
local node_p = node:GetWorldPosition()
|
|
|
|
local scene = node.scene
|
|
|
|
|
|
|
|
local zone_node = scene:CreateChild("Zone")
|
|
|
|
local zone = zone_node:CreateComponent("Zone")
|
|
|
|
zone.boundingBox = magic.BoundingBox(
|
|
|
|
node_p - magic.Vector3(cs.x, cs.y, cs.z)/2,
|
|
|
|
node_p + magic.Vector3(cs.x, cs.y, cs.z)/2
|
|
|
|
)
|
|
|
|
if has_sunlight then
|
|
|
|
zone.ambientColor = magic.Color(0.1, 0.1, 0.1)
|
|
|
|
zone.fogColor = magic.Color(0.6, 0.7, 0.8)
|
|
|
|
else
|
|
|
|
zone.ambientColor = magic.Color(0, 0, 0)
|
2014-10-20 14:05:58 +03:00
|
|
|
--zone.fogColor = magic.Color(0, 0, 0)
|
|
|
|
zone.fogColor = magic.Color(0.6, 0.7, 0.8)
|
2014-10-20 11:47:41 +03:00
|
|
|
end
|
|
|
|
--zone.ambientColor = magic.Color(
|
|
|
|
-- math.random(), math.random(), math.random())
|
|
|
|
--zone.fogEnd = 10 + math.random() * 50
|
|
|
|
zone.fogStart = 10
|
|
|
|
zone.fogEnd = voxelworld.camera_far_clip * 1.2
|
|
|
|
--zone.ambientGradient = true
|
2014-10-20 14:05:58 +03:00
|
|
|
--]]
|
2014-10-20 11:47:41 +03:00
|
|
|
end)
|
|
|
|
|
|
|
|
return M
|
|
|
|
-- vim: set noet ts=4 sw=4:
|