Merge pull request 'Misc fixes in preparation for multithreading refactor' (#10) from multithread-refactor into main
Reviewed-on: #10pull/13/head^2
commit
44edf3e53a
|
@ -18,6 +18,10 @@ public:
|
|||
|
||||
// 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);
|
||||
|
||||
posX = cameraPos.x;
|
||||
posY = cameraPos.y;
|
||||
posZ = cameraPos.z;
|
||||
}
|
||||
|
||||
void update(GLFWwindow *window, float deltaTime)
|
||||
|
@ -112,7 +116,7 @@ public:
|
|||
|
||||
|
||||
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 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 direction = glm::vec3(0.0f);
|
||||
|
|
|
@ -20,9 +20,16 @@
|
|||
#define CHUNK_VOLUME (CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE)
|
||||
#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
|
||||
{
|
||||
|
||||
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_MESHED = 2;
|
||||
constexpr uint8_t CHUNK_STATE_MESH_LOADED = 4;
|
||||
|
@ -58,12 +65,15 @@ namespace Chunk
|
|||
public:
|
||||
GLuint VAO{0}, VBO{0}, extentsBuffer{0}, texinfoBuffer{0}, numVertices{0};
|
||||
std::atomic<float> unload_timer{0};
|
||||
chunk_index_t getIndex(){ return this->index; }
|
||||
|
||||
private:
|
||||
glm::vec3 position{};
|
||||
IntervalMap<Block> blocks{};
|
||||
|
||||
std::atomic_uint8_t state{0};
|
||||
|
||||
chunk_index_t index;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
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;
|
||||
// The comparing function to use
|
||||
struct compare_f {
|
||||
|
@ -31,12 +31,11 @@ namespace chunkmanager
|
|||
|
||||
void init();
|
||||
void blockpick(bool place);
|
||||
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k);
|
||||
|
||||
void stop();
|
||||
void destroy();
|
||||
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);
|
||||
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
|
||||
|
||||
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 float sines[360];
|
||||
|
|
|
@ -3,6 +3,5 @@
|
|||
|
||||
void framebuffer_size_callback(GLFWwindow *, int, int);
|
||||
void mouse_callback(GLFWwindow *window, double xpos, double ypos);
|
||||
void processInput(GLFWwindow *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
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)
|
||||
|
||||
add_executable(OpenGLTest ${SOURCE_FILES})
|
||||
|
|
|
@ -15,11 +15,21 @@ namespace Chunk
|
|||
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)
|
||||
{
|
||||
this->position = pos;
|
||||
this->setState(CHUNK_STATE_EMPTY, true);
|
||||
this->setBlocks(0, CHUNK_MAX_INDEX, Block::AIR);
|
||||
this->index = calculateIndex(pos);
|
||||
}
|
||||
|
||||
Chunk ::~Chunk()
|
||||
|
|
|
@ -24,7 +24,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<chunk_intcoord_t, 3>, chunks_volume> chunks_indices;
|
||||
|
||||
/* Multithreading */
|
||||
std::atomic_bool should_run;
|
||||
|
@ -37,47 +37,18 @@ namespace chunkmanager
|
|||
int block_to_place{2};
|
||||
|
||||
// Init chunkmanager. Chunk indices and start threads
|
||||
int chunks_volume_real;
|
||||
void init(){
|
||||
int index{0};
|
||||
int rr{RENDER_DISTANCE * RENDER_DISTANCE};
|
||||
|
||||
int xp{0}, x{0};
|
||||
bool b = true;
|
||||
for(chunk_intcoord_t i = -RENDER_DISTANCE; i < RENDER_DISTANCE; i++)
|
||||
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
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Also init mesh data queue
|
||||
for(int i = 0; i < 10; i++)
|
||||
|
@ -95,8 +66,9 @@ namespace chunkmanager
|
|||
void generate(){
|
||||
while(should_run){
|
||||
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)
|
||||
|
@ -111,6 +83,7 @@ namespace chunkmanager
|
|||
}
|
||||
}
|
||||
}
|
||||
chunks_to_mesh_queue.clear();
|
||||
}
|
||||
|
||||
oneapi::tbb::concurrent_queue<Chunk::Chunk*> chunks_todelete;
|
||||
|
@ -121,24 +94,14 @@ namespace chunkmanager
|
|||
int chunkY=static_cast<int>(theCamera.getAtomicPosY() / 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
|
||||
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);
|
||||
for(int i = 0; i < chunks_volume; i++) {
|
||||
const chunk_intcoord_t x = chunks_indices[i][0] + chunkX;
|
||||
const chunk_intcoord_t y = chunks_indices[i][1] + chunkY;
|
||||
const chunk_intcoord_t z = chunks_indices[i][2] + chunkZ;
|
||||
|
||||
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;
|
||||
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));
|
||||
}else if(! (a->second->getState(Chunk::CHUNK_STATE_MESHED))){
|
||||
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))) &&
|
||||
(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))) &&
|
||||
(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))) &&
|
||||
(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))) &&
|
||||
(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))) &&
|
||||
(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)))
|
||||
)
|
||||
chunks_to_mesh_queue.push(std::make_pair(a->second, MESHING_PRIORITY_NORMAL));
|
||||
|
@ -172,11 +135,11 @@ namespace chunkmanager
|
|||
Chunk::Chunk* n;
|
||||
nUnloaded = 0;
|
||||
while(chunks_todelete.try_pop(n)){
|
||||
int x = static_cast<uint16_t>(n->getPosition().x);
|
||||
int y = static_cast<uint16_t>(n->getPosition().y);
|
||||
int z = static_cast<uint16_t>(n->getPosition().z);
|
||||
chunk_intcoord_t x = static_cast<chunk_intcoord_t>(n->getPosition().x);
|
||||
chunk_intcoord_t y = static_cast<chunk_intcoord_t>(n->getPosition().y);
|
||||
chunk_intcoord_t z = static_cast<chunk_intcoord_t>(n->getPosition().z);
|
||||
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);
|
||||
//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; }
|
||||
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() {
|
||||
should_run=false;
|
||||
|
||||
std::cout << "Waiting for secondary threads to shut down" << std::endl;
|
||||
update_thread.join();
|
||||
std::cout << "Update thread has terminated" << std::endl;
|
||||
gen_thread.join();
|
||||
std::cout << "Generation thread has terminated" << std::endl;
|
||||
mesh_thread.join();
|
||||
std::cout << "Meshing thread has terminated" << std::endl;
|
||||
}
|
||||
|
||||
void destroy(){
|
||||
/*for(const auto& n : chunks){
|
||||
delete n.second;
|
||||
|
@ -225,7 +189,7 @@ namespace chunkmanager
|
|||
if(px < 0 || py < 0 || pz < 0 || px >= 1024 || py >= 1024 || pz >= 1024) continue;
|
||||
|
||||
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;
|
||||
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
|
||||
if(px1 < 0 || py1 < 0 || pz1 < 0 || px1 >= 1024 || py1 >= 1024 || pz1 >= 1024) return;
|
||||
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;
|
||||
// place the new block (only stone for now)
|
||||
c1->setBlock((Block)block_to_place, bx1, by1, bz1);
|
||||
|
@ -276,17 +240,17 @@ namespace chunkmanager
|
|||
|
||||
// When necessary, also mesh nearby chunks
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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";
|
||||
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 {
|
||||
int bx = x % 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 <thread>
|
||||
|
||||
#include "main.hpp"
|
||||
|
||||
#define GLOBALS_DEFINER
|
||||
#include "globals.hpp"
|
||||
#undef GLOBALS_DEFINER
|
||||
|
||||
#include "chunkmanager.hpp"
|
||||
#include "main.hpp"
|
||||
#include "controls.hpp"
|
||||
#include "debugwindow.hpp"
|
||||
#include "renderer.hpp"
|
||||
#include "spacefilling.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "spacefilling.hpp"
|
||||
|
||||
float deltaTime = 0.0f; // Time between current frame and last frame
|
||||
float lastFrame = 0.0f; // Time of last frame
|
||||
float lastFPSFrame = 0.0f;
|
||||
int frames = 0;
|
||||
|
||||
float lastBlockPick=0.0;
|
||||
bool blockpick = false;
|
||||
bool cursor = false;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
|
@ -70,6 +67,7 @@ int main()
|
|||
}
|
||||
|
||||
SpaceFilling::initLUT();
|
||||
controls::init();
|
||||
chunkmanager::init();
|
||||
debug::window::init(window);
|
||||
renderer::init(window);
|
||||
|
@ -94,14 +92,24 @@ int main()
|
|||
glClearColor(0.431f, 0.694f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Input processing
|
||||
processInput(window);
|
||||
// Input handling
|
||||
// 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
|
||||
theCamera.update(window, deltaTime);
|
||||
|
||||
// Reset blockping timeout if 200ms have passed
|
||||
if(glfwGetTime() - lastBlockPick > 0.1) blockpick = false;
|
||||
debug::window::set_parameter("px", theCamera.getPos().x);
|
||||
debug::window::set_parameter("py", theCamera.getPos().y);
|
||||
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
|
||||
renderer::render();
|
||||
|
@ -134,33 +142,3 @@ void mouse_callback(GLFWwindow *window, double xpos, double 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,37 +149,36 @@ namespace renderer{
|
|||
if(dist <= static_cast<float>(RENDER_DISTANCE)){
|
||||
if(!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) continue;
|
||||
|
||||
// Increase total vertex count
|
||||
vertices += c->numVertices;
|
||||
if(c->numVertices > 0){
|
||||
// Increase total vertex count
|
||||
vertices += c->numVertices;
|
||||
|
||||
// reset out-of-vision and unload flags
|
||||
c->setState(Chunk::CHUNK_STATE_OUTOFVISION, false);
|
||||
c->setState(Chunk::CHUNK_STATE_UNLOADED, false);
|
||||
// reset out-of-vision and unload flags
|
||||
c->setState(Chunk::CHUNK_STATE_OUTOFVISION, false);
|
||||
c->setState(Chunk::CHUNK_STATE_UNLOADED, false);
|
||||
|
||||
// Perform frustum culling and eventually render
|
||||
glm::vec3 chunk = c->getPosition();
|
||||
glm::vec4 chunkW = glm::vec4(chunk.x*static_cast<float>(CHUNK_SIZE), chunk.y*static_cast<float>(CHUNK_SIZE), chunk.z*static_cast<float>(CHUNK_SIZE),1.0);
|
||||
glm::mat4 model = glm::translate(glm::mat4(1.0), ((float)CHUNK_SIZE) * chunk);
|
||||
// Perform frustum culling and eventually render
|
||||
glm::vec3 chunk = c->getPosition();
|
||||
glm::vec4 chunkW = glm::vec4(chunk.x*static_cast<float>(CHUNK_SIZE), chunk.y*static_cast<float>(CHUNK_SIZE), chunk.z*static_cast<float>(CHUNK_SIZE),1.0);
|
||||
glm::mat4 model = glm::translate(glm::mat4(1.0), ((float)CHUNK_SIZE) * chunk);
|
||||
|
||||
// Check if all the corners of the chunk are outside any of the planes
|
||||
// TODO (?) implement frustum culling as per (Inigo Quilez)[https://iquilezles.org/articles/frustumcorrect/], and check each
|
||||
// plane against each corner of the chunk
|
||||
bool out=false;
|
||||
int a{0};
|
||||
for(int p = 0; p < 6; p++){
|
||||
a = 0;
|
||||
for(int i = 0; i < 8; i++) a += glm::dot(frustumPlanes[p], glm::vec4(chunkW.x + ((float)(i & 1))*CHUNK_SIZE, chunkW.y
|
||||
+ ((float)((i & 2) >> 1))*CHUNK_SIZE, chunkW.z + ((float)((i & 4) >> 2))*CHUNK_SIZE, 1.0)) < 0.0;
|
||||
// Check if all the corners of the chunk are outside any of the planes
|
||||
// TODO (?) implement frustum culling as per (Inigo Quilez)[https://iquilezles.org/articles/frustumcorrect/], and check each
|
||||
// plane against each corner of the chunk
|
||||
bool out=false;
|
||||
int a{0};
|
||||
for(int p = 0; p < 6; p++){
|
||||
a = 0;
|
||||
for(int i = 0; i < 8; i++) a += glm::dot(frustumPlanes[p], glm::vec4(chunkW.x + ((float)(i & 1))*CHUNK_SIZE, chunkW.y
|
||||
+ ((float)((i & 2) >> 1))*CHUNK_SIZE, chunkW.z + ((float)((i & 4) >> 2))*CHUNK_SIZE, 1.0)) < 0.0;
|
||||
|
||||
if(a==8){
|
||||
out=true;
|
||||
break;
|
||||
if(a==8){
|
||||
out=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!out)
|
||||
{
|
||||
if(c->numVertices > 0)
|
||||
if (!out)
|
||||
{
|
||||
theShader->setMat4("model", model);
|
||||
theShader->setMat4("view", theCamera.getView());
|
||||
|
|
Loading…
Reference in New Issue