diff --git a/CMakeLists.txt b/CMakeLists.txt index cbfc917..6b95893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ add_executable(${PROJECT_NAME} src/gameplay/river_path.cpp src/block.cpp src/gameplay/vertex_data.cpp + src/gameplay/builders/ocean_builder.cpp ) if(CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/assets/data/block/air.toml b/assets/data/block/air.toml index 2b16aa3..47a8c02 100644 --- a/assets/data/block/air.toml +++ b/assets/data/block/air.toml @@ -5,5 +5,6 @@ is_discard = true is_gas = true is_liquid = false is_passable = true +is_transitional = false is_transparent = true name = 'air' \ No newline at end of file diff --git a/assets/data/block/dirt.toml b/assets/data/block/dirt.toml index f62f7e3..6e15751 100644 --- a/assets/data/block/dirt.toml +++ b/assets/data/block/dirt.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = false is_passable = false +is_transitional = true is_transparent = false name = 'dirt' \ No newline at end of file diff --git a/assets/data/block/grass.toml b/assets/data/block/grass.toml index 4eccd44..0cc428e 100644 --- a/assets/data/block/grass.toml +++ b/assets/data/block/grass.toml @@ -5,5 +5,6 @@ is_discard = true is_gas = false is_liquid = false is_passable = true +is_transitional = false is_transparent = true name = 'grass' \ No newline at end of file diff --git a/assets/data/block/grass_block.toml b/assets/data/block/grass_block.toml index 84bdf57..13db505 100644 --- a/assets/data/block/grass_block.toml +++ b/assets/data/block/grass_block.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = false is_passable = false +is_transitional = true is_transparent = false name = 'grass_block' \ No newline at end of file diff --git a/assets/data/block/leaf.toml b/assets/data/block/leaf.toml index ef8ba3f..07b0c99 100644 --- a/assets/data/block/leaf.toml +++ b/assets/data/block/leaf.toml @@ -5,5 +5,6 @@ is_discard = true is_gas = false is_liquid = false is_passable = false +is_transitional = false is_transparent = true name = 'leaf' \ No newline at end of file diff --git a/assets/data/block/log.toml b/assets/data/block/log.toml index 1dea710..a4b4bb9 100644 --- a/assets/data/block/log.toml +++ b/assets/data/block/log.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = false is_passable = false +is_transitional = false is_transparent = false name = 'log' \ No newline at end of file diff --git a/assets/data/block/sand.toml b/assets/data/block/sand.toml index bb23bbc..793ba67 100644 --- a/assets/data/block/sand.toml +++ b/assets/data/block/sand.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = false is_passable = false +is_transitional = true is_transparent = false name = 'sand' \ No newline at end of file diff --git a/assets/data/block/snowy_grass_block.toml b/assets/data/block/snowy_grass_block.toml index f6b501a..d52ecd0 100644 --- a/assets/data/block/snowy_grass_block.toml +++ b/assets/data/block/snowy_grass_block.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = false is_passable = false +is_transitional = true is_transparent = false name = 'snowy_grass_block' \ No newline at end of file diff --git a/assets/data/block/stone.toml b/assets/data/block/stone.toml index b5dddd3..9724776 100644 --- a/assets/data/block/stone.toml +++ b/assets/data/block/stone.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = false is_passable = false +is_transitional = true is_transparent = false name = 'stone' \ No newline at end of file diff --git a/assets/data/block/template.toml b/assets/data/block/template.toml index 4832ece..6be41a5 100644 --- a/assets/data/block/template.toml +++ b/assets/data/block/template.toml @@ -7,3 +7,4 @@ is_cross_plane = false is_transparent = false is_discard = false is_blend = false +is_transitional = false diff --git a/assets/data/block/water.toml b/assets/data/block/water.toml index ed808b6..d0efcf2 100644 --- a/assets/data/block/water.toml +++ b/assets/data/block/water.toml @@ -5,5 +5,6 @@ is_discard = false is_gas = false is_liquid = true is_passable = true +is_transitional = false is_transparent = true name = 'water' \ No newline at end of file diff --git a/include/Cubed/gameplay/biome.hpp b/include/Cubed/gameplay/biome.hpp index 72ac7f9..f4af4ed 100644 --- a/include/Cubed/gameplay/biome.hpp +++ b/include/Cubed/gameplay/biome.hpp @@ -15,6 +15,7 @@ enum class BiomeType { MOUNTAIN, RIVER, SNOWY_PLAIN, + OCEAN, NONE }; diff --git a/include/Cubed/gameplay/block.hpp b/include/Cubed/gameplay/block.hpp index c6c6770..87fa841 100644 --- a/include/Cubed/gameplay/block.hpp +++ b/include/Cubed/gameplay/block.hpp @@ -50,13 +50,14 @@ struct BlockData { bool is_discard = false; bool is_blend = false; - + bool is_transitional = false; BlockData(BlockType b_id, std::string_view b_name, bool liquid, bool passable, bool cross_plane, bool transparent, bool gas, - bool discard, bool blend) + bool discard, bool blend, bool transitional) : name(b_name), id(b_id), is_liquid(liquid), is_gas(gas), is_passable(passable), is_cross_plane(cross_plane), - is_transparent(transparent), is_discard(discard), is_blend(blend) {} + is_transparent(transparent), is_discard(discard), is_blend(blend), + is_transitional(transitional) {} }; class BlockManager { @@ -77,7 +78,7 @@ public: static bool is_discard(BlockType id); static bool is_blend(BlockType id); - + static bool is_transitional(BlockType id); static BlockType cross_plane_index(BlockType id); private: diff --git a/include/Cubed/gameplay/builders/biome_builder.hpp b/include/Cubed/gameplay/builders/biome_builder.hpp index a3270fe..b4756d5 100644 --- a/include/Cubed/gameplay/builders/biome_builder.hpp +++ b/include/Cubed/gameplay/builders/biome_builder.hpp @@ -9,6 +9,7 @@ public: virtual ChunkGenerator& get_chunk_generator() = 0; virtual void build_biome() = 0; virtual void build_vegetation() = 0; + void ocean_water_build(); protected: void build_bottom(); diff --git a/include/Cubed/gameplay/builders/ocean_builder.hpp b/include/Cubed/gameplay/builders/ocean_builder.hpp new file mode 100644 index 0000000..3404e6e --- /dev/null +++ b/include/Cubed/gameplay/builders/ocean_builder.hpp @@ -0,0 +1,23 @@ +#pragma once + +#pragma once + +#include "Cubed/gameplay/builders/biome_builder.hpp" +namespace Cubed { + +class ChunkGenerator; + +class OceanBuilder : public BiomeBuilder { +public: + OceanBuilder(ChunkGenerator& chunk_generator); + void build_biome() override; + ChunkGenerator& get_chunk_generator() override; + void build_vegetation() override; + +private: + ChunkGenerator& m_chunk_generator; + + void build_blocks(); +}; + +} // namespace Cubed diff --git a/include/Cubed/gameplay/chunk_generator.hpp b/include/Cubed/gameplay/chunk_generator.hpp index 396b6f8..2cf5d04 100644 --- a/include/Cubed/gameplay/chunk_generator.hpp +++ b/include/Cubed/gameplay/chunk_generator.hpp @@ -45,6 +45,7 @@ public: Chunk& chunk(); Random& random(); const std::array& neighbor_biome() const; + void ocean_build(); void generate_cave(); void generate_river(); diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index 73ab284..c6ed49f 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -70,8 +70,10 @@ private: void gen_chunks_internal(); void sync_player_pos(glm::vec3& player_pos); - void compute_required_chunks(ChunkPosSet& required_chunks, - ChunkHashMap& temp_neighbor); + void + compute_required_chunks(ChunkPosSet& required_chunks, + ChunkHashMap& temp_neighbor, + std::vector& need_gen_temp_chunks_pos); void sync_and_collect_missing_chunks(std::vector&, const ChunkPosSet&); void diff --git a/include/Cubed/tools/math_tools.hpp b/include/Cubed/tools/math_tools.hpp index 4a276b4..5bb4795 100644 --- a/include/Cubed/tools/math_tools.hpp +++ b/include/Cubed/tools/math_tools.hpp @@ -11,7 +11,7 @@ void extract_frustum_planes(const glm::mat4& mvp_matrix, float smootherstep(float edge0, float edge1, float x); bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents, const std::vector& planes); - +float deterministic_random(int x, int z, uint64_t seed); } // namespace Math } // namespace Cubed \ No newline at end of file diff --git a/src/block.cpp b/src/block.cpp index ddb3b4a..d3ab2f1 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -104,7 +104,13 @@ bool BlockManager::is_blend(BlockType id) { } return m_datas[id].is_blend; } - +bool BlockManager::is_transitional(BlockType id) { + if (id >= sums()) { + Logger::error("Id {}, is Over The Max Id", id, sums() - 1); + return m_datas[0].is_transitional; + } + return m_datas[id].is_transitional; +} void BlockManager::init() { fs::path data_path{block_data_dir}; @@ -142,9 +148,10 @@ void BlockManager::init() { auto is_gas = safe_get_value(block, "is_gas", false); auto is_discard = safe_get_value(block, "is_discard", false); auto is_blend = safe_get_value(block, "is_blend", false); + auto is_transitional = safe_get_value(block, "is_transitional", false); m_datas.emplace_back(*id, *name, *is_liquid, *is_passable, *is_cross_plane, *is_transparent, *is_gas, - *is_discard, *is_blend); + *is_discard, *is_blend, *is_transitional); } std::sort( m_datas.begin(), m_datas.end(), diff --git a/src/gameplay/biome.cpp b/src/gameplay/biome.cpp index 39fdeb9..76acaaa 100644 --- a/src/gameplay/biome.cpp +++ b/src/gameplay/biome.cpp @@ -62,6 +62,10 @@ std::string get_biome_str(BiomeType biome) { break; case SNOWY_PLAIN: str = "Snowy Plain"; + break; + case OCEAN: + str = "Ocean"; + break; case NONE: str = "Unknown"; break; @@ -190,6 +194,9 @@ BiomeType determine_biome(const BiomeConditions& conditions) { if (conditions.mountainous > 0.75) { return MOUNTAIN; } + if (conditions.mountainous < 0.25) { + return OCEAN; + } auto temp = conditions.temp; auto humid = conditions.humid; if (temp < 0.5) { diff --git a/src/gameplay/builders/biome_builder.cpp b/src/gameplay/builders/biome_builder.cpp index f0f83d6..9c7b901 100644 --- a/src/gameplay/builders/biome_builder.cpp +++ b/src/gameplay/builders/biome_builder.cpp @@ -39,4 +39,23 @@ void BiomeBuilder::place_grass() { } } } + +void BiomeBuilder::ocean_water_build() { + ChunkGenerator& chunk_generator = get_chunk_generator(); + Chunk& chunk = chunk_generator.chunk(); + auto& blocks = chunk.blocks(); + const auto& heightmap = chunk.get_heightmap(); + + for (int x = 0; x < SIZE_X; ++x) { + for (int z = 0; z < SIZE_Z; ++z) { + int height = heightmap[x][z]; + if (height <= SEA_LEVEL) { + for (int y = height; y <= SEA_LEVEL; y++) { + blocks[Chunk::index(x, y, z)] = 7; + } + } + } + } +} + } // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/builders/ocean_builder.cpp b/src/gameplay/builders/ocean_builder.cpp new file mode 100644 index 0000000..123461e --- /dev/null +++ b/src/gameplay/builders/ocean_builder.cpp @@ -0,0 +1,34 @@ +#include "Cubed/gameplay/builders/ocean_builder.hpp" + +#include "Cubed/gameplay/chunk.hpp" +#include "Cubed/gameplay/chunk_generator.hpp" +namespace Cubed { +OceanBuilder::OceanBuilder(ChunkGenerator& chunk_generator) + : m_chunk_generator(chunk_generator) {} + +void OceanBuilder::build_biome() { + BiomeBuilder::build_bottom(); + build_blocks(); +}; + +void OceanBuilder::build_blocks() { + auto& m_chunk = m_chunk_generator.chunk(); + auto& m_blocks = m_chunk.blocks(); + auto& m_heightmap = m_chunk.heightmap(); + for (int x = 0; x < CHUNK_SIZE; x++) { + for (int z = 0; z < CHUNK_SIZE; z++) { + int height = static_cast(m_heightmap[x][z]); + for (int y = 5; y <= height; y++) { + m_blocks[Chunk::index(x, y, z)] = 3; + } + } + } +} + +void OceanBuilder::build_vegetation() {} + +ChunkGenerator& OceanBuilder::get_chunk_generator() { + return m_chunk_generator; +}; + +} // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index 430fd85..60df97f 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -199,9 +199,8 @@ void Chunk::gen_phase_six( Logger::error("ChunkGenerator is Nullptr"); return; } + // This must be fully completed before any other operations can proceed! m_generator->blend_surface_blocks_borders(neighbor_block); - m_generator->generate_cave(); - m_generator->generate_river(); } void Chunk::gen_phase_seven() { @@ -209,6 +208,10 @@ void Chunk::gen_phase_seven() { Logger::error("ChunkGenerator is Nullptr"); return; } + m_generator->ocean_build(); + m_generator->generate_river(); + m_generator->generate_cave(); + m_generator->generate_vegetation(); mark_dirty(); m_generator = nullptr; diff --git a/src/gameplay/chunk_generator.cpp b/src/gameplay/chunk_generator.cpp index ddb7547..c07b471 100644 --- a/src/gameplay/chunk_generator.cpp +++ b/src/gameplay/chunk_generator.cpp @@ -3,6 +3,7 @@ #include "Cubed/gameplay/builders/desert_builder.hpp" #include "Cubed/gameplay/builders/forest_builder.hpp" #include "Cubed/gameplay/builders/mountain_builder.hpp" +#include "Cubed/gameplay/builders/ocean_builder.hpp" #include "Cubed/gameplay/builders/plain_builder.hpp" #include "Cubed/gameplay/builders/river_builder.hpp" #include "Cubed/gameplay/builders/snowy_plain_builder.hpp" @@ -17,7 +18,7 @@ namespace Cubed { using enum BiomeType; -constexpr int BLEND_RADIUS = 12; +constexpr int BLEND_RADIUS = 8; ChunkGenerator::ChunkGenerator(Chunk& chunk) : m_chunk(chunk) { ASSERT_MSG(is_init, "ChunksGenerator is not init"); ChunkPos pos = m_chunk.get_chunk_pos(); @@ -166,18 +167,43 @@ void ChunkGenerator::generate_heightmap() { amplitude = std::lerp(10, 40, t); */ float t; - if (mountainous >= 0.7f) { - t = Math::smootherstep(0.7f, 0.75, mountainous); - base_y = std::lerp(70, 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(66, 70, t); + if (mountainous >= 0.95f) { + t = Math::smootherstep(0.95f, 1.0f, mountainous); + base_y = std::lerp(130, 140, t); + amplitude = std::lerp(38, 48, t); + } else if (mountainous >= 0.85f) { + t = Math::smootherstep(0.85f, 0.95f, mountainous); + base_y = std::lerp(100, 130, t); + amplitude = std::lerp(28, 38, t); + } else if (mountainous >= 0.8) { + t = Math::smootherstep(0.8f, 0.85f, mountainous); + base_y = std::lerp(85, 100, t); amplitude = std::lerp(18, 28, t); + } else if (mountainous >= 0.75f) { + t = Math::smootherstep(0.75f, 0.8f, mountainous); + base_y = std::lerp(70, 85, t); + amplitude = std::lerp(6, 18, t); + } else if (mountainous >= 0.7) { + t = Math::smootherstep(0.7f, 0.75f, mountainous); + base_y = std::lerp(66, 70, t); + amplitude = std::lerp(6, 6, t); + + } else if (mountainous >= 0.45f) { + t = Math::smootherstep(0.45f, 0.7f, mountainous); + base_y = std::lerp(64, 66, t); + amplitude = std::lerp(6, 6, t); + } else if (mountainous >= 0.3f) { + t = Math::smootherstep(0.3f, 0.45f, mountainous); + base_y = std::lerp(60, 64, t); + amplitude = std::lerp(6, 6, t); + } else if (mountainous >= 0.25f) { + t = Math::smootherstep(0.25f, 0.3f, mountainous); + base_y = std::lerp(44, 60, t); + amplitude = std::lerp(6, 6, t); } else { - t = Math::smootherstep(0.55, 0.65, mountainous); - base_y = std::lerp(58, 66, t); - amplitude = std::lerp(8, 18, t); + t = Math::smootherstep(0.0f, 0.25f, mountainous); + base_y = std::lerp(35, 44, t); + amplitude = std::lerp(3, 6, t); } heightmap[x][z] = base_y + fbm_height(world_x, world_z, octaves, lacunarity, gain, @@ -451,9 +477,11 @@ void ChunkGenerator::blend_surface_blocks_borders( for (int y = WORLD_HEIGHT - 1; y >= 0; --y) { int idx = Chunk::index(nx, y, nz); // linear index: y * area + z * size + x - if (idx >= 0 && idx < static_cast(blocks.size()) && - blocks[idx] != 0) { - return blocks[idx]; + if (idx >= 0 && idx < static_cast(blocks.size())) { + BlockType neighbor_type = blocks[idx]; + if (BlockManager::is_transitional(neighbor_type)) { + return neighbor_type; + } } } return 0; // fallback, should not happen for valid chunks @@ -473,8 +501,8 @@ void ChunkGenerator::blend_surface_blocks_borders( // Weight map: type -> total weight std::unordered_map weights; - weights[type_self] = 1.0f; // self weight - + float self_weight = 1.0f; + weights[type_self] = self_weight; // --- Right neighbor (index 0) --- if (neighbor_block[0] && x >= CHUNK_SIZE - BLEND_RADIUS) { int dist = (CHUNK_SIZE - 1) - x; @@ -523,47 +551,50 @@ void ChunkGenerator::blend_surface_blocks_borders( } } + if (weights.empty()) { + continue; + } // Find type with maximum total weight BlockType final_type = type_self; - float max_weight = weights[type_self]; + /*float max_weight = weights[type_self]; for (const auto& [type, w] : weights) { if (w > max_weight) { max_weight = w; final_type = type; } + }*/ + + float sum = 0.0f; + for (auto& kv : weights) { + sum += kv.second; + } + float rnd = m_random.random_float(0.0f, 1.0f); + float accum = 0.0f; + for (auto [t, w] : weights) { + accum += w / sum; + if (rnd < accum) { + final_type = t; + break; + } } - if (final_type == 0) { - return; + if (!BlockManager::is_transitional(final_type)) { + continue; } - // Update the top block if the type changed if (final_type != type_self) { // top block - if (final_type == 7 && top_y > SEA_LEVEL) { - if (type_self == 7) { - m_blocks[Chunk::index(x, top_y, z)] = 0; - } else { - m_blocks[Chunk::index(x, top_y, z)] = type_self; - } - - } else { - m_blocks[Chunk::index(x, top_y, z)] = final_type; - } - + BlockType new_surface = final_type; + m_blocks[Chunk::index(x, top_y, z)] = new_surface; // bottom block unsigned fill_type = 2; - if (final_type == 1) { + if (final_type == 1 || final_type == 8) { fill_type = 2; - } else if (final_type == 4) { - fill_type = 4; + } else { + fill_type = final_type; } - for (int y = top_y - 5; y < top_y; y++) { - if (fill_type == 7 && y > SEA_LEVEL) { - m_blocks[Chunk::index(x, y, z)] = 0; - } else { - m_blocks[Chunk::index(x, y, z)] = fill_type; - } + for (int y = std::max(0, top_y - 5); y < top_y; y++) { + m_blocks[Chunk::index(x, y, z)] = fill_type; } } } @@ -600,12 +631,17 @@ void ChunkGenerator::make_biome_builder() { case SNOWY_PLAIN: m_biome_builder = std::make_unique(*this); break; + case OCEAN: + m_biome_builder = std::make_unique(*this); + break; case NONE: m_biome_builder = nullptr; break; } } +void ChunkGenerator::ocean_build() { m_biome_builder->ocean_water_build(); } + void ChunkGenerator::generate_cave() { auto& cave_carver = m_chunk.world().cave_carcer(); auto& paths = cave_carver.paths(); @@ -617,9 +653,14 @@ void ChunkGenerator::generate_cave() { const int CHUNK_MAX_Z = CHUNK_MIN_Z + SIZE_Z - 1; const int CHUNK_MIN_Y = 0; const int CHUNK_MAX_Y = SIZE_Y - 1; + for (auto& [id, path] : paths) { for (const auto& point : path.points()) { - + if ((m_chunk.biome() == BiomeType::RIVER) || + (m_chunk.biome() == BiomeType::OCEAN)) { + path.clear_chunk(chunk_pos); + continue; + } const glm::vec3& center = point.pos; float rad_xz = point.rad_xz; float rad_y = point.rad_y; @@ -651,6 +692,13 @@ void ChunkGenerator::generate_cave() { if (y == 0) { continue; } + if (blocks[Chunk::index(x, y, z)] == 7) { + continue; + } + if (y < WORLD_SIZE_Y - 1 && + blocks[Chunk::index(x, y + 1, z)] == 7) { + continue; + } blocks[Chunk::index(x, y, z)] = 0; } } @@ -678,7 +726,8 @@ void ChunkGenerator::generate_river() { for (auto& [id, path] : paths) { for (const auto& point : path.points()) { - if (m_chunk.biome() == BiomeType::DESERT) { + if ((m_chunk.biome() == BiomeType::DESERT) || + (m_chunk.biome() == BiomeType::OCEAN)) { path.clear_chunk(chunk_pos); continue; } diff --git a/src/gameplay/tree.cpp b/src/gameplay/tree.cpp index 26d1dea..e717ac7 100644 --- a/src/gameplay/tree.cpp +++ b/src/gameplay/tree.cpp @@ -1,7 +1,6 @@ #include "Cubed/gameplay/tree.hpp" #include "Cubed/gameplay/chunk.hpp" -#include "Cubed/tools/log.hpp" #include @@ -32,7 +31,6 @@ bool build_tree(Chunk& chunk, const glm::ivec3& pos) { auto& block = chunk.get_chunk_blocks(); if (block[Chunk::index(pos)] != 1) { - Logger::info("Root is not Grass Block"); return false; } for (const auto& d : TREE) { diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index 8d4197b..c2c7c37 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -320,7 +320,9 @@ void World::gen_chunks_internal() { m_chunk_gen_finished = false; ChunkPosSet required_chunks; ChunkHashMap temp_neighbor; - compute_required_chunks(required_chunks, temp_neighbor); + std::vector need_gen_temp_chunks_pos; + compute_required_chunks(required_chunks, temp_neighbor, + need_gen_temp_chunks_pos); ASSERT_MSG(!required_chunks.empty(), "required chunks is empty!!"); @@ -339,10 +341,13 @@ void World::gen_chunks_internal() { m_chunk_gen_fraction = 0.1f; ChunkUpdateList new_chunks; + ChunkHashMap new_temp_chunks; for (auto& pos : need_gen_chunks_pos) { new_chunks.push_back({pos, Chunk(*this, pos)}); } - + for (auto& pos : need_gen_temp_chunks_pos) { + new_temp_chunks.emplace(pos, Chunk(*this, pos)); + } ConstChunkMap new_chunks_neighbor; // affected neighbor ChunkPtrUpdateList affected_neighbor; @@ -357,13 +362,15 @@ void World::gen_chunks_internal() { m_cave_carcer.try_to_add_path(pos, chunk.seed()); m_river_worm.try_to_add_path(pos, chunk.seed()); } + for (auto& [pos, chunk] : new_temp_chunks) { + chunk.gen_phase_one(); + } // precompute path to ensure the continuity of the path for (auto& [pos, chunk] : temp_neighbor) { chunk.gen_phase_one(); m_cave_carcer.try_to_add_path(pos, chunk.seed()); m_river_worm.try_to_add_path(pos, chunk.seed()); } - m_chunk_gen_fraction = 0.2f; /* @@ -403,6 +410,9 @@ void World::gen_chunks_internal() { for (auto& [pos, chunks] : new_chunks) { chunks.gen_phase_three(); } + for (auto& [pos, chunk] : new_temp_chunks) { + chunk.gen_phase_three(); + } // for (auto& [pos, chunks] : temp_neighbor) { // chunks.gen_phase_three(); // } @@ -457,7 +467,9 @@ void World::gen_chunks_internal() { for (auto& [pos, chunks] : new_chunks) { chunks.gen_phase_five(); } - + for (auto& [pos, chunk] : new_temp_chunks) { + chunk.gen_phase_five(); + } /* for (auto& [pos, chunks] : temp_neighbor) { chunks.gen_phase_five(); @@ -472,7 +484,14 @@ void World::gen_chunks_internal() { auto neighbor_pos = pos + CHUNK_DIR[i]; auto it = new_chunks_neighbor.find(neighbor_pos); if (it == new_chunks_neighbor.end()) { - neighbor_blocks_data[i] = std::nullopt; + auto it = new_temp_chunks.find(neighbor_pos); + if (it == new_temp_chunks.end()) { + neighbor_blocks_data[i] = std::nullopt; + Logger::warn( + "Can't find neighbor for chunk surface blend"); + continue; + } + neighbor_blocks_data[i] = it->second.get_chunk_blocks(); continue; } neighbor_blocks_data[i] = it->second->get_chunk_blocks(); @@ -539,8 +558,9 @@ void World::sync_player_pos(glm::vec3& player_pos) { player_pos = m_gen_player_pos; } -void World::compute_required_chunks(ChunkPosSet& required_chunks, - ChunkHashMap& temp_neighbor) { +void World::compute_required_chunks( + ChunkPosSet& required_chunks, ChunkHashMap& temp_neighbor, + std::vector& need_gen_temp_chunks_pos) { glm::vec3 player_pos; sync_player_pos(player_pos); @@ -555,6 +575,15 @@ void World::compute_required_chunks(ChunkPosSet& required_chunks, required_chunks.emplace(u, v); } } + int new_half = half + 1; + for (int u = chunk_x - new_half; u <= chunk_x + new_half; ++u) { + for (int v = chunk_z - new_half; v <= chunk_z + new_half; ++v) { + auto it = required_chunks.find({u, v}); + if (it == required_chunks.end()) { + need_gen_temp_chunks_pos.push_back({u, v}); + } + } + } int max_path_len = std::max(CavePath::step_max(), RiverPath::step_max()); half = std::ceil(static_cast(max_path_len) / CHUNK_SIZE) * 2; for (int u = chunk_x - half; u <= chunk_x + half; ++u) { diff --git a/src/tools/math_tools.cpp b/src/tools/math_tools.cpp index c69803e..6f29107 100644 --- a/src/tools/math_tools.cpp +++ b/src/tools/math_tools.cpp @@ -59,7 +59,12 @@ bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents, } return true; } - +float deterministic_random(int x, int z, uint64_t seed) { + uint64_t h = seed; + h = h * 6364136223846793005ULL + (uint64_t)x; + h = h * 6364136223846793005ULL + (uint64_t)z; + return (float)(h >> 40) / (float)(1 << 24); +} } // namespace Math } // namespace Cubed \ No newline at end of file