diff --git a/include/Cubed/dev_panel.hpp b/include/Cubed/dev_panel.hpp index fa2e793..390d2a8 100644 --- a/include/Cubed/dev_panel.hpp +++ b/include/Cubed/dev_panel.hpp @@ -36,6 +36,7 @@ private: TextEditing m_text_editing; bool m_need_save_config = false; int m_theme = 0; + void show_biome_table_bar(); void show_settings_tab_item(); void show_world_tab_item(); void show_player_tab_item(); diff --git a/include/Cubed/gameplay/biome.hpp b/include/Cubed/gameplay/biome.hpp index 4fe8f21..5bc4f93 100644 --- a/include/Cubed/gameplay/biome.hpp +++ b/include/Cubed/gameplay/biome.hpp @@ -31,10 +31,40 @@ struct BiomeNonAdjacent { Biome replace; }; +struct BaseBiomeParams { + Biome biome; + std::pair temp; + std::pair humid; + std::array frequencies; + BiomeHeightRange height_range; +}; + +struct PlainParams : public BaseBiomeParams { + +}; + +struct ForestParams : public BaseBiomeParams { + float tree_frequency; +}; + +struct DesertParams : public BaseBiomeParams { + +}; + +struct MountainParams : public BaseBiomeParams { + +}; + std::string get_biome_str(Biome biome); Biome get_biome_from_noise(float temp, float humid); std::array get_noise_frequencies_for_biome(Biome biome); BiomeHeightRange get_biome_height_range(Biome biome); Biome safe_int_to_biome(int x); int get_interpolated_height(float world_x, float world_z, float temp, float humid); + +PlainParams& plain_params(); +ForestParams& forest_params(); +DesertParams& desert_params(); +MountainParams& mountain_params(); + } diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index 619725c..26e5ede 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -47,6 +47,7 @@ private: std::atomic m_is_rebuilding {false}; std::atomic m_could_gen{true}; std::atomic m_rendering_distance{24}; + std::atomic m_chunk_gen_fraction{0.0f}; std::vector m_dirty_queue; std::vector m_render_snapshots; std::vector> m_new_chunk; @@ -95,6 +96,9 @@ public: void rebuild_world(); + float chunk_gen_fraction() const; + int rendering_distance() const; + void rendering_distance(int rendering_distance); }; } diff --git a/src/dev_panel.cpp b/src/dev_panel.cpp index fa4012c..2089b37 100644 --- a/src/dev_panel.cpp +++ b/src/dev_panel.cpp @@ -15,6 +15,23 @@ static constexpr const char* GAITS[] = {"Walk", "Run"}; static constexpr const char* GAME_MODES[] = {"Creative", "Spectator"}; static char perlin_noise_input_buffer[64]; +constexpr float TEMP_MIN = 0.0f; +constexpr float TEMP_MAX = 1.0f; +constexpr float HUMID_MIN = 0.0f; +constexpr float HUMID_MAX = 1.0f; +constexpr float FREQ1_MIN = 0.001f; +constexpr float FREQ1_MAX = 0.020f; +constexpr float FREQ2_MIN = 0.005f; +constexpr float FREQ2_MAX = 0.050f; +constexpr float FREQ3_MIN = 0.010f; +constexpr float FREQ3_MAX = 0.080f; +constexpr int HEIGHT_BASE_MIN = 50; +constexpr int HEIGHT_BASE_MAX = 175; +constexpr int AMPLITUDE_MIN = 2; +constexpr int AMPLITUDE_MAX = 80; +constexpr float TREE_FREQ_MIM = 0.001f; +constexpr float TREE_FREQ_MAX = 0.3f; + static int filter_unsigned(ImGuiInputTextCallbackData* data) { if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter) { char c = data->EventChar; @@ -66,7 +83,7 @@ void DevPanel::render() { ImGui::Begin("DevPanel"); ImGui::Text("This is a DevPanel to control the game\n"); - if (ImGui::BeginTabBar("Bar")) { + if (ImGui::BeginTabBar("Menu")) { show_settings_tab_item(); show_world_tab_item(); show_player_tab_item(); @@ -78,6 +95,62 @@ void DevPanel::render() { } +void DevPanel::show_biome_table_bar() { + ImGui::Text("Biome"); + if (ImGui::BeginTabBar("Biome")) { + if (ImGui::BeginTabItem("Plain")) { + ImGui::SliderFloat("MinTemp##plain", &plain_params().temp.first, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MaxTemp##plain", &plain_params().temp.second, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MinHumid##plain", &plain_params().humid.first, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("MaxHumid##plain", &plain_params().humid.second, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("Freq One##plain", &plain_params().frequencies[0], FREQ1_MIN, FREQ1_MAX); + ImGui::SliderFloat("Freq Two##plain", &plain_params().frequencies[1], FREQ2_MIN, FREQ2_MAX); + ImGui::SliderFloat("Freq Three##plain", &plain_params().frequencies[2], FREQ3_MIN, FREQ3_MAX); + ImGui::SliderInt("Base Y##plain", &plain_params().height_range.base_y, HEIGHT_BASE_MIN, HEIGHT_BASE_MAX); + ImGui::SliderInt("Amplitude##plain", &plain_params().height_range.amplitude, AMPLITUDE_MIN, AMPLITUDE_MAX); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Forest")) { + ImGui::SliderFloat("MinTemp##forest", &forest_params().temp.first, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MaxTemp##forest", &forest_params().temp.second, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MinHumid##forest", &forest_params().humid.first, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("MaxHumid##forest", &forest_params().humid.second, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("Freq One##forest", &forest_params().frequencies[0], FREQ1_MIN, FREQ1_MAX); + ImGui::SliderFloat("Freq Two##forest", &forest_params().frequencies[1], FREQ2_MIN, FREQ2_MAX); + ImGui::SliderFloat("Freq Three##forest", &forest_params().frequencies[2], FREQ3_MIN, FREQ3_MAX); + ImGui::SliderInt("Base Y##forest", &forest_params().height_range.base_y, HEIGHT_BASE_MIN, HEIGHT_BASE_MAX); + ImGui::SliderInt("Amplitude##forest", &forest_params().height_range.amplitude, AMPLITUDE_MIN, AMPLITUDE_MAX); + ImGui::SliderFloat("Tree Freq##forest", &forest_params().tree_frequency, TREE_FREQ_MIM, TREE_FREQ_MAX); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Desert")) { + ImGui::SliderFloat("MinTemp##desert", &desert_params().temp.first, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MaxTemp##desert", &desert_params().temp.second, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MinHumid##desert", &desert_params().humid.first, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("MaxHumid##desert", &desert_params().humid.second, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("Freq One##desert", &desert_params().frequencies[0], FREQ1_MIN, FREQ1_MAX); + ImGui::SliderFloat("Freq Two##desert", &desert_params().frequencies[1], FREQ2_MIN, FREQ2_MAX); + ImGui::SliderFloat("Freq Three##desert", &desert_params().frequencies[2], FREQ3_MIN, FREQ3_MAX); + ImGui::SliderInt("Base Y##desert", &desert_params().height_range.base_y, HEIGHT_BASE_MIN, HEIGHT_BASE_MAX); + ImGui::SliderInt("Amplitude##desert", &desert_params().height_range.amplitude, AMPLITUDE_MIN, AMPLITUDE_MAX); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Mountain")) { + ImGui::SliderFloat("MinTemp##mountain", &mountain_params().temp.first, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MaxTemp##mountain", &mountain_params().temp.second, TEMP_MIN, TEMP_MAX); + ImGui::SliderFloat("MinHumid##mountain", &mountain_params().humid.first, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("MaxHumid##mountain", &mountain_params().humid.second, HUMID_MIN, HUMID_MAX); + ImGui::SliderFloat("Freq One##mountain", &mountain_params().frequencies[0], FREQ1_MIN, FREQ1_MAX); + ImGui::SliderFloat("Freq Two##mountain", &mountain_params().frequencies[1], FREQ2_MIN, FREQ2_MAX); + ImGui::SliderFloat("Freq Three##mountain", &mountain_params().frequencies[2], FREQ3_MIN, FREQ3_MAX); + ImGui::SliderInt("Base Y##mountain", &mountain_params().height_range.base_y, HEIGHT_BASE_MIN, HEIGHT_BASE_MAX); + ImGui::SliderInt("Amplitude##mountain", &mountain_params().height_range.amplitude, AMPLITUDE_MIN, AMPLITUDE_MAX); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } +} + void DevPanel::show_settings_tab_item() { if (ImGui::BeginTabItem("settings")) { if(ImGui::SliderFloat("FOV", &m_config.fov, 1.0f, 140.0f)) { @@ -149,9 +222,24 @@ void DevPanel::show_world_tab_item() { m_text_editing.perlin_seed = true; } } + static int rendering_distance = m_app.world().rendering_distance(); + if (ImGui::SliderInt("Render Distance", &rendering_distance, 2, 128)) { + m_app.world().rendering_distance(rendering_distance); + } if (ImGui::Button("Rebuild World")) { m_app.world().rebuild_world(); } + ImGui::SameLine(); + if (ImGui::Button("Request Chunk Build")) { + m_app.world().need_gen(); + } + ImGui::SameLine(); + if (ImGui::Button("Spawn Point")) { + m_player->set_player_pos({0.0f, 255.0f, 0.0f}); + } + ImGui::Text("Chunk Build Progress\n"); + ImGui::ProgressBar(m_app.world().chunk_gen_fraction()); + show_biome_table_bar(); ImGui::EndTabItem(); } } diff --git a/src/gameplay/biome.cpp b/src/gameplay/biome.cpp index 3fec711..bc9044f 100644 --- a/src/gameplay/biome.cpp +++ b/src/gameplay/biome.cpp @@ -8,6 +8,48 @@ namespace Cubed { +static PlainParams plain { + { + Biome::PLAIN, + {0.0f, 0.5f}, + {0.0f, 0.5f}, + {0.003f, 0.010f, 0.020f}, + {62, 8} + } +}; + +static ForestParams forest { + { + Biome::FOREST, + {0.5f, 1.0f}, + {0.5f, 1.0f}, + {0.004f, 0.012f, 0.022f}, + {64, 12} + }, + 0.1f + +}; + +static DesertParams desert { + { + Biome::DESERT, + {0.5f, 1.0f}, + {0.0f, 0.5f}, + {0.003f, 0.010f, 0.020f}, + {61, 12} + } +}; + +static MountainParams mountain { + { + Biome::MOUNTAIN, + {0.0f, 0.5f}, + {0.5f, 1.0f}, + {0.006f, 0.015f, 0.030f}, + {70, 70} + } +}; + std::string get_biome_str(Biome biome) { std::string str; using enum Biome; @@ -51,22 +93,32 @@ Biome get_biome_from_noise(float temp, float humid) { */ Biome get_biome_from_noise(float temp, float humid) { using enum Biome; - if (temp < 0.5f && humid < 0.5f) return PLAIN; - if (temp < 0.5f && humid >= 0.5f) return FOREST; - if (temp >= 0.5f && humid < 0.5f) return DESERT; - return MOUNTAIN; + 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 get_noise_frequencies_for_biome(Biome biome) { using enum Biome; switch (biome) { case PLAIN: - return {0.003f, 0.010f, 0.020f}; + return plain.frequencies; case FOREST: - return {0.004f, 0.012f, 0.022f}; + return forest.frequencies; case DESERT: - return {0.003f, 0.010f, 0.020f}; + return desert.frequencies; case MOUNTAIN: - return {0.006f, 0.015f, 0.030f}; + return mountain.frequencies; case NONE: ASSERT_MSG(false, "Chunk Biome is None"); throw std::invalid_argument{"Chunk Biome is None"}; @@ -79,13 +131,13 @@ BiomeHeightRange get_biome_height_range(Biome biome) { using enum Biome; switch (biome) { case PLAIN: - return {62, 8}; + return plain.height_range; case FOREST: - return {64, 12}; + return forest.height_range; case DESERT: - return {61, 12}; + return desert.height_range; case MOUNTAIN: - return {70, 70}; + return mountain.height_range; case NONE: ASSERT_MSG(false, "Chunk Biome is None"); throw std::invalid_argument{"Chunk Biome is None"}; @@ -149,5 +201,18 @@ int get_interpolated_height(float world_x, float world_z, float temp, float humi return static_cast(h); } +PlainParams& plain_params() { + return plain; +} +ForestParams& forest_params() { + return forest; +} +DesertParams& desert_params() { + return desert; +} +MountainParams& mountain_params() { + return mountain; +} + } diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index 4dfc3d4..952d67c 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -387,7 +387,7 @@ void Chunk::gen_phase_six() { std::shuffle(z_arr.begin(), z_arr.end(), Cubed::Random::get().engine()); for (auto x : x_arr) { for (auto z : z_arr) { - if (Cubed::Random::get().random_bool(0.1)) { + if (Cubed::Random::get().random_bool(forest_params().tree_frequency)) { build_tree(*this, {x, static_cast(m_heightmap[x][z]), z}); } diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index d18058a..f427e33 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -265,7 +265,7 @@ ChunkPos World::chunk_pos(int world_x, int world_z) { } void World::gen_chunks_internal() { - + m_chunk_gen_fraction = 0.0f; ChunkPosSet required_chunks; compute_required_chunks(required_chunks); @@ -277,8 +277,10 @@ void World::gen_chunks_internal() { Logger::info("New Gen Chunks Sum: {}", need_gen_chunks_pos.size()); if (need_gen_chunks_pos.empty()) { m_could_gen = true; + m_chunk_gen_fraction = 1.0f; return; } + m_chunk_gen_fraction = 0.1f; ChunkUpdateList new_chunks; for (auto& pos : need_gen_chunks_pos) { new_chunks.push_back({pos, Chunk(*this, pos)}); @@ -295,7 +297,7 @@ void World::gen_chunks_internal() { for (auto& [pos, chunk] : new_chunks) { chunk.gen_phase_one(); } - + m_chunk_gen_fraction = 0.2f; std::array neighbor_chunks; for (auto& [pos, chunks] : new_chunks) { for (int i = 0; i < 4; i++) { @@ -310,10 +312,11 @@ void World::gen_chunks_internal() { } chunks.gen_phase_two(neighbor_chunks); } - + m_chunk_gen_fraction = 0.3f; for (auto& [pos, chunks] : new_chunks) { chunks.gen_phase_three(); } + m_chunk_gen_fraction = 0.4f; std::array, 4> neighbor_chunk_heightmap; for (auto& [pos, chunks] : new_chunks) { { @@ -330,12 +333,12 @@ void World::gen_chunks_internal() { } chunks.gen_phase_four(neighbor_chunk_heightmap); } - + m_chunk_gen_fraction = 0.5f; for (auto& [pos, chunks] : new_chunks) { chunks.gen_phase_five(); chunks.gen_phase_six(); } - + m_chunk_gen_fraction = 0.6f; for (auto& [pos, chunk] : new_chunks) { for (int i = 0; i < 4; i++) { auto it = new_chunks_neighbor.find(pos + CHUNK_DIR[i]); @@ -347,8 +350,9 @@ void World::gen_chunks_internal() { } chunk.gen_vertex_data(neighbor_block); } + m_chunk_gen_fraction = 0.7f; build_neighbor_context_for_affected_neighbors(affected_neighbor, new_chunks_neighbor); - + m_chunk_gen_fraction = 0.8f; for (auto& [pos, chunk] : affected_neighbor) { for (int i = 0; i < 4; i++) { auto it = new_chunks_neighbor.find(pos + CHUNK_DIR[i]); @@ -361,7 +365,7 @@ void World::gen_chunks_internal() { chunk->gen_vertex_data(neighbor_block); chunk->need_upload(); } - + m_chunk_gen_fraction = 0.9f; { std::lock_guard lk(m_new_chunk_queue_mutex); for (auto& x : new_chunks) { @@ -369,7 +373,7 @@ void World::gen_chunks_internal() { } } - + m_chunk_gen_fraction = 1.0f; } void World::sync_player_pos(glm::vec3& player_pos) { @@ -690,9 +694,19 @@ void World::rebuild_world() { need_gen(); m_is_rebuilding = false; - for (auto& player : m_players) { - player.second.set_player_pos({0.0f, 255.0f, 0.0f}); - } + +} + +float World::chunk_gen_fraction() const { + return m_chunk_gen_fraction.load(); +} + +int World::rendering_distance() const { + return m_rendering_distance.load(); +} + +void World::rendering_distance(int rendering_distance) { + m_rendering_distance = rendering_distance; } } \ No newline at end of file