diff options
Diffstat (limited to 'src/datavisualization/engine/bars3drenderer.cpp')
-rw-r--r-- | src/datavisualization/engine/bars3drenderer.cpp | 869 |
1 files changed, 531 insertions, 338 deletions
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 689f3f5d..b6a191a9 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -31,7 +31,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION -const GLfloat gridLineWidth = 0.005f; const bool sliceGridLabels = true; Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) @@ -48,9 +47,7 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_depthShader(0), m_selectionShader(0), m_backgroundShader(0), - m_labelShader(0), m_bgrTexture(0), - m_depthTexture(0), m_selectionTexture(0), m_depthFrameBuffer(0), m_selectionFrameBuffer(0), @@ -67,7 +64,6 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_scaleFactor(0), m_maxSceneSize(40.0f), m_visualSelectedBarPos(Bars3DController::invalidSelectionPosition()), - m_resetCameraBaseOrientation(true), m_selectedBarPos(Bars3DController::invalidSelectionPosition()), m_selectedSeriesCache(0), m_noZeroInRange(false), @@ -79,17 +75,22 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_keepSeriesUniform(false), m_haveUniformColorSeries(false), m_haveGradientSeries(false), - m_zeroPosition(0.0f) + m_zeroPosition(0.0f), + m_xScaleFactor(1.0f), + m_zScaleFactor(1.0f), + m_floorLevel(0.0f), + m_actualFloorLevel(0.0f) { m_axisCacheY.setScale(2.0f); m_axisCacheY.setTranslate(-1.0f); - initializeOpenGLFunctions(); initializeOpenGL(); } Bars3DRenderer::~Bars3DRenderer() { + fixContextBeforeDelete(); + if (QOpenGLContext::currentContext()) { m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); @@ -103,7 +104,6 @@ Bars3DRenderer::~Bars3DRenderer() delete m_depthShader; delete m_selectionShader; delete m_backgroundShader; - delete m_labelShader; } void Bars3DRenderer::initializeOpenGL() @@ -111,13 +111,9 @@ void Bars3DRenderer::initializeOpenGL() Abstract3DRenderer::initializeOpenGL(); // Initialize shaders - initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), - QStringLiteral(":/shaders/fragmentLabel")); -#if !defined(QT_OPENGL_ES_2) // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. initDepthShader(); -#endif // Init selection shader initSelectionShader(); @@ -125,13 +121,57 @@ void Bars3DRenderer::initializeOpenGL() // Load grid line mesh loadGridLineMesh(); - // Load label mesh - loadLabelMesh(); - // Load background mesh (we need to be initialized first) loadBackgroundMesh(); } +void Bars3DRenderer::fixCameraTarget(QVector3D &target) +{ + target.setX(target.x() * m_xScaleFactor); + target.setY(0.0f); + target.setZ(target.z() * -m_zScaleFactor); +} + +void Bars3DRenderer::getVisibleItemBounds(QVector3D &minBounds, QVector3D &maxBounds) +{ + // The inputs are the item bounds in OpenGL coordinates. + // The outputs limit these bounds to visible ranges, normalized to range [-1, 1] + // Volume shader flips the Y and Z axes, so we need to set negatives of actual values to those + float itemRangeX = (maxBounds.x() - minBounds.x()); + float itemRangeY = (maxBounds.y() - minBounds.y()); + float itemRangeZ = (maxBounds.z() - minBounds.z()); + + if (minBounds.x() < -m_xScaleFactor) + minBounds.setX(-1.0f + (2.0f * qAbs(minBounds.x() + m_xScaleFactor) / itemRangeX)); + else + minBounds.setX(-1.0f); + + if (minBounds.y() < -1.0f + m_backgroundAdjustment) + minBounds.setY(-(-1.0f + (2.0f * qAbs(minBounds.y() + 1.0f - m_backgroundAdjustment) / itemRangeY))); + else + minBounds.setY(1.0f); + + if (minBounds.z() < -m_zScaleFactor) + minBounds.setZ(-(-1.0f + (2.0f * qAbs(minBounds.z() + m_zScaleFactor) / itemRangeZ))); + else + minBounds.setZ(1.0f); + + if (maxBounds.x() > m_xScaleFactor) + maxBounds.setX(1.0f - (2.0f * qAbs(maxBounds.x() - m_xScaleFactor) / itemRangeX)); + else + maxBounds.setX(1.0f); + + if (maxBounds.y() > 1.0f + m_backgroundAdjustment) + maxBounds.setY(-(1.0f - (2.0f * qAbs(maxBounds.y() - 1.0f - m_backgroundAdjustment) / itemRangeY))); + else + maxBounds.setY(-1.0f); + + if (maxBounds.z() > m_zScaleFactor) + maxBounds.setZ(-(1.0f - (2.0f * qAbs(maxBounds.z() - m_zScaleFactor) / itemRangeZ))); + else + maxBounds.setZ(-1.0f); +} + void Bars3DRenderer::updateData() { int minRow = m_axisCacheZ.min(); @@ -163,11 +203,11 @@ void Bars3DRenderer::updateData() GLfloat sceneRatio = qMin(GLfloat(newColumns) / GLfloat(newRows), GLfloat(newRows) / GLfloat(newColumns)); m_maxSceneSize = 2.0f * qSqrt(sceneRatio * newColumns * newRows); - // Calculate here and at setting bar specs - calculateSceneScalingFactors(); } - m_zeroPosition = m_axisCacheY.formatter()->positionAt(0.0f); + calculateSceneScalingFactors(); + + m_zeroPosition = m_axisCacheY.formatter()->positionAt(m_actualFloorLevel); foreach (SeriesRenderCache *baseCache, m_renderCacheList) { BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); @@ -390,14 +430,6 @@ void Bars3DRenderer::updateScene(Q3DScene *scene) } } - if (m_resetCameraBaseOrientation) { - // Set initial camera position. Also update if height adjustment has changed. - scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector, - zeroVector, - upVector); - m_resetCameraBaseOrientation = false; - } - Abstract3DRenderer::updateScene(scene); updateSlicingActive(scene->isSlicingActive()); @@ -418,10 +450,17 @@ void Bars3DRenderer::render(GLuint defaultFboHandle) void Bars3DRenderer::drawSlicedScene() { + if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow) + == m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) { + qWarning("Invalid selection mode. Either QAbstract3DGraph::SelectionRow or" + " QAbstract3DGraph::SelectionColumn must be set before calling" + " setSlicingActive(true)."); + return; + } + GLfloat barPosX = 0; QVector3D lightPos; QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); - static QQuaternion ninetyDegreeRotation = QQuaternion::fromAxisAndAngle(upVector, 90.0f); // Specify viewport glViewport(m_secondarySubViewport.x(), @@ -482,11 +521,12 @@ void Bars3DRenderer::drawSlicedScene() // Draw grid lines if (m_cachedTheme->isGridEnabled()) { glDisable(GL_DEPTH_TEST); -#if !(defined QT_OPENGL_ES_2) - ShaderHelper *lineShader = m_backgroundShader; -#else - ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES -#endif + ShaderHelper *lineShader; + if (m_isOpenGLES) + lineShader = m_selectionShader; // Plain color shader for GL_LINES + else + lineShader = m_backgroundShader; + // Bind line shader lineShader->bind(); @@ -496,7 +536,8 @@ void Bars3DRenderer::drawSlicedScene() lineShader->setUniformValue(lineShader->view(), viewMatrix); lineShader->setUniformValue(lineShader->color(), lineColor); lineShader->setUniformValue(lineShader->ambientS(), - m_cachedTheme->ambientLightStrength() * 2.3f); + m_cachedTheme->ambientLightStrength() + + m_cachedTheme->lightStrength() / 7.0f); lineShader->setUniformValue(lineShader->lightS(), 0.0f); lineShader->setUniformValue(lineShader->lightColor(), lightColor); @@ -524,11 +565,10 @@ void Bars3DRenderer::drawSlicedScene() lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); // Draw the object -#if !(defined QT_OPENGL_ES_2) - m_drawer->drawObject(lineShader, m_gridLineObj); -#else - m_drawer->drawLine(lineShader); -#endif + if (m_isOpenGLES) + m_drawer->drawLine(lineShader); + else + m_drawer->drawObject(lineShader, m_gridLineObj); // Check if we have a line at zero position already if (gridPos == (barPosYAdjustment + zeroPosAdjustment)) @@ -553,18 +593,16 @@ void Bars3DRenderer::drawSlicedScene() m_cachedTheme->labelTextColor())); // Draw the object -#if !(defined QT_OPENGL_ES_2) - m_drawer->drawObject(lineShader, m_gridLineObj); -#else - m_drawer->drawLine(lineShader); -#endif + if (m_isOpenGLES) + m_drawer->drawLine(lineShader); + else + m_drawer->drawObject(lineShader, m_gridLineObj); } } if (sliceGridLabels) { // Bind label shader m_labelShader->bind(); - glEnable(GL_TEXTURE_2D); glCullFace(GL_BACK); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -587,7 +625,6 @@ void Bars3DRenderer::drawSlicedScene() } labelNbr++; } - glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); } @@ -606,14 +643,16 @@ void Bars3DRenderer::drawSlicedScene() m_barShader->setUniformValue(m_barShader->view(), viewMatrix); m_barShader->setUniformValue(m_barShader->lightS(), 0.15f); m_barShader->setUniformValue(m_barShader->ambientS(), - m_cachedTheme->ambientLightStrength() * 2.3f); + m_cachedTheme->ambientLightStrength() + + m_cachedTheme->lightStrength() / 7.0f); m_barShader->setUniformValue(m_barShader->lightColor(), lightColor); m_barGradientShader->bind(); m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos); m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix); m_barGradientShader->setUniformValue(m_barGradientShader->lightS(), 0.15f); m_barGradientShader->setUniformValue(m_barGradientShader->ambientS(), - m_cachedTheme->ambientLightStrength() * 2.3f); + m_cachedTheme->ambientLightStrength() + + m_cachedTheme->lightStrength() / 7.0f); m_barGradientShader->setUniformValue(m_barGradientShader->gradientMin(), 0.0f); m_barGradientShader->setUniformValue(m_barGradientShader->lightColor(), lightColor); @@ -700,7 +739,7 @@ void Bars3DRenderer::drawSlicedScene() barPosX = item.translation().x(); } else { barPosX = -(item.translation().z()); // flip z; frontmost bar to the left - barRotation *= ninetyDegreeRotation; + barRotation *= m_yRightAngleRotation; } modelMatrix.translate(barPosX, barPosY, 0.0f); @@ -760,7 +799,6 @@ void Bars3DRenderer::drawSlicedScene() // Draw labels m_labelShader->bind(); glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); glCullFace(GL_BACK); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -778,6 +816,12 @@ void Bars3DRenderer::drawSlicedScene() int labelCount = m_sliceCache->labelItems().size(); for (int labelNo = 0; labelNo < labelCount; labelNo++) { + // Check for invalid usage (no selection when setting slicing active) + if (!firstVisualSliceArray) { + qWarning("No slice data found. Make sure there is a valid selection."); + continue; + } + // Get labels from first series only const BarRenderSliceItem &item = firstVisualSliceArray->at(labelNo); m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(), @@ -889,7 +933,6 @@ void Bars3DRenderer::drawSlicedScene() m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera, false, false, Drawer::LabelMid, Qt::AlignBottom); - glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); @@ -912,8 +955,6 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) GLfloat colPos = 0; GLfloat rowPos = 0; - QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); - const Q3DCamera *activeCamera = m_cachedScene->activeCamera(); glViewport(m_primarySubViewport.x(), @@ -990,15 +1031,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix; - bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow); - - GLfloat rowScaleFactor = m_rowWidth / m_scaleFactor; - GLfloat columnScaleFactor = m_columnDepth / m_scaleFactor; - BarRenderItem *selectedBar(0); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && !m_isOpenGLES) { // Render scene into a depth texture for using with shadow mapping // Enable drawing to depth framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -1052,6 +1087,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) shadowOffset = -0.015f; } + if (m_cachedTheme->isBackgroundEnabled() && m_reflectionEnabled + && ((m_yFlipped && item.height() > 0.0) + || (!m_yFlipped && item.height() < 0.0))) { + continue; + } + QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1097,8 +1138,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); + projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader); // Disable drawing to depth framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -1112,12 +1154,22 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_primarySubViewport.width(), m_primarySubViewport.height()); } -#endif + + // Do position mapping when necessary + if (m_graphPositionQueryPending) { + QVector3D graphDimensions(m_xScaleFactor, 0.0f, m_zScaleFactor); + queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle); + + // Y is always at floor level + m_queriedGraphPosition.setY(0.0f); + emit needRender(); + } // Skip selection mode drawing if we're slicing or have no selection mode if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone && m_selectionState == SelectOnScene - && (m_visibleSeriesCount > 0 || !m_customRenderCache.isEmpty())) { + && (m_visibleSeriesCount > 0 || !m_customRenderCache.isEmpty()) + && m_selectionTexture) { // Bind selection shader m_selectionShader->bind(); @@ -1181,18 +1233,20 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } glCullFace(GL_BACK); - Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, viewMatrix, + Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, + viewMatrix, projectionViewMatrix, depthProjectionViewMatrix, m_depthTexture, m_shadowQualityToShader); - drawLabels(true, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor, - columnScaleFactor); + drawLabels(true, activeCamera, viewMatrix, projectionMatrix); + drawBackground(backgroundRotation, depthProjectionViewMatrix, projectionViewMatrix, + viewMatrix, false, true); glEnable(GL_DITHER); // Read color under cursor - QVector4D clickedColor = Utils::getSelection(m_inputPosition, - m_viewport.height()); + QVector4D clickedColor = Utils::getSelection(m_inputPosition, m_viewport.height()); m_clickedPosition = selectionColorToArrayPosition(clickedColor); m_clickedSeries = selectionColorToSeries(clickedColor); + m_clickResolved = true; emit needRender(); @@ -1204,8 +1258,133 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_primarySubViewport.height()); } - // Enable texturing - glEnable(GL_TEXTURE_2D); + if (m_reflectionEnabled) { + // + // Draw reflections + // + glDisable(GL_DEPTH_TEST); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glEnable(GL_STENCIL_TEST); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xffffffff); + + // Draw background stencil + drawBackground(backgroundRotation, depthProjectionViewMatrix, projectionViewMatrix, + viewMatrix); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glEnable(GL_DEPTH_TEST); + + glStencilFunc(GL_EQUAL, 1, 0xffffffff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + // Set light + QVector3D reflectionLightPos = lightPos; + reflectionLightPos.setY(-(lightPos.y())); + m_cachedScene->activeLight()->setPosition(reflectionLightPos); + + // Draw bar reflections + (void)drawBars(&selectedBar, depthProjectionViewMatrix, + projectionViewMatrix, viewMatrix, + startRow, stopRow, stepRow, + startBar, stopBar, stepBar, -1.0f); + + Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, + viewMatrix, projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader, -1.0f); + + // Reset light + m_cachedScene->activeLight()->setPosition(lightPos); + + glDisable(GL_STENCIL_TEST); + + glCullFace(GL_BACK); + } + + // + // Draw the real scene + // + // Draw background + if (m_reflectionEnabled) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + drawBackground(backgroundRotation, depthProjectionViewMatrix, projectionViewMatrix, + viewMatrix, true); + glDisable(GL_BLEND); + } else { + drawBackground(backgroundRotation, depthProjectionViewMatrix, projectionViewMatrix, + viewMatrix); + } + + // Draw bars + bool barSelectionFound = drawBars(&selectedBar, depthProjectionViewMatrix, + projectionViewMatrix, viewMatrix, + startRow, stopRow, stepRow, + startBar, stopBar, stepBar); + + // Draw grid lines + drawGridLines(depthProjectionViewMatrix, projectionViewMatrix, viewMatrix); + + // Draw custom items + Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix, + projectionViewMatrix, depthProjectionViewMatrix, + m_depthTexture, m_shadowQualityToShader); + + // Draw labels + drawLabels(false, activeCamera, viewMatrix, projectionMatrix); + + // Handle selected bar label generation + if (barSelectionFound) { + // Print value of selected bar + glDisable(GL_DEPTH_TEST); + // Draw the selection label + LabelItem &labelItem = selectionLabelItem(); + if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId() + || m_selectionLabelDirty) { + QString labelText = selectionLabel(); + if (labelText.isNull() || m_selectionLabelDirty) { + labelText = m_selectedSeriesCache->itemLabel(); + setSelectionLabel(labelText); + m_selectionLabelDirty = false; + } + m_drawer->generateLabelItem(labelItem, labelText); + m_selectedBar = selectedBar; + } + + Drawer::LabelPosition position = + m_selectedBar->height() >= 0 ? Drawer::LabelOver : Drawer::LabelBelow; + + m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix, + zeroVector, identityQuaternion, selectedBar->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, activeCamera, true, false, position); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + + glEnable(GL_DEPTH_TEST); + } else { + m_selectedBar = 0; + } + + glDisable(GL_BLEND); + + // Release shader + glUseProgram(0); + m_selectionDirty = false; +} + +bool Bars3DRenderer::drawBars(BarRenderItem **selectedBar, + const QMatrix4x4 &depthProjectionViewMatrix, + const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &viewMatrix, + GLint startRow, GLint stopRow, GLint stepRow, + GLint startBar, GLint stopBar, GLint stepBar, GLfloat reflection) +{ + QVector3D lightPos = m_cachedScene->activeLight()->position(); + QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); + + bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow); ShaderHelper *barShader = 0; GLuint gradientTexture = 0; @@ -1251,7 +1430,6 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_sliceTitleItem = 0; } - // Draw bars glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.5f, 1.0f); @@ -1302,12 +1480,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } previousColorStyle = colorStyle; - for (int row = startRow; row != stopRow; row += stepRow) { BarRenderItemRow &renderRow = renderArray[row]; for (int bar = startBar; bar != stopBar; bar += stepBar) { BarRenderItem &item = renderRow[bar]; - if (item.height() < 0) + float adjustedHeight = reflection * item.height(); + if (adjustedHeight < 0) glCullFace(GL_FRONT); else glCullFace(GL_BACK); @@ -1316,13 +1494,13 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) QMatrix4x4 itModelMatrix; QMatrix4x4 MVPMatrix; - colPos = (bar + seriesPos) * (m_cachedBarSpacing.width()); - rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + GLfloat colPos = (bar + seriesPos) * (m_cachedBarSpacing.width()); + GLfloat rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, - item.height(), + adjustedHeight, (m_columnDepth - rowPos) / m_scaleFactor); - modelScaler.setY(item.height()); + modelScaler.setY(adjustedHeight); if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) { QQuaternion totalRotation = seriesRotation * item.rotation(); modelMatrix.rotate(totalRotation); @@ -1357,8 +1535,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // We have no ownership, don't delete the previous one if (!m_cachedIsSlicingActivated && m_selectedSeriesCache == cache) { - selectedBar = &item; - selectedBar->setPosition(QPoint(row, bar)); + *selectedBar = &item; + (*selectedBar)->setPosition(QPoint(row, bar)); item.setTranslation(modelMatrix.column(3).toVector3D()); barSelectionFound = true; } @@ -1438,8 +1616,15 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } - // Skip drawing of 0-height bars - if (item.height() != 0) { + if (item.height() == 0) { + continue; + } else if ((m_reflectionEnabled + && (reflection == 1.0f + || (reflection != 1.0f + && ((m_yFlipped && item.height() < 0.0) + || (!m_yFlipped && item.height() > 0.0))))) + || !m_reflectionEnabled) { + // Skip drawing of 0-height bars and reflections of bars on the "wrong side" // Set shader bindings barShader->setUniformValue(barShader->model(), modelMatrix); barShader->setUniformValue(barShader->nModel(), @@ -1452,8 +1637,10 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) qAbs(item.height()) / m_gradientFraction); } -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (((m_reflectionEnabled && reflection == 1.0f + && m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) + || m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) + && !m_isOpenGLES) { // Set shadow shader bindings QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; barShader->setUniformValue(barShader->shadowQ(), @@ -1465,13 +1652,15 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // Draw the object m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture); - } else -#else - Q_UNUSED(shadowLightStrength); -#endif - { + } else { // Set shadowless shader bindings - barShader->setUniformValue(barShader->lightS(), lightStrength); + if (m_reflectionEnabled && reflection != 1.0f + && m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + barShader->setUniformValue(barShader->lightS(), + adjustedLightStrength); + } else { + barShader->setUniformValue(barShader->lightS(), lightStrength); + } // Draw the object m_drawer->drawObject(barShader, barObj, gradientTexture); @@ -1481,122 +1670,145 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } } - glDisable(GL_POLYGON_OFFSET_FILL); // Reset culling glCullFace(GL_BACK); - // Bind background shader - m_backgroundShader->bind(); + return barSelectionFound; +} +void Bars3DRenderer::drawBackground(GLfloat backgroundRotation, + const QMatrix4x4 &depthProjectionViewMatrix, + const QMatrix4x4 &projectionViewMatrix, + const QMatrix4x4 &viewMatrix, bool reflectingDraw, + bool drawingSelectionBuffer) +{ // Draw background if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) { + QVector3D lightPos = m_cachedScene->activeLight()->position(); + QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); + GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f; + ShaderHelper *shader = 0; + + // Bind background shader + if (drawingSelectionBuffer) + shader = m_selectionShader; // Use single color shader when drawing to selection buffer + else + shader = m_backgroundShader; + shader->bind(); + QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; - QVector3D backgroundScaler(rowScaleFactor, 1.0f, columnScaleFactor); - modelMatrix.translate(0.0f, m_backgroundAdjustment, 0.0f); + QVector3D backgroundScaler(m_scaleXWithBackground, m_scaleYWithBackground, + m_scaleZWithBackground); + QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor()); + if (m_reflectionEnabled) + backgroundColor.setW(backgroundColor.w() * m_reflectivity); + // Set shader bindings + shader->setUniformValue(shader->lightP(), lightPos); + shader->setUniformValue(shader->view(), viewMatrix); + if (drawingSelectionBuffer) { + // Use selectionSkipColor for background when drawing to selection buffer + shader->setUniformValue(shader->color(), selectionSkipColor); + } else { + shader->setUniformValue(shader->color(), backgroundColor); + } + shader->setUniformValue(shader->ambientS(), + m_cachedTheme->ambientLightStrength() * 2.0f); + shader->setUniformValue(shader->lightColor(), lightColor); + + // Draw floor modelMatrix.scale(backgroundScaler); - itModelMatrix.scale(backgroundScaler); - modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); - itModelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + + if (m_yFlipped) + modelMatrix.rotate(m_xRightAngleRotation); + else + modelMatrix.rotate(m_xRightAngleRotationNeg); + + itModelMatrix = modelMatrix; #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionViewMatrix * modelMatrix; #else MVPMatrix = projectionViewMatrix * modelMatrix; #endif - QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor()); - - // Set shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); - m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), - itModelMatrix.inverted().transposed()); - m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor); - m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), - m_cachedTheme->ambientLightStrength() * 2.0f); - m_backgroundShader->setUniformValue(m_backgroundShader->lightColor(), lightColor); + // Set changed shader bindings + shader->setUniformValue(shader->model(), modelMatrix); + shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed()); + shader->setUniformValue(shader->MVP(), MVPMatrix); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && !m_isOpenGLES) { // Set shadow shader bindings QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), - m_shadowQualityToShader); - m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - adjustedLightStrength); - + shader->setUniformValue(shader->depth(), depthMVPMatrix); // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_cachedTheme->lightStrength()); - + m_drawer->drawObject(shader, m_gridLineObj, 0, m_depthTexture); + } else { // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj); + m_drawer->drawObject(shader, m_gridLineObj); } - // Draw floor + // Draw walls modelMatrix = QMatrix4x4(); itModelMatrix = QMatrix4x4(); + modelMatrix.translate(0.0f, m_backgroundAdjustment, 0.0f); modelMatrix.scale(backgroundScaler); - - if (m_yFlipped) - modelMatrix.rotate(90.0f, 1.0f, 0.0f, 0.0f); - else - modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); - - itModelMatrix = modelMatrix; + itModelMatrix.scale(backgroundScaler); + modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + itModelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionViewMatrix * modelMatrix; #else MVPMatrix = projectionViewMatrix * modelMatrix; #endif + // Set changed shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), - itModelMatrix.inverted().transposed()); - m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); + shader->setUniformValue(shader->model(), modelMatrix); + shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed()); + shader->setUniformValue(shader->MVP(), MVPMatrix); + if (!m_reflectionEnabled || (m_reflectionEnabled && reflectingDraw)) { + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && !m_isOpenGLES) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + shader->setUniformValue(shader->shadowQ(), m_shadowQualityToShader); + shader->setUniformValue(shader->depth(), depthMVPMatrix); + shader->setUniformValue(shader->lightS(), adjustedLightStrength); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_gridLineObj, 0, m_depthTexture); - } else -#endif - { - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_gridLineObj); + // Draw the object + m_drawer->drawObject(shader, m_backgroundObj, 0, m_depthTexture); + } else { + // Set shadowless shader bindings + shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength()); + + // Draw the object + m_drawer->drawObject(shader, m_backgroundObj); + } } } +} - // Disable textures - glDisable(GL_TEXTURE_2D); - - // Draw grid lines +void Bars3DRenderer::drawGridLines(const QMatrix4x4 &depthProjectionViewMatrix, + const QMatrix4x4 &projectionViewMatrix, + const QMatrix4x4 &viewMatrix) +{ if (m_cachedTheme->isGridEnabled()) { -#if !(defined QT_OPENGL_ES_2) - ShaderHelper *lineShader = m_backgroundShader; -#else - ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES -#endif + ShaderHelper *lineShader; + if (m_isOpenGLES) + lineShader = m_selectionShader; // Plain color shader for GL_LINES + else + lineShader = m_backgroundShader; + QQuaternion lineRotation; + QVector3D lightPos = m_cachedScene->activeLight()->position(); + QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); + // Bind bar shader lineShader->bind(); @@ -1607,15 +1819,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) lineShader->setUniformValue(lineShader->color(), barColor); lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength()); lineShader->setUniformValue(lineShader->lightColor(), lightColor); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && !m_isOpenGLES) { // Set shadowed shader bindings lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 20.0f); - } else -#endif - { + } else { // Set shadowless shader bindings lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f); @@ -1625,12 +1834,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) if (m_yFlipped) yFloorLinePosition = -yFloorLinePosition; - QVector3D gridLineScaler(rowScaleFactor, gridLineWidth, gridLineWidth); + QVector3D gridLineScaler(m_scaleXWithBackground, gridLineWidth, gridLineWidth); if (m_yFlipped) - lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f); + lineRotation = m_xRightAngleRotation; else - lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f); + lineRotation = m_xRightAngleRotationNeg; // Floor lines: rows for (GLfloat row = 0.0f; row <= m_cachedRowCount; row++) { @@ -1638,7 +1847,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; - rowPos = row * m_cachedBarSpacing.height(); + GLfloat rowPos = row * m_cachedBarSpacing.height(); modelMatrix.translate(0.0f, yFloorLinePosition, (m_columnDepth - rowPos) / m_scaleFactor); modelMatrix.scale(gridLineScaler); @@ -1654,33 +1863,32 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) itModelMatrix.inverted().transposed()); lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + if (m_isOpenGLES) { + m_drawer->drawLine(lineShader); } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } } -#else - m_drawer->drawLine(lineShader); -#endif } // Floor lines: columns -#if defined(QT_OPENGL_ES_2) - lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); -#endif - gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor); + if (m_isOpenGLES) + lineRotation = m_yRightAngleRotation; + gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, m_scaleZWithBackground); for (GLfloat bar = 0.0f; bar <= m_cachedColumnCount; bar++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; - colPos = bar * m_cachedBarSpacing.width(); + GLfloat colPos = bar * m_cachedBarSpacing.width(); modelMatrix.translate((m_rowWidth - colPos) / m_scaleFactor, yFloorLinePosition, 0.0f); modelMatrix.scale(gridLineScaler); @@ -1696,31 +1904,31 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) itModelMatrix.inverted().transposed()); lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + if (m_isOpenGLES) { + m_drawer->drawLine(lineShader); } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } } -#else - m_drawer->drawLine(lineShader); -#endif } if (m_axisCacheY.segmentCount() > 0) { // Wall lines: back wall int gridLineCount = m_axisCacheY.gridLineCount(); - GLfloat zWallLinePosition = -columnScaleFactor + gridLineOffset; + GLfloat zWallLinePosition = -m_scaleZWithBackground + gridLineOffset; if (m_zFlipped) zWallLinePosition = -zWallLinePosition; - gridLineScaler = QVector3D(rowScaleFactor, gridLineWidth, gridLineWidth); + gridLineScaler = QVector3D(m_scaleXWithBackground, gridLineWidth, gridLineWidth); for (int line = 0; line < gridLineCount; line++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1732,8 +1940,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) modelMatrix.scale(gridLineScaler); itModelMatrix.scale(gridLineScaler); if (m_zFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xFlipRotation); + itModelMatrix.rotate(m_xFlipRotation); } MVPMatrix = projectionViewMatrix * modelMatrix; @@ -1744,33 +1952,33 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) itModelMatrix.inverted().transposed()); lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + if (m_isOpenGLES) { + m_drawer->drawLine(lineShader); } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } } -#else - m_drawer->drawLine(lineShader); -#endif } // Wall lines: side wall - GLfloat xWallLinePosition = -rowScaleFactor + gridLineOffset; + GLfloat xWallLinePosition = -m_scaleXWithBackground + gridLineOffset; if (m_xFlipped) xWallLinePosition = -xWallLinePosition; if (m_xFlipped) - lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f); + lineRotation = m_yRightAngleRotationNeg; else - lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineRotation = m_yRightAngleRotation; - gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor); + gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, m_scaleZWithBackground); for (int line = 0; line < gridLineCount; line++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1792,76 +2000,27 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) itModelMatrix.inverted().transposed()); lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + if (m_isOpenGLES) { + m_drawer->drawLine(lineShader); } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } } -#else - m_drawer->drawLine(lineShader); -#endif } } } - - Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); - - drawLabels(false, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor, - columnScaleFactor); - - // Handle selected bar label generation - if (barSelectionFound) { - // Print value of selected bar - glDisable(GL_DEPTH_TEST); - // Draw the selection label - LabelItem &labelItem = selectionLabelItem(); - if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId() - || m_selectionLabelDirty) { - QString labelText = selectionLabel(); - if (labelText.isNull() || m_selectionLabelDirty) { - labelText = m_selectedSeriesCache->itemLabel(); - setSelectionLabel(labelText); - m_selectionLabelDirty = false; - } - m_drawer->generateLabelItem(labelItem, labelText); - m_selectedBar = selectedBar; - } - - Drawer::LabelPosition position = - m_selectedBar->height() >= 0 ? Drawer::LabelOver : Drawer::LabelBelow; - - m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix, - zeroVector, identityQuaternion, selectedBar->height(), - m_cachedSelectionMode, m_labelShader, - m_labelObj, activeCamera, true, false, position); - - // Reset label update flag; they should have been updated when we get here - m_updateLabels = false; - - glEnable(GL_DEPTH_TEST); - } else { - m_selectedBar = 0; - } - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - - // Release shader - glUseProgram(0); - m_selectionDirty = false; } void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera, - const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix, - GLfloat rowScaleFactor, GLfloat columnScaleFactor) { + const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix) { ShaderHelper *shader = 0; GLfloat alphaForValueSelection = labelValueAlpha / 255.0f; GLfloat alphaForRowSelection = labelRowAlpha / 255.0f; @@ -1873,7 +2032,6 @@ void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamer shader = m_labelShader; shader->bind(); - glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } @@ -1894,8 +2052,8 @@ void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamer int labelCount = m_axisCacheY.labelCount(); GLfloat labelMarginXTrans = labelMargin; GLfloat labelMarginZTrans = labelMargin; - GLfloat labelXTrans = rowScaleFactor; - GLfloat labelZTrans = columnScaleFactor; + GLfloat labelXTrans = m_scaleXWithBackground; + GLfloat labelZTrans = m_scaleZWithBackground; QVector3D backLabelRotation(0.0f, -90.0f, 0.0f); QVector3D sideLabelRotation(0.0f, 0.0f, 0.0f); Qt::AlignmentFlag backAlignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight; @@ -1999,10 +2157,8 @@ void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamer fractionCamY = activeCamera->yRotation() * labelAngleFraction; fractionCamX = activeCamera->xRotation() * labelAngleFraction; GLfloat labelYAdjustment = 0.005f; - GLfloat scaledRowWidth = rowScaleFactor; - GLfloat scaledColumnDepth = columnScaleFactor; - GLfloat colPosValue = scaledRowWidth + labelMargin; - GLfloat rowPosValue = scaledColumnDepth + labelMargin; + GLfloat colPosValue = m_scaleXWithBackground + labelMargin; + GLfloat rowPosValue = m_scaleZWithBackground + labelMargin; GLfloat rowPos = 0.0f; GLfloat colPos = 0.0f; Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight; @@ -2296,14 +2452,8 @@ void Bars3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientatio { Abstract3DRenderer::updateAxisRange(orientation, min, max); - if (orientation == QAbstract3DAxis::AxisOrientationY) { - // Check if we have negative values - if (min < 0) - m_hasNegativeValues = true; - else if (min >= 0) - m_hasNegativeValues = false; + if (orientation == QAbstract3DAxis::AxisOrientationY) calculateHeightAdjustment(); - } } void Bars3DRenderer::updateAxisReversed(QAbstract3DAxis::AxisOrientation orientation, bool enable) @@ -2384,10 +2534,12 @@ void Bars3DRenderer::updateShadowQuality(QAbstract3DGraph::ShadowQuality quality handleShadowQualityChange(); -#if !defined(QT_OPENGL_ES_2) // Re-init depth buffer updateDepthBuffer(); -#endif + + // Redraw to handle both reflections and shadows on background + if (m_reflectionEnabled) + needRender(); } void Bars3DRenderer::loadBackgroundMesh() @@ -2398,6 +2550,8 @@ void Bars3DRenderer::loadBackgroundMesh() void Bars3DRenderer::updateTextures() { + Abstract3DRenderer::updateTextures(); + // Drawer has changed; this flag needs to be checked when checking if we need to update labels m_updateLabels = true; } @@ -2420,30 +2574,60 @@ void Bars3DRenderer::calculateSceneScalingFactors() m_maxDimension = qMax(m_rowWidth, m_columnDepth); m_scaleFactor = qMin((m_cachedColumnCount * (m_maxDimension / m_maxSceneSize)), (m_cachedRowCount * (m_maxDimension / m_maxSceneSize))); + + // Single bar scaling m_scaleX = m_cachedBarThickness.width() / m_scaleFactor; m_scaleZ = m_cachedBarThickness.height() / m_scaleFactor; + + // Whole graph scale factors + m_xScaleFactor = m_rowWidth / m_scaleFactor; + m_zScaleFactor = m_columnDepth / m_scaleFactor; + + if (m_requestedMargin < 0.0f) { + m_hBackgroundMargin = 0.0f; + m_vBackgroundMargin = 0.0f; + } else { + m_hBackgroundMargin = m_requestedMargin; + m_vBackgroundMargin = m_requestedMargin; + } + + m_scaleXWithBackground = m_xScaleFactor + m_hBackgroundMargin; + m_scaleYWithBackground = 1.0f + m_vBackgroundMargin; + m_scaleZWithBackground = m_zScaleFactor + m_hBackgroundMargin; + + updateCameraViewport(); + updateCustomItemPositions(); } void Bars3DRenderer::calculateHeightAdjustment() { + float min = m_axisCacheY.min(); + float max = m_axisCacheY.max(); GLfloat newAdjustment = 1.0f; - GLfloat maxAbs = qFabs(m_axisCacheY.max()); - - if (m_axisCacheY.max() < 0.0f) { - m_heightNormalizer = GLfloat(qFabs(m_axisCacheY.min()) - qFabs(m_axisCacheY.max())); - maxAbs = qFabs(m_axisCacheY.max()) - qFabs(m_axisCacheY.min()); + m_actualFloorLevel = qBound(min, m_floorLevel, max); + GLfloat maxAbs = qFabs(max - m_actualFloorLevel); + + // Check if we have negative values + if (min < m_actualFloorLevel) + m_hasNegativeValues = true; + else if (min >= m_actualFloorLevel) + m_hasNegativeValues = false; + + if (max < m_actualFloorLevel) { + m_heightNormalizer = GLfloat(qFabs(min) - qFabs(max)); + maxAbs = qFabs(max) - qFabs(min); } else { - m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min()); + m_heightNormalizer = GLfloat(max - min); } // Height fractions are used in gradient calculations and are therefore doubled // Note that if max or min is exactly zero, we still consider it outside the range - if (m_axisCacheY.max() <= 0.0f || m_axisCacheY.min() >= 0.0f) { + if (max <= m_actualFloorLevel || min >= m_actualFloorLevel) { m_noZeroInRange = true; m_gradientFraction = 2.0f; } else { m_noZeroInRange = false; - GLfloat minAbs = qFabs(m_axisCacheY.min()); + GLfloat minAbs = qFabs(min - m_actualFloorLevel); m_gradientFraction = qMax(minAbs, maxAbs) / m_heightNormalizer * 2.0f; } @@ -2551,13 +2735,13 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing) m_cachedIsSlicingActivated = isSlicing; - if (!m_cachedIsSlicingActivated) - initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize + if (!m_cachedIsSlicingActivated) { + // We need to re-init selection buffer in case there has been a resize + initSelectionBuffer(); + initCursorPositionBuffer(); + } -#if !defined(QT_OPENGL_ES_2) updateDepthBuffer(); // Re-init depth buffer as well -#endif - m_selectionDirty = true; } @@ -2598,32 +2782,35 @@ void Bars3DRenderer::initSelectionBuffer() m_selectionDepthBuffer); } -#if !defined(QT_OPENGL_ES_2) void Bars3DRenderer::initDepthShader() { - if (m_depthShader) - delete m_depthShader; - m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), - QStringLiteral(":/shaders/fragmentDepth")); - m_depthShader->initialize(); + if (!m_isOpenGLES) { + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); + } } void Bars3DRenderer::updateDepthBuffer() { - m_textureHelper->deleteTexture(&m_depthTexture); + if (!m_isOpenGLES) { + m_textureHelper->deleteTexture(&m_depthTexture); - if (m_primarySubViewport.size().isEmpty()) - return; + if (m_primarySubViewport.size().isEmpty()) + return; - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(), - m_depthFrameBuffer, - m_shadowQualityMultiplier); - if (!m_depthTexture) - lowerShadowQuality(); + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + m_depthTexture = + m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(), + m_depthFrameBuffer, + m_shadowQualityMultiplier); + if (!m_depthTexture) + lowerShadowQuality(); + } } } -#endif void Bars3DRenderer::initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) @@ -2634,14 +2821,6 @@ void Bars3DRenderer::initBackgroundShaders(const QString &vertexShader, m_backgroundShader->initialize(); } -void Bars3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_labelShader) - delete m_labelShader; - m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_labelShader->initialize(); -} - QVector3D Bars3DRenderer::convertPositionToTranslation(const QVector3D &position, bool isAbsolute) { float xTrans = 0.0f; @@ -2649,15 +2828,15 @@ QVector3D Bars3DRenderer::convertPositionToTranslation(const QVector3D &position float zTrans = 0.0f; if (!isAbsolute) { // Convert row and column to translation on graph - xTrans = (((position.x() + 0.5f) * m_cachedBarSpacing.width()) - m_rowWidth) - / m_scaleFactor; - zTrans = (m_columnDepth - ((position.z() + 0.5f) * m_cachedBarSpacing.height())) - / m_scaleFactor; + xTrans = (((position.x() - m_axisCacheX.min() + 0.5f) * m_cachedBarSpacing.width()) + - m_rowWidth) / m_scaleFactor; + zTrans = (m_columnDepth - ((position.z() - m_axisCacheZ.min() + 0.5f) + * m_cachedBarSpacing.height())) / m_scaleFactor; yTrans = m_axisCacheY.positionAt(position.y()); } else { - xTrans = position.x() * m_scaleX; + xTrans = position.x() * m_xScaleFactor; yTrans = position.y() + m_backgroundAdjustment; - zTrans = position.z() * m_scaleZ; + zTrans = position.z() * -m_zScaleFactor; } return QVector3D(xTrans, yTrans, zTrans); } @@ -2667,4 +2846,18 @@ void Bars3DRenderer::updateAspectRatio(float ratio) Q_UNUSED(ratio) } +void Bars3DRenderer::updateFloorLevel(float level) +{ + foreach (SeriesRenderCache *cache, m_renderCacheList) + cache->setDataDirty(true); + m_floorLevel = level; + calculateHeightAdjustment(); +} + +void Bars3DRenderer::updateMargin(float margin) +{ + Abstract3DRenderer::updateMargin(margin); + calculateSceneScalingFactors(); +} + QT_END_NAMESPACE_DATAVISUALIZATION |