mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-17 16:17:02 +08:00
refactor: river (#10)
* fix: correct snowy grass block texture * refactor: river generation * fix: water placement error due to interpolation * perf: improve river naturalness * feat: add river tab item * fix: path truncation
This commit is contained in:
@@ -47,6 +47,7 @@ private:
|
||||
void show_about_table_bar();
|
||||
void show_biome_table_bar();
|
||||
void show_cave_table_bar();
|
||||
void show_river_table_bar();
|
||||
void show_settings_tab_item();
|
||||
void show_world_tab_item();
|
||||
void show_player_tab_item();
|
||||
|
||||
@@ -12,6 +12,5 @@ public:
|
||||
|
||||
protected:
|
||||
void build_bottom();
|
||||
void fill_water();
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -4,10 +4,10 @@ namespace Cubed {
|
||||
class CaveCarver {
|
||||
public:
|
||||
CaveCarver();
|
||||
std::unordered_map<int, CavePath>& paths();
|
||||
std::unordered_map<unsigned, CavePath>& paths();
|
||||
void init(unsigned world_seed);
|
||||
void reload(unsigned world_seed);
|
||||
void add_path(const glm::vec3& pos);
|
||||
void add_path(const glm::vec3& pos, unsigned chunk_seed);
|
||||
void try_to_add_path(const ChunkPos& pos, unsigned chunk_seed);
|
||||
void cleanup_finished_caves();
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
float& cave_probability();
|
||||
|
||||
private:
|
||||
std::unordered_map<int, CavePath> m_paths;
|
||||
std::unordered_map<unsigned, CavePath> m_paths;
|
||||
unsigned m_seed = 0;
|
||||
int m_sum = 0;
|
||||
Random m_random;
|
||||
|
||||
@@ -1,47 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path_point.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_set>
|
||||
namespace Cubed {
|
||||
|
||||
struct PathPoint {
|
||||
glm::vec3 pos;
|
||||
glm::vec3 tangent{0.0f, 0.0f, 1.0f};
|
||||
float rad_xz;
|
||||
float rad_y;
|
||||
PathPoint(const glm::vec3& p, float rx, float ry)
|
||||
: pos(p), rad_xz(rx), rad_y(ry) {}
|
||||
bool contains(const glm::vec3& other_pos) const {
|
||||
glm::vec3 to_point = other_pos - pos;
|
||||
|
||||
glm::vec3 world_up(0.0f, 1.0f, 0.0f);
|
||||
|
||||
glm::vec3 right = glm::normalize(glm::cross(tangent, world_up));
|
||||
|
||||
if (glm::length(right) < 0.001f) {
|
||||
glm::vec3 alt_up(1.0f, 0.0f, 0.0f);
|
||||
right = glm::normalize(glm::cross(tangent, alt_up));
|
||||
}
|
||||
|
||||
glm::vec3 up = glm::normalize(glm::cross(right, tangent));
|
||||
|
||||
float horizontal_dist = glm::dot(to_point, right);
|
||||
float vertical_dist = glm::dot(to_point, up);
|
||||
|
||||
float a = rad_xz;
|
||||
float b = rad_y;
|
||||
if (a <= 0.0f || b <= 0.0f)
|
||||
return false;
|
||||
|
||||
float check = (horizontal_dist * horizontal_dist) / (a * a) +
|
||||
(vertical_dist * vertical_dist) / (b * b);
|
||||
return check <= 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
class CavePath {
|
||||
public:
|
||||
CavePath(unsigned int world_seed, int path_id, const glm::vec3& start_pos);
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
Random& random();
|
||||
const std::array<BiomeType, 8>& neighbor_biome() const;
|
||||
void generate_cave();
|
||||
void generate_river();
|
||||
|
||||
private:
|
||||
static inline std::atomic<bool> is_init{false};
|
||||
|
||||
36
include/Cubed/gameplay/path_point.hpp
Normal file
36
include/Cubed/gameplay/path_point.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <glm/glm.hpp>
|
||||
struct PathPoint {
|
||||
glm::vec3 pos;
|
||||
glm::vec3 tangent{0.0f, 0.0f, 1.0f};
|
||||
float rad_xz;
|
||||
float rad_y;
|
||||
PathPoint(const glm::vec3& p, float rx, float ry)
|
||||
: pos(p), rad_xz(rx), rad_y(ry) {}
|
||||
bool contains(const glm::vec3& other_pos) const {
|
||||
glm::vec3 to_point = other_pos - pos;
|
||||
|
||||
glm::vec3 world_up(0.0f, 1.0f, 0.0f);
|
||||
|
||||
glm::vec3 right = glm::normalize(glm::cross(tangent, world_up));
|
||||
|
||||
if (glm::length(right) < 0.001f) {
|
||||
glm::vec3 alt_up(1.0f, 0.0f, 0.0f);
|
||||
right = glm::normalize(glm::cross(tangent, alt_up));
|
||||
}
|
||||
|
||||
glm::vec3 up = glm::normalize(glm::cross(right, tangent));
|
||||
|
||||
float horizontal_dist = glm::dot(to_point, right);
|
||||
float vertical_dist = glm::dot(to_point, up);
|
||||
|
||||
float a = rad_xz;
|
||||
float b = rad_y;
|
||||
if (a <= 0.0f || b <= 0.0f)
|
||||
return false;
|
||||
|
||||
float check = (horizontal_dist * horizontal_dist) / (a * a) +
|
||||
(vertical_dist * vertical_dist) / (b * b);
|
||||
return check <= 1.0f;
|
||||
}
|
||||
};
|
||||
52
include/Cubed/gameplay/river.path.hpp
Normal file
52
include/Cubed/gameplay/river.path.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path_point.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Cubed {
|
||||
class RiverPath {
|
||||
|
||||
public:
|
||||
RiverPath(unsigned int world_seed, int path_id, const glm::vec3& start_pos);
|
||||
const std::vector<PathPoint>& points() const;
|
||||
void clear_chunk(const ChunkPos& pos);
|
||||
bool is_finished() const;
|
||||
|
||||
static float& radius_xz_min();
|
||||
static float& radius_xz_max();
|
||||
static float& radius_y_min();
|
||||
static float& radius_y_max();
|
||||
static float& delta_angle_min();
|
||||
static float& delta_angle_max();
|
||||
static int& step_min();
|
||||
static int& step_max();
|
||||
|
||||
private:
|
||||
static inline float m_radius_xz_min = 5.0f;
|
||||
static inline float m_radius_xz_max = 10.0f;
|
||||
static inline float m_radius_y_min = 4.0f;
|
||||
static inline float m_radius_y_max = 8.0f;
|
||||
static inline float m_delta_angle_min = -3.0f;
|
||||
static inline float m_delta_angle_max = 3.0f;
|
||||
static inline int m_step_min = 150;
|
||||
static inline int m_step_max = 400;
|
||||
|
||||
int m_path_id = 0;
|
||||
unsigned int m_seed = 0;
|
||||
float m_yaw = 0.0f;
|
||||
float m_pitch = 0.0f;
|
||||
int m_step = 0;
|
||||
float m_step_len = 1.0f;
|
||||
PathPoint m_start_path_point{{0.0f, 0.0f, 0.0f}, 0.0f, 0.0f};
|
||||
Random m_random;
|
||||
|
||||
std::vector<PathPoint> m_points;
|
||||
std::unordered_set<ChunkPos, ChunkPos::Hash> m_pending_chunks;
|
||||
void collect_path_points();
|
||||
void precompute_chunk_coverage();
|
||||
};
|
||||
} // namespace Cubed
|
||||
31
include/Cubed/gameplay/river_worm.hpp
Normal file
31
include/Cubed/gameplay/river_worm.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/river.path.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
|
||||
class RiverWorm {
|
||||
public:
|
||||
RiverWorm();
|
||||
std::unordered_map<unsigned, RiverPath>& paths();
|
||||
void init(unsigned world_seed);
|
||||
void reload(unsigned world_seed);
|
||||
void add_path(const glm::vec3& pos, unsigned chunk_seed);
|
||||
void try_to_add_path(const ChunkPos& pos, unsigned chunk_seed);
|
||||
void cleanup_finished_rivers();
|
||||
|
||||
int river_sum() const;
|
||||
float& river_probability();
|
||||
|
||||
private:
|
||||
std::unordered_map<unsigned, RiverPath> m_paths;
|
||||
unsigned m_seed = 0;
|
||||
int m_sum = 0;
|
||||
Random m_random;
|
||||
float m_probability = 0.01f;
|
||||
};
|
||||
|
||||
}; // namespace Cubed
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Cubed/AABB.hpp"
|
||||
#include "Cubed/gameplay/cave_carver.hpp"
|
||||
#include "Cubed/gameplay/chunk.hpp"
|
||||
#include "Cubed/gameplay/river_worm.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
@@ -56,19 +57,19 @@ private:
|
||||
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk_queue;
|
||||
|
||||
CaveCarver m_cave_carcer;
|
||||
|
||||
RiverWorm m_river_worm;
|
||||
void init_chunks();
|
||||
|
||||
void gen_chunks_internal();
|
||||
void sync_player_pos(glm::vec3& player_pos);
|
||||
void compute_required_chunks(ChunkPosSet& required_chunks);
|
||||
void compute_required_chunks(ChunkPosSet& required_chunks,
|
||||
ChunkHashMap& temp_neighbor);
|
||||
void sync_and_collect_missing_chunks(std::vector<ChunkPos>&,
|
||||
const ChunkPosSet&);
|
||||
void
|
||||
build_neighbor_context_for_new_chunks(ConstChunkMap& new_chunks_neighbor,
|
||||
ChunkPtrUpdateList& affected_neighbor,
|
||||
const ChunkUpdateList& new_chunks,
|
||||
ChunkHashMap& temp_neighbor);
|
||||
const ChunkUpdateList& new_chunks);
|
||||
void build_neighbor_context_for_affected_neighbors(ChunkPtrUpdateList&,
|
||||
ConstChunkMap&);
|
||||
|
||||
@@ -112,6 +113,7 @@ public:
|
||||
void stop_gen_thread();
|
||||
|
||||
CaveCarver& cave_carcer();
|
||||
RiverWorm& river_worm();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
Reference in New Issue
Block a user