146 lines
4.9 KiB
C++
146 lines
4.9 KiB
C++
#include "Chunk.h"
|
|
#include <vector>
|
|
#include <iostream>
|
|
|
|
const int VERTEX_SIZE = 7; // x, y, z, nx, ny, nz, voxelKind
|
|
|
|
const float topFace[24] = {
|
|
// x, y, z, nx, ny, nz
|
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
|
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
|
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
|
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f
|
|
};
|
|
const float bottomFace[24] = {
|
|
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
|
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
|
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
|
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f
|
|
};
|
|
const float rightFace[24] = {
|
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
|
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
|
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f
|
|
};
|
|
const float leftFace[24] = {
|
|
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
|
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
|
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
|
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f
|
|
};
|
|
const float frontFace[24] = {
|
|
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
|
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
|
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
|
|
};
|
|
const float backFace[24] = {
|
|
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
|
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
|
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f
|
|
};
|
|
|
|
void addFace(glm::ivec3 pos, const float *faceVertices, float voxelKind, std::vector<float> &vbo, std::vector<unsigned int> &ebo) {
|
|
unsigned int vIndex = vbo.size() / VERTEX_SIZE;
|
|
for (int i = 0; i < 4; i++) {
|
|
const float* v = &faceVertices[i * 6]; // Face data is still 6 floats per vertex
|
|
float world_x = v[0] + pos.x;
|
|
float world_y = v[1] + pos.y;
|
|
float world_z = v[2] + pos.z;
|
|
|
|
// Debug: Print first vertex of first face
|
|
// if (vbo.empty() && i == 0) {
|
|
// std::cout << "[MESH] First vertex - Local pos: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
|
// std::cout << "[MESH] First vertex - World: (" << world_x << ", " << world_y << ", " << world_z << ")" << std::endl;
|
|
// }
|
|
|
|
vbo.push_back(world_x);
|
|
vbo.push_back(world_y);
|
|
vbo.push_back(world_z);
|
|
vbo.push_back(v[3]);
|
|
vbo.push_back(v[4]);
|
|
vbo.push_back(v[5]);
|
|
vbo.push_back(voxelKind); // Add voxel kind as 7th component
|
|
}
|
|
ebo.push_back(vIndex + 0);
|
|
ebo.push_back(vIndex + 1);
|
|
ebo.push_back(vIndex + 2);
|
|
ebo.push_back(vIndex + 0);
|
|
ebo.push_back(vIndex + 2);
|
|
ebo.push_back(vIndex + 3);
|
|
}
|
|
|
|
Chunk::Chunk() {
|
|
this->data.fill(VoxelKind::Air);
|
|
}
|
|
|
|
Mesh* Chunk::getMesh() {
|
|
// Generate mesh on first access if not already generated, or if dirty
|
|
if ((!mesh || mesh_dirty) && !this->isEmpty()) {
|
|
generateMesh();
|
|
mesh_dirty = false;
|
|
}
|
|
return mesh.get();
|
|
}
|
|
|
|
void Chunk::generateMesh() {
|
|
std::vector<float> vboData;
|
|
std::vector<unsigned int> eboData;
|
|
|
|
// std::cout << "Generating Chunk mesh..." << std::endl;
|
|
|
|
const std::pair<glm::ivec3, const float*> neighbors[6] = {
|
|
std::pair(glm::ivec3(0, 1, 0), topFace), // top
|
|
std::pair(glm::ivec3(0, -1, 0), bottomFace), // bottom
|
|
std::pair(glm::ivec3(1, 0, 0), rightFace), // right
|
|
std::pair(glm::ivec3(-1, 0, 0), leftFace), // left
|
|
std::pair(glm::ivec3(0, 0, 1), frontFace), // front
|
|
std::pair(glm::ivec3(0, 0, -1), backFace) // back
|
|
};
|
|
|
|
for (int i = 0; i < TOTAL; ++i) {
|
|
VoxelKind kind = this->data[i];
|
|
if (kind == VoxelKind::Air) continue;
|
|
|
|
int x = i % SIZE;
|
|
int y = (i / SIZE) % SIZE;
|
|
int z = i / (SIZE * SIZE);
|
|
|
|
glm::ivec3 pos(x, y, z);
|
|
|
|
for (const auto& neighborPair : neighbors) {
|
|
glm::ivec3 dir = neighborPair.first;
|
|
const float* face = neighborPair.second;
|
|
int nx = x + dir.x;
|
|
int ny = y + dir.y;
|
|
int nz = z + dir.z;
|
|
|
|
bool neighbour_is_solid = false;
|
|
// in-bounds neighbor -> check data
|
|
if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && nz >= 0 && nz < SIZE) {
|
|
// std::cout << "Accessing " << nx << ", " << ny << ", " << nz << std::endl;
|
|
neighbour_is_solid = (data[index(nx, ny, nz)] != VoxelKind::Air);
|
|
} else {
|
|
// neighbour out of this chunk: treat as air (exposed face)
|
|
// or call into World to query adjacent chunk here
|
|
neighbour_is_solid = false;
|
|
}
|
|
|
|
if (!neighbour_is_solid) {
|
|
addFace(pos, face, static_cast<float>(kind), vboData, eboData);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create and initialize mesh if it doesn't exist
|
|
if (!mesh) {
|
|
mesh = std::make_unique<Mesh>();
|
|
mesh->init();
|
|
}
|
|
|
|
// Now, upload this data to our mesh object
|
|
mesh->uploadData(vboData, eboData);
|
|
}
|