Move stuff from games/digger to builtin/ground_plane_lighting

This commit is contained in:
Perttu Ahola 2014-10-20 11:47:41 +03:00
parent adbb3290e7
commit 4313287a10
7 changed files with 298 additions and 112 deletions

View File

@ -0,0 +1,45 @@
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
#pragma once
#include "interface/event.h"
#include "interface/server.h"
#include "interface/module.h"
// TODO: Clean up
#include "interface/voxel.h"
#include <PolyVoxCore/Vector.h>
#include <PolyVoxCore/Region.h>
#include <PolyVoxCore/RawVolume.h>
#include <functional>
// TODO: Clean up
namespace Urho3D
{
class Context;
class Scene;
class Node;
}
namespace ground_plane_lighting
{
// TODO: Clean up
namespace magic = Urho3D;
namespace pv = PolyVox;
using interface::VoxelInstance;
struct Interface
{
};
inline bool access(interface::Server *server,
std::function<void(ground_plane_lighting::Interface*)> cb)
{
return server->access_module("ground_plane_lighting",
[&](interface::Module *module){
auto *iface = (ground_plane_lighting::Interface*)
module->check_interface();
cb(iface);
});
}
}
// vim: set noet ts=4 sw=4:

View File

@ -0,0 +1,63 @@
-- 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")
local voxelworld = require("buildat/module/voxelworld")
local M = {}
voxelworld.sub_geometry_update(function(node)
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
local v = yst_volume:get_voxel_at(0, 0, 0)
--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
local has_sunlight = (v_min < cs.y + 1)
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)
zone.fogColor = magic.Color(0, 0, 0)
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
end)
return M
-- vim: set noet ts=4 sw=4:

View File

@ -0,0 +1,182 @@
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
#include "ground_plane_lighting/api.h"
// TODO: Clean up
#include "network/api.h"
#include "client_file/api.h"
#include "voxelworld/api.h"
#include "replicate/api.h"
#include "core/log.h"
#include "interface/module.h"
#include "interface/server.h"
#include "interface/event.h"
#include "interface/mesh.h"
#include "interface/voxel.h"
#include "interface/block.h"
#include "interface/voxel_volume.h"
#include <PolyVoxCore/RawVolume.h>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/types/string.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#include <Node.h>
#pragma GCC diagnostic pop
// TODO: Clean up
using interface::Event;
namespace magic = Urho3D;
namespace pv = PolyVox;
using namespace Urho3D;
using interface::VoxelInstance;
// TODO: Move to a header (core/types_polyvox.h or something)
#define PV3I_FORMAT "(%i, %i, %i)"
#define PV3I_PARAMS(p) p.getX(), p.getY(), p.getZ()
namespace ground_plane_lighting {
// Y-seethrough commit hook
struct YstCommitHook: public voxelworld::CommitHook
{
static constexpr const char *MODULE = "YstCommitHook";
ss_ m_yst_data;
void in_thread(voxelworld::Interface *ivoxelworld,
const pv::Vector3DInt32 &chunk_p,
sp_<pv::RawVolume<VoxelInstance>> volume)
{
interface::VoxelRegistry *voxel_reg = ivoxelworld->get_voxel_reg();
const auto &chunk_size_voxels = ivoxelworld->get_chunk_size_voxels();
int w = chunk_size_voxels.getX();
int h = chunk_size_voxels.getY();
int d = chunk_size_voxels.getZ();
pv::Region yst_region(0, 0, 0, w, 0, d);
// Y-seethrough (value: Lowest Y where light can go)
// If chunk above does not pass light to this chunk, value=d+1
up_<pv::RawVolume<uint8_t>> yst_volume(
new pv::RawVolume<uint8_t>(yst_region));
auto lc = yst_region.getLowerCorner();
auto uc = yst_region.getUpperCorner();
for(int z = 0; z < d; z++){
for(int x = 0; x <= w; x++){
// TODO: Read initial value from the chunk above
int y;
for(y = d; y >= 0; y--){
VoxelInstance v = volume->getVoxelAt(x+1, y+1, z+1);
const auto *def = voxel_reg->get_cached(v);
if(!def)
throw Exception(ss_()+"Undefined voxel: "+itos(v.getId()));
bool light_passes = (!def || !def->physically_solid);
if(!light_passes)
break;
}
y++;
yst_volume->setVoxelAt(x, 0, z, y);
}
}
m_yst_data = interface::serialize_volume_compressed(*yst_volume);
}
void in_scene(voxelworld::Interface *ivoxelworld,
const pv::Vector3DInt32 &chunk_p, magic::Node *n)
{
if(m_yst_data.empty()){
// Can happen if in_thread() fails
log_w(MODULE, "Commit hook in_scene executed without in_thread");
return;
}
n->SetVar(StringHash("gpl_voxel_yst_data"), Variant(
PODVector<uint8_t>((const uint8_t*)m_yst_data.c_str(),
m_yst_data.size())));
m_yst_data.clear();
}
};
struct Module: public interface::Module, public ground_plane_lighting::Interface
{
interface::Server *m_server;
Module(interface::Server *server):
interface::Module("ground_plane_lighting"),
m_server(server)
{
}
~Module()
{
}
void init()
{
m_server->sub_event(this, Event::t("core:start"));
m_server->sub_event(this, Event::t("core:unload"));
m_server->sub_event(this, Event::t("core:continue"));
m_server->sub_event(this, Event::t("network:client_connected"));
m_server->sub_event(this, Event::t("core:tick"));
m_server->sub_event(this, Event::t("client_file:files_transmitted"));
}
void event(const Event::Type &type, const Event::Private *p)
{
EVENT_VOIDN("core:start", on_start)
EVENT_VOIDN("core:unload", on_unload)
EVENT_VOIDN("core:continue", on_continue)
EVENT_TYPEN("network:client_connected", on_client_connected,
network::NewClient)
EVENT_TYPEN("core:tick", on_tick, interface::TickEvent)
EVENT_TYPEN("client_file:files_transmitted", on_files_transmitted,
client_file::FilesTransmitted)
}
void on_start()
{
voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld)
{
ivoxelworld->add_commit_hook(
up_<YstCommitHook>(new YstCommitHook()));
});
}
void on_unload()
{
}
void on_continue()
{
}
void on_client_connected(const network::NewClient &client_connected)
{
}
void on_tick(const interface::TickEvent &event)
{
}
void on_files_transmitted(const client_file::FilesTransmitted &event)
{
int peer = event.recipient;
network::access(m_server, [&](network::Interface *inetwork){
inetwork->send(peer, "core:run_script",
"require(\"buildat/module/ground_plane_lighting\")");
});
}
// Interface
void* get_interface()
{
return dynamic_cast<Interface*>(this);
}
};
extern "C" {
BUILDAT_EXPORT void* createModule_ground_plane_lighting(
interface::Server *server){
return (void*)(new Module(server));
}
}
}
// vim: set noet ts=4 sw=4:

