mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-18 00:27:02 +08:00
Compare commits
4 Commits
17c7ad989d
...
b42b76b2fa
| Author | SHA1 | Date | |
|---|---|---|---|
| b42b76b2fa | |||
| ab5f82d1cd | |||
| 2f7ab6e29f | |||
| ca4d767a52 |
@@ -7,8 +7,15 @@ namespace Cubed {
|
|||||||
|
|
||||||
constexpr float BIOME_NOISE_FREQUENCY = 0.03f;
|
constexpr float BIOME_NOISE_FREQUENCY = 0.03f;
|
||||||
constexpr float HEIGHTMAP_NOISE_FREQUENCY = 0.001f;
|
constexpr float HEIGHTMAP_NOISE_FREQUENCY = 0.001f;
|
||||||
|
constexpr float MOUNTAINOUS_NOISE_FREQUENCY = 0.003f;
|
||||||
enum class BiomeType { PLAIN = 0, FOREST, DESERT, MOUNTAIN, RIVER, NONE };
|
enum class BiomeType { PLAIN = 0, FOREST, DESERT, MOUNTAIN, RIVER, NONE };
|
||||||
|
|
||||||
|
struct BiomeConditions {
|
||||||
|
float temp = 0.0f;
|
||||||
|
float humid = 0.0f;
|
||||||
|
float mountainous = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
struct BiomeHeightRange {
|
struct BiomeHeightRange {
|
||||||
int base_y;
|
int base_y;
|
||||||
int amplitude;
|
int amplitude;
|
||||||
@@ -47,13 +54,14 @@ struct MountainParams : public BaseBiomeParams {};
|
|||||||
struct RiverParams : public BaseBiomeParams {};
|
struct RiverParams : public BaseBiomeParams {};
|
||||||
|
|
||||||
std::string get_biome_str(BiomeType biome);
|
std::string get_biome_str(BiomeType biome);
|
||||||
BiomeType get_biome_from_noise(float temp, float humid);
|
|
||||||
std::array<float, 3> get_noise_frequencies_for_biome(BiomeType biome);
|
std::array<float, 3> get_noise_frequencies_for_biome(BiomeType biome);
|
||||||
BiomeHeightRange get_biome_height_range(BiomeType biome);
|
BiomeHeightRange get_biome_height_range(BiomeType biome);
|
||||||
BiomeType safe_int_to_biome(int x);
|
BiomeType safe_int_to_biome(int x);
|
||||||
int get_interpolated_height(float world_x, float world_z, float temp,
|
int get_interpolated_height(float world_x, float world_z, float temp,
|
||||||
float humid);
|
float humid);
|
||||||
|
|
||||||
|
BiomeType determine_biome(const BiomeConditions& conditions);
|
||||||
|
|
||||||
PlainParams& plain_params();
|
PlainParams& plain_params();
|
||||||
ForestParams& forest_params();
|
ForestParams& forest_params();
|
||||||
DesertParams& desert_params();
|
DesertParams& desert_params();
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ private:
|
|||||||
float frequency = 0.01f;
|
float frequency = 0.01f;
|
||||||
float height = 80;
|
float height = 80;
|
||||||
unsigned m_seed = 0;
|
unsigned m_seed = 0;
|
||||||
|
|
||||||
|
BiomeConditions m_conditions;
|
||||||
|
|
||||||
void clear_dirty();
|
void clear_dirty();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -108,6 +111,7 @@ public:
|
|||||||
std::vector<BlockType>& blocks();
|
std::vector<BlockType>& blocks();
|
||||||
World& world();
|
World& world();
|
||||||
unsigned seed() const;
|
unsigned seed() const;
|
||||||
|
BiomeConditions& conditions();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
Chunk& chunk();
|
Chunk& chunk();
|
||||||
Random& random();
|
Random& random();
|
||||||
const std::array<BiomeType, 8>& neighbor_biome() const;
|
const std::array<BiomeType, 8>& neighbor_biome() const;
|
||||||
|
void generate_cave();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static inline std::atomic<bool> is_init{false};
|
static inline std::atomic<bool> is_init{false};
|
||||||
@@ -58,7 +59,6 @@ private:
|
|||||||
unsigned m_chunk_seed = 0;
|
unsigned m_chunk_seed = 0;
|
||||||
|
|
||||||
void make_biome_builder();
|
void make_biome_builder();
|
||||||
void generate_cave();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
|
using enum BiomeType;
|
||||||
|
|
||||||
static PlainParams plain{{BiomeType::PLAIN,
|
static PlainParams plain{{BiomeType::PLAIN,
|
||||||
{0.0f, 0.5f},
|
{0.0f, 0.5f},
|
||||||
{0.0f, 0.5f},
|
{0.0f, 0.5f},
|
||||||
@@ -84,27 +86,7 @@ Biome get_biome_from_noise(float temp, float humid) {
|
|||||||
return Biome::FOREST;
|
return Biome::FOREST;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
BiomeType get_biome_from_noise(float temp, float humid) {
|
|
||||||
using enum BiomeType;
|
|
||||||
if (plain.temp.first <= temp && temp < plain.temp.second &&
|
|
||||||
plain.humid.first <= humid && humid < plain.humid.second) {
|
|
||||||
return PLAIN;
|
|
||||||
}
|
|
||||||
if (forest.temp.first <= temp && temp < forest.temp.second &&
|
|
||||||
forest.humid.first <= humid && humid < forest.humid.second) {
|
|
||||||
return FOREST;
|
|
||||||
}
|
|
||||||
if (desert.temp.first <= temp && temp < desert.temp.second &&
|
|
||||||
desert.humid.first <= humid && humid < desert.humid.second) {
|
|
||||||
return DESERT;
|
|
||||||
}
|
|
||||||
if (mountain.temp.first <= temp && temp <= mountain.temp.second &&
|
|
||||||
mountain.humid.first <= humid && humid <= mountain.humid.second) {
|
|
||||||
return MOUNTAIN;
|
|
||||||
}
|
|
||||||
Logger::warn("Invail Temp {} or Humid {}", temp, humid);
|
|
||||||
return PLAIN;
|
|
||||||
}
|
|
||||||
std::array<float, 3> get_noise_frequencies_for_biome(BiomeType biome) {
|
std::array<float, 3> get_noise_frequencies_for_biome(BiomeType biome) {
|
||||||
using enum BiomeType;
|
using enum BiomeType;
|
||||||
switch (biome) {
|
switch (biome) {
|
||||||
@@ -201,6 +183,29 @@ int get_interpolated_height(float world_x, float world_z, float temp,
|
|||||||
return static_cast<int>(h);
|
return static_cast<int>(h);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
BiomeType determine_biome(const BiomeConditions& conditions) {
|
||||||
|
if (conditions.mountainous > 0.75) {
|
||||||
|
return MOUNTAIN;
|
||||||
|
}
|
||||||
|
auto temp = conditions.temp;
|
||||||
|
auto humid = conditions.humid;
|
||||||
|
if (plain.temp.first <= temp && temp < plain.temp.second &&
|
||||||
|
plain.humid.first <= humid && humid < plain.humid.second) {
|
||||||
|
return PLAIN;
|
||||||
|
}
|
||||||
|
if (forest.temp.first <= temp && temp < forest.temp.second &&
|
||||||
|
forest.humid.first <= humid && humid < forest.humid.second) {
|
||||||
|
return FOREST;
|
||||||
|
}
|
||||||
|
if (desert.temp.first <= temp && temp < desert.temp.second &&
|
||||||
|
desert.humid.first <= humid && humid < desert.humid.second) {
|
||||||
|
return DESERT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PLAIN;
|
||||||
|
}
|
||||||
|
|
||||||
PlainParams& plain_params() { return plain; }
|
PlainParams& plain_params() { return plain; }
|
||||||
ForestParams& forest_params() { return forest; }
|
ForestParams& forest_params() { return forest; }
|
||||||
DesertParams& desert_params() { return desert; }
|
DesertParams& desert_params() { return desert; }
|
||||||
|
|||||||
@@ -18,21 +18,9 @@ void MountainBuilder::build_blocks() {
|
|||||||
for (int x = 0; x < CHUNK_SIZE; x++) {
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
for (int z = 0; z < CHUNK_SIZE; z++) {
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
int height = static_cast<int>(m_heightmap[x][z]);
|
int height = static_cast<int>(m_heightmap[x][z]);
|
||||||
for (int y = 5; y < height - 5; y++) {
|
for (int y = 5; y <= height; y++) {
|
||||||
m_blocks[Chunk::index(x, y, z)] = 3;
|
m_blocks[Chunk::index(x, y, z)] = 3;
|
||||||
}
|
}
|
||||||
for (int y = height - 5; y <= height - 1; y++) {
|
|
||||||
if (y > 110) {
|
|
||||||
m_blocks[Chunk::index(x, y, z)] = 3;
|
|
||||||
} else {
|
|
||||||
m_blocks[Chunk::index(x, y, z)] = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (height > 110) {
|
|
||||||
m_blocks[Chunk::index(x, height, z)] = 3;
|
|
||||||
} else {
|
|
||||||
m_blocks[Chunk::index(x, height, z)] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ Chunk::Chunk(Chunk&& other) noexcept
|
|||||||
m_chunk_pos(std::move(other.m_chunk_pos)), m_world(other.m_world),
|
m_chunk_pos(std::move(other.m_chunk_pos)), m_world(other.m_world),
|
||||||
m_heightmap(std::move(other.m_heightmap)),
|
m_heightmap(std::move(other.m_heightmap)),
|
||||||
m_blocks(std::move(other.m_blocks)), m_vbo(other.m_vbo),
|
m_blocks(std::move(other.m_blocks)), m_vbo(other.m_vbo),
|
||||||
m_vertexs_data(std::move(other.m_vertexs_data)), m_seed(other.m_seed) {
|
m_vertexs_data(std::move(other.m_vertexs_data)), m_seed(other.m_seed),
|
||||||
|
m_conditions(other.m_conditions) {
|
||||||
other.m_vbo = 0;
|
other.m_vbo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ Chunk& Chunk::operator=(Chunk&& other) noexcept {
|
|||||||
m_need_upload = other.m_need_upload.load();
|
m_need_upload = other.m_need_upload.load();
|
||||||
m_vertex_sum = other.m_vertex_sum.load();
|
m_vertex_sum = other.m_vertex_sum.load();
|
||||||
m_seed = other.m_seed;
|
m_seed = other.m_seed;
|
||||||
|
m_conditions = other.m_conditions;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +255,7 @@ void Chunk::gen_phase_two(const std::array<const Chunk*, 8>& adj_chunks) {
|
|||||||
Logger::error("ChunkGenerator is Nullptr");
|
Logger::error("ChunkGenerator is Nullptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_generator->resolve_biome_adjacency_conflict(adj_chunks);
|
// m_generator->resolve_biome_adjacency_conflict(adj_chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::gen_phase_three() {
|
void Chunk::gen_phase_three() {
|
||||||
@@ -290,7 +292,8 @@ void Chunk::gen_phase_six(
|
|||||||
Logger::error("ChunkGenerator is Nullptr");
|
Logger::error("ChunkGenerator is Nullptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// m_generator->blend_surface_blocks_borders(neighbor_block);
|
m_generator->blend_surface_blocks_borders(neighbor_block);
|
||||||
|
m_generator->generate_cave();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::gen_phase_seven() {
|
void Chunk::gen_phase_seven() {
|
||||||
@@ -349,4 +352,7 @@ unsigned Chunk::seed() const {
|
|||||||
}
|
}
|
||||||
return m_seed;
|
return m_seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BiomeConditions& Chunk::conditions() { return m_conditions; }
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Cubed/gameplay/tree.hpp"
|
#include "Cubed/gameplay/tree.hpp"
|
||||||
#include "Cubed/gameplay/world.hpp"
|
#include "Cubed/gameplay/world.hpp"
|
||||||
#include "Cubed/tools/cubed_hash.hpp"
|
#include "Cubed/tools/cubed_hash.hpp"
|
||||||
|
#include "Cubed/tools/math_tools.hpp"
|
||||||
#include "Cubed/tools/perlin_noise.hpp"
|
#include "Cubed/tools/perlin_noise.hpp"
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
@@ -59,7 +60,16 @@ void ChunkGenerator::assign_chunk_biome() {
|
|||||||
z * BIOME_NOISE_FREQUENCY);
|
z * BIOME_NOISE_FREQUENCY);
|
||||||
float humid = PerlinNoise3D::noise(x * BIOME_NOISE_FREQUENCY, 1.0f,
|
float humid = PerlinNoise3D::noise(x * BIOME_NOISE_FREQUENCY, 1.0f,
|
||||||
z * BIOME_NOISE_FREQUENCY);
|
z * BIOME_NOISE_FREQUENCY);
|
||||||
auto biome = get_biome_from_noise(temp, humid);
|
float center_x = static_cast<float>(SIZE_X / 2) + x * CHUNK_SIZE + 0.5f;
|
||||||
|
float center_z = static_cast<float>(SIZE_Z / 2) + z * CHUNK_SIZE + 0.5f;
|
||||||
|
float mountainous =
|
||||||
|
PerlinNoise2D::noise(center_x * MOUNTAINOUS_NOISE_FREQUENCY,
|
||||||
|
center_z * MOUNTAINOUS_NOISE_FREQUENCY);
|
||||||
|
auto& conditions = m_chunk.conditions();
|
||||||
|
conditions.mountainous = mountainous;
|
||||||
|
conditions.humid = humid;
|
||||||
|
conditions.temp = temp;
|
||||||
|
auto biome = determine_biome(conditions);
|
||||||
m_chunk.biome(biome);
|
m_chunk.biome(biome);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,11 +149,37 @@ void ChunkGenerator::generate_heightmap() {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
int octaves = 4;
|
int octaves = 4;
|
||||||
float lacunarity = 2.0f;
|
float lacunarity = 2.0f;
|
||||||
float gain = 0.5f;
|
float gain = 0.5f;
|
||||||
heightmap[x][z] = 64 + fbm_height(world_x, world_z, octaves,
|
float base_y = 64;
|
||||||
lacunarity, gain, 40, 0.005f);
|
float amplitude = 40.0f;
|
||||||
|
float mountainous =
|
||||||
|
PerlinNoise2D::noise(world_x * MOUNTAINOUS_NOISE_FREQUENCY,
|
||||||
|
world_z * MOUNTAINOUS_NOISE_FREQUENCY);
|
||||||
|
/*
|
||||||
|
float t = Math::smootherstep(0.6, 0.7, mountainous);
|
||||||
|
base_y = std::lerp(64, 85, t);
|
||||||
|
amplitude = std::lerp(10, 40, t);
|
||||||
|
*/
|
||||||
|
float t;
|
||||||
|
if (mountainous >= 0.7f) {
|
||||||
|
t = Math::smootherstep(0.7f, 0.75, mountainous);
|
||||||
|
base_y = std::lerp(72, 88, t);
|
||||||
|
amplitude = std::lerp(28, 48, t);
|
||||||
|
} else if (mountainous >= 0.65f) {
|
||||||
|
t = Math::smootherstep(0.65f, 0.7f, mountainous);
|
||||||
|
base_y = std::lerp(68, 72, t);
|
||||||
|
amplitude = std::lerp(18, 28, t);
|
||||||
|
} else {
|
||||||
|
t = Math::smootherstep(0.55, 0.65, mountainous);
|
||||||
|
base_y = std::lerp(60, 68, t);
|
||||||
|
amplitude = std::lerp(8, 18, t);
|
||||||
|
}
|
||||||
|
heightmap[x][z] =
|
||||||
|
base_y + fbm_height(world_x, world_z, octaves, lacunarity, gain,
|
||||||
|
amplitude, 0.005f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,7 +431,6 @@ void ChunkGenerator::generate_terrain_blocks() {
|
|||||||
}
|
}
|
||||||
m_chunk.blocks().assign(CHUNK_SIZE * CHUNK_SIZE * WORLD_SIZE_Y, 0);
|
m_chunk.blocks().assign(CHUNK_SIZE * CHUNK_SIZE * WORLD_SIZE_Y, 0);
|
||||||
m_biome_builder->build_biome();
|
m_biome_builder->build_biome();
|
||||||
generate_cave();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChunkGenerator::blend_surface_blocks_borders(
|
void ChunkGenerator::blend_surface_blocks_borders(
|
||||||
|
|||||||
Reference in New Issue
Block a user