added world mesh
This commit is contained in:
parent
90c99734bf
commit
f6de6a6758
@ -20,6 +20,9 @@ add_executable(VoxelEngine
|
||||
src/Object3D.cpp
|
||||
src/Camera.h
|
||||
src/World.h
|
||||
src/World.cpp
|
||||
src/Mesh.h
|
||||
src/Mesh.cpp
|
||||
)
|
||||
|
||||
# --- Configure GLAD (from your src/ and include/ folders) ---
|
||||
@ -38,4 +41,4 @@ target_include_directories(VoxelEngine PUBLIC
|
||||
# 2. Tell CMake to link against the specific GLFW .lib file
|
||||
target_link_libraries(VoxelEngine PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/lib-vc2022/glfw3.lib
|
||||
)
|
||||
)
|
||||
|
||||
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 "Mesh.h"
|
||||
|
||||
// Hash function for glm::ivec3 to use with unordered_set
|
||||
namespace std {
|
||||
template <>
|
||||
@ -25,6 +27,15 @@ class World
|
||||
{
|
||||
public:
|
||||
std::unordered_set<glm::ivec3> voxels;
|
||||
|
||||
World();
|
||||
|
||||
void generateMesh();
|
||||
|
||||
Mesh& getMesh();
|
||||
|
||||
private:
|
||||
Mesh m_mesh;
|
||||
};
|
||||
|
||||
#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));
|
||||
|
||||
unsigned int VBO, VAO, EBO;
|
||||
glGenVertexArrays(1, &VAO); // 1. Create Vertex Array Object (VAO)
|
||||
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);
|
||||
std::cout << "Generating world mesh..." << std::endl;
|
||||
world.generateMesh();
|
||||
std::cout << "Mesh generated!" << std::endl;
|
||||
|
||||
if (WIREFRAME_MODE)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
@ -294,27 +268,26 @@ int main() {
|
||||
|
||||
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 ----
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(1.0, 1.0); // Push solid faces "back"
|
||||
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
|
||||
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);
|
||||
}
|
||||
world.getMesh().draw();
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
// ---- PASS 2: Draw wireframe on top ----
|
||||
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
|
||||
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);
|
||||
}
|
||||
world.getMesh().draw();
|
||||
|
||||
// --- Reset polygon mode for next frame (good practice) ---
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
@ -332,10 +305,6 @@ int main() {
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// 7. --- Cleanup ---
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
glfwTerminate(); // Clean up GLFW
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user