refactor message-sending system between main and update thread
restores blockpicking with new multithread systemfix-multithread
parent
950e8c68ab
commit
df933bebdd
|
@ -1,8 +1,6 @@
|
||||||
#ifndef CHUNKMANAGER_H
|
#ifndef CHUNKMANAGER_H
|
||||||
#define CHUNKMANAGER_H
|
#define CHUNKMANAGER_H
|
||||||
|
|
||||||
#include "chunk.hpp"
|
|
||||||
|
|
||||||
#include <oneapi/tbb/concurrent_hash_map.h>
|
#include <oneapi/tbb/concurrent_hash_map.h>
|
||||||
#include <oneapi/tbb/concurrent_queue.h>
|
#include <oneapi/tbb/concurrent_queue.h>
|
||||||
#include <oneapi/tbb/concurrent_priority_queue.h>
|
#include <oneapi/tbb/concurrent_priority_queue.h>
|
||||||
|
@ -10,7 +8,9 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "chunk.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
|
#include "worldupdatemessage.h"
|
||||||
|
|
||||||
// Seconds to be passed outside of render distance for a chunk to be destroyed
|
// Seconds to be passed outside of render distance for a chunk to be destroyed
|
||||||
#define UNLOAD_TIMEOUT 5
|
#define UNLOAD_TIMEOUT 5
|
||||||
|
@ -35,14 +35,12 @@ namespace chunkmanager
|
||||||
typedef oneapi::tbb::concurrent_priority_queue<ChunkPQEntry, compare_f> ChunkPriorityQueue;
|
typedef oneapi::tbb::concurrent_priority_queue<ChunkPQEntry, compare_f> ChunkPriorityQueue;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void blockpick(bool place);
|
void update();
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
WorldUpdateMsgQueue& getWorldUpdateQueue();
|
||||||
std::array<std::array<int16_t, 3>, chunks_volume>& getChunksIndices();
|
std::array<std::array<int16_t, 3>, chunks_volume>& getChunksIndices();
|
||||||
Block getBlockAtPos(int x, int y, int z);
|
Block getBlockAtPos(int x, int y, int z);
|
||||||
void update();
|
|
||||||
void primary_thread_update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "worldupdatemessage.h"
|
#include "worldupdatemessage.h"
|
||||||
|
|
||||||
|
#define BLOCKPICK_TIMEOUT 0.1f
|
||||||
|
|
||||||
namespace controls{
|
namespace controls{
|
||||||
void init();
|
void init();
|
||||||
void update(GLFWwindow* window);
|
void update(GLFWwindow* window);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef WORLD_UPDATE_MSG_H
|
||||||
|
#define WORLD_UPDATE_MSG_H
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <oneapi/tbb/concurrent_queue.h>
|
||||||
|
|
||||||
|
enum class WorldUpdateMsgType{
|
||||||
|
BLOCKPICK_PLACE,
|
||||||
|
BLOCKPICK_BREAK
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct WorldUpdateMsg{
|
||||||
|
WorldUpdateMsgType msg_type;
|
||||||
|
glm::vec3 cameraPos;
|
||||||
|
glm::vec3 cameraFront;
|
||||||
|
float time;
|
||||||
|
} WorldUpdateMsg;
|
||||||
|
|
||||||
|
typedef oneapi::tbb::concurrent_queue<WorldUpdateMsg> WorldUpdateMsgQueue;
|
||||||
|
|
||||||
|
#endif
|
|
@ -22,9 +22,12 @@
|
||||||
|
|
||||||
namespace chunkmanager
|
namespace chunkmanager
|
||||||
{
|
{
|
||||||
|
void blockpick(WorldUpdateMsg& msg); // There's no need of passing by value again (check
|
||||||
|
// controls.cpp)
|
||||||
void generate();
|
void generate();
|
||||||
void mesh();
|
void mesh();
|
||||||
|
|
||||||
|
/* Chunk holding data structures */
|
||||||
// Concurrent hash table of chunks
|
// Concurrent hash table of chunks
|
||||||
ChunkTable chunks;
|
ChunkTable chunks;
|
||||||
// Concurrent queue for chunks to be deleted
|
// Concurrent queue for chunks to be deleted
|
||||||
|
@ -32,6 +35,9 @@ namespace chunkmanager
|
||||||
// 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<int16_t, 3>, chunks_volume> chunks_indices;
|
std::array<std::array<int16_t, 3>, chunks_volume> chunks_indices;
|
||||||
|
|
||||||
|
/* World Update messaging data structure */
|
||||||
|
WorldUpdateMsgQueue WorldUpdateQueue;
|
||||||
|
|
||||||
/* Multithreading */
|
/* Multithreading */
|
||||||
std::atomic_bool should_run;
|
std::atomic_bool should_run;
|
||||||
std::thread gen_thread, mesh_thread, update_thread;
|
std::thread gen_thread, mesh_thread, update_thread;
|
||||||
|
@ -40,7 +46,10 @@ namespace chunkmanager
|
||||||
// Queue of chunks to be meshed
|
// Queue of chunks to be meshed
|
||||||
ChunkPriorityQueue chunks_to_mesh_queue;
|
ChunkPriorityQueue chunks_to_mesh_queue;
|
||||||
|
|
||||||
|
/* Block picking */
|
||||||
int block_to_place{2};
|
int block_to_place{2};
|
||||||
|
|
||||||
|
WorldUpdateMsgQueue& getWorldUpdateQueue(){ return WorldUpdateQueue; }
|
||||||
|
|
||||||
// Init chunkmanager. Chunk indices and start threads
|
// Init chunkmanager. Chunk indices and start threads
|
||||||
void init(){
|
void init(){
|
||||||
|
@ -94,11 +103,25 @@ namespace chunkmanager
|
||||||
|
|
||||||
void update(){
|
void update(){
|
||||||
while(should_run) {
|
while(should_run) {
|
||||||
|
// Setup variables for the whole loop
|
||||||
|
// Atomic is needed by parallel_for
|
||||||
std::atomic_int nUnloaded{0}, nMarkUnload{0}, nExplored{0}, nMeshed{0}, nGenerated{0};
|
std::atomic_int nUnloaded{0}, nMarkUnload{0}, nExplored{0}, nMeshed{0}, nGenerated{0};
|
||||||
std::atomic_int chunkX=static_cast<int>(theCamera.getAtomicPosX() / CHUNK_SIZE);
|
std::atomic_int chunkX=static_cast<int>(theCamera.getAtomicPosX() / CHUNK_SIZE);
|
||||||
std::atomic_int chunkY=static_cast<int>(theCamera.getAtomicPosY() / CHUNK_SIZE);
|
std::atomic_int chunkY=static_cast<int>(theCamera.getAtomicPosY() / CHUNK_SIZE);
|
||||||
std::atomic_int chunkZ=static_cast<int>(theCamera.getAtomicPosZ() / CHUNK_SIZE);
|
std::atomic_int chunkZ=static_cast<int>(theCamera.getAtomicPosZ() / CHUNK_SIZE);
|
||||||
|
|
||||||
|
/* Process update messages before anything happens */
|
||||||
|
WorldUpdateMsg msg;
|
||||||
|
while(WorldUpdateQueue.try_pop(msg)){
|
||||||
|
switch(msg.msg_type){
|
||||||
|
case WorldUpdateMsgType::BLOCKPICK_BREAK:
|
||||||
|
case WorldUpdateMsgType::BLOCKPICK_PLACE:
|
||||||
|
blockpick(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Eventually delete old chunks
|
// Eventually delete old chunks
|
||||||
int i;
|
int i;
|
||||||
ChunkTable::accessor a;
|
ChunkTable::accessor a;
|
||||||
|
@ -225,14 +248,12 @@ namespace chunkmanager
|
||||||
void destroy(){
|
void destroy(){
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void blockpick(WorldUpdateMsg& msg){
|
||||||
void blockpick(bool place){
|
|
||||||
// cast a ray from the camera in the direction pointed by the camera itself
|
// cast a ray from the camera in the direction pointed by the camera itself
|
||||||
glm::vec3 pos = glm::vec3(theCamera.getAtomicPosX(), theCamera.getAtomicPosY(),
|
glm::vec3 pos = msg.cameraPos;
|
||||||
theCamera.getAtomicPosZ());
|
|
||||||
for(float t = 0.0; t <= 10.0; t += 0.5){
|
for(float t = 0.0; t <= 10.0; t += 0.5){
|
||||||
// traverse the ray a block at the time
|
// traverse the ray a block at the time
|
||||||
pos = theCamera.getPos() + t * theCamera.getFront();
|
pos = msg.cameraPos + t*msg.cameraFront;
|
||||||
|
|
||||||
// get which chunk and block the ray is at
|
// get which chunk and block the ray is at
|
||||||
int px = ((int)(pos.x))/CHUNK_SIZE;
|
int px = ((int)(pos.x))/CHUNK_SIZE;
|
||||||
|
@ -246,7 +267,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;
|
||||||
|
|
||||||
|
@ -257,7 +278,7 @@ namespace chunkmanager
|
||||||
if(b != Block::AIR){
|
if(b != Block::AIR){
|
||||||
|
|
||||||
// if placing a new block
|
// if placing a new block
|
||||||
if(place){
|
if(msg.msg_type == WorldUpdateMsgType::BLOCKPICK_PLACE){
|
||||||
// Go half a block backwards on the ray, to check the block where the ray was
|
// Go half a block backwards on the ray, to check the block where the ray was
|
||||||
// coming from
|
// coming from
|
||||||
// Doing this and not using normal adds the unexpected (and unwanted) ability to
|
// Doing this and not using normal adds the unexpected (and unwanted) ability to
|
||||||
|
@ -275,7 +296,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);
|
||||||
|
@ -284,8 +305,9 @@ namespace chunkmanager
|
||||||
chunks_to_mesh_queue.push(std::make_pair(c1, MESHING_PRIORITY_PLAYER_EDIT));
|
chunks_to_mesh_queue.push(std::make_pair(c1, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
chunks_to_mesh_queue.push(std::make_pair(c, MESHING_PRIORITY_PLAYER_EDIT));
|
chunks_to_mesh_queue.push(std::make_pair(c, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
|
|
||||||
debug::window::set_parameter("block_last_action", place);
|
debug::window::set_parameter("block_last_action", (int)msg.msg_type);
|
||||||
debug::window::set_parameter("block_last_action_block_type", (int)(Block::STONE));
|
debug::window::set_parameter("block_last_action_block_type",
|
||||||
|
(int)(block_to_place));
|
||||||
debug::window::set_parameter("block_last_action_x", px1*CHUNK_SIZE + bx1);
|
debug::window::set_parameter("block_last_action_x", px1*CHUNK_SIZE + bx1);
|
||||||
debug::window::set_parameter("block_last_action_y", px1*CHUNK_SIZE + by1);
|
debug::window::set_parameter("block_last_action_y", px1*CHUNK_SIZE + by1);
|
||||||
debug::window::set_parameter("block_last_action_z", px1*CHUNK_SIZE + bz1);
|
debug::window::set_parameter("block_last_action_z", px1*CHUNK_SIZE + bz1);
|
||||||
|
@ -297,20 +319,20 @@ 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);
|
chunks_to_mesh_queue.push(std::make_pair(a1->second, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
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);
|
chunks_to_mesh_queue.push(std::make_pair(a2->second, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
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);
|
chunks_to_mesh_queue.push(std::make_pair(b1->second, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
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);
|
chunks_to_mesh_queue.push(std::make_pair(b2->second, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
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);
|
chunks_to_mesh_queue.push(std::make_pair(c1->second, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
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);
|
chunks_to_mesh_queue.push(std::make_pair(c2->second, MESHING_PRIORITY_PLAYER_EDIT));
|
||||||
|
|
||||||
debug::window::set_parameter("block_last_action", place);
|
debug::window::set_parameter("block_last_action", (int)msg.msg_type);
|
||||||
debug::window::set_parameter("block_last_action_block_type", (int) (Block::AIR));
|
debug::window::set_parameter("block_last_action_block_type", (int) (Block::AIR));
|
||||||
debug::window::set_parameter("block_last_action_x", px*CHUNK_SIZE + bx);
|
debug::window::set_parameter("block_last_action_x", px*CHUNK_SIZE + bx);
|
||||||
debug::window::set_parameter("block_last_action_y", py*CHUNK_SIZE + by);
|
debug::window::set_parameter("block_last_action_y", py*CHUNK_SIZE + by);
|
||||||
|
@ -322,6 +344,7 @@ namespace chunkmanager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Block getBlockAtPos(int x, int y, int z){
|
Block getBlockAtPos(int x, int y, int z){
|
||||||
if(x < 0 || y < 0 || z < 0) return Block::NULLBLK;
|
if(x < 0 || y < 0 || z < 0) return Block::NULLBLK;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
#include "controls.hpp"
|
#include "controls.hpp"
|
||||||
|
|
||||||
|
#include "camera.hpp"
|
||||||
|
#include "chunkmanager.hpp"
|
||||||
|
#include "globals.hpp"
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
|
|
||||||
namespace controls{
|
namespace controls{
|
||||||
|
@ -11,24 +15,42 @@ namespace controls{
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(GLFWwindow* window){
|
void update(GLFWwindow* window){
|
||||||
// Reset blockping timeout if 200ms have passed
|
// Reset blockping timeout have passed
|
||||||
if(glfwGetTime() - lastBlockPick > 0.1) blockpick = false;
|
float current_time = glfwGetTime();
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* BlockPicking */
|
||||||
// Reset blockpicking if enough time has passed
|
// Reset blockpicking if enough time 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_1) == GLFW_RELEASE && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_RELEASE) blockpick = false;
|
||||||
|
// Process block picking if a mouse button is pressed
|
||||||
|
if((glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS ||
|
||||||
|
glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2 == GLFW_PRESS)) && !blockpick){
|
||||||
|
|
||||||
|
// Start timeout for next block pick action
|
||||||
|
blockpick = true;
|
||||||
|
lastBlockPick = current_time;
|
||||||
|
|
||||||
|
// Construct the message to send to chunkmanager
|
||||||
|
|
||||||
|
// WorldUpdateMsg is allocated on the stack
|
||||||
|
// unlike ChunkMeshData, the fields of WorldUpdateMsg are few and light, so there's no
|
||||||
|
// problem in passing them by value each time.
|
||||||
|
// It also has the advantage of having less memory to manage, since I'm not allocating
|
||||||
|
// anything on the heap
|
||||||
|
|
||||||
|
WorldUpdateMsg msg{};
|
||||||
|
msg.cameraPos = theCamera.getPos();
|
||||||
|
msg.cameraFront = theCamera.getFront();
|
||||||
|
msg.time = current_time;
|
||||||
|
msg.msg_type = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS ?
|
||||||
|
WorldUpdateMsgType::BLOCKPICK_PLACE : WorldUpdateMsgType::BLOCKPICK_BREAK;
|
||||||
|
|
||||||
|
// Send to chunk manager
|
||||||
|
chunkmanager::getWorldUpdateQueue().push(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SCREENSHOTS */
|
||||||
if(glfwGetKey(window, GLFW_KEY_F2) == GLFW_PRESS) renderer::saveScreenshot();
|
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_F3) == GLFW_PRESS) renderer::saveScreenshot(true);
|
||||||
if(glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
|
if(glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
|
||||||
|
|
53
src/main.cpp
53
src/main.cpp
|
@ -1,15 +1,16 @@
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "main.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#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 "spacefilling.hpp"
|
||||||
|
@ -20,10 +21,6 @@ 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()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -68,9 +65,10 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceFilling::initLUT();
|
SpaceFilling::initLUT();
|
||||||
debug::window::init(window);
|
controls::init();
|
||||||
chunkmanager::init();
|
chunkmanager::init();
|
||||||
chunkmesher::init();
|
chunkmesher::init();
|
||||||
|
debug::window::init(window);
|
||||||
renderer::init(window);
|
renderer::init(window);
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
|
@ -93,16 +91,15 @@ 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);
|
||||||
|
|
||||||
|
// Only handle window closing here
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
|
||||||
// Input processing
|
// Input processing
|
||||||
processInput(window);
|
controls::update(window);
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
theCamera.update(window, deltaTime);
|
theCamera.update(window, deltaTime);
|
||||||
|
|
||||||
// Reset blockping timeout if 200ms have passed
|
|
||||||
if(glfwGetTime() - lastBlockPick > 0.1) blockpick = false;
|
|
||||||
|
|
||||||
//chunkmanager::primary_thread_update();
|
|
||||||
|
|
||||||
// Render pass
|
// Render pass
|
||||||
renderer::render();
|
renderer::render();
|
||||||
|
@ -135,33 +132,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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue