mod_geo-tp/src/mesh_view.cpp

117 lines
3.7 KiB
C++

#include "mesh_view.h"
#include "util.h"
#include <QOpenGLContext>
#include <QOpenGLFunctions_2_1>
MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program)
:vertex_buffer(QOpenGLBuffer::VertexBuffer),
index_buffer(QOpenGLBuffer::IndexBuffer),
holes_index_buffer(QOpenGLBuffer::IndexBuffer),
n_faces(mesh.n_faces()),
n_vertices(mesh.n_vertices()),
mesh(mesh) {
QVector<GLfloat> vertices(n_vertices * 6);
size_t i = 0;
for (const VertexHandle it : mesh.vertices()) {
vertices[6*i + 0] = mesh.point(it)[0];
vertices[6*i + 1] = mesh.point(it)[1];
vertices[6*i + 2] = mesh.point(it)[2];
vertices[6*i + 3] = mesh.color(it)[0];
vertices[6*i + 4] = mesh.color(it)[1];
vertices[6*i + 5] = mesh.color(it)[2];
i++;
}
QVector<GLuint> indices(n_faces * 3);
i = 0;
for (const FaceHandle it : mesh.faces()) {
MyMesh::ConstFaceVertexIter it2 = mesh.cfv_begin(it);
indices[3 * i + 0] = it2->idx();
++it2;
indices[3 * i + 1] = it2->idx();
++it2;
indices[3 * i + 2] = it2->idx();
i++;
}
QVector<GLuint> holes_indices;
n_boundary_halfedges = 0;
for (std::vector<HalfedgeHandle> hole : mesh.holes) {
for (HalfedgeHandle it : hole) {
holes_indices.push_back(mesh.from_vertex_handle(it).idx());
holes_indices.push_back(mesh.to_vertex_handle(it).idx());
n_boundary_halfedges++;
}
}
vao.create();
{QOpenGLVertexArrayObject::Binder binder(&vao);
vertex_buffer.create();
vertex_buffer.bind();
vertex_buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
vertex_buffer.allocate(vertices.constData(), n_vertices * 6 * sizeof (GLfloat));
index_buffer.create();
index_buffer.bind();
index_buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
index_buffer.allocate(indices.constData(), n_faces * 3 * sizeof (GLuint));
holes_index_buffer.create();
holes_index_buffer.bind();
holes_index_buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
holes_index_buffer.allocate(holes_indices.constData(), n_boundary_halfedges * 2 * sizeof (GLuint));
vertex_buffer.bind();
program.setAttributeBuffer("pos", GL_FLOAT, 0,
3, 6 * sizeof (GLfloat));
program.enableAttributeArray("pos");
program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat),
3, 6 * sizeof (GLfloat));
program.enableAttributeArray("col");
}
}
MeshView::~MeshView() {
vertex_buffer.destroy();
index_buffer.destroy();
vao.destroy();
}
void MeshView::paint(QOpenGLShaderProgram &program) {
QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLExtraFunctions *glf = ctx->extraFunctions();
QOpenGLFunctions_2_1 *glf21 = nullptr;
glf21 = ctx->versionFunctions<QOpenGLFunctions_2_1>();
if (!glf21)
qFatal("Failed to get OpenGL 2.1 functions");
program.setUniformValue("model", mesh.transform);
// program.setUniformValue("col", mesh.color.redF(), mesh.color.greenF(), mesh.color.blueF());
{QOpenGLVertexArrayObject::Binder binder(&vao);
/* Mesh */
glf->glEnable(GL_POLYGON_OFFSET_FILL);
glf->glPolygonOffset(1.0, 2);
glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0);
glf->glDisable(GL_POLYGON_OFFSET_FILL);
program.setUniformValue("wireframe", 1);
/* Wireframe */
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glf->glDepthMask(GL_FALSE);
glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0);
glf->glDepthMask(GL_TRUE);
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
/* Holes */
program.setUniformValue("wf_col", QVector3D(1, 0, 1));
holes_index_buffer.bind();
glf->glDrawElements(GL_LINES, n_boundary_halfedges * 2, GL_UNSIGNED_INT, 0);
index_buffer.bind();
program.setUniformValue("wf_col", QVector3D(0, 0, 0));
program.setUniformValue("wireframe", 0);
}
}