Zepha/src/world/gen/MapGen.h

226 lines
7.7 KiB
C++

#pragma once
#include <queue>
#include <memory>
#include <glm/vec3.hpp>
#include <unordered_map>
#include <unordered_set>
#include "util/Vec.h"
#include "MapGenProps.h"
#include "NoiseSample.h"
#include "util/Voronoi3D.h"
class World;
class Chunk;
class Subgame;
class BiomeDef;
class BiomeAtlas;
class DefinitionAtlas;
class MapGen {
public:
/** A type alias for the type the map of Chunks stored in the Job. */
typedef std::unordered_map<ivec3, sptr<Chunk>, Vec::ivec3> ChunkMap;
/**
* A struct representing a single position in a chunk at which sunlight should be updated at.
*/
struct SunlightNode {
SunlightNode(u16 index, Chunk* chunk) : index(index), chunk(chunk) {};
u16 index;
Chunk* chunk;
};
/**
* A struct containing all the information for a generation job.
* Contains a list of chunks, Noise samples, and the world position of the the job's root.
*/
struct Job {
/**
* Creates a new job with the root position and size specified, and initializes the NoiseSample params.
* @param pos - The root position of the job.
* @param size - The size in chunks of the job.
*/
Job(ivec3 pos, u16 size) :
pos(pos), size(size),
volume(u16vec3(size * 16, (size + 1) * 16, size * 16), 4),
heightmap(u16vec2(size * 16), 4),
temperature(u16vec2(size * 16), 4),
humidity(u16vec2(size * 16), 4),
roughness(u16vec2(size * 16), 4) {}
ivec3 pos {};
u16 size {};
uptr<ChunkMap> chunks = make_unique<ChunkMap>();
std::queue<SunlightNode> sunlightQueue {};
NoiseSample heightmap, volume;
NoiseSample temperature, humidity, roughness;
};
typedef array<f32, 4096> ChunkData;
MapGen(const MapGen& o) = delete;
/**
* Create a MapGen object with the seed and biomes provided.
*
* @param game - A reference to the subgame, for block and biome definitions.
* @param world - A reference to the world, for assigning the blocks to.
* @param seed - A seed to base the generation off of.
* @param biomes - A list of biome identifiers or tags to include in generation.
*/
MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string> biomes);
/**
* Generate a single chunk at the dimension and position provided.
* As with all generate* functions, this may result in extraneous chunk partials being created.
* This is the least efficient generation call and should be used only in extenuating circumstances.
*
* @param dim - The dimension to insert the finished chunk into.
* @param pos - The position in the dimension to generate the chunk.
* @returns a set of positions that were generated by this function call.
*/
[[maybe_unused]] uptr<ChunkMap> generateChunk(u16 dim, ivec3 pos);
/**
* Generate a mapblock at the dimension and position provided.
* As with all generate* functions, this may result in extraneous chunk partials being created.
* Commonly used by the ServerGenStream for regular chunk generation.
*
* @param dim - The dimension to insert the finished chunk into.
* @param pos - The position in the dimension to generate the chunk.
* @returns a set of positions that were generated by this function call.
*/
uptr<ChunkMap> generateMapBlock(u16 dim, ivec3 pos);
/**
* The underlying generate function called by both generateMapBlock and generateChunk.
* Can also be called on it's own to generate an arbitrary region of chunks.
* As with all generate* functions, this may result in extraneous chunk partials being created.
*
* @param dim - The dimension to insert the finished chunk into.
* @param pos - The position in the dimension to generate the chunk.
* @return - A set of positions that were generated by this function call.
*/
uptr<ChunkMap> generateArea(u16 dim, ivec3 origin, u16 size = 1);
private:
/**
* Get the closest biome to the provided environmental values from the Vonoroi map.
* Returns the index of the matched biome.
*
* @param temperature - The temperature value of the position to check.
* @param humidity - The humidity value of the position to check.
* @param roughness - The roughness value of the position to check.
* @returns the biome index of the environmentally closest biome.
*/
u16 getBiomeAt(f32 temperature, f32 humidity, f32 roughness);
/**
* Generate the Vonoroi biome map, using the biomes listed,
* according to their definition parameters.
*
* @param biomes - The biomes to add to the map.
*/
void generateVoronoi(const std::unordered_set<u16>& biomes);
/**
* Create a density array for a chunk using a generation Job and an offset within it.
* Returns a flattened array of block densities for every point in the chunk.
*
* @param job - The Job to pull the data from.
* @param localPos - The offset of the chunk's data within the job.
* @returns a ChunkData array containing the chunk's density.
*/
static uptr<ChunkData> populateChunkDensity(Job& job, ivec3 localPos);
/**
* Create a depth array for a chunk using a generation Job and the chunk densities around it.
* Returns a flattened array of block depths for every point in the chunk.
*
* @param chunkDensity - A density array of the current chunk.
* @param chunkDensityAbove - A density array of the chunk above it.
* @returns a ChunkData array containing the chunk's depth.
*/
static uptr<ChunkData> populateChunkDepth(uptr<ChunkData>& chunkDensity, uptr<ChunkData> chunkDensityAbove);
/**
* Generates a chunk's blocks from a generation Job and an offset within it, and inserts it into the Job.
* Combines with any partials that have been previously created at that position within job.
*
* Declares the chunk generated, and counts renderable blocks within it. Though later functions manipulate
* chunk data, they do so using the chunk setBlock method, making it safe to count at this stage.
*
* @param job - The Job to pull the data from.
* @param localPos - The offset of the chunk within the job.
* @param biomeMap - The two-dimensional biome array of the entire generation area.
* @param depthMap - The depth map of the chunk being generated.
*/
void generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap);
/**
* Generates structures for a Chunk based on data within the generation job and an offset within it.
* Also generates initial light cascade, which will later be refined by propogateSunlightNodes.
* May create chunk partials, inserting them back into the Job for later completion.
*
* @param job - The job to pull the data from.
* @param localPos - The offset of the chunk within the job.
* @param biomeMap - The two-dimensional biome array of the entire generation area.
* @param depthMap - The depth map of the chunk being generated.
*/
void generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap);
/**
* Sets a block at the position specified into the Job, if the block at said position is not filled by
* a material greater than air. If a chunk does not exist at the specified position, a partial is generated
* into the chunk map, and the block is assigned on there.
*
* @param job - The job to pull the data from.
* @param worldPos - The world position to set the block at.
* @param block - The block to set.
* @param hint - An optional parameter that may speed up the function if set to the chunk to set to.
*/
static void setBlock(Job& job, ivec3 worldPos, u16 block, sptr<Chunk> hint);
/**
* Calculates and smooths sunlight for an entire Job's chunks.
*
* @param job - The job to act upon.
*/
void propogateSunlightNodes(Job& job);
u32 seed = 0;
MapGenProps props;
constexpr const static u16 voronoiSize = 64;
Voronoi3D voronoi { voronoiSize };
FastNoise::SmartNode<> biomeGenerator;
Subgame& game;
World& world;
};