use an element buffer for rendering
This commit is contained in:
parent
e56eed0a16
commit
b3d4899546
@ -21,7 +21,7 @@ int main(int argc, char *argv[]) {
|
|||||||
QObject::connect(mesh_viewer, &MeshViewer::initialized,
|
QObject::connect(mesh_viewer, &MeshViewer::initialized,
|
||||||
[&]() {
|
[&]() {
|
||||||
if (mesh_processor) {
|
if (mesh_processor) {
|
||||||
mesh_viewer->addMesh(mesh_processor->mesh);
|
mesh_viewer->addMesh(*mesh_processor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -34,11 +34,11 @@ int main(int argc, char *argv[]) {
|
|||||||
QObject::connect(&main_window, &MainWindow::open,
|
QObject::connect(&main_window, &MainWindow::open,
|
||||||
[&](const QString &path) {
|
[&](const QString &path) {
|
||||||
if (mesh_processor) {
|
if (mesh_processor) {
|
||||||
mesh_viewer->removeMesh(mesh_processor->mesh);
|
mesh_viewer->removeMesh(*mesh_processor);
|
||||||
delete mesh_processor;
|
delete mesh_processor;
|
||||||
}
|
}
|
||||||
mesh_processor = new MeshProcessor(path);
|
mesh_processor = new MeshProcessor(path);
|
||||||
mesh_viewer->addMesh(mesh_processor->mesh);
|
mesh_viewer->addMesh(*mesh_processor);
|
||||||
});
|
});
|
||||||
main_window.show();
|
main_window.show();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -28,30 +28,11 @@ MeshProcessor::MeshProcessor(const QString &path) {
|
|||||||
qWarning() << "Failed to read" << path;
|
qWarning() << "Failed to read" << path;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const VertexHandle &vh : mesh.vertices()) {
|
|
||||||
mesh.set_color(vh, MyMesh::Color(0, 0, 0));
|
|
||||||
}
|
|
||||||
holes = findHoles(mesh);
|
holes = findHoles(mesh);
|
||||||
highlightHoles();
|
|
||||||
fillHoles();
|
fillHoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setHoleBoundaryColor(MyMesh &mesh,
|
|
||||||
const HalfedgeHandle &hole,
|
|
||||||
MyMesh::Color color) {
|
|
||||||
for (HalfedgeHandle it : HalfedgeLoopRange(mesh, hole)) {
|
|
||||||
mesh.set_color(mesh.to_vertex_handle(it), color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshProcessor::highlightHoles() {
|
|
||||||
for (auto hole : holes) {
|
|
||||||
setHoleBoundaryColor(mesh, hole, {1, 0, 0});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void fillHoleDumb(MyMesh &mesh, HalfedgeHandle &hole) {
|
void fillHoleDumb(MyMesh &mesh, HalfedgeHandle &hole) {
|
||||||
mesh.request_vertex_status();
|
mesh.request_vertex_status();
|
||||||
mesh.request_edge_status();
|
mesh.request_edge_status();
|
||||||
|
@ -10,17 +10,13 @@
|
|||||||
class MeshProcessor : public QObject {
|
class MeshProcessor : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
std::vector<HalfedgeHandle> holes;
|
|
||||||
|
|
||||||
// friend class MeshProcessorPainter;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyMesh mesh;
|
MyMesh mesh;
|
||||||
|
std::vector<HalfedgeHandle> holes;
|
||||||
|
|
||||||
MeshProcessor(const QString &path);
|
MeshProcessor(const QString &path);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void highlightHoles();
|
|
||||||
void fillHoles();
|
void fillHoles();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,32 +1,49 @@
|
|||||||
#include "mesh_view.h"
|
#include "mesh_view.h"
|
||||||
|
#include "util.h"
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QOpenGLFunctions_2_1>
|
#include <QOpenGLFunctions_2_1>
|
||||||
|
|
||||||
|
|
||||||
MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program)
|
MeshView::MeshView(const MeshProcessor &mesh_processor, QOpenGLShaderProgram &program)
|
||||||
: buffer(QOpenGLBuffer::VertexBuffer),
|
:vertex_buffer(QOpenGLBuffer::VertexBuffer),
|
||||||
nverts(mesh.n_faces() * 3),
|
index_buffer(QOpenGLBuffer::IndexBuffer),
|
||||||
mesh(mesh) {
|
n_faces(mesh_processor.mesh.n_faces()),
|
||||||
QVector<GLfloat> verts(nverts * 6);
|
n_vertices(mesh_processor.mesh.n_vertices()),
|
||||||
|
mesh_processor(mesh_processor) {
|
||||||
|
const MyMesh &mesh = mesh_processor.mesh;
|
||||||
|
QVector<GLfloat> vertices(n_vertices * 6);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const FaceHandle face : mesh.faces()) {
|
for (const VertexHandle it : mesh.vertices()) {
|
||||||
for (const VertexHandle vec : mesh.fv_range(face)) {
|
vertices[6*i + 0] = mesh.point(it)[0];
|
||||||
verts[6*i + 0] = mesh.point(vec)[0];
|
vertices[6*i + 1] = mesh.point(it)[1];
|
||||||
verts[6*i + 1] = mesh.point(vec)[1];
|
vertices[6*i + 2] = mesh.point(it)[2];
|
||||||
verts[6*i + 2] = mesh.point(vec)[2];
|
vertices[6*i + 3] = mesh.color.red();
|
||||||
verts[6*i + 3] = mesh.color.red();
|
vertices[6*i + 4] = mesh.color.green();
|
||||||
verts[6*i + 4] = mesh.color.green();
|
vertices[6*i + 5] = mesh.color.blue();
|
||||||
verts[6*i + 5] = mesh.color.blue();
|
|
||||||
i++;
|
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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
vao.create();
|
vao.create();
|
||||||
{QOpenGLVertexArrayObject::Binder binder(&vao);
|
{QOpenGLVertexArrayObject::Binder binder(&vao);
|
||||||
buffer.create();
|
vertex_buffer.create();
|
||||||
buffer.bind();
|
vertex_buffer.bind();
|
||||||
buffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
|
vertex_buffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
|
||||||
buffer.allocate(verts.constData(), nverts * 6 * sizeof (GLfloat));
|
vertex_buffer.allocate(vertices.constData(), n_vertices * 6 * sizeof (GLfloat));
|
||||||
|
index_buffer.create();
|
||||||
|
index_buffer.bind();
|
||||||
|
index_buffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
|
||||||
|
index_buffer.allocate(indices.constData(), n_faces * 3 * sizeof (GLuint));
|
||||||
program.setAttributeBuffer("pos", GL_FLOAT, 0, 3, 6 * sizeof (GLfloat));
|
program.setAttributeBuffer("pos", GL_FLOAT, 0, 3, 6 * sizeof (GLfloat));
|
||||||
program.enableAttributeArray("pos");
|
program.enableAttributeArray("pos");
|
||||||
program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat), 3, 6 * sizeof (GLfloat));
|
program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat), 3, 6 * sizeof (GLfloat));
|
||||||
@ -36,12 +53,14 @@ MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program)
|
|||||||
|
|
||||||
|
|
||||||
MeshView::~MeshView() {
|
MeshView::~MeshView() {
|
||||||
|
vertex_buffer.destroy();
|
||||||
|
index_buffer.destroy();
|
||||||
vao.destroy();
|
vao.destroy();
|
||||||
buffer.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MeshView::paint(QOpenGLShaderProgram &program) {
|
void MeshView::paint(QOpenGLShaderProgram &program) {
|
||||||
|
const MyMesh &mesh = mesh_processor.mesh;
|
||||||
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||||
QOpenGLExtraFunctions *glf = ctx->extraFunctions();
|
QOpenGLExtraFunctions *glf = ctx->extraFunctions();
|
||||||
|
|
||||||
@ -56,15 +75,25 @@ void MeshView::paint(QOpenGLShaderProgram &program) {
|
|||||||
/* Mesh */
|
/* Mesh */
|
||||||
glf->glEnable(GL_POLYGON_OFFSET_FILL);
|
glf->glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
glf->glPolygonOffset(1.0, 2);
|
glf->glPolygonOffset(1.0, 2);
|
||||||
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
|
glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0);
|
||||||
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
glf->glDisable(GL_POLYGON_OFFSET_FILL);
|
glf->glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
|
||||||
/* Wireframe */
|
/* Wireframe */
|
||||||
program.setUniformValue("wireframe", 1);
|
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
|
|
||||||
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
glf->glLineWidth(2);
|
glf->glLineWidth(2);
|
||||||
|
program.setUniformValue("wireframe", 1);
|
||||||
|
glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0);
|
||||||
|
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
program.setUniformValue("wireframe", 0);
|
program.setUniformValue("wireframe", 0);
|
||||||
|
|
||||||
|
// program.setUniformValue("wf_col", QVector3D(1, 0, 1));
|
||||||
|
// for (HalfedgeHandle hole : mesh_processor.holes) {
|
||||||
|
// for (HalfedgeHandle it : ConstHalfedgeLoopRange(mesh, hole)) {
|
||||||
|
// int v0 = mesh.from_vertex_handle(it).idx();
|
||||||
|
// int v1 = mesh.to_vertex_handle(it).idx();
|
||||||
|
// glf->glDrawArrays(GL_LINES, std::min(v0, v1), std::max(v0, v1));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// program.setUniformValue("wf_col", QVector3D(0, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef MESH_VIEW_H
|
#ifndef MESH_VIEW_H
|
||||||
#define MESH_VIEW_H
|
#define MESH_VIEW_H
|
||||||
|
|
||||||
#include "my_mesh.h"
|
#include "mesh_processor.h"
|
||||||
#include <QOpenGLExtraFunctions>
|
#include <QOpenGLExtraFunctions>
|
||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
#include <QOpenGLVertexArrayObject>
|
#include <QOpenGLVertexArrayObject>
|
||||||
@ -10,13 +10,15 @@
|
|||||||
|
|
||||||
class MeshView {
|
class MeshView {
|
||||||
QOpenGLVertexArrayObject vao;
|
QOpenGLVertexArrayObject vao;
|
||||||
QOpenGLBuffer buffer;
|
QOpenGLBuffer vertex_buffer;
|
||||||
size_t nverts;
|
QOpenGLBuffer index_buffer;
|
||||||
|
unsigned n_faces;
|
||||||
|
unsigned n_vertices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const MyMesh &mesh;
|
const MeshProcessor &mesh_processor;
|
||||||
|
|
||||||
MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program);
|
MeshView(const MeshProcessor &mesh_processor, QOpenGLShaderProgram &program);
|
||||||
~MeshView();
|
~MeshView();
|
||||||
void paint(QOpenGLShaderProgram &program);
|
void paint(QOpenGLShaderProgram &program);
|
||||||
};
|
};
|
||||||
|
@ -83,19 +83,19 @@ void MeshViewer::paintGL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MeshViewer::addMesh(const MyMesh &mesh) {
|
void MeshViewer::addMesh(const MeshProcessor &mesh_processor) {
|
||||||
Q_ASSERT(isValid());
|
Q_ASSERT(isValid());
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
meshes.emplace_back(mesh, program);
|
meshes.emplace_back(mesh_processor, program);
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MeshViewer::removeMesh(const MyMesh &mesh) {
|
void MeshViewer::removeMesh(const MeshProcessor &mesh_processor) {
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
meshes.remove_if([&](const MeshView &mv) {
|
meshes.remove_if([&](const MeshView &mv) {
|
||||||
return &mv.mesh == &mesh;
|
return &mv.mesh_processor == &mesh_processor;
|
||||||
});
|
});
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
update();
|
update();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define MESH_VIEWER_H
|
#define MESH_VIEWER_H
|
||||||
|
|
||||||
#define GL_GLEXT_PROTOTYPES
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#include "my_mesh.h"
|
#include "mesh_processor.h"
|
||||||
#include "mesh_view.h"
|
#include "mesh_view.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
@ -39,8 +39,8 @@ public:
|
|||||||
void paintGL() override;
|
void paintGL() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void addMesh(const MyMesh &mesh);
|
void addMesh(const MeshProcessor &mesh);
|
||||||
void removeMesh(const MyMesh &mesh);
|
void removeMesh(const MeshProcessor &mesh);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void mousePressEvent(QMouseEvent *e);
|
virtual void mousePressEvent(QMouseEvent *e);
|
||||||
|
@ -2,21 +2,21 @@
|
|||||||
#define MY_MESH_H
|
#define MY_MESH_H
|
||||||
|
|
||||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
|
||||||
|
|
||||||
struct MyTraits : public OpenMesh::DefaultTraits {
|
struct MyTraits : public OpenMesh::DefaultTraits {
|
||||||
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color);
|
VertexAttributes(OpenMesh::Attributes::Normal);
|
||||||
HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);
|
HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);
|
||||||
FaceAttributes(OpenMesh::Attributes::Normal);
|
FaceAttributes(OpenMesh::Attributes::Normal);
|
||||||
EdgeAttributes(OpenMesh::Attributes::Color);
|
EdgeAttributes(OpenMesh::Attributes::Color);
|
||||||
typedef OpenMesh::Vec3f Color;
|
typedef OpenMesh::Vec3f Color;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyMesh : public OpenMesh::PolyMesh_ArrayKernelT<MyTraits> {
|
class MyMesh : public OpenMesh::TriMesh_ArrayKernelT<MyTraits> {
|
||||||
public:
|
public:
|
||||||
QMatrix4x4 transform;
|
QMatrix4x4 transform;
|
||||||
QColor color;
|
QColor color;
|
||||||
|
30
src/util.h
30
src/util.h
@ -1,23 +1,39 @@
|
|||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
#include "my_mesh.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Mesh>
|
||||||
class HalfedgeLoopRange {
|
class HalfedgeLoopRange {
|
||||||
MyMesh &mesh;
|
Mesh &mesh;
|
||||||
const HalfedgeHandle &start;
|
const typename Mesh::HalfedgeHandle &start;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HalfedgeLoopRange(MyMesh &mesh, const HalfedgeHandle &start)
|
HalfedgeLoopRange(Mesh &mesh, const typename Mesh::HalfedgeHandle &start)
|
||||||
:mesh(mesh), start(start) {}
|
:mesh(mesh), start(start) {}
|
||||||
MyMesh::HalfedgeLoopIter begin() {
|
typename Mesh::HalfedgeLoopIter begin() {
|
||||||
return mesh.hl_begin(start);
|
return mesh.hl_begin(start);
|
||||||
}
|
}
|
||||||
MyMesh::HalfedgeLoopIter end() {
|
typename Mesh::HalfedgeLoopIter end() {
|
||||||
return mesh.hl_end(start);
|
return mesh.hl_end(start);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Mesh>
|
||||||
|
class ConstHalfedgeLoopRange {
|
||||||
|
Mesh &mesh;
|
||||||
|
const typename Mesh::HalfedgeHandle &start;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConstHalfedgeLoopRange(Mesh &mesh, const typename Mesh::HalfedgeHandle &start)
|
||||||
|
:mesh(mesh), start(start) {}
|
||||||
|
typename Mesh::HalfedgeLoopIter begin() {
|
||||||
|
return mesh.chl_begin(start);
|
||||||
|
}
|
||||||
|
typename Mesh::HalfedgeLoopIter end() {
|
||||||
|
return mesh.chl_end(start);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user