diff options
author | Mika Salmela <mika.salmela@digia.com> | 2013-08-23 17:58:31 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-26 09:14:25 +0300 |
commit | 792d11e1093aa4e3ac249c57691c3bea6d07bc41 (patch) | |
tree | 0e4a58bd8c1c5aaf4e528d4aded4f6da3f64df48 | |
parent | 43ecfbc2ca07428874df5497cead68c895dfb115 (diff) |
AbstractRenderer into use and grid lines
Modified renderer to use AbstractRenderer and copied grid lines mostly
from scatter. Feel free to fix bugs. See you in a week.
Change-Id: I54c79b134be4ed5d7814c395a008a42003037307
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
-rw-r--r-- | examples/surfacechart/chartmodifier.cpp | 10 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dsurface.cpp | 87 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dsurface.h | 25 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dsurface_p.h | 3 | ||||
-rw-r--r-- | src/datavis3d/engine/surface3dcontroller.cpp | 46 | ||||
-rw-r--r-- | src/datavis3d/engine/surface3dcontroller_p.h | 11 | ||||
-rw-r--r-- | src/datavis3d/engine/surface3drenderer.cpp | 479 | ||||
-rw-r--r-- | src/datavis3d/engine/surface3drenderer_p.h | 71 |
8 files changed, 460 insertions, 272 deletions
diff --git a/examples/surfacechart/chartmodifier.cpp b/examples/surfacechart/chartmodifier.cpp index b685a680..03f55dc9 100644 --- a/examples/surfacechart/chartmodifier.cpp +++ b/examples/surfacechart/chartmodifier.cpp @@ -17,6 +17,8 @@ ****************************************************************************/ #include "chartmodifier.h" +#include <QCategoryAxis> +#include <QValueAxis> #include <qmath.h> @@ -70,9 +72,11 @@ void ChartModifier::toggleSqrtSin(bool enable) } } - m_chart->setSegmentCount(4, 0.5f); + m_chart->setSegmentCount(4, 0.5f); // Going to be obsolete m_chart->appendSeries(series, m_xCount, m_zCount); + m_chart->valueAxisZ()->setSegmentCount(7); + qDebug() << "biggest = " << biggest << ", smallest = " << smallest; } else { qDebug() << "Remove surface"; @@ -94,6 +98,10 @@ void ChartModifier::togglePlane(bool enable) m_chart->setSegmentCount(4, 0.5f); m_chart->appendSeries(series, m_xCount, m_zCount); + m_chart->valueAxisX()->setSegmentCount(m_xCount - 1); + m_chart->valueAxisY()->setSegmentCount(4); + m_chart->valueAxisY()->setRange(0.0, 2.0); + m_chart->valueAxisZ()->setSegmentCount(m_zCount - 1); } } diff --git a/src/datavis3d/engine/q3dsurface.cpp b/src/datavis3d/engine/q3dsurface.cpp index e3a30720..d4b5f2f1 100644 --- a/src/datavis3d/engine/q3dsurface.cpp +++ b/src/datavis3d/engine/q3dsurface.cpp @@ -18,6 +18,7 @@ #include "q3dsurface.h" #include "q3dsurface_p.h" +#include "qvalueaxis.h" #include <QMouseEvent> @@ -37,6 +38,7 @@ Q3DSurface::~Q3DSurface() void Q3DSurface::render() { + d_ptr->m_shared->synchDataToRenderer(); d_ptr->m_shared->render(); } @@ -78,6 +80,40 @@ void Q3DSurface::resizeEvent(QResizeEvent *event) d_ptr->m_shared->setHeight(height()); } +/*! + * \property Q3DSurface::gridVisible + * + * \a visible Flag to enable or disable grid. \c true by default. + * + * Sets grid drawing on or off. + */ +void Q3DSurface::setGridVisible(bool visible) +{ + d_ptr->m_shared->setGridEnabled(visible); +} + +bool Q3DSurface::isGridVisible() const +{ + return d_ptr->m_shared->gridEnabled(); +} + +/*! + * \property Q3DSurface::backgroundVisible + * + * \a visible Flag to enable or disable background. \c true by default. + * + * Sets backround rendering on or off. + */ +void Q3DSurface::setBackgroundVisible(bool visible) +{ + d_ptr->m_shared->setBackgroundEnabled(visible); +} + +bool Q3DSurface::isBackgroundVisible() const +{ + return d_ptr->m_shared->backgroundEnabled(); +} + void Q3DSurface::setSmoothSurface(bool enable) { d_ptr->m_shared->setSmoothSurface(enable); @@ -111,21 +147,49 @@ void Q3DSurface::setHeight(const int height) } /*! - * \a segmentCount How many segments will be drawn. \c 5 by default. - * - * \a step How large a step each segment is. - * - * \a minimum Minimum value a bar in data set can have. Setting this correctly is especially - * important if values can be negative, or autoscaling won't work correctly. - * - * Sets segment count and step. Note; segmentCount * step should be the maximum possible value of data - * set. + TODO: REMOVE */ void Q3DSurface::setSegmentCount(int segmentCount, qreal step, qreal minimum) { d_ptr->m_shared->setSegmentCount(GLint(segmentCount), GLfloat(step), GLfloat(minimum)); } +void Q3DSurface::setValueAxisX(QValueAxis *axis) +{ + Q_ASSERT(axis); + + return d_ptr->m_shared->setAxisX(axis); +} + +QValueAxis *Q3DSurface::valueAxisX() +{ + return static_cast<QValueAxis *>(d_ptr->m_shared->axisX()); +} + +void Q3DSurface::setValueAxisY(QValueAxis *axis) +{ + Q_ASSERT(axis); + + return d_ptr->m_shared->setAxisY(axis); +} + +QValueAxis *Q3DSurface::valueAxisY() +{ + return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); +} + +void Q3DSurface::setValueAxisZ(QValueAxis *axis) +{ + Q_ASSERT(axis); + + return d_ptr->m_shared->setAxisZ(axis); +} + +QValueAxis *Q3DSurface::valueAxisZ() +{ + return static_cast<QValueAxis *>(d_ptr->m_shared->axisZ()); +} + void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) { d_ptr->m_shared->setGradientColorAt(pos, color); @@ -154,9 +218,8 @@ void Q3DSurface::showData() const /////////////////// PRIVATE /////////////////////////////////// Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect) - : m_shared(new Surface3dController(rect)), - q_ptr(q) - + : q_ptr(q), + m_shared(new Surface3dController(rect)) { } diff --git a/src/datavis3d/engine/q3dsurface.h b/src/datavis3d/engine/q3dsurface.h index c2deea9a..357d65bd 100644 --- a/src/datavis3d/engine/q3dsurface.h +++ b/src/datavis3d/engine/q3dsurface.h @@ -25,10 +25,13 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DSurfacePrivate; +class QValueAxis; class QT_DATAVIS3D_EXPORT Q3DSurface : public Q3DWindow { Q_OBJECT + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) Q_PROPERTY(bool smoothSurface READ smoothSurface WRITE setSmoothSurface) Q_PROPERTY(bool surfaceGrid READ surfaceGrid WRITE setSurfaceGrid) @@ -36,6 +39,14 @@ public: explicit Q3DSurface(); ~Q3DSurface(); + // Enable or disable background grid + void setGridVisible(bool visible); + bool isGridVisible() const; + + // Enable or disable background mesh + void setBackgroundVisible(bool visible); + bool isBackgroundVisible() const; + // Enable or disable the smoothes of the surface void setSmoothSurface(bool enable); bool smoothSurface() const; @@ -46,9 +57,17 @@ public: void setGradientColorAt(qreal pos, const QColor &color); - // Set segment count and step. Note; segmentCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. + // Axes + void setValueAxisX(QValueAxis *axis); + QValueAxis *valueAxisX(); + + void setValueAxisY(QValueAxis *axis); + QValueAxis *valueAxisY(); + + void setValueAxisZ(QValueAxis *axis); + QValueAxis *valueAxisZ(); + + // TODO: Remove when axes handling in use void setSegmentCount(int segmentCount, qreal step, qreal minimum = 0.0f); //TODO part diff --git a/src/datavis3d/engine/q3dsurface_p.h b/src/datavis3d/engine/q3dsurface_p.h index 1e132416..1e92483b 100644 --- a/src/datavis3d/engine/q3dsurface_p.h +++ b/src/datavis3d/engine/q3dsurface_p.h @@ -50,10 +50,9 @@ public: int numOfSeries(); // TODO + Q3DSurface *q_ptr; Surface3dController *m_shared; -private: - Q3DSurface *q_ptr; QList<QList<qreal> > m_seriesList; // Temp to be replaced by dataset }; diff --git a/src/datavis3d/engine/surface3dcontroller.cpp b/src/datavis3d/engine/surface3dcontroller.cpp index 0bb17c6d..89ec4fe6 100644 --- a/src/datavis3d/engine/surface3dcontroller.cpp +++ b/src/datavis3d/engine/surface3dcontroller.cpp @@ -19,6 +19,9 @@ #include "surface3dcontroller_p.h" #include "surface3drenderer_p.h" #include "camerahelper_p.h" +#include "qabstractaxis_p.h" +#include "qvalueaxis_p.h" +#include "qcategoryaxis.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -30,12 +33,15 @@ QT_DATAVIS3D_BEGIN_NAMESPACE Surface3dController::Surface3dController(QRect rect) : Abstract3DController(rect), m_renderer(0), - m_isInitialized(false), m_smoothSurface(false), m_surfaceGrid(true), m_mouseState(MouseNone), m_mousePos(QPoint(0, 0)) { + // Default axes + setAxisX(new QValueAxis()); // Or QCategoryAxis + setAxisY(new QValueAxis()); + setAxisZ(new QValueAxis()); // Or QCategoryAxis } Surface3dController::~Surface3dController() @@ -45,24 +51,22 @@ Surface3dController::~Surface3dController() void Surface3dController::initializeOpenGL() { // Initialization is called multiple times when Qt Quick components are used - if (m_isInitialized) + if (isInitialized()) return; m_renderer = new Surface3dRenderer(this); - m_isInitialized = true; + setRenderer(m_renderer); + synchDataToRenderer(); } void Surface3dController::synchDataToRenderer() { - // TODO: Implement -} + Abstract3DController::synchDataToRenderer(); -void Surface3dController::render(const GLuint defaultFboHandle) -{ - if (!m_isInitialized) + if (!isInitialized()) return; - m_renderer->render(m_cameraHelper, defaultFboHandle); + // Notify changes to renderer } void Surface3dController::handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) @@ -82,18 +86,6 @@ QMatrix4x4 Surface3dController::calculateViewMatrix(int zoom, int viewPortWidth, showUnder); } -void Surface3dController::setWidth(const int width) -{ - qDebug() << "Surface3dController::setWidth"; - m_renderer->setWidth(width); -} - -void Surface3dController::setHeight(const int height) -{ - qDebug() << "Surface3dController::setHeight"; - m_renderer->setHeight(height); -} - void Surface3dController::setSmoothSurface(bool enable) { m_smoothSurface = enable; @@ -132,7 +124,7 @@ void Surface3dController::mousePressEvent(QMouseEvent *event, const QPoint &mous { if (Qt::LeftButton == event->button()) { m_mousePos = mousePos; - emit leftMousePressed(); + emit leftMousePressed(mousePos); } else if (Qt::RightButton == event->button()) { #if !defined(Q_OS_ANDROID) m_mouseState = Abstract3DController::MouseRotating; @@ -173,16 +165,6 @@ QPoint Surface3dController::mousePosition() return m_mousePos; } - -// TODO: abstract renderer should have accessor for Drawer instead -Drawer *Surface3dController::drawer() -{ - if (m_renderer) - return m_renderer->drawer(); - else - return 0; -} - void Surface3dController::setSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) { m_segmentCount = segmentCount; diff --git a/src/datavis3d/engine/surface3dcontroller_p.h b/src/datavis3d/engine/surface3dcontroller_p.h index d8c36d08..a9c0945c 100644 --- a/src/datavis3d/engine/surface3dcontroller_p.h +++ b/src/datavis3d/engine/surface3dcontroller_p.h @@ -44,7 +44,6 @@ class QT_DATAVIS3D_EXPORT Surface3dController : public Abstract3DController private: Surface3dRenderer *m_renderer; - bool m_isInitialized; QList<qreal> m_series; // TODO: TEMP int m_dataWidth; int m_dataDepth; @@ -65,16 +64,12 @@ public: ~Surface3dController(); void initializeOpenGL(); - void synchDataToRenderer(); - void render(const GLuint defaultFboHandle = 0); + virtual void synchDataToRenderer(); QPoint mousePosition(); QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder = false); - void setWidth(const int width); - void setHeight(const int height); - // Enable or disable the smoothes of the surface void setSmoothSurface(bool enable); bool smoothSurface(); @@ -102,15 +97,13 @@ public: void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); void wheelEvent(QWheelEvent *event); - // TODO: abstract renderer should have accessor for Drawer instead - virtual Drawer *drawer(); virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); signals: void smoothStatusChanged(bool enable); void surfaceGridChanged(bool enable); void segmentCountChanged(GLint segmentCount, GLfloat step, GLfloat minimum); - void leftMousePressed(); + void leftMousePressed(const QPoint &point); // My temp solution private: Q_DISABLE_COPY(Surface3dController) diff --git a/src/datavis3d/engine/surface3drenderer.cpp b/src/datavis3d/engine/surface3drenderer.cpp index 5337aa54..b98b4347 100644 --- a/src/datavis3d/engine/surface3drenderer.cpp +++ b/src/datavis3d/engine/surface3drenderer.cpp @@ -41,26 +41,27 @@ static const int ID_TO_RGBA_MASK = 0xff; QT_DATAVIS3D_BEGIN_NAMESPACE +const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background) +const GLfloat backgroundBottom = 1.0f; +const GLfloat gridLineWidth = 0.005f; +const GLfloat coordRatio = 2.0f; + Surface3dRenderer::Surface3dRenderer(Surface3dController *controller) - : QObject(controller), + : Abstract3DRenderer(controller), m_controller(controller), - m_mousePressed(MouseNone), - m_mousePos(QPoint(0, 0)), - m_labelTransparency(QDataVis::TransparencyFromTheme), - m_font(QFont(QStringLiteral("Arial"))), m_isGridEnabled(true), - m_isBackgroundEnabled(true), m_shadowQuality(QDataVis::ShadowLow), - m_hasNegativeValues(false), + m_labelTransparency(QDataVis::TransparencyFromTheme), + m_font(QFont(QStringLiteral("Arial"))), m_segmentYCount(0), m_segmentYStep(0.0f), m_segmentXCount(0), m_segmentZCount(0), + m_shader(0), m_backgroundShader(0), m_surfaceShader(0), m_surfaceGridShader(0), m_selectionShader(0), - m_isInitialized(false), m_yRange(0.0f), // m_heightNormalizer m_yAdjustment(0.0f), m_xLength(0.0f), @@ -84,7 +85,9 @@ Surface3dRenderer::Surface3dRenderer(Surface3dController *controller) m_querySelection(false), m_selectionPointer(0), m_selectionActive(false), - m_drawer(new Drawer(m_cachedTheme, m_font, m_labelTransparency)) + m_xFlipped(false), + m_zFlipped(false), + m_yFlipped(false) { // Listen to changes in the controller QObject::connect(m_controller, &Surface3dController::smoothStatusChanged, this, @@ -93,15 +96,13 @@ Surface3dRenderer::Surface3dRenderer(Surface3dController *controller) &Surface3dRenderer::updateSurfaceGridStatus); QObject::connect(m_controller, &Surface3dController::segmentCountChanged, this, &Surface3dRenderer::updateSegmentCount); - QObject::connect(m_controller, &Surface3dController::themeChanged, this, - &Surface3dRenderer::updateTheme); QObject::connect(m_controller, &Surface3dController::leftMousePressed, this, - &Surface3dRenderer::getSelection); + &Surface3dRenderer::requestSelectionAtPoint); // TODO: Possible temp m_cachedSmoothSurface = m_controller->smoothSurface(); updateSurfaceGridStatus(m_controller->surfaceGrid()); - updateTheme(m_controller->theme()); + initializeOpenGLFunctions(); initializeOpenGL(); } @@ -117,6 +118,7 @@ Surface3dRenderer::~Surface3dRenderer() m_textureHelper->deleteTexture(&m_selectionTexture); m_textureHelper->deleteTexture(&m_selectionResultTexture); + delete m_shader; delete m_backgroundShader; delete m_selectionShader; delete m_surfaceShader; @@ -124,8 +126,7 @@ Surface3dRenderer::~Surface3dRenderer() delete m_backgroundObj; delete m_surfaceObj; - delete m_textureHelper; - delete m_drawer; + delete m_gridLineObj; if (m_selectionPointer) delete m_selectionPointer; @@ -133,28 +134,10 @@ Surface3dRenderer::~Surface3dRenderer() void Surface3dRenderer::initializeOpenGL() { - // Initialization is called multiple times when Qt Quick components are used - if (m_isInitialized) - return; - - initializeOpenGLFunctions(); - - m_textureHelper = new TextureHelper(); - m_drawer->initializeOpenGL(); + Abstract3DRenderer::initializeOpenGL(); // Initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } else { - initBackgroundShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } -#else - initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); -#endif + handleShadowQualityChange(); initSurfaceShaders(); @@ -180,11 +163,8 @@ void Surface3dRenderer::initializeOpenGL() #endif // Set view port - glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), - m_sliceViewPort.width(), m_sliceViewPort.height()); - - // Set initialized -flag - m_isInitialized = true; + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); // Resize in case we've missed resize events // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here @@ -193,14 +173,11 @@ void Surface3dRenderer::initializeOpenGL() // Load background mesh (we need to be initialized first) loadBackgroundMesh(); - //loadSurfaceObj(); + updateSurfaceGradient(); } void Surface3dRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) { - if (!m_isInitialized) - return; - if (defaultFboHandle) { glDepthMask(true); glEnable(GL_DEPTH_TEST); @@ -222,6 +199,7 @@ void Surface3dRenderer::render(CameraHelper *camera, const GLuint defaultFboHand drawScene(camera, defaultFboHandle); + // If selection pointer is active, pass the render request for it also if (m_selectionPointer && m_selectionActive) m_selectionPointer->render(camera, defaultFboHandle); } @@ -248,6 +226,17 @@ void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH m_mainViewPort.height(), m_hasNegativeValues); + // Calculate flipping indicators + if (viewMatrix.row(0).x() > 0) + m_zFlipped = false; + else + m_zFlipped = true; + if (viewMatrix.row(0).z() <= 0) + m_xFlipped = false; + else + m_xFlipped = true; + + // calculate background rotation based on view matrix rotation if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) backgroundRotation = 270.0f; @@ -287,9 +276,7 @@ void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QMatrix4x4 MVPMatrix; modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); + modelMatrix.scale(QVector3D(m_scaleX, 1.0f, m_scaleZ)); MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; @@ -330,7 +317,7 @@ void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QPoint point = m_controller->mousePosition(); GLubyte pixel[4] = {0}; - glReadPixels(point.x(), height() - point.y(), 1, 1, + glReadPixels(point.x(), m_cachedBoundingRect.height() - point.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel); glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -361,12 +348,8 @@ void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QMatrix4x4 itModelMatrix; modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); - itModelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); + modelMatrix.scale(QVector3D(m_scaleX, 1.0f, m_scaleZ)); + itModelMatrix.scale(QVector3D(m_scaleX, 1.0f, m_scaleZ)); #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; @@ -431,20 +414,16 @@ void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH glCullFace(GL_BACK); // Draw background - if (m_isBackgroundEnabled && m_backgroundObj) { + if (m_cachedIsBackgroundEnabled && m_backgroundObj) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); + modelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, 1.0f, m_scaleZ * backgroundMargin)); modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); - itModelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); + itModelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, 1.0f, m_scaleZ * backgroundMargin)); #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; @@ -500,6 +479,227 @@ void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } + + // Draw grid lines + if (m_cachedIsGridEnabled && m_surfaceObj /*&& m_heightNormalizer*/) { + // Bind shader + m_shader->bind(); + + // Set unchanging shader bindings + QVector3D color = Utils::vectorFromColor(m_cachedTheme.m_gridLine); + m_shader->setUniformValue(m_shader->lightP(), lightPos); + m_shader->setUniformValue(m_shader->view(), viewMatrix); + m_shader->setUniformValue(m_shader->color(), color); + m_shader->setUniformValue(m_shader->ambientS(), m_cachedTheme.m_ambientStrength); + + GLfloat yPos = -backgroundBottom; + if (m_yFlipped) + yPos = backgroundBottom; + + if (m_axisCacheZ.segmentCount() > 0) { + GLfloat lineStep = 2.0f / (m_axisCacheZ.segmentCount()); + GLfloat linePos = -1.0; + + for (int segment = 0; segment <= m_axisCacheZ.segmentCount(); segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, yPos, linePos * m_scaleZ + zComp); + + modelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, gridLineWidth, gridLineWidth)); + itModelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, gridLineWidth, gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_shader->setUniformValue(m_shader->model(), modelMatrix); + m_shader->setUniformValue(m_shader->nModel(), + itModelMatrix.inverted().transposed()); + m_shader->setUniformValue(m_shader->MVP(), MVPMatrix); + + #if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_shader->setUniformValue(m_shader->shadowQ(), m_shadowQualityToShader); + m_shader->setUniformValue(m_shader->depth(), depthMVPMatrix); + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj, 0, m_depthTexture); + } else + #endif + { + // Set shadowless shader bindings + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj); + } + + linePos += lineStep; + } + } + + // Floor lines: columns (= X) + if (m_axisCacheX.segmentCount() > 0) { + GLfloat lineStep = 2.0f / (m_axisCacheX.segmentCount()); + GLfloat linePos = -1.0; + + for (int segment = 0; segment <= m_axisCacheX.segmentCount(); segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(linePos * m_scaleX, yPos, zComp); + + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, m_scaleZ * backgroundMargin)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, m_scaleZ * backgroundMargin)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_shader->setUniformValue(m_shader->model(), modelMatrix); + m_shader->setUniformValue(m_shader->nModel(), + itModelMatrix.inverted().transposed()); + m_shader->setUniformValue(m_shader->MVP(), MVPMatrix); + + #if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_shader->setUniformValue(m_shader->shadowQ(), m_shadowQualityToShader); + m_shader->setUniformValue(m_shader->depth(), depthMVPMatrix); + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj, 0, m_depthTexture); + } else + #endif + { + // Set shadowless shader bindings + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj); + } + + linePos += lineStep; + } + } + + // Wall lines: back wall + if (m_axisCacheY.segmentCount() > 0) { + GLfloat lineStep = 2.0f / (m_axisCacheY.segmentCount()); + GLfloat linePos = -1.0; + GLfloat zPos = -backgroundMargin; + + if (m_zFlipped) + zPos = backgroundMargin; + + for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, linePos, zPos * m_scaleZ + zComp); + + modelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, gridLineWidth, gridLineWidth)); + itModelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, gridLineWidth, gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_shader->setUniformValue(m_shader->model(), modelMatrix); + m_shader->setUniformValue(m_shader->nModel(), + itModelMatrix.inverted().transposed()); + m_shader->setUniformValue(m_shader->MVP(), MVPMatrix); + + #if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_shader->setUniformValue(m_shader->shadowQ(), m_shadowQualityToShader); + m_shader->setUniformValue(m_shader->depth(), depthMVPMatrix); + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj, 0, m_depthTexture); + } else + #endif + { + // Set shadowless shader bindings + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj); + } + + linePos += lineStep; + } + + // Wall lines: side wall + linePos = -1.0; + GLfloat xPos = -backgroundMargin; + + if (m_xFlipped) + xPos = backgroundMargin; + + for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(xPos * m_scaleX, linePos, 0.0f + zComp); + + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, m_scaleZ * backgroundMargin)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, m_scaleZ * backgroundMargin)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_shader->setUniformValue(m_shader->model(), modelMatrix); + m_shader->setUniformValue(m_shader->nModel(), + itModelMatrix.inverted().transposed()); + m_shader->setUniformValue(m_shader->MVP(), MVPMatrix); + + #if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_shader->setUniformValue(m_shader->shadowQ(), m_shadowQualityToShader); + m_shader->setUniformValue(m_shader->depth(), depthMVPMatrix); + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj, 0, m_depthTexture); + } else + #endif + { + // Set shadowless shader bindings + m_shader->setUniformValue(m_shader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_shader, m_gridLineObj); + } + + linePos += lineStep; + } + } + } } void Surface3dRenderer::updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) @@ -524,14 +724,6 @@ void Surface3dRenderer::setXZStuff(GLint segmentXCount, GLint segmentZCount) calculateSceneScalingFactors(); } -void Surface3dRenderer::updateTheme(Theme theme) -{ - m_cachedTheme.setFromTheme(theme); - - // Update things depending from the theme - updateSurfaceGradient(); -} - void Surface3dRenderer::updateSurfaceGradient() { QImage image(QSize(4, 100), QImage::Format_RGB32); @@ -548,6 +740,19 @@ void Surface3dRenderer::updateSurfaceGradient() m_gradientTexture = m_textureHelper->create2DTexture(image, false, true); } +void Surface3dRenderer::requestSelectionAtPoint(const QPoint &point) +{ + Q_UNUSED(point) + +// QMutexLocker locker(&m_mutex); +// m_selectionPointRequest.setX(point.x()); +// m_selectionPointRequest.setY(point.y()); +// m_isSelectionPointRequestActive = true; + + m_querySelection = true; +} + +// This one needs to be called when the data size changes void Surface3dRenderer::updateSelectionTexture() { // Create the selection ID image. Each grid corner gets 2x2 pixel area of @@ -595,7 +800,10 @@ void Surface3dRenderer::updateSelectionTexture() // Release the temp bits allocation delete bits; +} +void Surface3dRenderer::initSelectionBuffer() +{ // Create the result selection texture and buffers if (m_selectionResultTexture) { m_textureHelper->deleteTexture(&m_selectionResultTexture); @@ -635,11 +843,6 @@ void Surface3dRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a *a = (id >> 24) & ID_TO_RGBA_MASK; } -void Surface3dRenderer::getSelection() -{ - m_querySelection = true; -} - void Surface3dRenderer::setSeries(QList<qreal> series) { m_series = series; @@ -656,24 +859,27 @@ void Surface3dRenderer::setSeries(QList<qreal> series) updateSelectionTexture(); } +void Surface3dRenderer::updateTextures() +{ + qDebug() << "Surface3dRenderer::updateTextures() NEED TO DO SOMETHING"; + // Drawer has changed; this flag needs to be checked when checking if we need to update labels + //m_updateLabels = true; +} + void Surface3dRenderer::calculateSceneScalingFactors() { // Calculate scene scaling and translation factors - // m_rowWidth = ((m_columnCount + 1) * m_barSpacing.width()) / 2.0f; - // m_columnDepth = ((m_rowCount + 1) * m_barSpacing.height()) / 2.0f; - // m_maxDimension = qMax(m_rowWidth, m_columnDepth); - // m_scaleFactor = qMin((m_columnCount * (m_maxDimension / m_maxSceneSize)), - // (m_rowCount * (m_maxDimension / m_maxSceneSize))); - // m_scaleX = m_barThickness.width() / m_scaleFactor; - // m_scaleZ = m_barThickness.height() / m_scaleFactor; - m_xLength = m_segmentXCount; m_zLength = m_segmentZCount; m_maxDimension = qMax(m_xLength, m_zLength); - m_scaleFactor = qMin((m_segmentXCount * (m_maxDimension / m_maxSceneSize)), - (m_segmentZCount * (m_maxDimension / m_maxSceneSize))); - m_scaleX = 1.0f / m_scaleFactor; // TODO: correspondance to m_barThickness - m_scaleZ = 1.0f / m_scaleFactor; // TODO: correspondance to m_barThickness +// m_scaleFactor = qMin((m_segmentXCount * (m_maxDimension / m_maxSceneSize)), +// (m_segmentZCount * (m_maxDimension / m_maxSceneSize))); +// m_scaleX = 1.0f / m_scaleFactor; +// m_scaleZ = 1.0f / m_scaleFactor; + + m_scaleFactor = qMax(m_xLength, m_zLength); + m_scaleX = (coordRatio * m_xLength) / m_scaleFactor; + m_scaleZ = (coordRatio * m_zLength) / m_scaleFactor; //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; @@ -702,9 +908,6 @@ void Surface3dRenderer::updateSurfaceGridStatus(bool enable) void Surface3dRenderer::loadBackgroundMesh() { - if (!m_isInitialized) - return; - if (m_backgroundObj) delete m_backgroundObj; if (m_hasNegativeValues) @@ -716,9 +919,6 @@ void Surface3dRenderer::loadBackgroundMesh() void Surface3dRenderer::loadSurfaceObj() { - if (!m_isInitialized) - return; - if (m_surfaceObj) delete m_surfaceObj; m_surfaceObj = new SurfaceObject(); @@ -733,81 +933,17 @@ void Surface3dRenderer::loadGridLineMesh() m_gridLineObj->load(); } -const QSize Surface3dRenderer::size() -{ - return m_boundingRect.size(); -} - -const QRect Surface3dRenderer::boundingRect() -{ - return m_boundingRect; -} - -void Surface3dRenderer::setBoundingRect(const QRect boundingRect) -{ - m_boundingRect = boundingRect; - handleResize(); -} - -void Surface3dRenderer::setWidth(const int width) -{ - m_boundingRect.setWidth(width); - handleResize(); -} - -int Surface3dRenderer::width() -{ - return m_boundingRect.width(); -} - -void Surface3dRenderer::setHeight(const int height) -{ - m_boundingRect.setHeight(height); - handleResize(); -} - -int Surface3dRenderer::height() -{ - return m_boundingRect.height(); -} - -void Surface3dRenderer::setX(const int x) -{ - m_boundingRect.setX(x); -} - -int Surface3dRenderer::x() -{ - return m_boundingRect.x(); -} - -void Surface3dRenderer::setY(const int y) -{ - m_boundingRect.setY(y); -} - -int Surface3dRenderer::y() -{ - return m_boundingRect.y(); -} - void Surface3dRenderer::handleResize() { - if (!m_isInitialized) + if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) return; - qDebug() << "Surface3dRenderer::handleResize " << width() << "x" << height(); - - m_mainViewPort = QRect(0, 0, width(), height()); - m_sliceViewPort = QRect(0, 0, width(), height()); - -#if !defined(QT_OPENGL_ES_2) - // Re-init depth buffer - updateDepthBuffer(); -#endif + m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); if (m_selectionPointer) m_selectionPointer->updateBoundingRect(m_mainViewPort); + + Abstract3DRenderer::handleResize(); } #if !defined(QT_OPENGL_ES_2) @@ -853,9 +989,7 @@ void Surface3dRenderer::surfacePointSelected(qreal value, int column, int row) m_selectionPointer = new SelectionPointer(m_controller); m_selectionPointer->setPosition(normalize(float(column), value, float(row))); - m_selectionPointer->setScaling(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); + m_selectionPointer->setScaling(QVector3D(m_scaleX, 1.0f, m_scaleZ)); m_selectionPointer->setLabel(QString::number(value)); m_selectionPointer->updateBoundingRect(m_mainViewPort); @@ -881,6 +1015,25 @@ void Surface3dRenderer::surfacePointCleared() } } +void Surface3dRenderer::loadMeshFile() +{ + qDebug() << "Surface3dRenderer::loadMeshFile() should we do something"; +} + +void Surface3dRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) +{ + Q_UNUSED(quality) + qDebug() << "Surface3dRenderer::updateShadowQuality NEED TO DO SOMETHING"; +} + +void Surface3dRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_shader) + delete m_shader; + m_shader = new ShaderHelper(this, vertexShader, fragmentShader); + m_shader->initialize(); +} + void Surface3dRenderer::initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) { diff --git a/src/datavis3d/engine/surface3drenderer_p.h b/src/datavis3d/engine/surface3drenderer_p.h index b681db87..eee66705 100644 --- a/src/datavis3d/engine/surface3drenderer_p.h +++ b/src/datavis3d/engine/surface3drenderer_p.h @@ -38,6 +38,7 @@ #include "datavis3dglobal_p.h" #include "surface3dcontroller_p.h" +#include "abstract3drenderer_p.h" class QOpenGLShaderProgram; @@ -52,36 +53,20 @@ class Drawer; class CameraHelper; class SelectionPointer; -class QT_DATAVIS3D_EXPORT Surface3dRenderer : public QObject, protected QOpenGLFunctions +class QT_DATAVIS3D_EXPORT Surface3dRenderer : public Abstract3DRenderer { Q_OBJECT public: - enum MousePressType { - MouseNone = 0, - MouseOnScene, - MouseOnOverview, - MouseOnZoom, - MouseRotating, - MouseOnPinch - }; - Surface3dController *m_controller; - // Interaction related parameters // TODO: Moved to controller - MousePressType m_mousePressed; - QPoint m_mousePos; - QDataVis::SelectionMode m_selectionMode; - // Visual parameters QRect m_boundingRect; Theme m_cachedTheme; QDataVis::LabelTransparency m_labelTransparency; QFont m_font; bool m_isGridEnabled; - bool m_isBackgroundEnabled; QDataVis::ShadowQuality m_shadowQuality; - bool m_hasNegativeValues; private: // Data parameters @@ -93,13 +78,11 @@ private: // Internal attributes purely related to how the scene is drawn with GL. QRect m_mainViewPort; - QRect m_sliceViewPort; + ShaderHelper *m_shader; ShaderHelper *m_backgroundShader; ShaderHelper *m_surfaceShader; ShaderHelper *m_surfaceGridShader; ShaderHelper *m_selectionShader; - TextureHelper *m_textureHelper; - bool m_isInitialized; GLfloat m_yRange; // m_heightNormalizer GLfloat m_yAdjustment; GLfloat m_xLength; @@ -125,8 +108,12 @@ private: bool m_cachedSurfaceGridOn; SelectionPointer *m_selectionPointer; bool m_selectionActive; + bool m_xFlipped; + bool m_zFlipped; + bool m_yFlipped; - Drawer *m_drawer; +protected: + virtual void loadMeshFile(); public: explicit Surface3dRenderer(Surface3dController *controller); @@ -135,57 +122,41 @@ public: void initializeOpenGL(); void render(CameraHelper *camera, const GLuint defaultFboHandle = 0); - // TODO: Not thread-safe, needs rethinking how axes create labels - Drawer *drawer() { return m_drawer; } + // TODO: temp + void setXZStuff(GLint segmentXCount, GLint segmentZCount); + void setSeries(QList<qreal> series); public slots: - void updateTheme(Theme theme); void updateSmoothStatus(bool enable); void updateSurfaceGridStatus(bool enable); void updateSurfaceGradient(); void updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum = 0.0f); + virtual void requestSelectionAtPoint(const QPoint &point); - void getSelection(); - -public: - // Size - const QSize size(); - const QRect boundingRect(); - void setBoundingRect(const QRect boundingRect); - void setWidth(const int width); - int width(); - void setHeight(const int height); - int height(); - void setX(const int x); - int x(); - void setY(const int y); - int y(); - - void handleResize(); -#if !defined(QT_OPENGL_ES_2) - void updateDepthBuffer(); -#endif +private: + virtual void updateShadowQuality(QDataVis::ShadowQuality quality); + virtual void updateTextures(); + virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); void loadBackgroundMesh(); void loadGridLineMesh(); void loadSurfaceObj(); - - // TODO: temp - void setXZStuff(GLint segmentXCount, GLint segmentZCount); - void setSeries(QList<qreal> series); - -private: void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void handleResize(); void calculateSceneScalingFactors(); void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); void initSelectionShaders(); void initSurfaceShaders(); + void initSelectionBuffer(); void updateSelectionTexture(); void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a); void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride); void surfacePointSelected(qreal value, int column, int row); void surfacePointCleared(); QVector3D normalize(float x, float y, float z); +#if !defined(QT_OPENGL_ES_2) + void updateDepthBuffer(); +#endif Q_DISABLE_COPY(Surface3dRenderer) }; |