#include "gfx/mesh_gpu.h" #include namespace fn::gfx { MeshGpu mesh_gpu_upload(const Mesh& mesh) { MeshGpu g{}; if (mesh.positions.empty() || mesh.indices.empty()) return g; if (mesh.normals.size() != mesh.positions.size()) return g; const size_t nverts = mesh.positions.size() / 3; // Interleave pos.xyz + normal.xyz, stride 6 floats. std::vector interleaved; interleaved.resize(nverts * 6); for (size_t i = 0; i < nverts; ++i) { interleaved[i*6 + 0] = mesh.positions[i*3 + 0]; interleaved[i*6 + 1] = mesh.positions[i*3 + 1]; interleaved[i*6 + 2] = mesh.positions[i*3 + 2]; interleaved[i*6 + 3] = mesh.normals[i*3 + 0]; interleaved[i*6 + 4] = mesh.normals[i*3 + 1]; interleaved[i*6 + 5] = mesh.normals[i*3 + 2]; } glGenVertexArrays(1, &g.vao); glGenBuffers(1, &g.vbo); glGenBuffers(1, &g.ebo); glBindVertexArray(g.vao); glBindBuffer(GL_ARRAY_BUFFER, g.vbo); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(interleaved.size() * sizeof(float)), interleaved.data(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g.ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(mesh.indices.size() * sizeof(uint32_t)), mesh.indices.data(), GL_STATIC_DRAW); // location 0 = a_pos (vec3) glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (GLsizei)(6 * sizeof(float)), (const void*)0); // location 1 = a_normal (vec3) glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (GLsizei)(6 * sizeof(float)), (const void*)(3 * sizeof(float))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); g.index_count = (int)mesh.indices.size(); return g; } void mesh_gpu_destroy(MeshGpu& g) { if (g.ebo) { glDeleteBuffers(1, &g.ebo); g.ebo = 0; } if (g.vbo) { glDeleteBuffers(1, &g.vbo); g.vbo = 0; } if (g.vao) { glDeleteVertexArrays(1, &g.vao); g.vao = 0; } g.index_count = 0; } } // namespace fn::gfx