From bc4ac09c1a984cfd532370f0698eca94e5d981d5 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 19 Oct 2014 17:31:32 +0300 Subject: [PATCH] builtin/voxelworld and things: Transmit VoxelRegistry over network and deserialize it in Lua --- builtin/voxelworld/client_lua/module.lua | 10 +- builtin/voxelworld/voxelworld.cpp | 2 + client/api.lua | 6 +- doc/whynot.txt | 3 + games/digger/main/main.cpp | 100 +++++++++++++ src/impl/atlas.cpp | 3 + src/impl/mesh.cpp | 15 +- src/impl/voxel.cpp | 177 +++++++---------------- src/interface/atlas_cereal.h | 24 +++ src/interface/urho3d_cereal.h | 26 ++++ src/interface/voxel.h | 23 +-- src/interface/voxel_cereal.h | 42 ++++++ src/lua_bindings/atlas.cpp | 2 +- src/lua_bindings/voxel.cpp | 4 +- 14 files changed, 293 insertions(+), 144 deletions(-) create mode 100644 src/interface/atlas_cereal.h create mode 100644 src/interface/urho3d_cereal.h create mode 100644 src/interface/voxel_cereal.h diff --git a/builtin/voxelworld/client_lua/module.lua b/builtin/voxelworld/client_lua/module.lua index f2f8333..76f2d66 100644 --- a/builtin/voxelworld/client_lua/module.lua +++ b/builtin/voxelworld/client_lua/module.lua @@ -40,9 +40,6 @@ local end_of_update_processing_us = 0 local voxel_reg = buildat.createVoxelRegistry() local atlas_reg = buildat.createAtlasRegistry() -log:info("voxel_reg type: "..dump(buildat.class_info(voxel_reg).name)) -log:info("atlas_reg type: "..dump(buildat.class_info(atlas_reg).name)) - M.chunk_size_voxels = nil M.section_size_chunks = nil M.section_size_voxels = nil @@ -87,6 +84,10 @@ function M.init() M.chunk_size_voxels:mul_components(M.section_size_chunks) end) + buildat.sub_packet("voxelworld:voxel_registry", function(data) + voxel_reg:deserialize(data) + end) + buildat.sub_packet("voxelworld:node_voxel_data_updated", function(data) local values = cereal.binary_input(data, {"object", {"node_id", "int32_t"}, @@ -204,6 +205,9 @@ function M.init() magic.SubscribeToEvent("Update", function(event_type, event_data) buildat.profiler_block_begin("Buildat|voxelworld:update") + -- Required for handling device resets (eg. fullscreen toggle) + atlas_reg:update() + --local t0 = buildat.get_time_us() --local dt = event_data:GetFloat("TimeStep") update_counter = update_counter + 1 diff --git a/builtin/voxelworld/voxelworld.cpp b/builtin/voxelworld/voxelworld.cpp index 1e5c690..345ca7f 100644 --- a/builtin/voxelworld/voxelworld.cpp +++ b/builtin/voxelworld/voxelworld.cpp @@ -458,6 +458,8 @@ struct Module: public interface::Module, public voxelworld::Interface } network::access(m_server, [&](network::Interface *inetwork){ inetwork->send(peer, "voxelworld:init", os.str()); + inetwork->send(peer, "voxelworld:voxel_registry", + m_voxel_reg->serialize()); }); } diff --git a/client/api.lua b/client/api.lua index ad08efc..b397568 100644 --- a/client/api.lua +++ b/client/api.lua @@ -12,11 +12,11 @@ buildat.safe.disconnect = __buildat_disconnect buildat.safe.get_time_us = __buildat_get_time_us buildat.safe.profiler_block_begin = __buildat_profiler_block_begin buildat.safe.profiler_block_end = __buildat_profiler_block_end -buildat.safe.createVoxelRegistry = createVoxelRegistry -buildat.safe.createAtlasRegistry = createAtlasRegistry +buildat.safe.createVoxelRegistry = __buildat_createVoxelRegistry +buildat.safe.createAtlasRegistry = __buildat_createAtlasRegistry -- NOTE: Maybe not actually safe -buildat.safe.class_info = class_info -- Luabind class_info() +--buildat.safe.class_info = class_info -- Luabind class_info() buildat.safe.SpatialUpdateQueue = function() local internal = __buildat_SpatialUpdateQueue() diff --git a/doc/whynot.txt b/doc/whynot.txt index 75fb526..048edaa 100644 --- a/doc/whynot.txt +++ b/doc/whynot.txt @@ -6,3 +6,6 @@ Why not use protobuf? Why not detect -DURHO3D_64BIT automatically in the build system? - It's not possible +Why not use cereal's versioning system? +- It doesn't support forward compatibility + diff --git a/games/digger/main/main.cpp b/games/digger/main/main.cpp index 0cf6ee6..c63711d 100644 --- a/games/digger/main/main.cpp +++ b/games/digger/main/main.cpp @@ -68,6 +68,106 @@ struct Module: public interface::Module void init() { + voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld) + { + interface::VoxelRegistry *voxel_reg = + ivoxelworld->get_voxel_reg(); + { + interface::VoxelDefinition vdef; + vdef.name.block_name = "air"; + vdef.name.segment_x = 0; + vdef.name.segment_y = 0; + vdef.name.segment_z = 0; + vdef.name.rotation_primary = 0; + vdef.name.rotation_secondary = 0; + vdef.handler_module = ""; + for(size_t i = 0; i < 6; i++){ + interface::AtlasSegmentDefinition &seg = vdef.textures[i]; + seg.resource_name = ""; + seg.total_segments = magic::IntVector2(0, 0); + seg.select_segment = magic::IntVector2(0, 0); + } + vdef.edge_material_id = interface::EDGEMATERIALID_EMPTY; + voxel_reg->add_voxel(vdef); // id 1 + } + { + interface::VoxelDefinition vdef; + vdef.name.block_name = "rock"; + vdef.name.segment_x = 0; + vdef.name.segment_y = 0; + vdef.name.segment_z = 0; + vdef.name.rotation_primary = 0; + vdef.name.rotation_secondary = 0; + vdef.handler_module = ""; + for(size_t i = 0; i < 6; i++){ + interface::AtlasSegmentDefinition &seg = vdef.textures[i]; + seg.resource_name = "main/rock.png"; + seg.total_segments = magic::IntVector2(1, 1); + seg.select_segment = magic::IntVector2(0, 0); + } + vdef.edge_material_id = interface::EDGEMATERIALID_GROUND; + vdef.physically_solid = true; + voxel_reg->add_voxel(vdef); // id 2 + } + { + interface::VoxelDefinition vdef; + vdef.name.block_name = "dirt"; + vdef.name.segment_x = 0; + vdef.name.segment_y = 0; + vdef.name.segment_z = 0; + vdef.name.rotation_primary = 0; + vdef.name.rotation_secondary = 0; + vdef.handler_module = ""; + for(size_t i = 0; i < 6; i++){ + interface::AtlasSegmentDefinition &seg = vdef.textures[i]; + seg.resource_name = "main/dirt.png"; + seg.total_segments = magic::IntVector2(1, 1); + seg.select_segment = magic::IntVector2(0, 0); + } + vdef.edge_material_id = interface::EDGEMATERIALID_GROUND; + vdef.physically_solid = true; + voxel_reg->add_voxel(vdef); // id 3 + } + { + interface::VoxelDefinition vdef; + vdef.name.block_name = "grass"; + vdef.name.segment_x = 0; + vdef.name.segment_y = 0; + vdef.name.segment_z = 0; + vdef.name.rotation_primary = 0; + vdef.name.rotation_secondary = 0; + vdef.handler_module = ""; + for(size_t i = 0; i < 6; i++){ + interface::AtlasSegmentDefinition &seg = vdef.textures[i]; + seg.resource_name = "main/grass.png"; + seg.total_segments = magic::IntVector2(1, 1); + seg.select_segment = magic::IntVector2(0, 0); + } + vdef.edge_material_id = interface::EDGEMATERIALID_GROUND; + vdef.physically_solid = true; + voxel_reg->add_voxel(vdef); // id 4 + } + { + interface::VoxelDefinition vdef; + vdef.name.block_name = "leaves"; + vdef.name.segment_x = 0; + vdef.name.segment_y = 0; + vdef.name.segment_z = 0; + vdef.name.rotation_primary = 0; + vdef.name.rotation_secondary = 0; + vdef.handler_module = ""; + for(size_t i = 0; i < 6; i++){ + interface::AtlasSegmentDefinition &seg = vdef.textures[i]; + seg.resource_name = "main/leaves.png"; + seg.total_segments = magic::IntVector2(1, 1); + seg.select_segment = magic::IntVector2(0, 0); + } + vdef.edge_material_id = interface::EDGEMATERIALID_GROUND; + vdef.physically_solid = true; + voxel_reg->add_voxel(vdef); // id 5 + } + }); + m_server->sub_event(this, Event::t("core:start")); m_server->sub_event(this, Event::t("core:continue")); m_server->sub_event(this, Event::t("core:tick")); diff --git a/src/impl/atlas.cpp b/src/impl/atlas.cpp index fcb31e9..9846467 100644 --- a/src/impl/atlas.cpp +++ b/src/impl/atlas.cpp @@ -69,6 +69,9 @@ struct CAtlasRegistry: public AtlasRegistry m_defs.resize(m_defs.size()+1); atlas_def = &m_defs[m_defs.size()-1]; atlas_def->id = m_defs.size()-1; + if(segment_def.total_segments.x_ == 0 || + segment_def.total_segments.y_ == 0) + throw Exception("segment_def.total_segments is zero"); // Calculate segment resolution magic::IntVector2 seg_res( seg_img_size.x_ / segment_def.total_segments.x_, diff --git a/src/impl/mesh.cpp b/src/impl/mesh.cpp index b08f294..9a04185 100644 --- a/src/impl/mesh.cpp +++ b/src/impl/mesh.cpp @@ -195,6 +195,10 @@ public: m_voxel_reg->get_cached(back); const interface::CachedVoxelDefinition *front_def = m_voxel_reg->get_cached(front); + if(!back_def) + throw Exception(ss_()+"Undefined voxel: back="+itos(back.getId())); + if(!front_def) + throw Exception(ss_()+"Undefined voxel: front="+itos(front.getId())); if(!back_def || !back_def->physically_solid) return false; if(!front_def || !front_def->physically_solid){ @@ -300,9 +304,13 @@ public: m_voxel_reg->get_cached(back); const interface::CachedVoxelDefinition *front_def = m_voxel_reg->get_cached(front); - if(!back_def){ + if(!back_def) + throw Exception(ss_()+"Undefined voxel: back="+itos(back.getId())); + if(!front_def) + throw Exception(ss_()+"Undefined voxel: front="+itos(front.getId())); + /*if(!back_def){ return false; - } + }*/ else if(back_def->face_draw_type == interface::FaceDrawType::NEVER){ return false; } @@ -414,7 +422,8 @@ void preload_textures(pv::RawVolume &volume, VoxelInstance v = volume.getVoxelAt(x, y, z); const interface::CachedVoxelDefinition *def = voxel_reg->get_cached(v, atlas_reg); - (void)def; // Unused + if(!def) + throw Exception(ss_()+"Undefined voxel: "+itos(v.getId())); } } } diff --git a/src/impl/voxel.cpp b/src/impl/voxel.cpp index f2397f0..7d94c71 100644 --- a/src/impl/voxel.cpp +++ b/src/impl/voxel.cpp @@ -2,6 +2,9 @@ // Copyright 2014 Perttu Ahola #include "interface/voxel.h" #include "core/log.h" +#include "interface/voxel_cereal.h" +#include +#include #define MODULE "voxel" namespace std { @@ -24,9 +27,10 @@ ss_ VoxelName::dump() const std::ostringstream os(std::ios::binary); os<<"VoxelName("; os<<"block_name="< get_all() + { + sv_ result; + result.insert(result.end(), m_defs.begin()+1, m_defs.end()); + return result; } VoxelTypeId add_voxel(const VoxelDefinition &def) { VoxelTypeId id = m_defs.size(); + if(def.id != VOXELTYPEID_UNDEFINED && id != def.id) + throw Exception(ss_()+"add_voxel(): def.id="+itos(def.id)+ + "; should be "+itos(id)); // NOTE: This invalidates all previous pointers to cache entries that // were given out m_defs.resize(id + 1); @@ -272,29 +198,6 @@ struct CVoxelRegistry: public VoxelRegistry } // Caller sets cache.textures_valid = true } - - void serialize(std::ostream &os) - { - // TODO - } - - void deserialize(std::istream &is) - { - // TODO - } - - ss_ serialize() - { - std::ostringstream os(std::ios::binary); - serialize(os); - return os.str(); - } - - void deserialize(const ss_ &s) - { - std::istringstream is(s, std::ios::binary); - deserialize(is); - } }; VoxelRegistry* createVoxelRegistry() @@ -302,5 +205,35 @@ VoxelRegistry* createVoxelRegistry() return new CVoxelRegistry(); } +void VoxelRegistry::serialize(std::ostream &os) +{ + sv_ defs = get_all(); + cereal::PortableBinaryOutputArchive archive(os); + archive(defs); } + +void VoxelRegistry::deserialize(std::istream &is) +{ + sv_ defs; + cereal::PortableBinaryInputArchive archive(is); + archive(defs); + clear(); + for(auto &def : defs) + add_voxel(def); +} + +ss_ VoxelRegistry::serialize() +{ + std::ostringstream os(std::ios::binary); + serialize(os); + return os.str(); +} + +void VoxelRegistry::deserialize(const ss_ &s) +{ + std::istringstream is(s, std::ios::binary); + deserialize(is); +} + +} // interface // vim: set noet ts=4 sw=4: diff --git a/src/interface/atlas_cereal.h b/src/interface/atlas_cereal.h new file mode 100644 index 0000000..d60724a --- /dev/null +++ b/src/interface/atlas_cereal.h @@ -0,0 +1,24 @@ +// http://www.apache.org/licenses/LICENSE-2.0 +// Copyright 2014 Perttu Ahola +#pragma once +#include "core/types.h" +#include "interface/atlas.h" +#include "interface/urho3d_cereal.h" +#include + +namespace interface +{ + template + void serialize(Archive &archive, AtlasSegmentDefinition &v) + { + uint8_t version = 1; + archive( + version, + v.resource_name, + v.total_segments, + v.select_segment, + v.lod_simulation + ); + } +} +// vim: set noet ts=4 sw=4: diff --git a/src/interface/urho3d_cereal.h b/src/interface/urho3d_cereal.h new file mode 100644 index 0000000..a4223b0 --- /dev/null +++ b/src/interface/urho3d_cereal.h @@ -0,0 +1,26 @@ +// http://www.apache.org/licenses/LICENSE-2.0 +// Copyright 2014 Perttu Ahola +#pragma once +#include "core/types.h" +#include +#include +#include + +namespace cereal +{ + template + void save(Archive &archive, const Urho3D::IntVector2 &v) + { + archive((int32_t)v.x_); + archive((int32_t)v.y_); + } + template + void load(Archive &archive, Urho3D::IntVector2 &v) + { + int32_t x, y; + archive(x, y); + v.x_ = x; + v.y_ = y; + } +} +// vim: set noet ts=4 sw=4: diff --git a/src/interface/voxel.h b/src/interface/voxel.h index 58acca0..6508f2c 100644 --- a/src/interface/voxel.h +++ b/src/interface/voxel.h @@ -16,11 +16,13 @@ namespace interface struct VoxelName { ss_ block_name; // Name of the block this was instanced from - uint segment_x = 0; // Which segment of the block this was instanced from - uint segment_y = 0; - uint segment_z = 0; - uint rotation_primary = 0; // 4 possible rotations when looking at a face - uint rotation_secondary = 0; // 6 possible directions for a face to point to + uint8_t segment_x = 0; // Which segment of the block this was instanced from + uint8_t segment_y = 0; + uint8_t segment_z = 0; + // 4 possible rotations when looking at a face + uint8_t rotation_primary = 0; + // 6 possible directions for a face to point to + uint8_t rotation_secondary = 0; ss_ dump() const; bool operator==(const VoxelName &other) const; @@ -81,6 +83,9 @@ namespace interface { virtual ~VoxelRegistry(){} + virtual void clear() = 0; + virtual sv_ get_all() = 0; + virtual VoxelTypeId add_voxel(const VoxelDefinition &def) = 0; virtual const VoxelDefinition* get(const VoxelTypeId &id) = 0; @@ -92,10 +97,10 @@ namespace interface virtual const CachedVoxelDefinition* get_cached(const VoxelInstance &v, AtlasRegistry *atlas_reg = nullptr) = 0; - virtual void serialize(std::ostream &os) = 0; - virtual void deserialize(std::istream &is) = 0; - virtual ss_ serialize() = 0; - virtual void deserialize(const ss_ &s) = 0; + void serialize(std::ostream &os); + void deserialize(std::istream &is); + ss_ serialize(); + void deserialize(const ss_ &s); // TODO: Ability to track changes (just some kind of set_dirty()?) }; diff --git a/src/interface/voxel_cereal.h b/src/interface/voxel_cereal.h new file mode 100644 index 0000000..8e05d5c --- /dev/null +++ b/src/interface/voxel_cereal.h @@ -0,0 +1,42 @@ +// http://www.apache.org/licenses/LICENSE-2.0 +// Copyright 2014 Perttu Ahola +#pragma once +#include "core/types.h" +#include "interface/voxel.h" +#include "interface/atlas_cereal.h" +#include + +namespace interface +{ + template + void serialize(Archive &archive, VoxelName &v) + { + uint8_t version = 1; + archive( + version, + v.block_name, + v.segment_x, + v.segment_y, + v.segment_z, + v.rotation_primary, + v.rotation_secondary + ); + } + + template + void serialize(Archive &archive, VoxelDefinition &v) + { + uint8_t version = 1; + archive( + version, + v.name, + v.id, + v.textures, + v.handler_module, + v.face_draw_type, + v.edge_material_id, + v.physically_solid + ); + } +} +// vim: set noet ts=4 sw=4: diff --git a/src/lua_bindings/atlas.cpp b/src/lua_bindings/atlas.cpp index 0d8b221..52a6326 100644 --- a/src/lua_bindings/atlas.cpp +++ b/src/lua_bindings/atlas.cpp @@ -37,7 +37,7 @@ void init_atlas(lua_State *L) module(L)[ class_, sp_>("AtlasRegistry") .def("update", &AtlasRegistry::update), - def("createAtlasRegistry", &createAtlasRegistry) + def("__buildat_createAtlasRegistry", &createAtlasRegistry) ]; } diff --git a/src/lua_bindings/voxel.cpp b/src/lua_bindings/voxel.cpp index 017aff0..87e0fba 100644 --- a/src/lua_bindings/voxel.cpp +++ b/src/lua_bindings/voxel.cpp @@ -4,8 +4,6 @@ #include "core/log.h" #include "interface/voxel.h" #include -#include -#include #define MODULE "lua_bindings" using interface::VoxelInstance; @@ -29,7 +27,7 @@ void init_voxel(lua_State *L) &VoxelRegistry::serialize) .def("deserialize", (void(VoxelRegistry::*) (const ss_ &)) &VoxelRegistry::deserialize), - def("createVoxelRegistry", &createVoxelRegistry) + def("__buildat_createVoxelRegistry", &createVoxelRegistry) ]; }