Compare commits
No commits in common. "main" and "multithread-refactor" have entirely different histories.
main
...
multithrea
|
@ -1,9 +1,6 @@
|
|||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow *, int, int);
|
||||
void mouse_callback(GLFWwindow *window, double xpos, double ypos);
|
||||
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
#ifndef INTERVALMAP_H
|
||||
#define INTERVALMAP_H
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator> //std::prev
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <memory> //std::shared_ptr
|
||||
#include <map>
|
||||
|
||||
template <typename K, typename V>
|
||||
class IntervalMap
|
||||
{
|
||||
|
||||
public:
|
||||
~IntervalMap(){
|
||||
treemap.clear();
|
||||
}
|
||||
|
||||
void insert(K start, K end, V value)
|
||||
{
|
||||
if (start >= end)
|
||||
return;
|
||||
|
||||
// The entry just before the end index
|
||||
auto tmp = treemap.upper_bound(end);
|
||||
auto end_prev_entry = tmp == treemap.end() ? tmp : --tmp;
|
||||
auto added_end = treemap.end();
|
||||
|
||||
// If it doesn't exist (empty map)
|
||||
if(end_prev_entry == treemap.end()){
|
||||
V v{};
|
||||
added_end = treemap.insert_or_assign(treemap.begin(), end, v);
|
||||
}
|
||||
// Or if it has value different from the insertion
|
||||
else if(end_prev_entry->second != value)
|
||||
// Add it back at the end
|
||||
added_end = treemap.insert_or_assign(end_prev_entry, end, end_prev_entry->second);
|
||||
|
||||
// The entry just before the start index
|
||||
tmp = treemap.upper_bound(start);
|
||||
auto start_prev_entry = tmp == treemap.end() ? tmp : --tmp;
|
||||
auto added_start = treemap.end();
|
||||
// If it has value different from the insertion
|
||||
if(start_prev_entry == treemap.end() || start_prev_entry->second != value)
|
||||
// Add the start node of the insertion
|
||||
added_start = treemap.insert_or_assign(start_prev_entry, start, value);
|
||||
|
||||
// Delete everything else inside
|
||||
// map.erase(start, end) deletes every node with key in the range [start, end)
|
||||
|
||||
// The key to start deleting from is the key after the start node we added
|
||||
// (We don't want to delete a node we just added)
|
||||
auto del_start = added_start == treemap.end() ? std::next(start_prev_entry) : std::next(added_start);
|
||||
auto del_end = added_end == treemap.end() ? end_prev_entry : added_end;
|
||||
auto del_end_next = std::next(del_end);
|
||||
|
||||
// If the node after the end is of the same type of the end, delete it
|
||||
// We cannot just expand del_end (++del_end) otherwise interval limits get messed up
|
||||
if(del_end != treemap.end() && del_end_next != treemap.end() && del_end->second ==
|
||||
del_end_next->second) treemap.erase(del_end_next);
|
||||
|
||||
// Delete everything in between
|
||||
if(del_start != treemap.end() && (del_end==treemap.end() || del_start->first <
|
||||
del_end->first)) treemap.erase(del_start, del_end);
|
||||
}
|
||||
|
||||
void remove(K at)
|
||||
{
|
||||
treemap.erase(at);
|
||||
}
|
||||
|
||||
auto at(K index)
|
||||
{
|
||||
const auto tmp = treemap.lower_bound(index);
|
||||
const auto r = tmp != treemap.begin() && tmp->first!=index ? std::prev(tmp) : tmp;
|
||||
return r;
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
for (auto i = treemap.begin(); i != treemap.end(); i++)
|
||||
std::cout << i->first << ": " << (int)(i->second) << "\n";
|
||||
if(!treemap.empty()) std::cout << "end key: " << std::prev(treemap.end())->first << "\n";
|
||||
}
|
||||
|
||||
std::unique_ptr<V[]> toArray(int *length)
|
||||
{
|
||||
if (treemap.empty())
|
||||
{
|
||||
*length = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto &end = std::prev(treemap.end());
|
||||
*length = end->first;
|
||||
if(*length == 0) return nullptr;
|
||||
|
||||
std::unique_ptr<V[]> arr(new V[*length]);
|
||||
auto start = treemap.begin();
|
||||
for (auto i = std::next(treemap.begin()); i != treemap.end(); i++)
|
||||
{
|
||||
for (int k = start->first; k < i->first; k++)
|
||||
arr[k] = start->second;
|
||||
start = i;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
void fromArray(V *arr, int length)
|
||||
{
|
||||
treemap.clear();
|
||||
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
V prev = arr[0];
|
||||
unsigned int prev_start = 0;
|
||||
for (unsigned int i = 1; i < length; i++)
|
||||
{
|
||||
if (prev != arr[i])
|
||||
{
|
||||
insert(prev_start, i, prev);
|
||||
prev_start = i;
|
||||
}
|
||||
prev = arr[i];
|
||||
}
|
||||
insert(prev_start, length, prev);
|
||||
}
|
||||
|
||||
auto begin(){
|
||||
return treemap.begin();
|
||||
}
|
||||
|
||||
auto end(){
|
||||
return treemap.end();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<K, V> treemap{};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -26,30 +26,29 @@ void main(){
|
|||
EmitVertex();
|
||||
|
||||
if(gs_in[0].Extents.x == 0){
|
||||
|
||||
TexCoord = vec3(gs_in[0].Extents.z, 0.0, gs_in[0].BlockType);
|
||||
TexCoord = vec3(0.0, gs_in[0].Extents.z, gs_in[0].BlockType);
|
||||
gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, gs_in[0].Extents.z, 0.0);
|
||||
FragPos = vec3(gl_Position);
|
||||
gl_Position = projection * view * gl_Position;
|
||||
EmitVertex();
|
||||
|
||||
TexCoord = vec3(0.0, gs_in[0].Extents.y, gs_in[0].BlockType);
|
||||
TexCoord = vec3(gs_in[0].Extents.y, 0.0, gs_in[0].BlockType);
|
||||
gl_Position = gl_in[0].gl_Position + vec4(0.0, gs_in[0].Extents.y, 0.0, 0.0);
|
||||
FragPos = vec3(gl_Position);
|
||||
gl_Position = projection * view * gl_Position;
|
||||
EmitVertex();
|
||||
|
||||
TexCoord = vec3(gs_in[0].Extents.z, gs_in[0].Extents.y, gs_in[0].BlockType);
|
||||
TexCoord = vec3(gs_in[0].Extents.y, gs_in[0].Extents.z, gs_in[0].BlockType);
|
||||
}
|
||||
else if(gs_in[0].Extents.y == 0){
|
||||
TexCoord = vec3(gs_in[0].Extents.x, 0.0, gs_in[0].BlockType);
|
||||
gl_Position = gl_in[0].gl_Position + vec4(gs_in[0].Extents.x, 0.0, 0.0, 0.0);
|
||||
TexCoord = vec3(0.0, gs_in[0].Extents.z, gs_in[0].BlockType);
|
||||
gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, gs_in[0].Extents.z, 0.0);
|
||||
FragPos = vec3(gl_Position);
|
||||
gl_Position = projection * view * gl_Position;
|
||||
EmitVertex();
|
||||
|
||||
TexCoord = vec3(0.0, gs_in[0].Extents.z, gs_in[0].BlockType);
|
||||
gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, gs_in[0].Extents.z, 0.0);
|
||||
TexCoord = vec3(gs_in[0].Extents.x, 0.0, gs_in[0].BlockType);
|
||||
gl_Position = gl_in[0].gl_Position + vec4(gs_in[0].Extents.x, 0.0, 0.0, 0.0);
|
||||
FragPos = vec3(gl_Position);
|
||||
gl_Position = projection * view * gl_Position;
|
||||
EmitVertex();
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <thread>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <oneapi/tbb/parallel_for.h>
|
||||
|
@ -18,7 +17,6 @@
|
|||
#include "debugwindow.hpp"
|
||||
#include "globals.hpp"
|
||||
#include "renderer.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace chunkmanager
|
||||
{
|
||||
|
@ -26,7 +24,6 @@ namespace chunkmanager
|
|||
// controls.cpp)
|
||||
void generate();
|
||||
void mesh();
|
||||
void send_to_chunk_meshing_thread(Chunk::Chunk* c, int priority);
|
||||
|
||||
/* Chunk holding data structures */
|
||||
// Concurrent hash table of chunks
|
||||
|
@ -94,11 +91,6 @@ namespace chunkmanager
|
|||
chunks_to_mesh_queue.clear();
|
||||
}
|
||||
|
||||
void send_to_chunk_meshing_thread(Chunk::Chunk* c, int priority){
|
||||
c->setState(Chunk::CHUNK_STATE_IN_MESHING_QUEUE, true);
|
||||
chunks_to_mesh_queue.push(std::make_pair(c, MESHING_PRIORITY_NORMAL));
|
||||
}
|
||||
|
||||
oneapi::tbb::concurrent_queue<chunk_index_t> chunks_todelete;
|
||||
void update(){
|
||||
while(should_run) {
|
||||
|
@ -225,7 +217,8 @@ namespace chunkmanager
|
|||
// Mark as present in the queue before sending to avoid strange
|
||||
// a chunk being marked as in the queue after it was already
|
||||
// processed
|
||||
send_to_chunk_meshing_thread(c, MESHING_PRIORITY_NORMAL);
|
||||
c->setState(Chunk::CHUNK_STATE_IN_MESHING_QUEUE, true);
|
||||
chunks_to_mesh_queue.push(std::make_pair(c, MESHING_PRIORITY_NORMAL));
|
||||
}
|
||||
}else mesh++;
|
||||
}
|
||||
|
@ -254,11 +247,6 @@ namespace chunkmanager
|
|||
}
|
||||
});
|
||||
|
||||
debug::window::set_parameter("update_chunks_total", (int)chunks.size());
|
||||
debug::window::set_parameter("update_chunks_generated", (int) nGenerated);
|
||||
debug::window::set_parameter("update_chunks_meshed", (int) nMeshed);
|
||||
debug::window::set_parameter("update_chunks_freed", (int) nUnloaded);
|
||||
debug::window::set_parameter("update_chunks_explored", (int) nExplored);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,20 +271,12 @@ namespace chunkmanager
|
|||
chunks.clear();
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 ray_intersect(glm::vec3 startposition, glm::vec3 startdir){
|
||||
int old_bx{0}, old_by{0}, old_bz{0};
|
||||
int old_px{0}, old_py{0}, old_pz{0};
|
||||
Chunk::Chunk* old_chunk{nullptr};
|
||||
glm::vec3 old_pos;
|
||||
|
||||
void blockpick(WorldUpdateMsg& msg){
|
||||
// cast a ray from the camera in the direction pointed by the camera itself
|
||||
glm::vec3 origin = startposition;
|
||||
glm::vec3 pos = origin;
|
||||
glm::vec3 front = startdir;
|
||||
glm::vec3 pos = msg.cameraPos;
|
||||
for(float t = 0.0; t <= 10.0; t += 0.5){
|
||||
// traverse the ray a block at the time
|
||||
pos = origin + t*front;
|
||||
pos = msg.cameraPos + t*msg.cameraFront;
|
||||
|
||||
// get which chunk and block the ray is at
|
||||
int px = ((int)(pos.x))/CHUNK_SIZE;
|
||||
|
@ -306,196 +286,84 @@ namespace chunkmanager
|
|||
int by = pos.y - py*CHUNK_SIZE;
|
||||
int bz = pos.z - pz*CHUNK_SIZE;
|
||||
|
||||
if(bx == old_bx && by == old_by && bz == old_bz) continue;
|
||||
|
||||
// exit early if the position is invalid or the chunk does not exist
|
||||
if(px < 0 || py < 0 || pz < 0 || px >= 1024 || py >= 1024 || pz >= 1024) continue;
|
||||
|
||||
ChunkTable::const_accessor a;
|
||||
ChunkTable::accessor a;
|
||||
if(!chunks.find(a, Chunk::calculateIndex(px, py, pz))) continue;
|
||||
Chunk::Chunk* c = a->second;
|
||||
if(!c->isFree() || !c->getState(Chunk::CHUNK_STATE_GENERATED)){
|
||||
a.release();
|
||||
continue;
|
||||
}
|
||||
if(!c->getState(Chunk::CHUNK_STATE_GENERATED) || c->getState(Chunk::CHUNK_STATE_EMPTY)) continue;
|
||||
|
||||
Block b = c->getBlock(bx, by, bz);
|
||||
|
||||
a.release();
|
||||
|
||||
// if the block is non empty
|
||||
if(b != Block::AIR) return pos;
|
||||
if(b != Block::AIR){
|
||||
|
||||
old_chunk = c;
|
||||
old_bx = bx;
|
||||
old_by = by;
|
||||
old_bz = bz;
|
||||
old_px = px;
|
||||
old_py = py;
|
||||
old_pz = pz;
|
||||
old_pos = pos;
|
||||
// if placing a new block
|
||||
if(msg.msg_type == WorldUpdateMsgType::BLOCKPICK_PLACE){
|
||||
// Go half a block backwards on the ray, to check the block where the ray was
|
||||
// coming from
|
||||
// Doing this and not using normal adds the unexpected (and unwanted) ability to
|
||||
// place blocks diagonally, without faces colliding with the block that has
|
||||
// been clicked
|
||||
pos -= theCamera.getFront()*0.5f;
|
||||
|
||||
}
|
||||
return glm::vec3(-1);
|
||||
}
|
||||
int px1 = ((int)(pos.x))/CHUNK_SIZE;
|
||||
int py1 = ((int)(pos.y))/CHUNK_SIZE;
|
||||
int pz1 = ((int)(pos.z))/CHUNK_SIZE;
|
||||
int bx1 = pos.x - px1*CHUNK_SIZE;
|
||||
int by1 = pos.y - py1*CHUNK_SIZE;
|
||||
int bz1 = pos.z - pz1*CHUNK_SIZE;
|
||||
|
||||
void blockpick(WorldUpdateMsg& msg){
|
||||
//std::cout << glm::to_string(ray_intersect(msg.cameraPos, msg.cameraFront)) << std::endl;
|
||||
glm::vec3 ray_pos = ray_intersect(msg.cameraPos, msg.cameraFront);
|
||||
if(ray_pos == glm::vec3(-1)) return;
|
||||
// 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, Chunk::calculateIndex(px1, py1, pz1))) return;
|
||||
Chunk::Chunk* c1 = a1->second;
|
||||
// place the new block (only stone for now)
|
||||
c1->setBlock(msg.block, bx1, by1, bz1);
|
||||
|
||||
// Chunk in which the blockpick is happening
|
||||
int chunkx = (int)(ray_pos.x) / CHUNK_SIZE;
|
||||
int chunky = (int)(ray_pos.y) / CHUNK_SIZE;
|
||||
int chunkz = (int)(ray_pos.z) / CHUNK_SIZE;
|
||||
// Block (chunk coord) in which the blockpick is happening
|
||||
int blockx = ray_pos.x - chunkx*CHUNK_SIZE;
|
||||
int blocky = ray_pos.y - chunky*CHUNK_SIZE;
|
||||
int blockz = ray_pos.z - chunkz*CHUNK_SIZE;
|
||||
// mark the mesh of the chunk the be updated
|
||||
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));
|
||||
|
||||
// The chunk must exist, otherwise ray_intersect would have returned an error
|
||||
// Also, the block must be different from AIR
|
||||
|
||||
ChunkTable::accessor a;
|
||||
if(!chunks.find(a, Chunk::calculateIndex(chunkx, chunky, chunkz))) return;
|
||||
Chunk::Chunk* c = a->second;
|
||||
if(!(c->isFree() && c->getState(Chunk::CHUNK_STATE_GENERATED))) return;
|
||||
|
||||
if(msg.msg_type == WorldUpdateMsgType::BLOCKPICK_BREAK){
|
||||
c->setBlock(Block::AIR, blockx, blocky, blockz);
|
||||
send_to_chunk_meshing_thread(c, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
}else{
|
||||
// Traverse voxel using Amanatides&Woo traversal algorithm
|
||||
// http://www.cse.yorku.ca/~amana/research/grid.pdf
|
||||
|
||||
glm::vec3 pos = msg.cameraPos;
|
||||
glm::vec3 front = glm::normalize(pos - ray_pos);
|
||||
|
||||
// Original chunk in which the blockpick started
|
||||
const int ochunkX=chunkx, ochunkY = chunky, ochunkZ = chunkz;
|
||||
|
||||
// The ray has equation pos + t*front
|
||||
|
||||
// Initialize phase
|
||||
// Origin integer voxel coordinates
|
||||
// Avoid floating point accuracy errors: work as close to 0 as possible, translate
|
||||
// everything later
|
||||
int basex = std::floor(ray_pos.x);
|
||||
int basey = std::floor(ray_pos.y);
|
||||
int basez = std::floor(ray_pos.z);
|
||||
double x = ray_pos.x - basex;
|
||||
double y = ray_pos.y - basey;
|
||||
double z = ray_pos.z - basez;
|
||||
|
||||
auto sign = [=](double f){ return f > 0 ? 1 : f < 0 ? -1 : 0; };
|
||||
auto tmax = [=](double p, double dir){
|
||||
int s = sign(dir);
|
||||
|
||||
if(s > 0)
|
||||
return (1 - p) / dir;
|
||||
else if(s < 0)
|
||||
return -(p) / dir;
|
||||
return 0.0;
|
||||
};
|
||||
|
||||
|
||||
// Step
|
||||
int stepX = sign(front.x);
|
||||
int stepY = sign(front.y);
|
||||
int stepZ = sign(front.z);
|
||||
|
||||
// tMax: the value of t at which the ray crosses the first voxel boundary
|
||||
double tMaxX = tmax(x, front.x);
|
||||
double tMaxY = tmax(y, front.y);
|
||||
double tMaxZ = tmax(z, front.z);
|
||||
|
||||
// tDelta: how far along the ray along they ray (in units of t) for the _ component of such
|
||||
// a movement to equal the width of a voxel
|
||||
double tDeltaX = stepX / front.x;
|
||||
double tDeltaY = stepY / front.y;
|
||||
double tDeltaZ = stepZ / front.z;
|
||||
|
||||
for(int i = 0; i < 10; i++){
|
||||
if(tMaxX < tMaxY){
|
||||
if(tMaxX < tMaxZ) {
|
||||
x += stepX;
|
||||
tMaxX += tDeltaX;
|
||||
}else{
|
||||
z += stepZ;
|
||||
tMaxZ += tDeltaZ;
|
||||
}
|
||||
debug::window::set_parameter("block_last_action", true);
|
||||
debug::window::set_parameter("block_last_action_block_type", (int)(msg.block));
|
||||
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_z", px1*CHUNK_SIZE + bz1);
|
||||
}else{
|
||||
if(tMaxY < tMaxZ){
|
||||
y += stepY;
|
||||
tMaxY += tDeltaY;
|
||||
}else{
|
||||
z += stepZ;
|
||||
tMaxZ += tDeltaZ;
|
||||
}
|
||||
// replace the current block with air to remove it
|
||||
c->setBlock( Block::AIR, bx, by, bz);
|
||||
|
||||
chunks_to_mesh_queue.push(std::make_pair(c, MESHING_PRIORITY_PLAYER_EDIT));
|
||||
|
||||
// When necessary, also mesh nearby chunks
|
||||
ChunkTable::accessor a1, a2, b1, b2, c1, c2;
|
||||
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, Chunk::calculateIndex(px, py - 1, pz)))
|
||||
chunkmesher::mesh(b1->second);
|
||||
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, Chunk::calculateIndex(px +1, py, pz)))
|
||||
chunkmesher::mesh(a2->second);
|
||||
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, Chunk::calculateIndex(px, py, pz +1)))
|
||||
chunkmesher::mesh(c2->second);
|
||||
|
||||
debug::window::set_parameter("block_last_action", false);
|
||||
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_y", py*CHUNK_SIZE + by);
|
||||
debug::window::set_parameter("block_last_action_z", pz*CHUNK_SIZE + bz);
|
||||
|
||||
}
|
||||
|
||||
int realx = basex + x;
|
||||
int realy = basey + y;
|
||||
int realz = basez + z;
|
||||
|
||||
chunkx = realx / CHUNK_SIZE;
|
||||
chunky = realy / CHUNK_SIZE;
|
||||
chunkz = realz / CHUNK_SIZE;
|
||||
|
||||
if(chunkx < 0 || chunky < 0 || chunkz < 0 || chunkx > 1023 || chunky > 1023 ||
|
||||
chunkz > 1023) continue;
|
||||
|
||||
blockx = realx - chunkx*CHUNK_SIZE;
|
||||
blocky = realy - chunky*CHUNK_SIZE;
|
||||
blockz = realz - chunkz*CHUNK_SIZE;
|
||||
|
||||
|
||||
Chunk::Chunk* chunk;
|
||||
ChunkTable::accessor b;
|
||||
|
||||
if(chunkx != ochunkX || chunky != ochunkY || chunkz != ochunkZ){
|
||||
if(!chunks.find(b, Chunk::calculateIndex(chunkx, chunky, chunkz)))
|
||||
continue;
|
||||
chunk = b->second;
|
||||
if(!(chunk->isFree() && chunk->getState(Chunk::CHUNK_STATE_GENERATED)))
|
||||
continue;
|
||||
|
||||
}else{
|
||||
chunk = c;
|
||||
}
|
||||
|
||||
if(chunk->getBlock(blockx, blocky, blockz) != Block::AIR) continue;
|
||||
chunk->setBlock(msg.block, blockx, blocky, blockz);
|
||||
send_to_chunk_meshing_thread(chunk, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Release the chunk in which the blockpick started to avoid locks
|
||||
a.release();
|
||||
// When necessary, also mesh nearby chunks
|
||||
ChunkTable::accessor a1, a2, b1, b2, c1, c2;
|
||||
if(blockx == 0 && chunkx - 1 >= 0 && chunks.find(a1, Chunk::calculateIndex(chunkx - 1, chunky, chunkz)))
|
||||
send_to_chunk_meshing_thread(a1->second, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
if(blocky == 0 && chunky - 1 >= 0 && chunks.find(b1, Chunk::calculateIndex(chunkx, chunky - 1, chunkz)))
|
||||
send_to_chunk_meshing_thread(b1->second, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
if(blockz == 0 && chunkz - 1 >= 0 && chunks.find(c1, Chunk::calculateIndex(chunkx, chunky, chunkz - 1)))
|
||||
send_to_chunk_meshing_thread(c1->second, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
if(blockx == CHUNK_SIZE - 1 && chunkx +1 < 1024 && chunks.find(a2, Chunk::calculateIndex(chunkx +1, chunky, chunkz)))
|
||||
send_to_chunk_meshing_thread(a2->second, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
if(blocky == CHUNK_SIZE - 1 && chunky +1 < 1024 && chunks.find(b2, Chunk::calculateIndex(chunkx, chunky +1, chunkz)))
|
||||
send_to_chunk_meshing_thread(b2->second, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
if(blockz == CHUNK_SIZE - 1 && chunkz +1 < 1024 && chunks.find(c2, Chunk::calculateIndex(chunkx, chunky, chunkz +1)))
|
||||
send_to_chunk_meshing_thread(c2->second, MESHING_PRIORITY_PLAYER_EDIT);
|
||||
|
||||
// Update debugging information
|
||||
|
||||
debug::window::set_parameter("block_last_action", msg.msg_type ==
|
||||
WorldUpdateMsgType::BLOCKPICK_PLACE);
|
||||
debug::window::set_parameter("block_last_action_block_type", (int)(msg.msg_type ==
|
||||
WorldUpdateMsgType::BLOCKPICK_PLACE ? msg.block : Block::AIR));
|
||||
debug::window::set_parameter("block_last_action_x", chunkx*CHUNK_SIZE+blockx);
|
||||
debug::window::set_parameter("block_last_action_y", chunky*CHUNK_SIZE+blocky);
|
||||
debug::window::set_parameter("block_last_action_z", chunkz*CHUNK_SIZE+blockz);
|
||||
}
|
||||
|
||||
Block getBlockAtPos(int x, int y, int z){
|
||||
|
|
|
@ -69,9 +69,6 @@ namespace debug{
|
|||
ImGui::Text("FPS: %d", std::any_cast<int>(parameters.at("fps")));
|
||||
ImGui::Text("Frametime (ms): %f",
|
||||
std::any_cast<float>(parameters.at("frametime"))*1000);
|
||||
ImGui::Text("GPU: (%s) %s",
|
||||
std::any_cast<const GLubyte*>(parameters.at("gpu_vendor")),
|
||||
std::any_cast<const GLubyte*>(parameters.at("gpu_renderer")));
|
||||
//ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr);
|
||||
}
|
||||
|
||||
|
@ -115,14 +112,10 @@ namespace debug{
|
|||
if(ImGui::CollapsingHeader("Chunks")){
|
||||
ImGui::Text("Total chunks present: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_total")));
|
||||
ImGui::Text("Chunks generated: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_generated")));
|
||||
ImGui::Text("Chunks meshed: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_meshed")));
|
||||
ImGui::Text("Chunks actually freed from memory: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_freed")));
|
||||
ImGui::Text("Chunks explored: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_explored")));
|
||||
/*ImGui::Text("Chunks freed from memory: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_delete")));*/
|
||||
ImGui::Text("Bucket size: %d",
|
||||
std::any_cast<int>(parameters.at("update_chunks_bucket")));
|
||||
}
|
||||
}catch(const std::bad_any_cast& e){
|
||||
std::cout << e.what() << std::endl;
|
||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -1,8 +1,13 @@
|
|||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "main.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "main.hpp"
|
||||
|
||||
#define GLOBALS_DEFINER
|
||||
#include "globals.hpp"
|
||||
#undef GLOBALS_DEFINER
|
||||
|
@ -55,9 +60,9 @@ int main()
|
|||
//glEnable(GL_FRAMEBUFFER_SRGB); //gamma correction done in fragment shader
|
||||
//glEnable(GL_CULL_FACE); //GL_BACK GL_CCW by default
|
||||
|
||||
debug::window::set_parameter("gpu_vendor", glGetString(GL_VENDOR));
|
||||
debug::window::set_parameter("gpu_renderer", glGetString(GL_RENDERER));
|
||||
std::cout << "Using GPU: " << glGetString(GL_VENDOR) << " " << glGetString(GL_RENDERER) << "\n";
|
||||
|
||||
wireframe = false;
|
||||
for(int i = 0; i < 360; i++){
|
||||
sines[i] = sin(3.14 / 180 * i);
|
||||
cosines[i] = cos(3.14 / 180 * i);
|
||||
|
@ -125,6 +130,7 @@ int main()
|
|||
// Cleanup allocated memory
|
||||
chunkmanager::destroy();
|
||||
renderer::destroy();
|
||||
debug::window::destroy();
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue