diff --git a/src/mesh.cpp b/src/mesh.cpp index 8ba29ab1..ce000229 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -2,56 +2,111 @@ #include "meshlite.h" #include -Mesh::Mesh(void *meshlite, int mesh_id) : - m_vertices(NULL), - m_vertexCount(0) +Mesh::Mesh(void *meshlite, int meshId) : + m_triangleVertices(NULL), + m_triangleVertexCount(0), + m_edgeVertices(NULL), + m_edgeVertexCount(0) { - int positionCount = meshlite_get_vertex_count(meshlite, mesh_id); - GLfloat *positions = new GLfloat[positionCount * 3]; - int loadedPositionItemCount = meshlite_get_vertex_position_array(meshlite, mesh_id, positions, positionCount * 3); + int edgeVertexPositionCount = meshlite_get_vertex_count(meshlite, meshId); + GLfloat *edgeVertexPositions = new GLfloat[edgeVertexPositionCount * 3]; + int loadedEdgeVertexPositionItemCount = meshlite_get_vertex_position_array(meshlite, meshId, edgeVertexPositions, edgeVertexPositionCount * 3); - int triangleCount = meshlite_get_face_count(meshlite, mesh_id); - int *triangleIndices = new int[triangleCount * 3]; - int loadedIndexItemCount = meshlite_get_triangle_index_array(meshlite, mesh_id, triangleIndices, triangleCount * 3); - GLfloat *normals = new GLfloat[triangleCount * 3]; - int loadedNormalItemCount = meshlite_get_triangle_normal_array(meshlite, mesh_id, normals, triangleCount * 3); + int edgeCount = meshlite_get_halfedge_count(meshlite, meshId); + int *edgeIndices = new int[edgeCount * 2]; + int loadedEdgeVertexIndexItemCount = meshlite_get_halfedge_index_array(meshlite, meshId, edgeIndices, edgeCount * 2); + GLfloat *edgeNormals = new GLfloat[edgeCount * 3]; + int loadedEdgeNormalItemCount = meshlite_get_halfedge_normal_array(meshlite, meshId, edgeNormals, edgeCount * 3); - m_vertexCount = triangleCount * 3; - m_vertices = new Vertex[m_vertexCount * 3]; - for (int i = 0; i < triangleCount; i++) { - int firstIndex = i * 3; - for (int j = 0; j < 3; j++) { - assert(firstIndex + j < loadedIndexItemCount); - int posIndex = triangleIndices[firstIndex + j] * 3; - assert(posIndex < loadedPositionItemCount); - Vertex *v = &m_vertices[firstIndex + j]; - v->posX = positions[posIndex + 0]; - v->posY = positions[posIndex + 1]; - v->posZ = positions[posIndex + 2]; - assert(firstIndex + 2 < loadedNormalItemCount); - v->normX = normals[firstIndex + 0]; - v->normY = normals[firstIndex + 1]; - v->normZ = normals[firstIndex + 2]; + m_edgeVertexCount = edgeCount * 2; + m_edgeVertices = new Vertex[m_edgeVertexCount * 3]; + for (int i = 0; i < edgeCount; i++) { + int firstIndex = i * 2; + for (int j = 0; j < 2; j++) { + assert(firstIndex + j < loadedEdgeVertexIndexItemCount); + int posIndex = edgeIndices[firstIndex + j] * 3; + assert(posIndex < loadedEdgeVertexPositionItemCount); + Vertex *v = &m_edgeVertices[firstIndex + j]; + v->posX = edgeVertexPositions[posIndex + 0]; + v->posY = edgeVertexPositions[posIndex + 1]; + v->posZ = edgeVertexPositions[posIndex + 2]; + assert(firstIndex + 2 < loadedEdgeNormalItemCount); + v->normX = edgeNormals[firstIndex + 0]; + v->normY = edgeNormals[firstIndex + 1]; + v->normZ = edgeNormals[firstIndex + 2]; + v->colorR = 0; + v->colorG = 0; + v->colorB = 0; } } - delete[] positions; + int triangleMesh = meshlite_triangulate(meshlite, meshId); + + int triangleVertexPositionCount = meshlite_get_vertex_count(meshlite, triangleMesh); + GLfloat *triangleVertexPositions = new GLfloat[triangleVertexPositionCount * 3]; + int loadedTriangleVertexPositionItemCount = meshlite_get_vertex_position_array(meshlite, triangleMesh, triangleVertexPositions, triangleVertexPositionCount * 3); + + int triangleCount = meshlite_get_face_count(meshlite, triangleMesh); + int *triangleIndices = new int[triangleCount * 3]; + int loadedTriangleVertexIndexItemCount = meshlite_get_triangle_index_array(meshlite, triangleMesh, triangleIndices, triangleCount * 3); + GLfloat *triangleNormals = new GLfloat[triangleCount * 3]; + int loadedTriangleNormalItemCount = meshlite_get_triangle_normal_array(meshlite, triangleMesh, triangleNormals, triangleCount * 3); + + m_triangleVertexCount = triangleCount * 3; + m_triangleVertices = new Vertex[m_triangleVertexCount * 3]; + for (int i = 0; i < triangleCount; i++) { + int firstIndex = i * 3; + for (int j = 0; j < 3; j++) { + assert(firstIndex + j < loadedTriangleVertexIndexItemCount); + int posIndex = triangleIndices[firstIndex + j] * 3; + assert(posIndex < loadedTriangleVertexPositionItemCount); + Vertex *v = &m_triangleVertices[firstIndex + j]; + v->posX = triangleVertexPositions[posIndex + 0]; + v->posY = triangleVertexPositions[posIndex + 1]; + v->posZ = triangleVertexPositions[posIndex + 2]; + assert(firstIndex + 2 < loadedTriangleNormalItemCount); + v->normX = triangleNormals[firstIndex + 0]; + v->normY = triangleNormals[firstIndex + 1]; + v->normZ = triangleNormals[firstIndex + 2]; + v->colorR = 1.0; + v->colorG = 1.0; + v->colorB = 1.0; + } + } + + delete[] triangleVertexPositions; delete[] triangleIndices; - delete[] normals; + delete[] triangleNormals; + + delete[] edgeVertexPositions; + delete[] edgeIndices; + delete[] edgeNormals; } Mesh::~Mesh() { - delete[] m_vertices; - m_vertexCount = 0; + delete[] m_triangleVertices; + m_triangleVertexCount = 0; } -Vertex *Mesh::vertices() +Vertex *Mesh::triangleVertices() { - return m_vertices; + return m_triangleVertices; } -int Mesh::vertexCount() +int Mesh::triangleVertexCount() { - return m_vertexCount; + return m_triangleVertexCount; } + +Vertex *Mesh::edgeVertices() +{ + return m_edgeVertices; +} + +int Mesh::edgeVertexCount() +{ + return m_edgeVertexCount; +} + + diff --git a/src/mesh.h b/src/mesh.h index 7606fd7f..f726368f 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -13,19 +13,26 @@ typedef struct GLfloat normX; GLfloat normY; GLfloat normZ; + GLfloat colorR; + GLfloat colorG; + GLfloat colorB; } Vertex; #pragma pack(pop) class Mesh { public: - Mesh(void *meshlite, int mesh_id); + Mesh(void *meshlite, int meshId); ~Mesh(); - Vertex *vertices(); - int vertexCount(); + Vertex *triangleVertices(); + int triangleVertexCount(); + Vertex *edgeVertices(); + int edgeVertexCount(); private: - Vertex *m_vertices; - int m_vertexCount; + Vertex *m_triangleVertices; + int m_triangleVertexCount; + Vertex *m_edgeVertices; + int m_edgeVertexCount; }; #endif diff --git a/src/modelingwidget.cpp b/src/modelingwidget.cpp index 6dc4a96d..ae351131 100644 --- a/src/modelingwidget.cpp +++ b/src/modelingwidget.cpp @@ -14,7 +14,8 @@ ModelingWidget::ModelingWidget(QWidget *parent) m_yRot(0), m_zRot(0), m_program(0), - m_renderVertexCount(0), + m_renderTriangleVertexCount(0), + m_renderEdgeVertexCount(0), m_mesh(NULL), m_meshUpdated(false) { @@ -24,6 +25,11 @@ ModelingWidget::ModelingWidget(QWidget *parent) if (m_transparent) { QSurfaceFormat fmt = format(); fmt.setAlphaBufferSize(8); + fmt.setSamples(4); + setFormat(fmt); + } else { + QSurfaceFormat fmt = format(); + fmt.setSamples(4); setFormat(fmt); } } @@ -77,8 +83,8 @@ void ModelingWidget::cleanup() if (m_program == nullptr) return; makeCurrent(); - if (m_modelVbo.isCreated()) - m_modelVbo.destroy(); + if (m_vboTriangle.isCreated()) + m_vboTriangle.destroy(); delete m_program; m_program = 0; doneCurrent(); @@ -88,14 +94,17 @@ static const char *vertexShaderSourceCore = "#version 150\n" "in vec4 vertex;\n" "in vec3 normal;\n" + "in vec3 color;\n" "out vec3 vert;\n" "out vec3 vertNormal;\n" + "out vec3 vertColor;\n" "uniform mat4 projMatrix;\n" "uniform mat4 mvMatrix;\n" "uniform mat3 normalMatrix;\n" "void main() {\n" " vert = vertex.xyz;\n" " vertNormal = normalMatrix * normal;\n" + " vertColor = color;\n" " gl_Position = projMatrix * mvMatrix * vertex;\n" "}\n"; @@ -103,12 +112,13 @@ static const char *fragmentShaderSourceCore = "#version 150\n" "in highp vec3 vert;\n" "in highp vec3 vertNormal;\n" + "in highp vec3 vertColor;\n" "out highp vec4 fragColor;\n" "uniform highp vec3 lightPos;\n" "void main() {\n" " highp vec3 L = normalize(lightPos - vert);\n" " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n" - " highp vec3 color = vec3(1.0, 1.0, 1.0);\n" + " highp vec3 color = vertColor;\n" " highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n" " fragColor = vec4(col, 1.0);\n" "}\n"; @@ -116,25 +126,29 @@ static const char *fragmentShaderSourceCore = static const char *vertexShaderSource = "attribute vec4 vertex;\n" "attribute vec3 normal;\n" + "attribute vec3 color;\n" "varying vec3 vert;\n" "varying vec3 vertNormal;\n" + "varying vec3 vertColor;\n" "uniform mat4 projMatrix;\n" "uniform mat4 mvMatrix;\n" "uniform mat3 normalMatrix;\n" "void main() {\n" " vert = vertex.xyz;\n" " vertNormal = normalMatrix * normal;\n" + " vertColor = color;\n" " gl_Position = projMatrix * mvMatrix * vertex;\n" "}\n"; static const char *fragmentShaderSource = "varying highp vec3 vert;\n" "varying highp vec3 vertNormal;\n" + "varying highp vec3 vertColor;\n" "uniform highp vec3 lightPos;\n" "void main() {\n" " highp vec3 L = normalize(lightPos - vert);\n" " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n" - " highp vec3 color = vec3(1.0, 1.0, 1.0);\n" + " highp vec3 color = vertColor;\n" " highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n" " gl_FragColor = vec4(col, 1.0);\n" "}\n"; @@ -159,6 +173,7 @@ void ModelingWidget::initializeGL() m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_core ? fragmentShaderSourceCore : fragmentShaderSource); m_program->bindAttributeLocation("vertex", 0); m_program->bindAttributeLocation("normal", 1); + m_program->bindAttributeLocation("color", 2); m_program->link(); m_program->bind(); @@ -171,11 +186,8 @@ void ModelingWidget::initializeGL() // implementations this is optional and support may not be present // at all. Nonetheless the below code works in all cases and makes // sure there is a VAO when one is needed. - m_vao.create(); - //QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); - - // Store the vertex attribute bindings for the program. - + m_vaoTriangle.create(); + m_vaoEdge.create(); // Our camera never changes in this example. m_camera.setToIdentity(); @@ -187,17 +199,6 @@ void ModelingWidget::initializeGL() m_program->release(); } -void ModelingWidget::setupVertexAttribs() -{ - m_modelVbo.bind(); - QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); - f->glEnableVertexAttribArray(0); - f->glEnableVertexAttribArray(1); - f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0); - f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast(3 * sizeof(GLfloat))); - m_modelVbo.release(); -} - void ModelingWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -209,22 +210,47 @@ void ModelingWidget::paintGL() m_world.rotate(m_yRot / 16.0f, 0, 1, 0); m_world.rotate(m_zRot / 16.0f, 0, 0, 1); - QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); - { QMutexLocker lock(&m_meshMutex); if (m_meshUpdated) { if (m_mesh) { - // Setup our vertex buffer object. - if (m_modelVbo.isCreated()) - m_modelVbo.destroy(); - m_modelVbo.create(); - m_modelVbo.bind(); - m_modelVbo.allocate(m_mesh->vertices(), m_mesh->vertexCount() * sizeof(Vertex)); - m_renderVertexCount = m_mesh->vertexCount(); - setupVertexAttribs(); + { + QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTriangle); + if (m_vboTriangle.isCreated()) + m_vboTriangle.destroy(); + m_vboTriangle.create(); + m_vboTriangle.bind(); + m_vboTriangle.allocate(m_mesh->triangleVertices(), m_mesh->triangleVertexCount() * sizeof(Vertex)); + m_renderTriangleVertexCount = m_mesh->triangleVertexCount(); + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + f->glEnableVertexAttribArray(0); + f->glEnableVertexAttribArray(1); + f->glEnableVertexAttribArray(2); + f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), 0); + f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast(3 * sizeof(GLfloat))); + f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast(6 * sizeof(GLfloat))); + m_vboTriangle.release(); + } + { + QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoEdge); + if (m_vboEdge.isCreated()) + m_vboEdge.destroy(); + m_vboEdge.create(); + m_vboEdge.bind(); + m_vboEdge.allocate(m_mesh->edgeVertices(), m_mesh->edgeVertexCount() * sizeof(Vertex)); + m_renderEdgeVertexCount = m_mesh->edgeVertexCount(); + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + f->glEnableVertexAttribArray(0); + f->glEnableVertexAttribArray(1); + f->glEnableVertexAttribArray(2); + f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), 0); + f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast(3 * sizeof(GLfloat))); + f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast(6 * sizeof(GLfloat))); + m_vboEdge.release(); + } } else { - m_renderVertexCount = 0; + m_renderTriangleVertexCount = 0; + m_renderEdgeVertexCount = 0; } m_meshUpdated = false; } @@ -236,8 +262,14 @@ void ModelingWidget::paintGL() QMatrix3x3 normalMatrix = m_world.normalMatrix(); m_program->setUniformValue(m_normalMatrixLoc, normalMatrix); - if (m_renderVertexCount > 0) - glDrawArrays(GL_TRIANGLES, 0, m_renderVertexCount); + if (m_renderEdgeVertexCount > 0) { + QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoEdge); + glDrawArrays(GL_LINES, 0, m_renderEdgeVertexCount); + } + if (m_renderTriangleVertexCount > 0) { + QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTriangle); + glDrawArrays(GL_TRIANGLES, 0, m_renderTriangleVertexCount); + } m_program->release(); } diff --git a/src/modelingwidget.h b/src/modelingwidget.h index 5704e672..fb06925c 100644 --- a/src/modelingwidget.h +++ b/src/modelingwidget.h @@ -43,16 +43,18 @@ protected: void mouseMoveEvent(QMouseEvent *event) override; private: - void setupVertexAttribs(); bool m_core; int m_xRot; int m_yRot; int m_zRot; QPoint m_lastPos; - QOpenGLVertexArrayObject m_vao; - QOpenGLBuffer m_modelVbo; + QOpenGLVertexArrayObject m_vaoTriangle; + QOpenGLBuffer m_vboTriangle; + QOpenGLVertexArrayObject m_vaoEdge; + QOpenGLBuffer m_vboEdge; QOpenGLShaderProgram *m_program; - int m_renderVertexCount; + int m_renderTriangleVertexCount; + int m_renderEdgeVertexCount; int m_projMatrixLoc; int m_mvMatrixLoc; int m_normalMatrixLoc; diff --git a/src/skeletontomesh.cpp b/src/skeletontomesh.cpp index 90a1ff0d..d00b6d6a 100644 --- a/src/skeletontomesh.cpp +++ b/src/skeletontomesh.cpp @@ -373,10 +373,8 @@ void SkeletonToMesh::process() int meshIdGeneratedFromExternal = makeMeshliteMeshFromExternal(context, unionPolyhedron); delete unionPolyhedron; - //int subdived = meshlite_subdivide(context, meshIdGeneratedFromCarve); - int triangulate = meshlite_triangulate(context, meshIdGeneratedFromExternal); - meshlite_export(context, triangulate, "/Users/jeremy/testlib.obj"); - m_mesh = new Mesh(context, triangulate); + meshlite_export(context, meshIdGeneratedFromExternal, "/Users/jeremy/testlib.obj"); + m_mesh = new Mesh(context, meshIdGeneratedFromExternal); } meshlite_destroy_context(context); emit finished();