From 48143c5a2b166634a545ab967b0ebe5e889b4f5a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 15 Oct 2024 00:03:06 +0300 Subject: [PATCH] add fragment.crop, fragment:crop() & fix fragments rotation when width is not equal to depth & fix extra structures placements --- .../generators/demo.files/fragments/tower.vox | Bin 343 -> 241 bytes .../generators/demo.files/fragments/tree0.vox | Bin 262 -> 204 bytes .../generators/demo.files/fragments/tree1.vox | Bin 299 -> 243 bytes .../generators/demo.files/fragments/tree2.vox | Bin 291 -> 229 bytes res/scripts/stdcmd.lua | 13 +++++ src/content/loading/GeneratorLoader.cpp | 3 + .../scripting/lua/libs/libgeneration.cpp | 5 +- .../lua/usertypes/lua_type_voxelstructure.cpp | 17 +++++- src/voxels/ChunksStorage.cpp | 6 +- src/world/generator/VoxelFragment.cpp | 54 ++++++++++++++++-- src/world/generator/VoxelFragment.hpp | 1 + src/world/generator/WorldGenerator.cpp | 4 +- src/world/generator/WorldGenerator.hpp | 10 ++-- 13 files changed, 93 insertions(+), 20 deletions(-) diff --git a/res/content/base/generators/demo.files/fragments/tower.vox b/res/content/base/generators/demo.files/fragments/tower.vox index c992fe45175e0c29a4ced15147f0b5aff93f0957..a6b58857f876677a626a1989513825a0fea0b5ae 100644 GIT binary patch literal 241 zcmV3ZK0$~z zke68uuY`GznSxjYFsmDv1~5ScK7d}rg>U%~q^QBB<$ZlE&so3EMzHkyK)1VQUK_c=4~f5-7g92 r3~%*hMtXQ=Qk>2sn|?@&A1Ozx7YfRsEaV z_sg;Q&wT!${dXdf<+s(_Q*YO_XoSXgpGcE9yzAw$UmvS4nHjD*UVG=Nzy0QY)wQ>`{@yqB fMlIXQKd0<}Pn9_&u{%-w-bwMoD~?Y@Rz-Oz6on=FP6{U zMGfb>nmpo<`5Qk&jMlN>7&(*H`38Tgw$xXxm$Yl&rPOb(uje~1^}Gbjz4?cn&?`M0 zc9T4kpJqY;z@QCvax|j#K`$+JC$0BlbB`2B=Zo!lAwU0C*rEVO#*TXOUly)W{AK1J G2LJ$$?_*g2 literal 262 zcmV+h0r~zPiwFp>2=8V919Wm_WiT#wZ+HOh*UhTJFc5~}N#ddhH{OUh;L1CZs#z4P zfd;C0^`{jS1UF`a@#p2CErrfBgnlV8tEEUEPQHy|o#3k(Hz_^_0A-MW;CGRKpd9TE zOIuI=fpnVujkRVtr}oHGKe=2rJv8;AtOYc*-)*Vv*at^S{g{8_+|xbmT@ShSNE?HG z9)J|@kbmvFbFCk#`Oj7V>Ny0oO77ott{eyI08imfUU*@Vt7>ZYsyhMRRA{o)wHwwhk=T3`3W!?8Jgv2He!-gmJH2XRLJ M0gAB5;$J`j0G3IA9smFU diff --git a/res/content/base/generators/demo.files/fragments/tree1.vox b/res/content/base/generators/demo.files/fragments/tree1.vox index 7dda751dfcc3095bd7f6523019ef26af1fc59f9e..6c2aec445a987c1e61a2b8b09666ae6066f47239 100644 GIT binary patch literal 243 zcmVhiwFP!000001MQdL3WFdJ$4?#1Sg$hny|=M;A7U*bp^ZKLY#^-B=`2SK z;8&b{WtcFePd5+R7c@&K4t%|3&qDhF&7`$*X_jP ze0+R9ZcfZI`=oSn?7nZOWTR`q$@;OE`54A)KQ*CrnR8xzHTs4XJh15Z|xZL%PJ~vVtg2TNb}q1WgI_7uHAakqJp+6@@6rKew8 z5SFrqHWQqRe|{(kPE_!lMBUS)$e7+^pT!3Oe&E85`8@!zLH>d5BLBd4k$+&lG=F#e z#a4>`0oc&w*DLGiF+TIpA7*S-jrmtoTQbIFotyTW{xRoY`y9a1^mCtA&A;x8Hh+J= zhwr^Z(?2ZNAEK_ciQG)El z+JEUEOJBcceJS#fwX=Nxt?RYV4*&oF0000000000uo80U)A8lu)V{_nzG+0{n1;A- xyP>(A4i0UO`?r*yo4fg_kL@^}oV$-GKJ3DM*vS}&+@+HQCua}2>!n{%0092&n@9iv diff --git a/res/content/base/generators/demo.files/fragments/tree2.vox b/res/content/base/generators/demo.files/fragments/tree2.vox index 98fc3bef1ffdf3fc90a02b808229d7e6cb64fe3e..0aac534c37676823ec8fe2ea1c9e1b1c7da122ca 100644 GIT binary patch literal 229 zcmVgf0R>C3Clp1$1L_~_~_%|{ literal 291 zcmV+;0o?u{iwFP!000001MS(tYJ)%!#_`#m9xT1&*q7)FRfD4*-0Sf1q9DA7~f(2iiscfp%H* z&(~$ZSJb*3E;UR3YwH2nS+W!V3vi{cdthJW@Z+Y)*^$cpp z4%~yS`hIO~_*1w3zn*tk#{#s-t9M@Ze~)_yVB?*C0KTmAhjsn$aeV;wwpcq@=l}dW z1pIh?L)_x}0DO^O00000000000001hyC;V+A3t7B{bwo?yG}%oc}n|!n7YUF&Y>@9 p|CRH5_q6Vfsh`gWm*FQ#)SW)-PUbX~A)iEp`~r;2=8Rup003mslwbe= diff --git a/res/scripts/stdcmd.lua b/res/scripts/stdcmd.lua index ef742d5e..a2edd9b8 100644 --- a/res/scripts/stdcmd.lua +++ b/res/scripts/stdcmd.lua @@ -174,3 +174,16 @@ console.add_command( " has been saved as "..file.resolve(filename)) end ) + +console.add_command( + "fragment.crop filename:str", + "Crop fragment", + function(args, kwargs) + local filename = args[1] + local fragment = generation.load_fragment(filename) + fragment:crop() + generation.save_fragment(fragment, filename, crop) + console.log("fragment with size "..vec3.tostring(fragment.size).. + " has been saved as "..file.resolve(filename)) + end +) diff --git a/src/content/loading/GeneratorLoader.cpp b/src/content/loading/GeneratorLoader.cpp index 54b9b288..ec8315f5 100644 --- a/src/content/loading/GeneratorLoader.cpp +++ b/src/content/loading/GeneratorLoader.cpp @@ -145,6 +145,9 @@ static std::vector> load_structures( } auto fragment = std::make_unique(); fragment->deserialize(files::read_binary_json(structFile)); + logger.info() << "fragment " << name << " has size [" << + fragment->getSize().x << ", " << fragment->getSize().y << ", " << + fragment->getSize().z << "]"; structures.push_back(std::make_unique( load_structure_meta(name, config), diff --git a/src/logic/scripting/lua/libs/libgeneration.cpp b/src/logic/scripting/lua/libs/libgeneration.cpp index 2874dbad..ca97815c 100644 --- a/src/logic/scripting/lua/libs/libgeneration.cpp +++ b/src/logic/scripting/lua/libs/libgeneration.cpp @@ -36,9 +36,8 @@ static int l_create_fragment(lua::State* L) { static int l_load_fragment(lua::State* L) { auto paths = engine->getPaths(); - auto [prefix, filename] = EnginePaths::parsePath(lua::require_string(L, 1)); - - auto path = paths->resolve(prefix+":generators/"+filename+".vox"); + auto filename = lua::require_string(L, 1); + auto path = paths->resolve(filename); if (!std::filesystem::exists(path)) { throw std::runtime_error("file "+path.u8string()+" does not exist"); } diff --git a/src/logic/scripting/lua/usertypes/lua_type_voxelstructure.cpp b/src/logic/scripting/lua/usertypes/lua_type_voxelstructure.cpp index fd40ee83..eb6a24ab 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_voxelstructure.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_voxelstructure.cpp @@ -13,6 +13,17 @@ LuaVoxelFragment::LuaVoxelFragment(std::shared_ptr fragment) LuaVoxelFragment::~LuaVoxelFragment() { } +static int l_crop(lua::State* L) { + if (auto fragment = touserdata(L, 1)) { + fragment->getFragment()->crop(); + } + return 0; +} + +static std::unordered_map methods { + {"crop", lua::wrap}, +}; + static int l_meta_tostring(lua::State* L) { return pushstring(L, "VoxelFragment(0x" + util::tohex( reinterpret_cast(topointer(L, 1)))+")"); @@ -27,12 +38,16 @@ static int l_meta_index(lua::State* L) { auto fieldname = tostring(L, 2); if (!std::strcmp(fieldname, "size")) { return pushivec(L, fragment->getFragment()->getSize()); + } else { + auto found = methods.find(tostring(L, 2)); + if (found != methods.end()) { + return pushcfunction(L, found->second); + } } } return 0; } - int LuaVoxelFragment::createMetatable(lua::State* L) { createtable(L, 0, 2); pushcfunction(L, lua::wrap); diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp index 75925a38..75b37b9e 100644 --- a/src/voxels/ChunksStorage.cpp +++ b/src/voxels/ChunksStorage.cpp @@ -108,10 +108,10 @@ void ChunksStorage::getVoxels(VoxelsVolume* volume, bool backlight) const { int ecz = floordiv(z + d, CHUNK_D); int cw = ecx - scx + 1; - int ch = ecz - scz + 1; + int cd = ecz - scz + 1; - // cw*ch chunks will be scanned - for (int cz = scz; cz < scz + ch; cz++) { + // cw*cd chunks will be scanned + for (int cz = scz; cz < scz + cd; cz++) { for (int cx = scx; cx < scx + cw; cx++) { const auto& found = chunksMap.find(glm::ivec2(cx, cz)); if (found == chunksMap.end()) { diff --git a/src/world/generator/VoxelFragment.cpp b/src/world/generator/VoxelFragment.cpp index 5289051b..96191725 100644 --- a/src/world/generator/VoxelFragment.cpp +++ b/src/world/generator/VoxelFragment.cpp @@ -9,6 +9,7 @@ #include "voxels/ChunksStorage.hpp" #include "voxels/VoxelsVolume.hpp" #include "world/Level.hpp" +#include "core_defs.hpp" std::unique_ptr VoxelFragment::create( Level* level, @@ -51,10 +52,10 @@ std::unique_ptr VoxelFragment::create( level->chunksStorage->getVoxels(&volume); auto volVoxels = volume.getVoxels(); - std::vector voxels(size.x*size.y*size.z); + std::vector voxels(size.x * size.y * size.z); - std::vector blockNames; - std::unordered_map blocksRegistered; + std::vector blockNames {CORE_AIR}; + std::unordered_map blocksRegistered {{0, 0}}; auto contentIndices = level->content->getIndices(); for (size_t i = 0 ; i < voxels.size(); i++) { blockid_t id = volVoxels[i].id; @@ -113,6 +114,49 @@ void VoxelFragment::deserialize(const dv::value& src) { } } +void VoxelFragment::crop() { + glm::ivec3 min = size; + glm::ivec3 max = {}; + + blockid_t air; + const auto& found = std::find(blockNames.begin(), blockNames.end(), CORE_AIR); + if (found == blockNames.end()) { + throw std::runtime_error(CORE_AIR+" is not found in fragment"); + } + air = found - blockNames.begin(); + + for (int y = 0; y < size.y; y++) { + for (int z = 0; z < size.z; z++) { + for (int x = 0; x < size.x; x++) { + if (voxels[vox_index(x, y, z, size.x, size.z)].id != air) { + min = glm::min(min, {x, y, z}); + max = glm::max(max, {x+1, y+1, z+1}); + } + } + } + } + if (glm::min(min, max) == min) { + auto newSize = max - min; + std::vector newVoxels(newSize.x * newSize.y * newSize.z); + for (int y = 0; y < newSize.y; y++) { + for (int z = 0; z < newSize.z; z++) { + for (int x = 0; x < newSize.x; x++) { + newVoxels[vox_index(x, y, z, newSize.x, newSize.z)] = + voxels[vox_index( + x + min.x, + y + min.y, + z + min.z, + size.x, + size.z + )]; + } + } + } + voxels = std::move(newVoxels); + size = newSize; + } +} + void VoxelFragment::prepare(const Content& content) { auto volume = size.x*size.y*size.z; voxelsRuntime.resize(volume); @@ -129,8 +173,8 @@ std::unique_ptr VoxelFragment::rotated(const Content& content) co for (int y = 0; y < size.y; y++) { for (int z = 0; z < size.z; z++) { for (int x = 0; x < size.x; x++) { - auto& voxel = newVoxels[vox_index(x, y, z, size.x, size.z)]; - voxel = voxels[vox_index(size.z-z-1, y, x, size.z, size.x)]; + auto& voxel = newVoxels[vox_index(size.z-z-1, y, x, size.z, size.x)]; + voxel = voxels[vox_index(x, y, z, size.x, size.z)]; // swap X and Z segment bits voxel.state.segment = ((voxel.state.segment & 0b001) << 2) | (voxel.state.segment & 0b010) diff --git a/src/world/generator/VoxelFragment.hpp b/src/world/generator/VoxelFragment.hpp index f9e94ab8..95a5375b 100644 --- a/src/world/generator/VoxelFragment.hpp +++ b/src/world/generator/VoxelFragment.hpp @@ -35,6 +35,7 @@ public: dv::value serialize() const override; void deserialize(const dv::value& src) override; + void crop(); /// @brief Build runtime voxel indices /// @param content world content diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index 0f79c4e8..b0236ec2 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -272,9 +272,6 @@ void WorldGenerator::generateStructures( glm::ivec3 position {x, height, z}; position.x -= structure.getSize().x / 2; position.z -= structure.getSize().z / 2; - prototype.placements.emplace_back( - 1, StructurePlacement {structureId, position, rotation} - ); placeStructure( StructurePlacement { structureId, @@ -486,6 +483,7 @@ void WorldGenerator::generateStructure( auto& structVoxels = structure.getRuntimeVoxels(); const auto& offset = placement.position; const auto& size = structure.getSize(); + for (int y = 0; y < size.y; y++) { int sy = y + offset.y; if (sy < 0 || sy >= CHUNK_H) { diff --git a/src/world/generator/WorldGenerator.hpp b/src/world/generator/WorldGenerator.hpp index c6f37fa1..fa8a51e0 100644 --- a/src/world/generator/WorldGenerator.hpp +++ b/src/world/generator/WorldGenerator.hpp @@ -66,10 +66,6 @@ class WorldGenerator { void generateStructures(ChunkPrototype& prototype, int x, int z); - void generatePlacements( - const ChunkPrototype& prototype, voxel* voxels, int x, int z - ); - void generateBiomes(ChunkPrototype& prototype, int x, int z); void generateHeightmap(ChunkPrototype& prototype, int x, int z); @@ -81,6 +77,9 @@ class WorldGenerator { void placeLine(const LinePlacement& line, int priority); + void generatePlacements( + const ChunkPrototype& prototype, voxel* voxels, int x, int z + ); void generateLine( const ChunkPrototype& prototype, const LinePlacement& placement, @@ -113,7 +112,8 @@ class WorldGenerator { void placeStructures( const std::vector& placements, ChunkPrototype& prototype, - int x, int z); + int x, int z + ); public: WorldGenerator( const GeneratorDef& def,