sfw/render/mesh.cpp

188 lines
4.6 KiB
C++

#include "mesh.h"
#include "shader.h"
void Mesh::add_vertex2(float x, float y) {
vertices.push_back(x);
vertices.push_back(y);
}
void Mesh::add_vertex3(float x, float y, float z) {
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
}
void Mesh::add_normal(float x, float y, float z) {
normals.push_back(x);
normals.push_back(y);
normals.push_back(z);
}
void Mesh::add_color(float r, float g, float b, float a) {
colors.push_back(r);
colors.push_back(g);
colors.push_back(b);
colors.push_back(a);
}
void Mesh::add_uv(float u, float v) {
uvs.push_back(u);
uvs.push_back(v);
}
void Mesh::add_index(uint32_t index) {
indices.push_back(index);
}
void Mesh::add_triangle(uint32_t i1, uint32_t i2, uint32_t i3) {
indices.push_back(i1);
indices.push_back(i2);
indices.push_back(i3);
}
void Mesh::clear() {
vertices.clear();
normals.clear();
colors.clear();
uvs.clear();
indices.clear();
}
void Mesh::upload() {
if (vertices.size() == 0) {
return;
}
if (!VBO) {
glGenBuffers(1, &VBO);
}
vertices_vbo_size = sizeof(float) * vertices.size();
normals_vbo_size = sizeof(float) * normals.size();
colors_vbo_size = sizeof(float) * colors.size();
uvs_vbo_size = sizeof(float) * uvs.size();
indices_vbo_size = sizeof(float) * indices.size();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, &vertices[0]);
if (normals_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, &normals[0]);
}
if (colors_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, &colors[0]);
}
if (uvs_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, &uvs[0]);
}
if (indices_vbo_size > 0) {
if (!IBO) {
glGenBuffers(1, &IBO);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Mesh::destroy() {
if (VBO) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (IBO) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
}
void Mesh::render() {
if (vertices.size() == 0) {
return;
}
if (!Shader::current_shader) {
return;
}
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(Shader::ATTRIBUTE_POSITION, vertex_dimesions, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
if (normals_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, (void*)(vertices_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (colors_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_FALSE, 0, (void*)(vertices_vbo_size + normals_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (uvs_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_UV, 2, GL_FLOAT, GL_FALSE, 0, (void*)(vertices_vbo_size + normals_vbo_size + colors_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
if (indices_vbo_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (GLvoid*)0);
} else {
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
}
glDisableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
if (normals_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (colors_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (uvs_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
Mesh::Mesh() {
VBO = 0;
IBO = 0;
vertex_dimesions = 3;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
}
Mesh::Mesh(int vert_dim) {
VBO = 0;
IBO = 0;
vertex_dimesions = vert_dim;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
}
Mesh::~Mesh() {
destroy();
clear();
}