Optimize render view port

- Fix the bad performance of view port manipulation
- Allow to view the mesh inside
- Fix environment light not enabled in image export
- Fix wireframe not follow the view port setting in image export
master
huxingyi 2020-04-15 23:35:04 +09:30
parent 29b7f13460
commit 420a5997ea
9 changed files with 194 additions and 72 deletions

View File

@ -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();

View File

@ -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;
};

View File

@ -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()

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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<QVector3D, QVector3D> 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);

View File

@ -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<QVector3D, QVector3D> screenPositionToMouseRay(const QPoint &screenPosition);
void updateProjectionMatrix();
public:
static int m_defaultXRotation;
static int m_defaultYRotation;

View File

@ -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;
}