diff --git a/src/graphics/VoxelRenderer.cpp b/src/graphics/VoxelRenderer.cpp index fde67308..5b5a7537 100644 --- a/src/graphics/VoxelRenderer.cpp +++ b/src/graphics/VoxelRenderer.cpp @@ -1,12 +1,12 @@ #include "VoxelRenderer.h" + +#include #include "Mesh.h" #include "../voxels/Chunk.h" #include "../voxels/voxel.h" #include "../voxels/Block.h" #include "../lighting/Lightmap.h" -#define VERTEX_SIZE (3 + 2 + 4) - #define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A))) #define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X)) #define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE)) @@ -17,16 +17,16 @@ #define VOXEL(X,Y,Z) (GET_CHUNK(X,Y,Z)->voxels[(LOCAL(Y, CHUNK_H) * CHUNK_D + LOCAL(Z, CHUNK_D)) * CHUNK_W + LOCAL(X, CHUNK_W)]) #define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP)) -#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer[INDEX+0] = (X);\ - buffer[INDEX+1] = (Y);\ - buffer[INDEX+2] = (Z);\ - buffer[INDEX+3] = (U);\ - buffer[INDEX+4] = (V);\ - buffer[INDEX+5] = (R);\ - buffer[INDEX+6] = (G);\ - buffer[INDEX+7] = (B);\ - buffer[INDEX+8] = (S);\ - INDEX += VERTEX_SIZE; +#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer.push_back(X);\ + buffer.push_back(Y);\ + buffer.push_back(Z);\ + buffer.push_back(U);\ + buffer.push_back(V);\ + buffer.push_back(R);\ + buffer.push_back(G);\ + buffer.push_back(B);\ + buffer.push_back(S);\ + INDEX += CHUNK_VERTEX_SIZE; #define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\ @@ -36,15 +36,13 @@ int chunk_attrs[] = {3,2,4, 0}; -VoxelRenderer::VoxelRenderer(size_t capacity) : capacity(capacity) { - buffer = new float[capacity * VERTEX_SIZE * 6]; +VoxelRenderer::VoxelRenderer() { } VoxelRenderer::~VoxelRenderer(){ - delete[] buffer; } -inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ +inline void _renderBlock(std::vector& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ unsigned int id = vox.id; if (!id){ @@ -289,7 +287,8 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk } } -Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){ +const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& size){ + buffer.clear(); size_t index = 0; for (int y = 0; y < CHUNK_H; y++){ for (int z = 0; z < CHUNK_D; z++){ @@ -323,5 +322,6 @@ Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){ } } } - return new Mesh(buffer, index / VERTEX_SIZE, chunk_attrs); + size = buffer.size(); + return &buffer[0]; } diff --git a/src/graphics/VoxelRenderer.h b/src/graphics/VoxelRenderer.h index 4b3a6255..84e38238 100644 --- a/src/graphics/VoxelRenderer.h +++ b/src/graphics/VoxelRenderer.h @@ -2,18 +2,20 @@ #define GRAPHICS_VOXELRENDERER_H_ #include +#include class Mesh; class Chunk; +#define CHUNK_VERTEX_SIZE (3 + 2 + 4) + class VoxelRenderer { - float* buffer; - size_t capacity; public: - VoxelRenderer(size_t capacity); + std::vector buffer; + VoxelRenderer(); ~VoxelRenderer(); - Mesh* render(Chunk* chunk, const Chunk** chunks); + const float* render(Chunk* chunk, const Chunk** chunks, size_t& size); }; #endif /* GRAPHICS_VOXELRENDERER_H_ */ diff --git a/src/player_control.cpp b/src/player_control.cpp index 26223c43..6b814fba 100644 --- a/src/player_control.cpp +++ b/src/player_control.cpp @@ -25,7 +25,7 @@ #define CAMERA_SHAKING_OFFSET_Y 0.031f #define CAMERA_SHAKING_SPEED 1.6f #define CAMERA_SHAKING_DELTA_K 10.0f -#define FLIGHT_SPEED_MUL 5.0f +#define FLIGHT_SPEED_MUL 8.0f #define JUMP_FORCE 7.0f void update_controls(PhysicsSolver* physics, diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index 415627f3..9c1a0bed 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -81,10 +81,12 @@ void update_level(World* world, Level* level, vec3 position, float delta, long f update_controls(level->physics, level->chunks, level->player, delta); update_interaction(level, lineBatch); - level->chunks->setCenter(world->wfile, position.x,0,position.z); - level->chunksController->_buildMeshes(renderer, frame); - + level->chunks->setCenter(world->wfile, position.x, 0, position.z); int freeLoaders = level->chunksController->countFreeLoaders(); + for (int i = 0; i < freeLoaders; i++) + level->chunksController->_buildMeshes(renderer, frame); + + freeLoaders = level->chunksController->countFreeLoaders(); for (int i = 0; i < freeLoaders; i++) level->chunksController->loadVisible(world->wfile); } @@ -140,7 +142,7 @@ int main() { bool occlusion = false; bool devdata = false; - glfwSwapInterval(0); + Window::swapInterval(0); std::cout << "-- initializing finished" << std::endl; while (!Window::isShouldClose()){ diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index a4e645b0..5bf9006e 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -8,6 +8,7 @@ Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){ for (unsigned int i = 0; i < CHUNK_VOL; i++) voxels[i].id = 1; lightmap = new Lightmap(); + renderData.vertices = nullptr; } Chunk::~Chunk(){ diff --git a/src/voxels/Chunk.h b/src/voxels/Chunk.h index 14d1689c..2c37fed9 100644 --- a/src/voxels/Chunk.h +++ b/src/voxels/Chunk.h @@ -1,6 +1,8 @@ #ifndef VOXELS_CHUNK_H_ #define VOXELS_CHUNK_H_ +#include + #define CHUNK_W 16 #define CHUNK_H 256 #define CHUNK_D 16 @@ -9,6 +11,11 @@ class voxel; class Lightmap; +struct RenderData { + float* vertices; + size_t size; +}; + class Chunk { public: int x,y,z; @@ -19,6 +26,8 @@ public: bool loaded = false; int surrounding = 0; int references = 1; + RenderData renderData; + Chunk(int x, int y, int z); ~Chunk(); diff --git a/src/voxels/ChunksController.cpp b/src/voxels/ChunksController.cpp index d2b98eb1..9d8d3489 100644 --- a/src/voxels/ChunksController.cpp +++ b/src/voxels/ChunksController.cpp @@ -20,7 +20,7 @@ ChunksController::ChunksController(Chunks* chunks, Lighting* lighting) : chunks(chunks), lighting(lighting){ - loadersCount = std::thread::hardware_concurrency() - 1; + loadersCount = std::thread::hardware_concurrency() * 2 - 1; if (loadersCount <= 0) loadersCount = 1; loaders = new ChunksLoader*[loadersCount]; @@ -130,7 +130,7 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){ oz += 1; closes[(oy * 3 + oz) * 3 + ox] = other; } - freeLoader->perform(chunk, (Chunk**)closes); + freeLoader->load(chunk, (Chunk**)closes); return true; } @@ -139,6 +139,35 @@ bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) { const int h = chunks->h; const int d = chunks->d; + for (int y = 0; y < h; y++){ + for (int z = 1; z < d-1; z++){ + for (int x = 1; x < w-1; x++){ + int index = (y * d + z) * w + x; + Chunk* chunk = chunks->chunks[index]; + if (chunk == nullptr) + continue; + if (chunk->renderData.vertices > (void*)1){ + const int chunk_attrs[] = {3,2,4, 0}; + Mesh* mesh = new Mesh(chunk->renderData.vertices, chunk->renderData.size / CHUNK_VERTEX_SIZE, chunk_attrs); + chunks->meshes[index] = mesh; + delete[] chunk->renderData.vertices; + chunk->renderData.vertices = nullptr; + } + } + } + } + ChunksLoader* freeLoader = nullptr; + for (int i = 0; i < loadersCount; i++){ + ChunksLoader* loader = loaders[i]; + if (loader->isBusy()){ + continue; + } + freeLoader = loader; + break; + } + if (freeLoader == nullptr) + return false; + int nearX = 0; int nearY = 0; int nearZ = 0; @@ -208,9 +237,15 @@ bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) { oz += 1; closes[(oy * 3 + oz) * 3 + ox] = other; } - mesh = renderer->render(chunk, (const Chunk**)closes); - chunks->meshes[index] = mesh; - return true; + if (chunk->renderData.vertices == nullptr){ + chunk->renderData.vertices = (float*)1; + freeLoader->render(chunk, (Chunk**)closes); + + return true; + } + //mesh = renderer->render(chunk, (const Chunk**)closes); + //chunks->meshes[index] = mesh; + } return false; } diff --git a/src/voxels/ChunksLoader.cpp b/src/voxels/ChunksLoader.cpp index 89963760..be82d168 100644 --- a/src/voxels/ChunksLoader.cpp +++ b/src/voxels/ChunksLoader.cpp @@ -5,6 +5,7 @@ #include "Chunks.h" #include "WorldGenerator.h" #include "../lighting/Lighting.h" +#include "../graphics/VoxelRenderer.h" #include @@ -13,7 +14,8 @@ void ChunksLoader::_thread(){ Chunks chunks(3,3,3, -1,-1,-1); Lighting lighting(&chunks); - while (working){ + VoxelRenderer renderer; + while (state != OFF){ if (current == nullptr){ std::this_thread::sleep_for(std::chrono::milliseconds(1)); continue; @@ -27,12 +29,24 @@ void ChunksLoader::_thread(){ } } - if (!chunk->loaded){ - WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z); + if (state == LOAD){ + chunks.putChunk(chunk); + if (!chunk->loaded){ + WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z); + } + + lighting.onChunkLoaded(chunk->x, chunk->y, chunk->z, true); + } + else if (state == RENDER){ + size_t size; + renderer.render(chunk, (const Chunk**)(closes.load()), size); + float* vertices = new float[size]; + for (size_t i = 0; i < size; i++) + vertices[i] = renderer.buffer[i]; + chunk->renderData.vertices = vertices; + chunk->renderData.size = size; } - chunks.putChunk(chunk); - lighting.onChunkLoaded(chunk->x, chunk->y, chunk->z, true); chunks.clear(false); for (int i = 0; i < CLOSES_C; i++){ Chunk* other = closes[i]; @@ -45,7 +59,7 @@ void ChunksLoader::_thread(){ } } -void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed){ +void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode){ if (isBusy()){ std::cerr << "performing while busy" << std::endl; return; @@ -64,4 +78,13 @@ void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed){ } } current = chunk; + state = mode; +} + +void ChunksLoader::load(Chunk* chunk, Chunk** closes_passed){ + perform(chunk, closes_passed, LOAD); +} + +void ChunksLoader::render(Chunk* chunk, Chunk** closes_passed){ + perform(chunk, closes_passed, RENDER); } diff --git a/src/voxels/ChunksLoader.h b/src/voxels/ChunksLoader.h index aff93ec7..98433b7c 100644 --- a/src/voxels/ChunksLoader.h +++ b/src/voxels/ChunksLoader.h @@ -12,19 +12,25 @@ class Chunk; +enum LoaderMode { + OFF, IDLE, LOAD, RENDER, +}; + class ChunksLoader final { private: std::thread loaderThread; void _thread(); std::atomic current {nullptr}; std::atomic closes {nullptr}; - std::atomic working {true}; + std::atomic state {IDLE}; + + void perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode); public: ChunksLoader() : loaderThread{} { loaderThread = std::thread{&ChunksLoader::_thread, this}; } ~ChunksLoader(){ - working = false; + state = OFF; loaderThread.join(); } @@ -32,10 +38,11 @@ public: return current != nullptr; } - void perform(Chunk* chunk, Chunk** closes_passed); + void load(Chunk* chunk, Chunk** closes_passed); + void render(Chunk* chunk, Chunk** closes_passed); void stop(){ - working = false; + state = OFF; } }; diff --git a/src/window/Window.cpp b/src/window/Window.cpp index ef6d48d8..a761631e 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -57,6 +57,10 @@ void Window::setShouldClose(bool flag){ glfwSetWindowShouldClose(window, flag); } +void Window::swapInterval(int interval){ + glfwSwapInterval(interval); +} + void Window::swapBuffers(){ glfwSwapBuffers(window); } diff --git a/src/window/Window.h b/src/window/Window.h index a0575af9..b54e1a58 100644 --- a/src/window/Window.h +++ b/src/window/Window.h @@ -15,6 +15,7 @@ public: static bool isShouldClose(); static void setShouldClose(bool flag); static void swapBuffers(); + static void swapInterval(int interval); }; #endif /* WINDOW_WINDOW_H_ */ diff --git a/src/world_render.h b/src/world_render.h index 0531eb79..d50c68f6 100644 --- a/src/world_render.h +++ b/src/world_render.h @@ -57,7 +57,7 @@ void init_renderer(){ uicamera->perspective = false; uicamera->flipped = true; - renderer = new VoxelRenderer(1024*1024); + renderer = new VoxelRenderer(); }