master
Perttu Ahola 2014-10-20 17:15:32 +03:00
parent a71a4c56ef
commit 265860cf62
8 changed files with 285 additions and 41 deletions

View File

@ -5,11 +5,134 @@ local dump = buildat.dump
local log = buildat.Logger("ground_plane_lighting")
local magic = require("buildat/extension/urho3d")
local replicate = require("buildat/extension/replicate")
local cereal = require("buildat/extension/cereal")
local voxelworld = require("buildat/module/voxelworld")
local M = {}
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)
log:verbose("set_dark_zones(): sector_p="..sector_p:dump())
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
for x = 0, M.zone_size.x - 1 do
for y = 0, M.zone_size.y - 1 do
local x_in_sector = x + x_div * M.zone_size.x
local y_in_sector = y + y_div * M.zone_size.y
local v = yst_volume:get_voxel_at(
x_in_sector, 0, y_in_sector)
log:warning("v.int32="..v.int32)
if v.int32 < yst_min then
yst_min = v.int32
end
end
end
local y_min = -10000
local y_max = yst_min
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
)
log:verbose("Adding zone at lc=("..lc.x..", "..lc.y..", "..lc.z..
"), 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.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
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()
log:verbose("region: ("..region.x0..", "..region.y0..", "..region.z0..", "..
region.x1..", "..region.y1..", "..region.z1..")")
local sector_p = buildat.Vector2(values.p)
set_dark_zones(sector_p, volume)
end)
-- TODO: Remove
voxelworld.sub_geometry_update(function(node)
---[[
--[[
local cs = voxelworld.chunk_size_voxels
local node_p = node:GetWorldPosition()
local scene = node.scene

View File

@ -17,6 +17,7 @@
#include "interface/voxel_volume.h"
#include "interface/polyvox_numeric.h"
#include "interface/polyvox_cereal.h"
#include "interface/os.h"
#include <PolyVoxCore/RawVolume.h>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/types/string.hpp>
@ -56,6 +57,7 @@ namespace ground_plane_lighting {
// Y-seethrough data of a sector (size defined by voxelworld)
struct YSTSector
{
static constexpr const char *MODULE = "YSTSector";
pv::Vector<2, int16_t> sector_p; // In sectors
pv::Vector<2, int16_t> sector_size; // In voxels
sp_<pv::RawVolume<int32_t>> volume; // Voxel columns (region in global coords)
@ -69,16 +71,19 @@ struct YSTSector
sector_size(sector_size),
volume(new pv::RawVolume<int32_t>(pv::Region(
sector_p.getX() * sector_size.getX(),
1,
sector_p.getZ() * sector_size.getZ(),
0,
sector_p.getY() * sector_size.getY(),
sector_p.getX() * sector_size.getX() + sector_size.getX() - 1,
1,
sector_p.getZ() * sector_size.getZ() + sector_size.getZ() - 1
0,
sector_p.getY() * sector_size.getY() + sector_size.getY() - 1
)))
{
pv::Region region = volume->getEnclosingRegion();
auto lc = region.getLowerCorner();
auto uc = region.getUpperCorner();
/*log_v(MODULE, "YSTSector volume lc=" PV3I_FORMAT ", uc=" PV3I_FORMAT
", size=%zu", PV3I_PARAMS(lc), PV3I_PARAMS(uc),
volume->m_dataSize);*/
for(int z = lc.getZ(); z <= uc.getZ(); z++){
for(int x = lc.getX(); x <= uc.getX(); x++){
volume->setVoxelAt(x, 0, z, INT_MIN);
@ -196,7 +201,7 @@ struct YstCommitHook: public voxelworld::CommitHook
//log_nv(MODULE, "%i, ", yst);
int y = h - 1;
for(; y >= 0; y--){
VoxelInstance v = volume->getVoxelAt(x+1, y+1, z+1);
VoxelInstance v = volume->getVoxelAt(x, y, z);
const auto *def = voxel_reg->get_cached(v);
if(!def)
throw Exception(ss_()+"Undefined voxel: "+itos(v.getId()));
@ -205,10 +210,13 @@ struct YstCommitHook: public voxelworld::CommitHook
break;
}
y++;
if(y == 0){
log_w(MODULE, "YST should propagate down");
// TODO: Continue to lower chunks until solid found
}
int32_t yst1 = lc.getY() + y;
log_nv(MODULE, "%i -> %i, ", yst0, yst1);
igpl->set_yst(lc.getX() + x, lc.getZ() + z, yst1);
// TODO: If y==0, continue to lower chunk
}
}
log_v(MODULE, "]");
@ -287,24 +295,24 @@ struct Module: public interface::Module, public ground_plane_lighting::Interface
void on_tick(const interface::TickEvent &event)
{
if(!m_global_yst->m_dirty_sectors.empty()){
sv_<std::tuple<pv::Vector<2, int16_t>, ss_>> sector_data;
for(YSTSector *sector : m_global_yst->m_dirty_sectors){
sv_<YSTSector*> dirty_sectors;
dirty_sectors.swap(m_global_yst->m_dirty_sectors);
for(YSTSector *sector : dirty_sectors){
ss_ s = interface::serialize_volume_compressed(*sector->volume);
std::tuple<pv::Vector<2, int16_t>, ss_> thing(sector->sector_p, s);
sector_data.push_back(thing);
std::ostringstream os(std::ios::binary);
{
cereal::PortableBinaryOutputArchive ar(os);
ar(sector->sector_p);
ar(s);
}
network::access(m_server, [&](network::Interface *inetwork){
sv_<network::PeerInfo::Id> peers = inetwork->list_peers();
for(auto &peer : peers){
inetwork->send(peer, "ground_plane_lighting:update",
os.str());
}
});
}
m_global_yst->m_dirty_sectors.clear();
std::ostringstream os(std::ios::binary);
{
cereal::PortableBinaryOutputArchive ar(os);
ar(sector_data);
}
network::access(m_server, [&](network::Interface *inetwork){
sv_<network::PeerInfo::Id> peers = inetwork->list_peers();
for(auto &peer : peers)
inetwork->send(peer, "ground_plane_lighting:update", os.str());
});
}
}
@ -323,6 +331,25 @@ struct Module: public interface::Module, public ground_plane_lighting::Interface
network::access(m_server, [&](network::Interface *inetwork){
inetwork->send(peer, "ground_plane_lighting:init", os.str());
});
send_initial_sectors(peer);
}
void send_initial_sectors(int peer)
{
for(auto &pair : m_global_yst->m_sectors){
YSTSector *sector = &pair.second;
ss_ s = interface::serialize_volume_compressed(*sector->volume);
std::ostringstream os(std::ios::binary);
{
cereal::PortableBinaryOutputArchive ar(os);
ar(sector->sector_p);
ar(s);
}
network::access(m_server, [&](network::Interface *inetwork){
inetwork->send(peer, "ground_plane_lighting:update", os.str());
});
}
}
// Interface

View File

@ -125,7 +125,7 @@ function M.init()
local lod = math.floor(1 + lod_fraction)
if lod > MAX_LOD then lod = MAX_LOD end
log:verbose("update_voxel_geometry(): lod="..lod..
log:debug("update_voxel_geometry(): lod="..lod..
", d="..math.floor(d)..", #data="..data:GetSize()..
", node="..node:GetID())
@ -139,7 +139,7 @@ function M.init()
local far_weight = nil
if d >= M.camera_far_clip * 1.4 then
log:verbose("Clearing voxel geometry outside camera far clip ("
log:debug("Clearing voxel geometry outside camera far clip ("
..M.camera_far_clip..")")
buildat.clear_voxel_geometry(node)
@ -196,7 +196,7 @@ function M.init()
local node_p = node:GetWorldPosition()
local d = (node_p - camera_p):Length()
log:verbose("update_voxel_physics(): d="..math.floor(d)..
log:debug("update_voxel_physics(): d="..math.floor(d)..
", #data="..data:GetSize()..", node="..node:GetID())
local near_trigger_d = nil
@ -205,7 +205,7 @@ function M.init()
local far_weight = nil
if d > PHYSICS_DISTANCE then
log:verbose("Clearing physics boxes outside physics distance ("..
log:debug("Clearing physics boxes outside physics distance ("..
PHYSICS_DISTANCE..")")
buildat.clear_voxel_physics_boxes(node)
@ -278,7 +278,7 @@ function M.init()
if f and f <= 1.0 then
local node_update = node_update_queue:get()
local node = replicate.main_scene:GetNode(node_update.node_id)
log:verbose("Node update #"..
log:debug("Node update #"..
node_update_queue:get_length()..
" (f="..(math.floor(f*100)/100)..""..
", fw="..(math.floor(fw*100)/100)..")"..
@ -291,7 +291,7 @@ function M.init()
end
did_update = true
else
log:verbose("Poked update #"..
log:debug("Poked update #"..
node_update_queue:get_length()..
" (f="..(math.floor((f or -1)*100)/100)..""..
", fw="..(math.floor((fw or -1)*100)/100)..")")

View File

@ -20,7 +20,8 @@ buildat.safe.createAtlasRegistry = __buildat_createAtlasRegistry
buildat.safe.Region = __buildat_Region
buildat.safe.VoxelInstance = __buildat_VoxelInstance
buildat.safe.Volume = __buildat_Volume
buildat.safe.deserialize_volume_8bit = __buildat_deserialize_volume_8bit
buildat.safe.deserialize_volume_int32 = __buildat_deserialize_volume_int32
buildat.safe.deserialize_volume_8bit = __buildat_deserialize_volume_8bit
-- NOTE: Maybe not actually safe
--buildat.safe.class_info = class_info -- Luabind class_info()
@ -209,6 +210,9 @@ local Vector3_prototype = {
x = 0,
y = 0,
z = 0,
dump = function(a)
return "("..a.x..", "..a.y..", "..a.z..")"
end,
mul_components = function(a, b)
return buildat.safe.Vector3(
a.x * b.x, a.y * b.y, a.z * b.z)
@ -229,6 +233,14 @@ local Vector3_prototype = {
return buildat.safe.Vector3(
a.x - b.x, a.y - b.y, a.z - b.z)
end,
mul = function(a, b)
return buildat.safe.Vector3(
a.x * b, a.y * b, a.z * b)
end,
div = function(a, b)
return buildat.safe.Vector3(
a.x / b, a.y / b, a.z / b)
end,
length = function(a)
return math.sqrt(a.x*a.x + a.y*a.y + a.z*a.z)
end,
@ -248,6 +260,8 @@ function buildat.safe.Vector3(x, y, z)
__index = Vector3_prototype,
__add = Vector3_prototype.add,
__sub = Vector3_prototype.sub,
__mul = Vector3_prototype.mul,
__div = Vector3_prototype.div,
})
return self
end
@ -255,6 +269,9 @@ end
local Vector2_prototype = {
x = 0,
y = 0,
dump = function(a)
return "("..a.x..", "..a.y..")"
end,
mul_components = function(a, b)
return buildat.safe.Vector2(
a.x * b.x, a.y * b.y)
@ -275,6 +292,14 @@ local Vector2_prototype = {
return buildat.safe.Vector2(
a.x - b.x, a.y - b.y)
end,
mul = function(a, b)
return buildat.safe.Vector2(
a.x * b, a.y * b)
end,
div = function(a, b)
return buildat.safe.Vector2(
a.x / b, a.y / b)
end,
length = function(a)
return math.sqrt(a.x*a.x + a.y*a.y)
end,
@ -292,6 +317,8 @@ function buildat.safe.Vector2(x, y)
__index = Vector2_prototype,
__add = Vector2_prototype.add,
__sub = Vector2_prototype.sub,
__mul = Vector2_prototype.mul,
__div = Vector2_prototype.div,
})
return self
end

View File

@ -38,6 +38,7 @@ do
--zone.fogColor = magic.Color(0, 0, 0)
zone.fogStart = 10
zone.fogEnd = FOG_END
zone.priority = -1
end
--]]

View File

@ -38,5 +38,11 @@ namespace interface
v.physically_solid
);
}
template<class Archive>
void serialize(Archive &archive, VoxelInstance &v)
{
archive(v.data);
}
}
// vim: set noet ts=4 sw=4:

View File

@ -16,7 +16,7 @@
#define GET_SANDBOX_STUFF(result_name, index, type) \
lua_getmetatable(L, index); \
lua_getfield(L, -1, "type_name"); \
if(ss_(lua_tostring(L, -1)) != #type){ \
if(!lua_isstring(L, -1) || ss_(lua_tostring(L, -1)) != #type){ \
lua_pop(L, 2); /* type_name, metatable */ \
throw Exception("Value is not a sandboxed " #type); \
} \
@ -30,9 +30,8 @@
lua_getmetatable(L, index); \
lua_getfield(L, -1, "type_name"); \
type *result_name = nullptr; \
if(ss_(lua_tostring(L, -1)) != #type){ \
if(!lua_isstring(L, -1) || ss_(lua_tostring(L, -1)) != #type){ \
lua_pop(L, 2); /* type_name, metatable */ \
throw Exception("Value is not a sandboxed " #type); \
} else { \
lua_pop(L, 1); /* type_name */ \
lua_getfield(L, -1, "unsafe"); \

View File

@ -26,16 +26,68 @@ using namespace Urho3D;
namespace lua_bindings {
#define TRY_GET_TOLUA_STUFF(result_name, index, type) \
type *result_name = nullptr; \
{ \
tolua_Error tolua_err; \
if(tolua_isusertype(L, index, #type, 0, &tolua_err)) \
result_name = (type*)tolua_tousertype(L, index, 0); \
}
int region_get_x0(const pv::Region &region){
return region.getLowerCorner().getX();
}
int region_get_y0(const pv::Region &region){
return region.getLowerCorner().getY();
}
int region_get_z0(const pv::Region &region){
return region.getLowerCorner().getZ();
}
int region_get_x1(const pv::Region &region){
return region.getUpperCorner().getX();
}
int region_get_y1(const pv::Region &region){
return region.getUpperCorner().getY();
}
int region_get_z1(const pv::Region &region){
return region.getUpperCorner().getZ();
}
// These are supposed to store the value so that negative values will be
// preserved
int32_t voxelinstance_get_int32(const VoxelInstance &v){
return (int32_t)v.data;
}
void voxelinstance_set_int32(VoxelInstance &v, int32_t d){
v.data = (uint32_t)d;
}
typedef pv::RawVolume<VoxelInstance> CommonVolume;
sp_<CommonVolume> deserialize_volume_int32(
const luabind::object &buffer_o, lua_State *L)
{
TRY_GET_SANDBOX_STUFF(buf, 1, VectorBuffer);
ss_ data;
if(buf == nullptr)
data = lua_checkcppstring(L, 1);
else
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
up_<pv::RawVolume<int32_t>> volume_int32 =
interface::deserialize_volume_int32(data);
auto region = volume_int32->getEnclosingRegion();
sp_<CommonVolume> volume(new CommonVolume(region));
auto &lc = region.getLowerCorner();
auto &uc = region.getUpperCorner();
for(int z = lc.getZ(); z <= uc.getZ(); z++){
for(int y = lc.getY(); y <= uc.getY(); y++){
for(int x = lc.getX(); x <= uc.getX(); x++){
uint8_t v = volume_int32->getVoxelAt(x, y, z);
volume->setVoxelAt(x, y, z, VoxelInstance(v));
}
}
}
return volume;
}
sp_<CommonVolume> deserialize_volume_8bit(
const luabind::object &buffer_o, lua_State *L)
{
@ -43,7 +95,7 @@ sp_<CommonVolume> deserialize_volume_8bit(
ss_ data;
if(buf == nullptr)
data = lua_tocppstring(L, 2);
data = lua_checkcppstring(L, 1);
else
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
@ -76,11 +128,19 @@ void init_voxel_volume(lua_State *L)
module(L)[
class_<pv::Region, bases<>, sp_<pv::Region>>("__buildat_Region")
.def(constructor<int, int, int, int, int ,int>())
.property("x0", &region_get_x0)
.property("y0", &region_get_y0)
.property("z0", &region_get_z0)
.property("x1", &region_get_x1)
.property("y1", &region_get_y1)
.property("z1", &region_get_z1)
,
class_<VoxelInstance>("__buildat_VoxelInstance")
.def(constructor<uint32_t>())
.def_readwrite("data", &VoxelInstance::data)
.property("id", &VoxelInstance::getId)
.property("int32", &voxelinstance_get_int32,
&voxelinstance_set_int32)
.def("get_id", &VoxelInstance::getId)
,
class_<CommonVolume, bases<>, sp_<CommonVolume>>("__buildat_Volume")
@ -92,6 +152,7 @@ void init_voxel_volume(lua_State *L)
&CommonVolume::setVoxelAt)
.def("get_enclosing_region", &CommonVolume::getEnclosingRegion)
,
LUABIND_FUNC(deserialize_volume_int32),
LUABIND_FUNC(deserialize_volume_8bit)
];
}