add StructurePlacement & add SurroundMap visualization test

This commit is contained in:
MihailRis 2024-09-20 23:43:54 +03:00
parent 88b0f8e3d6
commit 4f882a3ca3
5 changed files with 72 additions and 9 deletions

View File

@ -62,7 +62,7 @@ namespace util {
return &firstBuffer[ly * sizeX + lx]; return &firstBuffer[ly * sizeX + lx];
} }
T get(TCoord x, TCoord y) { T get(TCoord x, TCoord y) const {
auto lx = x - offsetX; auto lx = x - offsetX;
auto ly = y - offsetY; auto ly = y - offsetY;
if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) { if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) {

View File

@ -7,6 +7,7 @@
#include "maths/Heightmap.hpp" #include "maths/Heightmap.hpp"
class Content; class Content;
class VoxelStructure;
struct BlocksLayer { struct BlocksLayer {
/// @brief Layer block /// @brief Layer block
@ -99,8 +100,11 @@ class GeneratorScript {
public: public:
virtual ~GeneratorScript() = default; virtual ~GeneratorScript() = default;
/// @brief Load all structures
//virtual std::vector<std::shared_ptr<VoxelStructure>> loadStructures() = 0;
/// @brief Generates a heightmap with values in range 0..1 /// @brief Generates a heightmap with values in range 0..1
/// @param offset position of the heightmap top left corner in the world /// @param offset position of the heightmap in the world
/// @param size size of the heightmap /// @param size size of the heightmap
/// @param seed world seed /// @param seed world seed
/// @return generated heightmap of given size (can't be nullptr) /// @return generated heightmap of given size (can't be nullptr)

View File

@ -14,8 +14,8 @@
static debug::Logger logger("world-generator"); static debug::Logger logger("world-generator");
static inline constexpr uint MAX_PARAMETERS = 8; static inline constexpr uint MAX_PARAMETERS = 4;
static inline constexpr uint MAX_CHUNK_PROTOTYPE_LEVELS = 8; static inline constexpr uint MAX_CHUNK_PROTOTYPE_LEVELS = 3;
WorldGenerator::WorldGenerator( WorldGenerator::WorldGenerator(
const GeneratorDef& def, const Content* content, uint64_t seed const GeneratorDef& def, const Content* content, uint64_t seed
@ -114,10 +114,11 @@ std::unique_ptr<ChunkPrototype> WorldGenerator::generatePrototype(
{chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed); {chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed);
const auto& biomes = def.script->getBiomes(); const auto& biomes = def.script->getBiomes();
std::vector<const Biome*> chunkBiomes(CHUNK_W*CHUNK_D); auto chunkBiomes = std::make_unique<const Biome*[]>(CHUNK_W*CHUNK_D);
for (uint z = 0; z < CHUNK_D; z++) { for (uint z = 0; z < CHUNK_D; z++) {
for (uint x = 0; x < CHUNK_W; x++) { for (uint x = 0; x < CHUNK_W; x++) {
chunkBiomes[z * CHUNK_W + x] = choose_biome(biomes, biomeParams, x, z); chunkBiomes.get()[z * CHUNK_W + x] =
choose_biome(biomes, biomeParams, x, z);
} }
} }
return std::make_unique<ChunkPrototype>( return std::make_unique<ChunkPrototype>(
@ -162,9 +163,10 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
PseudoRandom plantsRand; PseudoRandom plantsRand;
plantsRand.setSeed(chunkX, chunkZ); plantsRand.setSeed(chunkX, chunkZ);
const auto& biomes = prototype->biomes.get();
for (uint z = 0; z < CHUNK_D; z++) { for (uint z = 0; z < CHUNK_D; z++) {
for (uint x = 0; x < CHUNK_W; x++) { for (uint x = 0; x < CHUNK_W; x++) {
const Biome* biome = prototype->biomes[z * CHUNK_W + x]; const Biome* biome = biomes[z * CHUNK_W + x];
int height = values[z * CHUNK_W + x] * CHUNK_H; int height = values[z * CHUNK_W + x] * CHUNK_H;
height = std::max(0, height); height = std::max(0, height);

View File

@ -20,18 +20,29 @@ enum class ChunkPrototypeLevel {
BIOMES, HEIGHTMAP BIOMES, HEIGHTMAP
}; };
struct StructurePlacement {
VoxelStructure& structure;
glm::ivec3 position;
StructurePlacement(VoxelStructure& structure, glm::ivec3 position)
: structure(structure), position(std::move(position)) {}
};
struct ChunkPrototype { struct ChunkPrototype {
ChunkPrototypeLevel level; ChunkPrototypeLevel level;
/// @brief chunk biomes matrix /// @brief chunk biomes matrix
std::vector<const Biome*> biomes; std::unique_ptr<const Biome*[]> biomes;
/// @brief chunk heightmap /// @brief chunk heightmap
std::shared_ptr<Heightmap> heightmap; std::shared_ptr<Heightmap> heightmap;
std::vector<StructurePlacement> structures;
ChunkPrototype( ChunkPrototype(
ChunkPrototypeLevel level, ChunkPrototypeLevel level,
std::vector<const Biome*> biomes, std::unique_ptr<const Biome*[]> biomes,
std::shared_ptr<Heightmap> heightmap std::shared_ptr<Heightmap> heightmap
) : level(level), ) : level(level),
biomes(std::move(biomes)), biomes(std::move(biomes)),

View File

@ -30,3 +30,49 @@ TEST(SurroundMap, InitTest) {
map.completeAt(x - 1, y); map.completeAt(x - 1, y);
EXPECT_EQ(affected, maxLevel * 2 - 1); EXPECT_EQ(affected, maxLevel * 2 - 1);
} }
#define VISUAL_TEST
#ifdef VISUAL_TEST
#include <glm/gtc/random.hpp>
#include "coders/png.hpp"
#include "graphics/core/ImageData.hpp"
void visualize(const SurroundMap& map, int mul, int max) {
const auto& areaMap = map.getArea();
int w = areaMap.getWidth();
int h = areaMap.getHeight();
int ox = areaMap.getOffsetX();
int oy = areaMap.getOffsetY();
ImageData image(ImageFormat::rgb888, w, h);
ubyte* bytes = image.getData();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int val = areaMap.get(x + ox, y + oy) * mul;
if (val && val / mul < max) {
val = val / 4 + 50;
}
bytes[(y * w + x) * 3] = val;
bytes[(y * w + x) * 3 + 1] = val;
bytes[(y * w + x) * 3 + 2] = val;
}
}
png::write_image("test.png", &image);
}
TEST(SurroundMap, Visualize) {
int levels = 3;
SurroundMap map(50, levels);
map.setCenter(0, 0);
for (int i = 0; i < 1000; i++) {
float x = glm::gaussRand(0.0f, 2.0f);
float y = glm::gaussRand(0.0f, 2.0f);
map.completeAt(x, y);
}
visualize(map, 30, levels);
}
#endif