View File

@ -0,0 +1,6 @@
{
"dependencies": [
{"module": "voxelworld"},
{"module": "client_lua"}
]
}

View File

@ -41,57 +41,6 @@ do
end end
--]] --]]
voxelworld.sub_geometry_update(function(node)
local yst_data = node:GetVar("main_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
local v = yst_volume:get_voxel_at(0, 0, 0)
--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
local has_sunlight = (v_min < cs.y + 1)
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)
zone.fogColor = magic.Color(0, 0, 0)
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
end)
-- Add lights -- Add lights
do do
--[[ --[[

View File

@ -54,63 +54,6 @@ namespace digger {
using namespace Urho3D; using namespace Urho3D;
// Y-seethrough commit hook
struct YstCommitHook: public voxelworld::CommitHook
{
static constexpr const char *MODULE = "YstCommitHook";
ss_ m_yst_data;
void in_thread(voxelworld::Interface *ivoxelworld,
const pv::Vector3DInt32 &chunk_p,
sp_<pv::RawVolume<VoxelInstance>> volume)
{
interface::VoxelRegistry *voxel_reg = ivoxelworld->get_voxel_reg();
const auto &chunk_size_voxels = ivoxelworld->get_chunk_size_voxels();
int w = chunk_size_voxels.getX();
int h = chunk_size_voxels.getY();
int d = chunk_size_voxels.getZ();
pv::Region yst_region(0, 0, 0, w, 0, d);
// Y-seethrough (value: Lowest Y where light can go)
// If chunk above does not pass light to this chunk, value=d+1
up_<pv::RawVolume<uint8_t>> yst_volume(
new pv::RawVolume<uint8_t>(yst_region));
auto lc = yst_region.getLowerCorner();
auto uc = yst_region.getUpperCorner();
for(int z = 0; z < d; z++){
for(int x = 0; x <= w; x++){
// TODO: Read initial value from the chunk above
int y;
for(y = d; y >= 0; y--){
VoxelInstance v = volume->getVoxelAt(x+1, y+1, z+1);
const auto *def = voxel_reg->get_cached(v);
if(!def)
throw Exception(ss_()+"Undefined voxel: "+itos(v.getId()));
bool light_passes = (!def || !def->physically_solid);
if(!light_passes)
break;
}
y++;
yst_volume->setVoxelAt(x, 0, z, y);
}
}
m_yst_data = interface::serialize_volume_compressed(*yst_volume);
}
void in_scene(voxelworld::Interface *ivoxelworld,
const pv::Vector3DInt32 &chunk_p, magic::Node *n)
{
if(m_yst_data.empty()){
// Can happen if in_thread() fails
log_w(MODULE, "Commit hook in_scene executed without in_thread");
return;
}
n->SetVar(StringHash("main_voxel_yst_data"), Variant(
PODVector<uint8_t>((const uint8_t*)m_yst_data.c_str(),
m_yst_data.size())));
m_yst_data.clear();
}
};
struct Module: public interface::Module struct Module: public interface::Module
{ {
interface::Server *m_server; interface::Server *m_server;
@ -156,9 +99,6 @@ struct Module: public interface::Module
{ {
voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld) voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld)
{ {
ivoxelworld->add_commit_hook(
up_<YstCommitHook>(new YstCommitHook()));
interface::VoxelRegistry *voxel_reg = ivoxelworld->get_voxel_reg(); interface::VoxelRegistry *voxel_reg = ivoxelworld->get_voxel_reg();
{ {
interface::VoxelDefinition vdef; interface::VoxelDefinition vdef;

View File

@ -4,6 +4,7 @@
{"module": "client_lua"}, {"module": "client_lua"},
{"module": "client_data"}, {"module": "client_data"},
{"module": "replicate"}, {"module": "replicate"},
{"module": "voxelworld"} {"module": "voxelworld"},
{"module": "ground_plane_lighting"}
] ]
} }