From a30c0c304e55ffe30545ab0838e4dbe11a99b8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomi=20Korpip=C3=A4=C3=A4?= Date: Tue, 15 Apr 2014 10:32:03 +0300 Subject: Add custom item support, part 1 Task-number: QTRD-2866 + Added API for adding and removing custom items + Added custom data and custom render items + Added shaders for textured objects + Added custom item rendering draft to scatter + Fixed some shaders - to be continued in part 2 Change-Id: I9735fd02fc9e86ae486cca4c06f6d7f2a4b0b7da Reviewed-by: Mika Salmela --- .../engine/abstract3dcontroller.cpp | 39 ++++++- .../engine/abstract3dcontroller_p.h | 8 ++ .../engine/abstract3drenderer.cpp | 20 +++- .../engine/abstract3drenderer_p.h | 15 ++- src/datavisualization/engine/bars3drenderer.cpp | 25 +++++ src/datavisualization/engine/bars3drenderer_p.h | 4 + src/datavisualization/engine/engine.qrc | 2 + src/datavisualization/engine/qabstract3dgraph.cpp | 32 ++++++ src/datavisualization/engine/qabstract3dgraph.h | 8 +- src/datavisualization/engine/scatter3drenderer.cpp | 124 +++++++++++++++++++++ src/datavisualization/engine/scatter3drenderer_p.h | 6 + src/datavisualization/engine/shaders/default.vert | 8 +- src/datavisualization/engine/shaders/shadow.vert | 8 +- .../engine/shaders/surfaceFlat.vert | 8 +- .../engine/shaders/surfaceShadowFlat.vert | 8 +- src/datavisualization/engine/shaders/texture.frag | 37 ++++++ .../engine/shaders/texture_ES2.frag | 40 +++++++ src/datavisualization/engine/surface3drenderer.cpp | 32 +++++- src/datavisualization/engine/surface3drenderer_p.h | 4 + 19 files changed, 403 insertions(+), 25 deletions(-) create mode 100644 src/datavisualization/engine/shaders/texture.frag create mode 100644 src/datavisualization/engine/shaders/texture_ES2.frag (limited to 'src/datavisualization/engine') diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index 885904d4..e10069ff 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -50,6 +50,7 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen m_axisZ(0), m_renderer(0), m_isDataDirty(true), + m_isCustomDataDirty(true), m_isSeriesVisualsDirty(true), m_renderPending(false), m_measureFps(false), @@ -87,6 +88,9 @@ Abstract3DController::~Abstract3DController() destroyRenderer(); delete m_scene; delete m_themeManager; + foreach (CustomDataItem *item, m_customItems) + delete item; + m_customItems.clear(); } void Abstract3DController::destroyRenderer() @@ -369,6 +373,11 @@ void Abstract3DController::synchDataToRenderer() m_renderer->updateData(); m_isDataDirty = false; } + + if (m_isCustomDataDirty) { + m_renderer->updateCustomData(m_customItems); + m_isCustomDataDirty = false; + } } void Abstract3DController::render(const GLuint defaultFboHandle) @@ -814,6 +823,30 @@ void Abstract3DController::requestRender(QOpenGLFramebufferObject *fbo) m_renderer->render(fbo->handle()); } +int Abstract3DController::addCustomItem(const QString &meshFile, const QVector3D &position, + const QVector3D &scaling, const QQuaternion &rotation, + const QImage &textureImage) +{ + CustomDataItem *newItem = new CustomDataItem(); + newItem->setMeshFile(meshFile); + newItem->setPosition(position); + newItem->setScaling(scaling); + newItem->setRotation(rotation); + newItem->setTextureImage(textureImage); + m_customItems.append(newItem); + m_isCustomDataDirty = true; + emitNeedRender(); + return m_customItems.count() - 1; +} + +void Abstract3DController::deleteCustomItem(int index) +{ + delete m_customItems[index]; + m_customItems.removeAt(index); + m_isCustomDataDirty = true; + emitNeedRender(); +} + void Abstract3DController::handleAxisTitleChanged(const QString &title) { Q_UNUSED(title) @@ -974,9 +1007,9 @@ void Abstract3DController::setMeasureFps(bool enable) m_currentFps = 0.0; if (enable) { - m_frameTimer.start(); - m_numFrames = -1; - emitNeedRender(); + m_frameTimer.start(); + m_numFrames = -1; + emitNeedRender(); } emit measureFpsChanged(enable); } diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index 4f597769..98df8fda 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -35,6 +35,7 @@ #include "qabstract3dinputhandler.h" #include "qabstractdataproxy.h" #include "q3dscene_p.h" +#include "customdataitem_p.h" #include #include @@ -155,6 +156,7 @@ protected: QList m_axes; // List of all added axes Abstract3DRenderer *m_renderer; bool m_isDataDirty; + bool m_isCustomDataDirty; bool m_isSeriesVisualsDirty; bool m_renderPending; @@ -167,6 +169,8 @@ protected: QVector m_changedSeriesList; + QList m_customItems; + explicit Abstract3DController(QRect initialViewport, Q3DScene *scene, QObject *parent = 0); public: @@ -226,6 +230,10 @@ public: void requestRender(QOpenGLFramebufferObject *fbo); + int addCustomItem(const QString &meshFile, const QVector3D &position, const QVector3D &scaling, + const QQuaternion &rotation, const QImage &textureImage); + void deleteCustomItem(int index); + void emitNeedRender(); virtual void clearSelection() = 0; diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index f70d128b..1cb4bdba 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -27,6 +27,7 @@ #include "q3dtheme_p.h" #include "objecthelper_p.h" #include "qvalue3daxisformatter_p.h" +#include "shaderhelper_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -48,7 +49,8 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_clickedSeries(0), m_clickedType(QAbstract3DGraph::ElementNone), m_selectionLabelItem(0), - m_visibleSeriesCount(0) + m_visibleSeriesCount(0), + m_customItemShader(0) { QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures); @@ -65,6 +67,7 @@ Abstract3DRenderer::~Abstract3DRenderer() delete m_cachedScene; delete m_cachedTheme; delete m_selectionLabelItem; + delete m_customItemShader; foreach (SeriesRenderCache *cache, m_renderCacheList) { cache->cleanup(m_textureHelper); @@ -140,6 +143,15 @@ void Abstract3DRenderer::initGradientShaders(const QString &vertexShader, Q_UNUSED(fragmentShader) } +void Abstract3DRenderer::initCustomItemShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_customItemShader) + delete m_customItemShader; + m_customItemShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_customItemShader->initialize(); +} + void Abstract3DRenderer::updateTheme(Q3DTheme *theme) { // Synchronize the controller theme with renderer @@ -206,6 +218,8 @@ void Abstract3DRenderer::reInitShaders() QStringLiteral(":/shaders/fragmentShadowNoTex")); initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), QStringLiteral(":/shaders/fragmentShadowNoTex")); + initCustomItemShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadow")); } else { initGradientShaders(QStringLiteral(":/shaders/vertex"), QStringLiteral(":/shaders/fragmentColorOnY")); @@ -213,6 +227,8 @@ void Abstract3DRenderer::reInitShaders() QStringLiteral(":/shaders/fragment")); initBackgroundShaders(QStringLiteral(":/shaders/vertex"), QStringLiteral(":/shaders/fragment")); + initCustomItemShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentTexture")); } #else initGradientShaders(QStringLiteral(":/shaders/vertex"), @@ -221,6 +237,8 @@ void Abstract3DRenderer::reInitShaders() QStringLiteral(":/shaders/fragmentES2")); initBackgroundShaders(QStringLiteral(":/shaders/vertex"), QStringLiteral(":/shaders/fragmentES2")); + initCustomItemShaders(QStringLiteral(":/shaders/vertex"), // TODO: Need new shader? At least this one doesn't work + QStringLiteral(":/shaders/fragmentTextureES2")); #endif } diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index ce21deff..884c0f39 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -36,6 +36,7 @@ #include "axisrendercache_p.h" #include "qabstractdataproxy.h" #include "seriesrendercache_p.h" +#include "customrenderitem_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -55,13 +56,20 @@ protected: SelectOnSlice }; -// QString generateValueLabel(const QString &format, float value); + enum RenderingState { + RenderingNormal = 0, + RenderingSelection, + RenderingDepth + }; + + // QString generateValueLabel(const QString &format, float value); public: virtual ~Abstract3DRenderer(); virtual void updateData() = 0; virtual void updateSeries(const QList &seriesList); + virtual void updateCustomData(const QList &customItems) = 0; virtual SeriesRenderCache *createNewCache(QAbstract3DSeries *series); virtual void cleanCache(SeriesRenderCache *cache); virtual void render(GLuint defaultFboHandle); @@ -82,6 +90,8 @@ public: virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader); virtual void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) = 0; + virtual void initCustomItemShaders(const QString &vertexShader, + const QString &fragmentShader); virtual void updateAxisType(QAbstract3DAxis::AxisOrientation orientation, QAbstract3DAxis::AxisType type); virtual void updateAxisTitle(QAbstract3DAxis::AxisOrientation orientation, @@ -150,6 +160,7 @@ protected: SelectionState m_selectionState; QPoint m_inputPosition; QHash m_renderCacheList; + CustomRenderItemArray m_customRenderCache; QRect m_primarySubViewport; QRect m_secondarySubViewport; float m_devicePixelRatio; @@ -161,6 +172,8 @@ protected: QString m_selectionLabel; LabelItem *m_selectionLabelItem; int m_visibleSeriesCount; + + ShaderHelper *m_customItemShader; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index c8b25463..f02b9910 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -299,6 +299,11 @@ void Bars3DRenderer::updateSeries(const QList &seriesList) m_selectionLabelDirty = true; } +void Bars3DRenderer::updateCustomData(const QList &customItems) +{ + // TODO +} + SeriesRenderCache *Bars3DRenderer::createNewCache(QAbstract3DSeries *series) { return new BarSeriesRenderCache(series, this); @@ -987,6 +992,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } + drawCustomItems(RenderingDepth, m_depthShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + // Disable drawing to depth framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -1067,6 +1075,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } glCullFace(GL_BACK); + drawCustomItems(RenderingSelection, m_selectionShader, activeCamera, projectionMatrix, + depthProjectionMatrix); drawLabels(true, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor, columnScaleFactor); glEnable(GL_DITHER); @@ -1363,6 +1373,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_POLYGON_OFFSET_FILL); + drawCustomItems(RenderingNormal, m_customItemShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + // Bind background shader m_backgroundShader->bind(); @@ -1732,6 +1745,14 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_selectionDirty = false; } +void Bars3DRenderer::drawCustomItems(RenderingState state, ShaderHelper *shader, + const Q3DCamera *activeCamera, + const QMatrix4x4 &projectionMatrix, + const QMatrix4x4 &depthProjectionMatrix) +{ + // TODO +} + void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix, GLfloat rowScaleFactor, GLfloat columnScaleFactor) { @@ -2189,6 +2210,10 @@ QPoint Bars3DRenderer::selectionColorToArrayPosition(const QVector4D &selectionC position = Bars3DController::invalidSelectionPosition(); // Pass label clicked info to input handler m_clickedType = QAbstract3DGraph::ElementAxisYLabel; + } else if (selectionColor.w() == customItemAlpha) { + // Custom item selection + position = Bars3DController::invalidSelectionPosition(); + m_clickedType = QAbstract3DGraph::ElementCustomItem; } return position; } diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 549a63f6..efe84d39 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -115,6 +115,7 @@ public: void updateData(); void updateSeries(const QList &seriesList); + void updateCustomData(const QList &customItems); SeriesRenderCache *createNewCache(QAbstract3DSeries *series); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); @@ -145,6 +146,9 @@ private: void drawSlicedScene(); void drawScene(GLuint defaultFboHandle); + void drawCustomItems(RenderingState state, ShaderHelper *shader, const Q3DCamera *activeCamera, + const QMatrix4x4 &projectionMatrix, + const QMatrix4x4 &depthProjectionMatrix); void drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix, GLfloat rowScaleFactor, GLfloat columnScaleFactor); diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc index 18cba7fe..38a9e651 100644 --- a/src/datavisualization/engine/engine.qrc +++ b/src/datavisualization/engine/engine.qrc @@ -54,5 +54,7 @@ shaders/surfaceShadowNoTex.frag shaders/surfaceShadowFlat.frag shaders/surfaceShadowFlat.vert + shaders/texture.frag + shaders/texture_ES2.frag diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp index 703cd18b..0d1bdfc9 100644 --- a/src/datavisualization/engine/qabstract3dgraph.cpp +++ b/src/datavisualization/engine/qabstract3dgraph.cpp @@ -135,6 +135,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION Z axis label. \value ElementAxisYLabel Y axis label. + \value ElementCustomItem + Custom item. */ /*! @@ -379,6 +381,36 @@ void QAbstract3DGraph::clearSelection() d_ptr->m_visualController->clearSelection(); } +/*! + * Adds a custom mesh item located in \a meshFile to a graph at \a position with \a {scaling}, + * \a rotation and optional \a textureImage. Item must be in Wavefront obj format and include + * vertices, normals and UVs. It also needs to be in triangles. Item position is given in data + * coordinates. + * + * \return index to the added item. + * + * \sa removeCustomItemAt() + * + * \since Qt Data Visualization 1.1 + */ +int QAbstract3DGraph::addCustomItem(const QString &meshFile, const QVector3D &position, + const QVector3D &scaling, const QQuaternion &rotation, + const QImage &textureImage) +{ + return d_ptr->m_visualController->addCustomItem(meshFile, position, scaling, rotation, + textureImage); +} + +/*! + * Removes the custom item at \a {index}. Deletes the resource allocated to it. + * + * \since Qt Data Visualization 1.1 + */ +void QAbstract3DGraph::removeCustomItemAt(int index) +{ + d_ptr->m_visualController->deleteCustomItem(index); +} + /*! * Renders current frame to an image of \a imageSize. Default size is the window size. Image is * rendered with antialiasing level given in \a msaaSamples. Default level is \c{0}. diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h index 2f417c2f..2e909b1d 100644 --- a/src/datavisualization/engine/qabstract3dgraph.h +++ b/src/datavisualization/engine/qabstract3dgraph.h @@ -77,7 +77,8 @@ public: ElementSeries, ElementAxisXLabel, ElementAxisZLabel, - ElementAxisYLabel + ElementAxisYLabel, + ElementCustomItem }; public: @@ -106,6 +107,11 @@ public: void clearSelection(); + int addCustomItem(const QString &meshFile, const QVector3D &position, + const QVector3D &scaling, const QQuaternion &rotation, + const QImage &textureImage = QImage()); + void removeCustomItemAt(int index); + QImage renderToImage(int msaaSamples = 0, const QSize &imageSize = QSize()); void setMeasureFps(bool enable); diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index ef39deba..b1c5e903 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -267,6 +267,19 @@ void Scatter3DRenderer::updateSeries(const QList &seriesLis m_selectionLabelDirty = true; } +void Scatter3DRenderer::updateCustomData(const QList &customItems) +{ + if (customItems.isEmpty() && m_customRenderCache.isEmpty()) + return; + + // There are probably not too many custom items, just recreate the array if something changes + foreach (CustomRenderItem *item, m_customRenderCache) + delete item; + m_customRenderCache.clear(); + foreach (CustomDataItem *item, customItems) + addCustomItem(item); +} + SeriesRenderCache *Scatter3DRenderer::createNewCache(QAbstract3DSeries *series) { return new ScatterSeriesRenderCache(series, this); @@ -469,6 +482,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } } + drawCustomItems(RenderingDepth, m_depthShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + // Disable drawing to framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -566,6 +582,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } } + drawCustomItems(RenderingSelection, m_selectionShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + drawLabels(true, activeCamera, viewMatrix, projectionMatrix); glEnable(GL_DITHER); @@ -794,6 +813,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } #endif + drawCustomItems(RenderingNormal, m_customItemShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + // Bind background shader m_backgroundShader->bind(); @@ -1305,6 +1327,87 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) m_selectionDirty = false; } +void Scatter3DRenderer::drawCustomItems(RenderingState state, ShaderHelper *shader, + const Q3DCamera *activeCamera, + const QMatrix4x4 &projectionMatrix, + const QMatrix4x4 &depthProjectionMatrix) +{ + if (m_customRenderCache.isEmpty()) + return; + + int itemIndex = 0; + QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix(); + QMatrix4x4 depthViewMatrix; + QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix; + QVector3D depthLightPos = activeCamera->d_ptr->calculatePositionRelativeToCamera( + zeroVector, 0.0f, 2.5f / m_autoScaleAdjustment); + depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector); + QMatrix4x4 depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix; + + if (RenderingNormal == state) { + shader->bind(); + shader->setUniformValue(shader->lightP(), m_cachedScene->activeLight()->position()); + shader->setUniformValue(shader->ambientS(), m_cachedTheme->ambientLightStrength()); + shader->setUniformValue(shader->lightColor(), + Utils::vectorFromColor(m_cachedTheme->lightColor())); + shader->setUniformValue(shader->view(), viewMatrix); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Draw custom items + foreach (CustomRenderItem *item, m_customRenderCache) { + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(item->translation()); + modelMatrix.rotate(item->rotation()); + modelMatrix.scale(item->scaling()); + itModelMatrix.rotate(item->rotation()); + itModelMatrix.scale(item->scaling()); + + if (RenderingNormal == state) { + // Normal render + shader->setUniformValue(shader->model(), modelMatrix); + shader->setUniformValue(shader->MVP(), projectionViewMatrix * modelMatrix); + shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed()); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + shader->setUniformValue(shader->shadowQ(), m_shadowQualityToShader); + shader->setUniformValue(shader->depth(), depthProjectionViewMatrix * modelMatrix); + shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength() / 10.0f); + m_drawer->drawObject(shader, item->mesh(), item->texture(), m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength()); + m_drawer->drawObject(shader, item->mesh(), item->texture()); + } + } else if (RenderingSelection == state) { + // Selection render + QVector4D itemColor = indexToSelectionColor(itemIndex++); + itemColor.setW(customItemAlpha); + itemColor /= 255.0f; + shader->setUniformValue(shader->color(), itemColor); + m_drawer->drawObject(shader, item->mesh()); + } else { + // Depth render + shader->setUniformValue(shader->MVP(), depthProjectionViewMatrix * modelMatrix); + m_drawer->drawObject(shader, item->mesh()); + } + } + + if (RenderingNormal == state) { + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + } +} + void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix) { @@ -1761,6 +1864,7 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color, { m_clickedType = QAbstract3DGraph::ElementNone; if (color != selectionSkipColor) { + qDebug() << __FUNCTION__ << color.w(); if (color.w() == labelRowAlpha) { // Row selection index = Scatter3DController::invalidSelectionIndex(); @@ -1773,6 +1877,11 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color, // Value selection index = Scatter3DController::invalidSelectionIndex(); m_clickedType = QAbstract3DGraph::ElementAxisYLabel; + } else if (color.w() == customItemAlpha) { + // Custom item selection + index = Scatter3DController::invalidSelectionIndex(); + m_clickedType = QAbstract3DGraph::ElementCustomItem; + qDebug() << "custom item selected"; } else { int totalIndex = int(color.x()) + (int(color.y()) << 8) @@ -1800,4 +1909,19 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color, series = 0; } +void Scatter3DRenderer::addCustomItem(CustomDataItem *item) { + CustomRenderItem *newItem = new CustomRenderItem(); + newItem->setMesh(item->m_meshFile); + newItem->setScaling(item->m_scaling); + newItem->setRotation(item->m_rotation); + newItem->setTexture(item->m_texture); + const QVector3D &pos = item->m_position; + float xTrans = m_axisCacheX.positionAt(pos.x()); + float yTrans = m_axisCacheY.positionAt(pos.y()); + float zTrans = m_axisCacheZ.positionAt(pos.z()); + newItem->setTranslation(QVector3D(xTrans, yTrans, zTrans)); + m_customRenderCache.append(newItem); + qDebug() << __FUNCTION__ << item->m_meshFile << newItem->rotation() << newItem->scaling() << newItem->translation(); +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index ab45381e..3aad8788 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -104,6 +104,7 @@ public: void updateData(); void updateSeries(const QList &seriesList); + void updateCustomData(const QList &customItems); SeriesRenderCache *createNewCache(QAbstract3DSeries *series); void updateScene(Q3DScene *scene); @@ -123,6 +124,9 @@ private: virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh); void drawScene(GLuint defaultFboHandle); + void drawCustomItems(RenderingState state, ShaderHelper *shader, const Q3DCamera *activeCamera, + const QMatrix4x4 &projectionMatrix, + const QMatrix4x4 &depthProjectionMatrix); void drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix); @@ -142,6 +146,8 @@ private: void calculateTranslation(ScatterRenderItem &item); void calculateSceneScalingFactors(); + void addCustomItem(CustomDataItem *item); + Q_DISABLE_COPY(Scatter3DRenderer) friend class ScatterRenderItem; diff --git a/src/datavisualization/engine/shaders/default.vert b/src/datavisualization/engine/shaders/default.vert index efb40862..e0718b20 100644 --- a/src/datavisualization/engine/shaders/default.vert +++ b/src/datavisualization/engine/shaders/default.vert @@ -17,10 +17,10 @@ varying highp vec2 coords_mdl; void main() { gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); coords_mdl = vertexPosition_mdl.xy; - position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; - vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = vec4(V * M * vec4(vertexPosition_mdl, 1.0)).xyz; eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; - vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz; lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; - normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; } diff --git a/src/datavisualization/engine/shaders/shadow.vert b/src/datavisualization/engine/shaders/shadow.vert index e29a8a30..0adcd43c 100644 --- a/src/datavisualization/engine/shaders/shadow.vert +++ b/src/datavisualization/engine/shaders/shadow.vert @@ -28,10 +28,10 @@ void main() { gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); coords_mdl = vertexPosition_mdl.xy; shadowCoord = bias * depthMVP * vec4(vertexPosition_mdl, 1.0); - position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; - vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = vec4(V * M * vec4(vertexPosition_mdl, 1.0)).xyz; eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; - lightDirection_cmr = (V * vec4(lightPosition_wrld, 0.0)).xyz; - normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + lightDirection_cmr = vec4(V * vec4(lightPosition_wrld, 0.0)).xyz; + normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; UV = vertexUV; } diff --git a/src/datavisualization/engine/shaders/surfaceFlat.vert b/src/datavisualization/engine/shaders/surfaceFlat.vert index 0d39f6bc..102bea78 100644 --- a/src/datavisualization/engine/shaders/surfaceFlat.vert +++ b/src/datavisualization/engine/shaders/surfaceFlat.vert @@ -20,10 +20,10 @@ varying highp vec3 coords_mdl; void main() { gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); coords_mdl = vertexPosition_mdl; - position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; - vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = vec4(V * M * vec4(vertexPosition_mdl, 1.0)).xyz; eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; - vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz; lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; - normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; } diff --git a/src/datavisualization/engine/shaders/surfaceShadowFlat.vert b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert index 0a6e967f..8da7b196 100644 --- a/src/datavisualization/engine/shaders/surfaceShadowFlat.vert +++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert @@ -28,10 +28,10 @@ void main() { gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); coords_mdl = vertexPosition_mdl; shadowCoord = bias * depthMVP * vec4(vertexPosition_mdl, 1.0); - position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; - vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = vec4(V * M * vec4(vertexPosition_mdl, 1.0)).xyz; eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; - vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz; lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; - normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; } diff --git a/src/datavisualization/engine/shaders/texture.frag b/src/datavisualization/engine/shaders/texture.frag new file mode 100644 index 00000000..69509a3f --- /dev/null +++ b/src/datavisualization/engine/shaders/texture.frag @@ -0,0 +1,37 @@ +#version 120 + +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform highp vec3 lightPosition_wrld; +uniform highp sampler2D textureSampler; +uniform highp float lightStrength; +uniform highp float ambientStrength; +uniform highp vec3 lightColor; + +void main() { + highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb; + highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor; + highp vec3 materialSpecularColor = lightColor; + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + + materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; + gl_FragColor.a = texture2D(textureSampler, UV).a; + gl_FragColor.rgb = clamp(gl_FragColor.rgb, 0.0, 1.0); +} + diff --git a/src/datavisualization/engine/shaders/texture_ES2.frag b/src/datavisualization/engine/shaders/texture_ES2.frag new file mode 100644 index 00000000..e749d763 --- /dev/null +++ b/src/datavisualization/engine/shaders/texture_ES2.frag @@ -0,0 +1,40 @@ +varying highp vec2 UV; +varying highp vec2 coords_mdl; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform highp vec3 lightPosition_wrld; +uniform highp sampler2D textureSampler; +uniform highp float lightStrength; +uniform highp float ambientStrength; +uniform highp vec3 lightColor; + +void main() { + highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb; + highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor; + highp vec3 materialSpecularColor = lightColor; + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = dot(n, l); + if (cosTheta < 0.0) cosTheta = 0.0; + else if (cosTheta > 1.0) cosTheta = 1.0; + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = dot(E, R); + if (cosAlpha < 0.0) cosAlpha = 0.0; + else if (cosAlpha > 1.0) cosAlpha = 1.0; + + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance + + materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance; + gl_FragColor.a = texture2D(textureSampler, UV).a; + gl_FragColor.rgb = clamp(gl_FragColor.rgb, 0.0, 1.0); +} + diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 0d5536e2..eeeaaf0d 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -41,8 +41,9 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION //#define SHOW_DEPTH_TEXTURE_SCENE const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd. -const GLfloat backgroundMargin = 1.1f; // Margin for background (1.10 make it 10% larger to avoid - // selection ball being drawn inside background) +// Margin for background (1.10 make it 10% larger to avoid +// selection ball being drawn inside background) +const GLfloat backgroundMargin = 1.1f; const GLfloat labelMargin = 0.05f; const GLfloat gridLineWidth = 0.005f; const GLfloat sliceZScale = 0.1f; @@ -293,6 +294,11 @@ void Surface3DRenderer::updateSeries(const QList &seriesLis } } +void Surface3DRenderer::updateCustomData(const QList &customItems) +{ + // TODO +} + SeriesRenderCache *Surface3DRenderer::createNewCache(QAbstract3DSeries *series) { m_selectionTexturesDirty = true; @@ -1133,6 +1139,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisableVertexAttribArray(m_depthShader->posAtt()); + drawCustomItems(RenderingDepth, m_depthShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + // Disable drawing to depth framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -1180,6 +1189,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) cache->selectionTexture()); } } + drawCustomItems(RenderingSelection, m_selectionShader, activeCamera, projectionMatrix, + depthProjectionMatrix); drawLabels(true, activeCamera, viewMatrix, projectionMatrix); glEnable(GL_DITHER); @@ -1310,6 +1321,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } } + drawCustomItems(RenderingNormal, m_customItemShader, activeCamera, projectionMatrix, + depthProjectionMatrix); + // Bind background shader m_backgroundShader->bind(); glCullFace(GL_BACK); @@ -1753,6 +1767,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } } +void Surface3DRenderer::drawCustomItems(RenderingState state, ShaderHelper *shader, + const Q3DCamera *activeCamera, + const QMatrix4x4 &projectionMatrix, + const QMatrix4x4 &depthProjectionMatrix) +{ + // TODO +} + void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix) { @@ -2235,7 +2257,7 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id) { m_clickedType = QAbstract3DGraph::ElementNone; - // Check for label selection + // Check for label and custom item selection if (id / alphaMultiplier == labelRowAlpha) { m_clickedType = QAbstract3DGraph::ElementAxisZLabel; return Surface3DController::invalidSelectionPosition(); @@ -2245,6 +2267,10 @@ QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id) } else if (id / alphaMultiplier == labelValueAlpha) { m_clickedType = QAbstract3DGraph::ElementAxisYLabel; return Surface3DController::invalidSelectionPosition(); + } else if (id / alphaMultiplier == customItemAlpha) { + // Custom item selection + m_clickedType = QAbstract3DGraph::ElementCustomItem; + return Surface3DController::invalidSelectionPosition(); } // Not a label selection diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index e1147e3c..98968dd5 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -106,6 +106,7 @@ public: void updateData(); void updateSeries(const QList &seriesList); + void updateCustomData(const QList &customItems); SeriesRenderCache *createNewCache(QAbstract3DSeries *series); void cleanCache(SeriesRenderCache *cache); void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode); @@ -141,6 +142,9 @@ private: void loadBackgroundMesh(); void loadLabelMesh(); void drawScene(GLuint defaultFboHandle); + void drawCustomItems(RenderingState state, ShaderHelper *shader, const Q3DCamera *activeCamera, + const QMatrix4x4 &projectionMatrix, + const QMatrix4x4 &depthProjectionMatrix); void drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix); void calculateSceneScalingFactors(); -- cgit v1.2.3