initial blockpicking

vertex-deduplication
EmaMaker 2023-03-20 22:57:29 +01:00
parent e18a2cca05
commit e609f4858b
5 changed files with 104 additions and 10 deletions

View File

@ -18,6 +18,9 @@ namespace chunkmanager
void updateChunk(uint32_t, uint16_t, uint16_t, uint16_t); void updateChunk(uint32_t, uint16_t, uint16_t, uint16_t);
void destroy(); void destroy();
void blockpick(bool place);
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k);
void mesh(); void mesh();
void generate(); void generate();

View File

@ -6,6 +6,7 @@
#include "intervalmap.hpp" #include "intervalmap.hpp"
#include "globals.hpp" #include "globals.hpp"
#include <memory>
namespace Chunk namespace Chunk
{ {
@ -17,13 +18,12 @@ namespace Chunk
Chunk::Chunk(glm::vec3 pos) Chunk::Chunk(glm::vec3 pos)
{ {
this->position = pos; this->position = pos;
this->blocks.insert(0, CHUNK_VOLUME, Block::AIR);
this->setState(CHUNK_STATE_EMPTY, true); this->setState(CHUNK_STATE_EMPTY, true);
// std::cout << "CHUNK" << std::endl; // std::cout << "CHUNK" << std::endl;
glGenVertexArrays(1, &(this->VAO)); glGenVertexArrays(1, &(this->VAO));
glGenBuffers(1, &(this->colorBuffer)); glGenBuffers(1, &(this->colorBuffer));
glGenBuffers(1, &(this->VBO)); glGenBuffers(1, &(this->VBO));
glGenBuffers(1, &(this->EBO)); glGenBuffers(1, &(this->EBO));
} }
@ -49,7 +49,7 @@ namespace Chunk
void Chunk::setBlock(Block b, int x, int y, int z) void Chunk::setBlock(Block b, int x, int y, int z)
{ {
int coord = HILBERT_XYZ_ENCODE[x][y][z]; int coord = HILBERT_XYZ_ENCODE[x][y][z];
blocks.insert(coord <= 0 ? 0 : coord, coord+1 >= CHUNK_VOLUME ? CHUNK_VOLUME : coord+1, b); this->setBlocks(coord, coord+1, b);
} }
void Chunk::setBlocks(int start, int end, Block b){ void Chunk::setBlocks(int start, int end, Block b){

View File

@ -90,4 +90,4 @@ void generatePyramid(Chunk::Chunk *chunk)
for (int k = 0; k < CHUNK_SIZE; k++) 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; // 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); 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);
} }

View File

@ -97,6 +97,8 @@ namespace chunkmanager
std::unordered_map<uint32_t, std::time_t> to_delete; std::unordered_map<uint32_t, std::time_t> to_delete;
std::set<uint32_t> to_delete_delete; std::set<uint32_t> to_delete_delete;
glm::vec3 cameraPos = theCamera.getPos();
int chunkX, chunkY, chunkZ;
void update(float deltaTime) void update(float deltaTime)
{ {
int nUnloaded{0}; int nUnloaded{0};
@ -107,9 +109,9 @@ namespace chunkmanager
// Iterate over all chunks, in concentric spheres starting fron the player and going outwards // 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² // Eq. of the sphere (x - a)² + (y - b)² + (z - c)² = r²
glm::vec3 cameraPos = theCamera.getPos(); cameraPos = theCamera.getPos();
theCamera.getFrustumPlanes(frustumPlanes, true); theCamera.getFrustumPlanes(frustumPlanes, true);
int 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;
std::time_t currentTime = std::time(nullptr); std::time_t currentTime = std::time(nullptr);
// Check for far chunks that need to be cleaned up from memory // Check for far chunks that need to be cleaned up from memory
@ -190,7 +192,8 @@ namespace chunkmanager
else else
k = z; k = z;
uint32_t in = i | (j << 10) | (k << 20); // 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 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); chunkmanager::updateChunk(in, i, j, k);
} }
} }
@ -321,6 +324,77 @@ 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){
// traverse the ray a block at the time
pos = theCamera.getPos() + t * theCamera.getFront();
// get which chunk and block the ray is at
int px = ((int)(pos.x))/CHUNK_SIZE;
int py = ((int)(pos.y))/CHUNK_SIZE;
int pz = ((int)(pos.z))/CHUNK_SIZE;
int bx = pos.x - px*CHUNK_SIZE;
int by = pos.y - py*CHUNK_SIZE;
int bz = pos.z - pz*CHUNK_SIZE;
// exit early if the position is invalid or the chunk does not exist
if(px < 0 || py < 0 || pz < 0) return;
if(chunks.find(calculateIndex(px, py, pz)) == chunks.end()) return;
Chunk::Chunk* c = chunks.at(calculateIndex(px, py, pz));
Block b = c->getBlock(bx, by, bz);
// if the block is non empty
if(b != Block::AIR){
// if placing a new block
if(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;
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;
// exit early if the position is invalid or the chunk does not exist
if(px1 < 0 || py1 < 0 || pz1 < 0) return;
if(chunks.find(calculateIndex(px1, py1, pz1)) == chunks.end()) return;
Chunk::Chunk* c1 = chunks.at(calculateIndex(px1, py1, pz1));
// place the new block (only stone for now)
c1->setBlock( Block::STONE, bx1, by1, bz1);
// update the mesh of the chunk
chunkmesher::mesh(c1);
// mark the mesh of the chunk the be updated on the gpu
c1->setState(Chunk::CHUNK_STATE_MESH_LOADED, false);
}else{
// replace the current block with air to remove it
c->setBlock( Block::AIR, bx, by, bz);
// update the mesh of the chunk
chunkmesher::mesh(c);
// mark the mesh of the chunk the be updated on the gpu
c->setState(Chunk::CHUNK_STATE_MESH_LOADED, false);
}
break;
}
}
}
uint32_t calculateIndex(uint16_t i, uint16_t j, uint16_t k){
return i | (j << 10) | (k << 20);
}
void destroy() void destroy()
{ {
for (auto &n : chunks) for (auto &n : chunks)

View File

@ -17,6 +17,9 @@ 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;
int main() int main()
{ {
@ -76,6 +79,8 @@ int main()
lastFPSFrame = currentFrame; lastFPSFrame = currentFrame;
} }
if(glfwGetTime() - lastBlockPick > 0.2) blockpick = false;
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -123,4 +128,16 @@ void processInput(GLFWwindow *window)
{ {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true); 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();
}
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_RELEASE && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_RELEASE) blockpick = false;
} }