From b99e0db0b2ac8982d4767b713592ba42ac8666e5 Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Mon, 2 Apr 2018 14:05:06 +0800 Subject: [PATCH] Seperate the shader program and mesh binder to seperated source files --- dust3d.pro | 6 ++ src/modelmeshbinder.cpp | 122 +++++++++++++++++++++++++ src/modelmeshbinder.h | 31 +++++++ src/modelshaderprogram.cpp | 101 ++++++++++++++++++++ src/modelshaderprogram.h | 20 ++++ src/modelwidget.cpp | 183 +++---------------------------------- src/modelwidget.h | 24 +---- 7 files changed, 297 insertions(+), 190 deletions(-) create mode 100644 src/modelmeshbinder.cpp create mode 100644 src/modelmeshbinder.h create mode 100644 src/modelshaderprogram.cpp create mode 100644 src/modelshaderprogram.h diff --git a/dust3d.pro b/dust3d.pro index 689d43c7..3ac8c55b 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -7,6 +7,12 @@ INCLUDEPATH += src SOURCES += src/mainwindow.cpp HEADERS += src/mainwindow.h +SOURCES += src/modelshaderprogram.cpp +HEADERS += src/modelshaderprogram.h + +SOURCES += src/modelmeshbinder.cpp +HEADERS += src/modelmeshbinder.h + SOURCES += src/modelwidget.cpp HEADERS += src/modelwidget.h diff --git a/src/modelmeshbinder.cpp b/src/modelmeshbinder.cpp new file mode 100644 index 00000000..f414336c --- /dev/null +++ b/src/modelmeshbinder.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include "modelmeshbinder.h" +#include "ds3file.h" + +ModelMeshBinder::ModelMeshBinder() : + m_renderTriangleVertexCount(0), + m_renderEdgeVertexCount(0), + m_mesh(NULL), + m_meshUpdated(false) +{ +} + +ModelMeshBinder::~ModelMeshBinder() +{ + delete m_mesh; +} + +void ModelMeshBinder::updateMesh(Mesh *mesh) +{ + QMutexLocker lock(&m_meshMutex); + if (mesh != m_mesh) { + delete m_mesh; + m_mesh = mesh; + m_meshUpdated = true; + } +} + +void ModelMeshBinder::exportMeshAsObj(const QString &filename) +{ + QMutexLocker lock(&m_meshMutex); + if (m_mesh) { + QFile file(filename); + if (file.open(QIODevice::WriteOnly)) { + QTextStream stream(&file); + stream << "# " << Ds3FileReader::m_applicationName << endl; + for (std::vector::iterator it = m_mesh->vertices().begin() ; it != m_mesh->vertices().end(); ++it) { + stream << "v " << (*it).x() << " " << (*it).y() << " " << (*it).z() << endl; + } + for (std::vector>::iterator it = m_mesh->faces().begin() ; it != m_mesh->faces().end(); ++it) { + stream << "f"; + for (std::vector::iterator subIt = (*it).begin() ; subIt != (*it).end(); ++subIt) { + stream << " " << (1 + *subIt); + } + stream << endl; + } + } + } +} + +void ModelMeshBinder::initialize() +{ + m_vaoTriangle.create(); + m_vaoEdge.create(); +} + +void ModelMeshBinder::paint() +{ + { + QMutexLocker lock(&m_meshMutex); + if (m_meshUpdated) { + if (m_mesh) { + { + 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_renderTriangleVertexCount = 0; + m_renderEdgeVertexCount = 0; + } + m_meshUpdated = false; + } + } + + 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); + } +} + +void ModelMeshBinder::cleanup() +{ + if (m_vboTriangle.isCreated()) + m_vboTriangle.destroy(); + if (m_vboEdge.isCreated()) + m_vboEdge.destroy(); +} diff --git a/src/modelmeshbinder.h b/src/modelmeshbinder.h new file mode 100644 index 00000000..3cf036d3 --- /dev/null +++ b/src/modelmeshbinder.h @@ -0,0 +1,31 @@ +#ifndef MODEL_MESH_BINDER_H +#define MODEL_MESH_BINDER_H +#include +#include +#include +#include +#include "mesh.h" + +class ModelMeshBinder +{ +public: + ModelMeshBinder(); + ~ModelMeshBinder(); + void updateMesh(Mesh *mesh); + void exportMeshAsObj(const QString &filename); + void initialize(); + void paint(); + void cleanup(); +private: + QOpenGLVertexArrayObject m_vaoTriangle; + QOpenGLBuffer m_vboTriangle; + QOpenGLVertexArrayObject m_vaoEdge; + QOpenGLBuffer m_vboEdge; + Mesh *m_mesh; + QMutex m_meshMutex; + int m_renderTriangleVertexCount; + int m_renderEdgeVertexCount; + bool m_meshUpdated; +}; + +#endif diff --git a/src/modelshaderprogram.cpp b/src/modelshaderprogram.cpp new file mode 100644 index 00000000..91931195 --- /dev/null +++ b/src/modelshaderprogram.cpp @@ -0,0 +1,101 @@ +#include +#include "modelshaderprogram.h" + +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"; + +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 = 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"; + +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 = 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"; + +ModelShaderProgram::ModelShaderProgram() +{ + this->addShaderFromSourceCode(QOpenGLShader::Vertex, QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile ? vertexShaderSourceCore : vertexShaderSource); + this->addShaderFromSourceCode(QOpenGLShader::Fragment, QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile ? fragmentShaderSourceCore : fragmentShaderSource); + this->bindAttributeLocation("vertex", 0); + this->bindAttributeLocation("normal", 1); + this->bindAttributeLocation("color", 2); + this->link(); + + this->bind(); + m_projMatrixLoc = this->uniformLocation("projMatrix"); + m_mvMatrixLoc = this->uniformLocation("mvMatrix"); + m_normalMatrixLoc = this->uniformLocation("normalMatrix"); + m_lightPosLoc = this->uniformLocation("lightPos"); +} + +int ModelShaderProgram::projMatrixLoc() +{ + return m_projMatrixLoc; +} + +int ModelShaderProgram::mvMatrixLoc() +{ + return m_mvMatrixLoc; +} + +int ModelShaderProgram::normalMatrixLoc() +{ + return m_normalMatrixLoc; +} + +int ModelShaderProgram::lightPosLoc() +{ + return m_lightPosLoc; +} diff --git a/src/modelshaderprogram.h b/src/modelshaderprogram.h new file mode 100644 index 00000000..42e2f779 --- /dev/null +++ b/src/modelshaderprogram.h @@ -0,0 +1,20 @@ +#ifndef MODEL_SHADER_PROGRAM_H +#define MODEL_SHADER_PROGRAM_H +#include + +class ModelShaderProgram : public QOpenGLShaderProgram +{ +public: + ModelShaderProgram(); + int projMatrixLoc(); + int mvMatrixLoc(); + int normalMatrixLoc(); + int lightPosLoc(); +private: + int m_projMatrixLoc; + int m_mvMatrixLoc; + int m_normalMatrixLoc; + int m_lightPosLoc; +}; + +#endif \ No newline at end of file diff --git a/src/modelwidget.cpp b/src/modelwidget.cpp index 0208f5dd..511a2ab4 100644 --- a/src/modelwidget.cpp +++ b/src/modelwidget.cpp @@ -16,15 +16,10 @@ ModelWidget::ModelWidget(QWidget *parent) m_xRot(0), m_yRot(0), m_zRot(0), - m_program(0), - m_renderTriangleVertexCount(0), - m_renderEdgeVertexCount(0), - m_mesh(NULL), - m_meshUpdated(false), + m_program(NULL), m_moveStarted(false), m_graphicsView(NULL) { - m_core = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile; // --transparent causes the clear color to be transparent. Therefore, on systems that // support it, the widget will become transparent apart from the logo. if (m_transparent) { @@ -49,7 +44,6 @@ void ModelWidget::setGraphicsView(SkeletonEditGraphicsView *view) ModelWidget::~ModelWidget() { cleanup(); - delete m_mesh; } static void qNormalizeAngle(int &angle) @@ -95,76 +89,12 @@ void ModelWidget::cleanup() if (m_program == nullptr) return; makeCurrent(); - if (m_vboTriangle.isCreated()) - m_vboTriangle.destroy(); + m_meshBinder.cleanup(); delete m_program; m_program = 0; doneCurrent(); } -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"; - -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 = 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"; - -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 = 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"; - void ModelWidget::initializeGL() { // In this example the widget's corresponding top-level window can change @@ -184,33 +114,20 @@ void ModelWidget::initializeGL() glClearColor(bgcolor.redF(), bgcolor.greenF(), bgcolor.blueF(), 1); } - m_program = new QOpenGLShaderProgram; - m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_core ? vertexShaderSourceCore : vertexShaderSource); - 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(); - m_projMatrixLoc = m_program->uniformLocation("projMatrix"); - m_mvMatrixLoc = m_program->uniformLocation("mvMatrix"); - m_normalMatrixLoc = m_program->uniformLocation("normalMatrix"); - m_lightPosLoc = m_program->uniformLocation("lightPos"); - + m_program = new ModelShaderProgram; + // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x // 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_vaoTriangle.create(); - m_vaoEdge.create(); + m_meshBinder.initialize(); // Our camera never changes in this example. m_camera.setToIdentity(); m_camera.translate(0, 0, -2.5); // Light position is fixed. - m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70)); + m_program->setUniformValue(m_program->lightPosLoc(), QVector3D(0, 0, 70)); m_program->release(); } @@ -227,66 +144,14 @@ void ModelWidget::paintGL() m_world.rotate(m_yRot / 16.0f, 0, 1, 0); m_world.rotate(m_zRot / 16.0f, 0, 0, 1); - { - QMutexLocker lock(&m_meshMutex); - if (m_meshUpdated) { - if (m_mesh) { - { - 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_renderTriangleVertexCount = 0; - m_renderEdgeVertexCount = 0; - } - m_meshUpdated = false; - } - } m_program->bind(); - m_program->setUniformValue(m_projMatrixLoc, m_proj); - m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world); + m_program->setUniformValue(m_program->projMatrixLoc(), m_proj); + m_program->setUniformValue(m_program->mvMatrixLoc(), m_camera * m_world); QMatrix3x3 normalMatrix = m_world.normalMatrix(); - m_program->setUniformValue(m_normalMatrixLoc, normalMatrix); + m_program->setUniformValue(m_program->normalMatrixLoc(), normalMatrix); - 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_meshBinder.paint(); m_program->release(); } @@ -365,33 +230,11 @@ void ModelWidget::wheelEvent(QWheelEvent *event) void ModelWidget::updateMesh(Mesh *mesh) { - QMutexLocker lock(&m_meshMutex); - if (mesh != m_mesh) { - delete m_mesh; - m_mesh = mesh; - m_meshUpdated = true; - update(); - } + m_meshBinder.updateMesh(mesh); + update(); } void ModelWidget::exportMeshAsObj(const QString &filename) { - QMutexLocker lock(&m_meshMutex); - if (m_mesh) { - QFile file(filename); - if (file.open(QIODevice::WriteOnly)) { - QTextStream stream(&file); - stream << "# " << Ds3FileReader::m_applicationName << endl; - for (std::vector::iterator it = m_mesh->vertices().begin() ; it != m_mesh->vertices().end(); ++it) { - stream << "v " << (*it).x() << " " << (*it).y() << " " << (*it).z() << endl; - } - for (std::vector>::iterator it = m_mesh->faces().begin() ; it != m_mesh->faces().end(); ++it) { - stream << "f"; - for (std::vector::iterator subIt = (*it).begin() ; subIt != (*it).end(); ++subIt) { - stream << " " << (1 + *subIt); - } - stream << endl; - } - } - } + m_meshBinder.exportMeshAsObj(filename); } diff --git a/src/modelwidget.h b/src/modelwidget.h index e8fe2c40..a7c35366 100644 --- a/src/modelwidget.h +++ b/src/modelwidget.h @@ -1,6 +1,5 @@ #ifndef MODEL_WIDGET_H #define MODEL_WIDGET_H - #include #include #include @@ -9,8 +8,8 @@ #include #include #include "mesh.h" - -QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) +#include "modelshaderprogram.h" +#include "modelmeshbinder.h" class SkeletonEditGraphicsView; @@ -49,34 +48,19 @@ protected: void wheelEvent(QWheelEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; private: - bool m_core; int m_xRot; int m_yRot; int m_zRot; QPoint m_lastPos; - QOpenGLVertexArrayObject m_vaoTriangle; - QOpenGLBuffer m_vboTriangle; - QOpenGLVertexArrayObject m_vaoEdge; - QOpenGLBuffer m_vboEdge; - QOpenGLShaderProgram *m_program; - int m_renderTriangleVertexCount; - int m_renderEdgeVertexCount; - int m_projMatrixLoc; - int m_mvMatrixLoc; - int m_normalMatrixLoc; - int m_lightPosLoc; + ModelMeshBinder m_meshBinder; + ModelShaderProgram *m_program; QMatrix4x4 m_proj; QMatrix4x4 m_camera; QMatrix4x4 m_world; static bool m_transparent; - - Mesh *m_mesh; - QMutex m_meshMutex; - bool m_meshUpdated; bool m_moveStarted; QPoint m_moveStartPos; QRect m_moveStartGeometry; - SkeletonEditGraphicsView *m_graphicsView; };