rcpp_framework/rendering/opengl/mesh.cpp

179 lines
4.6 KiB
C++

#include "mesh.h"
#include "shader.h"
void Mesh::add_vertex2(GLfloat x, GLfloat y) {
vertices.push_back(x);
vertices.push_back(y);
}
void Mesh::add_vertex3(GLfloat x, GLfloat y, GLfloat z) {
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
}
void Mesh::add_normal(GLfloat x, GLfloat y, GLfloat z) {
normals.push_back(x);
normals.push_back(y);
normals.push_back(z);
}
void Mesh::add_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
colors.push_back(r);
colors.push_back(g);
colors.push_back(b);
colors.push_back(a);
}
void Mesh::add_uv(GLfloat u, GLfloat v) {
uvs.push_back(u);
uvs.push_back(v);
}
void Mesh::add_index(GLuint index) {
indices.push_back(index);
}
void Mesh::add_triangle(GLuint i1, GLuint i2, GLuint 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(GLfloat) * vertices.size();
normals_vbo_size = sizeof(GLfloat) * normals.size();
colors_vbo_size = sizeof(GLfloat) * colors.size();
uvs_vbo_size = sizeof(GLfloat) * uvs.size();
indices_vbo_size = sizeof(GLfloat) * indices.size();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, 0, 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_ARRAY_BUFFER, 0);
}
void Mesh::destroy() {
if (VBO) {
glDeleteBuffers(1, &VBO);
}
if (IBO) {
glDeleteBuffers(1, &IBO);
}
}
void Mesh::render() {
if (vertices.size() == 0 || !VBO)
return;
if (!Shader::current_shader)
return;
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(Shader::ATTRIBUTE_POSITION, vertex_dimensions, 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_dimensions = 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_dimensions = 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();
}