general code cleanup
parent
19cd81b9fb
commit
8584d2e974
|
@ -8,8 +8,6 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include "chunk.hpp"
|
||||
|
||||
class Camera
|
||||
{
|
||||
|
||||
|
@ -17,13 +15,15 @@ public:
|
|||
Camera()
|
||||
{
|
||||
view = glm::mat4(1.0f);
|
||||
// note that we're translating the scene in the reverse direction of where we want to move
|
||||
|
||||
// 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, 200.0f);
|
||||
}
|
||||
|
||||
void update(GLFWwindow *window, float deltaTime)
|
||||
{
|
||||
const float cameraSpeed = 10.0f * deltaTime; // adjust accordingly
|
||||
const float cameraSpeed = 25.0f * deltaTime; // adjust accordingly
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
this->cameraPos += cameraSpeed * cameraFront;
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
|
@ -72,34 +72,16 @@ public:
|
|||
pitch = -89.0f;
|
||||
}
|
||||
|
||||
glm::vec3 getPos()
|
||||
{
|
||||
return cameraPos;
|
||||
}
|
||||
|
||||
glm::vec3 getFront()
|
||||
{
|
||||
return cameraFront;
|
||||
}
|
||||
|
||||
glm::vec3 getUp()
|
||||
{
|
||||
return cameraUp;
|
||||
}
|
||||
|
||||
glm::mat4 getView()
|
||||
{
|
||||
return view;
|
||||
}
|
||||
|
||||
glm::mat4 getProjection()
|
||||
{
|
||||
return projection;
|
||||
}
|
||||
glm::vec3 getPos() { return cameraPos; }
|
||||
glm::vec3 getFront() { return cameraFront; }
|
||||
glm::vec3 getUp() { return cameraUp; }
|
||||
glm::mat4 getView() { return view; }
|
||||
glm::mat4 getProjection() { return projection; }
|
||||
|
||||
// Plane extraction as per Gribb&Hartmann
|
||||
// 6 planes, each with 4 components (a,b,c,d)
|
||||
void getFrustumPlanes(glm::vec4 planes[6], bool normalize){
|
||||
void getFrustumPlanes(glm::vec4 planes[6], bool normalize)
|
||||
{
|
||||
glm::mat4 mat = transpose(projection*view);
|
||||
|
||||
// This just compressed the code below
|
||||
|
@ -122,9 +104,8 @@ public:
|
|||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
glm::vec3 cameraPos = glm::vec3(static_cast<float>(CHUNK_SIZE)*24, 40.0f, static_cast<float>(CHUNK_SIZE)*24);
|
||||
glm::vec3 cameraPos = glm::vec3(0.0, 80.0f, 0.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);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "intervalmap.hpp"
|
||||
#include "shader.hpp"
|
||||
|
||||
#define CHUNK_SIZE 8
|
||||
#define CHUNK_SIZE 16
|
||||
#define CHUNK_VOLUME (CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE)
|
||||
#define CHUNK_MAX_INDEX (CHUNK_VOLUME - 1)
|
||||
|
||||
|
|
|
@ -13,17 +13,15 @@ namespace chunkmanager
|
|||
void stopGenThread();
|
||||
void stopMeshThread();
|
||||
|
||||
void update(float deltaTime);
|
||||
|
||||
void updateChunk(uint32_t, uint16_t, uint16_t, uint16_t);
|
||||
void destroy();
|
||||
void mesh();
|
||||
void generate();
|
||||
|
||||
void blockpick(bool place);
|
||||
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k);
|
||||
|
||||
void mesh();
|
||||
void generate();
|
||||
|
||||
void destroy();
|
||||
void update(float deltaTime);
|
||||
void updateChunk(uint32_t, uint16_t, uint16_t, uint16_t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "chunk.hpp"
|
||||
#include "globals.hpp"
|
||||
#include "shader.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace chunkmesher{
|
||||
void mesh(Chunk::Chunk* chunk);
|
||||
|
@ -17,7 +17,6 @@ void sendtogpu(Chunk::Chunk* chunk);
|
|||
void draw(Chunk::Chunk* chunk, glm::mat4 model);
|
||||
|
||||
void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, glm::vec3 bottomRight, Block block, bool backFace);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define extr extern
|
||||
#endif
|
||||
|
||||
#define RENDER_DISTANCE 8
|
||||
#define RENDER_DISTANCE 16
|
||||
|
||||
extr Camera theCamera;
|
||||
extr Shader* theShader;
|
||||
|
|
|
@ -20,10 +20,7 @@ public:
|
|||
if (start >= end)
|
||||
return;
|
||||
|
||||
// higherEntry -> upper_bound
|
||||
// lowerEntry -> find()--
|
||||
// c++ has no builtin function to find the greater key LESS THAN the supplied key. The solution I've found is to get an iterator to the key with find() and traverse back with std::prev
|
||||
|
||||
const auto &tmp = treemap.lower_bound(end);
|
||||
const auto &end_prev_entry = tmp != treemap.begin() && tmp != treemap.end() ? std::prev(tmp) : tmp; // first element before end
|
||||
const auto &end_next_entry = tmp; // first element after end
|
||||
|
@ -40,7 +37,11 @@ public:
|
|||
{
|
||||
if(end_next_entry->first != end)
|
||||
treemap[end] = end_prev_entry->second;
|
||||
|
||||
// A little optimization: delete next key if it is of the same value of the end key
|
||||
if(end_next_entry->second == treemap[end]) treemap.erase(end_next_entry);
|
||||
}
|
||||
|
||||
// insert the start key. Replaces whatever value is already there. Do not place if the element before is of the same value
|
||||
treemap[start] = value;
|
||||
treemap.erase(treemap.upper_bound(start), treemap.lower_bound(end));
|
||||
|
@ -70,23 +71,18 @@ public:
|
|||
{
|
||||
if (treemap.empty())
|
||||
{
|
||||
// std::cout << "List is empty" << std::endl;
|
||||
*length = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto &end = std::prev(treemap.end());
|
||||
|
||||
*length = end->first;
|
||||
if(*length == 0) return nullptr;
|
||||
|
||||
// std::cout << "Length: " << *length << "\n";
|
||||
std::unique_ptr<V[]> arr(new V[*length]);
|
||||
|
||||
auto start = treemap.begin();
|
||||
for (auto i = std::next(treemap.begin()); i != treemap.end(); i++)
|
||||
{
|
||||
// std::cout << "creating list from " << start->first << " to " << i->first << " of type " << (int)(start->second) << "\n";
|
||||
for (int k = start->first; k < i->first; k++)
|
||||
arr[k] = start->second;
|
||||
start = i;
|
||||
|
|
|
@ -5,5 +5,4 @@ void framebuffer_size_callback(GLFWwindow *, int, int);
|
|||
void mouse_callback(GLFWwindow *window, double xpos, double ypos);
|
||||
void processInput(GLFWwindow *);
|
||||
|
||||
|
||||
#endif
|
|
@ -7,18 +7,11 @@
|
|||
namespace SpaceFilling
|
||||
{
|
||||
uint32_t MortonToHilbert3D(const uint32_t morton, const uint32_t bits);
|
||||
|
||||
uint32_t HilbertToMorton3D(const uint32_t hilbert, const uint32_t bits);
|
||||
|
||||
uint32_t Morton_3D_Encode_5bit(uint32_t index1, uint32_t index2, uint32_t index3);
|
||||
|
||||
void Morton_3D_Decode_5bit(const uint32_t morton,
|
||||
uint32_t &index1, uint32_t &index2, uint32_t &index3);
|
||||
|
||||
void Morton_3D_Decode_5bit(const uint32_t morton, uint32_t &index1, uint32_t &index2, uint32_t &index3);
|
||||
uint32_t Morton_3D_Encode_10bit(uint32_t index1, uint32_t index2, uint32_t index3);
|
||||
|
||||
void Morton_3D_Decode_10bit(const uint32_t morton,
|
||||
uint32_t &index1, uint32_t &index2, uint32_t &index3);
|
||||
void Morton_3D_Decode_10bit(const uint32_t morton, uint32_t &index1, uint32_t &index2, uint32_t &index3);
|
||||
|
||||
void initLUT();
|
||||
};
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
namespace utils
|
||||
{
|
||||
bool withinDistance(int startx, int starty, int startz, int x, int y, int z, int dist);
|
||||
// https://stackoverflow.com/questions/20266201/3d-array-1d-flat-indexing
|
||||
// flatten 3d coords to 1d array cords
|
||||
int coord3DTo1D(int x, int y, int z, int maxX, int maxY, int maxZ);
|
||||
std::array<int, 3> coord1DTo3D(int idx, int maxX, int maxY, int mazZ);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Chunk
|
|||
{
|
||||
this->position = pos;
|
||||
this->setState(CHUNK_STATE_EMPTY, true);
|
||||
// std::cout << "CHUNK" << std::endl;
|
||||
|
||||
glGenVertexArrays(1, &(this->VAO));
|
||||
glGenBuffers(1, &(this->colorBuffer));
|
||||
glGenBuffers(1, &(this->VBO));
|
||||
|
|
|
@ -33,6 +33,7 @@ OpenSimplexNoise::Noise noiseGen2(12345);
|
|||
|
||||
std::array<int, CHUNK_SIZE * CHUNK_SIZE> grassNoiseLUT;
|
||||
std::array<int, CHUNK_SIZE * CHUNK_SIZE> dirtNoiseLUT;
|
||||
|
||||
void generateNoise(Chunk::Chunk *chunk)
|
||||
{
|
||||
for (int i = 0; i < grassNoiseLUT.size(); i++)
|
||||
|
@ -88,6 +89,5 @@ void generatePyramid(Chunk::Chunk *chunk)
|
|||
for (int i = 0; i < CHUNK_SIZE; i++)
|
||||
for (int j = 0; j < CHUNK_SIZE; j++)
|
||||
for (int k = 0; k < CHUNK_SIZE; k++)
|
||||
// blocks[utils::coord3DTo1D(i, j, k, CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE)] = j == 0 ? Block::STONE : Block::AIR;
|
||||
chunk->setBlock(i >= j && i < CHUNK_SIZE - j && k >= j && k < CHUNK_SIZE - j ? (j & 1) == 0 ? Block::GRASS : Block::STONE : Block::AIR, i, j, k);
|
||||
}
|
||||
|
|
|
@ -20,16 +20,25 @@ std::unordered_map<std::uint32_t, Chunk::Chunk *> chunks;
|
|||
|
||||
namespace chunkmanager
|
||||
{
|
||||
// thread management
|
||||
std::mutex mutex_queue_generate;
|
||||
std::set<Chunk::Chunk *> to_generate;
|
||||
std::set<Chunk::Chunk *> to_generate_shared;
|
||||
|
||||
std::mutex mutex_queue_mesh;
|
||||
std::set<Chunk::Chunk *> to_generate;
|
||||
std::set<Chunk::Chunk *> to_mesh;
|
||||
std::set<Chunk::Chunk *> to_mesh_shared;
|
||||
|
||||
std::atomic_bool mesh_should_run;
|
||||
std::atomic_bool generate_should_run;
|
||||
std::atomic_bool mesh_should_run;
|
||||
|
||||
// update variables
|
||||
uint8_t f = 0;
|
||||
int rr{RENDER_DISTANCE * RENDER_DISTANCE};
|
||||
glm::vec4 frustumPlanes[6];
|
||||
glm::vec3 cameraPos;
|
||||
int chunkX, chunkY, chunkZ;
|
||||
int total{0}, toGpu{0};
|
||||
|
||||
// disposal
|
||||
std::unordered_map<uint32_t, float> to_delete;
|
||||
std::set<uint32_t> to_delete_delete;
|
||||
|
||||
void mesh()
|
||||
{
|
||||
|
@ -75,6 +84,7 @@ namespace chunkmanager
|
|||
std::thread mesh_thread(mesh);
|
||||
return mesh_thread;
|
||||
}
|
||||
|
||||
std::thread initGenThread()
|
||||
{
|
||||
generate_should_run = true;
|
||||
|
@ -90,31 +100,25 @@ namespace chunkmanager
|
|||
mesh_should_run = false;
|
||||
}
|
||||
|
||||
int total{0}, toGpu{0};
|
||||
int rr{RENDER_DISTANCE * RENDER_DISTANCE};
|
||||
uint8_t f = 0;
|
||||
glm::vec4 frustumPlanes[6];
|
||||
std::unordered_map<uint32_t, std::time_t> to_delete;
|
||||
std::set<uint32_t> to_delete_delete;
|
||||
|
||||
glm::vec3 cameraPos = theCamera.getPos();
|
||||
int chunkX, chunkY, chunkZ;
|
||||
void update(float deltaTime)
|
||||
{
|
||||
int nUnloaded{0};
|
||||
|
||||
// Try to lock resources
|
||||
f = 0;
|
||||
f |= mutex_queue_generate.try_lock();
|
||||
f |= mutex_queue_mesh.try_lock() << 1;
|
||||
|
||||
// Iterate over all chunks, in concentric spheres starting fron the player and going outwards
|
||||
// Eq. of the sphere (x - a)² + (y - b)² + (z - c)² = r²
|
||||
cameraPos = theCamera.getPos();
|
||||
theCamera.getFrustumPlanes(frustumPlanes, true);
|
||||
chunkX=(static_cast<int>(cameraPos.x)) / CHUNK_SIZE; chunkY=(static_cast<int>(cameraPos.y)) / CHUNK_SIZE; chunkZ=(static_cast<int>(cameraPos.z)) / CHUNK_SIZE;
|
||||
chunkX=static_cast<int>(cameraPos.x) / CHUNK_SIZE;
|
||||
chunkY=static_cast<int>(cameraPos.y) / CHUNK_SIZE;
|
||||
chunkZ=static_cast<int>(cameraPos.z) / CHUNK_SIZE;
|
||||
|
||||
// Use time in float to be consistent with glfw
|
||||
float currentTime = glfwGetTime();
|
||||
|
||||
std::time_t currentTime = std::time(nullptr);
|
||||
// Check for far chunks that need to be cleaned up from memory
|
||||
int nUnloaded{0};
|
||||
for(const auto& n : chunks){
|
||||
Chunk::Chunk* c = n.second;
|
||||
int x{(int)(c->getPosition().x)};
|
||||
|
@ -130,6 +134,8 @@ namespace chunkmanager
|
|||
delete chunks.at(n.first);
|
||||
chunks.erase(n.first);
|
||||
nUnloaded++;
|
||||
|
||||
// Delete afterwards to avoid exception due to invalid iterators
|
||||
to_delete_delete.insert(n.first);
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +143,9 @@ namespace chunkmanager
|
|||
to_delete_delete.clear();
|
||||
if(nUnloaded) std::cout << "Unloaded " << nUnloaded << " chunks\n";
|
||||
|
||||
// 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²
|
||||
|
||||
// Possible change: coordinates everything at the origin, then translate later?
|
||||
// Step 1. Eq. of a circle. Fix the x coordinate, get the 2 possible y's
|
||||
|
@ -144,16 +153,9 @@ namespace chunkmanager
|
|||
bool b = true;
|
||||
while (xp <= RENDER_DISTANCE)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
x = chunkX + xp;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = chunkX - xp;
|
||||
}
|
||||
// for (int x = chunkX - RENDER_DISTANCE; x < chunkX + RENDER_DISTANCE; x++)
|
||||
// {
|
||||
// Alternate between left and right
|
||||
if (b) x = chunkX + xp;
|
||||
else x = chunkX - xp;
|
||||
|
||||
// Possible optimization: use sqrt lookup
|
||||
int y1 = sqrt((rr) - (x - chunkX) * (x - chunkX)) + chunkY;
|
||||
|
@ -192,7 +194,6 @@ namespace chunkmanager
|
|||
else
|
||||
k = z;
|
||||
|
||||
// uint32_t is fine, since i'm limiting the coordinate to only use up to ten bits (1024). There's actually two spare bits
|
||||
uint32_t in = calculateIndex(i, j, k);
|
||||
chunkmanager::updateChunk(in, i, j, k);
|
||||
}
|
||||
|
@ -203,10 +204,7 @@ namespace chunkmanager
|
|||
xp++;
|
||||
b = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = false;
|
||||
}
|
||||
else b = false;
|
||||
}
|
||||
//std::cout << "Chunks to mesh: " << to_mesh.size() << "\n";
|
||||
//std::cout << "Chunks to generate: " << to_generate.size() << "\n";
|
||||
|
@ -214,6 +212,8 @@ namespace chunkmanager
|
|||
//total = 0;
|
||||
//toGpu = 0;
|
||||
|
||||
// Unlock mutexes if previously locked. Unlocking a mutex not locked by the current thread
|
||||
// or already locked is undefined behaviour, so checking has to be done
|
||||
if ((f & 1))
|
||||
mutex_queue_generate.unlock();
|
||||
if ((f & 2))
|
||||
|
@ -221,8 +221,10 @@ namespace chunkmanager
|
|||
}
|
||||
|
||||
// Generation and meshing happen in two separate threads from the main one
|
||||
// Chunk states are used to decide which actions need to be done on the chunk and queues+mutexes to pass the chunks between the threads
|
||||
// Uploading data to GPU still needs to be done in the main thread, or another OpenGL context needs to be opened, which further complicates stuff
|
||||
// Chunk states are used to decide which actions need to be done on the chunk and sets+mutexes
|
||||
// to pass the chunks to be operated on between the threads.
|
||||
// Uploading data to GPU still needs to be done in the main thread, or another OpenGL context
|
||||
// needs to be opened, which further complicates stuff.
|
||||
void updateChunk(uint32_t index, uint16_t i, uint16_t j, uint16_t k)
|
||||
{
|
||||
if (chunks.find(index) == chunks.end())
|
||||
|
@ -252,6 +254,7 @@ namespace chunkmanager
|
|||
else
|
||||
{
|
||||
if (!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) chunkmesher::sendtogpu(c);
|
||||
|
||||
// Frustum Culling of chunk
|
||||
total++;
|
||||
|
||||
|
@ -259,18 +262,15 @@ namespace chunkmanager
|
|||
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;
|
||||
// First test, check if all the corners of the chunk are outside any of the
|
||||
// planes
|
||||
for(int p = 0; p < 6; p++){
|
||||
|
||||
int 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;
|
||||
}
|
||||
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;
|
||||
|
@ -292,7 +292,7 @@ namespace chunkmanager
|
|||
void blockpick(bool place){
|
||||
// cast a ray from the camera in the direction pointed by the camera itself
|
||||
glm::vec3 pos = cameraPos;
|
||||
for(float t = 0.0; t <= 25.0; t += 0.5){
|
||||
for(float t = 0.0; t <= 10.0; t += 0.5){
|
||||
// traverse the ray a block at the time
|
||||
pos = theCamera.getPos() + t * theCamera.getFront();
|
||||
|
||||
|
@ -356,6 +356,7 @@ namespace chunkmanager
|
|||
}
|
||||
}
|
||||
|
||||
// uint32_t is fine, since i'm limiting the coordinate to only use up to ten bits (1024). There's actually two spare bits
|
||||
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k){
|
||||
return i | (j << 10) | (k << 20);
|
||||
}
|
||||
|
|
|
@ -27,18 +27,14 @@ void mesh(Chunk::Chunk* chunk)
|
|||
* across different planes everytime I change dimension without having to
|
||||
* write 3 separate 3-nested-for-loops
|
||||
*/
|
||||
/*
|
||||
* It's not feasible to just create a new mesh everytime a quad needs placing.
|
||||
* This ends up creating TONS of meshes and the game will just lag out.
|
||||
* As I did in the past, it's better to create a single mesh for each chunk,
|
||||
* containing all the quads. In the future, maybe translucent blocks and liquids
|
||||
* will need a separate mesh, but still on a per-chunk basis
|
||||
*/
|
||||
|
||||
// Cleanup previous data
|
||||
chunk->vertices.clear();
|
||||
chunk->indices.clear();
|
||||
chunk->colors.clear();
|
||||
chunk->vIndex = 0;
|
||||
|
||||
// Abort if chunk is empty
|
||||
if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)) return;
|
||||
|
||||
// convert tree to array since it is easier to work with it
|
||||
|
@ -95,7 +91,8 @@ void mesh(Chunk::Chunk* chunk)
|
|||
|
||||
// Additionally checking whether b1 and b2 are AIR or Block::NULLBLK allows face culling,
|
||||
// thus not rendering faces that cannot be seen
|
||||
// Removing the control for Block::NULLBLK disables chunk borders
|
||||
// Removing the control for Block::NULLBLK disables chunk borders, which is
|
||||
// not always wanted and needs further checking
|
||||
// This can be surely refactored in something that isn't such a big one-liner
|
||||
mask[n++] = b1 != Block::NULLBLK && b2 != Block::NULLBLK && b1 == b2 ? Block::NULLBLK
|
||||
: backFace ? b1 == Block::AIR || b1 == Block::NULLBLK ? b2 : Block::NULLBLK
|
||||
|
@ -209,12 +206,16 @@ void sendtogpu(Chunk::Chunk* chunk)
|
|||
|
||||
glBindVertexArray(0);
|
||||
|
||||
// save the number of indices of the mesh, it is needed later for drawing
|
||||
chunk->vIndex = (GLuint)(chunk->indices.size());
|
||||
|
||||
// once data has been sent to the GPU, it can be cleared from system RAM
|
||||
chunk->vertices.clear();
|
||||
chunk->indices.clear();
|
||||
chunk->colors.clear();
|
||||
}
|
||||
|
||||
// mark the chunk mesh has loaded on GPU
|
||||
chunk->setState(Chunk::CHUNK_STATE_MESH_LOADED, true);
|
||||
}
|
||||
|
||||
|
@ -274,7 +275,7 @@ void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec
|
|||
}
|
||||
chunk->vIndex += 4;
|
||||
|
||||
// ugly switch case
|
||||
// ugly switch case for colors
|
||||
GLfloat r, g, b;
|
||||
switch (block)
|
||||
{
|
||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -79,8 +79,6 @@ int main()
|
|||
lastFPSFrame = currentFrame;
|
||||
}
|
||||
|
||||
if(glfwGetTime() - lastBlockPick > 0.2) blockpick = false;
|
||||
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
@ -90,6 +88,9 @@ int main()
|
|||
// Camera
|
||||
theCamera.update(window, deltaTime);
|
||||
|
||||
// Reset blockping timeout if 200ms have passed
|
||||
if(glfwGetTime() - lastBlockPick > 0.1) blockpick = false;
|
||||
|
||||
// ChunkManager
|
||||
chunkmanager::update(deltaTime);
|
||||
|
||||
|
@ -98,14 +99,14 @@ int main()
|
|||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// Stop threads and wait for them to finish
|
||||
chunkmanager::stopGenThread();
|
||||
chunkmanager::stopMeshThread();
|
||||
|
||||
genThread.join();
|
||||
meshThread.join();
|
||||
|
||||
// Cleanup allocated memory
|
||||
chunkmanager::destroy();
|
||||
|
||||
delete theShader;
|
||||
|
||||
|
||||
|
@ -128,16 +129,20 @@ 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;
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
// http://and-what-happened.blogspot.com/2011/08/fast-2d-and-3d-hilbert-curves-and.html
|
||||
namespace SpaceFilling
|
||||
{
|
||||
uint32_t MortonToHilbert3D(const uint32_t morton, const uint32_t bits)
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#include "utils.hpp"
|
||||
|
||||
bool utils::withinDistance(int startx, int starty, int startz, int x, int y, int z, int dist){
|
||||
bool utils::withinDistance(int startx, int starty, int startz, int x, int y, int z, int dist)
|
||||
{
|
||||
return (x-startx)*(x-startx) + (y - starty)*(y-starty) + (z-startz)*(z-startz) <= dist*dist;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/20266201/3d-array-1d-flat-indexing
|
||||
//flatten 3d coords to 1d array cords
|
||||
int utils::coord3DTo1D (int x, int y, int z, int maxX, int maxY, int maxZ){
|
||||
return x + maxX * (y + z * maxY);
|
||||
}
|
||||
// https://stackoverflow.com/questions/20266201/3d-array-1d-flat-indexing
|
||||
int utils::coord3DTo1D (int x, int y, int z, int maxX, int maxY, int maxZ) { return x + maxX * (y + z * maxY); }
|
||||
|
||||
std::array<int, 3> utils::coord1DTo3D(int idx, int maxX, int maxY, int mazZ){
|
||||
std::array<int, 3> utils::coord1DTo3D(int idx, int maxX, int maxY, int mazZ)
|
||||
{
|
||||
int z = idx / (maxX * maxY);
|
||||
idx -= (z * maxX* maxY);
|
||||
int y = idx / maxX;
|
||||
|
|
Loading…
Reference in New Issue