added world mesh
This commit is contained in:
parent
90c99734bf
commit
f6de6a6758
@ -20,6 +20,9 @@ add_executable(VoxelEngine
|
|||||||
src/Object3D.cpp
|
src/Object3D.cpp
|
||||||
src/Camera.h
|
src/Camera.h
|
||||||
src/World.h
|
src/World.h
|
||||||
|
src/World.cpp
|
||||||
|
src/Mesh.h
|
||||||
|
src/Mesh.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Configure GLAD (from your src/ and include/ folders) ---
|
# --- Configure GLAD (from your src/ and include/ folders) ---
|
||||||
|
|||||||
56
src/Mesh.cpp
Normal file
56
src/Mesh.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "Mesh.h"
|
||||||
|
|
||||||
|
Mesh::Mesh() : m_VAO(0), m_VBO(0), m_EBO(0), m_indexCount(0) {}
|
||||||
|
|
||||||
|
Mesh::~Mesh() {
|
||||||
|
glDeleteVertexArrays(1, &m_VAO);
|
||||||
|
glDeleteBuffers(1, &m_VBO);
|
||||||
|
glDeleteBuffers(1, &m_EBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::init() {
|
||||||
|
// Generate all the OpenGL objects
|
||||||
|
glGenVertexArrays(1, &m_VAO);
|
||||||
|
glGenBuffers(1, &m_VBO);
|
||||||
|
glGenBuffers(1, &m_EBO);
|
||||||
|
|
||||||
|
// Bind the VAO and set up the vertex attributes
|
||||||
|
glBindVertexArray(m_VAO);
|
||||||
|
|
||||||
|
// 1. Bind VBO
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
||||||
|
|
||||||
|
// 2. Set up attributes (this layout is now saved in the VAO)
|
||||||
|
// Position Attribute
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
// Normal Attribute
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
// 3. Bind EBO
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
||||||
|
|
||||||
|
// 4. Unbind VAO (good practice)
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::uploadData(const std::vector<float> &vboData, const std::vector<unsigned int> &eboData) {
|
||||||
|
m_indexCount = eboData.size();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(float), vboData.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindVertexArray(m_VAO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, eboData.size() * sizeof(unsigned int), eboData.data(), GL_STATIC_DRAW);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::draw() {
|
||||||
|
if (m_indexCount == 0) return;
|
||||||
|
|
||||||
|
glBindVertexArray(m_VAO);
|
||||||
|
glDrawElements(GL_TRIANGLES, m_indexCount, GL_UNSIGNED_INT, nullptr);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
27
src/Mesh.h
Normal file
27
src/Mesh.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef MESH_H
|
||||||
|
#define MESH_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
class Mesh {
|
||||||
|
public:
|
||||||
|
Mesh();
|
||||||
|
~Mesh(); // Destructor to clean up GPU memory
|
||||||
|
|
||||||
|
// Initializes the VAO and buffer objects
|
||||||
|
void init();
|
||||||
|
|
||||||
|
// Uploads mesh data to the GPU
|
||||||
|
void uploadData(const std::vector<float>& vboData, const std::vector<unsigned int>& eboData);
|
||||||
|
|
||||||
|
// Binds the VAO and draws the mesh
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int m_VAO, m_VBO, m_EBO;
|
||||||
|
size_t m_indexCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif MESH_H
|
||||||
98
src/World.cpp
Normal file
98
src/World.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include "World.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
m_mesh.uploadData(vboData, eboData);
|
||||||
|
}
|
||||||
11
src/World.h
11
src/World.h
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "Mesh.h"
|
||||||
|
|
||||||
// Hash function for glm::ivec3 to use with unordered_set
|
// Hash function for glm::ivec3 to use with unordered_set
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
@ -25,6 +27,15 @@ class World
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::unordered_set<glm::ivec3> voxels;
|
std::unordered_set<glm::ivec3> voxels;
|
||||||
|
|
||||||
|
World();
|
||||||
|
|
||||||
|
void generateMesh();
|
||||||
|
|
||||||
|
Mesh& getMesh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mesh m_mesh;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif WORLD_H
|
#endif WORLD_H
|
||||||
|
|||||||
55
src/main.cpp
55
src/main.cpp
@ -238,35 +238,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
world.voxels.insert(glm::ivec3(7, 0, 13));
|
world.voxels.insert(glm::ivec3(7, 0, 13));
|
||||||
|
std::cout << "Generating world mesh..." << std::endl;
|
||||||
unsigned int VBO, VAO, EBO;
|
world.generateMesh();
|
||||||
glGenVertexArrays(1, &VAO); // 1. Create Vertex Array Object (VAO)
|
std::cout << "Mesh generated!" << std::endl;
|
||||||
glGenBuffers(1, &VBO); // 2. Create Vertex Buffer Object (VBO)
|
|
||||||
glGenBuffers(1, &EBO);
|
|
||||||
|
|
||||||
glBindVertexArray(VAO); // 3. Bind the VAO
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 4. Bind the VBO
|
|
||||||
// 5. Copy vertex data into VBO's memory
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, cube.VBO_buffer.size() * sizeof(float), &cube.VBO_buffer.front(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// 6. Tell OpenGL how to interpret the vertex data
|
|
||||||
|
|
||||||
// Position Attribute
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
|
||||||
glEnableVertexAttribArray(0); // Enable the vertex attribute (location 0)
|
|
||||||
|
|
||||||
// Normal Attribute
|
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
|
|
||||||
// 6.5 Setup EBO
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, cube.EBO_buffer.size() * sizeof(unsigned int), &cube.EBO_buffer.front(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// Unbind VBO and VAO (optional, but good practice)
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
|
|
||||||
if (WIREFRAME_MODE)
|
if (WIREFRAME_MODE)
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
@ -294,27 +268,26 @@ int main() {
|
|||||||
|
|
||||||
view = camera.getView();
|
view = camera.getView();
|
||||||
|
|
||||||
|
shader.use();
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
glm::mat4 mvp = projection * view * model;
|
||||||
|
shader.setMat4("u_mvp", mvp);
|
||||||
|
|
||||||
// ---- PASS 1: Draw solid grey cubes ----
|
// ---- PASS 1: Draw solid grey cubes ----
|
||||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
glPolygonOffset(1.0, 1.0); // Push solid faces "back"
|
glPolygonOffset(1.0, 1.0); // Push solid faces "back"
|
||||||
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));
|
||||||
|
|
||||||
glm::vec3 solidColor = glm::vec3(0.5, 0.5, 0.5); // Grey
|
world.getMesh().draw();
|
||||||
for (glm::ivec3 voxel_pos : world.voxels) {
|
|
||||||
// [UPDATED] Pass the grey color
|
|
||||||
draw_cube(voxel_pos, shader, VAO, cube.EBO_buffer.size(), view, projection, solidColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
|
||||||
// ---- PASS 2: Draw wireframe on top ----
|
// ---- PASS 2: Draw wireframe on top ----
|
||||||
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));
|
||||||
|
|
||||||
glm::vec3 wireframeColor = glm::vec3(1.0, 1.0, 1.0); // White
|
world.getMesh().draw();
|
||||||
for (glm::ivec3 voxel_pos : world.voxels) {
|
|
||||||
// [UPDATED] Pass the white wireframe color
|
|
||||||
draw_cube(voxel_pos, shader, VAO, cube.EBO_buffer.size(), view, projection, wireframeColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 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);
|
||||||
@ -332,10 +305,6 @@ int main() {
|
|||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. --- Cleanup ---
|
|
||||||
glDeleteVertexArrays(1, &VAO);
|
|
||||||
glDeleteBuffers(1, &VBO);
|
|
||||||
|
|
||||||
glfwTerminate(); // Clean up GLFW
|
glfwTerminate(); // Clean up GLFW
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user