chunkmesher: keep a table of vertices to avoid duplicates
parent
b4f3bdad06
commit
80d3297213
|
@ -1,6 +1,8 @@
|
||||||
#ifndef CHUNK_H
|
#ifndef CHUNK_H
|
||||||
#define CHUNK_H
|
#define CHUNK_H
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/gtx/hash.hpp>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
@ -8,6 +10,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "block.hpp"
|
#include "block.hpp"
|
||||||
|
@ -15,7 +18,7 @@
|
||||||
#include "intervalmap.hpp"
|
#include "intervalmap.hpp"
|
||||||
#include "shader.hpp"
|
#include "shader.hpp"
|
||||||
|
|
||||||
#define CHUNK_SIZE 16
|
#define CHUNK_SIZE 32
|
||||||
#define CHUNK_VOLUME (CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE)
|
#define CHUNK_VOLUME (CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE)
|
||||||
#define CHUNK_MAX_INDEX (CHUNK_VOLUME - 1)
|
#define CHUNK_MAX_INDEX (CHUNK_VOLUME - 1)
|
||||||
|
|
||||||
|
@ -50,7 +53,7 @@ namespace Chunk
|
||||||
std::unique_ptr<Block[]> getBlocksArray(int* len) { return (this->blocks.toArray(len)); }
|
std::unique_ptr<Block[]> getBlocksArray(int* len) { return (this->blocks.toArray(len)); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, vIndex{0};
|
GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, nIndices{0};
|
||||||
|
|
||||||
std::mutex mutex_state;
|
std::mutex mutex_state;
|
||||||
|
|
||||||
|
@ -58,6 +61,10 @@ namespace Chunk
|
||||||
std::vector<GLfloat> colors;
|
std::vector<GLfloat> colors;
|
||||||
std::vector<GLuint> indices;
|
std::vector<GLuint> indices;
|
||||||
|
|
||||||
|
std::unordered_map<glm::vec3, std::tuple<GLuint, glm::vec3, glm::vec3> > vertices_map; // index,
|
||||||
|
// normal,
|
||||||
|
std::vector<glm::vec3> index_to_vertex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 position{};
|
glm::vec3 position{};
|
||||||
IntervalMap<Block> blocks{};
|
IntervalMap<Block> blocks{};
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,18 @@ namespace Chunk
|
||||||
|
|
||||||
Chunk ::~Chunk()
|
Chunk ::~Chunk()
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &(this->colorBuffer));
|
vertices_map.clear();
|
||||||
glDeleteBuffers(1, &(this->VBO));
|
index_to_vertex.clear();
|
||||||
glDeleteBuffers(1, &(this->EBO));
|
|
||||||
glDeleteVertexArrays(1, &(this->VAO));
|
|
||||||
|
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
indices.clear();
|
indices.clear();
|
||||||
colors.clear();
|
colors.clear();
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &(this->colorBuffer));
|
||||||
|
glDeleteBuffers(1, &(this->VBO));
|
||||||
|
glDeleteBuffers(1, &(this->EBO));
|
||||||
|
glDeleteVertexArrays(1, &(this->VAO));
|
||||||
|
|
||||||
mutex_state.unlock();
|
mutex_state.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ void generateNoise3D(Chunk::Chunk *chunk);
|
||||||
|
|
||||||
void generateChunk(Chunk::Chunk *chunk)
|
void generateChunk(Chunk::Chunk *chunk)
|
||||||
{
|
{
|
||||||
generateNoise3D(chunk);
|
generateNoise(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block block;
|
Block block;
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
#include <array>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "block.hpp"
|
#include "block.hpp"
|
||||||
#include "chunk.hpp"
|
#include "chunk.hpp"
|
||||||
#include "chunkmesher.hpp"
|
#include "chunkmesher.hpp"
|
||||||
|
@ -8,8 +5,15 @@
|
||||||
#include "spacefilling.hpp"
|
#include "spacefilling.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
|
||||||
namespace chunkmesher{
|
namespace chunkmesher{
|
||||||
|
|
||||||
|
int indexCount{0};
|
||||||
|
|
||||||
void mesh(Chunk::Chunk* chunk)
|
void mesh(Chunk::Chunk* chunk)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -29,10 +33,13 @@ void mesh(Chunk::Chunk* chunk)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Cleanup previous data
|
// Cleanup previous data
|
||||||
|
chunk->vertices_map.clear();
|
||||||
|
chunk->index_to_vertex.clear();
|
||||||
|
indexCount = 0;
|
||||||
chunk->vertices.clear();
|
chunk->vertices.clear();
|
||||||
chunk->indices.clear();
|
chunk->indices.clear();
|
||||||
chunk->colors.clear();
|
chunk->colors.clear();
|
||||||
chunk->vIndex = 0;
|
chunk->nIndices = 0;
|
||||||
|
|
||||||
// Abort if chunk is empty
|
// Abort if chunk is empty
|
||||||
if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)) return;
|
if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)) return;
|
||||||
|
@ -184,8 +191,26 @@ void mesh(Chunk::Chunk* chunk)
|
||||||
|
|
||||||
void sendtogpu(Chunk::Chunk* chunk)
|
void sendtogpu(Chunk::Chunk* chunk)
|
||||||
{
|
{
|
||||||
if (chunk->vIndex > 0)
|
if (chunk->indices.size() > 0)
|
||||||
{
|
{
|
||||||
|
for(int i = 0; i < chunk->index_to_vertex.size(); i++){
|
||||||
|
glm::vec3 v = chunk->index_to_vertex[i];
|
||||||
|
auto t = chunk->vertices_map.at(v);;
|
||||||
|
glm::vec3 n = std::get<1>(t);
|
||||||
|
glm::vec3 c = std::get<2>(t);
|
||||||
|
|
||||||
|
chunk->vertices.push_back(v.x);
|
||||||
|
chunk->vertices.push_back(v.y);
|
||||||
|
chunk->vertices.push_back(v.z);
|
||||||
|
|
||||||
|
chunk->vertices.push_back(n.x);
|
||||||
|
chunk->vertices.push_back(n.y);
|
||||||
|
chunk->vertices.push_back(n.z);
|
||||||
|
|
||||||
|
chunk->colors.push_back(c.x);
|
||||||
|
chunk->colors.push_back(c.y);
|
||||||
|
chunk->colors.push_back(c.z);
|
||||||
|
}
|
||||||
|
|
||||||
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
|
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
|
||||||
glBindVertexArray(chunk->VAO);
|
glBindVertexArray(chunk->VAO);
|
||||||
|
@ -215,9 +240,11 @@ void sendtogpu(Chunk::Chunk* chunk)
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
// save the number of indices of the mesh, it is needed later for drawing
|
// save the number of indices of the mesh, it is needed later for drawing
|
||||||
chunk->vIndex = (GLuint)(chunk->indices.size());
|
chunk->nIndices = (GLuint)(chunk->indices.size());
|
||||||
|
|
||||||
// once data has been sent to the GPU, it can be cleared from system RAM
|
// once data has been sent to the GPU, it can be cleared from system RAM
|
||||||
|
chunk->vertices_map.clear();
|
||||||
|
chunk->index_to_vertex.clear();
|
||||||
chunk->vertices.clear();
|
chunk->vertices.clear();
|
||||||
chunk->indices.clear();
|
chunk->indices.clear();
|
||||||
chunk->colors.clear();
|
chunk->colors.clear();
|
||||||
|
@ -230,7 +257,7 @@ void sendtogpu(Chunk::Chunk* chunk)
|
||||||
void draw(Chunk::Chunk* chunk, glm::mat4 model)
|
void draw(Chunk::Chunk* chunk, glm::mat4 model)
|
||||||
{
|
{
|
||||||
|
|
||||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode
|
||||||
if(chunk->getState(Chunk::CHUNK_STATE_MESH_LOADED))
|
if(chunk->getState(Chunk::CHUNK_STATE_MESH_LOADED))
|
||||||
{
|
{
|
||||||
theShader->use();
|
theShader->use();
|
||||||
|
@ -239,7 +266,7 @@ void draw(Chunk::Chunk* chunk, glm::mat4 model)
|
||||||
theShader->setMat4("projection", theCamera.getProjection());
|
theShader->setMat4("projection", theCamera.getProjection());
|
||||||
|
|
||||||
glBindVertexArray(chunk->VAO);
|
glBindVertexArray(chunk->VAO);
|
||||||
glDrawElements(GL_TRIANGLES, chunk->vIndex , GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, chunk->nIndices , GL_UNSIGNED_INT, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,86 +275,86 @@ void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec
|
||||||
glm::vec3 bottomRight, glm::vec3 normal, Block block, bool backFace)
|
glm::vec3 bottomRight, glm::vec3 normal, Block block, bool backFace)
|
||||||
{
|
{
|
||||||
|
|
||||||
chunk->vertices.push_back(bottomLeft.x);
|
|
||||||
chunk->vertices.push_back(bottomLeft.y);
|
|
||||||
chunk->vertices.push_back(bottomLeft.z);
|
|
||||||
chunk->vertices.push_back(normal.x);
|
|
||||||
chunk->vertices.push_back(normal.y);
|
|
||||||
chunk->vertices.push_back(normal.z);
|
|
||||||
|
|
||||||
chunk->vertices.push_back(bottomRight.x);
|
|
||||||
chunk->vertices.push_back(bottomRight.y);
|
|
||||||
chunk->vertices.push_back(bottomRight.z);
|
|
||||||
chunk->vertices.push_back(normal.x);
|
|
||||||
chunk->vertices.push_back(normal.y);
|
|
||||||
chunk->vertices.push_back(normal.z);
|
|
||||||
|
|
||||||
chunk->vertices.push_back(topLeft.x);
|
|
||||||
chunk->vertices.push_back(topLeft.y);
|
|
||||||
chunk->vertices.push_back(topLeft.z);
|
|
||||||
chunk->vertices.push_back(normal.x);
|
|
||||||
chunk->vertices.push_back(normal.y);
|
|
||||||
chunk->vertices.push_back(normal.z);
|
|
||||||
|
|
||||||
chunk->vertices.push_back(topRight.x);
|
|
||||||
chunk->vertices.push_back(topRight.y);
|
|
||||||
chunk->vertices.push_back(topRight.z);
|
|
||||||
chunk->vertices.push_back(normal.x);
|
|
||||||
chunk->vertices.push_back(normal.y);
|
|
||||||
chunk->vertices.push_back(normal.z);
|
|
||||||
|
|
||||||
|
|
||||||
if (backFace)
|
|
||||||
{
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 2);
|
|
||||||
chunk->indices.push_back(chunk->vIndex);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 1);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 1);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 3);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 2);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 3);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 1);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 1);
|
|
||||||
chunk->indices.push_back(chunk->vIndex);
|
|
||||||
chunk->indices.push_back(chunk->vIndex + 2);
|
|
||||||
}
|
|
||||||
chunk->vIndex += 4;
|
|
||||||
|
|
||||||
// ugly switch case for colors
|
// ugly switch case for colors
|
||||||
GLfloat r, g, b;
|
glm::vec3 color = glm::vec3(0.0f);
|
||||||
switch (block)
|
switch (block)
|
||||||
{
|
{
|
||||||
case Block::STONE:
|
case Block::STONE:
|
||||||
r = 0.588f;
|
color = glm::vec3(0.588f);
|
||||||
g = 0.588f;
|
|
||||||
b = 0.588f;
|
|
||||||
break;
|
break;
|
||||||
case Block::GRASS:
|
case Block::GRASS:
|
||||||
r = 0.05f;
|
color = glm::vec3(0.05f, 0.725f, 0.0f);
|
||||||
g = 0.725f;
|
|
||||||
b = 0.0f;
|
|
||||||
break;
|
break;
|
||||||
case Block::DIRT:
|
case Block::DIRT:
|
||||||
r = 0.152f;
|
color = glm::vec3(0.152f, 0.056f, 0.056f);
|
||||||
g = 0.056f;
|
|
||||||
b = 0.056f;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
r = 0.0f;
|
|
||||||
g = 0.0f;
|
|
||||||
b = 0.0f;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
int ibottomLeft, ibottomRight, itopLeft, itopRight;
|
||||||
|
|
||||||
|
if(chunk->vertices_map.find(bottomLeft) == chunk->vertices_map.end()){
|
||||||
|
chunk->index_to_vertex.push_back(bottomLeft);
|
||||||
|
ibottomLeft = indexCount++;
|
||||||
|
chunk->vertices_map[bottomLeft] = std::make_tuple(ibottomLeft, normal, color);
|
||||||
|
}else{
|
||||||
|
auto vm = chunk->vertices_map[bottomLeft];
|
||||||
|
ibottomLeft = std::get<0>(vm);
|
||||||
|
chunk->vertices_map[bottomLeft] = std::make_tuple(std::get<0>(vm), std::get<1>(vm) + normal,
|
||||||
|
std::get<2>(vm) + color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chunk->vertices_map.find(bottomRight) == chunk->vertices_map.end()){
|
||||||
|
chunk->index_to_vertex.push_back(bottomRight);
|
||||||
|
ibottomRight = indexCount++;
|
||||||
|
chunk->vertices_map[bottomRight] = std::make_tuple(ibottomRight, normal, color);
|
||||||
|
}else{
|
||||||
|
auto vm = chunk->vertices_map[bottomRight];
|
||||||
|
ibottomRight = std::get<0>(vm);
|
||||||
|
chunk->vertices_map[bottomRight] = std::make_tuple(std::get<0>(vm), std::get<1>(vm) + normal,
|
||||||
|
std::get<2>(vm) + color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chunk->vertices_map.find(topLeft) == chunk->vertices_map.end()){
|
||||||
|
chunk->index_to_vertex.push_back(topLeft);
|
||||||
|
itopLeft = indexCount++;
|
||||||
|
chunk->vertices_map[topLeft] = std::make_tuple(itopLeft, normal, color);
|
||||||
|
}else{
|
||||||
|
auto vm = chunk->vertices_map[topLeft];
|
||||||
|
itopLeft = std::get<0>(vm);
|
||||||
|
chunk->vertices_map[topLeft] = std::make_tuple(std::get<0>(vm), std::get<1>(vm) + normal,
|
||||||
|
std::get<2>(vm) + color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chunk->vertices_map.find(topRight) == chunk->vertices_map.end()){
|
||||||
|
chunk->index_to_vertex.push_back(topRight);
|
||||||
|
itopRight = indexCount++;
|
||||||
|
chunk->vertices_map[topRight] = std::make_tuple(itopRight, normal, color);
|
||||||
|
}else{
|
||||||
|
auto vm = chunk->vertices_map[topRight];
|
||||||
|
itopRight = std::get<0>(vm);
|
||||||
|
chunk->vertices_map[topRight] = std::make_tuple(std::get<0>(vm), std::get<1>(vm) + normal,
|
||||||
|
std::get<2>(vm) + color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottomLeft, bottomRight, topLeft, topRight
|
||||||
|
if (backFace)
|
||||||
{
|
{
|
||||||
chunk->colors.push_back(r);
|
chunk->indices.push_back(itopLeft);
|
||||||
chunk->colors.push_back(g);
|
chunk->indices.push_back(ibottomLeft);
|
||||||
chunk->colors.push_back(b);
|
chunk->indices.push_back(ibottomRight);
|
||||||
|
chunk->indices.push_back(ibottomRight);
|
||||||
|
chunk->indices.push_back(itopRight);
|
||||||
|
chunk->indices.push_back(itopLeft);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->indices.push_back(itopLeft);
|
||||||
|
chunk->indices.push_back(itopRight);
|
||||||
|
chunk->indices.push_back(ibottomRight);
|
||||||
|
chunk->indices.push_back(ibottomRight);
|
||||||
|
chunk->indices.push_back(ibottomLeft);
|
||||||
|
chunk->indices.push_back(itopLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue