Misc fixes in preparation for multithreading refactor #10
|
@ -18,6 +18,10 @@ public:
|
||||||
|
|
||||||
// This matrix needs to be also updated in viewPortCallback whenever it is changed
|
// This matrix needs to be also updated in viewPortCallback whenever it is changed
|
||||||
projection = glm::perspective(glm::radians(90.0f), 800.0f / 600.0f, 0.1f, 1200.0f);
|
projection = glm::perspective(glm::radians(90.0f), 800.0f / 600.0f, 0.1f, 1200.0f);
|
||||||
|
|
||||||
|
posX = cameraPos.x;
|
||||||
|
posY = cameraPos.y;
|
||||||
|
posZ = cameraPos.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(GLFWwindow *window, float deltaTime)
|
void update(GLFWwindow *window, float deltaTime)
|
||||||
|
@ -112,7 +116,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 cameraPos = glm::vec3(256.0, 80.0f, 256.0f);
|
glm::vec3 cameraPos = glm::vec3(512.0, 80.0f, 512.0f);
|
||||||
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
|
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
|
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
glm::vec3 direction = glm::vec3(0.0f);
|
glm::vec3 direction = glm::vec3(0.0f);
|
||||||
|
|
|
@ -20,9 +20,16 @@
|
||||||
#define CHUNK_VOLUME (CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE)
|
#define CHUNK_VOLUME (CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE)
|
||||||
#define CHUNK_MAX_INDEX (CHUNK_VOLUME - 1)
|
#define CHUNK_MAX_INDEX (CHUNK_VOLUME - 1)
|
||||||
|
|
||||||
|
// int32_t is fine, since i'm limiting the coordinate to only use up to ten bits (1023). There's actually two spare bits
|
||||||
|
typedef int32_t chunk_index_t;
|
||||||
|
typedef int16_t chunk_intcoord_t;
|
||||||
|
|
||||||
namespace Chunk
|
namespace Chunk
|
||||||
{
|
{
|
||||||
|
|
||||||
|
chunk_index_t calculateIndex(chunk_intcoord_t i, chunk_intcoord_t j, chunk_intcoord_t k);
|
||||||
|
chunk_index_t calculateIndex(glm::vec3 pos);
|
||||||
|
|
||||||
constexpr uint8_t CHUNK_STATE_GENERATED = 1;
|
constexpr uint8_t CHUNK_STATE_GENERATED = 1;
|
||||||
constexpr uint8_t CHUNK_STATE_MESHED = 2;
|
constexpr uint8_t CHUNK_STATE_MESHED = 2;
|
||||||
constexpr uint8_t CHUNK_STATE_MESH_LOADED = 4;
|
constexpr uint8_t CHUNK_STATE_MESH_LOADED = 4;
|
||||||
|
@ -58,12 +65,15 @@ namespace Chunk
|
||||||
public:
|
public:
|
||||||
GLuint VAO{0}, VBO{0}, extentsBuffer{0}, texinfoBuffer{0}, numVertices{0};
|
GLuint VAO{0}, VBO{0}, extentsBuffer{0}, texinfoBuffer{0}, numVertices{0};
|
||||||
std::atomic<float> unload_timer{0};
|
std::atomic<float> unload_timer{0};
|
||||||
|
chunk_index_t getIndex(){ return this->index; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 position{};
|
glm::vec3 position{};
|
||||||
IntervalMap<Block> blocks{};
|
IntervalMap<Block> blocks{};
|
||||||
|
|
||||||
std::atomic_uint8_t state{0};
|
std::atomic_uint8_t state{0};
|
||||||
|
|
||||||
|
chunk_index_t index;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
namespace chunkmanager
|
namespace chunkmanager
|
||||||
{
|
{
|
||||||
typedef oneapi::tbb::concurrent_hash_map<uint32_t, Chunk::Chunk*> ChunkTable;
|
typedef oneapi::tbb::concurrent_hash_map<chunk_index_t, Chunk::Chunk*> ChunkTable;
|
||||||
typedef std::pair<Chunk::Chunk*, uint8_t> ChunkPQEntry;
|
typedef std::pair<Chunk::Chunk*, uint8_t> ChunkPQEntry;
|
||||||
// The comparing function to use
|
// The comparing function to use
|
||||||
struct compare_f {
|
struct compare_f {
|
||||||
|
@ -31,12 +31,11 @@ namespace chunkmanager
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void blockpick(bool place);
|
void blockpick(bool place);
|
||||||
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k);
|
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
void destroy();
|
void destroy();
|
||||||
oneapi::tbb::concurrent_queue<Chunk::Chunk*>& getDeleteVector();
|
oneapi::tbb::concurrent_queue<Chunk::Chunk*>& getDeleteVector();
|
||||||
std::array<std::array<int, 3>, chunks_volume>& getChunksIndices();
|
std::array<std::array<chunk_intcoord_t, 3>, chunks_volume>& getChunksIndices();
|
||||||
Block getBlockAtPos(int x, int y, int z);
|
Block getBlockAtPos(int x, int y, int z);
|
||||||
void update();
|
void update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef CONTROLS_H
|
||||||
|
#define CONTROLS_H
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#define BLOCKPICK_TIMEOUT 0.15f
|
||||||
|
|
||||||
|
namespace controls{
|
||||||
|
void init();
|
||||||
|
void update(GLFWwindow* window);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,7 +13,8 @@
|
||||||
#define RENDER_DISTANCE 16
|
#define RENDER_DISTANCE 16
|
||||||
|
|
||||||
extr Camera theCamera;
|
extr Camera theCamera;
|
||||||
constexpr int chunks_volume = static_cast<int>(1.333333333333*M_PI*(RENDER_DISTANCE*RENDER_DISTANCE*RENDER_DISTANCE));
|
// the cube spans in both directions, to each axis has to be multiplied by 2. 2^3=8
|
||||||
|
constexpr int chunks_volume = 8*(RENDER_DISTANCE*RENDER_DISTANCE*RENDER_DISTANCE);
|
||||||
extr bool wireframe;
|
extr bool wireframe;
|
||||||
|
|
||||||
extr float sines[360];
|
extr float sines[360];
|
||||||
|
|
|
@ -3,6 +3,5 @@
|
||||||
|
|
||||||
void framebuffer_size_callback(GLFWwindow *, int, int);
|
void framebuffer_size_callback(GLFWwindow *, int, int);
|
||||||
void mouse_callback(GLFWwindow *window, double xpos, double ypos);
|
void mouse_callback(GLFWwindow *window, double xpos, double ypos);
|
||||||
void processInput(GLFWwindow *);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
project(OpenGLTest)
|
project(OpenGLTest)
|
||||||
|
|
||||||
set(SOURCE_FILES main.cpp chunk.cpp chunkmanager.cpp chunkmesher.cpp chunkgenerator.cpp
|
set(SOURCE_FILES main.cpp controls.cpp chunk.cpp chunkmanager.cpp chunkmesher.cpp chunkgenerator.cpp
|
||||||
debugwindow.cpp renderer.cpp spacefilling.cpp stb_image.cpp utils.cpp OpenSimplexNoise.cpp)
|
debugwindow.cpp renderer.cpp spacefilling.cpp stb_image.cpp utils.cpp OpenSimplexNoise.cpp)
|
||||||
|
|
||||||
add_executable(OpenGLTest ${SOURCE_FILES})
|
add_executable(OpenGLTest ${SOURCE_FILES})
|
||||||
|
|
|
@ -15,11 +15,21 @@ namespace Chunk
|
||||||
return utils::coord3DTo1D(x, y, z, CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE);
|
return utils::coord3DTo1D(x, y, z, CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunk_index_t calculateIndex(glm::vec3 pos){
|
||||||
|
return calculateIndex(static_cast<chunk_intcoord_t>(pos.x), static_cast<chunk_intcoord_t>(pos.y),
|
||||||
|
static_cast<chunk_intcoord_t>(pos.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_index_t calculateIndex(chunk_intcoord_t i, chunk_intcoord_t j, chunk_intcoord_t k){
|
||||||
|
return i | (j << 10) | (k << 20);
|
||||||
|
}
|
||||||
|
|
||||||
Chunk::Chunk(glm::vec3 pos)
|
Chunk::Chunk(glm::vec3 pos)
|
||||||
{
|
{
|
||||||
this->position = pos;
|
this->position = pos;
|
||||||
this->setState(CHUNK_STATE_EMPTY, true);
|
this->setState(CHUNK_STATE_EMPTY, true);
|
||||||
this->setBlocks(0, CHUNK_MAX_INDEX, Block::AIR);
|
this->setBlocks(0, CHUNK_MAX_INDEX, Block::AIR);
|
||||||
|
this->index = calculateIndex(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk ::~Chunk()
|
Chunk ::~Chunk()
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace chunkmanager
|
||||||
// Concurrent hash table of chunks
|
// Concurrent hash table of chunks
|
||||||
ChunkTable chunks;
|
ChunkTable chunks;
|
||||||
// Chunk indices. Centered at (0,0,0), going in concentric sphere outwards
|
// 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<chunk_intcoord_t, 3>, chunks_volume> chunks_indices;
|
||||||
|
|
||||||
/* Multithreading */
|
/* Multithreading */
|
||||||
std::atomic_bool should_run;
|
std::atomic_bool should_run;
|
||||||
|
@ -37,47 +37,18 @@ namespace chunkmanager
|
||||||
int block_to_place{2};
|
int block_to_place{2};
|
||||||
|
|
||||||
// Init chunkmanager. Chunk indices and start threads
|
// Init chunkmanager. Chunk indices and start threads
|
||||||
int chunks_volume_real;
|
|
||||||
void init(){
|
void init(){
|
||||||
int index{0};
|
int index{0};
|
||||||
int rr{RENDER_DISTANCE * RENDER_DISTANCE};
|
|
||||||
|
|
||||||
int xp{0}, x{0};
|
for(chunk_intcoord_t i = -RENDER_DISTANCE; i < RENDER_DISTANCE; i++)
|
||||||
bool b = true;
|
for(chunk_intcoord_t j = -RENDER_DISTANCE; j < RENDER_DISTANCE; j++)
|
||||||
|
for(chunk_intcoord_t k = -RENDER_DISTANCE; k < RENDER_DISTANCE; k++){
|
||||||
|
|
||||||
// Iterate over all chunks, in concentric spheres starting fron the player and going outwards. Alternate left and right
|
chunks_indices[index][0]=i;
|
||||||
// Eq. of the sphere (x - a)² + (y - b)² + (z - c)² = r²
|
chunks_indices[index][1]=j;
|
||||||
while (xp <= RENDER_DISTANCE)
|
chunks_indices[index][2]=k;
|
||||||
{
|
|
||||||
// Alternate between left and right
|
|
||||||
if (b) x = +xp;
|
|
||||||
else x = -xp;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!b)
|
|
||||||
{
|
|
||||||
xp++;
|
|
||||||
b = true;
|
|
||||||
}
|
|
||||||
else b = false;
|
|
||||||
}
|
|
||||||
chunks_volume_real = index;
|
|
||||||
|
|
||||||
// Also init mesh data queue
|
// Also init mesh data queue
|
||||||
for(int i = 0; i < 10; i++)
|
for(int i = 0; i < 10; i++)
|
||||||
|
@ -95,8 +66,9 @@ namespace chunkmanager
|
||||||
void generate(){
|
void generate(){
|
||||||
while(should_run){
|
while(should_run){
|
||||||
ChunkPQEntry entry;
|
ChunkPQEntry entry;
|
||||||
while(chunks_to_generate_queue.try_pop(entry)) generateChunk(entry.first);
|
if(chunks_to_generate_queue.try_pop(entry)) generateChunk(entry.first);
|
||||||
}
|
}
|
||||||
|
chunks_to_generate_queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method for chunk meshing thread(s)
|
// Method for chunk meshing thread(s)
|
||||||
|
@ -111,6 +83,7 @@ namespace chunkmanager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
chunks_to_mesh_queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
oneapi::tbb::concurrent_queue<Chunk::Chunk*> chunks_todelete;
|
oneapi::tbb::concurrent_queue<Chunk::Chunk*> chunks_todelete;
|
||||||
|
@ -121,24 +94,14 @@ namespace chunkmanager
|
||||||
int chunkY=static_cast<int>(theCamera.getAtomicPosY() / CHUNK_SIZE);
|
int chunkY=static_cast<int>(theCamera.getAtomicPosY() / CHUNK_SIZE);
|
||||||
int chunkZ=static_cast<int>(theCamera.getAtomicPosZ() / CHUNK_SIZE);
|
int chunkZ=static_cast<int>(theCamera.getAtomicPosZ() / CHUNK_SIZE);
|
||||||
|
|
||||||
debug::window::set_parameter("px", theCamera.getAtomicPosX());
|
|
||||||
debug::window::set_parameter("py", theCamera.getAtomicPosY());
|
|
||||||
debug::window::set_parameter("pz", theCamera.getAtomicPosZ());
|
|
||||||
debug::window::set_parameter("cx", chunkX);
|
|
||||||
debug::window::set_parameter("cy", chunkY);
|
|
||||||
debug::window::set_parameter("cz", chunkZ);
|
|
||||||
debug::window::set_parameter("lx", theCamera.getFront().x);
|
|
||||||
debug::window::set_parameter("ly", theCamera.getFront().y);
|
|
||||||
debug::window::set_parameter("lz", theCamera.getFront().z);
|
|
||||||
|
|
||||||
// Update other chunks
|
// Update other chunks
|
||||||
for(int i = 0; i < chunks_volume_real; i++) {
|
for(int i = 0; i < chunks_volume; i++) {
|
||||||
const uint16_t x = chunks_indices[i][0] + chunkX;
|
const chunk_intcoord_t x = chunks_indices[i][0] + chunkX;
|
||||||
const uint16_t y = chunks_indices[i][1] + chunkY;
|
const chunk_intcoord_t y = chunks_indices[i][1] + chunkY;
|
||||||
const uint16_t z = chunks_indices[i][2] + chunkZ;
|
const chunk_intcoord_t z = chunks_indices[i][2] + chunkZ;
|
||||||
const uint32_t index = calculateIndex(x, y, z);
|
|
||||||
|
|
||||||
if(x > 1023 || y > 1023 || z > 1023) continue;
|
if(x < 0 || y < 0 || z < 0 || x > 1023 || y > 1023 || z > 1023) continue;
|
||||||
|
const chunk_index_t index = Chunk::calculateIndex(x, y, z);
|
||||||
|
|
||||||
ChunkTable::accessor a, a1, a2, b1, b2, c1, c2;
|
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(!chunks.find(a, index)) chunks.emplace(a, std::make_pair(index, new Chunk::Chunk(glm::vec3(x,y,z))));
|
||||||
|
@ -147,17 +110,17 @@ namespace chunkmanager
|
||||||
chunks_to_generate_queue.push(std::make_pair(a->second, GENERATION_PRIORITY_NORMAL));
|
chunks_to_generate_queue.push(std::make_pair(a->second, GENERATION_PRIORITY_NORMAL));
|
||||||
}else if(! (a->second->getState(Chunk::CHUNK_STATE_MESHED))){
|
}else if(! (a->second->getState(Chunk::CHUNK_STATE_MESHED))){
|
||||||
if(
|
if(
|
||||||
(x + 1 > 1023 || (chunks.find(a1, calculateIndex(x+1, y, z)) &&
|
(x + 1 > 1023 || (chunks.find(a1, Chunk::calculateIndex(x+1, y, z)) &&
|
||||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||||
(x - 1 < 0|| (chunks.find(a1, calculateIndex(x-1, y, z)) &&
|
(x - 1 < 0|| (chunks.find(a1, Chunk::calculateIndex(x-1, y, z)) &&
|
||||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||||
(y + 1 > 1023 || (chunks.find(a1, calculateIndex(x, y+1, z)) &&
|
(y + 1 > 1023 || (chunks.find(a1, Chunk::calculateIndex(x, y+1, z)) &&
|
||||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||||
(y - 1 < 0|| (chunks.find(a1, calculateIndex(x, y-1, z)) &&
|
(y - 1 < 0|| (chunks.find(a1, Chunk::calculateIndex(x, y-1, z)) &&
|
||||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||||
(z + 1 > 1023 || (chunks.find(a1, calculateIndex(x, y, z+1)) &&
|
(z + 1 > 1023 || (chunks.find(a1, Chunk::calculateIndex(x, y, z+1)) &&
|
||||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
a1->second->getState(Chunk::CHUNK_STATE_GENERATED))) &&
|
||||||
(z - 1 < 0|| (chunks.find(a1, calculateIndex(x, y, z-1)) &&
|
(z - 1 < 0|| (chunks.find(a1, Chunk::calculateIndex(x, y, z-1)) &&
|
||||||
a1->second->getState(Chunk::CHUNK_STATE_GENERATED)))
|
a1->second->getState(Chunk::CHUNK_STATE_GENERATED)))
|
||||||
)
|
)
|
||||||
chunks_to_mesh_queue.push(std::make_pair(a->second, MESHING_PRIORITY_NORMAL));
|
chunks_to_mesh_queue.push(std::make_pair(a->second, MESHING_PRIORITY_NORMAL));
|
||||||
|
@ -172,11 +135,11 @@ namespace chunkmanager
|
||||||
Chunk::Chunk* n;
|
Chunk::Chunk* n;
|
||||||
nUnloaded = 0;
|
nUnloaded = 0;
|
||||||
while(chunks_todelete.try_pop(n)){
|
while(chunks_todelete.try_pop(n)){
|
||||||
int x = static_cast<uint16_t>(n->getPosition().x);
|
chunk_intcoord_t x = static_cast<chunk_intcoord_t>(n->getPosition().x);
|
||||||
int y = static_cast<uint16_t>(n->getPosition().y);
|
chunk_intcoord_t y = static_cast<chunk_intcoord_t>(n->getPosition().y);
|
||||||
int z = static_cast<uint16_t>(n->getPosition().z);
|
chunk_intcoord_t z = static_cast<chunk_intcoord_t>(n->getPosition().z);
|
||||||
if(x > 1023 || y > 1023 || z > 1023) continue;
|
if(x > 1023 || y > 1023 || z > 1023) continue;
|
||||||
const uint32_t index = calculateIndex(x, y, z);
|
const uint32_t index = Chunk::calculateIndex(x, y, z);
|
||||||
|
|
||||||
chunks.erase(index);
|
chunks.erase(index);
|
||||||
//delete n;
|
//delete n;
|
||||||
|
@ -185,20 +148,21 @@ namespace chunkmanager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint32_t is fine, since i'm limiting the coordinate to only use up to ten bits (1023). There's actually two spare bits
|
|
||||||
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k){
|
|
||||||
return i | (j << 10) | (k << 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
oneapi::tbb::concurrent_queue<Chunk::Chunk*>& getDeleteVector(){ return chunks_todelete; }
|
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<chunk_intcoord_t, 3>, chunks_volume>& getChunksIndices(){ return chunks_indices; }
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
should_run=false;
|
should_run=false;
|
||||||
|
|
||||||
|
std::cout << "Waiting for secondary threads to shut down" << std::endl;
|
||||||
update_thread.join();
|
update_thread.join();
|
||||||
|
std::cout << "Update thread has terminated" << std::endl;
|
||||||
gen_thread.join();
|
gen_thread.join();
|
||||||
|
std::cout << "Generation thread has terminated" << std::endl;
|
||||||
mesh_thread.join();
|
mesh_thread.join();
|
||||||
|
std::cout << "Meshing thread has terminated" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy(){
|
void destroy(){
|
||||||
/*for(const auto& n : chunks){
|
/*for(const auto& n : chunks){
|
||||||
delete n.second;
|
delete n.second;
|
||||||
|
@ -225,7 +189,7 @@ namespace chunkmanager
|
||||||
if(px < 0 || py < 0 || pz < 0 || px >= 1024 || py >= 1024 || pz >= 1024) continue;
|
if(px < 0 || py < 0 || pz < 0 || px >= 1024 || py >= 1024 || pz >= 1024) continue;
|
||||||
|
|
||||||
ChunkTable::accessor a;
|
ChunkTable::accessor a;
|
||||||
if(!chunks.find(a, calculateIndex(px, py, pz))) continue;
|
if(!chunks.find(a, Chunk::calculateIndex(px, py, pz))) continue;
|
||||||
Chunk::Chunk* c = a->second;
|
Chunk::Chunk* c = a->second;
|
||||||
if(!c->getState(Chunk::CHUNK_STATE_GENERATED) || c->getState(Chunk::CHUNK_STATE_EMPTY)) continue;
|
if(!c->getState(Chunk::CHUNK_STATE_GENERATED) || c->getState(Chunk::CHUNK_STATE_EMPTY)) continue;
|
||||||
|
|
||||||
|
@ -254,7 +218,7 @@ namespace chunkmanager
|
||||||
// exit early if the position is invalid or the chunk does not exist
|
// exit early if the position is invalid or the chunk does not exist
|
||||||
if(px1 < 0 || py1 < 0 || pz1 < 0 || px1 >= 1024 || py1 >= 1024 || pz1 >= 1024) return;
|
if(px1 < 0 || py1 < 0 || pz1 < 0 || px1 >= 1024 || py1 >= 1024 || pz1 >= 1024) return;
|
||||||
ChunkTable::accessor a1;
|
ChunkTable::accessor a1;
|
||||||
if(!chunks.find(a1, calculateIndex(px1, py1, pz1))) return;
|
if(!chunks.find(a1, Chunk::calculateIndex(px1, py1, pz1))) return;
|
||||||
Chunk::Chunk* c1 = a1->second;
|
Chunk::Chunk* c1 = a1->second;
|
||||||
// place the new block (only stone for now)
|
// place the new block (only stone for now)
|
||||||
c1->setBlock((Block)block_to_place, bx1, by1, bz1);
|
c1->setBlock((Block)block_to_place, bx1, by1, bz1);
|
||||||
|
@ -276,17 +240,17 @@ namespace chunkmanager
|
||||||
|
|
||||||
// When necessary, also mesh nearby chunks
|
// When necessary, also mesh nearby chunks
|
||||||
ChunkTable::accessor a1, a2, b1, b2, c1, c2;
|
ChunkTable::accessor a1, a2, b1, b2, c1, c2;
|
||||||
if(bx == 0 && px - 1 >= 0 && chunks.find(a1, calculateIndex(px - 1, py, pz)))
|
if(bx == 0 && px - 1 >= 0 && chunks.find(a1, Chunk::calculateIndex(px - 1, py, pz)))
|
||||||
chunkmesher::mesh(a1->second);
|
chunkmesher::mesh(a1->second);
|
||||||
if(by == 0 && py - 1 >= 0 && chunks.find(b1, calculateIndex(px, py - 1, pz)))
|
if(by == 0 && py - 1 >= 0 && chunks.find(b1, Chunk::calculateIndex(px, py - 1, pz)))
|
||||||
chunkmesher::mesh(b1->second);
|
chunkmesher::mesh(b1->second);
|
||||||
if(bz == 0 && pz - 1 >= 0 && chunks.find(c1, calculateIndex(px, py, pz - 1)))
|
if(bz == 0 && pz - 1 >= 0 && chunks.find(c1, Chunk::calculateIndex(px, py, pz - 1)))
|
||||||
chunkmesher::mesh(c1->second);
|
chunkmesher::mesh(c1->second);
|
||||||
if(bx == CHUNK_SIZE - 1 && px +1 < 1024 && chunks.find(a2, calculateIndex(px +1, py, pz)))
|
if(bx == CHUNK_SIZE - 1 && px +1 < 1024 && chunks.find(a2, Chunk::calculateIndex(px +1, py, pz)))
|
||||||
chunkmesher::mesh(a2->second);
|
chunkmesher::mesh(a2->second);
|
||||||
if(by == CHUNK_SIZE - 1 && py +1 < 1024 && chunks.find(b2, calculateIndex(px, py +1, pz)))
|
if(by == CHUNK_SIZE - 1 && py +1 < 1024 && chunks.find(b2, Chunk::calculateIndex(px, py +1, pz)))
|
||||||
chunkmesher::mesh(b2->second);
|
chunkmesher::mesh(b2->second);
|
||||||
if(bz == CHUNK_SIZE - 1 && pz +1 < 1024 && chunks.find(c2, calculateIndex(px, py, pz +1)))
|
if(bz == CHUNK_SIZE - 1 && pz +1 < 1024 && chunks.find(c2, Chunk::calculateIndex(px, py, pz +1)))
|
||||||
chunkmesher::mesh(c2->second);
|
chunkmesher::mesh(c2->second);
|
||||||
|
|
||||||
debug::window::set_parameter("block_last_action", place);
|
debug::window::set_parameter("block_last_action", place);
|
||||||
|
@ -312,7 +276,7 @@ namespace chunkmanager
|
||||||
|
|
||||||
//std::cout << "Block at " << x << ", " << y << ", " << z << " is in chunk " << cx << "," << cy << "," << cz << "\n";
|
//std::cout << "Block at " << x << ", " << y << ", " << z << " is in chunk " << cx << "," << cy << "," << cz << "\n";
|
||||||
ChunkTable::accessor a;
|
ChunkTable::accessor a;
|
||||||
if(!chunks.find(a, calculateIndex(cx, cy, cz))) return Block::NULLBLK;
|
if(!chunks.find(a, Chunk::calculateIndex(cx, cy, cz))) return Block::NULLBLK;
|
||||||
else {
|
else {
|
||||||
int bx = x % CHUNK_SIZE;
|
int bx = x % CHUNK_SIZE;
|
||||||
int by = y % CHUNK_SIZE;
|
int by = y % CHUNK_SIZE;
|
||||||
|
@ -324,3 +288,4 @@ namespace chunkmanager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "controls.hpp"
|
||||||
|
#include "renderer.hpp"
|
||||||
|
|
||||||
|
namespace controls{
|
||||||
|
float lastBlockPick=0.0;
|
||||||
|
bool blockpick = false;
|
||||||
|
bool cursor = false;
|
||||||
|
|
||||||
|
void init(){
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(GLFWwindow* window){
|
||||||
|
float current_time = glfwGetTime();
|
||||||
|
|
||||||
|
// Reset blockpicking timeout has passed
|
||||||
|
if(current_time - lastBlockPick > BLOCKPICK_TIMEOUT) blockpick = false;
|
||||||
|
// Reset blockpicking if both mouse buttons are released
|
||||||
|
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_RELEASE && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_RELEASE) blockpick = false;
|
||||||
|
|
||||||
|
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS && !blockpick){
|
||||||
|
//chunkmanager::blockpick(false);
|
||||||
|
blockpick=true;
|
||||||
|
lastBlockPick=glfwGetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS && !blockpick){
|
||||||
|
//chunkmanager::blockpick(true);
|
||||||
|
blockpick=true;
|
||||||
|
lastBlockPick=glfwGetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(glfwGetKey(window, GLFW_KEY_F2) == GLFW_PRESS) renderer::saveScreenshot();
|
||||||
|
if(glfwGetKey(window, GLFW_KEY_F3) == GLFW_PRESS) renderer::saveScreenshot(true);
|
||||||
|
if(glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
|
||||||
|
cursor = !cursor;
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, cursor ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
62
src/main.cpp
62
src/main.cpp
|
@ -4,26 +4,23 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "main.hpp"
|
||||||
|
|
||||||
#define GLOBALS_DEFINER
|
#define GLOBALS_DEFINER
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
#undef GLOBALS_DEFINER
|
#undef GLOBALS_DEFINER
|
||||||
|
|
||||||
#include "chunkmanager.hpp"
|
#include "chunkmanager.hpp"
|
||||||
#include "main.hpp"
|
#include "controls.hpp"
|
||||||
#include "debugwindow.hpp"
|
#include "debugwindow.hpp"
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "spacefilling.hpp"
|
|
||||||
#include "shader.hpp"
|
#include "shader.hpp"
|
||||||
|
#include "spacefilling.hpp"
|
||||||
|
|
||||||
float deltaTime = 0.0f; // Time between current frame and last frame
|
float deltaTime = 0.0f; // Time between current frame and last frame
|
||||||
float lastFrame = 0.0f; // Time of last frame
|
float lastFrame = 0.0f; // Time of last frame
|
||||||
float lastFPSFrame = 0.0f;
|
float lastFPSFrame = 0.0f;
|
||||||
int frames = 0;
|
int frames = 0;
|
||||||
|
|
||||||
float lastBlockPick=0.0;
|
|
||||||
bool blockpick = false;
|
|
||||||
bool cursor = false;
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -70,6 +67,7 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceFilling::initLUT();
|
SpaceFilling::initLUT();
|
||||||
|
controls::init();
|
||||||
chunkmanager::init();
|
chunkmanager::init();
|
||||||
debug::window::init(window);
|
debug::window::init(window);
|
||||||
renderer::init(window);
|
renderer::init(window);
|
||||||
|
@ -94,14 +92,24 @@ int main()
|
||||||
glClearColor(0.431f, 0.694f, 1.0f, 1.0f);
|
glClearColor(0.431f, 0.694f, 1.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// Input processing
|
// Input handling
|
||||||
processInput(window);
|
// Only close event is handles by main
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
// the rest of input processing is handled by controls.cpp
|
||||||
|
controls::update(window);
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
theCamera.update(window, deltaTime);
|
theCamera.update(window, deltaTime);
|
||||||
|
debug::window::set_parameter("px", theCamera.getPos().x);
|
||||||
// Reset blockping timeout if 200ms have passed
|
debug::window::set_parameter("py", theCamera.getPos().y);
|
||||||
if(glfwGetTime() - lastBlockPick > 0.1) blockpick = false;
|
debug::window::set_parameter("pz", theCamera.getPos().z);
|
||||||
|
debug::window::set_parameter("cx", (int)(theCamera.getPos().x / CHUNK_SIZE));
|
||||||
|
debug::window::set_parameter("cy", (int)(theCamera.getPos().y / CHUNK_SIZE));
|
||||||
|
debug::window::set_parameter("cz", (int)(theCamera.getPos().z / CHUNK_SIZE));
|
||||||
|
debug::window::set_parameter("lx", theCamera.getFront().x);
|
||||||
|
debug::window::set_parameter("ly", theCamera.getFront().y);
|
||||||
|
debug::window::set_parameter("lz", theCamera.getFront().z);
|
||||||
|
|
||||||
// Render pass
|
// Render pass
|
||||||
renderer::render();
|
renderer::render();
|
||||||
|
@ -134,33 +142,3 @@ void mouse_callback(GLFWwindow *window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
theCamera.mouseCallback(window, xpos, ypos);
|
theCamera.mouseCallback(window, xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void processInput(GLFWwindow *window)
|
|
||||||
{
|
|
||||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
|
||||||
glfwSetWindowShouldClose(window, true);
|
|
||||||
|
|
||||||
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS && !blockpick){
|
|
||||||
chunkmanager::blockpick(false);
|
|
||||||
blockpick=true;
|
|
||||||
lastBlockPick=glfwGetTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS && !blockpick){
|
|
||||||
chunkmanager::blockpick(true);
|
|
||||||
blockpick=true;
|
|
||||||
lastBlockPick=glfwGetTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset blockpicking if enough time has passed
|
|
||||||
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_RELEASE && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_RELEASE) blockpick = false;
|
|
||||||
|
|
||||||
if(glfwGetKey(window, GLFW_KEY_F2) == GLFW_PRESS) renderer::saveScreenshot();
|
|
||||||
if(glfwGetKey(window, GLFW_KEY_F3) == GLFW_PRESS) renderer::saveScreenshot(true);
|
|
||||||
if(glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
|
|
||||||
cursor = !cursor;
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, cursor ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -149,6 +149,7 @@ namespace renderer{
|
||||||
if(dist <= static_cast<float>(RENDER_DISTANCE)){
|
if(dist <= static_cast<float>(RENDER_DISTANCE)){
|
||||||
if(!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) continue;
|
if(!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) continue;
|
||||||
|
|
||||||
|
if(c->numVertices > 0){
|
||||||
// Increase total vertex count
|
// Increase total vertex count
|
||||||
vertices += c->numVertices;
|
vertices += c->numVertices;
|
||||||
|
|
||||||
|
@ -178,8 +179,6 @@ namespace renderer{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!out)
|
if (!out)
|
||||||
{
|
|
||||||
if(c->numVertices > 0)
|
|
||||||
{
|
{
|
||||||
theShader->setMat4("model", model);
|
theShader->setMat4("model", model);
|
||||||
theShader->setMat4("view", theCamera.getView());
|
theShader->setMat4("view", theCamera.getView());
|
||||||
|
|
Loading…
Reference in New Issue