Compare commits

..

9 Commits

32 changed files with 418 additions and 179 deletions

View File

@@ -85,12 +85,14 @@ add_executable(${PROJECT_NAME}
src/gameplay/biome.cpp
src/gameplay/chunk.cpp
src/gameplay/player.cpp
src/gameplay/tree.cpp
src/gameplay/world.cpp
src/input.cpp
src/map_table.cpp
src/renderer.cpp
src/shader.cpp
src/texture_manager.cpp
src/tools/cubed_random.cpp
src/tools/math_tools.cpp
src/tools/shader_tools.cpp
src/tools/font.cpp
@@ -105,12 +107,14 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(${PROJECT_NAME} PRIVATE
-fsanitize=address
#-fsanitize=thread
-fno-omit-frame-pointer
-g
)
target_link_options(${PROJECT_NAME} PRIVATE
-fsanitize=address
#-fsanitize=thread
)
target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG_MODE)
@@ -135,6 +139,10 @@ target_link_libraries(${PROJECT_NAME}
Freetype::Freetype
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_link_libraries(${PROJECT_NAME} PRIVATE tbb)
endif()
if (UNIX AND NOT APPLE)
target_link_libraries(${PROJECT_NAME}
PRIVATE

View File

@@ -8,5 +8,8 @@ layout (binding = 0) uniform sampler2DArray samp;
void main(void) {
color = texture(samp, vec3(tc, tex_layer));
if (color.a < 0.5) {
discard;
}
//color = varyingColor;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

View File

@@ -6,6 +6,7 @@
#include <Cubed/renderer.hpp>
#include <Cubed/texture_manager.hpp>
#include <Cubed/window.hpp>
namespace Cubed {
class App {
public:
@@ -35,7 +36,6 @@ private:
inline static double fps_time_count = 0.0f;
inline static int frame_count = 0;
inline static int fps = 0;
inline static unsigned int m_seed = 0;
void init();
@@ -47,3 +47,5 @@ private:
void run();
void update();
};
}

View File

@@ -1,6 +1,6 @@
#pragma once
constexpr int WORLD_SIZE_Y = 256;
constexpr int MAX_BLOCK_NUM = 5;
constexpr int MAX_BLOCK_NUM = 7;
constexpr int MAX_UI_NUM = 1;
constexpr int CHUCK_SIZE = 16;

View File

@@ -4,9 +4,9 @@
constexpr float BIOME_NOISE_FREQUENCY = 0.003f;
constexpr float PLAIN_FREQ = 0.5f;
constexpr float FOREST_FREQ = 1.0f;
constexpr float DESERT_FREQ = 1.0f;
constexpr float PLAIN_FREQ = 0.4f;
constexpr float FOREST_FREQ = 1.2f;
constexpr float DESERT_FREQ = 1.2f;
constexpr float MOUNTAIN_FREQ = 2.0f;
enum class Biome {

View File

@@ -1,11 +1,12 @@
#pragma once
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <array>
#include <string>
#include <vector>
#include <Cubed/config.hpp>
#include <Cubed/tools/cubed_assert.hpp>
struct BlockTexture {
std::string name;
unsigned id;
@@ -39,3 +40,28 @@ struct LookBlock {
glm::ivec3 pos;
glm::ivec3 normal;
};
constexpr std::array<std::string_view, MAX_BLOCK_NUM> BLOCK_REISTER{
"air",
"grass_block",
"dirt",
"stone",
"sand",
"log",
"leaf"
};
const std::array<bool, MAX_BLOCK_NUM> TRANSPARENT_MAP {
true,
false,
false,
false,
false,
false,
true
};
inline bool is_in_transparent_map(unsigned id) {
CUBED_ASSERT_MSG(id < MAX_BLOCK_NUM, "ID is invaild");
return TRANSPARENT_MAP[id];
};

View File

@@ -47,14 +47,14 @@ public:
const std::vector<uint8_t>& get_chunk_blocks() const;
static int get_index(int x, int y, int z);
static int get_index(const glm::vec3& pos);
void init_chunk();
void gen_vertex_data();
//void gen_vertex_data();
// 0 : (1, 0)
// 1 : (-1, 0)
// 2 : (0, 1)
// 3 : (0, -1)
void gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neighbor_block);
void gen_vertex_data(const std::array<const std::vector<uint8_t>*, 4>& neighbor_block);
void upload_to_gpu();
GLuint get_vbo() const;

View File

@@ -0,0 +1,12 @@
#pragma once
#include <glm/glm.hpp>
class Chunk;
struct TreeStructNode {
glm::ivec3 offset{0, 0, 0};
unsigned id = 0;
};
bool build_tree(Chunk& chunk, const glm::ivec3& pos);

View File

@@ -0,0 +1,22 @@
#pragma once
#include <random>
namespace Cubed {
class Random {
public:
static unsigned get_base_seed();
static unsigned get_thread_seed();
static Random& get();
bool random_bool(double probability);
std::mt19937& engine();
unsigned seed();
private:
Random();
unsigned int m_seed = 0;
std::mt19937 m_engine;
};
}

View File

@@ -1,4 +1,5 @@
#pragma once
#include <syncstream>
#include <iostream>
#include <chrono>
#include <format>
@@ -21,11 +22,11 @@ namespace Logger {
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::cout << "\033[1;32m"
std::osyncstream(std::cout) << "\033[1;32m"
<< std::format("[INFO][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg
<< "\033[0m"
<< std::endl;
<< "\n";
}
template<typename... Args>
@@ -34,11 +35,11 @@ namespace Logger {
time_point_cast<std::chrono::seconds>
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::cerr << "\033[1;31m"
std::osyncstream(std::cerr) << "\033[1;31m"
<< std::format("[ERROR][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg
<< "\033[0m"
<< std::endl;
<< "\n";
}
@@ -48,11 +49,11 @@ namespace Logger {
time_point_cast<std::chrono::seconds>
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::cout << "\033[1;33m"
std::osyncstream(std::cout) << "\033[1;33m"
<< std::format("[WARN][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg
<< "\033[0m"
<< std::endl;
<< "\n";
}
template<typename... Args>
@@ -63,7 +64,7 @@ namespace Logger {
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
switch (level) {
case Logger::Level::TRACE:
std::cout << "\033[1;34m"
std::osyncstream(std::cout) << "\033[1;34m"
<< std::format("[TRACE][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< "[" << loc.file_name() << ":" << loc.line() << "]"
<< "[" << loc.function_name() << "]"
@@ -72,20 +73,20 @@ namespace Logger {
<< "\n";
break;
case Logger::Level::DEBUG:
std::cout << "\033[1;34m"
std::osyncstream(std::cout) << "\033[1;34m"
<< std::format("[DEBUG][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg
<< "\033[0m"
<< "\n";
break;
case Logger::Level::INFO:
info(fmt, std::forward<Args...>(args)...);
info(fmt, std::forward<Args>(args)...);
break;
case Logger::Level::WARN:
warn(fmt, std::forward<Args...>(args)...);
warn(fmt, std::forward<Args>(args)...);
break;
case Logger::Level::ERROR:
error(fmt, std::forward<Args...>(args)...);
error(fmt, std::forward<Args>(args)...);
break;
}

View File

@@ -1,13 +1,13 @@
#pragma once
#include <atomic>
#include <vector>
class PerlinNoise {
public:
static void init(unsigned int seed);
static void init();
static float noise(float x, float y, float z);
private:
static inline bool is_init = false;
static inline std::atomic<bool> is_init = false;
static inline std::vector<int> p;
static float fade(float t);

View File

@@ -4,11 +4,14 @@
#include <Cubed/map_table.hpp>
#include <Cubed/tools/cubed_assert.hpp>
#include <Cubed/tools/log.hpp>
#include <Cubed/tools/cubed_random.hpp>
#include <Cubed/tools/system_info.hpp>
#include <Cubed/tools/perlin_noise.hpp>
#include <exception>
#include <random>
namespace Cubed {
App::App() {
@@ -36,10 +39,8 @@ void App::init() {
glfwSetWindowFocusCallback(m_window.get_glfw_window(), window_focus_callback);
glfwSetWindowSizeCallback(m_window.get_glfw_window(), window_reshape_callback);
glfwSetKeyCallback(m_window.get_glfw_window(), key_callback);
std::random_device d;
m_seed = d();
Logger::info("Seed: {}", m_seed);
PerlinNoise::init(m_seed);
PerlinNoise::init();
m_renderer.init();
Logger::info("Renderer Init Success");
@@ -204,10 +205,6 @@ int App::start_cubed_application(int argc, char** argv) {
return 1;
}
unsigned int App::seed() {
return m_seed;
}
float App::delte_time() {
return delta_time;
}
@@ -215,3 +212,5 @@ float App::delte_time() {
float App::get_fps() {
return fps;
}
}

View File

@@ -1,10 +1,13 @@
#include <Cubed/gameplay/chunk.hpp>
#include <Cubed/gameplay/tree.hpp>
#include <Cubed/gameplay/world.hpp>
#include <Cubed/tools/cubed_assert.hpp>
#include <Cubed/tools/cubed_random.hpp>
#include <Cubed/tools/log.hpp>
#include <Cubed/tools/math_tools.hpp>
#include <Cubed/tools/perlin_noise.hpp>
#include <numeric>
#include <utility>
Chunk::Chunk(World& world, ChunkPos chunk_pos) :
m_world(world),
@@ -59,63 +62,12 @@ int Chunk::get_index(int x, int y, int z) {
}
return (x * WORLD_SIZE_Y + y) * CHUCK_SIZE + z;
}
// this is thread-unsafe!
void Chunk::gen_vertex_data() {
m_vertexs_data.clear();
static const glm::ivec3 DIR[6] = {
{0,0,1},{1,0,0},{0,0,-1},{-1,0,0},{0,1,0},{0,-1,0}
};
for (int x = 0; x < SIZE_X; x++) {
for (int y = 0; y < SIZE_Y; y++) {
for (int z = 0; z < SIZE_Z; 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;
int id = m_blocks[get_index(x, y, z)];
// air
if (id == 0) {
continue;
}
for (int face = 0; face < 6; face++) {
int nx = x + DIR[face].x;
int ny = y + DIR[face].y;
int nz = z + DIR[face].z;
bool neighbor_soild = false;
if (nx < 0 || nx >= SIZE_X || ny < 0 || ny >= SIZE_Y || nz < 0 || nz>= SIZE_Z) {
neighbor_soild = m_world.is_block(glm::ivec3(world_x, world_y, world_z) + DIR[face]);
} else {
if (m_blocks[get_index(nx, ny, nz)] != 0) {
neighbor_soild = true;
}
}
if (neighbor_soild) {
continue;
}
for (int i = 0; i < 6; i++) {
Vertex vex = {
VERTICES_POS[face][i][0] + (float)world_x * 1.0f,
VERTICES_POS[face][i][1] + (float)world_y * 1.0f,
VERTICES_POS[face][i][2] + (float)world_z * 1.0f,
TEX_COORDS[face][i][0],
TEX_COORDS[face][i][1],
static_cast<float>(id * 6 + face)
};
m_vertexs_data.emplace_back(vex);
}
}
}
}
}
int Chunk::get_index(const glm::vec3& pos) {
return Chunk::get_index(pos.x, pos.y, pos.z);
}
void Chunk::gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neighbor_block) {
void Chunk::gen_vertex_data(const std::array<const std::vector<uint8_t>*, 4>& neighbor_block) {
m_vertexs_data.clear();
static const glm::ivec3 DIR[6] = {
@@ -128,16 +80,17 @@ void Chunk::gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neig
int world_x = x + m_chunk_pos.x * CHUCK_SIZE;
int world_z = z + m_chunk_pos.z * CHUCK_SIZE;
int world_y = y;
int id = m_blocks[get_index(x, y, z)];
int cur_id = m_blocks[get_index(x, y, z)];
// air
if (id == 0) {
if (cur_id == 0) {
continue;
}
for (int face = 0; face < 6; face++) {
int nx = x + DIR[face].x;
int ny = y + DIR[face].y;
int nz = z + DIR[face].z;
bool neighbor_soild = false;
bool neighbor_cull = false;
if (nx < 0 || nx >= SIZE_X || ny < 0 || ny >= SIZE_Y || nz < 0 || nz>= SIZE_Z) {
@@ -147,7 +100,7 @@ void Chunk::gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neig
auto [neighbor_x, neighbor_z] = World::chunk_pos(world_nx, world_nz);
auto is_block = [&](const std::vector<uint8_t>* chunk_blocks){
auto is_cull = [&](const std::vector<uint8_t>* chunk_blocks){
if (chunk_blocks == nullptr) {
return false;
}
@@ -166,30 +119,42 @@ void Chunk::gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neig
return false;
}
auto id = (*chunk_blocks)[idx];
if (id == 0) {
return false;
if (is_in_transparent_map(id)) {
if (id == cur_id) {
return true;
} else {
return false;
}
} else {
return true;
}
};
if (m_chunk_pos.x + 1 == neighbor_x) {
neighbor_soild = is_block(neighbor_block[0]);
neighbor_cull = is_cull(neighbor_block[0]);
} else if (m_chunk_pos.x - 1 == neighbor_x) {
neighbor_soild = is_block(neighbor_block[1]);
neighbor_cull = is_cull(neighbor_block[1]);
} else if (m_chunk_pos.z + 1 == neighbor_z) {
neighbor_soild = is_block(neighbor_block[2]);
neighbor_cull = is_cull(neighbor_block[2]);
} else if (m_chunk_pos.z - 1 == neighbor_z) {
neighbor_soild = is_block(neighbor_block[3]);
neighbor_cull = is_cull(neighbor_block[3]);
}
//neighbor_soild = m_world.is_block(glm::ivec3(world_x, world_y, world_z) + DIR[face]);
//neighbor_cull = m_world.is_block(glm::ivec3(world_x, world_y, world_z) + DIR[face]);
} else {
if (m_blocks[get_index(nx, ny, nz)] != 0) {
neighbor_soild = true;
auto id = m_blocks[get_index(nx, ny, nz)];
if (!is_in_transparent_map(id)) {
neighbor_cull = true;
} else {
if (id == cur_id) {
neighbor_cull = true;
} else {
neighbor_cull = false;
}
}
}
if (neighbor_soild) {
if (neighbor_cull) {
continue;
}
for (int i = 0; i < 6; i++) {
@@ -199,7 +164,7 @@ void Chunk::gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neig
VERTICES_POS[face][i][2] + (float)world_z * 1.0f,
TEX_COORDS[face][i][0],
TEX_COORDS[face][i][1],
static_cast<float>(id * 6 + face)
static_cast<float>(cur_id * 6 + face)
};
m_vertexs_data.emplace_back(vex);
@@ -274,7 +239,7 @@ void Chunk::resolve_blocks() {
}
}
}
std::array<std::array<int, SIZE_Z>, SIZE_X> heights;
for (int x = 0; x < CHUCK_SIZE; x++) {
for (int z = 0; z < CHUCK_SIZE; z++) {
@@ -284,12 +249,18 @@ void Chunk::resolve_blocks() {
float temp = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 0.0f, world_z * BIOME_NOISE_FREQUENCY);
float humid = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 1.0f, world_z * BIOME_NOISE_FREQUENCY);
int height = get_interpolated_height(world_x, world_z, temp, humid);
auto biome = get_biome_from_noise(temp, humid);
if (height >= SIZE_Y) {
Logger::warn("height: {} is exceed max_height", height);
height = SIZE_Y - 1;
}
heights[x][z] = height;
for (int y = 5; y < height - 5; y++) {
m_blocks[get_index(x, y, z)] = 3;
}
if (biome == Biome::MOUNTAIN) {
for (int y = height - 5; y < height - 1; y++) {
for (int y = height - 5; y <= height - 1; y++) {
if (y > 101) {
m_blocks[get_index(x, y, z)] = 3;
} else {
@@ -297,26 +268,43 @@ void Chunk::resolve_blocks() {
}
}
if (height - 1 > 101) {
if (height > 101) {
m_blocks[get_index(x, height - 1, z)] = 3;
} else {
m_blocks[get_index(x, height - 1, z)] = 1;
}
} else if (biome == Biome::DESERT) {
for (int y = height - 5; y < height; y++) {
for (int y = height - 5; y <= height; y++) {
m_blocks[get_index(x, y, z)] = 4;
}
} else {
for (int y = height - 5; y < height - 1; y++) {
for (int y = height - 5; y <= height - 1; y++) {
m_blocks[get_index(x, y, z)] = 2;
}
for (int y = height - 1; y < height; y++) {
for (int y = height; y <= height; y++) {
m_blocks[get_index(x, y, z)] = 1;
}
}
}
}
if (m_biome == Biome::FOREST) {
std::array<int, SIZE_X> x_arr;
std::iota(x_arr.begin(), x_arr.end(), 0);
std::shuffle(x_arr.begin(), x_arr.end(), Cubed::Random::get().engine());
std::array<int, SIZE_Z> z_arr;
std::iota(z_arr.begin(), z_arr.end(), 0);
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.8)) {
build_tree(*this, {x, heights[x][z], z});
}
}
}
}
mark_dirty();
}

98
src/gameplay/tree.cpp Normal file
View File

@@ -0,0 +1,98 @@
#include <Cubed/gameplay/tree.hpp>
#include <Cubed/gameplay/chunk.hpp>
#include <array>
using glm::ivec3;
static constexpr std::array<TreeStructNode, 62> TREE {{
{{0, 1, 0}, 5},
{{0, 2, 0}, 5},
{{0, 3, 0}, 5},
{{0, 4, 0}, 5},
{{0, 5, 0}, 5},
{{0, 6, 0}, 6},
{{0, 5, 1}, 6},
{{1, 5, 0}, 6},
{{0, 5, -1}, 6},
{{-1, 5, 0}, 6},
{{1, 5, 1}, 6},
{{1, 5, -1}, 6},
{{-1, 5, -1}, 6},
{{-1, 5, 1}, 6},
{{0, 4, 1}, 6},
{{1, 4, 0}, 6},
{{0, 4, -1}, 6},
{{-1, 4, 0}, 6},
{{1, 4, 1}, 6},
{{1, 4, -1}, 6},
{{-1, 4, -1}, 6},
{{-1, 4, 1}, 6},
{{0, 4, 2}, 6},
{{2, 4, 0}, 6},
{{0, 4, -2}, 6},
{{-2, 4, 0}, 6},
{{2, 4, 2}, 6},
{{2, 4, -2}, 6},
{{-2, 4, -2}, 6},
{{-2, 4, 2}, 6},
{{1, 4, 2}, 6},
{{2, 4, 1}, 6},
{{-1, 4, 2}, 6},
{{2, 4, -1}, 6},
{{1, 4, -2}, 6},
{{-2, 4, 1}, 6},
{{-1, 4, -2}, 6},
{{-2, 4, -1}, 6},
{{0, 3, 1}, 6},
{{1, 3, 0}, 6},
{{0, 3, -1}, 6},
{{-1, 3, 0}, 6},
{{1, 3, 1}, 6},
{{1, 3, -1}, 6},
{{-1, 3, -1}, 6},
{{-1, 3, 1}, 6},
{{0, 3, 2}, 6},
{{2, 3, 0}, 6},
{{0, 3, -2}, 6},
{{-2, 3, 0}, 6},
{{2, 3, 2}, 6},
{{2, 3, -2}, 6},
{{-2, 3, -2}, 6},
{{-2, 3, 2}, 6},
{{1, 3, 2}, 6},
{{2, 3, 1}, 6},
{{-1, 3, 2}, 6},
{{2, 3, -1}, 6},
{{1, 3, -2}, 6},
{{-2, 3, 1}, 6},
{{-1, 3, -2}, 6},
{{-2, 3, -1}, 6},
}};
bool build_tree(Chunk& chunk, const glm::ivec3& pos) {
auto& block = chunk.get_chunk_blocks();
if (block[Chunk::get_index(pos)] != 1) {
Logger::info("Root is not Grass Block");
return false;
}
for (const auto& d : TREE) {
auto tree_node = pos + d.offset;
int x = tree_node.x;
int y = tree_node.y;
int z = tree_node.z;
if (x < 0 || y < 0 || z < 0 || x >= CHUCK_SIZE || y >= WORLD_SIZE_Y || z >= CHUCK_SIZE) {
return false;
}
if (block[Chunk::get_index(tree_node)] != 0) {
return false;
}
}
for (const auto& d : TREE) {
auto tree_node = pos + d.offset;
chunk.set_chunk_block(Chunk::get_index(tree_node), d.id);
}
return true;
}

View File

@@ -7,8 +7,18 @@
#include <Cubed/tools/cubed_hash.hpp>
#include <Cubed/tools/math_tools.hpp>
#include <execution>
#include <unordered_set>
static constexpr ChunkPos CHUNK_DIR[] {
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
};
struct ChunkRenderData {
std::array<const std::vector<uint8_t>*, 4> neighbor_block;
Chunk* chunk;
};
World::World() {
}
@@ -29,44 +39,7 @@ bool World::can_move(const AABB& player_box) const{
return true;
}
/*
const BlockRenderData& World::get_block_render_data(int world_x, int world_y ,int world_z) {
auto [chunk_x, chunk_z] = chunk_pos(world_x, world_z);
//Logger::info("Chunk PosX : {} Chuch PosZ : {}", chunk_x, chunk_z);
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
CUBED_ASSERT_MSG(it != m_chunks.end(), "Chunk not find");
const auto& chunk_blocks = it->second.get_chunk_blocks();
int x, y, z;
y = world_y;
x = world_x - chunk_x * CHUCK_SIZE;
z = world_z - chunk_z * CHUCK_SIZE;
//BlockRenderData m_block_render_data;
// block id
m_block_render_data.block_id = chunk_blocks[Chunk::get_index(x, y, z)];
if (m_block_render_data.block_id == 0) {
return m_block_render_data;
}
// draw_face
m_block_render_data.draw_face.assign(6, true);
static const std::vector<glm::ivec3> DIR = {
glm::ivec3(0, 0, 1),
glm::ivec3(1, 0, 0),
glm::ivec3(0 ,0, -1),
glm::ivec3(-1, 0, 0),
glm::ivec3(0, 1, 0),
glm::ivec3(0, -1, 0)
};
glm::ivec3 world_pos = glm::ivec3(world_x, world_y, world_z);
for (int i = 0; i < 6; i++) {
if (is_block(world_pos + DIR[i])) {
m_block_render_data.draw_face[i] = false;
}
}
return m_block_render_data;
}
*/
const std::optional<LookBlock>& World::get_look_block_pos(const std::string& name) const{
static std::optional<LookBlock> null_look_block = std::nullopt;
auto it = m_players.find(HASH::str(name));
@@ -99,7 +72,6 @@ Player& World::get_player(const std::string& name){
return it->second;
}
void World::init_world() {
auto t1 = std::chrono::system_clock::now();
for (int s = 0; s < DISTANCE; s++) {
@@ -112,17 +84,65 @@ void World::init_world() {
m_chunks.emplace(pos, Chunk(*this, pos));
}
}
/*
for (auto& chunk_map : m_chunks) {
auto& [chunk_pos, chunk] = chunk_map;
chunk.init_chunk();
}
// After block gen fininshed
std::array<const std::vector<uint8_t>*, 4> neighbor_block;
for (auto& [pos, chunk] : m_chunks) {
for (int i = 0; i < 4; i++) {
auto it = m_chunks.find(pos + CHUNK_DIR[i]);
if (it != m_chunks.end()) {
neighbor_block[i] = &(it->second.get_chunk_blocks());
} else {
neighbor_block[i] = nullptr;
}
}
chunk.gen_vertex_data(neighbor_block);
}
*/
std::vector<Chunk*> chunk_ptrs;
chunk_ptrs.reserve(m_chunks.size());
for (auto& [pos, chunk] : m_chunks) {
chunk_ptrs.push_back(&chunk);
}
std::for_each(std::execution::par, chunk_ptrs.begin(), chunk_ptrs.end(), [](auto& chunk){
chunk->init_chunk();
});
std::atomic<int> sync{0};
sync.store(1, std::memory_order_release);
sync.load(std::memory_order_acquire);
std::vector<ChunkRenderData> pending_gen_data;
pending_gen_data.reserve(m_chunks.size());
for (auto& [pos, chunk] : m_chunks) {
ChunkRenderData data;
data.chunk = &chunk;
for (int i = 0; i < 4; i++) {
auto it = m_chunks.find(pos + CHUNK_DIR[i]);
if (it != m_chunks.end()) {
data.neighbor_block[i] = &(it->second.get_chunk_blocks());
} else {
data.neighbor_block[i] = nullptr;
}
}
pending_gen_data.emplace_back(std::move(data));
}
std::for_each(std::execution::par, pending_gen_data.begin(), pending_gen_data.end(), [](ChunkRenderData& data){
if(!data.chunk) {
return ;
}
data.chunk->gen_vertex_data(data.neighbor_block);
});
for (auto& chunk_map : m_chunks) {
auto& [chunk_pos, chunk] = chunk_map;
chunk.gen_vertex_data();
chunk.upload_to_gpu();
}
@@ -230,11 +250,7 @@ void World::gen_chunks_internal() {
new_chunks.push_back({pos, Chunk(*this, pos)});
}
static const ChunkPos CHUNK_DIR[] {
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
};
std::unordered_map<ChunkPos, const Chunk&, ChunkPos::Hash> neighbor;
std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash> neighbor;
{
std::lock_guard lk(m_chunks_mutex);
@@ -242,18 +258,18 @@ void World::gen_chunks_internal() {
for (const auto& dir : CHUNK_DIR) {
auto it = m_chunks.find(pos + dir);
if (it != m_chunks.end()) {
neighbor.insert({it->first, (it->second)});
neighbor.insert({it->first, &(it->second)});
}
}
}
}
std::vector<const std::vector<uint8_t>*> neighbor_block(4);
std::array<const std::vector<uint8_t>*, 4> neighbor_block;
for (auto& [pos, chunk] : new_chunks) {
chunk.init_chunk();
neighbor.insert({pos, chunk});
neighbor.insert({pos, &chunk});
}
@@ -261,7 +277,7 @@ void World::gen_chunks_internal() {
for (int i = 0; i < 4; i++) {
auto it = neighbor.find(pos + CHUNK_DIR[i]);
if (it != neighbor.end()) {
neighbor_block[i] = &(it->second.get_chunk_blocks());
neighbor_block[i] = &(it->second->get_chunk_blocks());
} else {
neighbor_block[i] = nullptr;
}
@@ -335,7 +351,7 @@ bool World::is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_ex
int World::get_block(const glm::ivec3& block_pos) const {
auto [chunk_x, chunk_z] = chunk_pos(block_pos.x, block_pos.z);
std::lock_guard lk(m_chunks_mutex);
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
if (it == m_chunks.end()) {
@@ -356,6 +372,7 @@ int World::get_block(const glm::ivec3& block_pos) const {
bool World::is_block(const glm::ivec3& block_pos) const{
auto [chunk_x, chunk_z] = chunk_pos(block_pos.x, block_pos.z);
std::lock_guard lk(m_chunks_mutex);
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
if (it == m_chunks.end()) {
@@ -385,7 +402,7 @@ void World::set_block(const glm::ivec3& block_pos, unsigned id) {
world_z = block_pos.z;
auto [chunk_x, chunk_z] = chunk_pos(world_x, world_z);
std::lock_guard lk(m_chunks_mutex);
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
if (it == m_chunks.end()) {
@@ -454,7 +471,16 @@ void World::update(float delta_time) {
for (auto& [pos, chunk] : m_chunks) {
if (chunk.is_dirty()) {
// the curial fator influence
chunk.gen_vertex_data();
std::array<const std::vector<uint8_t>*, 4> neighbor_block;
for (int i = 0; i < 4; i++) {
auto it = m_chunks.find(pos + CHUNK_DIR[i]);
if (it != m_chunks.end()) {
neighbor_block[i] = &(it->second.get_chunk_blocks());
} else {
neighbor_block[i] = nullptr;
}
}
chunk.gen_vertex_data(neighbor_block);
chunk.upload_to_gpu();
}
if (!chunk.is_dirty()) {

View File

@@ -1,7 +1,7 @@
#include <Cubed/app.hpp>
int main(int argc, char** argv) {
return App::start_cubed_application(argc, argv);
return Cubed::App::start_cubed_application(argc, argv);
}

View File

@@ -1,21 +1,11 @@
#include <Cubed/config.hpp>
#include <Cubed/map_table.hpp>
#include <Cubed/gameplay/block.hpp>
#include <Cubed/tools/cubed_assert.hpp>
#include <Cubed/tools/cubed_hash.hpp>
#include <array>
std::unordered_map<unsigned, std::string> MapTable::id_to_name_map;
std::unordered_map<size_t, unsigned> MapTable::name_to_id_map;
constexpr std::array<std::string_view, MAX_BLOCK_NUM> BLOCK_REISTER{
"air",
"grass_block",
"dirt",
"stone",
"sand"
};
const std::string& MapTable::get_name_from_id(unsigned id) {
auto it = id_to_name_map.find(id);

View File

@@ -0,0 +1,49 @@
#include <Cubed/tools/cubed_random.hpp>
#include <Cubed/tools/log.hpp>
#include <atomic>
namespace Cubed {
unsigned Random::get_base_seed() {
static unsigned base = [] {
std::random_device rd;
return rd();
}();
return base;
}
unsigned Random::get_thread_seed() {
static std::atomic<unsigned> counter{0};
thread_local static unsigned seed = get_base_seed() + counter.fetch_add(1);
return seed;
}
Random::Random() {
m_seed = get_thread_seed();
Logger::info("Seed: {}", m_seed);
m_engine.seed(m_seed);
}
Random& Random::get() {
thread_local Random instance;
return instance;
}
bool Random::random_bool(double probability) {
std::bernoulli_distribution dist(probability);
return dist(m_engine);
}
std::mt19937& Random::engine() {
return m_engine;
}
unsigned Random::seed() {
return m_seed;
}
}

View File

@@ -2,17 +2,17 @@
#include <Cubed/config.hpp>
#include <Cubed/tools/cubed_assert.hpp>
#include <Cubed/tools/cubed_random.hpp>
#include <algorithm>
#include <numeric>
#include <random>
void PerlinNoise::init(unsigned int seed) {
void PerlinNoise::init() {
p.resize(256);
std::iota(p.begin(), p.end(), 0);
std::mt19937 engine(seed);
std::shuffle(p.begin(), p.end(), engine);
int seed = std::random_device{}();
Logger::info("Init Perlin Noise With Seed {}", seed);
std::shuffle(p.begin(), p.end(), std::mt19937(seed));
p.insert(p.end(), p.begin(), p.end());
is_init = true;

15
tsan.supp Normal file
View File

@@ -0,0 +1,15 @@
# tsan.supp
race:g_queue_pop_tail
race:g_strsplit
race:g_variant_type_info_get
race:g_rec_mutex_lock
race:libgallium
race:libEGL_mesa
race:libglib-2.0
race:libglycin-2
race:tbb::detail::d1::fold_tree
race:libgio-2.0
race:libtbb
race:tbb::detail
race:libpangoft2
race:libfontconfig