squashed commits
erase chunk buffers only after marking as to be deleted update chunks around player with a cube instead of concentric spheres only generate chunks around player, update all chunks use onetbb::parallel_forfix-multithread
parent
5f396a9801
commit
01f1f9da16
|
@ -36,9 +36,10 @@ namespace chunkmanager
|
|||
void stop();
|
||||
void destroy();
|
||||
oneapi::tbb::concurrent_queue<Chunk::Chunk*>& getDeleteVector();
|
||||
std::array<std::array<int, 3>, chunks_volume>& getChunksIndices();
|
||||
std::array<std::array<uint16_t, 3>, chunks_volume>& getChunksIndices();
|
||||
Block getBlockAtPos(int x, int y, int z);
|
||||
void update();
|
||||
void primary_thread_update();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,10 +10,11 @@
|
|||
#define extr extern
|
||||
#endif
|
||||
|
||||
#define RENDER_DISTANCE 16
|
||||
#define RENDER_DISTANCE 8
|
||||
|
||||
extr Camera theCamera;
|
||||
constexpr int chunks_volume = static_cast<int>(1.333333333333*M_PI*(RENDER_DISTANCE*RENDER_DISTANCE*RENDER_DISTANCE));
|
||||
//constexpr int chunks_volume = static_cast<int>(1.333333333333*M_PI*(RENDER_DISTANCE*RENDER_DISTANCE*RENDER_DISTANCE));
|
||||
constexpr int chunks_volume = RENDER_DISTANCE*RENDER_DISTANCE*RENDER_DISTANCE*8;
|
||||
extr bool wireframe;
|
||||
|
||||
extr float sines[360];
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
#include <oneapi/tbb.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
|
@ -24,7 +26,7 @@ namespace chunkmanager
|
|||
// Concurrent hash table of chunks
|
||||
ChunkTable chunks;
|
||||
// Chunk indices. Centered at (0,0,0), going in concentric sphere outwards
|
||||
std::array<std::array<int, 3>, chunks_volume> chunks_indices;
|
||||
std::array<std::array<uint16_t, 3>, chunks_volume> chunks_indices;
|
||||
|
||||
/* Multithreading */
|
||||
std::atomic_bool should_run;
|
||||
|
@ -40,45 +42,22 @@ namespace chunkmanager
|
|||
int chunks_volume_real;
|
||||
void init(){
|
||||
int index{0};
|
||||
int rr{RENDER_DISTANCE * RENDER_DISTANCE};
|
||||
constexpr int rr{RENDER_DISTANCE * RENDER_DISTANCE};
|
||||
|
||||
int xp{0}, x{0};
|
||||
bool b = true;
|
||||
|
||||
// Iterate over all chunks, in concentric spheres starting fron the player and going outwards. Alternate left and right
|
||||
// Eq. of the sphere (x - a)² + (y - b)² + (z - c)² = r²
|
||||
while (xp <= RENDER_DISTANCE)
|
||||
{
|
||||
// Alternate between left and right
|
||||
if (b) x = +xp;
|
||||
else x = -xp;
|
||||
for(int i = -RENDER_DISTANCE; i < RENDER_DISTANCE; i++)
|
||||
for(int j = -RENDER_DISTANCE; j < RENDER_DISTANCE; j++)
|
||||
for(int k = -RENDER_DISTANCE; k < RENDER_DISTANCE; k++){
|
||||
|
||||
// Step 1. At current x, get the corresponding y values (2nd degree equation, up to 2
|
||||
// possible results)
|
||||
int y1 = static_cast<int>(sqrt((rr) - x*x));
|
||||
|
||||
for (int y = -y1 + 1 ; y <= y1; y++)
|
||||
{
|
||||
// Step 2. At both y's, get the corresponding z values
|
||||
int z1 = static_cast<int>(sqrt( rr - x*x - y*y));
|
||||
|
||||
for (int z = -z1 + 1; z <= z1; z++){
|
||||
chunks_indices[index][0] = x;
|
||||
chunks_indices[index][1] = y;
|
||||
chunks_indices[index][2] = z;
|
||||
chunks_indices[index][0]=i;
|
||||
chunks_indices[index][1]=j;
|
||||
chunks_indices[index][2]=k;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!b)
|
||||
{
|
||||
xp++;
|
||||
b = true;
|
||||
}
|
||||
else b = false;
|
||||
}
|
||||
chunks_volume_real = index;
|
||||
|
||||
std::cout << index << std::endl;
|
||||
// Also init mesh data queue
|
||||
for(int i = 0; i < 10; i++)
|
||||
chunkmesher::getMeshDataQueue().push(new chunkmesher::MeshData());
|
||||
|
@ -107,7 +86,6 @@ namespace chunkmanager
|
|||
Chunk::Chunk* chunk = entry.first;
|
||||
if(chunk->getState(Chunk::CHUNK_STATE_GENERATED)){
|
||||
chunkmesher::mesh(chunk);
|
||||
renderer::getChunksToRender().insert(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +99,19 @@ namespace chunkmanager
|
|||
int chunkY=static_cast<int>(theCamera.getAtomicPosY() / CHUNK_SIZE);
|
||||
int chunkZ=static_cast<int>(theCamera.getAtomicPosZ() / CHUNK_SIZE);
|
||||
|
||||
// Eventually create new chunks
|
||||
for(int i = 0; i < chunks_volume; i++) {
|
||||
const uint16_t x = chunks_indices[i][0] + chunkX;
|
||||
const uint16_t y = chunks_indices[i][1] + chunkY;
|
||||
const uint16_t z = chunks_indices[i][2] + chunkZ;
|
||||
const uint32_t index = calculateIndex(x, y, z);
|
||||
|
||||
if(x > 1023 || y > 1023 || z > 1023) continue;
|
||||
|
||||
ChunkTable::accessor a, a1, a2, b1, b2, c1, c2;
|
||||
if(!chunks.find(a, index)) chunks.emplace(a, std::make_pair(index, new Chunk::Chunk(glm::vec3(x,y,z))));
|
||||
}
|
||||
|
||||
debug::window::set_parameter("px", theCamera.getAtomicPosX());
|
||||
debug::window::set_parameter("py", theCamera.getAtomicPosY());
|
||||
debug::window::set_parameter("pz", theCamera.getAtomicPosZ());
|
||||
|
@ -131,46 +122,49 @@ namespace chunkmanager
|
|||
debug::window::set_parameter("ly", theCamera.getFront().y);
|
||||
debug::window::set_parameter("lz", theCamera.getFront().z);
|
||||
|
||||
// Update other chunks
|
||||
for(int i = 0; i < chunks_volume_real; i++) {
|
||||
const uint16_t x = chunks_indices[i][0] + chunkX;
|
||||
const uint16_t y = chunks_indices[i][1] + chunkY;
|
||||
const uint16_t z = chunks_indices[i][2] + chunkZ;
|
||||
const uint32_t index = calculateIndex(x, y, z);
|
||||
|
||||
if(x > 1023 || y > 1023 || z > 1023) continue;
|
||||
|
||||
ChunkTable::accessor a, a1, a2, b1, b2, c1, c2;
|
||||
if(!chunks.find(a, index)) chunks.emplace(a, std::make_pair(index, new Chunk::Chunk(glm::vec3(x,y,z))));
|
||||
|
||||
if(! (a->second->getState(Chunk::CHUNK_STATE_GENERATED))) {
|
||||
chunks_to_generate_queue.push(std::make_pair(a->second, GENERATION_PRIORITY_NORMAL));
|
||||
}else if(! (a->second->getState(Chunk::CHUNK_STATE_MESHED))){
|
||||
if(
|
||||
(x + 1 > 1023 || (chunks.find(a1, calculateIndex(x+1, y, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(x - 1 < 0|| (chunks.find(a1, calculateIndex(x-1, y, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(y + 1 > 1023 || (chunks.find(a1, calculateIndex(x, y+1, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(y - 1 < 0|| (chunks.find(a1, calculateIndex(x, y-1, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(z + 1 > 1023 || (chunks.find(a1, calculateIndex(x, y, z+1)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(z - 1 < 0|| (chunks.find(a1, calculateIndex(x, y, z-1)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED)))
|
||||
)
|
||||
chunks_to_mesh_queue.push(std::make_pair(a->second, MESHING_PRIORITY_NORMAL));
|
||||
}
|
||||
|
||||
a.release();
|
||||
}
|
||||
|
||||
debug::window::set_parameter("update_chunks_total", (int) (chunks.size()));
|
||||
debug::window::set_parameter("update_chunks_bucket", (int) (chunks.max_size()));
|
||||
|
||||
// Perform needed operations on all the chunks
|
||||
oneapi::tbb::parallel_for(chunks.range(), [](ChunkTable::range_type &r){
|
||||
for(ChunkTable::const_iterator a = r.begin(); a != r.end(); a++){
|
||||
if(a->second->getState(Chunk::CHUNK_STATE_UNLOADED)){
|
||||
chunks_todelete.push(a->second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(! (a->second->getState(Chunk::CHUNK_STATE_GENERATED))) {
|
||||
chunks_to_generate_queue.push(std::make_pair(a->second, GENERATION_PRIORITY_NORMAL));
|
||||
}else if(! (a->second->getState(Chunk::CHUNK_STATE_MESHED))){
|
||||
int x = a->second->getPosition().x;
|
||||
int y = a->second->getPosition().y;
|
||||
int z = a->second->getPosition().z;
|
||||
|
||||
ChunkTable::const_accessor a1;
|
||||
if(
|
||||
(x + 1 > 1023 || (chunks.find(a1, calculateIndex(x+1, y, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(x - 1 < 0|| (chunks.find(a1, calculateIndex(x-1, y, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(y + 1 > 1023 || (chunks.find(a1, calculateIndex(x, y+1, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(y - 1 < 0|| (chunks.find(a1, calculateIndex(x, y-1, z)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(z + 1 > 1023 || (chunks.find(a1, calculateIndex(x, y, z+1)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||
(z - 1 < 0|| (chunks.find(a1, calculateIndex(x, y, z-1)) &&
|
||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED)))
|
||||
)
|
||||
chunks_to_mesh_queue.push(std::make_pair(a->second, MESHING_PRIORITY_NORMAL));
|
||||
}else{
|
||||
renderer::getChunksToRender().insert(a->second);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Chunk::Chunk* n;
|
||||
nUnloaded = 0;
|
||||
ChunkTable::accessor a;
|
||||
while(chunks_todelete.try_pop(n)){
|
||||
int x = static_cast<uint16_t>(n->getPosition().x);
|
||||
int y = static_cast<uint16_t>(n->getPosition().y);
|
||||
|
@ -178,10 +172,14 @@ namespace chunkmanager
|
|||
if(x > 1023 || y > 1023 || z > 1023) continue;
|
||||
const uint32_t index = calculateIndex(x, y, z);
|
||||
|
||||
chunks.erase(index);
|
||||
//delete n;
|
||||
nUnloaded++;
|
||||
//std::cout << n->getState(Chunk::CHUNK_STATE_GENERATED) << "\n";
|
||||
if(chunks.erase(index)){
|
||||
delete n;
|
||||
nUnloaded++;
|
||||
}
|
||||
}
|
||||
|
||||
debug::window::set_parameter("update_chunks_freed", nUnloaded);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +189,7 @@ namespace chunkmanager
|
|||
}
|
||||
|
||||
oneapi::tbb::concurrent_queue<Chunk::Chunk*>& getDeleteVector(){ return chunks_todelete; }
|
||||
std::array<std::array<int, 3>, chunks_volume>& getChunksIndices(){ return chunks_indices; }
|
||||
std::array<std::array<uint16_t, 3>, chunks_volume>& getChunksIndices(){ return chunks_indices; }
|
||||
|
||||
void stop() {
|
||||
should_run=false;
|
||||
|
|
|
@ -115,8 +115,8 @@ namespace debug{
|
|||
if(ImGui::CollapsingHeader("Chunks")){
|
||||
ImGui::Text("Total chunks present: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_total")));
|
||||
/*ImGui::Text("Chunks freed from memory: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_delete")));*/
|
||||
ImGui::Text("Chunks freed from memory: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_freed")));
|
||||
ImGui::Text("Bucket size: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_bucket")));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "renderer.hpp"
|
||||
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#include <oneapi/tbb/concurrent_vector.h>
|
||||
#include <oneapi/tbb/concurrent_queue.h>
|
||||
|
||||
|
@ -145,8 +148,11 @@ namespace renderer{
|
|||
}
|
||||
|
||||
for(auto& c : chunks_torender){
|
||||
float dist = glm::distance(c->getPosition(), cameraChunkPos);
|
||||
if(dist <= static_cast<float>(RENDER_DISTANCE)){
|
||||
//float dist = glm::distance(c->getPosition(), cameraChunkPos);
|
||||
//if(static_cast<int>(dist) <= RENDER_DISTANCE + 1){
|
||||
if(abs(c->getPosition().x - cameraChunkPos.x) <= RENDER_DISTANCE &&
|
||||
abs(c->getPosition().y - cameraChunkPos.y) <= RENDER_DISTANCE &&
|
||||
abs(c->getPosition().z - cameraChunkPos.z) <= RENDER_DISTANCE){
|
||||
if(!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) continue;
|
||||
|
||||
// Increase total vertex count
|
||||
|
@ -204,6 +210,7 @@ namespace renderer{
|
|||
render_todelete.push_back(c);
|
||||
}
|
||||
} else{
|
||||
std::cout << "chunk at " << glm::to_string(c->getPosition()) << std::endl;
|
||||
// Mark has out of vision and annotate when it started
|
||||
c->setState(Chunk::CHUNK_STATE_OUTOFVISION, true);
|
||||
c->setState(Chunk::CHUNK_STATE_UNLOADED, false);
|
||||
|
@ -222,11 +229,11 @@ namespace renderer{
|
|||
debug::window::set_parameter("render_chunks_vertices", vertices);
|
||||
|
||||
for(auto& c : render_todelete){
|
||||
c->deleteBuffers();
|
||||
// we can get away with unsafe erase as access to the container is only done by this
|
||||
// thread
|
||||
c->deleteBuffers();
|
||||
chunks_torender.unsafe_erase(c);
|
||||
chunkmanager::getDeleteVector().push(c);
|
||||
c->setState(Chunk::CHUNK_STATE_UNLOADED, true);
|
||||
}
|
||||
render_todelete.clear();
|
||||
|
||||
|
|
Loading…
Reference in New Issue