mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-04-09 21:54:09 +08:00
feat: add perlin noise
This commit is contained in:
@@ -93,6 +93,7 @@ add_executable(${PROJECT_NAME}
|
||||
src/tools/shader_tools.cpp
|
||||
src/tools/font.cpp
|
||||
src/tools/log.cpp
|
||||
src/tools/perlin_noise.cpp
|
||||
src/window.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
#pragma once
|
||||
constexpr int WORLD_SIZE_X = 32;
|
||||
constexpr int WORLD_SIZE_Z = 32;
|
||||
constexpr int WORLD_SIZE_Y = 16;
|
||||
constexpr int WORLD_SIZE_Y = 256;
|
||||
constexpr int MAX_BLOCK_NUM = 2;
|
||||
constexpr int MAX_UI_NUM = 1;
|
||||
|
||||
constexpr int CHUCK_SIZE = 16;
|
||||
constexpr int DISTANCE = 8;
|
||||
constexpr int DISTANCE = 16;
|
||||
constexpr int MAX_BLOCK_STATUS = 1;
|
||||
constexpr int MAX_CHARACTER = 128;
|
||||
constexpr float FOV = 70.0f;
|
||||
|
||||
constexpr int SEED = 999;
|
||||
|
||||
constexpr float VERTICES_POS[6][6][3] = {
|
||||
// ===== front (z = +1) =====
|
||||
0.0f, 0.0f, 1.0f, // bottom left
|
||||
|
||||
@@ -16,6 +16,9 @@ private:
|
||||
std::vector<uint8_t> m_blocks;
|
||||
GLuint m_vbo = 0;
|
||||
std::vector<Vertex> m_vertexs_data;
|
||||
|
||||
float frequency = 0.01f;
|
||||
float height = 80;
|
||||
|
||||
public:
|
||||
Chunk(World& world, ChunkPos chunk_pos);
|
||||
|
||||
@@ -21,7 +21,8 @@ private:
|
||||
|
||||
float m_sensitivity = 0.15f;
|
||||
|
||||
float max_speed = 4.5f;
|
||||
//float max_speed = 4.5f;
|
||||
float max_speed = 7.5f;
|
||||
float y_speed = 0.0f;
|
||||
bool can_up = true;
|
||||
float speed = 0;
|
||||
@@ -29,7 +30,7 @@ private:
|
||||
glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
glm::vec3 move_distance {0.0f, 0.0f, 0.0f};
|
||||
// player is tow block tall, the pos is the lower pos
|
||||
glm::vec3 m_player_pos {0.0f, 15.0f, 0.0f};
|
||||
glm::vec3 m_player_pos {0.0f, 120.0f, 0.0f};
|
||||
glm::vec3 m_front {0, 0, -1};
|
||||
glm::vec3 m_right {0, 0, 0};
|
||||
glm::vec3 m_size {0.6f, 1.8f, 0.6f};
|
||||
|
||||
16
include/Cubed/tools/perlin_noise.hpp
Normal file
16
include/Cubed/tools/perlin_noise.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
class PerlinNoise {
|
||||
public:
|
||||
static void init();
|
||||
static float noise(float x, float y, float z);
|
||||
private:
|
||||
static inline bool is_init = false;
|
||||
static inline std::vector<int> p;
|
||||
|
||||
static float fade(float t);
|
||||
static float lerp(float t, float a, float b);
|
||||
static float grad(int hash, float x, float y, float z);
|
||||
};
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Cubed/map_table.hpp>
|
||||
#include <Cubed/tools/cubed_assert.hpp>
|
||||
#include <Cubed/tools/log.hpp>
|
||||
#include <Cubed/tools/perlin_noise.hpp>
|
||||
|
||||
#include <exception>
|
||||
|
||||
@@ -30,7 +31,8 @@ void App::init() {
|
||||
glfwSetWindowSizeCallback(m_window.get_glfw_window(), window_reshape_callback);
|
||||
glfwSetKeyCallback(m_window.get_glfw_window(), key_callback);
|
||||
|
||||
|
||||
PerlinNoise::init();
|
||||
|
||||
m_renderer.init();
|
||||
Logger::info("Renderer Init Success");
|
||||
m_window.update_viewport();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <Cubed/gameplay/chunk.hpp>
|
||||
#include <Cubed/gameplay/world.hpp>
|
||||
#include <Cubed/tools/cubed_assert.hpp>
|
||||
#include <Cubed/tools/log.hpp>
|
||||
#include <Cubed/tools/perlin_noise.hpp>
|
||||
Chunk::Chunk(World& world, ChunkPos chunk_pos) :
|
||||
m_world(world),
|
||||
m_chunk_pos(chunk_pos)
|
||||
@@ -18,15 +20,19 @@ const std::vector<uint8_t>& Chunk::get_chunk_blocks() const{
|
||||
|
||||
|
||||
int Chunk::get_index(int x, int y, int z) {
|
||||
return x * CHUCK_SIZE * CHUCK_SIZE + y * CHUCK_SIZE + z;
|
||||
if ((x * WORLD_SIZE_Y + y) * CHUCK_SIZE + z < 0 || (x * WORLD_SIZE_Y + y) * CHUCK_SIZE + z >= CHUCK_SIZE * CHUCK_SIZE * WORLD_SIZE_Y) {
|
||||
Logger::error("block pos x {} y {} z {} range error", x, y, z);
|
||||
CUBED_ASSERT(0);
|
||||
}
|
||||
return (x * WORLD_SIZE_Y + y) * CHUCK_SIZE + z;
|
||||
}
|
||||
|
||||
void Chunk::gen_vertex_data() {
|
||||
m_vertexs_data.clear();
|
||||
glDeleteBuffers(1, &m_vbo);
|
||||
for (int x = 0; x < CHUCK_SIZE; x++) {
|
||||
for (int z = 0; z < CHUCK_SIZE; z++) {
|
||||
for (int y = 0; y < CHUCK_SIZE; y++) {
|
||||
for (int y = 0; y < WORLD_SIZE_Y; y++) {
|
||||
for (int z = 0; z < CHUCK_SIZE; z++) {
|
||||
int world_x = x + m_chunk_pos.x * CHUCK_SIZE;
|
||||
int world_z = z + m_chunk_pos.z * CHUCK_SIZE;
|
||||
int world_y = y;
|
||||
@@ -73,7 +79,7 @@ const std::vector<Vertex>& Chunk::get_vertex_data() const{
|
||||
}
|
||||
|
||||
void Chunk::init_chunk() {
|
||||
m_blocks.assign(CHUCK_SIZE * CHUCK_SIZE * CHUCK_SIZE, 0);
|
||||
m_blocks.assign(CHUCK_SIZE * CHUCK_SIZE * WORLD_SIZE_Y, 0);
|
||||
for (int x = 0; x < CHUCK_SIZE; x++) {
|
||||
for (int y = 0; y < 5; y++) {
|
||||
for (int z = 0; z < CHUCK_SIZE; z++) {
|
||||
@@ -81,6 +87,26 @@ void Chunk::init_chunk() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < CHUCK_SIZE; x++) {
|
||||
for (int z = 0; z < CHUCK_SIZE; z++) {
|
||||
|
||||
float world_x = static_cast<float>(x + m_chunk_pos.x * CHUCK_SIZE);
|
||||
float world_z = static_cast<float>(z + m_chunk_pos.z * CHUCK_SIZE);
|
||||
|
||||
float noise =
|
||||
0.5f * PerlinNoise::noise(world_x * 0.01f, world_z * 0.01f, 0.5f) +
|
||||
0.25f * PerlinNoise::noise(world_x * 0.02f, world_z * 0.02f, 0.5f) +
|
||||
0.125f * PerlinNoise::noise(world_x * 0.04f, world_z * 0.04f, 0.5f);
|
||||
int y_max = height * noise;
|
||||
|
||||
for (int y = 5; y < y_max; y++) {
|
||||
m_blocks[get_index(x, y, z)] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -292,6 +292,7 @@ void Player::update_move(float delta_time) {
|
||||
|
||||
move_distance = {direction.x * speed * delta_time, 0.0f, direction.z * speed * delta_time};
|
||||
|
||||
/*
|
||||
if (m_move_state.up && can_up) {
|
||||
y_speed = 7.5;
|
||||
can_up = false;
|
||||
@@ -299,6 +300,19 @@ void Player::update_move(float delta_time) {
|
||||
}
|
||||
|
||||
y_speed += -G * delta_time;
|
||||
*/
|
||||
if (m_move_state.up) {
|
||||
y_speed = 7.5f;
|
||||
}
|
||||
|
||||
if (m_move_state.down) {
|
||||
y_speed = -7.5f;
|
||||
}
|
||||
|
||||
if (!m_move_state.down && !m_move_state.up) {
|
||||
y_speed = 0.0f;
|
||||
}
|
||||
|
||||
move_distance.y = y_speed * delta_time;
|
||||
// y
|
||||
update_y_move();
|
||||
@@ -308,7 +322,7 @@ void Player::update_move(float delta_time) {
|
||||
update_z_move();
|
||||
|
||||
if (m_player_pos.y < -15.0f) {
|
||||
m_player_pos = glm::vec3(0.0f, 20.0f, 0.0f);
|
||||
m_player_pos = glm::vec3(0.0f, 100.0f, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ void World::init_world() {
|
||||
m_chunks.emplace(pos, Chunk(*this, pos));
|
||||
}
|
||||
}
|
||||
Logger::info("Chunk Init Finish");
|
||||
|
||||
for (auto& chunk_map : m_chunks) {
|
||||
auto& [chunk_pos, chunk] = chunk_map;
|
||||
@@ -126,8 +125,8 @@ void World::render(const glm::mat4& mvp_matrix) {
|
||||
Math::extract_frustum_planes(mvp_matrix, m_planes);
|
||||
for (const auto& chunk_map : m_chunks) {
|
||||
const auto& [pos, chunk] = chunk_map;
|
||||
glm::vec3 center = glm::vec3(static_cast<float>(pos.x * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(pos.z * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2));
|
||||
if (is_aabb_in_frustum(center, glm::vec3(static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2)))) {
|
||||
glm::vec3 center = glm::vec3(static_cast<float>(pos.x * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(WORLD_SIZE_Y/ 2), static_cast<float>(pos.z * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2));
|
||||
if (is_aabb_in_frustum(center, glm::vec3(static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(WORLD_SIZE_Y / 2), static_cast<float>(CHUCK_SIZE / 2)))) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, chunk.get_vbo());
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, s));
|
||||
@@ -190,7 +189,7 @@ bool World::is_block(const glm::ivec3& block_pos) const{
|
||||
y = world_y;
|
||||
x = world_x - chunk_x * CHUCK_SIZE;
|
||||
z = world_z - chunk_z * CHUCK_SIZE;
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUCK_SIZE || y >= CHUCK_SIZE || z >= CHUCK_SIZE) {
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUCK_SIZE || y >= WORLD_SIZE_Y || z >= CHUCK_SIZE) {
|
||||
return false;
|
||||
}
|
||||
auto id = chunk_blocks[Chunk::get_index(x, y, z)];
|
||||
@@ -232,7 +231,7 @@ void World::set_block(const glm::ivec3& block_pos, unsigned id) {
|
||||
y = world_y;
|
||||
x = world_x - chunk_x * CHUCK_SIZE;
|
||||
z = world_z - chunk_z * CHUCK_SIZE;
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUCK_SIZE || y >= CHUCK_SIZE || z >= CHUCK_SIZE) {
|
||||
if (x < 0 || y < 0 || z < 0 || x >= CHUCK_SIZE || y >= WORLD_SIZE_Y || z >= CHUCK_SIZE) {
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
71
src/tools/perlin_noise.cpp
Normal file
71
src/tools/perlin_noise.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <Cubed/tools/perlin_noise.hpp>
|
||||
|
||||
#include <Cubed/config.hpp>
|
||||
#include <Cubed/tools/cubed_assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
|
||||
void PerlinNoise::init() {
|
||||
p.resize(256);
|
||||
std::iota(p.begin(), p.end(), 0);
|
||||
|
||||
std::mt19937 engine(SEED);
|
||||
std::shuffle(p.begin(), p.end(), engine);
|
||||
|
||||
p.insert(p.end(), p.begin(), p.end());
|
||||
is_init = true;
|
||||
}
|
||||
|
||||
float PerlinNoise::noise(float x, float y, float z) {
|
||||
CUBED_ASSERT_MSG(is_init, "The PerlinNoise don't init!");
|
||||
int ix = static_cast<int>(std::floor(x)) & 255;
|
||||
int iy = static_cast<int>(std::floor(y)) & 255;
|
||||
int iz = static_cast<int>(std::floor(z)) & 255;
|
||||
|
||||
x -= std::floor(x);
|
||||
y -= std::floor(y);
|
||||
z -= std::floor(z);
|
||||
|
||||
double u = fade(x);
|
||||
double v = fade(y);
|
||||
double w = fade(z);
|
||||
|
||||
int a = p[ix] + iy;
|
||||
int aa = p[a] + iz;
|
||||
int ab = p[a + 1] + iz;
|
||||
int b = p[ix + 1] + iy;
|
||||
int ba = p[b] + iz;
|
||||
int bb = p[b + 1] + iz;
|
||||
|
||||
float res = lerp (w,
|
||||
lerp (v,
|
||||
lerp(u, grad(p[aa], x, y, z), grad(p[ba], x - 1, y, z)),
|
||||
lerp(u, grad(p[ab], x, y - 1, z), grad(p[bb], x - 1, y - 1, z))
|
||||
),
|
||||
lerp(v,
|
||||
lerp(u, grad(p[aa + 1], x, y, z - 1), grad(p[ba + 1], x - 1, y, z - 1)),
|
||||
lerp(u, grad(p[ab + 1], x, y - 1, z - 1), grad(p[bb + 1 ], x - 1, y - 1, z - 1))
|
||||
)
|
||||
|
||||
);
|
||||
return (res + 1.0f) / 2.0f;
|
||||
}
|
||||
|
||||
float PerlinNoise::fade(float t) {
|
||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
float PerlinNoise::lerp(float t, float a, float b) {
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
float PerlinNoise::grad(int hash, float x, float y, float z) {
|
||||
int h = hash & 15;
|
||||
|
||||
float u = h < 8 ? x : y;
|
||||
float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||
|
||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||
}
|
||||
Reference in New Issue
Block a user