Documentation on the MapGen class, fix hint in setBlock.
parent
e49ab18617
commit
2c97101c39
|
@ -1,13 +1,13 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C>
|
||||
<option name="INDENT_VISIBILITY_KEYWORDS" value="4" />
|
||||
<option name="INDENT_PREPROCESSOR_DIRECTIVE" value="4" />
|
||||
<option name="KEEP_CASE_EXPRESSIONS_IN_ONE_LINE" value="true" />
|
||||
<option name="FUNCTION_PARAMETERS_ALIGN_MULTILINE" value="false" />
|
||||
<option name="FUNCTION_CALL_ARGUMENTS_ALIGN_MULTILINE" value="false" />
|
||||
<option name="CLASS_CONSTRUCTOR_INIT_LIST_ALIGN_MULTILINE" value="false" />
|
||||
<option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false" />
|
||||
<option name="SPACE_BEFORE_INIT_LIST" value="true" />
|
||||
<option name="SPACE_BEFORE_POINTER_IN_DECLARATION" value="false" />
|
||||
<option name="SPACE_AFTER_POINTER_IN_DECLARATION" value="true" />
|
||||
<option name="SPACE_BEFORE_REFERENCE_IN_DECLARATION" value="false" />
|
||||
|
@ -37,10 +37,11 @@
|
|||
</rules>
|
||||
</Objective-C-extensions>
|
||||
<codeStyleSettings language="ObjectiveC">
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<option name="BLANK_LINES_AROUND_CLASS" value="0" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
|
||||
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="false" />
|
||||
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="false" />
|
||||
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
|
||||
<indentOptions>
|
||||
|
|
|
@ -6,57 +6,31 @@
|
|||
|
||||
#include "MapGen.h"
|
||||
|
||||
#include "game/def/BiomeDef.h"
|
||||
#include "game/atlas/BiomeAtlas.h"
|
||||
#include "game/Subgame.h"
|
||||
#include "MapGenProps.h"
|
||||
#include "game/def/BlockDef.h"
|
||||
#include "game/atlas/DefinitionAtlas.h"
|
||||
#include "world/dim/Dimension.h"
|
||||
#include "world/dim/chunk/Chunk.h"
|
||||
#include "world/World.h"
|
||||
#include "game/Subgame.h"
|
||||
#include "util/Schematic.h"
|
||||
#include "game/def/BiomeDef.h"
|
||||
#include "game/def/BlockDef.h"
|
||||
#include "world/dim/Dimension.h"
|
||||
#include "game/atlas/BiomeAtlas.h"
|
||||
#include "world/dim/chunk/Chunk.h"
|
||||
#include "game/atlas/DefinitionAtlas.h"
|
||||
|
||||
MapGen::MapGen(Subgame& game, World& world, unsigned int seed, std::unordered_set<std::string> biomes) :
|
||||
game(game), world(world), props(seed) {
|
||||
|
||||
std::unordered_set<unsigned int> biomeIndices{};
|
||||
std::unordered_set<unsigned int> biomeIndices {};
|
||||
for (const auto& str : biomes) {
|
||||
if (str[0] == '#') {
|
||||
for (auto& biome : game.getBiomes().biomesFromTag(str.substr(1, str.length() - 1))) {
|
||||
if (str[0] == '#')
|
||||
for (auto& biome : game.getBiomes().biomesFromTag(str.substr(1, str.length() - 1)))
|
||||
biomeIndices.insert(biome->index);
|
||||
}
|
||||
}
|
||||
else biomeIndices.insert(game.getBiomes().biomeFromStr(str).index);
|
||||
}
|
||||
|
||||
generateVoronoi(biomeIndices);
|
||||
}
|
||||
|
||||
void MapGen::generateVoronoi(const std::unordered_set<unsigned int>& biomes) {
|
||||
std::vector<std::pair<glm::vec3, unsigned short>> points{};
|
||||
for (auto biomeInd : biomes) {
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeInd);
|
||||
|
||||
points.emplace_back(glm::vec3{
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1,
|
||||
std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, biome.humidity * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize)))
|
||||
}, biomeInd);
|
||||
}
|
||||
|
||||
voronoi.setPoints(points);
|
||||
}
|
||||
|
||||
unsigned int MapGen::getBiomeAt(float temperature, float humidity, float roughness) {
|
||||
return voronoi.getPoint(
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, (temperature + 1) / 2 * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, humidity * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, roughness * voronoiSize))));
|
||||
}
|
||||
|
||||
std::unique_ptr<MapGen::CreatedSet> MapGen::generateChunk(unsigned int dim, glm::ivec3 pos) {
|
||||
[[maybe_unused]] std::unique_ptr<MapGen::CreatedSet> MapGen::generateChunk(unsigned int dim, glm::ivec3 pos) {
|
||||
return generateArea(dim, pos, 1);
|
||||
}
|
||||
|
||||
|
@ -82,7 +56,7 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
|
|||
|
||||
// Generate Biome Topmap
|
||||
|
||||
std::vector<unsigned int> biomeMap{};
|
||||
std::vector<unsigned int> biomeMap {};
|
||||
biomeMap.resize((job.size * 16 + 1) * (job.size * 16 + 1));
|
||||
|
||||
for (unsigned short i = 0; i < biomeMap.size(); i++) {
|
||||
|
@ -111,7 +85,7 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
|
|||
|
||||
// Generate Chunks
|
||||
|
||||
glm::ivec3 pos{};
|
||||
glm::ivec3 pos {};
|
||||
for (pos.x = 0; pos.x < job.size; pos.x++)
|
||||
for (pos.z = 0; pos.z < job.size; pos.z++) {
|
||||
std::unique_ptr<ChunkData> densityAbove = nullptr;
|
||||
|
@ -122,7 +96,7 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
|
|||
}
|
||||
|
||||
std::unique_ptr<ChunkData> density = populateChunkDensity(job, pos);
|
||||
std::unique_ptr<ChunkData> depth = populateChunkDepth(job, density, std::move(densityAbove));
|
||||
std::unique_ptr<ChunkData> depth = populateChunkDepth(density, std::move(densityAbove));
|
||||
|
||||
generateChunkBlocks(job, pos, biomeMap, *depth);
|
||||
generateChunkStructures(job, pos, biomeMap, *depth);
|
||||
|
@ -142,6 +116,29 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
|
|||
return std::move(created);
|
||||
}
|
||||
|
||||
void MapGen::generateVoronoi(const std::unordered_set<unsigned int>& biomes) {
|
||||
std::vector<std::pair<glm::vec3, unsigned short>> points {};
|
||||
for (auto biomeInd : biomes) {
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeInd);
|
||||
|
||||
points.emplace_back(glm::vec3 {
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1,
|
||||
std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, biome.humidity * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize)))
|
||||
}, biomeInd);
|
||||
}
|
||||
|
||||
voronoi.setPoints(points);
|
||||
}
|
||||
|
||||
unsigned int MapGen::getBiomeAt(float temperature, float humidity, float roughness) {
|
||||
return voronoi.getPoint(
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, (temperature + 1) / 2 * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, humidity * voronoiSize))),
|
||||
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, roughness * voronoiSize))));
|
||||
}
|
||||
|
||||
std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDensity(MapGen::Job& job, glm::ivec3 localPos) {
|
||||
auto data = std::make_unique<ChunkData>();
|
||||
|
||||
|
@ -155,8 +152,9 @@ std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDensity(MapGen::Job& job
|
|||
return data;
|
||||
}
|
||||
|
||||
std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDepth(Job& job, std::unique_ptr<ChunkData>& chunkDensity,
|
||||
std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDepth(std::unique_ptr<ChunkData>& chunkDensity,
|
||||
std::unique_ptr<ChunkData> chunkDensityAbove) {
|
||||
|
||||
auto data = std::make_unique<ChunkData>();
|
||||
|
||||
for (unsigned short i = 0; i < 256; i++) {
|
||||
|
@ -215,12 +213,12 @@ MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector<unsigned
|
|||
}
|
||||
|
||||
float depth = depthMap[i];
|
||||
unsigned int blockID
|
||||
= partialBlock != DefinitionAtlas::INVALID ? partialBlock
|
||||
: depth <= 1 ? DefinitionAtlas::AIR
|
||||
: depth <= 2 ? biome.topBlock
|
||||
: depth <= 4 ? biome.soilBlock
|
||||
: biome.rockBlock;
|
||||
unsigned int blockID =
|
||||
partialBlock != DefinitionAtlas::INVALID ? partialBlock
|
||||
: depth <= 1 ? DefinitionAtlas::AIR
|
||||
: depth <= 2 ? biome.topBlock
|
||||
: depth <= 4 ? biome.soilBlock
|
||||
: biome.rockBlock;
|
||||
|
||||
if (biomeID != cBiomeID) {
|
||||
chunk.biomes.emplace_back(i);
|
||||
|
@ -241,6 +239,7 @@ MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector<unsigned
|
|||
|
||||
void MapGen::generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector<unsigned int> biomeMap,
|
||||
ChunkData& depthMap) {
|
||||
|
||||
glm::vec3 posFloat = job.pos + localPos;
|
||||
std::default_random_engine generator(posFloat.x + posFloat.y / M_PI + posFloat.z / (M_PI * 2));
|
||||
std::uniform_real_distribution<float> distribution(0, 1);
|
||||
|
@ -277,14 +276,16 @@ void MapGen::generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector<
|
|||
|
||||
void MapGen::setBlock(MapGen::Job& job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr<Chunk> hint) {
|
||||
if (block == DefinitionAtlas::INVALID) return;
|
||||
|
||||
glm::ivec3 chunkPos = Space::Chunk::world::fromBlock(worldPos);
|
||||
auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos, true)).first).second;
|
||||
// if (!job.chunks->count(chunkPos)) return;
|
||||
// auto& chunk = *job.chunks->at(chunkPos);
|
||||
|
||||
unsigned int ind = Space::Block::index(worldPos);
|
||||
if (chunk.getBlock(ind) <= DefinitionAtlas::AIR) chunk.setBlock(ind, block);
|
||||
|
||||
if (hint && Space::Chunk::world::fromBlock(worldPos) == hint->getPos()) {
|
||||
if (hint->getBlock(ind) <= DefinitionAtlas::AIR) hint->setBlock(ind, block);
|
||||
}
|
||||
else {
|
||||
glm::ivec3 chunkPos = Space::Chunk::world::fromBlock(worldPos);
|
||||
auto chunk = *(*job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos, true)).first).second;
|
||||
if (chunk.getBlock(ind) <= DefinitionAtlas::AIR) chunk.setBlock(ind, block);
|
||||
}
|
||||
}
|
||||
|
||||
//void MapGen::generateSunlight(MapGen::chunk_partials_map &chunks, glm::ivec3 mbPos) {
|
||||
|
|
|
@ -17,33 +17,45 @@
|
|||
#include "util/Voronoi3D.h"
|
||||
|
||||
class World;
|
||||
|
||||
class Chunk;
|
||||
|
||||
class Subgame;
|
||||
|
||||
class BiomeDef;
|
||||
|
||||
class BiomeAtlas;
|
||||
|
||||
class DefinitionAtlas;
|
||||
|
||||
class MapGen {
|
||||
public:
|
||||
constexpr static unsigned int BIOP = 4; // Biome Prop Precision
|
||||
constexpr static unsigned int TERP = 4; // Terrain Map Precision
|
||||
public:
|
||||
/** The precision of the Biome map, as a divisor of the chunk size. */
|
||||
constexpr static unsigned int BIOP = 4;
|
||||
|
||||
typedef std::unordered_map<glm::ivec3, std::shared_ptr<Chunk>, Vec::ivec3> ChunkMap;
|
||||
/** The precision of the Terrain maps, as a divisor of the chunk size. */
|
||||
constexpr static unsigned int TERP = 4;
|
||||
|
||||
/** A type alias for the returned list of chunk positions that were generated. */
|
||||
typedef std::unordered_set<glm::ivec3, Vec::ivec3> CreatedSet;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
/** A type alias for the type the map of Chunks stored in the Job. */
|
||||
typedef std::unordered_map<glm::ivec3, std::shared_ptr<Chunk>, Vec::ivec3> ChunkMap;
|
||||
|
||||
/**
|
||||
* 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(glm::ivec3 pos, unsigned int size) :
|
||||
pos(pos), size(size),
|
||||
volume{{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap{{ size * TERP, 0 }},
|
||||
temperature{{ size * BIOP, 0 }}, roughness{{ size * BIOP, 0 }}, humidity{{ size * BIOP, 0 }} {}
|
||||
volume {{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap {{ size * TERP, 0 }},
|
||||
temperature {{ size * BIOP, 0 }}, roughness {{ size * BIOP, 0 }}, humidity {{ size * BIOP, 0 }} {}
|
||||
|
||||
glm::ivec3 pos{};
|
||||
unsigned int size{};
|
||||
glm::ivec3 pos {};
|
||||
unsigned int size {};
|
||||
|
||||
std::unique_ptr<ChunkMap> chunks = std::make_unique<ChunkMap>();
|
||||
|
||||
|
@ -55,29 +67,138 @@ class MapGen {
|
|||
|
||||
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, unsigned int seed, std::unordered_set<std::string> biomes);
|
||||
|
||||
std::unique_ptr<CreatedSet> generateChunk(unsigned int dim, glm::ivec3 pos);
|
||||
/**
|
||||
* 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]] std::unique_ptr<CreatedSet> generateChunk(unsigned int dim, glm::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.
|
||||
*/
|
||||
|
||||
std::unique_ptr<CreatedSet> generateMapBlock(unsigned int dim, glm::ivec3 pos);
|
||||
|
||||
std::unique_ptr<CreatedSet> generateArea(unsigned int dim, glm::ivec3 origin, unsigned int size = 1);
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
std::unique_ptr<CreatedSet> generateArea(unsigned int dim, glm::ivec3 origin, unsigned int 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.
|
||||
*/
|
||||
|
||||
private:
|
||||
unsigned int getBiomeAt(float temperature, float humidity, float 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<unsigned int>& 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 std::unique_ptr<ChunkData> populateChunkDensity(Job& job, glm::ivec3 localPos);
|
||||
|
||||
static std::unique_ptr<ChunkData> populateChunkDepth(Job& job, std::unique_ptr<ChunkData>& chunkDensity,
|
||||
/**
|
||||
* 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 std::unique_ptr<ChunkData> populateChunkDepth(std::unique_ptr<ChunkData>& chunkDensity,
|
||||
std::unique_ptr<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, glm::ivec3 localPos, std::vector<unsigned int> biomeMap, ChunkData& depthMap);
|
||||
|
||||
/**
|
||||
* Generates structures for a Chunk based on data within the generation job and an offset within it.
|
||||
* 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
|
||||
generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector<unsigned int> 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, glm::ivec3 worldPos, unsigned int block, std::shared_ptr<Chunk> hint);
|
||||
|
||||
// // Generate sunlight on the mapgen threads to speed up perf
|
||||
|
@ -89,7 +210,7 @@ class MapGen {
|
|||
unsigned int seed = 0;
|
||||
|
||||
constexpr const static unsigned short voronoiSize = 64;
|
||||
Voronoi3D voronoi{ voronoiSize };
|
||||
Voronoi3D voronoi { voronoiSize };
|
||||
|
||||
Subgame& game;
|
||||
World& world;
|
||||
|
|
Loading…
Reference in New Issue