Move stuff from games/digger to builtin/ground_plane_lighting
This commit is contained in:
parent
adbb3290e7
commit
4313287a10
45
builtin/ground_plane_lighting/api.h
Normal file
45
builtin/ground_plane_lighting/api.h
Normal 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:
|
63
builtin/ground_plane_lighting/client_lua/module.lua
Normal file
63
builtin/ground_plane_lighting/client_lua/module.lua
Normal 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:
|
182
builtin/ground_plane_lighting/ground_plane_lighting.cpp
Normal file
182
builtin/ground_plane_lighting/ground_plane_lighting.cpp
Normal 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:
|
6
builtin/ground_plane_lighting/meta.json
Normal file
6
builtin/ground_plane_lighting/meta.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": [
|
||||||
|
{"module": "voxelworld"},
|
||||||
|
{"module": "client_lua"}
|
||||||
|
]
|
||||||
|
}
|
@ -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
|
||||||
--[[
|
--[[
|
||||||
|
@ -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;
|
||||||
|
@ -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"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user