186 lines
6.7 KiB
C++
186 lines
6.7 KiB
C++
#include "chunk.h"
|
|
|
|
#include "world.h"
|
|
|
|
static glm::vec3 cube_vertexes[6][4] = {
|
|
{glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f)}, // Left
|
|
{glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 1.0f)}, // Right
|
|
{glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f)}, // Back
|
|
{glm::vec3(1.0f, 0.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 1.0f)}, // Front
|
|
{glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 1.0f)}, // Bottom
|
|
{glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 0.0f)}, // Top
|
|
};
|
|
|
|
static glm::vec3 cube_normals[6] = {
|
|
glm::vec3(-1.0f, 0.0f, 0.0f), // Left
|
|
glm::vec3(1.0f, 0.0f, 0.0f), // Right
|
|
glm::vec3(0.0f, 0.0f, -1.0f), // Back
|
|
glm::vec3(0.0f, 0.0f, 1.0f), // Front
|
|
glm::vec3(0.0f, -1.0f, 0.0f), // Bottom
|
|
glm::vec3(0.0f, 1.0f, 0.0f), // Top
|
|
};
|
|
|
|
void Chunk::set_block(int x, int y, int z, int block) {
|
|
if (x < 0 || x >= Chunk::horiz_size)
|
|
return;
|
|
if (z < 0 || z >= Chunk::horiz_size)
|
|
return;
|
|
if (y < 0 || y >= Chunk::vert_size)
|
|
return;
|
|
this->blocks[y * Chunk::horiz_size * Chunk::horiz_size + z * Chunk::horiz_size + x] = block;
|
|
}
|
|
|
|
int Chunk::get_block(int x, int y, int z) {
|
|
if (x < 0 || x >= Chunk::horiz_size)
|
|
return 0;
|
|
if (z < 0 || z >= Chunk::horiz_size)
|
|
return 0;
|
|
if (y < 0 || y >= Chunk::vert_size)
|
|
return 0;
|
|
return this->blocks[y * Chunk::horiz_size * Chunk::horiz_size + z * Chunk::horiz_size + x];
|
|
}
|
|
|
|
Chunk::Chunk(int x, int z) {
|
|
this->x = x;
|
|
this->z = z;
|
|
|
|
std::cerr << "Chunk created at X: " << x << " Z: " << z << "\n";
|
|
|
|
for (int x=0; x<Chunk::horiz_size; x++) {
|
|
for (int z=0; z<Chunk::horiz_size; z++) {
|
|
int max_height = 96 + 32 * World::get_height_at(this->x * 16 + x, this->z * 16 + z);
|
|
|
|
int stone_ceil = max_height / 1.2f;
|
|
|
|
for (int y=0; y<=Chunk::vert_size; y++) {
|
|
if (y == 0) {
|
|
set_block(x, y, z, 1);
|
|
} else if (y < stone_ceil) {
|
|
set_block(x, y, z, 2);
|
|
} else if (y < max_height) {
|
|
set_block(x, y, z, 3);
|
|
} else if (y == max_height) {
|
|
set_block(x, y, z, 5);
|
|
} else {
|
|
set_block(x, y, z, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Chunk::~Chunk() {
|
|
glDeleteBuffers(4, this->VBOs);
|
|
glDeleteVertexArrays(1, &this->VAO);
|
|
}
|
|
|
|
|
|
void Chunk::generate() {
|
|
std::chrono::high_resolution_clock clock;
|
|
if (mesh_version < current_version) {
|
|
auto t1 = clock.now();
|
|
mesh_version++;
|
|
|
|
std::vector<glm::vec3> vertex_positions;
|
|
std::vector<glm::vec3> vertex_normals;
|
|
std::vector<glm::vec2> vertex_tex_coords;
|
|
std::vector<int> vertex_indexes;
|
|
|
|
int index=0;
|
|
|
|
for (int x=0; x<Chunk::horiz_size; x++) {
|
|
for (int z=0; z<Chunk::horiz_size; z++) {
|
|
for (int y=0; y<Chunk::vert_size; y++) {
|
|
int block;
|
|
if (block = get_block(x, y, z)) {
|
|
bool faces[6] = {
|
|
!get_block(x-1, y, z), // Left
|
|
!get_block(x+1, y, z), // Right
|
|
!get_block(x, y, z-1), // Back
|
|
!get_block(x, y, z+1), // Front
|
|
!get_block(x, y-1, z), // Bottom
|
|
!get_block(x, y+1, z), // Top
|
|
};
|
|
|
|
for (int i=0; i<6; i++) {
|
|
if (faces[i]) {
|
|
vertex_positions.emplace_back(cube_vertexes[i][0].x + x, cube_vertexes[i][0].y + y, cube_vertexes[i][0].z + z);
|
|
vertex_positions.emplace_back(cube_vertexes[i][1].x + x, cube_vertexes[i][1].y + y, cube_vertexes[i][1].z + z);
|
|
vertex_positions.emplace_back(cube_vertexes[i][2].x + x, cube_vertexes[i][2].y + y, cube_vertexes[i][2].z + z);
|
|
vertex_positions.emplace_back(cube_vertexes[i][3].x + x, cube_vertexes[i][3].y + y, cube_vertexes[i][3].z + z);
|
|
|
|
vertex_normals.push_back(cube_normals[i]);
|
|
vertex_normals.push_back(cube_normals[i]);
|
|
vertex_normals.push_back(cube_normals[i]);
|
|
vertex_normals.push_back(cube_normals[i]);
|
|
|
|
int u = block % 16;
|
|
int v = block / 16;
|
|
|
|
float uv_step = 1.0f / 16.0f;
|
|
|
|
vertex_tex_coords.emplace_back(uv_step * (u), uv_step * (v));
|
|
vertex_tex_coords.emplace_back(uv_step * (u), uv_step * (v+1));
|
|
vertex_tex_coords.emplace_back(uv_step * (u+1), uv_step * (v+1));
|
|
vertex_tex_coords.emplace_back(uv_step * (u+1), uv_step * (v));
|
|
|
|
vertex_indexes.push_back(index + 0);
|
|
vertex_indexes.push_back(index + 1);
|
|
vertex_indexes.push_back(index + 2);
|
|
vertex_indexes.push_back(index + 2);
|
|
vertex_indexes.push_back(index + 3);
|
|
vertex_indexes.push_back(index + 0);
|
|
|
|
index += 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
glGenVertexArrays(1, &this->VAO);
|
|
glBindVertexArray(this->VAO);
|
|
glGenBuffers(4, this->VBOs);
|
|
|
|
glEnableVertexAttribArray(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[0]);
|
|
glBufferData(GL_ARRAY_BUFFER, vertex_positions.size() * sizeof(glm::vec3), &vertex_positions[0].x, GL_STATIC_DRAW);
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
|
|
|
glEnableVertexAttribArray(1);
|
|
glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[1]);
|
|
glBufferData(GL_ARRAY_BUFFER, vertex_normals.size() * sizeof(glm::vec3), &vertex_normals[0].x, GL_STATIC_DRAW);
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, (void*)0);
|
|
|
|
glEnableVertexAttribArray(2);
|
|
glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[2]);
|
|
glBufferData(GL_ARRAY_BUFFER, vertex_tex_coords.size() * sizeof(glm::vec2), &vertex_tex_coords[0].x, GL_STATIC_DRAW);
|
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
|
|
|
glEnableVertexAttribArray(3);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->VBOs[3]);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex_indexes.size() * sizeof(int), &vertex_indexes[0], GL_STATIC_DRAW);
|
|
glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, 0, (void*)0);
|
|
|
|
this->vertex_count = vertex_indexes.size();
|
|
|
|
auto t2 = clock.now();
|
|
|
|
std::chrono::duration<double> d = (t2 - t1);
|
|
|
|
std::cerr << "Generated chunk in " << d.count() << " seconds.\n";
|
|
}
|
|
}
|
|
|
|
bool Chunk::outdated() {
|
|
return mesh_version < current_version;
|
|
}
|
|
|
|
glm::mat4 Chunk::get_transformation_matrix() {
|
|
return glm::translate(glm::mat4(1.0f), glm::vec3(Chunk::horiz_size * this->x, 0.0f, Chunk::horiz_size * this->z));
|
|
}
|
|
|
|
void Chunk::select() {
|
|
glBindVertexArray(this->VAO);
|
|
} |