added chunk rendering
This commit is contained in:
parent
20f38ad3a9
commit
3ba2d75cff
BIN
.attachments/chunk-render.png
Normal file
BIN
.attachments/chunk-render.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@ -23,6 +23,8 @@ add_executable(VoxelEngine
|
|||||||
src/World.cpp
|
src/World.cpp
|
||||||
src/Mesh.h
|
src/Mesh.h
|
||||||
src/Mesh.cpp
|
src/Mesh.cpp
|
||||||
|
src/Chunk.h
|
||||||
|
src/Chunk.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Configure GLAD (from your src/ and include/ folders) ---
|
# --- Configure GLAD (from your src/ and include/ folders) ---
|
||||||
|
|||||||
@ -6,9 +6,15 @@ Currently, however, the program only renders a single cube.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## World Render - 11/10/25
|
## World Mesh Rendering - 11/10/25
|
||||||
|
|
||||||
World now renders as a single mesh! Much faster than rendering cube by cube.
|
World now renders as a single mesh! Much faster than rendering cube by cube.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Chunk Mesh Rendering - 11/11/25
|
||||||
|
|
||||||
|
Instead of making the _entire_ world a single mesh, now the world is made up of 32x32x32 "Chunks" which are areas of the world that are a single mesh.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|||||||
108
src/Chunk.cpp
Normal file
108
src/Chunk.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "Chunk.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
const int VERTEX_SIZE = 6;
|
||||||
|
|
||||||
|
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, 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 * VERTEX_SIZE];
|
||||||
|
vbo.push_back(v[0] + pos.x);
|
||||||
|
vbo.push_back(v[1] + pos.y);
|
||||||
|
vbo.push_back(v[2] + pos.z);
|
||||||
|
vbo.push_back(v[3]);
|
||||||
|
vbo.push_back(v[4]);
|
||||||
|
vbo.push_back(v[5]);
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
// mesh is initially null (nullptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh* Chunk::getMesh() {
|
||||||
|
// Generate mesh on first access if not already generated
|
||||||
|
if (!mesh && !voxels.empty()) {
|
||||||
|
generateMesh();
|
||||||
|
}
|
||||||
|
return mesh.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunk::generateMesh() {
|
||||||
|
std::vector<float> vboData;
|
||||||
|
std::vector<unsigned int> eboData;
|
||||||
|
|
||||||
|
for (const glm::ivec3 pos : voxels) {
|
||||||
|
if (voxels.count(pos + glm::ivec3(0, 1, 0)) == 0) {
|
||||||
|
addFace(pos, topFace, vboData, eboData);
|
||||||
|
}
|
||||||
|
if (voxels.count(pos + glm::ivec3(0, -1, 0)) == 0) {
|
||||||
|
addFace(pos, bottomFace, vboData, eboData);
|
||||||
|
}
|
||||||
|
if (voxels.count(pos + glm::ivec3(1, 0, 0)) == 0) {
|
||||||
|
addFace(pos, rightFace, vboData, eboData);
|
||||||
|
}
|
||||||
|
if (voxels.count(pos + glm::ivec3(-1, 0, 0)) == 0) {
|
||||||
|
addFace(pos, leftFace, vboData, eboData);
|
||||||
|
}
|
||||||
|
if (voxels.count(pos + glm::ivec3(0, 0, 1)) == 0) {
|
||||||
|
addFace(pos, frontFace, vboData, eboData);
|
||||||
|
}
|
||||||
|
if (voxels.count(pos + glm::ivec3(0, 0, -1)) == 0) {
|
||||||
|
addFace(pos, backFace, 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);
|
||||||
|
}
|
||||||
43
src/Chunk.h
Normal file
43
src/Chunk.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef CHUNK_H
|
||||||
|
#define CHUNK_H
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "Mesh.h"
|
||||||
|
|
||||||
|
const int CHUNK_SIZE = 32;
|
||||||
|
|
||||||
|
// Hash function for glm::ivec3 to use with unordered_set
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<glm::ivec3> {
|
||||||
|
size_t operator()(const glm::ivec3& v) const {
|
||||||
|
// Combine hash values of x, y, z components
|
||||||
|
size_t h1 = hash<int>()(v.x);
|
||||||
|
size_t h2 = hash<int>()(v.y);
|
||||||
|
size_t h3 = hash<int>()(v.z);
|
||||||
|
|
||||||
|
// Use a simple hash combination algorithm
|
||||||
|
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Chunk {
|
||||||
|
public:
|
||||||
|
std::unordered_set<glm::ivec3> voxels;
|
||||||
|
|
||||||
|
Chunk();
|
||||||
|
|
||||||
|
Mesh* getMesh(); // Returns pointer, can be null if not generated yet
|
||||||
|
|
||||||
|
void generateMesh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Mesh> mesh; // Nullable mesh
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif CHUNK_H
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
|
|
||||||
Mesh::Mesh() : m_VAO(0), m_VBO(0), m_EBO(0), m_indexCount(0) {}
|
Mesh::Mesh() : m_VAO(0), m_VBO(0), m_EBO(0), m_indexCount(0) {}
|
||||||
@ -38,10 +40,14 @@ void Mesh::init() {
|
|||||||
void Mesh::uploadData(const std::vector<float> &vboData, const std::vector<unsigned int> &eboData) {
|
void Mesh::uploadData(const std::vector<float> &vboData, const std::vector<unsigned int> &eboData) {
|
||||||
m_indexCount = eboData.size();
|
m_indexCount = eboData.size();
|
||||||
|
|
||||||
|
std::cout << "Uploading mesh: " << vboData.size() << " floats, " << eboData.size() << " indices" << std::endl;
|
||||||
|
|
||||||
|
// Bind VAO first, then upload buffer data
|
||||||
|
glBindVertexArray(m_VAO);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(float), vboData.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(float), vboData.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
glBindVertexArray(m_VAO);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, eboData.size() * sizeof(unsigned int), eboData.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, eboData.size() * sizeof(unsigned int), eboData.data(), GL_STATIC_DRAW);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|||||||
104
src/World.cpp
104
src/World.cpp
@ -1,98 +1,22 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
const int VERTEX_SIZE = 6;
|
World::World() {}
|
||||||
|
|
||||||
const float topFace[24] = {
|
void World::flip_voxel(glm::ivec3 position) {
|
||||||
// x, y, z, nx, ny, nz
|
glm::ivec3 chunk_position = position / CHUNK_SIZE;
|
||||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
glm::ivec3 local_position = position % CHUNK_SIZE;
|
||||||
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, std::vector<float> &vbo, std::vector<unsigned int> &ebo) {
|
Chunk * chunk = get_or_create_chunk(chunk_position);
|
||||||
unsigned int vIndex = vbo.size() / VERTEX_SIZE;
|
if (chunk->voxels.count(local_position) != 0) {
|
||||||
for (int i = 0; i < 4; i++) {
|
chunk->voxels.erase(chunk->voxels.find(local_position));
|
||||||
const float* v = &faceVertices[i * VERTEX_SIZE];
|
} else {
|
||||||
vbo.push_back(v[0] + pos.x);
|
chunk->voxels.insert(local_position);
|
||||||
vbo.push_back(v[1] + pos.y);
|
|
||||||
vbo.push_back(v[2] + pos.z);
|
|
||||||
vbo.push_back(v[3]);
|
|
||||||
vbo.push_back(v[4]);
|
|
||||||
vbo.push_back(v[5]);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
World::World() {
|
|
||||||
m_mesh.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh& World::getMesh() {
|
|
||||||
return m_mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::generateMesh() {
|
|
||||||
std::vector<float> vboData;
|
|
||||||
std::vector<unsigned int> eboData;
|
|
||||||
|
|
||||||
for (const glm::ivec3 pos : voxels) {
|
|
||||||
if (voxels.count(pos + glm::ivec3(0, 1, 0)) == 0) {
|
|
||||||
addFace(pos, topFace, vboData, eboData);
|
|
||||||
}
|
|
||||||
if (voxels.count(pos + glm::ivec3(0, -1, 0)) == 0) {
|
|
||||||
addFace(pos, bottomFace, vboData, eboData);
|
|
||||||
}
|
|
||||||
if (voxels.count(pos + glm::ivec3(1, 0, 0)) == 0) {
|
|
||||||
addFace(pos, rightFace, vboData, eboData);
|
|
||||||
}
|
|
||||||
if (voxels.count(pos + glm::ivec3(-1, 0, 0)) == 0) {
|
|
||||||
addFace(pos, leftFace, vboData, eboData);
|
|
||||||
}
|
|
||||||
if (voxels.count(pos + glm::ivec3(0, 0, 1)) == 0) {
|
|
||||||
addFace(pos, frontFace, vboData, eboData);
|
|
||||||
}
|
|
||||||
if (voxels.count(pos + glm::ivec3(0, 0, -1)) == 0) {
|
|
||||||
addFace(pos, backFace, vboData, eboData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, upload this data to our mesh object
|
Chunk* World::get_or_create_chunk(glm::ivec3 chunk_position) {
|
||||||
m_mesh.uploadData(vboData, eboData);
|
if (this->chunks.count(chunk_position) == 0) {
|
||||||
|
this->chunks[chunk_position] = Chunk();
|
||||||
|
}
|
||||||
|
return &this->chunks[chunk_position];
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/World.h
31
src/World.h
@ -1,41 +1,22 @@
|
|||||||
#ifndef WORLD_H
|
#ifndef WORLD_H
|
||||||
#define CAMERA_H
|
#define WORLD_H
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Mesh.h"
|
#include "Chunk.h"
|
||||||
|
|
||||||
// Hash function for glm::ivec3 to use with unordered_set
|
|
||||||
namespace std {
|
|
||||||
template <>
|
|
||||||
struct hash<glm::ivec3> {
|
|
||||||
size_t operator()(const glm::ivec3& v) const {
|
|
||||||
// Combine hash values of x, y, z components
|
|
||||||
size_t h1 = hash<int>()(v.x);
|
|
||||||
size_t h2 = hash<int>()(v.y);
|
|
||||||
size_t h3 = hash<int>()(v.z);
|
|
||||||
|
|
||||||
// Use a simple hash combination algorithm
|
|
||||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class World
|
class World
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::unordered_set<glm::ivec3> voxels;
|
std::unordered_map<glm::ivec3, Chunk> chunks;
|
||||||
|
|
||||||
World();
|
World();
|
||||||
|
|
||||||
void generateMesh();
|
void flip_voxel(glm::ivec3 position);
|
||||||
|
|
||||||
Mesh& getMesh();
|
Chunk* get_or_create_chunk(glm::ivec3 chunk_position);
|
||||||
|
|
||||||
private:
|
|
||||||
Mesh m_mesh;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif WORLD_H
|
#endif WORLD_H
|
||||||
|
|||||||
84
src/main.cpp
84
src/main.cpp
@ -1,5 +1,4 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include <glad/glad.h> // Must be included before GLFW
|
#include <glad/glad.h> // Must be included before GLFW
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
@ -171,28 +170,6 @@ void processInput(GLFWwindow *window)
|
|||||||
camera.speed = CAMERA_SPEED * 20;
|
camera.speed = CAMERA_SPEED * 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a cube at some x, y, z
|
|
||||||
// [UPDATED] Added a new 'color' parameter
|
|
||||||
void draw_cube(glm::ivec3 coords, Shader& shader, unsigned int VAO, size_t indexCount, const glm::mat4& view, const glm::mat4& projection, const glm::vec3& color) {
|
|
||||||
// Create model matrix for positioning the cube
|
|
||||||
glm::mat4 model = glm::mat4(1.0f);
|
|
||||||
model = glm::translate(model, glm::vec3(coords));
|
|
||||||
|
|
||||||
model = glm::scale(model, glm::vec3(0.5f, 0.5f, 0.5f));
|
|
||||||
|
|
||||||
// Calculate MVP matrix
|
|
||||||
glm::mat4 mvp = projection * view * model;
|
|
||||||
|
|
||||||
// Set the uniform and draw
|
|
||||||
shader.use();
|
|
||||||
shader.setMat4("u_mvp", mvp);
|
|
||||||
// [NEW] Set the color uniform in the fragment shader
|
|
||||||
shader.setVec3("u_Color", color);
|
|
||||||
|
|
||||||
glBindVertexArray(VAO);
|
|
||||||
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// 1. --- Initialize GLFW ---
|
// 1. --- Initialize GLFW ---
|
||||||
if (!glfwInit()) {
|
if (!glfwInit()) {
|
||||||
@ -231,16 +208,15 @@ int main() {
|
|||||||
Object3D cube = Object3D("objs/cube.obj");
|
Object3D cube = Object3D("objs/cube.obj");
|
||||||
|
|
||||||
// Place cubes in the world
|
// Place cubes in the world
|
||||||
for (int z = 0; z <= 32; z++) {
|
for (int z = 0; z <= 256; z++) {
|
||||||
for (int x = 0; x <= 32; x++) {
|
for (int x = 0; x <= 256; x++) {
|
||||||
world.voxels.insert(glm::ivec3(x, -1, z));
|
world.flip_voxel(glm::ivec3(x, -1, z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
world.voxels.insert(glm::ivec3(7, 0, 13));
|
world.flip_voxel(glm::ivec3(7, 0, 13));
|
||||||
std::cout << "Generating world mesh..." << std::endl;
|
std::cout << "World created with " << world.chunks.size() << " chunks" << std::endl;
|
||||||
world.generateMesh();
|
// Mesh generation now happens automatically when first rendering
|
||||||
std::cout << "Mesh generated!" << std::endl;
|
|
||||||
|
|
||||||
if (WIREFRAME_MODE)
|
if (WIREFRAME_MODE)
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
@ -257,6 +233,7 @@ int main() {
|
|||||||
double move_time = glfwGetTime();
|
double move_time = glfwGetTime();
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
bool debug_printed = false;
|
||||||
|
|
||||||
// 6. --- The Render Loop ---
|
// 6. --- The Render Loop ---
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
@ -269,9 +246,13 @@ int main() {
|
|||||||
view = camera.getView();
|
view = camera.getView();
|
||||||
|
|
||||||
shader.use();
|
shader.use();
|
||||||
glm::mat4 model = glm::mat4(1.0f);
|
|
||||||
glm::mat4 mvp = projection * view * model;
|
if (!debug_printed) {
|
||||||
shader.setMat4("u_mvp", mvp);
|
std::cout << "\n=== RENDER DEBUG ===" << std::endl;
|
||||||
|
std::cout << "Camera pos: (" << camera.position.x << ", " << camera.position.y << ", " << camera.position.z << ")" << std::endl;
|
||||||
|
std::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
std::cout << "Number of chunks to draw: " << world.chunks.size() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
// ---- PASS 1: Draw solid grey cubes ----
|
// ---- PASS 1: Draw solid grey cubes ----
|
||||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
@ -279,7 +260,28 @@ int main() {
|
|||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
shader.setVec3("u_Color", glm::vec3(0.5, 0.5, 0.5));
|
shader.setVec3("u_Color", glm::vec3(0.5, 0.5, 0.5));
|
||||||
|
|
||||||
world.getMesh().draw();
|
for (auto& [chunk_position, chunk] : world.chunks) {
|
||||||
|
|
||||||
|
glm::ivec3 chunk_offset = chunk_position * CHUNK_SIZE;
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
model = glm::translate(model, glm::vec3(chunk_offset));
|
||||||
|
glm::mat4 mvp = projection * view * model;
|
||||||
|
shader.setMat4("u_mvp", mvp);
|
||||||
|
|
||||||
|
if (!debug_printed) {
|
||||||
|
std::cout << "Drawing chunk at (" << chunk_position.x << ", " << chunk_position.y << ", " << chunk_position.z << ")" << std::endl;
|
||||||
|
std::cout << "Chunk offset: (" << chunk_offset.x << ", " << chunk_offset.y << ", " << chunk_offset.z << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh* chunkMesh = chunk.getMesh();
|
||||||
|
if (chunkMesh) {
|
||||||
|
chunkMesh->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!debug_printed) {
|
||||||
|
debug_printed = true;
|
||||||
|
}
|
||||||
|
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
|
||||||
@ -287,7 +289,19 @@ int main() {
|
|||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Just the lines
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Just the lines
|
||||||
shader.setVec3("u_Color", glm::vec3(1.0, 1.0, 1.0));
|
shader.setVec3("u_Color", glm::vec3(1.0, 1.0, 1.0));
|
||||||
|
|
||||||
world.getMesh().draw();
|
for (auto& [chunk_position, chunk] : world.chunks) {
|
||||||
|
|
||||||
|
glm::ivec3 chunk_offset = chunk_position * CHUNK_SIZE;
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
model = glm::translate(model, glm::vec3(chunk_offset));
|
||||||
|
glm::mat4 mvp = projection * view * model;
|
||||||
|
shader.setMat4("u_mvp", mvp);
|
||||||
|
|
||||||
|
Mesh* chunkMesh = chunk.getMesh();
|
||||||
|
if (chunkMesh) {
|
||||||
|
chunkMesh->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Reset polygon mode for next frame (good practice) ---
|
// --- Reset polygon mode for next frame (good practice) ---
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user