From d3e82ea306b52a5847f70cd75bb65476ccfdd0eb Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Mon, 12 Mar 2018 00:02:15 +0800 Subject: [PATCH] Add skeleton edit UI --- dust3d.pro | 12 ++ src/mainwindow.cpp | 50 +++++++-- src/mainwindow.h | 9 +- src/modelingwidget.cpp | 57 ++++++---- src/modelingwidget.h | 2 + src/skeletoneditedgeitem.cpp | 27 +++++ src/skeletoneditedgeitem.h | 17 +++ src/skeletoneditgraphicsview.cpp | 181 +++++++++++++++++++++++++++++++ src/skeletoneditgraphicsview.h | 39 +++++++ src/skeletoneditnodeitem.cpp | 39 +++++++ src/skeletoneditnodeitem.h | 19 ++++ src/skeletoneditwidget.cpp | 37 ++++--- src/skeletoneditwidget.h | 11 +- src/skeletontomesh.cpp | 34 ++++++ src/skeletontomesh.h | 23 ++++ 15 files changed, 509 insertions(+), 48 deletions(-) create mode 100644 src/skeletoneditedgeitem.cpp create mode 100644 src/skeletoneditedgeitem.h create mode 100644 src/skeletoneditgraphicsview.cpp create mode 100644 src/skeletoneditgraphicsview.h create mode 100644 src/skeletoneditnodeitem.cpp create mode 100644 src/skeletoneditnodeitem.h create mode 100644 src/skeletontomesh.cpp create mode 100644 src/skeletontomesh.h diff --git a/dust3d.pro b/dust3d.pro index e33ce2d3..e8a86142 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -12,6 +12,18 @@ HEADERS += src/modelingwidget.h SOURCES += src/skeletoneditwidget.cpp HEADERS += src/skeletoneditwidget.h +SOURCES += src/skeletoneditgraphicsview.cpp +HEADERS += src/skeletoneditgraphicsview.h + +SOURCES += src/skeletoneditnodeitem.cpp +HEADERS += src/skeletoneditnodeitem.h + +SOURCES += src/skeletoneditedgeitem.cpp +HEADERS += src/skeletoneditedgeitem.h + +SOURCES += src/skeletontomesh.cpp +HEADERS += src/skeletontomesh.h + SOURCES += src/mesh.cpp HEADERS += src/mesh.h diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cfd4dc6c..281d5906 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,10 +1,14 @@ -#include "mainwindow.h" -#include "skeletoneditwidget.h" #include #include #include #include #include +#include +#include +#include "mainwindow.h" +#include "skeletoneditwidget.h" +#include "meshlite.h" +#include "skeletontomesh.h" MainWindow::MainWindow() { @@ -36,14 +40,15 @@ MainWindow::MainWindow() motionButton->adjustSize(); modelButton->adjustSize(); - SkeletonEditWidget *skeletonEditWidget = new SkeletonEditWidget; - ModelingWidget *modelViewWidget = new ModelingWidget; - modelViewWidget->setFixedSize(128, 128); + m_skeletonEditWidget = new SkeletonEditWidget; + + m_modelingWidget = new ModelingWidget; + m_modelingWidget->setFixedSize(128, 128); QPushButton *changeTurnaroundButton = new QPushButton("Change turnaround.."); QVBoxLayout *rightLayout = new QVBoxLayout; - rightLayout->addWidget(modelViewWidget); + rightLayout->addWidget(m_modelingWidget); rightLayout->addSpacing(10); rightLayout->addWidget(changeTurnaroundButton); rightLayout->addStretch(); @@ -61,7 +66,7 @@ MainWindow::MainWindow() QHBoxLayout *middleLayout = new QHBoxLayout; middleLayout->addLayout(leftLayout); - middleLayout->addWidget(skeletonEditWidget); + middleLayout->addWidget(m_skeletonEditWidget); middleLayout->addLayout(rightLayout); QVBoxLayout *mainLayout = new QVBoxLayout; @@ -74,5 +79,36 @@ MainWindow::MainWindow() setCentralWidget(centralWidget); setWindowTitle(tr("Dust 3D")); + + bool connectResult; + + connectResult = connect(addAction, SIGNAL(triggered(bool)), m_skeletonEditWidget->graphicsView(), SLOT(turnOnAddNodeMode())); + assert(connectResult); + + connectResult = connectResult = connect(selectAction, SIGNAL(triggered(bool)), m_skeletonEditWidget->graphicsView(), SLOT(turnOffAddNodeMode())); + assert(connectResult); + + connectResult = connect(m_skeletonEditWidget->graphicsView(), SIGNAL(nodesChanged()), this, SLOT(skeletonChanged())); + assert(connectResult); } +void MainWindow::meshReady() +{ + SkeletonToMesh *worker = dynamic_cast(sender()); + if (worker) { + m_modelingWidget->updateMesh(worker->takeResultMesh()); + } +} + +void MainWindow::skeletonChanged() +{ + QThread *thread = new QThread; + SkeletonToMesh *worker = new SkeletonToMesh(m_skeletonEditWidget->graphicsView()); + worker->moveToThread(thread); + connect(thread, SIGNAL(started()), worker, SLOT(process())); + connect(worker, SIGNAL(finished()), thread, SLOT(quit())); + connect(worker, SIGNAL(finished()), this, SLOT(meshReady())); + connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + thread->start(); +} diff --git a/src/mainwindow.h b/src/mainwindow.h index 4996439c..66a0baa1 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -1,17 +1,20 @@ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H - #include #include "modelingwidget.h" +#include "skeletoneditwidget.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); - +public slots: + void skeletonChanged(); + void meshReady(); private: - ModelingWidget *modelingWidget; + ModelingWidget *m_modelingWidget; + SkeletonEditWidget *m_skeletonEditWidget; }; #endif diff --git a/src/modelingwidget.cpp b/src/modelingwidget.cpp index ee8ce472..432d088d 100644 --- a/src/modelingwidget.cpp +++ b/src/modelingwidget.cpp @@ -3,7 +3,6 @@ #include #include #include -#include "meshlite.h" // Modifed from http://doc.qt.io/qt-5/qtopengl-hellogl2-glwidget-cpp.html @@ -15,7 +14,9 @@ ModelingWidget::ModelingWidget(QWidget *parent) m_yRot(0), m_zRot(0), m_program(0), - m_mesh(NULL) + m_renderVertexCount(0), + m_mesh(NULL), + m_meshUpdated(false) { m_core = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile; // --transparent causes the clear color to be transparent. Therefore, on systems that @@ -25,16 +26,6 @@ ModelingWidget::ModelingWidget(QWidget *parent) fmt.setAlphaBufferSize(8); setFormat(fmt); } - - void *lite = meshlite_create_context(); - int first = meshlite_import(lite, "../assets/cube.obj"); - int second = meshlite_import(lite, "../assets/ball.obj"); - meshlite_scale(lite, first, 0.65); - int merged = meshlite_union(lite, first, second); - int triangulate = meshlite_triangulate(lite, merged); - //meshlite_export(lite, triangulate, "/Users/jeremy/testlib.obj"); - Mesh *mesh = new Mesh(lite, triangulate); - updateMesh(mesh); } ModelingWidget::~ModelingWidget() @@ -96,7 +87,8 @@ void ModelingWidget::cleanup() if (m_program == nullptr) return; makeCurrent(); - m_modelVbo.destroy(); + if (m_modelVbo.isCreated()) + m_modelVbo.destroy(); delete m_program; m_program = 0; doneCurrent(); @@ -169,7 +161,8 @@ void ModelingWidget::initializeGL() connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ModelingWidget::cleanup); initializeOpenGLFunctions(); - glClearColor(0.2078, 0.2078, 0.2078, m_transparent ? 0 : 1); + QColor bgcolor = QWidget::palette().color(QWidget::backgroundRole()); + glClearColor(bgcolor.redF(), bgcolor.greenF(), bgcolor.blueF(), m_transparent ? 0 : 1); m_program = new QOpenGLShaderProgram; m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_core ? vertexShaderSourceCore : vertexShaderSource); @@ -189,15 +182,10 @@ void ModelingWidget::initializeGL() // 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); - - // Setup our vertex buffer object. - m_modelVbo.create(); - m_modelVbo.bind(); - m_modelVbo.allocate(m_mesh->vertices(), m_mesh->vertexCount() * sizeof(Vertex)); + //QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); // Store the vertex attribute bindings for the program. - setupVertexAttribs(); + // Our camera never changes in this example. m_camera.setToIdentity(); @@ -232,13 +220,34 @@ void ModelingWidget::paintGL() 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(); + } else { + m_renderVertexCount = 0; + } + m_meshUpdated = false; + } + } + m_program->bind(); m_program->setUniformValue(m_projMatrixLoc, m_proj); m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world); QMatrix3x3 normalMatrix = m_world.normalMatrix(); m_program->setUniformValue(m_normalMatrixLoc, normalMatrix); - - glDrawArrays(GL_TRIANGLES, 0, m_mesh->vertexCount()); + + if (m_renderVertexCount > 0) + glDrawArrays(GL_TRIANGLES, 0, m_renderVertexCount); m_program->release(); } @@ -275,6 +284,8 @@ void ModelingWidget::updateMesh(Mesh *mesh) if (mesh != m_mesh) { delete m_mesh; m_mesh = mesh; + m_meshUpdated = true; + update(); } } diff --git a/src/modelingwidget.h b/src/modelingwidget.h index 5b4d47f1..371fd98d 100644 --- a/src/modelingwidget.h +++ b/src/modelingwidget.h @@ -55,6 +55,7 @@ private: QOpenGLVertexArrayObject m_vao; QOpenGLBuffer m_modelVbo; QOpenGLShaderProgram *m_program; + int m_renderVertexCount; int m_projMatrixLoc; int m_mvMatrixLoc; int m_normalMatrixLoc; @@ -66,6 +67,7 @@ private: Mesh *m_mesh; QMutex m_meshMutex; + bool m_meshUpdated; }; #endif diff --git a/src/skeletoneditedgeitem.cpp b/src/skeletoneditedgeitem.cpp new file mode 100644 index 00000000..993f41dd --- /dev/null +++ b/src/skeletoneditedgeitem.cpp @@ -0,0 +1,27 @@ +#include +#include "skeletoneditedgeitem.h" + +SkeletonEditEdgeItem::SkeletonEditEdgeItem(QGraphicsItem *parent) : + QGraphicsLineItem(parent), + m_firstNode(NULL), + m_secondNode(NULL) +{ + QPen pen(Qt::darkGray); + pen.setWidth(15); + setPen(pen); +} + +void SkeletonEditEdgeItem::setNodes(SkeletonEditNodeItem *first, SkeletonEditNodeItem *second) +{ + m_firstNode = first; + m_secondNode = second; + updatePosition(); +} + +void SkeletonEditEdgeItem::updatePosition() +{ + if (m_firstNode && m_secondNode) { + QLineF line(m_firstNode->origin(), m_secondNode->origin()); + setLine(line); + } +} diff --git a/src/skeletoneditedgeitem.h b/src/skeletoneditedgeitem.h new file mode 100644 index 00000000..d3cb203d --- /dev/null +++ b/src/skeletoneditedgeitem.h @@ -0,0 +1,17 @@ +#ifndef SKELETON_EDIT_EDGE_ITEM_H +#define SKELETON_EDIT_EDGE_ITEM_H +#include +#include "skeletoneditnodeitem.h" + +class SkeletonEditEdgeItem : public QGraphicsLineItem +{ +public: + SkeletonEditEdgeItem(QGraphicsItem *parent = 0); + void setNodes(SkeletonEditNodeItem *first, SkeletonEditNodeItem *second); + void updatePosition(); +private: + SkeletonEditNodeItem *m_firstNode; + SkeletonEditNodeItem *m_secondNode; +}; + +#endif diff --git a/src/skeletoneditgraphicsview.cpp b/src/skeletoneditgraphicsview.cpp new file mode 100644 index 00000000..8f7ea98d --- /dev/null +++ b/src/skeletoneditgraphicsview.cpp @@ -0,0 +1,181 @@ +#include +#include "skeletoneditgraphicsview.h" +#include "skeletoneditnodeitem.h" +#include "skeletoneditedgeitem.h" + +qreal SkeletonEditGraphicsView::m_initialNodeSize = 128; +qreal SkeletonEditGraphicsView::m_minimalNodeSize = 32; + +SkeletonEditGraphicsView::SkeletonEditGraphicsView(QWidget *parent) : + QGraphicsView(parent), + m_pendingNodeItem(NULL), + m_pendingEdgeItem(NULL), + m_inAddNodeMode(true), + m_nextStartNodeItem(NULL), + m_lastHoverNodeItem(NULL) +{ + setScene(new QGraphicsScene()); + + setMouseTracking(true); + + QImage image("../assets/male_werewolf_turnaround_lineart_by_jennette_brown.png"); + m_backgroundItem = new QGraphicsPixmapItem(QPixmap::fromImage(image)); + scene()->addItem(m_backgroundItem); + + m_pendingNodeItem = new QGraphicsEllipseItem(0, 0, m_initialNodeSize, m_initialNodeSize); + scene()->addItem(m_pendingNodeItem); + + m_pendingEdgeItem = new QGraphicsLineItem(0, 0, 0, 0); + scene()->addItem(m_pendingEdgeItem); + + applyAddNodeMode(); +} + +void SkeletonEditGraphicsView::toggleAddNodeMode() +{ + m_inAddNodeMode = !m_inAddNodeMode; + applyAddNodeMode(); +} + +void SkeletonEditGraphicsView::applyAddNodeMode() +{ + m_pendingNodeItem->setVisible(m_inAddNodeMode); + m_pendingEdgeItem->setVisible(m_inAddNodeMode); + setMouseTracking(true); +} + +void SkeletonEditGraphicsView::turnOffAddNodeMode() +{ + m_inAddNodeMode = false; + applyAddNodeMode(); +} + +void SkeletonEditGraphicsView::turnOnAddNodeMode() +{ + m_inAddNodeMode = true; + applyAddNodeMode(); +} + +SkeletonEditNodeItem *SkeletonEditGraphicsView::findNodeItemByPos(QPointF pos) +{ + QList::iterator it; + QList list = scene()->items(); + for (it = list.begin(); it != list.end(); ++it) { + SkeletonEditNodeItem *nodeItem = dynamic_cast(*it); + if (nodeItem) { + SkeletonEditNodeItem *nodeItem = (SkeletonEditNodeItem *)(*it); + if (nodeItem->rect().contains(pos)) { + return nodeItem; + } + } + } + return NULL; +} + +void SkeletonEditGraphicsView::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (!m_inAddNodeMode) { + if (m_lastHoverNodeItem) { + setNextStartNodeItem(m_lastHoverNodeItem); + m_lastHoverNodeItem = NULL; + } + } + } +} + +void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (m_inAddNodeMode) { + SkeletonEditNodeItem *newNode = new SkeletonEditNodeItem(m_pendingNodeItem->rect()); + scene()->addItem(newNode); + if (m_nextStartNodeItem) { + SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem(); + newEdge->setNodes(newNode, m_nextStartNodeItem); + scene()->addItem(newEdge); + } + setNextStartNodeItem(newNode); + emit nodesChanged(); + } + } else if (event->button() == Qt::RightButton) { + if (m_inAddNodeMode) { + toggleAddNodeMode(); + } + } +} + +void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event) +{ + QWidget::mouseMoveEvent(event); + QPointF pos = mapToScene(event->pos()); + QPointF moveTo = QPointF(pos.x() - m_pendingNodeItem->rect().width() / 2, pos.y() - m_pendingNodeItem->rect().height() / 2); + if (moveTo.x() < 0) + moveTo.setX(0); + if (moveTo.y() < 0) + moveTo.setY(0); + if (moveTo.x() + m_pendingNodeItem->rect().width() >= m_backgroundItem->boundingRect().width()) + moveTo.setX(m_backgroundItem->boundingRect().width() - m_pendingNodeItem->rect().width()); + if (moveTo.y() + m_pendingNodeItem->rect().height() >= m_backgroundItem->boundingRect().height()) + moveTo.setY(m_backgroundItem->boundingRect().height() - m_pendingNodeItem->rect().height()); + QSizeF oldSize = m_pendingNodeItem->rect().size(); + m_pendingNodeItem->setRect(moveTo.x(), moveTo.y(), + oldSize.width(), + oldSize.height()); + if (m_nextStartNodeItem) { + m_pendingEdgeItem->setLine(QLineF(m_nextStartNodeItem->origin(), QPointF(moveTo.x() + m_pendingNodeItem->rect().width() / 2, + moveTo.y() + m_pendingNodeItem->rect().height() / 2))); + } + if (!m_inAddNodeMode) { + SkeletonEditNodeItem *hoverNodeItem = findNodeItemByPos(pos); + if (hoverNodeItem) { + hoverNodeItem->setHighlighted(true); + } + if (hoverNodeItem != m_lastHoverNodeItem) { + if (m_lastHoverNodeItem) + m_lastHoverNodeItem->setHighlighted(false); + m_lastHoverNodeItem = hoverNodeItem; + } + } else { + if (m_lastHoverNodeItem) { + m_lastHoverNodeItem->setHighlighted(false); + m_lastHoverNodeItem = NULL; + } + } +} + +void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event) +{ + QWidget::wheelEvent(event); + qreal delta = event->delta(); + QSizeF oldSize = m_pendingNodeItem->rect().size(); + QPointF originPt = QPointF(m_pendingNodeItem->rect().left() + oldSize.width() / 2, + m_pendingNodeItem->rect().top() + oldSize.height() / 2); + QSizeF newSize = QSizeF(oldSize.width() + delta, oldSize.height() + delta); + if (newSize.width() < m_minimalNodeSize || newSize.height() < m_minimalNodeSize) { + newSize.setWidth(m_minimalNodeSize); + newSize.setHeight(m_minimalNodeSize); + } + QPointF newLeftTop = QPointF(originPt.x() - newSize.width() / 2, + originPt.y() - newSize.height() / 2); + if (newLeftTop.x() < 0 || newLeftTop.x() + newSize.width() >= m_backgroundItem->boundingRect().width()) + return; + if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height()) + return; + m_pendingNodeItem->setRect(newLeftTop.x(), + newLeftTop.y(), + newSize.width(), + newSize.height()); +} + +void SkeletonEditGraphicsView::setNextStartNodeItem(SkeletonEditNodeItem *item) +{ + if (m_nextStartNodeItem != item) { + if (m_nextStartNodeItem) + m_nextStartNodeItem->setIsNextStartNode(false); + } + m_nextStartNodeItem = item; + if (m_nextStartNodeItem) + m_nextStartNodeItem->setIsNextStartNode(true); +} + diff --git a/src/skeletoneditgraphicsview.h b/src/skeletoneditgraphicsview.h new file mode 100644 index 00000000..6b9e3f0a --- /dev/null +++ b/src/skeletoneditgraphicsview.h @@ -0,0 +1,39 @@ +#ifndef SKELETON_EDIT_GRAPHICS_VIEW_H +#define SKELETON_EDIT_GRAPHICS_VIEW_H +#include +#include +#include "skeletoneditnodeitem.h" +#include "skeletoneditedgeitem.h" + +class SkeletonEditGraphicsView : public QGraphicsView +{ + Q_OBJECT +signals: + void nodesChanged(); +public slots: + void turnOffAddNodeMode(); + void turnOnAddNodeMode(); +public: + SkeletonEditGraphicsView(QWidget *parent = 0); +protected: + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); +private: + QGraphicsPixmapItem *m_backgroundItem; + QGraphicsEllipseItem *m_pendingNodeItem; + QGraphicsLineItem *m_pendingEdgeItem; + static qreal m_initialNodeSize; + static qreal m_minimalNodeSize; + bool m_inAddNodeMode; + SkeletonEditNodeItem *m_nextStartNodeItem; + SkeletonEditNodeItem *m_lastHoverNodeItem; + void toggleAddNodeMode(); + void applyAddNodeMode(); + SkeletonEditNodeItem *findNodeItemByPos(QPointF pos); + void setNextStartNodeItem(SkeletonEditNodeItem *item); + +}; + +#endif diff --git a/src/skeletoneditnodeitem.cpp b/src/skeletoneditnodeitem.cpp new file mode 100644 index 00000000..084c35a4 --- /dev/null +++ b/src/skeletoneditnodeitem.cpp @@ -0,0 +1,39 @@ +#include +#include "skeletoneditnodeitem.h" + +SkeletonEditNodeItem::SkeletonEditNodeItem(const QRectF &rect, QGraphicsItem *parent) : + QGraphicsEllipseItem(rect, parent), + m_highlighted(false), + m_isNextStartNode(false) +{ + updateBorder(); +} + +QPointF SkeletonEditNodeItem::origin() +{ + return QPointF(rect().left() + rect().width() / 2, + rect().top() + rect().height() / 2); +} + +void SkeletonEditNodeItem::setHighlighted(bool highlighted) +{ + m_highlighted = highlighted; + if (m_highlighted) { + setBrush(QBrush(Qt::gray)); + } else { + setBrush(QBrush(Qt::transparent)); + } +} + +void SkeletonEditNodeItem::setIsNextStartNode(bool isNextStartNode) +{ + m_isNextStartNode = isNextStartNode; + updateBorder(); +} + +void SkeletonEditNodeItem::updateBorder() +{ + QPen pen(m_isNextStartNode ? Qt::black : Qt::darkGray); + pen.setWidth(15); + setPen(pen); +} diff --git a/src/skeletoneditnodeitem.h b/src/skeletoneditnodeitem.h new file mode 100644 index 00000000..dc231d35 --- /dev/null +++ b/src/skeletoneditnodeitem.h @@ -0,0 +1,19 @@ +#ifndef SKELETON_EDIT_NODE_ITEM_H +#define SKELETON_EDIT_NODE_ITEM_H +#include + +class SkeletonEditNodeItem : public QGraphicsEllipseItem +{ +public: + SkeletonEditNodeItem(const QRectF &rect, QGraphicsItem *parent = 0); + QPointF origin(); + void setHighlighted(bool highlited); + void setIsNextStartNode(bool isNextStartNode); +private: + bool m_highlighted; + bool m_isNextStartNode; + void updateBorder(); +}; + +#endif + diff --git a/src/skeletoneditwidget.cpp b/src/skeletoneditwidget.cpp index 9d72c60d..7fe88055 100644 --- a/src/skeletoneditwidget.cpp +++ b/src/skeletoneditwidget.cpp @@ -6,23 +6,34 @@ // Modifed from http://doc.qt.io/qt-5/qtwidgets-graphicsview-chip-view-cpp.html -SkeletonEditWidget::SkeletonEditWidget(QFrame *parent) - : QFrame(parent) +SkeletonEditWidget::SkeletonEditWidget(QFrame *parent) : + QFrame(parent) { - //setFrameStyle(Sunken | StyledPanel); + m_graphicsView = new SkeletonEditGraphicsView(this); + m_graphicsView->setRenderHint(QPainter::Antialiasing, false); + m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - graphicsView = new QGraphicsView(this); - graphicsView->setRenderHint(QPainter::Antialiasing, false); - - scene = new QGraphicsScene(); - graphicsView->setScene(scene); - - QImage image("../assets/male_werewolf_turnaround_lineart_by_jennette_brown.png"); - QGraphicsPixmapItem *backgroundItem = new QGraphicsPixmapItem(QPixmap::fromImage(image)); - scene->addItem(backgroundItem); + m_graphicsView->setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern)); QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(graphicsView, 0, 0, 1, 1); + mainLayout->addWidget(m_graphicsView, 0, 0, 1, 1); setLayout(mainLayout); } + +SkeletonEditGraphicsView *SkeletonEditWidget::graphicsView() +{ + return m_graphicsView; +} + +void SkeletonEditWidget::resizeEvent(QResizeEvent *event) +{ + QFrame::resizeEvent(event); + m_graphicsView->fitInView(QRectF(0, 0, m_graphicsView->scene()->width(), m_graphicsView->scene()->height()), Qt::KeepAspectRatio); +} + +void SkeletonEditWidget::mouseMoveEvent(QMouseEvent *event) +{ + QFrame::mouseMoveEvent(event); +} diff --git a/src/skeletoneditwidget.h b/src/skeletoneditwidget.h index 771c345b..d28a37cf 100644 --- a/src/skeletoneditwidget.h +++ b/src/skeletoneditwidget.h @@ -3,15 +3,22 @@ #include #include #include +#include +#include +#include +#include "skeletoneditgraphicsview.h" class SkeletonEditWidget : public QFrame { Q_OBJECT public: SkeletonEditWidget(QFrame *parent = 0); + SkeletonEditGraphicsView *graphicsView(); +protected: + void resizeEvent(QResizeEvent *event); + void mouseMoveEvent(QMouseEvent *event); private: - QGraphicsView *graphicsView; - QGraphicsScene *scene; + SkeletonEditGraphicsView *m_graphicsView; }; #endif diff --git a/src/skeletontomesh.cpp b/src/skeletontomesh.cpp new file mode 100644 index 00000000..2ac8b5e0 --- /dev/null +++ b/src/skeletontomesh.cpp @@ -0,0 +1,34 @@ +#include "skeletontomesh.h" +#include "meshlite.h" + +// Modified from https://wiki.qt.io/QThreads_general_usage + +SkeletonToMesh::SkeletonToMesh(SkeletonEditGraphicsView *graphicsView) : + m_mesh(NULL) +{ +} + +SkeletonToMesh::~SkeletonToMesh() +{ + delete m_mesh; +} + +Mesh *SkeletonToMesh::takeResultMesh() +{ + Mesh *mesh = m_mesh; + m_mesh = NULL; + return mesh; +} + +void SkeletonToMesh::process() +{ + void *lite = meshlite_create_context(); + int first = meshlite_import(lite, "../assets/cube.obj"); + int second = meshlite_import(lite, "../assets/ball.obj"); + meshlite_scale(lite, first, 0.65); + int merged = meshlite_union(lite, first, second); + int triangulate = meshlite_triangulate(lite, merged); + //meshlite_export(lite, triangulate, "/Users/jeremy/testlib.obj"); + m_mesh = new Mesh(lite, triangulate); + emit finished(); +} diff --git a/src/skeletontomesh.h b/src/skeletontomesh.h new file mode 100644 index 00000000..cb2ac951 --- /dev/null +++ b/src/skeletontomesh.h @@ -0,0 +1,23 @@ +#ifndef SKELETON_TO_MESH_H +#define SKELETON_TO_MESH_H +#include +#include +#include "skeletoneditgraphicsview.h" +#include "mesh.h" + +class SkeletonToMesh : public QObject +{ + Q_OBJECT +public: + SkeletonToMesh(SkeletonEditGraphicsView *graphicsView); + ~SkeletonToMesh(); + Mesh *takeResultMesh(); +signals: + void finished(); +public slots: + void process(); +private: + Mesh *m_mesh; +}; + +#endif