diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index 374332f7..76c9dd02 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -49,13 +49,6 @@ #include "fileforever.h" #include "documentsaver.h" -int DocumentWindow::m_modelRenderWidgetInitialX = 16; -int DocumentWindow::m_modelRenderWidgetInitialY = 16; -int DocumentWindow::m_modelRenderWidgetInitialSize = 128; -int DocumentWindow::m_skeletonRenderWidgetInitialX = DocumentWindow::m_modelRenderWidgetInitialX + DocumentWindow::m_modelRenderWidgetInitialSize + 16; -int DocumentWindow::m_skeletonRenderWidgetInitialY = DocumentWindow::m_modelRenderWidgetInitialY; -int DocumentWindow::m_skeletonRenderWidgetInitialSize = DocumentWindow::m_modelRenderWidgetInitialSize; - int DocumentWindow::m_autoRecovered = false; LogBrowser *g_logBrowser = nullptr; @@ -327,14 +320,19 @@ DocumentWindow::DocumentWindow() : //connect(containerWidget, &GraphicsContainerWidget::containerSizeChanged, this, &DocumentWindow::updateInfoWidgetPosition); m_modelRenderWidget = new ModelWidget(containerWidget); + m_modelRenderWidget->setMoveAndZoomByWindow(false); + m_modelRenderWidget->move(0, 0); m_modelRenderWidget->setAttribute(Qt::WA_TransparentForMouseEvents); - m_modelRenderWidget->setMinimumSize(DocumentWindow::m_modelRenderWidgetInitialSize, DocumentWindow::m_modelRenderWidgetInitialSize); - m_modelRenderWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY); m_modelRenderWidget->setMousePickRadius(m_document->mousePickRadius()); if (!Preferences::instance().toonShading()) m_modelRenderWidget->toggleWireframe(); m_modelRenderWidget->enableEnvironmentLight(); + m_modelRenderWidget->disableCullFace(); + m_modelRenderWidget->setEyePosition(QVector3D(0.0, 0.0, -4.0)); + m_modelRenderWidget->setMoveToPosition(QVector3D(-0.5, -0.5, 0.0)); + + connect(containerWidget, &GraphicsContainerWidget::containerSizeChanged, + m_modelRenderWidget, &ModelWidget::canvasResized); connect(m_modelRenderWidget, &ModelWidget::mouseRayChanged, m_document, [=](const QVector3D &nearPosition, const QVector3D &farPosition) { @@ -752,18 +750,18 @@ DocumentWindow::DocumentWindow() : m_viewMenu = menuBar()->addMenu(tr("&View")); - auto isModelSitInVisibleArea = [](ModelWidget *modelWidget) { - QRect parentRect = QRect(QPoint(0, 0), modelWidget->parentWidget()->size()); - return parentRect.contains(modelWidget->geometry().center()); - }; + //auto isModelSitInVisibleArea = [](ModelWidget *modelWidget) { + // QRect parentRect = QRect(QPoint(0, 0), modelWidget->parentWidget()->size()); + // return parentRect.contains(modelWidget->geometry().center()); + //}; - m_resetModelWidgetPosAction = new QAction(tr("Show Model"), this); - connect(m_resetModelWidgetPosAction, &QAction::triggered, [=]() { - if (!isModelSitInVisibleArea(m_modelRenderWidget)) { - m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY); - } - }); - m_viewMenu->addAction(m_resetModelWidgetPosAction); + //m_resetModelWidgetPosAction = new QAction(tr("Show Model"), this); + //connect(m_resetModelWidgetPosAction, &QAction::triggered, [=]() { + // if (!isModelSitInVisibleArea(m_modelRenderWidget)) { + // m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY); + // } + //}); + //m_viewMenu->addAction(m_resetModelWidgetPosAction); m_toggleWireframeAction = new QAction(tr("Toggle Wireframe"), this); connect(m_toggleWireframeAction, &QAction::triggered, [=]() { @@ -800,9 +798,9 @@ DocumentWindow::DocumentWindow() : }); m_viewMenu->addAction(m_toggleUvCheckAction); - connect(m_viewMenu, &QMenu::aboutToShow, [=]() { - m_resetModelWidgetPosAction->setEnabled(!isModelSitInVisibleArea(m_modelRenderWidget)); - }); + //connect(m_viewMenu, &QMenu::aboutToShow, [=]() { + // m_resetModelWidgetPosAction->setEnabled(!isModelSitInVisibleArea(m_modelRenderWidget)); + //}); m_windowMenu = menuBar()->addMenu(tr("&Window")); @@ -2160,6 +2158,11 @@ void DocumentWindow::exportImageToFilename(const QString &filename) offlineRender->setYRotation(m_modelRenderWidget->yRot()); offlineRender->setZRotation(m_modelRenderWidget->zRot()); offlineRender->setEyePosition(m_modelRenderWidget->eyePosition()); + offlineRender->setMoveToPosition(m_modelRenderWidget->moveToPosition()); + if (m_modelRenderWidget->isWireframeVisible()) + offlineRender->enableWireframe(); + if (m_modelRenderWidget->isEnvironmentLightEnabled()) + offlineRender->enableEnvironmentLight(); offlineRender->setRenderPurpose(0); QImage *normalMap = new QImage(); QImage *depthMap = new QImage(); diff --git a/src/documentwindow.h b/src/documentwindow.h index c2fa077a..5f9fe1a2 100644 --- a/src/documentwindow.h +++ b/src/documentwindow.h @@ -180,7 +180,7 @@ private: QAction *m_colorizeAsAutoAction; QMenu *m_viewMenu; - QAction *m_resetModelWidgetPosAction; + //QAction *m_resetModelWidgetPosAction; QAction *m_toggleWireframeAction; QAction *m_toggleUvCheckAction; QAction *m_toggleRotationAction; @@ -220,12 +220,6 @@ private: AutoSaver *m_autoSaver = nullptr; public: - static int m_modelRenderWidgetInitialX; - static int m_modelRenderWidgetInitialY; - static int m_modelRenderWidgetInitialSize; - static int m_skeletonRenderWidgetInitialX; - static int m_skeletonRenderWidgetInitialY; - static int m_skeletonRenderWidgetInitialSize; static int m_autoRecovered; }; diff --git a/src/modelmeshbinder.cpp b/src/modelmeshbinder.cpp index f4acf7eb..eed1db79 100644 --- a/src/modelmeshbinder.cpp +++ b/src/modelmeshbinder.cpp @@ -68,6 +68,11 @@ void ModelMeshBinder::enableEnvironmentLight() m_environmentLightEnabled = true; } +bool ModelMeshBinder::isEnvironmentLightEnabled() +{ + return m_environmentLightEnabled; +} + Model *ModelMeshBinder::fetchCurrentMesh() { QMutexLocker lock(&m_meshMutex); @@ -262,7 +267,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) program->setUniformValue(program->environmentSpecularMapIdLoc(), 4); program->setUniformValue(program->toonNormalMapIdLoc(), 5); program->setUniformValue(program->toonDepthMapIdLoc(), 6); - if (m_showWireframes) { + if (m_showWireframe) { if (m_renderEdgeVertexCount > 0) { QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoEdge); QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); @@ -392,19 +397,19 @@ void ModelMeshBinder::cleanup() m_toonDepthMap = nullptr; } -void ModelMeshBinder::showWireframes() +void ModelMeshBinder::showWireframe() { - m_showWireframes = true; + m_showWireframe = true; } -void ModelMeshBinder::hideWireframes() +void ModelMeshBinder::hideWireframe() { - m_showWireframes = false; + m_showWireframe = false; } -bool ModelMeshBinder::isWireframesVisible() +bool ModelMeshBinder::isWireframeVisible() { - return m_showWireframes; + return m_showWireframe; } void ModelMeshBinder::enableCheckUv() diff --git a/src/modelmeshbinder.h b/src/modelmeshbinder.h index f616bc78..f6783366 100644 --- a/src/modelmeshbinder.h +++ b/src/modelmeshbinder.h @@ -18,12 +18,13 @@ public: void initialize(); void paint(ModelShaderProgram *program); void cleanup(); - void showWireframes(); - void hideWireframes(); - bool isWireframesVisible(); + void showWireframe(); + void hideWireframe(); + bool isWireframeVisible(); void enableCheckUv(); void disableCheckUv(); void enableEnvironmentLight(); + bool isEnvironmentLightEnabled(); bool isCheckUvEnabled(); void reloadMesh(); void fetchCurrentToonNormalAndDepthMaps(QImage *normalMap, QImage *depthMap); @@ -35,7 +36,7 @@ private: int m_renderEdgeVertexCount = 0; int m_renderToolVertexCount = 0; bool m_newMeshComing = false; - bool m_showWireframes = false; + bool m_showWireframe = false; bool m_hasTexture = false; QOpenGLTexture *m_texture = nullptr; bool m_hasNormalMap = false; diff --git a/src/modeloffscreenrender.cpp b/src/modeloffscreenrender.cpp index 5ca76708..10bf2524 100644 --- a/src/modeloffscreenrender.cpp +++ b/src/modeloffscreenrender.cpp @@ -58,6 +58,16 @@ void ModelOffscreenRender::setEyePosition(const QVector3D &eyePosition) m_eyePosition = eyePosition; } +void ModelOffscreenRender::setMoveToPosition(const QVector3D &moveToPosition) +{ + m_moveToPosition = moveToPosition; +} + +void ModelOffscreenRender::enableWireframe() +{ + m_isWireframeVisible = true; +} + void ModelOffscreenRender::setRenderPurpose(int purpose) { m_renderPurpose = purpose; @@ -68,6 +78,11 @@ void ModelOffscreenRender::setToonShading(bool toonShading) m_toonShading = toonShading; } +void ModelOffscreenRender::enableEnvironmentLight() +{ + m_isEnvironmentLightEnabled = true; +} + void ModelOffscreenRender::updateToonNormalAndDepthMaps(QImage *normalMap, QImage *depthMap) { delete m_normalMap; @@ -124,7 +139,12 @@ QImage ModelOffscreenRender::toImage(const QSize &size) ModelShaderProgram *program = new ModelShaderProgram(isCoreProfile); ModelMeshBinder meshBinder; meshBinder.initialize(); - meshBinder.hideWireframes(); + if (m_isWireframeVisible) + meshBinder.showWireframe(); + else + meshBinder.hideWireframe(); + if (m_isEnvironmentLightEnabled) + meshBinder.enableEnvironmentLight(); if (nullptr != m_normalMap && nullptr != m_depthMap) { meshBinder.updateToonNormalAndDepthMaps(m_normalMap, m_depthMap); m_normalMap = nullptr; @@ -135,7 +155,7 @@ QImage ModelOffscreenRender::toImage(const QSize &size) m_context->functions()->glEnable(GL_BLEND); m_context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); m_context->functions()->glEnable(GL_DEPTH_TEST); - m_context->functions()->glEnable(GL_CULL_FACE); + //m_context->functions()->glEnable(GL_CULL_FACE); #ifdef GL_LINE_SMOOTH m_context->functions()->glEnable(GL_LINE_SMOOTH); #endif @@ -146,6 +166,7 @@ QImage ModelOffscreenRender::toImage(const QSize &size) world.rotate(m_zRot / 16.0f, 0, 0, 1); projection.setToIdentity(); + projection.translate(m_moveToPosition.x(), m_moveToPosition.y(), m_moveToPosition.z()); projection.perspective(45.0f, GLfloat(size.width()) / size.height(), 0.01f, 100.0f); camera.setToIdentity(); diff --git a/src/modeloffscreenrender.h b/src/modeloffscreenrender.h index 6850146d..730af718 100644 --- a/src/modeloffscreenrender.h +++ b/src/modeloffscreenrender.h @@ -20,8 +20,11 @@ public: void setYRotation(int angle); void setZRotation(int angle); void setEyePosition(const QVector3D &eyePosition); + void setMoveToPosition(const QVector3D &moveToPosition); void setRenderPurpose(int purpose); void setRenderThread(QThread *thread); + void enableWireframe(); + void enableEnvironmentLight(); void updateMesh(Model *mesh); void updateToonNormalAndDepthMaps(QImage *normalMap, QImage *depthMap); void setToonShading(bool toonShading); @@ -31,6 +34,7 @@ private: int m_yRot = 0; int m_zRot = 0; QVector3D m_eyePosition; + QVector3D m_moveToPosition; int m_renderPurpose = 0; QOpenGLContext *m_context = nullptr; QOpenGLFramebufferObject *m_renderFbo = nullptr; @@ -38,6 +42,8 @@ private: QImage *m_normalMap = nullptr; QImage *m_depthMap = nullptr; bool m_toonShading = false; + bool m_isWireframeVisible = false; + bool m_isEnvironmentLightEnabled = false; }; #endif diff --git a/src/modelwidget.cpp b/src/modelwidget.cpp index 8bf5591b..7caa4733 100644 --- a/src/modelwidget.cpp +++ b/src/modelwidget.cpp @@ -61,6 +61,18 @@ const QVector3D &ModelWidget::eyePosition() return m_eyePosition; } +const QVector3D &ModelWidget::moveToPosition() +{ + return m_moveToPosition; +} + +void ModelWidget::setEyePosition(const QVector3D &eyePosition) +{ + m_eyePosition = eyePosition; + emit eyePositionChanged(m_eyePosition); + update(); +} + void ModelWidget::reRender() { emit renderParametersChanged(); @@ -174,13 +186,24 @@ void ModelWidget::initializeGL() m_program->release(); } +void ModelWidget::disableCullFace() +{ + m_enableCullFace = false; +} + +void ModelWidget::setMoveToPosition(const QVector3D &moveToPosition) +{ + m_moveToPosition = moveToPosition; +} + void ModelWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); + if (m_enableCullFace) + glEnable(GL_CULL_FACE); #ifdef GL_LINE_SMOOTH glEnable(GL_LINE_SMOOTH); #endif @@ -227,12 +250,18 @@ void ModelWidget::paintGL() m_program->release(); } +void ModelWidget::updateProjectionMatrix() +{ + m_projection.setToIdentity(); + m_projection.translate(m_moveToPosition.x(), m_moveToPosition.y(), m_moveToPosition.z()); + m_projection.perspective(45.0f, GLfloat(width()) / height(), 0.01f, 100.0f); +} + void ModelWidget::resizeGL(int w, int h) { m_widthInPixels = w * window()->devicePixelRatio(); m_heightInPixels = h * window()->devicePixelRatio(); - m_projection.setToIdentity(); - m_projection.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f); + updateProjectionMatrix(); emit renderParametersChanged(); } @@ -251,19 +280,29 @@ std::pair ModelWidget::screenPositionToMouseRay(const QPoi void ModelWidget::toggleWireframe() { - if (m_meshBinder.isWireframesVisible()) - m_meshBinder.hideWireframes(); + if (m_meshBinder.isWireframeVisible()) + m_meshBinder.hideWireframe(); else - m_meshBinder.showWireframes(); + m_meshBinder.showWireframe(); update(); } +bool ModelWidget::isWireframeVisible() +{ + return m_meshBinder.isWireframeVisible(); +} + void ModelWidget::enableEnvironmentLight() { m_meshBinder.enableEnvironmentLight(); update(); } +bool ModelWidget::isEnvironmentLightEnabled() +{ + return m_meshBinder.isEnvironmentLightEnabled(); +} + void ModelWidget::toggleRotation() { if (nullptr != m_rotationTimer) { @@ -329,6 +368,11 @@ bool ModelWidget::inputMouseReleaseEventFromOtherWidget(QMouseEvent *event) return false; } +void ModelWidget::canvasResized() +{ + resize(parentWidget()->size()); +} + bool ModelWidget::inputMouseMoveEventFromOtherWidget(QMouseEvent *event) { QPoint pos = convertInputPosFromOtherWidget(event); @@ -349,10 +393,27 @@ bool ModelWidget::inputMouseMoveEventFromOtherWidget(QMouseEvent *event) (m_moveStarted && (event->buttons() & Qt::LeftButton))) { if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) { if (m_moveStarted) { - QRect rect = m_moveStartGeometry; - QPoint posInParent = mapToParent(pos); - rect.translate(posInParent.x() - m_moveStartPos.x(), posInParent.y() - m_moveStartPos.y()); - setGeometry(rect); + if (m_moveAndZoomByWindow) { + QPoint posInParent = mapToParent(pos); + QRect rect = m_moveStartGeometry; + rect.translate(posInParent.x() - m_moveStartPos.x(), posInParent.y() - m_moveStartPos.y()); + setGeometry(rect); + } else { + m_moveToPosition.setX(m_moveToPosition.x() + (float)2 * dx / width()); + m_moveToPosition.setY(m_moveToPosition.y() + (float)2 * -dy / height()); + if (m_moveToPosition.x() < -1.0) + m_moveToPosition.setX(-1.0); + if (m_moveToPosition.x() > 1.0) + m_moveToPosition.setX(1.0); + if (m_moveToPosition.y() < -1.0) + m_moveToPosition.setY(-1.0); + if (m_moveToPosition.y() > 1.0) + m_moveToPosition.setY(1.0); + updateProjectionMatrix(); + emit moveToPositionChanged(m_moveToPosition); + emit renderParametersChanged(); + update(); + } } } else { setXRotation(m_xRot + 8 * dy); @@ -394,22 +455,34 @@ bool ModelWidget::inputWheelEventFromOtherWidget(QWheelEvent *event) void ModelWidget::zoom(float delta) { - QMargins margins(delta, delta, delta, delta); - if (0 == m_modelInitialHeight) { - m_modelInitialHeight = height(); - } else { - float ratio = (float)height() / m_modelInitialHeight; - if (ratio <= m_minZoomRatio) { - if (delta < 0) - return; - } else if (ratio >= m_maxZoomRatio) { - if (delta > 0) - return; + if (m_moveAndZoomByWindow) { + QMargins margins(delta, delta, delta, delta); + if (0 == m_modelInitialHeight) { + m_modelInitialHeight = height(); + } else { + float ratio = (float)height() / m_modelInitialHeight; + if (ratio <= m_minZoomRatio) { + if (delta < 0) + return; + } else if (ratio >= m_maxZoomRatio) { + if (delta > 0) + return; + } } + setGeometry(geometry().marginsAdded(margins)); + emit renderParametersChanged(); + update(); + return; + } else { + m_eyePosition += QVector3D(0, 0, m_eyePosition.z() * (delta > 0 ? -0.1 : 0.1)); + if (m_eyePosition.z() < -15) + m_eyePosition.setZ(-15); + else if (m_eyePosition.z() > -0.1) + m_eyePosition.setZ(-0.1); + emit eyePositionChanged(m_eyePosition); + emit renderParametersChanged(); + update(); } - setGeometry(geometry().marginsAdded(margins)); - emit renderParametersChanged(); - update(); } void ModelWidget::setMousePickTargetPositionInModelSpace(QVector3D position) @@ -467,6 +540,11 @@ void ModelWidget::enableMousePicking(bool enabled) m_mousePickingEnabled = enabled; } +void ModelWidget::setMoveAndZoomByWindow(bool byWindow) +{ + m_moveAndZoomByWindow = byWindow; +} + void ModelWidget::mousePressEvent(QMouseEvent *event) { inputMousePressEventFromOtherWidget(event); diff --git a/src/modelwidget.h b/src/modelwidget.h index f89dbea0..0cd32aab 100644 --- a/src/modelwidget.h +++ b/src/modelwidget.h @@ -24,6 +24,11 @@ signals: void mouseReleased(); void addMouseRadius(float radius); void renderParametersChanged(); + void xRotationChanged(int angle); + void yRotationChanged(int angle); + void zRotationChanged(int angle); + void eyePositionChanged(const QVector3D &eyePosition); + void moveToPositionChanged(const QVector3D &moveToPosition); public: ModelWidget(QWidget *parent = 0); ~ModelWidget(); @@ -39,12 +44,17 @@ public: void updateMesh(Model *mesh); void setGraphicsFunctions(SkeletonGraphicsFunctions *graphicsFunctions); void toggleWireframe(); + bool isWireframeVisible(); void toggleRotation(); void toggleUvCheck(); void enableEnvironmentLight(); + bool isEnvironmentLightEnabled(); void enableMove(bool enabled); void enableZoom(bool enabled); void enableMousePicking(bool enabled); + void setMoveAndZoomByWindow(bool byWindow); + void disableCullFace(); + void setMoveToPosition(const QVector3D &moveToPosition); bool inputMousePressEventFromOtherWidget(QMouseEvent *event); bool inputMouseMoveEventFromOtherWidget(QMouseEvent *event); bool inputWheelEventFromOtherWidget(QWheelEvent *event); @@ -58,15 +68,13 @@ public slots: void setXRotation(int angle); void setYRotation(int angle); void setZRotation(int angle); + void setEyePosition(const QVector3D &eyePosition); void cleanup(); void zoom(float delta); void setMousePickTargetPositionInModelSpace(QVector3D position); void setMousePickRadius(float radius); void reRender(); -signals: - void xRotationChanged(int angle); - void yRotationChanged(int angle); - void zRotationChanged(int angle); + void canvasResized(); protected: void initializeGL() override; void paintGL() override; @@ -80,6 +88,7 @@ public: int yRot(); int zRot(); const QVector3D &eyePosition(); + const QVector3D &moveToPosition(); private: int m_xRot; int m_yRot; @@ -107,7 +116,11 @@ private: QTimer *m_rotationTimer = nullptr; int m_widthInPixels = 0; int m_heightInPixels = 0; + QVector3D m_moveToPosition; + bool m_moveAndZoomByWindow = true; + bool m_enableCullFace = true; std::pair screenPositionToMouseRay(const QPoint &screenPosition); + void updateProjectionMatrix(); public: static int m_defaultXRotation; static int m_defaultYRotation; diff --git a/src/normalanddepthmapsgenerator.cpp b/src/normalanddepthmapsgenerator.cpp index 2cbe1bd4..a980fe0c 100644 --- a/src/normalanddepthmapsgenerator.cpp +++ b/src/normalanddepthmapsgenerator.cpp @@ -34,6 +34,7 @@ ModelOffscreenRender *NormalAndDepthMapsGenerator::createOfflineRender(ModelWidg offlineRender->setYRotation(modelWidget->yRot()); offlineRender->setZRotation(modelWidget->zRot()); offlineRender->setEyePosition(modelWidget->eyePosition()); + offlineRender->setMoveToPosition(modelWidget->moveToPosition()); offlineRender->setRenderPurpose(purpose); return offlineRender; }