add fragment.crop, fragment:crop() & fix fragments rotation when width is not equal to depth & fix extra structures placements
This commit is contained in:
parent
44eedadc06
commit
48143c5a2b
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||
)
|
||||
|
||||
@ -145,6 +145,9 @@ static std::vector<std::unique_ptr<VoxelStructure>> load_structures(
|
||||
}
|
||||
auto fragment = std::make_unique<VoxelFragment>();
|
||||
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<VoxelStructure>(
|
||||
load_structure_meta(name, config),
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -13,6 +13,17 @@ LuaVoxelFragment::LuaVoxelFragment(std::shared_ptr<VoxelFragment> fragment)
|
||||
LuaVoxelFragment::~LuaVoxelFragment() {
|
||||
}
|
||||
|
||||
static int l_crop(lua::State* L) {
|
||||
if (auto fragment = touserdata<LuaVoxelFragment>(L, 1)) {
|
||||
fragment->getFragment()->crop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"crop", lua::wrap<l_crop>},
|
||||
};
|
||||
|
||||
static int l_meta_tostring(lua::State* L) {
|
||||
return pushstring(L, "VoxelFragment(0x" + util::tohex(
|
||||
reinterpret_cast<uint64_t>(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<l_meta_tostring>);
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include "voxels/ChunksStorage.hpp"
|
||||
#include "voxels/VoxelsVolume.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "core_defs.hpp"
|
||||
|
||||
std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
||||
Level* level,
|
||||
@ -51,10 +52,10 @@ std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
||||
level->chunksStorage->getVoxels(&volume);
|
||||
|
||||
auto volVoxels = volume.getVoxels();
|
||||
std::vector<voxel> voxels(size.x*size.y*size.z);
|
||||
std::vector<voxel> voxels(size.x * size.y * size.z);
|
||||
|
||||
std::vector<std::string> blockNames;
|
||||
std::unordered_map<blockid_t, blockid_t> blocksRegistered;
|
||||
std::vector<std::string> blockNames {CORE_AIR};
|
||||
std::unordered_map<blockid_t, blockid_t> 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<voxel> 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> 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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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<Placement>& placements,
|
||||
ChunkPrototype& prototype,
|
||||
int x, int z);
|
||||
int x, int z
|
||||
);
|
||||
public:
|
||||
WorldGenerator(
|
||||
const GeneratorDef& def,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user