summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Korpipää <tomi.korpipaa@digia.com>2013-06-12 13:48:48 +0300
committerTomi Korpipää <tomi.korpipaa@digia.com>2013-06-12 13:48:48 +0300
commitb185e2c557bb987197ee9147f088724f6a06f4a0 (patch)
tree4c25116ae68193d14b18848d0db0ab1ed9780636
parentb61b63ff5e3b4ba7c4f4174c16b33bedadbfcfb8 (diff)
parent317f3f15fed855cfaa31a9b558bf1279583832e6 (diff)
Merge remote-tracking branch 'origin/master' into develop
Conflicts: examples/qmlbarchart/qml/qmlbarchart/main.qml src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro src/datavis3d/engine/q3dbars.cpp src/datavis3d/engine/q3dwindow.cpp src/datavis3dqml2/datavisview.cpp Change-Id: Ida37fd44e7e58aec07af09a6d1dde4ac4adbd8a4
-rw-r--r--examples/barchart/doc/images/barchart-example.pngbin0 -> 163146 bytes
-rw-r--r--examples/barchart/doc/src/barchart.qdoc37
-rw-r--r--examples/barchart/main.cpp2
-rw-r--r--examples/mapdata/doc/images/mapdata-example.pngbin0 -> 114152 bytes
-rw-r--r--examples/mapdata/doc/src/mapdata.qdoc38
-rw-r--r--examples/qmlbarchart/doc/src/qmlbarchart.qdoc38
-rw-r--r--examples/qmlbarchart/main.cpp2
-rw-r--r--examples/qmlbarchart/qml/qmlbarchart/main.qml123
-rw-r--r--examples/rainfall/doc/images/rainfall-example.pngbin0 -> 294202 bytes
-rw-r--r--examples/rainfall/doc/src/rainfall.qdoc37
-rw-r--r--examples/spectrum/doc/images/spectrum-example.pngbin0 -> 79769 bytes
-rw-r--r--examples/spectrum/doc/src/spectrum.qdoc37
-rw-r--r--examples/widget/doc/images/widget-example.pngbin0 -> 233825 bytes
-rw-r--r--examples/widget/doc/src/widget.qdoc38
-rw-r--r--src/datavis3d/doc/images/q3dbars-minimal.pngbin0 -> 7688 bytes
-rw-r--r--src/datavis3d/doc/qtdatavis3d.qdocconf62
-rw-r--r--src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp63
-rw-r--r--src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp (renamed from src/datavis3dqml2/datavisview.h)34
-rw-r--r--src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro (renamed from src/datavis3dqml2/datavisview.cpp)47
-rw-r--r--src/datavis3d/doc/src/qtdatavis3d-index.qdoc68
-rw-r--r--src/datavis3d/doc/src/qtdatavis3d.qdoc35
-rw-r--r--src/datavis3d/doc/src/qtdatavis3dlicense.qdoc40
-rw-r--r--src/datavis3d/engine/bars3dshared.cpp2421
-rw-r--r--src/datavis3d/engine/bars3dshared_p.h326
-rw-r--r--src/datavis3d/engine/drawer.cpp12
-rw-r--r--src/datavis3d/engine/drawer_p.h4
-rw-r--r--src/datavis3d/engine/engine.pri6
-rw-r--r--src/datavis3d/engine/q3dbars.cpp2655
-rw-r--r--src/datavis3d/engine/q3dbars.h24
-rw-r--r--src/datavis3d/engine/q3dbars_p.h115
-rw-r--r--src/datavis3d/engine/q3dmaps.cpp55
-rw-r--r--src/datavis3d/engine/q3dmaps.h7
-rw-r--r--src/datavis3d/engine/q3dwindow.cpp49
-rw-r--r--src/datavis3d/engine/q3dwindow.h13
-rw-r--r--src/datavis3d/engine/qdataitem.cpp59
-rw-r--r--src/datavis3d/engine/qdataitem.h5
-rw-r--r--src/datavis3d/engine/qdatarow.cpp34
-rw-r--r--src/datavis3d/engine/qdatarow.h3
-rw-r--r--src/datavis3d/engine/qdataset.cpp40
-rw-r--r--src/datavis3d/engine/qdataset.h3
-rw-r--r--src/datavis3d/engine/theme_p.h3
-rw-r--r--src/datavis3d/global/qdatavis3dglobal.h4
-rw-r--r--src/datavis3d/utils/objecthelper.cpp2
-rw-r--r--src/datavis3d/utils/texturehelper.cpp1
-rw-r--r--src/datavis3dqml2/datavis3dqml2.pro9
-rw-r--r--src/datavis3dqml2/datavis3dqml2_plugin.cpp10
-rw-r--r--src/datavis3dqml2/declarativebars.cpp316
-rw-r--r--src/datavis3dqml2/declarativebars.h150
-rw-r--r--src/datavis3dqml2/declarativebars_p.h (renamed from src/datavis3dqml2/scenerenderernode_p.h)60
-rw-r--r--src/datavis3dqml2/scenerenderernode.cpp117
50 files changed, 4541 insertions, 2663 deletions
diff --git a/examples/barchart/doc/images/barchart-example.png b/examples/barchart/doc/images/barchart-example.png
new file mode 100644
index 00000000..0f321c95
--- /dev/null
+++ b/examples/barchart/doc/images/barchart-example.png
Binary files differ
diff --git a/examples/barchart/doc/src/barchart.qdoc b/examples/barchart/doc/src/barchart.qdoc
new file mode 100644
index 00000000..498388bb
--- /dev/null
+++ b/examples/barchart/doc/src/barchart.qdoc
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example barchart
+ \title Barchart Example
+
+ The barchart example shows how to make a simple 3D bar chart using Q3DBars.
+
+ \image barchart-example.png
+
+ TODO
+*/
diff --git a/examples/barchart/main.cpp b/examples/barchart/main.cpp
index f2862bfd..6887bb0b 100644
--- a/examples/barchart/main.cpp
+++ b/examples/barchart/main.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the documentation of the Qt Toolkit.
+** This file is part of the documentation of the QtDataVis3D module.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
diff --git a/examples/mapdata/doc/images/mapdata-example.png b/examples/mapdata/doc/images/mapdata-example.png
new file mode 100644
index 00000000..8bd8fc18
--- /dev/null
+++ b/examples/mapdata/doc/images/mapdata-example.png
Binary files differ
diff --git a/examples/mapdata/doc/src/mapdata.qdoc b/examples/mapdata/doc/src/mapdata.qdoc
new file mode 100644
index 00000000..be424509
--- /dev/null
+++ b/examples/mapdata/doc/src/mapdata.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example mapdata
+ \title Mapdata Example
+
+ The mapdata example shows how to make a simple 3D maps visualization using Q3DMaps and
+ combining the use of widgets for adjusting several adjustable qualities.
+
+ \image mapdata-example.png
+
+ TODO
+*/
diff --git a/examples/qmlbarchart/doc/src/qmlbarchart.qdoc b/examples/qmlbarchart/doc/src/qmlbarchart.qdoc
new file mode 100644
index 00000000..42bb05aa
--- /dev/null
+++ b/examples/qmlbarchart/doc/src/qmlbarchart.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example qmlbarchart
+ \title Qt Quick 2 Barchart Example
+
+ The Qt Quick 2 barchart example shows how to make a simple 3D bar chart using Q3DBars using Qt
+ Quick 2.
+
+ \image qmlbarchart-example.png
+
+ TODO
+*/
diff --git a/examples/qmlbarchart/main.cpp b/examples/qmlbarchart/main.cpp
index 37fd461e..d813443e 100644
--- a/examples/qmlbarchart/main.cpp
+++ b/examples/qmlbarchart/main.cpp
@@ -20,10 +20,12 @@
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
+#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
+ qDebug() << "Hello world.";
QtQuick2ApplicationViewer viewer;
#ifdef Q_OS_ANDROID
diff --git a/examples/qmlbarchart/qml/qmlbarchart/main.qml b/examples/qmlbarchart/qml/qmlbarchart/main.qml
index f36aece6..990c78e6 100644
--- a/examples/qmlbarchart/qml/qmlbarchart/main.qml
+++ b/examples/qmlbarchart/qml/qmlbarchart/main.qml
@@ -23,15 +23,16 @@ import QtQuick.Window 2.1
import com.digia.QtDataVis3D 1.0
Item {
- id: container
- //anchors.fill: parent
- width: 800
- height: 500
+ id: mainview
+ //title: "My MainWindow"
+ width: 640
+ height: 480
+ visible: true
- DataVisView {
- id: mainview
- anchors.fill: parent
- antialiasing: true
+ Bars3D {
+ id: testchart
+ width: mainview.width
+ height: mainview.height
DataItem {
id: testitem
@@ -43,56 +44,78 @@ Item {
label: "Test2"
value: -10
}
+ DataItem {
+ id: testitem3
+ label: "Test3"
+ value: 5
+ }
+
+ DataItem {
+ id: testitem4
+ label: "Test4"
+ value: -7
+ }
+ DataItem {
+ id: testitem5
+ label: "Test5"
+ value: 8
+ }
+ DataItem {
+ id: testitem6
+ label: "Test6"
+ value: 1
+ }
+
DataRow {
- id: testrow
+ id: testrow1
function addData() {
- testrow.addItem(testitem);
- testrow.addItem(testitem2);
+ testrow1.addItem(testitem);
+ testrow1.addItem(testitem2);
+ testrow1.addItem(testitem3);
+ testrow1.addItem(testitem4);
+ testrow1.addItem(testitem5);
+ testrow1.addItem(testitem6);
}
}
-// Bars {
-// id: testchart
-// visible: true
-// width: mainview.width
-// height: mainview.height
-// //x: mainview.x + mainview.width
-// //y: mainview.y
-// grid: false
-// shadowQuality: Bars.ShadowNone
-// selectionMode: Bars.ModeNone
-// labelTransparency: Bars.TransparencyNone
-// windowTitle: "QmlTest3DBars"
+ //visible: true
+ //x: mainview.x + mainview.width
+ //y: mainview.y
-// function setUpBars() {
-// /*console.log(parent)
-// console.log(container.x)
-// console.log(container.y)
-// console.log(Window.x)
-// console.log(Window.y)
-// console.log(Screen.desktopAvailableHeight)
-// console.log(Screen.desktopAvailableWidth)
-// console.log(mainview.x)
-// console.log(mainview.y)
-// console.log(x)
-// console.log(y)*/
-// testchart.setupSampleSpace(2, 1);
-// testchart.addDataRow(testrow);
-// }
-// }
+ grid: false
+ shadowQuality: Bars3D.ShadowNone
+ selectionMode: Bars3D.ModeNone
+ labelTransparency: Bars3D.TransparencyNone
- MouseArea {
- anchors.fill: parent
- onClicked: {
-// testchart.destroy();
-// testchart.close();
- Qt.quit();
- }
+ function setUpBars3D() {
+ /*console.log(parent)
+ console.log(container.x)
+ console.log(container.y)
+ console.log(Window.x)
+ console.log(Window.y)
+ console.log(Screen.desktopAvailableHeight)
+ console.log(Screen.desktopAvailableWidth)
+ console.log(mainview.x)
+ console.log(mainview.y)
+ console.log(x)
+ console.log(y)*/
+ testchart.setupSampleSpace(6, 1);
+ testchart.addDataRow(testrow1);
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ Qt.quit();
}
+ }
-// Component.onCompleted: {
-// testrow.addData();
-// testchart.setUpBars();
-// }
+ Component.onCompleted: {
+ // This allows us to flip the texture to be displayed correctly in scene graph
+ // TODO: Find a way to do it in code..
+ //rotation.angle = 180
+ testrow1.addData();
+ testchart.setUpBars3D();
}
}
diff --git a/examples/rainfall/doc/images/rainfall-example.png b/examples/rainfall/doc/images/rainfall-example.png
new file mode 100644
index 00000000..f4087927
--- /dev/null
+++ b/examples/rainfall/doc/images/rainfall-example.png
Binary files differ
diff --git a/examples/rainfall/doc/src/rainfall.qdoc b/examples/rainfall/doc/src/rainfall.qdoc
new file mode 100644
index 00000000..b1a4d8e0
--- /dev/null
+++ b/examples/rainfall/doc/src/rainfall.qdoc
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example rainfall
+ \title Rainfall Example
+
+ The barchart example shows how to make a simple 3D bar chart using Q3DBars.
+
+ \image rainfall-example.png
+
+ TODO
+*/
diff --git a/examples/spectrum/doc/images/spectrum-example.png b/examples/spectrum/doc/images/spectrum-example.png
new file mode 100644
index 00000000..2a703948
--- /dev/null
+++ b/examples/spectrum/doc/images/spectrum-example.png
Binary files differ
diff --git a/examples/spectrum/doc/src/spectrum.qdoc b/examples/spectrum/doc/src/spectrum.qdoc
new file mode 100644
index 00000000..87028e9c
--- /dev/null
+++ b/examples/spectrum/doc/src/spectrum.qdoc
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example spectrum
+ \title Spectrum Example
+
+ The spectrum example shows how feed dynamic data to a graph using Q3DBars.
+
+ \image spectrum-example.png
+
+ TODO
+*/
diff --git a/examples/widget/doc/images/widget-example.png b/examples/widget/doc/images/widget-example.png
new file mode 100644
index 00000000..4fb43b42
--- /dev/null
+++ b/examples/widget/doc/images/widget-example.png
Binary files differ
diff --git a/examples/widget/doc/src/widget.qdoc b/examples/widget/doc/src/widget.qdoc
new file mode 100644
index 00000000..d8790a60
--- /dev/null
+++ b/examples/widget/doc/src/widget.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example widget
+ \title Widget Example
+
+ The widget example shows how to make a 3D bar chart using Q3DBars and combining the use of
+ widgets for adjusting several adjustable qualities.
+
+ \image widget-example.png
+
+ TODO
+*/
diff --git a/src/datavis3d/doc/images/q3dbars-minimal.png b/src/datavis3d/doc/images/q3dbars-minimal.png
new file mode 100644
index 00000000..63b77998
--- /dev/null
+++ b/src/datavis3d/doc/images/q3dbars-minimal.png
Binary files differ
diff --git a/src/datavis3d/doc/qtdatavis3d.qdocconf b/src/datavis3d/doc/qtdatavis3d.qdocconf
index c2c084b3..c3fd9826 100644
--- a/src/datavis3d/doc/qtdatavis3d.qdocconf
+++ b/src/datavis3d/doc/qtdatavis3d.qdocconf
@@ -1,47 +1,33 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
-# Name of the project which must match the outputdir. Determines the .index file
-project = qtdatavis3d
+project = QtDataVis3D
+description = Qt Data Visualization 3D Reference Documentation
+version = 1.0.0
-# Directories in which to search for files to document and images.
-# By default set to the root directory of the project for sources
-# and headers and qdoc will therefore generate output for each file.
-# Images should be placed in <rootdir>/dic/images and examples in
-# <rootdir>/examples.
-# Paths are relative to the location of this file.
exampledirs += ../../../examples \
snippets
headerdirs += ..
-imagedirs += images
+imagedirs += ../images \
+ images
sourcedirs += ..
-depends += qtcore qtgui
-
-# The following parameters are for creating a qhp file, the qhelpgenerator
-# program can convert the qhp file into a qch file which can be opened in
-# Qt Assistant and/or Qt Creator.
-
-# Defines the name of the project. You cannot use operators (+, =, -) in
-# the name. Properties for this project are set using a qhp.<projectname>.property
-# format.
-qhp.projects = qtdatavis3d
-
-# Sets the name of the output qhp file.
-qhp.qtdatavis3d.file = qtdatavis3d.qhp
-
-# Namespace for the output file. This namespace is used to distinguish between
-# different documentation files in Creator/Assistant.
-qhp.qtdatavis3d.namespace = org.qt-project.qtdatavis3d.501
-
-# Title for the package, will be the main title for the package in
-# Assistant/Creator.
-qhp.qtdatavis3d.indexTitle = Qt Data Visualization 3D
-
-# Only update the name of the project for the next variables.
-qhp.qtdatavis3d.virtualFolder = qtdatavis3d
-qhp.qtdatavis3d.subprojects = classes
-qhp.qtdatavis3d.subprojects.classes.title = C++ Classes
-qhp.qtdatavis3d.subprojects.classes.indexTitle = Qt Data Visualization 3D C++ Classes
-qhp.qtdatavis3d.subprojects.classes.selectors = class fake:headerfile
-qhp.qtdatavis3d.subprojects.classes.sortPages = true
+depends += qtcore \
+ qtgui
+
+qhp.projects = QtDataVis3D
+
+qhp.qtdatavis3d.file = qtdatavis3d.qhp
+qhp.qtdatavis3d.namespace = org.qt-project.qtdatavis3d.1.0.0
+qhp.qtdatavis3d.virtualFolder = qtdatavis3d
+qhp.qtdatavis3d.indexTitle = Qt Data Visualization 3D
+qhp.qtdatavis3d.indexRoot =
+
+qhp.qtdatavis3d.filterAttributes = qtdatavis3d 1.0.0 qtrefdoc
+qhp.qtdatavis3d.customFilters.Qt.name = QtDataVis3D 1.0.0
+qhp.qtdatavis3d.customFilters.Qt.filterAttributes = qtdatavis3d 1.0.0
+qhp.qtdatavis3d.subprojects = classes
+qhp.qtdatavis3d.subprojects.classes.title = C++ Classes
+qhp.qtdatavis3d.subprojects.classes.indexTitle = Qt Data Visualization 3D C++ Classes
+qhp.qtdatavis3d.subprojects.classes.selectors = class fake:headerfile
+qhp.qtdatavis3d.subprojects.classes.sortPages = true
diff --git a/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp b/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp
new file mode 100644
index 00000000..0d94e0eb
--- /dev/null
+++ b/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [3]
+#include <QtDataVis3D>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ //! [0]
+ Q3DBars bars;
+ bars.setupSampleSpace(5, 5);
+ //! [0]
+ //! [1]
+ QVector<float> data;
+ data << 1.0f << 3.0f << 7.5f << 5.0f << 2.2f;
+ bars.addDataRow(data);
+ //! [1]
+ //! [2]
+ bars.show();
+ //! [2]
+
+ return app.exec();
+}
+//! [3]
diff --git a/src/datavis3dqml2/datavisview.h b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp
index 0edfd829..ac2f7f40 100644
--- a/src/datavis3dqml2/datavisview.h
+++ b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp
@@ -39,34 +39,6 @@
**
****************************************************************************/
-#ifndef DATAVISVIEW_H
-#define DATAVISVIEW_H
-
-#include "QtDataVis3D/qdatavis3dglobal.h"
-
-#include <QQuickItem>
-
-QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-
-class DataVisView : public QQuickItem
-{
- Q_OBJECT
- Q_DISABLE_COPY(DataVisView)
-
-public:
- DataVisView(QQuickItem *parent = 0);
- ~DataVisView();
-
-protected:
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
-
-};
-
-QTENTERPRISE_DATAVIS3D_END_NAMESPACE
-
-QTENTERPRISE_DATAVIS3D_USE_NAMESPACE
-
-QML_DECLARE_TYPE(DataVisView)
-
-#endif // DATAVISVIEW_H
-
+//! [0]
+#include <QtDataVis3D>
+//! [0]
diff --git a/src/datavis3dqml2/datavisview.cpp b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro
index bc7da610..4b670157 100644
--- a/src/datavis3dqml2/datavisview.cpp
+++ b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro
@@ -39,47 +39,6 @@
**
****************************************************************************/
-#define TEST1
-
-#include "datavisview.h"
-#include "scenerenderernode_p.h"
-
-#include <QDebug>
-
-QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-
-DataVisView::DataVisView(QQuickItem *parent):
- QQuickItem(parent)
-{
- // By default, QQuickItem does not draw anything. If you subclass
- // QQuickItem to create a visual item, you will need to uncomment the
- // following line and re-implement updatePaintNode()
-
- setFlag(ItemHasContents, true);
- setRotation(180.0);
- setAntialiasing(true);
- setSmooth(true);
-}
-
-DataVisView::~DataVisView()
-{
-}
-
-QSGNode *DataVisView::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
-#ifdef TEST1
- // Delete old node and recreate it. This function gets called when window geometry changes.
- if (oldNode)
- delete oldNode;
-
- // We need to create a node class that does the rendering (ie. a node that "captures" the rendering we do)
- SceneRendererNode *node = new SceneRendererNode(window());
- node->setRect(boundingRect());
-
- return node;
-#else
- return NULL;
-#endif
-}
-
-QTENTERPRISE_DATAVIS3D_END_NAMESPACE
+#! [0]
+QT += datavis3d
+#! [0]
diff --git a/src/datavis3d/doc/src/qtdatavis3d-index.qdoc b/src/datavis3d/doc/src/qtdatavis3d-index.qdoc
new file mode 100644
index 00000000..0c9cf8cc
--- /dev/null
+++ b/src/datavis3d/doc/src/qtdatavis3d-index.qdoc
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \title Qt Data Visualization 3D
+ \page qtdatavis3d-index.html
+ \brief QtDataVis3D module provides functionality for 3D visualization.
+
+ Qt Data Visualization module provides a way to visualize data in 3D.
+ It uses OpneGL for the data rendering.
+
+ \section1 Getting Started
+
+ Qt Data Visualization provides classes for rendering 3D data. To include
+ the definitions of the module's classes, use the following directive:
+
+ \snippet doc_src_qtdatavis3d.cpp 0
+
+ To link against the module, add this line to your \l qmake \c
+ .pro file:
+
+ \snippet doc_src_qtdatavis3d.pro 0
+
+ \section1 Articles
+ \list
+ \li \l{Qt Data Visualization 3D License Information}{License Information}
+ \endlist
+
+ \section1 References
+ \list
+ \li \l{Qt Data Visualization 3D C++ Classes}
+ \endlist
+
+ Qt Data Visualization 3D comes with the following examples:
+
+ \list
+ \li \l{Barchart Example}
+ \li \l{Mapdata Example}
+ \li \l{Qt Quick 2 Barchart Example}
+ \li \l{Rainfall Example}
+ \li \l{Spectrum Example}
+ \li \l{Widget Example}
+ \endlist
+*/
diff --git a/src/datavis3d/doc/src/qtdatavis3d.qdoc b/src/datavis3d/doc/src/qtdatavis3d.qdoc
new file mode 100644
index 00000000..37e53161
--- /dev/null
+++ b/src/datavis3d/doc/src/qtdatavis3d.qdoc
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module QtDataVis3D
+ \title Qt Data Visualization 3D C++ Classes
+ \ingroup modules
+
+ \brief The QtDataVis3D module provides functionality for 3D visualization.
+*/
+
diff --git a/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc b/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc
new file mode 100644
index 00000000..9821b26f
--- /dev/null
+++ b/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt SVG module.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtdatavis3dlicense.html
+ \title Qt Data Visualization 3D License Information
+ \ingroup licensing
+ \brief License information for Qt Data Visualization 3D
+
+ TODO
+
+ \legalese
+ TODO
+ \endlegalese
+
+*/
diff --git a/src/datavis3d/engine/bars3dshared.cpp b/src/datavis3d/engine/bars3dshared.cpp
new file mode 100644
index 00000000..55efb7cc
--- /dev/null
+++ b/src/datavis3d/engine/bars3dshared.cpp
@@ -0,0 +1,2421 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "bars3dshared_p.h"
+#include "camerahelper_p.h"
+#include "qdataitem_p.h"
+#include "qdatarow_p.h"
+#include "qdataset_p.h"
+#include "shaderhelper_p.h"
+#include "objecthelper_p.h"
+#include "texturehelper_p.h"
+#include "theme_p.h"
+#include "utils_p.h"
+#include "drawer_p.h"
+
+#include <QMatrix4x4>
+#include <QOpenGLPaintDevice>
+#include <QPainter>
+#include <QScreen>
+#include <QMouseEvent>
+
+#include <qmath.h>
+
+#include <QDebug>
+
+// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light
+// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway)
+#define USE_WIDER_SHADOWS
+
+// You can verify that depth buffer drawing works correctly by uncommenting this.
+// You should see the scene from where the light is
+//#define SHOW_DEPTH_TEXTURE_SCENE
+
+//#define DISPLAY_RENDER_SPEED
+
+#ifdef DISPLAY_RENDER_SPEED
+#include <QTime>
+#endif
+
+QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
+
+//#define USE_HAX0R_SELECTION // keep this defined until the "real" method works
+#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels
+
+const GLfloat gridLineWidth = 0.005f;
+static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color
+
+Bars3dShared::Bars3dShared(QRect rect, GLuint fbohandle)
+ : m_boundingRect(rect.x(), rect.y(), rect.width(), rect.height()),
+ m_paintDevice(0),
+ m_barShader(0),
+ m_depthShader(0),
+ m_selectionShader(0),
+ m_backgroundShader(0),
+ m_labelShader(0),
+ m_barObj(0),
+ m_backgroundObj(0),
+ m_gridLineObj(0),
+ m_labelObj(0),
+ m_sampleCount(0, 0),
+ m_objFile(QStringLiteral(":/defaultMeshes/bar")),
+ m_mousePressed(MouseNone),
+ m_mousePos(QPoint(0, 0)),
+ m_zoomLevel(100),
+ m_zoomAdjustment(1.0f),
+ m_horizontalRotation(-45.0f),
+ m_verticalRotation(15.0f),
+ m_barThickness(QSizeF(0.75f, 0.75f)),
+ m_barSpacing(m_barThickness * 3.0f),
+ m_heightNormalizer(0.0f),
+ m_yAdjustment(0.0f),
+ m_rowWidth(0),
+ m_columnDepth(0),
+ m_maxDimension(0),
+ m_scaleX(0),
+ m_scaleZ(0),
+ m_scaleFactor(0),
+ m_maxSceneSize(40.0),
+ m_theme(new Theme()),
+ m_isInitialized(false),
+ m_selectionMode(ModeBar),
+ m_selectedBar(0),
+ m_zoomSelection(0),
+ m_dataSet(new QDataSet()),
+ m_axisLabelX(QStringLiteral("X")),
+ m_axisLabelZ(QStringLiteral("Z")),
+ m_axisLabelY(QStringLiteral("Y")),
+ m_sceneViewPort(rect.x(), rect.y(), rect.width(), rect.height()),
+ m_zoomViewPort(rect.x(), rect.y(), rect.width(), rect.height()),
+ m_zoomActivated(false),
+ m_labelTransparency(TransparencyFromTheme),
+ m_font(QFont(QStringLiteral("Arial"))),
+ m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)),
+ m_xFlipped(false),
+ m_zFlipped(false),
+ m_yFlipped(false),
+ m_bgrTexture(0),
+ m_depthTexture(0),
+ m_selectionTexture(0),
+ m_depthFrameBuffer(0),
+ m_selectionFrameBuffer(0),
+ m_selectionDepthBuffer(0),
+ m_updateLabels(false),
+ m_gridEnabled(true),
+ m_bgrEnabled(true),
+ m_shadowQuality(ShadowLow),
+ m_shadowQualityToShader(33.3f),
+ m_tickCount(0),
+ m_tickStep(0),
+ m_negativeValues(false),
+ m_fbohandle(fbohandle)
+{
+ m_theme = new Theme();
+ m_dataSet->d_ptr->setDrawer(m_drawer);
+ QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Bars3dShared::updateTextures);
+}
+
+Bars3dShared::~Bars3dShared()
+{
+#ifndef USE_HAX0R_SELECTION
+ glDeleteFramebuffers(1, &m_selectionFrameBuffer);
+ glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
+ m_textureHelper->deleteTexture(&m_selectionTexture);
+#endif
+ glDeleteFramebuffers(1, &m_depthFrameBuffer);
+ m_textureHelper->deleteTexture(&m_bgrTexture);
+ delete m_dataSet;
+ if (m_zoomSelection) {
+ m_zoomSelection->d_ptr->clear();
+ delete m_zoomSelection;
+ }
+ delete m_barShader;
+ delete m_depthShader;
+ delete m_selectionShader;
+ delete m_backgroundShader;
+ delete m_barObj;
+ delete m_backgroundObj;
+ delete m_gridLineObj;
+ delete m_textureHelper;
+ delete m_drawer;
+}
+
+
+void Bars3dShared::render()
+{
+ if (!m_isInitialized)
+ return;
+
+#ifdef DISPLAY_RENDER_SPEED
+ // For speed computation
+ static bool firstRender = true;
+ static QTime lastTime;
+ static GLint nbFrames = 0;
+ if (firstRender) {
+ lastTime.start();
+ firstRender = false;
+ }
+
+ // Measure speed (as milliseconds per frame)
+ nbFrames++;
+ if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago
+ qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)";
+ nbFrames = 0;
+ lastTime.restart();
+ }
+#endif
+
+ // If zoom selection is on, draw zoom scene
+ drawZoomScene();
+ // Draw bars scene
+ drawScene();
+}
+
+void Bars3dShared::initializeOpenGL()
+{
+ // Initialization is called multiple times when Qt Quick components are used
+ if (m_isInitialized)
+ return;
+
+ initializeOpenGLFunctions();
+
+ m_textureHelper = new TextureHelper();
+ m_drawer->initializeOpenGL();
+
+ // Resize in case we've missed resize events
+ resizeNotify();
+
+ // Initialize shaders
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ }
+ initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ // Init the depth buffer (for shadows)
+ initDepthBuffer();
+ } else {
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
+ }
+ initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
+ }
+#else
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentColorOnYES2"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentES2"));
+ }
+ initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentES2"));
+#endif
+
+ 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();
+
+#ifndef USE_HAX0R_SELECTION
+ // Init the selection buffer
+ initSelectionBuffer();
+#endif
+
+ // Load default mesh
+ loadBarMesh();
+
+ // Load background mesh
+ loadBackgroundMesh();
+
+ // Load grid line mesh
+ loadGridLineMesh();
+
+ // Load label mesh
+ loadLabelMesh();
+
+ // Set OpenGL features
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+#if !defined(QT_OPENGL_ES_2)
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
+ glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
+#endif
+
+ // Set initial camera position
+ // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later
+ CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+
+ // Set view port
+ glViewport(0, 0, width(), height());
+
+ // Set initialized -flag
+ m_isInitialized = true;
+
+ // Load background mesh
+ loadBackgroundMesh();
+}
+
+void Bars3dShared::drawZoomScene()
+{
+ // Set clear color
+ QVector3D clearColor = Utils::vectorFromColor(m_theme->m_windowColor);
+ glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // If no zoom, return
+ if (!m_zoomActivated)
+ return;
+
+ GLfloat barPosX = 0;
+ GLint startBar = 0;
+ GLint stopBar = m_zoomSelection->d_ptr->row().size();
+ GLint stepBar = 1;
+ QVector3D lightPos;
+
+ // Specify viewport
+ glViewport(m_zoomViewPort.x(), m_zoomViewPort.y(),
+ m_zoomViewPort.width(), m_zoomViewPort.height());
+
+ // Set up projection matrix
+ QMatrix4x4 projectionMatrix;
+ projectionMatrix.perspective(45.0f, (GLfloat)m_zoomViewPort.width()
+ / (GLfloat)m_zoomViewPort.height(), 0.1f, 100.0f);
+
+#ifdef ROTATE_ZOOM_SELECTION
+ // Calculate view matrix
+ QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(m_mousePos,
+ m_zoomLevel
+ * m_zoomAdjustment,
+ m_zoomViewPort.width(),
+ m_zoomViewPort.height());
+
+ // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos))
+ lightPos = CameraHelper::calculateLightPosition(defaultLightPos);
+
+ if (viewMatrix.row(0).z() <= 0) {
+ startBar = m_zoomSelection->d_ptr->row().size() - 1;
+ stopBar = -1;
+ stepBar = -1;
+ }
+#else
+ // Set view matrix
+ QMatrix4x4 viewMatrix;
+
+ // Adjust scaling (zoom rate based on aspect ratio)
+ GLfloat camPosZoomed = 5.0f / m_zoomAdjustment + zComp;
+
+ viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camPosZoomed),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+
+ // Set light position a bit below the camera to reduce glare (depends on do we have row or column zoom)
+ QVector3D zoomLightPos = defaultLightPos;
+ zoomLightPos.setY(-10.0f);
+ if (ModeZoomColumn == m_selectionMode)
+ lightPos = CameraHelper::calculateLightPosition(zoomLightPos, -85.0f);
+ else
+ lightPos = CameraHelper::calculateLightPosition(zoomLightPos, 5.0f);
+#endif
+
+ // Bind bar shader
+ m_barShader->bind();
+
+ // Draw bars
+ // Draw the selected row / column
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ QDataItem *item = m_zoomSelection->d_ptr->getItem(bar);
+ if (!item)
+ continue;
+
+ GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer;
+
+ if (barHeight < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ GLfloat barPosY = item->d_ptr->translation().y() - m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f
+ if (ModeZoomRow == m_selectionMode)
+ barPosX = item->d_ptr->translation().x();
+ else
+ barPosX = -(item->d_ptr->translation().z() - zComp); // flip z; frontmost bar to the left
+ modelMatrix.translate(barPosX, barPosY, zComp);
+ modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ));
+ itModelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ));
+
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+
+ QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor);
+ QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) * barHeight;
+
+ QVector3D barColor = baseColor + heightColor;
+
+ GLfloat lightStrength = m_theme->m_lightStrength;
+
+ if (barHeight != 0) {
+ // Set shader bindings
+ m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
+ m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
+ m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
+ m_barShader->setUniformValue(m_barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
+ m_barShader->setUniformValue(m_barShader->color(), barColor);
+ m_barShader->setUniformValue(m_barShader->lightS(), lightStrength);
+ m_barShader->setUniformValue(m_barShader->ambientS(),
+ m_theme->m_ambientStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_barObj);
+ }
+ }
+
+ // Release bar shader
+ m_barShader->release();
+
+ // Draw labels
+ m_labelShader->bind();
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_TEXTURE_2D);
+ glCullFace(GL_BACK);
+ if (m_labelTransparency > TransparencyNone) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ // Draw labels for axes
+ QDataItem *dummyItem = NULL;
+ LabelItem x;
+ LabelItem z;
+ LabelItem y;
+ m_dataSet->d_ptr->axisLabelItems(&x, &z, &y);
+ LabelItem zoomSelectionLabel = m_zoomSelection->d_ptr->labelItem();
+ if (ModeZoomRow == m_selectionMode) {
+ m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, false, false, LabelTop);
+ m_drawer->drawLabel(*dummyItem, z, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, false, false, LabelBottom);
+ } else {
+ m_drawer->drawLabel(*dummyItem, x, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, false, false, LabelBottom);
+ m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, false, false, LabelTop);
+ }
+ m_drawer->drawLabel(*dummyItem, y, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 90.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, false, false, LabelLeft);
+
+ // Draw labels for bars
+ for (int col = 0; col < m_zoomSelection->d_ptr->row().size(); col++) {
+ QDataItem *item = m_zoomSelection->d_ptr->getItem(col);
+ // Draw values
+ m_drawer->drawLabel(*item, item->d_ptr->label(), viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj);
+ // Draw labels
+ LabelItem labelItem;
+ if (ModeZoomRow == m_selectionMode) {
+ if (m_dataSet->d_ptr->columnLabelItems().size() > col) {
+ // If draw order of bars is flipped, label draw order should be too
+ if (m_xFlipped) {
+ labelItem = m_dataSet->d_ptr->columnLabelItems().at(
+ m_dataSet->d_ptr->columnLabelItems().size() - col - 1);
+ } else {
+ labelItem = m_dataSet->d_ptr->columnLabelItems().at(col);
+ }
+ }
+ } else {
+ if (m_dataSet->d_ptr->rowLabelItems().size() > col) {
+ // If draw order of bars is flipped, label draw order should be too
+ if (m_zFlipped) {
+ labelItem = m_dataSet->d_ptr->rowLabelItems().at(
+ m_dataSet->d_ptr->rowLabelItems().size() - col - 1);
+ } else {
+ labelItem = m_dataSet->d_ptr->rowLabelItems().at(col);
+ }
+ }
+ }
+ m_drawer->drawLabel(*item, labelItem, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, -45.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, false, false, LabelBelow);
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ if (m_labelTransparency > TransparencyNone)
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+
+ // Release label shader
+ m_labelShader->release();
+}
+
+void Bars3dShared::drawScene()
+{
+ GLint startBar = 0;
+ GLint stopBar = 0;
+ GLint stepBar = 0;
+
+ GLint startRow = 0;
+ GLint stopRow = 0;
+ GLint stepRow = 0;
+
+ GLfloat backgroundRotation = 0;
+
+ GLfloat barPos = 0;
+ GLfloat rowPos = 0;
+
+ static QVector3D selection = skipColor;
+
+ // Specify viewport
+ glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(),
+ m_sceneViewPort.width(), m_sceneViewPort.height());
+
+ // Set up projection matrix
+ QMatrix4x4 projectionMatrix;
+ projectionMatrix.perspective(45.0f, (GLfloat)m_sceneViewPort.width()
+ / (GLfloat)m_sceneViewPort.height(), 0.1f, 100.0f);
+
+ // Calculate view matrix
+ QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(m_mousePos,
+ m_zoomLevel
+ * m_zoomAdjustment,
+ m_sceneViewPort.width(),
+ m_sceneViewPort.height(),
+ m_negativeValues);
+
+ // Calculate drawing order
+ // Draw order is reversed to optimize amount of drawing (ie. draw front objects first, depth test handles not needing to draw objects behind them)
+ if (viewMatrix.row(0).x() > 0) {
+ startRow = 0;
+ stopRow = m_sampleCount.second;
+ stepRow = 1;
+ m_zFlipped = false;
+ } else {
+ startRow = m_sampleCount.second - 1;
+ stopRow = -1;
+ stepRow = -1;
+ m_zFlipped = true;
+ }
+ if (viewMatrix.row(0).z() <= 0) {
+ startBar = 0;
+ stopBar = m_sampleCount.first;
+ stepBar = 1;
+ m_xFlipped = false;
+ } else {
+ startBar = m_sampleCount.first - 1;
+ stopBar = -1;
+ stepBar = -1;
+ m_xFlipped = true;
+ }
+
+ // Check if we're viewing the scene from below
+ if (viewMatrix.row(2).y() < 0)
+ m_yFlipped = true;
+ else
+ m_yFlipped = false;
+
+ // calculate background rotation based on view matrix rotation
+ if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0)
+ backgroundRotation = 270.0f;
+ else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0)
+ backgroundRotation = 180.0f;
+ else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0)
+ backgroundRotation = 90.0f;
+ else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0)
+ backgroundRotation = 0.0f;
+
+ // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos))
+ QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos);
+ //lightPos = QVector3D(0.0f, 4.0f, zComp); // center of bars, 4.0f above - for testing
+
+ // Skip depth rendering if we're in zoom mode
+ // TODO: Fix this, causes problems if depth rendering is off in zoom mode
+ // Introduce regardless of shadow quality to simplify logic
+ QMatrix4x4 depthViewMatrix;
+ QMatrix4x4 depthProjectionMatrix;
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone/*!m_zoomActivated*/) {
+ // Render scene into a depth texture for using with shadow mapping
+ // Bind depth shader
+ m_depthShader->bind();
+
+ // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
+ glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(),
+ m_sceneViewPort.width() * m_shadowQuality,
+ m_sceneViewPort.height() * m_shadowQuality);
+
+ // Enable drawing to framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ // Get the depth view matrix
+ // It may be possible to hack lightPos here if we want to make some tweaks to shadow
+ depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -m_yAdjustment, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+ // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed
+ //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3);
+ // Set the depth projection matrix
+#ifdef USE_WIDER_SHADOWS
+ // Use this for a bit exaggerated shadows
+ depthProjectionMatrix.perspective(20.0f, (GLfloat)m_sceneViewPort.width()
+ / (GLfloat)m_sceneViewPort.height(), 3.0f, 100.0f);
+#else
+ // Use these for normal shadows, with the light further away
+ depthProjectionMatrix = projectionMatrix;
+#endif
+ // Draw bars to depth buffer
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ if (!m_dataSet->d_ptr->getRow(row))
+ continue;
+ QDataItem *item = m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar);
+ if (!item)
+ continue;
+
+ GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer;
+
+ // skip shadows for 0 -height bars
+ if (barHeight == 0)
+ continue;
+
+ // Set front face culling for positive valued bars and back face culling for
+ // negative valued bars to reduce self-shadowing issues
+ if (barHeight < 0)
+ glCullFace(GL_BACK);
+ else
+ glCullFace(GL_FRONT);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ barPos = (bar + 1) * (m_barSpacing.width());
+ rowPos = (row + 1) * (m_barSpacing.height());
+
+ modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor,
+ barHeight - m_yAdjustment,
+ (m_columnDepth - rowPos) / m_scaleFactor
+ + zComp);
+ modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ));
+
+ MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ }
+ }
+
+ // Disable drawing to framebuffer (= enable drawing to screen)
+ glBindFramebuffer(GL_FRAMEBUFFER, m_fbohandle);
+
+ // Release depth shader
+ m_depthShader->release();
+
+#if 0 // Use this if you want to see what is being drawn to the framebuffer
+ // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it)
+ m_labelShader->bind();
+ glCullFace(GL_BACK);
+ glEnable(GL_TEXTURE_2D);
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 viewmatrix;
+ viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+ modelMatrix.translate(0.0, 0.0, zComp);
+ QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix;
+ m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
+ m_drawer->drawObject(m_labelShader, m_labelObj,
+ m_depthTexture);
+ glDisable(GL_TEXTURE_2D);
+ m_labelShader->release();
+#endif
+ // Reset culling to normal
+ glCullFace(GL_BACK);
+
+ // Revert to original viewport
+ glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(),
+ m_sceneViewPort.width(), m_sceneViewPort.height());
+ }
+#endif
+
+ // Skip selection mode drawing if we're zoomed or have no selection mode
+ if (!m_zoomActivated && m_selectionMode > ModeNone) {
+ // Bind selection shader
+ m_selectionShader->bind();
+
+ // Draw bars to selection buffer
+#ifndef USE_HAX0R_SELECTION
+ glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
+ glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
+ glClearColor(skipColor.x() / 255, skipColor.y() / 255, skipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
+#endif
+ glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ if (!m_dataSet->d_ptr->getRow(row))
+ continue;
+ QDataItem *item = m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar);
+ if (!item)
+ continue;
+
+ GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer;
+
+ if (barHeight < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ barPos = (bar + 1) * (m_barSpacing.width());
+ rowPos = (row + 1) * (m_barSpacing.height());
+
+ modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor,
+ barHeight - m_yAdjustment,
+ (m_columnDepth - rowPos) / m_scaleFactor
+ + zComp);
+ modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ));
+
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+
+ // TODO: Save position to qdataitem, so that we don't need to calculate it each time?
+
+ //#if !defined(QT_OPENGL_ES_2)
+ // QVector3D barColor = QVector3D((GLdouble)row / 32767.0,
+ // (GLdouble)bar / 32767.0,
+ // 0.0);
+ //#else
+ QVector3D barColor = QVector3D((GLdouble)row / 255.0,
+ (GLdouble)bar / 255.0,
+ 0.0);
+ //#endif
+
+ m_selectionShader->setUniformValue(m_selectionShader->MVP(),
+ MVPMatrix);
+ m_selectionShader->setUniformValue(m_selectionShader->color(),
+ barColor);
+
+#ifdef USE_HAX0R_SELECTION
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_selectionShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
+ glVertexAttribPointer(m_selectionShader->posAtt(),
+ 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, m_barObj->indexCount(),
+ GL_UNSIGNED_SHORT, (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_selectionShader->posAtt());
+#else
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_selectionShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
+ glVertexAttribPointer(m_selectionShader->posAtt(),
+ 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_selectionShader->posAtt());
+#endif
+ }
+ }
+ glEnable(GL_DITHER);
+
+ // Read color under cursor
+ if (Bars3dShared::MouseOnScene == m_mousePressed)
+ selection = Utils::getSelection(m_mousePos, height());
+
+#ifndef USE_HAX0R_SELECTION
+ glBindFramebuffer(GL_FRAMEBUFFER, m_fbohandle);
+#endif
+
+ // Release selection shader
+ m_selectionShader->release();
+
+#if 0 // Use this if you want to see what is being drawn to the framebuffer
+ glCullFace(GL_BACK);
+ m_labelShader->bind();
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_TEXTURE_2D);
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 viewmatrix;
+ viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+ modelMatrix.translate(0.0, 0.0, zComp);
+ QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix;
+ m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
+ m_drawer->drawObject(m_labelShader, m_labelObj,
+ m_selectionTexture);
+ glDisable(GL_TEXTURE_2D);
+ m_labelShader->release();
+#endif
+
+#ifdef USE_HAX0R_SELECTION
+ // Set clear color
+ QVector3D clearColor = Utils::vectorFromColor(m_theme->m_windowColor);
+ glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
+ // Clear after selection
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#endif
+ }
+
+ // Bind bar shader
+ m_barShader->bind();
+
+ // Enable texturing
+ glEnable(GL_TEXTURE_2D);
+
+ // Draw bars
+ if (!m_zoomActivated && m_zoomSelection)
+ m_zoomSelection->d_ptr->clear();
+ bool barSelectionFound = false;
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ if (!m_dataSet->d_ptr->getRow(row))
+ continue;
+ QDataItem *item = m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar);
+ if (!item)
+ continue;
+
+ GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer;
+
+ if (barHeight < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
+
+ barPos = (bar + 1) * (m_barSpacing.width());
+ rowPos = (row + 1) * (m_barSpacing.height());
+ modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor,
+ barHeight - m_yAdjustment,
+ (m_columnDepth - rowPos) / m_scaleFactor + zComp);
+ modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ));
+ itModelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ));
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+#else
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+#endif
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor);
+ QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor)
+ * barHeight;
+ QVector3D depthColor = Utils::vectorFromColor(m_theme->m_depthColor)
+ * (float(row) / GLfloat(m_sampleCount.second));
+
+ QVector3D barColor = baseColor + heightColor + depthColor;
+
+ GLfloat lightStrength = m_theme->m_lightStrength;
+ if (m_selectionMode > ModeNone) {
+ Bars3dShared::SelectionType selectionType = isSelected(row, bar,
+ selection);
+ switch (selectionType) {
+ case Bars3dShared::SelectionBar: {
+ barColor = Utils::vectorFromColor(m_theme->m_highlightBarColor);
+ lightStrength = m_theme->m_highlightLightStrength;
+ // Insert data to QDataItem. We have no ownership, don't delete the previous one
+ if (!m_zoomActivated) {
+ m_selectedBar = item;
+ if (m_dataSet->d_ptr->rowLabelItems().size() > row
+ && m_dataSet->d_ptr->columnLabelItems().size() > bar) {
+ m_selectedBar->setPosition(
+ QPoint(m_dataSet->d_ptr->rowLabelItems().size()
+ - row - 1,
+ m_dataSet->d_ptr->columnLabelItems().size()
+ - bar - 1));
+ }
+ item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
+ barSelectionFound = true;
+ if (m_selectionMode >= ModeZoomRow) {
+ item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
+ m_zoomSelection->addItem(item);
+ }
+ }
+ break;
+ }
+ case Bars3dShared::SelectionRow: {
+ // Current bar is on the same row as the selected bar
+ barColor = Utils::vectorFromColor(m_theme->m_highlightRowColor);
+ lightStrength = m_theme->m_highlightLightStrength;
+ if (!m_zoomActivated && ModeZoomRow == m_selectionMode) {
+ item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
+ m_zoomSelection->addItem(item);
+ if (m_dataSet->d_ptr->rowLabelItems().size() > row) {
+ m_zoomSelection->d_ptr->setLabelItem(
+ m_dataSet->d_ptr->rowLabelItems().at(
+ m_dataSet->d_ptr->rowLabelItems().size()
+ - row - 1));
+ }
+ }
+ break;
+ }
+ case Bars3dShared::SelectionColumn: {
+ // Current bar is on the same column as the selected bar
+ barColor = Utils::vectorFromColor(m_theme->m_highlightColumnColor);
+ lightStrength = m_theme->m_highlightLightStrength;
+ if (!m_zoomActivated && ModeZoomColumn == m_selectionMode) {
+ item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
+ m_zoomSelection->addItem(item);
+ if (m_dataSet->d_ptr->columnLabelItems().size() > bar) {
+ m_zoomSelection->d_ptr->setLabelItem(
+ m_dataSet->d_ptr->columnLabelItems().at(
+ m_dataSet->d_ptr->columnLabelItems().size()
+ - bar - 1));
+ }
+ }
+ break;
+ }
+ case Bars3dShared::SelectionNone: {
+ // Current bar is not selected, nor on a row or column
+ // do nothing
+ break;
+ }
+ }
+ }
+
+ if (barHeight != 0) {
+ // Set shader bindings
+ m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
+ m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
+ m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
+ m_barShader->setUniformValue(m_barShader->nModel(),
+ itModelMatrix.transposed().inverted());
+ m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
+ m_barShader->setUniformValue(m_barShader->color(), barColor);
+ m_barShader->setUniformValue(m_barShader->ambientS(),
+ m_theme->m_ambientStrength);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Set shadow shader bindings
+ m_barShader->setUniformValue(m_barShader->shadowQ(),
+ m_shadowQualityToShader);
+ m_barShader->setUniformValue(m_barShader->depth(),
+ depthMVPMatrix);
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ lightStrength / 10.0f);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_barObj,
+ 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Set shadowless shader bindings
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_barObj);
+ }
+ }
+ }
+ }
+
+ // Release bar shader
+ m_barShader->release();
+
+ // Bind background shader
+ m_backgroundShader->bind();
+
+ if (m_negativeValues)
+ glDisable(GL_CULL_FACE);
+ else
+ glCullFace(GL_BACK);
+
+ // Draw background
+ if (m_bgrEnabled && m_backgroundObj) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp);
+ modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor,
+ 1.0f,
+ m_columnDepth / m_scaleFactor));
+ modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
+ itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor,
+ 1.0f,
+ m_columnDepth / m_scaleFactor));
+
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+#else
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+#endif
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ QVector3D backgroundColor = Utils::vectorFromColor(m_theme->m_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_theme->m_ambientStrength * 2.0f);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Set shadow shader bindings
+ m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(),
+ m_shadowQualityToShader);
+ m_backgroundShader->setUniformValue(m_backgroundShader->depth(),
+ depthMVPMatrix);
+ m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
+ m_theme->m_lightStrength / 10.0f);
+
+ // 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_theme->m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
+ }
+ }
+
+ // Disable textures
+ glDisable(GL_TEXTURE_2D);
+
+ // Release background shader
+ m_backgroundShader->release();
+
+ // Reset culling
+ if (m_negativeValues) {
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ }
+
+ // Draw grid lines
+ if (m_gridEnabled && m_heightNormalizer) {
+ // Bind bar shader
+ m_barShader->bind();
+
+ // Set unchanging shader bindings
+ QVector3D barColor = Utils::vectorFromColor(m_theme->m_gridLine);
+ m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
+ m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
+ m_barShader->setUniformValue(m_barShader->color(), barColor);
+ m_barShader->setUniformValue(m_barShader->ambientS(),
+ m_theme->m_ambientStrength);
+
+ // Floor lines: rows
+ for (GLfloat row = 0.0f; row <= m_sampleCount.second; row++) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ rowPos = (row + 0.5f) * (m_barSpacing.height());
+ modelMatrix.translate(0.0f, -m_yAdjustment,
+ (m_columnDepth - rowPos) / m_scaleFactor + zComp);
+ modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth,
+ gridLineWidth));
+ itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth,
+ gridLineWidth));
+ // If we're viewing from below, grid line object must be flipped
+ if (m_yFlipped)
+ modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
+
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
+ m_barShader->setUniformValue(m_barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Set shadow shader bindings
+ m_barShader->setUniformValue(m_barShader->shadowQ(),
+ m_shadowQualityToShader);
+ m_barShader->setUniformValue(m_barShader->depth(),
+ depthMVPMatrix);
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength / 10.0f);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj,
+ 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Set shadowless shader bindings
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj);
+ }
+ }
+
+ // Floor lines: columns
+ for (GLfloat bar = 0.0f; bar <= m_sampleCount.first; bar++) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ barPos = (bar + 0.5f) * (m_barSpacing.width());
+ modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor,
+ -m_yAdjustment, zComp);
+ modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
+ m_columnDepth / m_scaleFactor));
+ itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
+ m_columnDepth / m_scaleFactor));
+
+ // If we're viewing from below, grid line object must be flipped
+ if (m_yFlipped)
+ modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
+
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
+ m_barShader->setUniformValue(m_barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Set shadow shader bindings
+ m_barShader->setUniformValue(m_barShader->shadowQ(),
+ m_shadowQualityToShader);
+ m_barShader->setUniformValue(m_barShader->depth(),
+ depthMVPMatrix);
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength / 10.0f);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj,
+ 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Set shadowless shader bindings
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj);
+ }
+ }
+
+ // Wall lines: back wall
+ GLfloat heightStep = m_heightNormalizer / 5.0f; // default to 5 lines
+ GLfloat startLine;
+
+ if (m_tickCount > 0)
+ heightStep = m_tickStep;
+
+ if (m_negativeValues)
+ startLine = -m_heightNormalizer;
+ else
+ startLine = heightStep;
+
+ for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer;
+ lineHeight += heightStep) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ if (m_zFlipped) {
+ modelMatrix.translate(0.0f,
+ 2.0f * lineHeight / m_heightNormalizer
+ - m_yAdjustment,
+ m_columnDepth / m_scaleFactor + zComp);
+ } else {
+ modelMatrix.translate(0.0f,
+ 2.0f * lineHeight / m_heightNormalizer
+ - m_yAdjustment,
+ -m_columnDepth / m_scaleFactor + zComp);
+ }
+ modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth,
+ gridLineWidth));
+ itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth,
+ gridLineWidth));
+
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
+ m_barShader->setUniformValue(m_barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Set shadow shader bindings
+ m_barShader->setUniformValue(m_barShader->shadowQ(),
+ m_shadowQualityToShader);
+ m_barShader->setUniformValue(m_barShader->depth(),
+ depthMVPMatrix);
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength / 10.0f);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj,
+ 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Set shadowless shader bindings
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj);
+ }
+ }
+
+ // Wall lines: side wall
+ for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer;
+ lineHeight += heightStep) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ if (m_xFlipped) {
+ modelMatrix.translate(m_rowWidth / m_scaleFactor,
+ 2.0f * lineHeight / m_heightNormalizer
+ - m_yAdjustment,
+ zComp);
+ } else {
+ modelMatrix.translate(-m_rowWidth / m_scaleFactor,
+ 2.0f * lineHeight / m_heightNormalizer
+ - m_yAdjustment,
+ zComp);
+ }
+ modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
+ m_columnDepth / m_scaleFactor));
+ itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
+ m_columnDepth / m_scaleFactor));
+
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
+ m_barShader->setUniformValue(m_barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Set shadow shader bindings
+ m_barShader->setUniformValue(m_barShader->shadowQ(),
+ m_shadowQualityToShader);
+ m_barShader->setUniformValue(m_barShader->depth(),
+ depthMVPMatrix);
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength / 10.0f);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj,
+ 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Set shadowless shader bindings
+ m_barShader->setUniformValue(m_barShader->lightS(),
+ m_theme->m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(m_barShader, m_gridLineObj);
+ }
+ }
+
+ // Release bar shader
+ m_barShader->release();
+ }
+
+ // TODO: Draw y labels
+
+ // Generate label textures for zoom selection if m_updateLabels is set
+ if (m_zoomActivated && m_updateLabels) {
+ // Create label textures
+ for (int col = 0; col < m_zoomSelection->d_ptr->row().size(); col++) {
+ QDataItem *item = m_zoomSelection->d_ptr->getItem(col);
+ m_drawer->generateLabelTexture(item);
+ }
+ }
+
+ // Handle zoom activation and label drawing
+ if (!barSelectionFound) {
+ // We have no ownership, don't delete. Just NULL the pointer.
+ m_selectedBar = NULL;
+ if (m_zoomActivated && Bars3dShared::MouseOnOverview == m_mousePressed) {
+ m_sceneViewPort = QRect(0, 0, width(), height());
+ m_zoomActivated = false;
+ }
+ } else if (m_selectionMode >= ModeZoomRow
+ && Bars3dShared::MouseOnScene == m_mousePressed) {
+ // Activate zoom mode
+ m_zoomActivated = true;
+ m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5);
+
+ // Create label textures
+ for (int col = 0; col < m_zoomSelection->d_ptr->row().size(); col++) {
+ QDataItem *item = m_zoomSelection->d_ptr->getItem(col);
+ m_drawer->generateLabelTexture(item);
+ }
+ } else {
+ // Print value of selected bar
+ static QDataItem *prevItem = m_selectedBar;
+ m_labelShader->bind();
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_TEXTURE_2D);
+ if (m_labelTransparency > TransparencyNone) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+#ifndef DISPLAY_FULL_DATA_ON_SELECTION
+ // Draw just the value string of the selected bar
+ if (prevItem != m_selectedBar || m_updateLabels) {
+ m_drawer->generateLabelTexture(m_selectedBar);
+ prevItem = m_selectedBar;
+ }
+
+ m_drawer->drawLabel(*m_selectedBar, m_selectedBar->label(),
+ viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, true);
+#else
+ static bool firstSelection = true;
+ // Draw the value string followed by row label and column label
+ LabelItem labelItem = m_selectedBar->d_ptr->selectionLabel();
+ if (firstSelection || prevItem != m_selectedBar || m_updateLabels) {
+ QString labelText = m_selectedBar->d_ptr->valueStr();
+ if ((m_dataSet->d_ptr->columnLabels().size()
+ > m_selectedBar->position().y())
+ && (m_dataSet->d_ptr->rowLabels().size()
+ > m_selectedBar->position().x())) {
+ labelText.append(QStringLiteral(" ("));
+ labelText.append(m_dataSet->d_ptr->rowLabels().at(
+ m_selectedBar->position().x()));
+ labelText.append(QStringLiteral(", "));
+ labelText.append(m_dataSet->d_ptr->columnLabels().at(
+ m_selectedBar->position().y()));
+ labelText.append(QStringLiteral(")"));
+ //qDebug() << labelText;
+ }
+ m_drawer->generateLabelItem(&labelItem, labelText);
+ m_selectedBar->d_ptr->setSelectionLabel(labelItem);
+ prevItem = m_selectedBar;
+ firstSelection = false;
+ }
+
+ m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer,
+ m_selectionMode, m_labelShader,
+ m_labelObj, true, false);
+#endif
+ glDisable(GL_TEXTURE_2D);
+ if (m_labelTransparency > TransparencyNone)
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+
+ // Release label shader
+ m_labelShader->release();
+
+ // Reset label update flag; they should have been updated when we get here
+ m_updateLabels = false;
+ }
+
+ // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here.
+ // Bind label shader
+ m_labelShader->bind();
+
+ glEnable(GL_TEXTURE_2D);
+ if (m_labelTransparency > TransparencyNone) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?)
+ for (int row = 0; row != m_sampleCount.second; row += 1) {
+ // Go through all rows and get position of max+1 or min-1 column, depending on x flip
+ // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems
+ rowPos = (row + 1) * (m_barSpacing.height());
+ barPos = 0;
+ GLfloat rotLabelX = -90.0f;
+ GLfloat rotLabelY = 0.0f;
+ GLfloat rotLabelZ = 0.0f;
+ Qt::AlignmentFlag alignment = Qt::AlignRight;
+ if (m_zFlipped)
+ rotLabelY = 180.0f;
+ if (m_xFlipped) {
+ barPos = (m_sampleCount.first + 1) * (m_barSpacing.width());
+ alignment = Qt::AlignLeft;
+ }
+ if (m_yFlipped) {
+ if (m_zFlipped)
+ rotLabelY = 0.0f;
+ else
+ rotLabelY = 180.0f;
+ rotLabelZ = 180.0f;
+ }
+ QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor,
+ -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering"
+ (m_columnDepth - rowPos) / m_scaleFactor
+ + zComp);
+
+ // TODO: Try it; draw the label here
+
+ // Create a data item
+ QDataItem *label = new QDataItem();
+ label->d_ptr->setTranslation(labelPos);
+ if (m_dataSet->d_ptr->rowLabelItems().size() > row) {
+ label->d_ptr->setLabel(m_dataSet->d_ptr->rowLabelItems().at(
+ m_dataSet->d_ptr->rowLabelItems().size() - row - 1));
+ }
+
+ //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_dataSet->d_ptr->rowLabels().at(row);
+
+ m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(rotLabelX, rotLabelY, rotLabelZ),
+ m_heightNormalizer, m_selectionMode,
+ m_labelShader, m_labelObj, true, true, LabelMid,
+ alignment);
+
+ delete label;
+ }
+ for (int bar = 0; bar != m_sampleCount.first; bar += 1) {
+ // Go through all columns and get position of max+1 or min-1 row, depending on z flip
+ // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems
+ barPos = (bar + 1) * (m_barSpacing.width());
+ rowPos = 0;
+ GLfloat rotLabelX = -90.0f;
+ GLfloat rotLabelY = 90.0f;
+ GLfloat rotLabelZ = 0.0f;
+ Qt::AlignmentFlag alignment = Qt::AlignLeft;
+ if (m_xFlipped)
+ rotLabelY = -90.0f;
+ if (m_zFlipped) {
+ rowPos = (m_sampleCount.second + 1) * (m_barSpacing.height());
+ alignment = Qt::AlignRight;
+ }
+ if (m_yFlipped) {
+ if (m_xFlipped)
+ rotLabelY = -90.0f;
+ else
+ rotLabelY = 90.0f;
+ rotLabelZ = 180.0f;
+ }
+ QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor,
+ -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering"
+ (m_columnDepth - rowPos) / m_scaleFactor
+ + zComp);
+
+ // TODO: Try it; draw the label here
+
+ // Create a data item
+ QDataItem *label = new QDataItem();
+ label->d_ptr->setTranslation(labelPos);
+ if (m_dataSet->d_ptr->columnLabelItems().size() > bar) {
+ label->d_ptr->setLabel(m_dataSet->d_ptr->columnLabelItems().at(
+ m_dataSet->d_ptr->columnLabelItems().size()
+ - bar - 1));
+ }
+
+ //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << m_dataSet->d_ptr->columnLabels().at(bar);
+
+ m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix,
+ QVector3D(0.0f, m_yAdjustment, zComp),
+ QVector3D(rotLabelX, rotLabelY, rotLabelZ),
+ m_heightNormalizer, m_selectionMode,
+ m_labelShader, m_labelObj, true, true, LabelMid,
+ alignment);
+
+ delete label;
+ }
+ glDisable(GL_TEXTURE_2D);
+ if (m_labelTransparency > TransparencyNone)
+ glDisable(GL_BLEND);
+
+ // Release label shader
+ m_labelShader->release();
+}
+
+#if defined(Q_OS_ANDROID)
+void Bars3dShared::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ if (!m_zoomActivated) {
+ m_mousePressed = Bars3dShared::MouseOnScene;
+ // update mouse positions to prevent jumping when releasing or repressing a button
+ m_mousePos = event->pos();
+ }
+}
+
+void Bars3dShared::touchEvent(QTouchEvent *event)
+{
+ static int prevDistance = 0;
+
+ QList<QTouchEvent::TouchPoint> points;
+ points = event->touchPoints();
+
+ if (points.count() == 2) {
+ m_mousePressed = Bars3dShared::MouseOnPinch;
+
+ QPointF distance = points.at(0).pos() - points.at(1).pos();
+ int newDistance = distance.manhattanLength();
+ int zoomRate = 1;
+ if (m_zoomLevel > 100)
+ zoomRate = 5;
+ if (newDistance > prevDistance)
+ m_zoomLevel += zoomRate;
+ else
+ m_zoomLevel -= zoomRate;
+ if (m_zoomLevel > 500)
+ m_zoomLevel = 500;
+ else if (m_zoomLevel < 10)
+ m_zoomLevel = 10;
+ prevDistance = newDistance;
+ //qDebug() << "distance" << distance.manhattanLength();
+ }
+}
+#endif
+
+void Bars3dShared::mousePressEvent(QMouseEvent *event)
+{
+ if (Qt::LeftButton == event->button()) {
+ if (m_zoomActivated) {
+ if (event->pos().x() <= m_sceneViewPort.width()
+ && event->pos().y() <= m_sceneViewPort.height()) {
+ m_mousePressed = Bars3dShared::MouseOnOverview;
+ //qDebug() << "Mouse pressed on overview";
+ } else {
+ m_mousePressed = Bars3dShared::MouseOnZoom;
+ //qDebug() << "Mouse pressed on zoom";
+ }
+ } else {
+#if !defined(Q_OS_ANDROID)
+ m_mousePressed = Bars3dShared::MouseOnScene;
+#else
+ m_mousePressed = Bars3dShared::MouseRotating;
+#endif
+ // update mouse positions to prevent jumping when releasing or repressing a button
+ m_mousePos = event->pos();
+ //qDebug() << "Mouse pressed on scene";
+ }
+ } else if (Qt::MiddleButton == event->button()) {
+ // reset rotations
+ m_mousePos = QPoint(0, 0);
+ } else if (Qt::RightButton == event->button()) {
+#if !defined(Q_OS_ANDROID)
+ m_mousePressed = Bars3dShared::MouseRotating;
+#else
+ m_mousePressed = Bars3dShared::MouseOnScene;
+#endif
+ // update mouse positions to prevent jumping when releasing or repressing a button
+ m_mousePos = event->pos();
+ }
+ CameraHelper::updateMousePos(m_mousePos);
+}
+
+void Bars3dShared::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (Bars3dShared::MouseRotating == m_mousePressed) {
+ // update mouse positions to prevent jumping when releasing or repressing a button
+ m_mousePos = event->pos();
+ CameraHelper::updateMousePos(event->pos());
+ }
+ m_mousePressed = Bars3dShared::MouseNone;
+}
+
+void Bars3dShared::mouseMoveEvent(QMouseEvent *event)
+{
+ if (Bars3dShared::MouseRotating == m_mousePressed)
+ m_mousePos = event->pos();
+}
+
+void Bars3dShared::wheelEvent(QWheelEvent *event)
+{
+ if (m_zoomLevel > 100)
+ m_zoomLevel += event->angleDelta().y() / 12;
+ else if (m_zoomLevel > 50)
+ m_zoomLevel += event->angleDelta().y() / 60;
+ else
+ m_zoomLevel += event->angleDelta().y() / 120;
+ if (m_zoomLevel > 500)
+ m_zoomLevel = 500;
+ else if (m_zoomLevel < 10)
+ m_zoomLevel = 10;
+}
+
+void Bars3dShared::resizeNotify()
+{
+ qDebug() << "Bars3dShared::resizeEvent " << width() << "x" <<height();
+
+ // Set view port
+ if (m_zoomActivated)
+ m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5);
+ else
+ m_sceneViewPort = QRect(0, 0, width(), height());
+ m_zoomViewPort = QRect(0, 0, width(), height());
+
+ // Calculate zoom level based on aspect ratio
+ GLfloat div;
+ GLfloat zoomAdjustment;
+ div = qMin(width(), height());
+ zoomAdjustment = defaultRatio * ((width() / div) / (height() / div));
+ //qDebug() << "zoom adjustment" << zoomAdjustment;
+ m_zoomAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f
+
+ // Re-init selection buffer
+ initSelectionBuffer();
+
+#if !defined(QT_OPENGL_ES_2)
+ // Re-init depth buffer
+ if (m_isInitialized && m_shadowQuality > ShadowNone)
+ initDepthBuffer();
+#endif
+}
+
+void Bars3dShared::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative)
+{
+ m_barThickness = thickness;
+ if (relative) {
+ m_barSpacing.setWidth((thickness.width() * 2) * (spacing.width() + 1.0f));
+ m_barSpacing.setHeight((thickness.height() * 2) * (spacing.height() + 1.0f));
+ } else {
+ m_barSpacing = thickness * 2 + spacing * 2;
+ }
+ // Calculate here and at setting sample space
+ calculateSceneScalingFactors();
+}
+
+void Bars3dShared::setBarType(BarStyle style, bool smooth)
+{
+ if (style == Bars) {
+ if (smooth)
+ m_objFile = QStringLiteral(":/defaultMeshes/barSmooth");
+ else
+ m_objFile = QStringLiteral(":/defaultMeshes/bar");
+ } else if (style == Pyramids) {
+ if (smooth)
+ m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth");
+ else
+ m_objFile = QStringLiteral(":/defaultMeshes/pyramid");
+ } else if (style == Cones) {
+ if (smooth)
+ m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth");
+ else
+ m_objFile = QStringLiteral(":/defaultMeshes/cone");
+ } else if (style == Cylinders) {
+ if (smooth)
+ m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth");
+ else
+ m_objFile = QStringLiteral(":/defaultMeshes/cylinder");
+ } else if (style == BevelBars) {
+ if (smooth)
+ m_objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth");
+ else
+ m_objFile = QStringLiteral(":/defaultMeshes/bevelbar");
+ }
+ // Reload mesh data
+ if (m_isInitialized)
+ loadBarMesh();
+}
+
+void Bars3dShared::setMeshFileName(const QString &objFileName)
+{
+ m_objFile = objFileName;
+}
+
+void Bars3dShared::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow,
+ const QString &labelColumn, const QString &labelHeight)
+{
+ // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
+ closeZoomMode();
+ // Delete previous data set
+ delete m_dataSet;
+ m_dataSet = new QDataSet();
+ m_sampleCount = qMakePair(samplesRow, samplesColumn);
+ m_dataSet->setLabels(labelRow, labelColumn, labelHeight);
+ // TODO: Invent "idiotproof" max scene size formula..
+ // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high)
+ m_maxSceneSize = 2 * qSqrt(samplesRow * samplesColumn);
+ //qDebug() << "maxSceneSize" << m_maxSceneSize;
+ // Calculate here and at setting bar specs
+ calculateSceneScalingFactors();
+ m_axisLabelX = labelRow;
+ m_axisLabelZ = labelColumn;
+ m_axisLabelY = labelHeight;
+}
+
+void Bars3dShared::setCameraPreset(CameraPreset preset)
+{
+ CameraHelper::setCameraPreset(preset);
+}
+
+void Bars3dShared::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance)
+{
+ m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f);
+ m_verticalRotation = qBound(0.0f, vertical, 90.0f);
+ m_zoomLevel = qBound(10, distance, 500);
+ CameraHelper::setCameraRotation(QPointF(m_horizontalRotation,
+ m_verticalRotation));
+ //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation;
+}
+
+void Bars3dShared::setTheme(ColorTheme theme)
+{
+ m_theme->useTheme(theme);
+ m_drawer->setTheme(*m_theme);
+ // Re-initialize shaders
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ }
+ } else {
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
+ }
+ }
+#else
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentColorOnYES2"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentES2"));
+ }
+#endif
+}
+
+void Bars3dShared::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor,
+ bool uniform)
+{
+ m_theme->m_baseColor = baseColor;
+ m_theme->m_heightColor = heightColor;
+ m_theme->m_depthColor = depthColor;
+ //qDebug() << "colors:" << m_baseColor << m_heightColor << m_depthColor;
+ if (m_theme->m_uniformColor != uniform) {
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ }
+ } else {
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
+ }
+ }
+#else
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentColorOnYES2"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentES2"));
+ }
+#endif
+ }
+ m_theme->m_uniformColor = uniform;
+}
+
+void Bars3dShared::setSelectionMode(SelectionMode mode)
+{
+ m_selectionMode = mode;
+ // Disable zoom if selection mode changes
+ closeZoomMode();
+ // Create zoom selection if there isn't one
+ if (mode >= ModeZoomRow && !m_zoomSelection)
+ m_zoomSelection = new QDataRow();
+}
+
+SelectionMode Bars3dShared::selectionMode()
+{
+ return m_selectionMode;
+}
+
+void Bars3dShared::setFontSize(float fontsize)
+{
+ m_font.setPointSizeF(fontsize);
+ m_drawer->setFont(m_font);
+}
+
+float Bars3dShared::fontSize()
+{
+ return m_font.pointSizeF();
+}
+
+void Bars3dShared::setFont(const QFont &font)
+{
+ m_font = font;
+ m_drawer->setFont(font);
+}
+
+QFont Bars3dShared::font()
+{
+ return m_font;
+}
+
+void Bars3dShared::setLabelTransparency(LabelTransparency transparency)
+{
+ m_labelTransparency = transparency;
+ m_drawer->setTransparency(transparency);
+}
+
+LabelTransparency Bars3dShared::labelTransparency()
+{
+ return m_labelTransparency;
+}
+
+void Bars3dShared::setGridEnabled(bool enable)
+{
+ m_gridEnabled = enable;
+}
+
+bool Bars3dShared::gridEnabled()
+{
+ return m_gridEnabled;
+}
+
+void Bars3dShared::setBackgroundEnabled(bool enable)
+{
+ if (m_bgrEnabled != enable) {
+ m_bgrEnabled = enable;
+ // Load changed bar type
+ loadBarMesh();
+ }
+}
+
+bool Bars3dShared::backgroundEnabled()
+{
+ return m_bgrEnabled;
+}
+
+void Bars3dShared::setShadowQuality(ShadowQuality quality)
+{
+ m_shadowQuality = quality;
+ switch (quality) {
+ case ShadowLow:
+ m_shadowQualityToShader = 33.3f;
+ break;
+ case ShadowMedium:
+ m_shadowQualityToShader = 100.0f;
+ break;
+ case ShadowHigh:
+ m_shadowQualityToShader = 200.0f;
+ break;
+ default:
+ m_shadowQualityToShader = 0.0f;
+ break;
+ }
+ if (m_isInitialized) {
+#if !defined(QT_OPENGL_ES_2)
+ if (m_shadowQuality > ShadowNone) {
+ // Re-init depth buffer
+ initDepthBuffer();
+ // Re-init shaders
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ }
+ initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ } else {
+ // Re-init shaders
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnY"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
+ }
+ initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
+ }
+#else
+ if (!m_theme->m_uniformColor) {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentColorOnYES2"));
+ } else {
+ initShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentES2"));
+ }
+ initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"),
+ QStringLiteral(":/shaders/fragmentES2"));
+#endif
+ }
+}
+
+ShadowQuality Bars3dShared::shadowQuality()
+{
+ return m_shadowQuality;
+}
+
+void Bars3dShared::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum)
+{
+ m_tickCount = tickCount;
+ m_tickStep = step;
+ if (tickCount > 0 && step > 0) {
+ m_heightNormalizer = tickCount * step;
+ calculateHeightAdjustment(QPair<float, float>(minimum, m_heightNormalizer));
+ }
+}
+
+void Bars3dShared::addDataRow(const QVector<float> &dataRow, const QString &labelRow,
+ const QVector<QString> &labelsColumn)
+{
+ // Convert to QDataRow and add to QDataSet
+ QDataRow *row = new QDataRow(labelRow);
+ for (int i = 0; i < dataRow.size(); i++)
+ row->addItem(new QDataItem(dataRow.at(i)));
+ row->d_ptr->verifySize(m_sampleCount.first);
+ m_dataSet->addRow(row);
+ handleLimitChange();
+ m_dataSet->setLabels(m_axisLabelX, m_axisLabelZ, m_axisLabelY,
+ QVector<QString>(), labelsColumn);
+ m_dataSet->d_ptr->verifySize(m_sampleCount.second);
+}
+
+void Bars3dShared::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow,
+ const QVector<QString> &labelsColumn)
+{
+ // Convert to QDataRow and add to QDataSet
+ QDataRow *row = new QDataRow(labelRow);
+ for (int i = 0; i < dataRow.size(); i++)
+ row->addItem(dataRow.at(i));
+ row->d_ptr->verifySize(m_sampleCount.first);
+ m_dataSet->addRow(row);
+ handleLimitChange();
+ m_dataSet->setLabels(m_axisLabelX, m_axisLabelZ, m_axisLabelY,
+ QVector<QString>(), labelsColumn);
+ m_dataSet->d_ptr->verifySize(m_sampleCount.second);
+}
+
+void Bars3dShared::addDataRow(QDataRow *dataRow)
+{
+ QDataRow *row = dataRow;
+ // Check that the input data fits into sample space, and resize if it doesn't
+ row->d_ptr->verifySize(m_sampleCount.first);
+ // With each new row, the previous data row must be moved back
+ // ie. we need as many vectors as we have rows in the sample space
+ m_dataSet->addRow(row);
+ // if the added data pushed us over sample space, remove the oldest data set
+ m_dataSet->d_ptr->verifySize(m_sampleCount.second);
+ handleLimitChange();
+}
+
+void Bars3dShared::addDataSet(const QVector< QVector<float> > &data,
+ const QVector<QString> &labelsRow,
+ const QVector<QString> &labelsColumn)
+{
+ // Copy axis labels
+ QString xAxis;
+ QString zAxis;
+ QString yAxis;
+ m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis);
+ // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
+ closeZoomMode();
+ // Delete old data set
+ delete m_dataSet;
+ m_dataSet = new QDataSet();
+ // Give drawer to data set
+ m_dataSet->d_ptr->setDrawer(m_drawer);
+ // Convert to QDataRow and add to QDataSet
+ QDataRow *row;
+ for (int rowNr = 0; rowNr < data.size(); rowNr++) {
+ if (labelsRow.size() >= (rowNr + 1))
+ row = new QDataRow(labelsRow.at(rowNr));
+ else
+ row = new QDataRow();
+ for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++)
+ row->addItem(new QDataItem(data.at(rowNr).at(colNr)));
+ row->d_ptr->verifySize(m_sampleCount.first);
+ m_dataSet->addRow(row);
+ row++;
+ }
+ handleLimitChange();
+ m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn);
+ m_dataSet->d_ptr->verifySize(m_sampleCount.second);
+}
+
+void Bars3dShared::addDataSet(const QVector< QVector<QDataItem*> > &data,
+ const QVector<QString> &labelsRow,
+ const QVector<QString> &labelsColumn)
+{
+ // Copy axis labels
+ QString xAxis;
+ QString zAxis;
+ QString yAxis;
+ m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis);
+ // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
+ closeZoomMode();
+ // Delete old data set
+ delete m_dataSet;
+ m_dataSet = new QDataSet();
+ // Give drawer to data set
+ m_dataSet->d_ptr->setDrawer(m_drawer);
+ // Convert to QDataRow and add to QDataSet
+ QDataRow *row;
+ for (int rowNr = 0; rowNr < data.size(); rowNr++) {
+ if (labelsRow.size() >= (rowNr + 1))
+ row = new QDataRow(labelsRow.at(rowNr));
+ else
+ row = new QDataRow();
+ for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++)
+ row->addItem(data.at(rowNr).at(colNr));
+ row->d_ptr->verifySize(m_sampleCount.first);
+ m_dataSet->addRow(row);
+ row++;
+ }
+ handleLimitChange();
+ m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn);
+ m_dataSet->d_ptr->verifySize(m_sampleCount.second);
+}
+
+void Bars3dShared::addDataSet(QDataSet* dataSet)
+{
+ // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
+ closeZoomMode();
+ // Delete old data set
+ delete m_dataSet;
+ // Check sizes
+ dataSet->d_ptr->verifySize(m_sampleCount.second, m_sampleCount.first);
+ // Take ownership of given set
+ m_dataSet = dataSet;
+ handleLimitChange();
+ // Give drawer to data set
+ m_dataSet->d_ptr->setDrawer(m_drawer);
+}
+
+const QSize Bars3dShared::size()
+{
+ return m_boundingRect.size();;
+}
+
+const QRect Bars3dShared::boundingRect()
+{
+ return m_boundingRect;
+}
+
+void Bars3dShared::setBoundingRect(const QRect boundingRect)
+{
+ m_boundingRect = boundingRect;
+}
+
+void Bars3dShared::setWidth(const int width)
+{
+ m_boundingRect.setWidth(width);
+}
+
+int Bars3dShared::width()
+{
+ return m_boundingRect.width();
+}
+
+void Bars3dShared::setHeight(const int height)
+{
+ m_boundingRect.setHeight(height);
+}
+
+int Bars3dShared::height()
+{
+ return m_boundingRect.height();
+}
+
+void Bars3dShared::setX(const int x)
+{
+ m_boundingRect.setX(x);
+}
+
+int Bars3dShared::x()
+{
+ return m_boundingRect.x();
+}
+
+void Bars3dShared::setY(const int y)
+{
+ m_boundingRect.setY(y);
+}
+
+int Bars3dShared::y()
+{
+ return m_boundingRect.y();
+}
+
+void Bars3dShared::loadBarMesh()
+{
+ QString objectFileName = m_objFile;
+ if (m_barObj)
+ delete m_barObj;
+ // If background is disabled, load full version of bar mesh
+ if (!m_bgrEnabled)
+ objectFileName.append(QStringLiteral("Full"));
+ m_barObj = new ObjectHelper(objectFileName);
+ m_barObj->load();
+}
+
+void Bars3dShared::loadBackgroundMesh()
+{
+ if (!m_isInitialized)
+ return;
+
+ if (m_backgroundObj)
+ delete m_backgroundObj;
+ if (m_negativeValues)
+ m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground"));
+ else
+ m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background"));
+ m_backgroundObj->load();
+}
+
+void Bars3dShared::loadGridLineMesh()
+{
+ if (m_gridLineObj)
+ delete m_gridLineObj;
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj->load();
+}
+
+void Bars3dShared::loadLabelMesh()
+{
+ if (m_labelObj)
+ delete m_labelObj;
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj->load();
+}
+
+void Bars3dShared::initShaders(const QString &vertexShader, const QString &fragmentShader)
+{
+ if (m_barShader)
+ delete m_barShader;
+ m_barShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_barShader->initialize();
+}
+
+void Bars3dShared::initSelectionShader()
+{
+ if (m_selectionShader)
+ delete m_selectionShader;
+ m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"),
+ QStringLiteral(":/shaders/fragmentSelection"));
+ m_selectionShader->initialize();
+}
+
+void Bars3dShared::initSelectionBuffer()
+{
+#ifndef USE_HAX0R_SELECTION
+ if (m_selectionTexture) {
+ glDeleteFramebuffers(1, &m_selectionFrameBuffer);
+ glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
+ m_textureHelper->deleteTexture(&m_selectionTexture);
+ }
+ m_selectionTexture = m_textureHelper->createSelectionTexture(this->size(),
+ m_selectionFrameBuffer,
+ m_selectionDepthBuffer);
+#endif
+}
+
+#if !defined(QT_OPENGL_ES_2)
+void Bars3dShared::initDepthShader()
+{
+ if (m_depthShader)
+ delete m_depthShader;
+ m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"),
+ QStringLiteral(":/shaders/fragmentDepth"));
+ m_depthShader->initialize();
+}
+
+void Bars3dShared::initDepthBuffer()
+{
+ if (m_depthTexture) {
+ glDeleteFramebuffers(1, &m_depthFrameBuffer);
+ m_textureHelper->deleteTexture(&m_depthTexture);
+ }
+ m_depthTexture = m_textureHelper->createDepthTexture(this->size(), m_depthFrameBuffer,
+ m_shadowQuality);
+}
+#endif
+
+void Bars3dShared::initBackgroundShaders(const QString &vertexShader,
+ const QString &fragmentShader)
+{
+ if (m_backgroundShader)
+ delete m_backgroundShader;
+ m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_backgroundShader->initialize();
+}
+
+void Bars3dShared::initLabelShaders(const QString &vertexShader, const QString &fragmentShader)
+{
+ if (m_labelShader)
+ delete m_labelShader;
+ m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_labelShader->initialize();
+}
+
+void Bars3dShared::updateTextures()
+{
+ // Drawer has changed; this flag needs to be checked when checking if we need to update labels
+ m_updateLabels = true;
+}
+
+void Bars3dShared::calculateSceneScalingFactors()
+{
+ // Calculate scene scaling and translation factors
+ m_rowWidth = ((m_sampleCount.first + 1) * m_barSpacing.width()) / 2.0f;
+ m_columnDepth = ((m_sampleCount.second + 1) * m_barSpacing.height()) / 2.0f;
+ m_maxDimension = qMax(m_rowWidth, m_columnDepth);
+ m_scaleFactor = qMin((m_sampleCount.first * (m_maxDimension / m_maxSceneSize)),
+ (m_sampleCount.second * (m_maxDimension / m_maxSceneSize)));
+ m_scaleX = m_barThickness.width() / m_scaleFactor;
+ m_scaleZ = m_barThickness.height() / m_scaleFactor;
+ //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor;
+ //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor;
+ //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension;
+}
+
+void Bars3dShared::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits)
+{
+ // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer
+ m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer);
+ //qDebug() << m_yAdjustment;
+}
+
+Bars3dShared::SelectionType Bars3dShared::isSelected(GLint row, GLint bar,
+ const QVector3D &selection)
+{
+ //static QVector3D prevSel = selection; // TODO: For debugging
+ SelectionType isSelectedType = SelectionNone;
+#ifdef USE_HAX0R_SELECTION
+ if (selection == Utils::vectorFromColor(m_theme->m_windowColor))
+#else
+ if (selection == skipColor)
+#endif
+ return isSelectedType; // skip window
+
+ //#if !defined(QT_OPENGL_ES_2)
+ // QVector3D current = QVector3D((GLuint)row, (GLuint)bar, 0);
+ //#else
+ QVector3D current = QVector3D((GLubyte)row, (GLubyte)bar, 0);
+ //#endif
+
+ // TODO: For debugging
+ //if (selection != prevSel) {
+ // qDebug() << "current" << current.x() << current .y() << current.z();
+ // qDebug() << "selection" << selection.x() << selection .y() << selection.z();
+ // prevSel = selection;
+ //}
+ if (current == selection)
+ isSelectedType = SelectionBar;
+ else if (current.y() == selection.y() && (m_selectionMode == ModeBarAndColumn
+ || m_selectionMode == ModeBarRowAndColumn
+ || m_selectionMode == ModeZoomColumn))
+ isSelectedType = SelectionColumn;
+ else if (current.x() == selection.x() && (m_selectionMode == ModeBarAndRow
+ || m_selectionMode == ModeBarRowAndColumn
+ || m_selectionMode == ModeZoomRow))
+ isSelectedType = SelectionRow;
+ return isSelectedType;
+}
+
+void Bars3dShared::handleLimitChange()
+{
+ // Get the limits
+ QPair<GLfloat, GLfloat> limits = m_dataSet->d_ptr->limitValues();
+
+ // TODO: What if we have only negative values?
+
+ // Check if we have negative values
+ if (limits.first < 0 && !m_negativeValues) {
+ m_negativeValues = true;
+ // Reload background
+ loadBackgroundMesh();
+ } else if (limits.first >= 0 && m_negativeValues) {
+ m_negativeValues = false;
+ // Reload background
+ loadBackgroundMesh();
+ }
+
+ // Don't auto-adjust height if tick count is set
+ if (m_tickCount == 0) {
+ m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first));
+ calculateHeightAdjustment(limits);
+ }
+}
+
+void Bars3dShared::closeZoomMode()
+{
+ m_zoomActivated = false;
+ m_sceneViewPort = QRect(0, 0, this->width(), this->height());
+}
+
+QTENTERPRISE_DATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/engine/bars3dshared_p.h b/src/datavis3d/engine/bars3dshared_p.h
new file mode 100644
index 00000000..2250b7c4
--- /dev/null
+++ b/src/datavis3d/engine/bars3dshared_p.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Q3DBARSSHARED_p_H
+#define Q3DBARSSHARED_p_H
+
+#include "QtDataVis3D/qdatavis3dglobal.h"
+#include "QtDataVis3D/qdatavis3namespace.h"
+
+#include <QtCore/QSize>
+#include <QtCore/QObject>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QFont>
+
+#include <QWindow>
+
+class QOpenGLPaintDevice;
+class QPoint;
+class QSizeF;
+class QOpenGLShaderProgram;
+
+QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
+
+class QDataItem;
+class QDataRow;
+class QDataSet;
+class ShaderHelper;
+class ObjectHelper;
+class TextureHelper;
+class Theme;
+class Drawer;
+class LabelItem;
+class Bars3dSharedPrivate;
+
+class QTENTERPRISE_DATAVIS3D_EXPORT Bars3dShared : public QObject, public QOpenGLFunctions
+{
+ Q_OBJECT
+
+public:
+ enum SelectionType {
+ SelectionNone = 0,
+ SelectionBar,
+ SelectionRow,
+ SelectionColumn
+ };
+
+ enum MousePressType {
+ MouseNone = 0,
+ MouseOnScene,
+ MouseOnOverview,
+ MouseOnZoom,
+ MouseRotating,
+ MouseOnPinch
+ };
+
+ QRect m_boundingRect;
+ QOpenGLPaintDevice *m_paintDevice;
+ ShaderHelper *m_barShader;
+ ShaderHelper *m_depthShader;
+ ShaderHelper *m_selectionShader;
+ ShaderHelper *m_backgroundShader;
+ ShaderHelper *m_labelShader;
+ ObjectHelper *m_barObj;
+ ObjectHelper *m_backgroundObj;
+ ObjectHelper *m_gridLineObj;
+ ObjectHelper *m_labelObj;
+ QPair<int, int> m_sampleCount;
+ QString m_objFile;
+ MousePressType m_mousePressed;
+ QPoint m_mousePos;
+ GLint m_zoomLevel;
+ GLfloat m_zoomAdjustment;
+ GLfloat m_horizontalRotation;
+ GLfloat m_verticalRotation;
+ QSizeF m_barThickness;
+ QSizeF m_barSpacing;
+ GLfloat m_heightNormalizer;
+ GLfloat m_yAdjustment;
+ GLfloat m_rowWidth;
+ GLfloat m_columnDepth;
+ GLfloat m_maxDimension;
+ GLfloat m_scaleX;
+ GLfloat m_scaleZ;
+ GLfloat m_scaleFactor;
+ GLfloat m_maxSceneSize;
+ Theme *m_theme;
+ bool m_isInitialized;
+ SelectionMode m_selectionMode;
+ QDataItem *m_selectedBar;
+ QDataRow *m_zoomSelection;
+ QDataSet *m_dataSet;
+ QString m_axisLabelX;
+ QString m_axisLabelZ;
+ QString m_axisLabelY;
+ QRect m_sceneViewPort;
+ QRect m_zoomViewPort;
+ bool m_zoomActivated;
+ TextureHelper *m_textureHelper;
+ LabelTransparency m_labelTransparency;
+ QFont m_font;
+ Drawer *m_drawer;
+ bool m_xFlipped;
+ bool m_zFlipped;
+ bool m_yFlipped;
+ GLuint m_bgrTexture;
+ GLuint m_depthTexture;
+ GLuint m_selectionTexture;
+ GLuint m_depthFrameBuffer;
+ GLuint m_selectionFrameBuffer;
+ GLuint m_selectionDepthBuffer;
+ bool m_updateLabels;
+ bool m_gridEnabled;
+ bool m_bgrEnabled;
+ ShadowQuality m_shadowQuality;
+ GLfloat m_shadowQualityToShader;
+ GLint m_tickCount;
+ GLfloat m_tickStep;
+ bool m_negativeValues;
+ GLuint m_fbohandle;
+ QSize m_size;
+
+public:
+ explicit Bars3dShared(QRect rect, GLuint fbohandle=0);
+ ~Bars3dShared();
+
+ void initializeOpenGL();
+ void render();
+
+ // Add a row of data. Each new row is added to the front of the sample space, moving previous
+ // rows back (if sample space is more than one row deep)
+ void addDataRow(const QVector<GLfloat> &dataRow,
+ const QString &labelRow = QString(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+ // ownership of dataItems is transferred
+ void addDataRow(const QVector<QDataItem*> &dataRow,
+ const QString &labelRow = QString(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+ // ownership of dataRow is transferred
+ void addDataRow(QDataRow *dataRow);
+
+ // Add complete data set at a time, as a vector of data rows
+ void addDataSet(const QVector< QVector<GLfloat> > &data,
+ const QVector<QString> &labelsRow = QVector<QString>(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+
+ // ownership of dataItems is transferred
+ void addDataSet(const QVector< QVector<QDataItem*> > &data,
+ const QVector<QString> &labelsRow = QVector<QString>(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+ // ownership of dataSet is transferred
+ void addDataSet(QDataSet* dataSet);
+
+ // bar thickness, spacing between bars, and is spacing relative to thickness or absolute
+ // y -component sets the thickness/spacing of z -direction
+ // With relative 0.0f means side-to-side, 1.0f = one thickness in between
+ void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f),
+ QSizeF spacing = QSizeF(1.0f, 1.0f),
+ bool relative = true);
+
+ // bar type; bars (=cubes), pyramids, cones, cylinders, etc.
+ void setBarType(BarStyle style, bool smooth = false);
+
+ // override bar type with own mesh
+ void setMeshFileName(const QString &objFileName);
+
+ // how many samples per row and column, and names for axes
+ void setupSampleSpace(int samplesRow, int samplesColumn,
+ const QString &labelRow = QString(),
+ const QString &labelColumn = QString(),
+ const QString &labelHeight = QString());
+
+ // Select preset camera placement
+ void setCameraPreset(CameraPreset preset);
+
+ // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and
+ // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in
+ // percentage (10...500))
+ void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100);
+
+ // Set theme (bar colors, shaders, window color, background colors, light intensity and text
+ // colors are affected)
+ void setTheme(ColorTheme theme);
+
+ // Set color if you don't want to use themes. Set uniform to false if you want the (height)
+ // color to change from bottom to top
+ void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor,
+ bool uniform = true);
+
+ // Set tick count and step. Note; tickCount * 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.
+ void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f);
+
+ // TODO: light placement API
+
+ // 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();
+
+ // Change selection mode; single bar, bar and row, bar and column, or all
+ void setSelectionMode(SelectionMode mode);
+ SelectionMode selectionMode();
+
+ // Font size adjustment
+ void setFontSize(float fontsize);
+ float fontSize();
+
+ // Set font
+ void setFont(const QFont &font);
+ QFont font();
+
+ // Label transparency adjustment
+ void setLabelTransparency(LabelTransparency transparency);
+ LabelTransparency labelTransparency();
+
+ // Enable or disable background grid
+ void setGridEnabled(bool enable);
+ bool gridEnabled();
+
+ // Enable or disable background mesh
+ void setBackgroundEnabled(bool enable);
+ bool backgroundEnabled();
+
+ // Adjust shadow quality
+ void setShadowQuality(ShadowQuality quality);
+ ShadowQuality shadowQuality();
+
+#if defined(Q_OS_ANDROID)
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void touchEvent(QTouchEvent *event);
+#endif
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void wheelEvent(QWheelEvent *event);
+ void resizeNotify();
+
+ void loadBarMesh();
+ void loadBackgroundMesh();
+ void loadGridLineMesh();
+ void loadLabelMesh();
+ void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ void initSelectionShader();
+ void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
+ void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
+ void initSelectionBuffer();
+#if !defined(QT_OPENGL_ES_2)
+ void initDepthShader();
+ void initDepthBuffer();
+#endif
+ void updateTextures();
+ void calculateSceneScalingFactors();
+ void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits);
+ SelectionType isSelected(GLint row, GLint bar, const QVector3D &selection);
+ void handleLimitChange();
+ void closeZoomMode();
+
+private:
+ void drawZoomScene();
+ void drawScene();
+ Q_DISABLE_COPY(Bars3dShared)
+
+ friend class DeclarativeBars;
+ friend class DeclarativeBarsRenderer;
+};
+
+QTENTERPRISE_DATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/engine/drawer.cpp b/src/datavis3d/engine/drawer.cpp
index d642b645..3c4d30cf 100644
--- a/src/datavis3d/engine/drawer.cpp
+++ b/src/datavis3d/engine/drawer.cpp
@@ -68,14 +68,20 @@ Drawer::Drawer(const Theme &theme, const QFont &font, LabelTransparency transpar
: m_theme(theme),
m_font(font),
m_transparency(transparency),
- m_textureHelper(new TextureHelper())
+ m_textureHelper(0)
{
- initializeOpenGLFunctions();
}
Drawer::~Drawer()
{
+}
+void Drawer::initializeOpenGL()
+{
+ if (!m_textureHelper) {
+ initializeOpenGLFunctions();
+ m_textureHelper = new TextureHelper();
+ }
}
void Drawer::setTheme(const Theme &theme)
@@ -289,6 +295,8 @@ void Drawer::generateLabelTexture(QDataItem *item)
void Drawer::generateLabelItem(LabelItem *item, const QString &text)
{
+ initializeOpenGL();
+
// Delete previous texture, if there is one
GLuint labelTexture = item->textureId();
if (labelTexture)
diff --git a/src/datavis3d/engine/drawer_p.h b/src/datavis3d/engine/drawer_p.h
index 5330a4aa..e31ab0cb 100644
--- a/src/datavis3d/engine/drawer_p.h
+++ b/src/datavis3d/engine/drawer_p.h
@@ -66,7 +66,7 @@ class ShaderHelper;
class ObjectHelper;
class TextureHelper;
-class Drawer : public QObject, protected QOpenGLFunctions
+class Drawer : public QObject, public QOpenGLFunctions
{
Q_OBJECT
@@ -74,6 +74,8 @@ public:
explicit Drawer(const Theme &theme, const QFont &font, LabelTransparency transparency);
~Drawer();
+ void initializeOpenGL();
+
void setTheme(const Theme &theme);
void setFont(const QFont &font);
void setTransparency(LabelTransparency transparency);
diff --git a/src/datavis3d/engine/engine.pri b/src/datavis3d/engine/engine.pri
index ba063186..b220120f 100644
--- a/src/datavis3d/engine/engine.pri
+++ b/src/datavis3d/engine/engine.pri
@@ -6,7 +6,8 @@ SOURCES += $$PWD/q3dwindow.cpp \
$$PWD/qdataset.cpp \
$$PWD/theme.cpp \
$$PWD/drawer.cpp \
- $$PWD/labelitem.cpp
+ $$PWD/labelitem.cpp \
+ $$PWD/bars3dshared.cpp
HEADERS += $$PWD/q3dwindow_p.h \
$$PWD/q3dwindow.h \
@@ -22,6 +23,7 @@ HEADERS += $$PWD/q3dwindow_p.h \
$$PWD/qdataset_p.h \
$$PWD/theme_p.h \
$$PWD/drawer_p.h \
- $$PWD/labelitem_p.h
+ $$PWD/labelitem_p.h \
+ $$PWD/bars3dshared_p.h
RESOURCES += engine/engine.qrc
diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp
index 7ccab074..39750b38 100644
--- a/src/datavis3d/engine/q3dbars.cpp
+++ b/src/datavis3d/engine/q3dbars.cpp
@@ -41,18 +41,8 @@
#include "q3dbars.h"
#include "q3dbars_p.h"
-#include "camerahelper_p.h"
-#include "qdataitem_p.h"
-#include "qdatarow_p.h"
-#include "qdataset_p.h"
-#include "shaderhelper_p.h"
-#include "objecthelper_p.h"
-#include "texturehelper_p.h"
-#include "theme_p.h"
-#include "utils_p.h"
-#include "drawer_p.h"
-
-#include <QMatrix4x4>
+#include "bars3dshared_p.h"
+
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <QScreen>
@@ -62,1765 +52,431 @@
#include <QDebug>
-// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light
-// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway)
-#define USE_WIDER_SHADOWS
-
-// You can verify that depth buffer drawing works correctly by uncommenting this.
-// You should see the scene from where the light is
-//#define SHOW_DEPTH_TEXTURE_SCENE
-
-//#define DISPLAY_RENDER_SPEED
-
-#ifdef DISPLAY_RENDER_SPEED
-#include <QTime>
-#endif
-
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-//#define USE_HAX0R_SELECTION // keep this defined until the "real" method works
-#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels
-
-const GLfloat gridLineWidth = 0.005f;
-static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color
-
-Q3DBars::Q3DBars()
- : d_ptr(new Q3DBarsPrivate(this))
-{
-}
-
+/*!
+ * \class Q3DBars
+ * \inmodule QtDataVis3D
+ * \brief The Q3DBars class provides methods for rendering 3D bar graphs.
+ * \since 1.0.0
+ *
+ * This class enables developers to render bar graphs in 3D and to view them by rotating the scene
+ * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming
+ * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be
+ * reset to default camera view by clicking mouse wheel. In touch devices rotation is done
+ * by tap-and-move, selection by tap-and-hold and zoom by pinch.
+ *
+ * Methods are provided for changing bar types, themes, bar selection modes and so on. See the
+ * methods for more detailed descriptions.
+ *
+ * \section1 How to construct a minimal Q3DBars chart
+ *
+ * After constructing Q3DBars, you need to set up sample space using setupSampleSpace(). Let's
+ * set the sample space to 5 rows and 5 columns:
+ *
+ * \snippet doc_src_q3dbars_construction.cpp 0
+ *
+ * Now Q3DBars is ready to receive data to be rendered. Add one row of 5 floats into the data
+ * set:
+ *
+ * \snippet doc_src_q3dbars_construction.cpp 1
+ *
+ * \note We set the sample space to 5 x 5, but we are inserting only one row of data. This is ok,
+ * the rest of the rows will just be blank.
+ *
+ * Finally you will need to set it visible:
+ *
+ * \snippet doc_src_q3dbars_construction.cpp 2
+ *
+ * The complete code needed to create and display this chart is:
+ *
+ * \snippet doc_src_q3dbars_construction.cpp 3
+ *
+ * And this is what those few lines of code produce:
+ *
+ * \image q3dbars-minimal.png
+ *
+ * The scene can be rotated and zoomed into, but no other interaction is included in this minimal
+ * code example. You can learn more by familiarizing yourself with the examples provided, like
+ * the \l{Rainfall Example} or the \l{Widget Example}.
+ *
+ * \sa Q3DMaps, {Qt Data Visualization 3D C++ Classes}
+ */
+
+/*!
+ \enum BarStyle
+
+ Predefined bar types.
+
+ \value Bars
+ Basic cubic bar.
+ \value Pyramids
+ Four -sided pyramid.
+ \value Cones
+ Basic cone.
+ \value Cylinders
+ Basic cylinder.
+ \value BevelBars
+ Slilghtly beveled (rounded) cubic bar.
+ \value Spheres
+ Sphere. Not usable in Q3DBars.
+*/
+
+/*!
+ \enum CameraPreset
+
+ Predefined positions for camera.
+
+ \value PresetFrontLow
+ \value PresetFront
+ \value PresetFrontHigh
+ \value PresetLeftLow
+ \value PresetLeft
+ \value PresetLeftHigh
+ \value PresetRightLow
+ \value PresetRight
+ \value PresetRightHigh
+ \value PresetBehindLow
+ \value PresetBehind
+ \value PresetBehindHigh
+ \value PresetIsometricLeft
+ \value PresetIsometricLeftHigh
+ \value PresetIsometricRight
+ \value PresetIsometricRightHigh
+ \value PresetDirectlyAbove
+ \value PresetDirectlyAboveCW45
+ \value PresetDirectlyAboveCCW45
+ \value PresetFrontBelow
+ From PresetFrontBelow onward these only work for graphs including negative values.
+ They act as Preset...Low for positive-only values.
+ \value PresetLeftBelow
+ \value PresetRightBelow
+ \value PresetBehindBelow
+ \value PresetDirectlyBelow
+ Acts as PresetFrontLow for positive -only bars.
+*/
+
+/*!
+ \enum ColorTheme
+
+ Predefined color themes.
+
+ \value ThemeSystem
+ \value ThemeBlueCerulean
+ \value ThemeBlueIcy
+ \value ThemeBlueNcs
+ \value ThemeBrownSand
+ \value ThemeDark
+ \value ThemeHighContrast
+ \value ThemeLight
+*/
+
+/*!
+ \enum SelectionMode
+
+ Bar selection modes.
+
+ \value ModeNone
+ Selection mode disabled.
+ \value ModeBar
+ Selection selects a single bar.
+ \value ModeBarAndRow
+ Selection selects a single bar and highlights the row it is on.
+ \value ModeBarAndColumn
+ Selection selects a single bar and highlights the column it is on.
+ \value ModeBarRowAndColumn
+ Selection selects a single bar and highlights the row and the column it is on.
+ \value ModeZoomRow
+ Selection selects a single bar and displays the row it is on in a separate view. The
+ original view is shrunk into upper left corner. Original view is restored by clicking
+ on it.
+ \value ModeZoomColumn
+ Selection selects a single bar and displays the column it is on in a separate view. The
+ original view is shrunk into upper left corner. Original view is restored by clicking
+ on it.
+*/
+
+/*!
+ \enum ShadowQuality
+
+ Quality of shadows.
+
+ \value ShadowNone
+ Shadows are disabled.
+ \value ShadowLow
+ Shadows are rendered in low quality.
+ \value ShadowMedium
+ Shadows are rendered in medium quality.
+ \value ShadowHigh
+ Shadows are rendered in high quality.
+*/
+
+/*!
+ \enum LabelTransparency
+
+ Label transparencies.
+
+ \value TransparencyNone
+ Full solid, using colors from theme.
+ \value TransparencyFromTheme
+ Use colors and transparencies from theme.
+ \value TransparencyNoBackground
+ Draw just text on transparent background.
+*/
+
+/*!
+ * \a fbohandle Handle to QML2 scene graph's framebuffer object. Developers should not need to
+ * ever use this directly. Not used when using C++ API.
+ *
+ * \a windowsize QML2 window size Developers should not need to ever use this directly. Not
+ * used when using C++ API.
+ *
+ * Constructs a new 3D bar window. Parameters are not used unless instantiating from Qt Quick 2.
+ */
+Q3DBars::Q3DBars(GLuint fbohandle, const QSize &windowsize)
+ : d_ptr(new Q3DBarsPrivate(this, geometry(), fbohandle))
+{
+}
+
+/*!
+ * Destroys the 3d bar window.
+ */
Q3DBars::~Q3DBars()
{
}
+/*!
+ * \internal
+ */
void Q3DBars::initialize()
{
- // Initialize shaders
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- }
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- // Init the depth buffer (for shadows)
- d_ptr->initDepthBuffer();
- } else {
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
-#else
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentColorOnYES2"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
- }
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
-#endif
-
- d_ptr->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.
- d_ptr->initDepthShader();
-#endif
-
- // Init selection shader
- d_ptr->initSelectionShader();
-
-#ifndef USE_HAX0R_SELECTION
- // Init the selection buffer
- d_ptr->initSelectionBuffer();
-#endif
-
- // Load default mesh
- d_ptr->loadBarMesh();
-
- // Load background mesh
- d_ptr->loadBackgroundMesh();
-
- // Load grid line mesh
- d_ptr->loadGridLineMesh();
-
- // Load label mesh
- d_ptr->loadLabelMesh();
-
- // Set OpenGL features
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
-
-#if !defined(QT_OPENGL_ES_2)
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
- glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
-#endif
-
- // Set initial camera position
- // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later
- CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp),
- QVector3D(0.0f, 0.0f, zComp),
- QVector3D(0.0f, 1.0f, 0.0f));
-
- // Set view port
-#ifdef USE_QML2_VERSION
- glViewport(0, 0, 800, 500);
-#else
- glViewport(0, 0, width(), height());
-#endif
-
- // Set initialized -flag
- d_ptr->m_isInitialized = true;
+ d_ptr->m_shared->setWidth(width());
+ d_ptr->m_shared->setHeight(height());
+ d_ptr->m_shared->initializeOpenGL();
}
+/*!
+ * \internal
+ */
void Q3DBars::render()
{
-#ifdef USE_QML2_VERSION
- glDepthMask(true);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
-#endif
-
- if (!d_ptr->m_isInitialized)
- return;
-
-#ifdef DISPLAY_RENDER_SPEED
- // For speed computation
- static bool firstRender = true;
- static QTime lastTime;
- static GLint nbFrames = 0;
- if (firstRender) {
- lastTime.start();
- firstRender = false;
- }
-
- // Measure speed (as milliseconds per frame)
- nbFrames++;
- if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago
- qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)";
- nbFrames = 0;
- lastTime.restart();
- }
-#endif
-
- // If zoom selection is on, draw zoom scene
- drawZoomScene();
- // Draw bars scene
- drawScene();
-}
-
-void Q3DBars::drawZoomScene()
-{
- // Set clear color
- QVector3D clearColor = Utils::vectorFromColor(d_ptr->m_theme->m_windowColor);
- glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- // If no zoom, return
- if (!d_ptr->m_zoomActivated)
- return;
-
- GLfloat barPosX = 0;
- GLint startBar = 0;
- GLint stopBar = d_ptr->m_zoomSelection->d_ptr->row().size();
- GLint stepBar = 1;
- QVector3D lightPos;
-
- // Specify viewport
- glViewport(d_ptr->m_zoomViewPort.x(), d_ptr->m_zoomViewPort.y(),
- d_ptr->m_zoomViewPort.width(), d_ptr->m_zoomViewPort.height());
-
- // Set up projection matrix
- QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(45.0f, (GLfloat)d_ptr->m_zoomViewPort.width()
- / (GLfloat)d_ptr->m_zoomViewPort.height(), 0.1f, 100.0f);
-
-#ifdef ROTATE_ZOOM_SELECTION
- // Calculate view matrix
- QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(d_ptr->m_mousePos,
- d_ptr->m_zoomLevel
- * d_ptr->m_zoomAdjustment,
- d_ptr->m_zoomViewPort.width(),
- d_ptr->m_zoomViewPort.height());
-
- // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos))
- lightPos = CameraHelper::calculateLightPosition(defaultLightPos);
-
- if (viewMatrix.row(0).z() <= 0) {
- startBar = d_ptr->m_zoomSelection->d_ptr->row().size() - 1;
- stopBar = -1;
- stepBar = -1;
- }
-#else
- // Set view matrix
- QMatrix4x4 viewMatrix;
-
- // Adjust scaling (zoom rate based on aspect ratio)
- GLfloat camPosZoomed = 5.0f / d_ptr->m_zoomAdjustment + zComp;
-
- viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camPosZoomed),
- QVector3D(0.0f, 0.0f, zComp),
- QVector3D(0.0f, 1.0f, 0.0f));
-
- // Set light position a bit below the camera to reduce glare (depends on do we have row or column zoom)
- QVector3D zoomLightPos = defaultLightPos;
- zoomLightPos.setY(-10.0f);
- if (ModeZoomColumn == d_ptr->m_selectionMode)
- lightPos = CameraHelper::calculateLightPosition(zoomLightPos, -85.0f);
- else
- lightPos = CameraHelper::calculateLightPosition(zoomLightPos, 5.0f);
-#endif
-
- // Bind bar shader
- d_ptr->m_barShader->bind();
-
- // Draw bars
- // Draw the selected row / column
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(bar);
- if (!item)
- continue;
-
- GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer;
-
- if (barHeight < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- GLfloat barPosY = item->d_ptr->translation().y() - d_ptr->m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f
- if (ModeZoomRow == d_ptr->m_selectionMode)
- barPosX = item->d_ptr->translation().x();
- else
- barPosX = -(item->d_ptr->translation().z() - zComp); // flip z; frontmost bar to the left
- modelMatrix.translate(barPosX, barPosY, zComp);
- modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ));
- itModelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ));
-
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
-
- QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor);
- QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor) * barHeight;
-
- QVector3D barColor = baseColor + heightColor;
-
- GLfloat lightStrength = d_ptr->m_theme->m_lightStrength;
-
- if (barHeight != 0) {
- // Set shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), lightStrength);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(),
- d_ptr->m_theme->m_ambientStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj);
- }
- }
-
- // Release bar shader
- d_ptr->m_barShader->release();
-
- // Draw labels
- d_ptr->m_labelShader->bind();
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- glCullFace(GL_BACK);
- if (d_ptr->m_labelTransparency > TransparencyNone) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- // Draw labels for axes
- QDataItem *dummyItem = NULL;
- LabelItem x;
- LabelItem z;
- LabelItem y;
- d_ptr->m_dataSet->d_ptr->axisLabelItems(&x, &z, &y);
- LabelItem zoomSelectionLabel = d_ptr->m_zoomSelection->d_ptr->labelItem();
- if (ModeZoomRow == d_ptr->m_selectionMode) {
- d_ptr->m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, false, false, LabelTop);
- d_ptr->m_drawer->drawLabel(*dummyItem, z, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, false, false, LabelBottom);
- } else {
- d_ptr->m_drawer->drawLabel(*dummyItem, x, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, false, false, LabelBottom);
- d_ptr->m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, false, false, LabelTop);
- }
- d_ptr->m_drawer->drawLabel(*dummyItem, y, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 90.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, false, false, LabelLeft);
-
- // Draw labels for bars
- for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) {
- QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col);
- // Draw values
- d_ptr->m_drawer->drawLabel(*item, item->d_ptr->label(), viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj);
- // Draw labels
- LabelItem labelItem;
- if (ModeZoomRow == d_ptr->m_selectionMode) {
- if (d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > col) {
- // If draw order of bars is flipped, label draw order should be too
- if (d_ptr->m_xFlipped) {
- labelItem = d_ptr->m_dataSet->d_ptr->columnLabelItems().at(
- d_ptr->m_dataSet->d_ptr->columnLabelItems().size() - col - 1);
- } else {
- labelItem = d_ptr->m_dataSet->d_ptr->columnLabelItems().at(col);
- }
- }
- } else {
- if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > col) {
- // If draw order of bars is flipped, label draw order should be too
- if (d_ptr->m_zFlipped) {
- labelItem = d_ptr->m_dataSet->d_ptr->rowLabelItems().at(
- d_ptr->m_dataSet->d_ptr->rowLabelItems().size() - col - 1);
- } else {
- labelItem = d_ptr->m_dataSet->d_ptr->rowLabelItems().at(col);
- }
- }
- }
- d_ptr->m_drawer->drawLabel(*item, labelItem, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, -45.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, false, false, LabelBelow);
- }
-
- glDisable(GL_TEXTURE_2D);
- if (d_ptr->m_labelTransparency > TransparencyNone)
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
-
- // Release label shader
- d_ptr->m_labelShader->release();
-}
-
-void Q3DBars::drawScene()
-{
- GLint startBar = 0;
- GLint stopBar = 0;
- GLint stepBar = 0;
-
- GLint startRow = 0;
- GLint stopRow = 0;
- GLint stepRow = 0;
-
- GLfloat backgroundRotation = 0;
-
- GLfloat barPos = 0;
- GLfloat rowPos = 0;
-
- static QVector3D selection = skipColor;
-
-#ifdef USE_QML2_VERSION
- d_ptr->m_sceneViewPort = QRect(0, 0, 800, 500);
-#endif
-
- // Specify viewport
- glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(),
- d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height());
-
- // Set up projection matrix
- QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(45.0f, (GLfloat)d_ptr->m_sceneViewPort.width()
- / (GLfloat)d_ptr->m_sceneViewPort.height(), 0.1f, 100.0f);
-
- // Calculate view matrix
-#ifdef USE_QML2_VERSION
- static int rot = 0;
- rot += 5;
- if (rot > 2870)
- rot = 0;
- d_ptr->m_mousePos.setX(rot);
- d_ptr->m_mousePos.setY(100);
-#endif
- QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(d_ptr->m_mousePos,
- d_ptr->m_zoomLevel
- * d_ptr->m_zoomAdjustment,
- d_ptr->m_sceneViewPort.width(),
- d_ptr->m_sceneViewPort.height(),
- d_ptr->m_negativeValues);
-
- // Calculate drawing order
- // Draw order is reversed to optimize amount of drawing (ie. draw front objects first, depth test handles not needing to draw objects behind them)
- if (viewMatrix.row(0).x() > 0) {
- startRow = 0;
- stopRow = d_ptr->m_sampleCount.second;
- stepRow = 1;
- d_ptr->m_zFlipped = false;
- } else {
- startRow = d_ptr->m_sampleCount.second - 1;
- stopRow = -1;
- stepRow = -1;
- d_ptr->m_zFlipped = true;
- }
- if (viewMatrix.row(0).z() <= 0) {
- startBar = 0;
- stopBar = d_ptr->m_sampleCount.first;
- stepBar = 1;
- d_ptr->m_xFlipped = false;
- } else {
- startBar = d_ptr->m_sampleCount.first - 1;
- stopBar = -1;
- stepBar = -1;
- d_ptr->m_xFlipped = true;
- }
-
- // Check if we're viewing the scene from below
- if (viewMatrix.row(2).y() < 0)
- d_ptr->m_yFlipped = true;
- else
- d_ptr->m_yFlipped = false;
-
- // calculate background rotation based on view matrix rotation
- if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0)
- backgroundRotation = 270.0f;
- else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0)
- backgroundRotation = 180.0f;
- else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0)
- backgroundRotation = 90.0f;
- else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0)
- backgroundRotation = 0.0f;
-
- // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos))
- QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos);
- //lightPos = QVector3D(0.0f, 4.0f, zComp); // center of bars, 4.0f above - for testing
-
- // Skip depth rendering if we're in zoom mode
- // TODO: Fix this, causes problems if depth rendering is off in zoom mode
- // Introduce regardless of shadow quality to simplify logic
- QMatrix4x4 depthViewMatrix;
- QMatrix4x4 depthProjectionMatrix;
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone/*!d_ptr->m_zoomActivated*/) {
- // Render scene into a depth texture for using with shadow mapping
- // Bind depth shader
- d_ptr->m_depthShader->bind();
-
- // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
- glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(),
- d_ptr->m_sceneViewPort.width() * d_ptr->m_shadowQuality,
- d_ptr->m_sceneViewPort.height() * d_ptr->m_shadowQuality);
-
- // Enable drawing to framebuffer
- glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_depthFrameBuffer);
- glClear(GL_DEPTH_BUFFER_BIT);
-
- // Get the depth view matrix
- // It may be possible to hack lightPos here if we want to make some tweaks to shadow
- depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 1.0f, 0.0f));
- // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed
- //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3);
- // Set the depth projection matrix
-#ifdef USE_WIDER_SHADOWS
- // Use this for a bit exaggerated shadows
- depthProjectionMatrix.perspective(20.0f, (GLfloat)d_ptr->m_sceneViewPort.width()
- / (GLfloat)d_ptr->m_sceneViewPort.height(), 3.0f, 100.0f);
-#else
- // Use these for normal shadows, with the light further away
- depthProjectionMatrix = projectionMatrix;
-#endif
- // Draw bars to depth buffer
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- if (!d_ptr->m_dataSet->d_ptr->getRow(row))
- continue;
- QDataItem *item = d_ptr->m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar);
- if (!item)
- continue;
-
- GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer;
-
- // skip shadows for 0 -height bars
- if (barHeight == 0)
- continue;
-
- // Set front face culling for positive valued bars and back face culling for
- // negative valued bars to reduce self-shadowing issues
- if (barHeight < 0)
- glCullFace(GL_BACK);
- else
- glCullFace(GL_FRONT);
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- barPos = (bar + 1) * (d_ptr->m_barSpacing.width());
- rowPos = (row + 1) * (d_ptr->m_barSpacing.height());
-
- modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor,
- barHeight - d_ptr->m_yAdjustment,
- (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor
- + zComp);
- modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ));
-
- MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix);
-
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf());
- glVertexAttribPointer(d_ptr->m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
- (void *)0);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt());
- }
- }
-
- // Disable drawing to framebuffer (= enable drawing to screen)
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- // Release depth shader
- d_ptr->m_depthShader->release();
-
-#if 0 // Use this if you want to see what is being drawn to the framebuffer
- // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it)
- d_ptr->m_labelShader->bind();
- glEnable(GL_TEXTURE_2D);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 viewmatrix;
- viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp),
- QVector3D(0.0f, 0.0f, zComp),
- QVector3D(0.0f, 1.0f, 0.0f));
- modelMatrix.translate(0.0, 0.0, zComp);
- QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix;
- d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix);
- d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj,
- d_ptr->m_depthTexture);
- glDisable(GL_TEXTURE_2D);
- d_ptr->m_labelShader->release();
-#endif
- // Reset culling to normal
- glCullFace(GL_BACK);
-
- // Revert to original viewport
- glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(),
- d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height());
- }
-#endif
-
- // Skip selection mode drawing if we're zoomed or have no selection mode
- if (!d_ptr->m_zoomActivated && d_ptr->m_selectionMode > ModeNone) {
- // Bind selection shader
- d_ptr->m_selectionShader->bind();
-
- // Draw bars to selection buffer
-#ifndef USE_HAX0R_SELECTION
- glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_selectionFrameBuffer);
- glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
- glClearColor(skipColor.x() / 255, skipColor.y() / 255, skipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor)
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
-#endif
- glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- if (!d_ptr->m_dataSet->d_ptr->getRow(row))
- continue;
- QDataItem *item = d_ptr->m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar);
- if (!item)
- continue;
-
- GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer;
-
- if (barHeight < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- barPos = (bar + 1) * (d_ptr->m_barSpacing.width());
- rowPos = (row + 1) * (d_ptr->m_barSpacing.height());
-
- modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor,
- barHeight - d_ptr->m_yAdjustment,
- (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor
- + zComp);
- modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ));
-
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
-
- // TODO: Save position to qdataitem, so that we don't need to calculate it each time?
-
-//#if !defined(QT_OPENGL_ES_2)
-// QVector3D barColor = QVector3D((GLdouble)row / 32767.0,
-// (GLdouble)bar / 32767.0,
-// 0.0);
-//#else
- QVector3D barColor = QVector3D((GLdouble)row / 255.0,
- (GLdouble)bar / 255.0,
- 0.0);
-//#endif
-
- d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->MVP(),
- MVPMatrix);
- d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->color(),
- barColor);
-
-#ifdef USE_HAX0R_SELECTION
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf());
- glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(),
- 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(),
- GL_UNSIGNED_SHORT, (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(d_ptr->m_selectionShader->posAtt());
-#else
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf());
- glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(),
- 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(d_ptr->m_selectionShader->posAtt());
-#endif
- }
- }
- glEnable(GL_DITHER);
-
- // Read color under cursor
- if (Q3DBarsPrivate::MouseOnScene == d_ptr->m_mousePressed)
- selection = Utils::getSelection(d_ptr->m_mousePos, height());
-
-#ifndef USE_HAX0R_SELECTION
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-#endif
-
- // Release selection shader
- d_ptr->m_selectionShader->release();
-
-#if 0 // Use this if you want to see what is being drawn to the framebuffer
- glCullFace(GL_BACK);
- d_ptr->m_labelShader->bind();
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 viewmatrix;
- viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp),
- QVector3D(0.0f, 0.0f, zComp),
- QVector3D(0.0f, 1.0f, 0.0f));
- modelMatrix.translate(0.0, 0.0, zComp);
- QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix;
- d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix);
- d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, true,
- d_ptr->m_selectionTexture);
- glDisable(GL_TEXTURE_2D);
- d_ptr->m_labelShader->release();
-#endif
-
-#ifdef USE_HAX0R_SELECTION
- // Set clear color
- QVector3D clearColor = Utils::vectorFromColor(d_ptr->m_theme->m_windowColor);
- glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
- // Clear after selection
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-#endif
- }
-
- // Bind bar shader
- d_ptr->m_barShader->bind();
-
- // Enable texturing
- glEnable(GL_TEXTURE_2D);
-
- // Draw bars
- if (!d_ptr->m_zoomActivated && d_ptr->m_zoomSelection)
- d_ptr->m_zoomSelection->d_ptr->clear();
- bool barSelectionFound = false;
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- if (!d_ptr->m_dataSet->d_ptr->getRow(row))
- continue;
- QDataItem *item = d_ptr->m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar);
- if (!item)
- continue;
-
- GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer;
-
- if (barHeight < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 itModelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 depthMVPMatrix;
-
- barPos = (bar + 1) * (d_ptr->m_barSpacing.width());
- rowPos = (row + 1) * (d_ptr->m_barSpacing.height());
- modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor,
- barHeight - d_ptr->m_yAdjustment,
- (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + zComp);
- modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ));
- itModelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ));
-#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-#else
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
-#endif
- depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor);
- QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor)
- * barHeight;
- QVector3D depthColor = Utils::vectorFromColor(d_ptr->m_theme->m_depthColor)
- * (float(row) / GLfloat(d_ptr->m_sampleCount.second));
-
- QVector3D barColor = baseColor + heightColor + depthColor;
-
- GLfloat lightStrength = d_ptr->m_theme->m_lightStrength;
- if (d_ptr->m_selectionMode > ModeNone) {
- Q3DBarsPrivate::SelectionType selectionType = d_ptr->isSelected(row, bar,
- selection);
- switch (selectionType) {
- case Q3DBarsPrivate::SelectionBar: {
- barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightBarColor);
- lightStrength = d_ptr->m_theme->m_highlightLightStrength;
- // Insert data to QDataItem. We have no ownership, don't delete the previous one
- if (!d_ptr->m_zoomActivated) {
- d_ptr->m_selectedBar = item;
- if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > row
- && d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > bar) {
- d_ptr->m_selectedBar->setPosition(
- QPoint(d_ptr->m_dataSet->d_ptr->rowLabelItems().size()
- - row - 1,
- d_ptr->m_dataSet->d_ptr->columnLabelItems().size()
- - bar - 1));
- }
- item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
- barSelectionFound = true;
- if (d_ptr->m_selectionMode >= ModeZoomRow) {
- item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
- d_ptr->m_zoomSelection->addItem(item);
- }
- }
- break;
- }
- case Q3DBarsPrivate::SelectionRow: {
- // Current bar is on the same row as the selected bar
- barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightRowColor);
- lightStrength = d_ptr->m_theme->m_highlightLightStrength;
- if (!d_ptr->m_zoomActivated && ModeZoomRow == d_ptr->m_selectionMode) {
- item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
- d_ptr->m_zoomSelection->addItem(item);
- if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > row) {
- d_ptr->m_zoomSelection->d_ptr->setLabelItem(
- d_ptr->m_dataSet->d_ptr->rowLabelItems().at(
- d_ptr->m_dataSet->d_ptr->rowLabelItems().size()
- - row - 1));
- }
- }
- break;
- }
- case Q3DBarsPrivate::SelectionColumn: {
- // Current bar is on the same column as the selected bar
- barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightColumnColor);
- lightStrength = d_ptr->m_theme->m_highlightLightStrength;
- if (!d_ptr->m_zoomActivated && ModeZoomColumn == d_ptr->m_selectionMode) {
- item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D());
- d_ptr->m_zoomSelection->addItem(item);
- if (d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > bar) {
- d_ptr->m_zoomSelection->d_ptr->setLabelItem(
- d_ptr->m_dataSet->d_ptr->columnLabelItems().at(
- d_ptr->m_dataSet->d_ptr->columnLabelItems().size()
- - bar - 1));
- }
- }
- break;
- }
- case Q3DBarsPrivate::SelectionNone: {
- // Current bar is not selected, nor on a row or column
- // do nothing
- break;
- }
- }
- }
-
- if (barHeight != 0) {
- // Set shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(),
- itModelMatrix.transposed().inverted());
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(),
- d_ptr->m_theme->m_ambientStrength);
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Set shadow shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(),
- d_ptr->m_shadowQualityToShader);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(),
- depthMVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- lightStrength / 10.0f);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj,
- 0, d_ptr->m_depthTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- lightStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj);
- }
- }
- }
- }
-
- // Release bar shader
- d_ptr->m_barShader->release();
-
- // Bind background shader
- d_ptr->m_backgroundShader->bind();
-
- if (d_ptr->m_negativeValues)
- glDisable(GL_CULL_FACE);
- else
- glCullFace(GL_BACK);
-
- // Draw background
- if (d_ptr->m_bgrEnabled && d_ptr->m_backgroundObj) {
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 depthMVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- modelMatrix.translate(0.0f, 1.0f - d_ptr->m_yAdjustment, zComp);
- modelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor,
- 1.0f,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor));
- modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
- itModelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor,
- 1.0f,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor));
-
-#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-#else
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
-#endif
- depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- QVector3D backgroundColor = Utils::vectorFromColor(d_ptr->m_theme->m_backgroundColor);
-
- // Set shader bindings
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightP(),
- lightPos);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->view(),
- viewMatrix);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->model(),
- modelMatrix);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->nModel(),
- itModelMatrix.inverted().transposed());
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(),
- MVPMatrix);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->color(),
- backgroundColor);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->ambientS(),
- d_ptr->m_theme->m_ambientStrength * 2.0f);
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Set shadow shader bindings
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->shadowQ(),
- d_ptr->m_shadowQualityToShader);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->depth(),
- depthMVPMatrix);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(),
- d_ptr->m_theme->m_lightStrength / 10.0f);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj,
- 0, d_ptr->m_depthTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(),
- d_ptr->m_theme->m_lightStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj);
- }
- }
-
- // Disable textures
- glDisable(GL_TEXTURE_2D);
-
- // Release background shader
- d_ptr->m_backgroundShader->release();
-
- // Reset culling
- if (d_ptr->m_negativeValues) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- }
-
- // Draw grid lines
- if (d_ptr->m_gridEnabled && d_ptr->m_heightNormalizer) {
- // Bind bar shader
- d_ptr->m_barShader->bind();
-
- // Set unchanging shader bindings
- QVector3D barColor = Utils::vectorFromColor(d_ptr->m_theme->m_gridLine);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(),
- d_ptr->m_theme->m_ambientStrength);
-
- // Floor lines: rows
- for (GLfloat row = 0.0f; row <= d_ptr->m_sampleCount.second; row++) {
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 depthMVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- rowPos = (row + 0.5f) * (d_ptr->m_barSpacing.height());
- modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment,
- (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + zComp);
- modelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth,
- gridLineWidth));
- itModelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth,
- gridLineWidth));
- // If we're viewing from below, grid line object must be flipped
- if (d_ptr->m_yFlipped)
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
-
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
- depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- // Set the rest of the shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix);
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Set shadow shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(),
- d_ptr->m_shadowQualityToShader);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(),
- depthMVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength / 10.0f);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj,
- 0, d_ptr->m_depthTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj);
- }
- }
-
- // Floor lines: columns
- for (GLfloat bar = 0.0f; bar <= d_ptr->m_sampleCount.first; bar++) {
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 depthMVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- barPos = (bar + 0.5f) * (d_ptr->m_barSpacing.width());
- modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor,
- -d_ptr->m_yAdjustment, zComp);
- modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor));
- itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor));
-
- // If we're viewing from below, grid line object must be flipped
- if (d_ptr->m_yFlipped)
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
-
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
- depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- // Set the rest of the shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix);
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Set shadow shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(),
- d_ptr->m_shadowQualityToShader);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(),
- depthMVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength / 10.0f);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj,
- 0, d_ptr->m_depthTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj);
- }
- }
-
- // Wall lines: back wall
- GLfloat heightStep = d_ptr->m_heightNormalizer / 5.0f; // default to 5 lines
- GLfloat startLine;
-
- if (d_ptr->m_tickCount > 0)
- heightStep = d_ptr->m_tickStep;
-
- if (d_ptr->m_negativeValues)
- startLine = -d_ptr->m_heightNormalizer;
- else
- startLine = heightStep;
-
- for (GLfloat lineHeight = startLine; lineHeight <= d_ptr->m_heightNormalizer;
- lineHeight += heightStep) {
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 depthMVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- if (d_ptr->m_zFlipped) {
- modelMatrix.translate(0.0f,
- 2.0f * lineHeight / d_ptr->m_heightNormalizer
- - d_ptr->m_yAdjustment,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor + zComp);
- } else {
- modelMatrix.translate(0.0f,
- 2.0f * lineHeight / d_ptr->m_heightNormalizer
- - d_ptr->m_yAdjustment,
- -d_ptr->m_columnDepth / d_ptr->m_scaleFactor + zComp);
- }
- modelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth,
- gridLineWidth));
- itModelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth,
- gridLineWidth));
-
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
- depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- // Set the rest of the shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix);
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Set shadow shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(),
- d_ptr->m_shadowQualityToShader);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(),
- depthMVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength / 10.0f);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj,
- 0, d_ptr->m_depthTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj);
- }
- }
-
- // Wall lines: side wall
- for (GLfloat lineHeight = startLine; lineHeight <= d_ptr->m_heightNormalizer;
- lineHeight += heightStep) {
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 depthMVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- if (d_ptr->m_xFlipped) {
- modelMatrix.translate(d_ptr->m_rowWidth / d_ptr->m_scaleFactor,
- 2.0f * lineHeight / d_ptr->m_heightNormalizer
- - d_ptr->m_yAdjustment,
- zComp);
- } else {
- modelMatrix.translate(-d_ptr->m_rowWidth / d_ptr->m_scaleFactor,
- 2.0f * lineHeight / d_ptr->m_heightNormalizer
- - d_ptr->m_yAdjustment,
- zComp);
- }
- modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor));
- itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth,
- d_ptr->m_columnDepth / d_ptr->m_scaleFactor));
-
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
- depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
-
- // Set the rest of the shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix);
-
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Set shadow shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(),
- d_ptr->m_shadowQualityToShader);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(),
- depthMVPMatrix);
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength / 10.0f);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj,
- 0, d_ptr->m_depthTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(),
- d_ptr->m_theme->m_lightStrength);
-
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj);
- }
- }
-
- // Release bar shader
- d_ptr->m_barShader->release();
- }
-
- // TODO: Draw y labels
-
- // Generate label textures for zoom selection if m_updateLabels is set
- if (d_ptr->m_zoomActivated && d_ptr->m_updateLabels) {
- // Create label textures
- for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) {
- QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col);
- d_ptr->m_drawer->generateLabelTexture(item);
- }
- }
-
- // Handle zoom activation and label drawing
- if (!barSelectionFound) {
- // We have no ownership, don't delete. Just NULL the pointer.
- d_ptr->m_selectedBar = NULL;
- if (d_ptr->m_zoomActivated && Q3DBarsPrivate::MouseOnOverview == d_ptr->m_mousePressed) {
- d_ptr->m_sceneViewPort = QRect(0, 0, width(), height());
- d_ptr->m_zoomActivated = false;
- }
- } else if (d_ptr->m_selectionMode >= ModeZoomRow
- && Q3DBarsPrivate::MouseOnScene == d_ptr->m_mousePressed) {
- // Activate zoom mode
- d_ptr->m_zoomActivated = true;
- d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5);
-
- // Create label textures
- for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) {
- QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col);
- d_ptr->m_drawer->generateLabelTexture(item);
- }
- } else {
- // Print value of selected bar
- static QDataItem *prevItem = d_ptr->m_selectedBar;
- d_ptr->m_labelShader->bind();
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- if (d_ptr->m_labelTransparency > TransparencyNone) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-#ifndef DISPLAY_FULL_DATA_ON_SELECTION
- // Draw just the value string of the selected bar
- if (prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) {
- d_ptr->m_drawer->generateLabelTexture(d_ptr->m_selectedBar);
- prevItem = d_ptr->m_selectedBar;
- }
-
- d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, d_ptr->m_selectedBar->d_ptr->label(),
- viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, true);
-#else
- static bool firstSelection = true;
- // Draw the value string followed by row label and column label
- LabelItem labelItem = d_ptr->m_selectedBar->d_ptr->selectionLabel();
- if (firstSelection || prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) {
- QString labelText = d_ptr->m_selectedBar->d_ptr->valueStr();
- if ((d_ptr->m_dataSet->d_ptr->columnLabels().size()
- > d_ptr->m_selectedBar->d_ptr->position().y())
- && (d_ptr->m_dataSet->d_ptr->rowLabels().size()
- > d_ptr->m_selectedBar->d_ptr->position().x())) {
- labelText.append(QStringLiteral(" ("));
- labelText.append(d_ptr->m_dataSet->d_ptr->rowLabels().at(
- d_ptr->m_selectedBar->d_ptr->position().x()));
- labelText.append(QStringLiteral(", "));
- labelText.append(d_ptr->m_dataSet->d_ptr->columnLabels().at(
- d_ptr->m_selectedBar->d_ptr->position().y()));
- labelText.append(QStringLiteral(")"));
- //qDebug() << labelText;
- }
- d_ptr->m_drawer->generateLabelItem(&labelItem, labelText);
- d_ptr->m_selectedBar->d_ptr->setSelectionLabel(labelItem);
- prevItem = d_ptr->m_selectedBar;
- firstSelection = false;
- }
-
- d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, labelItem, viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer,
- d_ptr->m_selectionMode, d_ptr->m_labelShader,
- d_ptr->m_labelObj, true, false);
-#endif
- glDisable(GL_TEXTURE_2D);
- if (d_ptr->m_labelTransparency > TransparencyNone)
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
-
- // Release label shader
- d_ptr->m_labelShader->release();
-
- // Reset label update flag; they should have been updated when we get here
- d_ptr->m_updateLabels = false;
- }
-
- // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here.
- // Bind label shader
- d_ptr->m_labelShader->bind();
-
- glEnable(GL_TEXTURE_2D);
- if (d_ptr->m_labelTransparency > TransparencyNone) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?)
- for (int row = 0; row != d_ptr->m_sampleCount.second; row += 1) {
- // Go through all rows and get position of max+1 or min-1 column, depending on x flip
- // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems
- rowPos = (row + 1) * (d_ptr->m_barSpacing.height());
- barPos = 0;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 0.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignRight;
- if (d_ptr->m_zFlipped)
- rotLabelY = 180.0f;
- if (d_ptr->m_xFlipped) {
- barPos = (d_ptr->m_sampleCount.first + 1) * (d_ptr->m_barSpacing.width());
- alignment = Qt::AlignLeft;
- }
- if (d_ptr->m_yFlipped) {
- if (d_ptr->m_zFlipped)
- rotLabelY = 0.0f;
- else
- rotLabelY = 180.0f;
- rotLabelZ = 180.0f;
- }
- QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor,
- -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering"
- (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor
- + zComp);
-
- // TODO: Try it; draw the label here
-
- // Create a data item
- QDataItem *label = new QDataItem();
- label->d_ptr->setTranslation(labelPos);
- if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > row) {
- label->d_ptr->setLabel(d_ptr->m_dataSet->d_ptr->rowLabelItems().at(
- d_ptr->m_dataSet->d_ptr->rowLabelItems().size() - row - 1));
- }
-
- //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->rowLabels().at(row);
-
- d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(rotLabelX, rotLabelY, rotLabelZ),
- d_ptr->m_heightNormalizer, d_ptr->m_selectionMode,
- d_ptr->m_labelShader, d_ptr->m_labelObj, true, true, LabelMid,
- alignment);
-
- delete label;
- }
- for (int bar = 0; bar != d_ptr->m_sampleCount.first; bar += 1) {
- // Go through all columns and get position of max+1 or min-1 row, depending on z flip
- // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems
- barPos = (bar + 1) * (d_ptr->m_barSpacing.width());
- rowPos = 0;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignLeft;
- if (d_ptr->m_xFlipped)
- rotLabelY = -90.0f;
- if (d_ptr->m_zFlipped) {
- rowPos = (d_ptr->m_sampleCount.second + 1) * (d_ptr->m_barSpacing.height());
- alignment = Qt::AlignRight;
- }
- if (d_ptr->m_yFlipped) {
- if (d_ptr->m_xFlipped)
- rotLabelY = -90.0f;
- else
- rotLabelY = 90.0f;
- rotLabelZ = 180.0f;
- }
- QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor,
- -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering"
- (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor
- + zComp);
-
- // TODO: Try it; draw the label here
-
- // Create a data item
- QDataItem *label = new QDataItem();
- label->d_ptr->setTranslation(labelPos);
- if (d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > bar) {
- label->d_ptr->setLabel(d_ptr->m_dataSet->d_ptr->columnLabelItems().at(
- d_ptr->m_dataSet->d_ptr->columnLabelItems().size()
- - bar - 1));
- }
-
- //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->columnLabels().at(bar);
-
- d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix,
- QVector3D(0.0f, d_ptr->m_yAdjustment, zComp),
- QVector3D(rotLabelX, rotLabelY, rotLabelZ),
- d_ptr->m_heightNormalizer, d_ptr->m_selectionMode,
- d_ptr->m_labelShader, d_ptr->m_labelObj, true, true, LabelMid,
- alignment);
-
- delete label;
- }
- glDisable(GL_TEXTURE_2D);
- if (d_ptr->m_labelTransparency > TransparencyNone)
- glDisable(GL_BLEND);
-
- // Release label shader
- d_ptr->m_labelShader->release();
+ d_ptr->m_shared->render();
}
#if defined(Q_OS_ANDROID)
+/*!
+ * \internal
+ */
void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event)
{
- if (!d_ptr->m_zoomActivated) {
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnScene;
- // update mouse positions to prevent jumping when releasing or repressing a button
- d_ptr->m_mousePos = event->pos();
- }
+ d_ptr->m_shared->mouseDoubleClickEvent(event);
}
+/*!
+ * \internal
+ */
void Q3DBars::touchEvent(QTouchEvent *event)
{
- static int prevDistance = 0;
-
- QList<QTouchEvent::TouchPoint> points;
- points = event->touchPoints();
-
- if (points.count() == 2) {
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnPinch;
-
- QPointF distance = points.at(0).pos() - points.at(1).pos();
- int newDistance = distance.manhattanLength();
- int zoomRate = 1;
- if (d_ptr->m_zoomLevel > 100)
- zoomRate = 5;
- if (newDistance > prevDistance)
- d_ptr->m_zoomLevel += zoomRate;
- else
- d_ptr->m_zoomLevel -= zoomRate;
- if (d_ptr->m_zoomLevel > 500)
- d_ptr->m_zoomLevel = 500;
- else if (d_ptr->m_zoomLevel < 10)
- d_ptr->m_zoomLevel = 10;
- prevDistance = newDistance;
- //qDebug() << "distance" << distance.manhattanLength();
- }
+ d_ptr->m_shared->touchEvent(event);
}
#endif
+/*!
+ * \internal
+ */
void Q3DBars::mousePressEvent(QMouseEvent *event)
{
- if (Qt::LeftButton == event->button()) {
- if (d_ptr->m_zoomActivated) {
- if (event->pos().x() <= d_ptr->m_sceneViewPort.width()
- && event->pos().y() <= d_ptr->m_sceneViewPort.height()) {
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnOverview;
- //qDebug() << "Mouse pressed on overview";
- } else {
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnZoom;
- //qDebug() << "Mouse pressed on zoom";
- }
- } else {
-#if !defined(Q_OS_ANDROID)
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnScene;
-#else
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseRotating;
-#endif
- // update mouse positions to prevent jumping when releasing or repressing a button
- d_ptr->m_mousePos = event->pos();
- //qDebug() << "Mouse pressed on scene";
- }
- } else if (Qt::MiddleButton == event->button()) {
- // reset rotations
- d_ptr->m_mousePos = QPoint(0, 0);
- } else if (Qt::RightButton == event->button()) {
-#if !defined(Q_OS_ANDROID)
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseRotating;
-#else
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnScene;
-#endif
- // update mouse positions to prevent jumping when releasing or repressing a button
- d_ptr->m_mousePos = event->pos();
- }
- CameraHelper::updateMousePos(d_ptr->m_mousePos);
+ d_ptr->m_shared->mousePressEvent(event);
}
+/*!
+ * \internal
+ */
void Q3DBars::mouseReleaseEvent(QMouseEvent *event)
{
- if (Q3DBarsPrivate::MouseRotating == d_ptr->m_mousePressed) {
- // update mouse positions to prevent jumping when releasing or repressing a button
- d_ptr->m_mousePos = event->pos();
- CameraHelper::updateMousePos(event->pos());
- }
- d_ptr->m_mousePressed = Q3DBarsPrivate::MouseNone;
+ d_ptr->m_shared->mouseReleaseEvent(event);
}
+/*!
+ * \internal
+ */
void Q3DBars::mouseMoveEvent(QMouseEvent *event)
{
- if (Q3DBarsPrivate::MouseRotating == d_ptr->m_mousePressed)
- d_ptr->m_mousePos = event->pos();
+ d_ptr->m_shared->mouseMoveEvent(event);
}
+/*!
+ * \internal
+ */
void Q3DBars::wheelEvent(QWheelEvent *event)
{
- if (d_ptr->m_zoomLevel > 100)
- d_ptr->m_zoomLevel += event->angleDelta().y() / 12;
- else if (d_ptr->m_zoomLevel > 50)
- d_ptr->m_zoomLevel += event->angleDelta().y() / 60;
- else
- d_ptr->m_zoomLevel += event->angleDelta().y() / 120;
- if (d_ptr->m_zoomLevel > 500)
- d_ptr->m_zoomLevel = 500;
- else if (d_ptr->m_zoomLevel < 10)
- d_ptr->m_zoomLevel = 10;
+ d_ptr->m_shared->wheelEvent(event);
}
+/*!
+ * \internal
+ */
void Q3DBars::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
-
- // Set view port
- if (d_ptr->m_zoomActivated)
- d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5);
- else
- d_ptr->m_sceneViewPort = QRect(0, 0, width(), height());
- d_ptr->m_zoomViewPort = QRect(0, 0, width(), height());
-
- // Calculate zoom level based on aspect ratio
- GLfloat div;
- GLfloat zoomAdjustment;
- div = qMin(width(), height());
- zoomAdjustment = defaultRatio * ((width() / div) / (height() / div));
- //qDebug() << "zoom adjustment" << zoomAdjustment;
- d_ptr->m_zoomAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f
-
- // Re-init selection buffer
- d_ptr->initSelectionBuffer();
-
-#if !defined(QT_OPENGL_ES_2)
- // Re-init depth buffer
- if (d_ptr->m_isInitialized && d_ptr->m_shadowQuality > ShadowNone)
- d_ptr->initDepthBuffer();
-#endif
+ d_ptr->m_shared->setWidth(width());
+ d_ptr->m_shared->setHeight(height());
+ if (d_ptr->m_shared->m_isInitialized)
+ d_ptr->m_shared->resizeNotify();
}
-void Q3DBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative)
+// TODO: Document
+// Size
+void Q3DBars::setWidth(const int width)
{
- d_ptr->m_barThickness = thickness;
- if (relative) {
- d_ptr->m_barSpacing.setWidth((thickness.width() * 2) * (spacing.width() + 1.0f));
- d_ptr->m_barSpacing.setHeight((thickness.height() * 2) * (spacing.height() + 1.0f));
- } else {
- d_ptr->m_barSpacing = thickness * 2 + spacing * 2;
- }
- // Calculate here and at setting sample space
- d_ptr->calculateSceneScalingFactors();
+ d_ptr->m_shared->setWidth(width);
+ QWindow::setWidth(width);
}
-void Q3DBars::setBarType(BarStyle style, bool smooth)
+void Q3DBars::setHeight(const int height)
{
- if (style == Bars) {
- if (smooth)
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/barSmooth");
- else
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bar");
- } else if (style == Pyramids) {
- if (smooth)
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth");
- else
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramid");
- } else if (style == Cones) {
- if (smooth)
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth");
- else
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cone");
- } else if (style == Cylinders) {
- if (smooth)
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth");
- else
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinder");
- } else if (style == BevelBars) {
- if (smooth)
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth");
- else
- d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bevelbar");
- }
- // Reload mesh data
- if (d_ptr->m_isInitialized)
- d_ptr->loadBarMesh();
+ d_ptr->m_shared->setHeight(height);
+ QWindow::setHeight(height);
}
-void Q3DBars::setMeshFileName(const QString &objFileName)
+/*!
+ * \a thickness Thickness of a bar in x and z axes.
+ *
+ * \a spacing Spacing between bars in x and z axes. If relative -flag is true, value of 0.0f
+ * means the bars are side-to-side and for example 1.0f means there is one thickness in between the
+ * bars.
+ *
+ * \a relative A flag to indicate if spacing is meant to be absolute or relative. \c true by
+ * default.
+ *
+ * Sets bar specifications. Bar thickness is relative, as scene is automatically scaled to fit into
+ * the view.
+ */
+void Q3DBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative)
{
- d_ptr->m_objFile = objFileName;
+ d_ptr->m_shared->setBarSpecs(thickness, spacing, relative);
}
+/*!
+ * \a style One of the values in \c BarStyle. \c Bars by default.
+ *
+ * \a smooth A flag to set shading to smooth. \c false by default.
+ *
+ * Sets the bar type to one of the supplied ones.
+ *
+ * \sa setMeshFileName()
+ */
+void Q3DBars::setBarType(BarStyle style, bool smooth)
+{
+ d_ptr->m_shared->setBarType(style, smooth);
+}
+
+/*!
+ * \a samplesRow How many rows of data there will be.
+ *
+ * \a samplesColumn How many items there are per row.
+ *
+ * \a labelRow QString label for the rows, ie. x -axis label.
+ *
+ * \a labelColumn QString label for the columns, ie. z -axis label.
+ *
+ * \a labelHeight QString label for height, ie. y -axis label.
+ *
+ * Set up sample space. This must be called to initialize the sample space before adding data to the
+ * Q3DBars.
+ *
+ * \sa addDataRow(), addDataSet()
+ */
void Q3DBars::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow,
const QString &labelColumn, const QString &labelHeight)
{
- // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
- d_ptr->closeZoomMode();
- // Delete previous data set
- delete d_ptr->m_dataSet;
- d_ptr->m_dataSet = new QDataSet();
- d_ptr->m_sampleCount = qMakePair(samplesRow, samplesColumn);
- d_ptr->m_dataSet->setLabels(labelRow, labelColumn, labelHeight);
- // TODO: Invent "idiotproof" max scene size formula..
- // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high)
- d_ptr->m_maxSceneSize = 2 * qSqrt(samplesRow * samplesColumn);
- //qDebug() << "maxSceneSize" << d_ptr->m_maxSceneSize;
- // Calculate here and at setting bar specs
- d_ptr->calculateSceneScalingFactors();
- d_ptr->m_axisLabelX = labelRow;
- d_ptr->m_axisLabelZ = labelColumn;
- d_ptr->m_axisLabelY = labelHeight;
+ d_ptr->m_shared->setupSampleSpace(samplesRow, samplesColumn, labelRow, labelColumn,
+ labelHeight);
}
+/*!
+ * \a preset Move camera to a predefined position from \c CameraPreset.
+ *
+ * Moves camera to a predefined position.
+ */
void Q3DBars::setCameraPreset(CameraPreset preset)
{
- CameraHelper::setCameraPreset(preset);
-}
-
+ d_ptr->m_shared->setCameraPreset(preset);
+}
+
+/*!
+ * \a horizontal Horizontal angle for camera.
+ *
+ * \a vertical Vertical angle for camera.
+ *
+ * \a distance Distance from the center. \c 100 by default.
+ *
+ * Move camera to a wanted position based on horizontal and veritcal angles. Angles are limited
+ * to -180...180 in horizontal direction and either -90...90 or 0...90 in vertical, depending
+ * on data values. Negative vertical angles are allowed only if there are negative bar values.
+ * Distance is adjustable between 10 and 500.
+ */
void Q3DBars::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance)
{
- d_ptr->m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f);
- d_ptr->m_verticalRotation = qBound(0.0f, vertical, 90.0f);
- d_ptr->m_zoomLevel = qBound(10, distance, 500);
- CameraHelper::setCameraRotation(QPointF(d_ptr->m_horizontalRotation,
- d_ptr->m_verticalRotation));
- //qDebug() << "camera rotation set to" << d_ptr->m_horizontalRotation << d_ptr->m_verticalRotation;
+ d_ptr->m_shared->setCameraPosition(horizontal, vertical, distance);
}
+/*!
+ * \a theme Apply a predefined theme from \c ColorTheme.
+ *
+ * Sets a predefined theme. Theme affects bar colors, label colors, text color, background color,
+ * window color and grid color. Lighting is also adjusted by themes.
+ */
void Q3DBars::setTheme(ColorTheme theme)
{
- d_ptr->m_theme->useTheme(theme);
- d_ptr->m_drawer->setTheme(*d_ptr->m_theme);
- // Re-initialize shaders
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- }
- } else {
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
- }
-#else
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentColorOnYES2"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
- }
-#endif
-}
-
+ d_ptr->m_shared->setTheme(theme);
+}
+
+/*!
+ * \a baseColor The base color of a bar. If all other colors are black, this sets the final color of
+ * the bar.
+ *
+ * \a heightColor This color is added to the bar based on its height. The higher the bar, the more
+ * prominent this color becomes. Setting this black keeps the color unchanged regardless of height.
+ *
+ * \a depthColor This color becomes more prominent the further away from the first row the bar is.
+ * Setting this black keeps bars the same color regardless of "depth" in the set.
+ *
+ * \a uniform A flag to define if color needs to be uniform throughout bar's length, or will the
+ * colors be applied by height. \c true by default.
+ *
+ * Set bar color using your own colors. This overrides colors from theme.
+ */
void Q3DBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform)
{
- d_ptr->m_theme->m_baseColor = baseColor;
- d_ptr->m_theme->m_heightColor = heightColor;
- d_ptr->m_theme->m_depthColor = depthColor;
- //qDebug() << "colors:" << d_ptr->m_baseColor << d_ptr->m_heightColor << d_ptr->m_depthColor;
- if (d_ptr->m_theme->m_uniformColor != uniform) {
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- }
- } else {
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
- }
-#else
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentColorOnYES2"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
- }
-#endif
- }
- d_ptr->m_theme->m_uniformColor = uniform;
+ d_ptr->m_shared->setBarColor(baseColor, heightColor, depthColor, uniform);
}
+/*!
+ * \a mode Set bar selection mode from \c SelectionMode. \c ModeBar by default.
+ *
+ * Sets bar selection mode to be used.
+ */
void Q3DBars::setSelectionMode(SelectionMode mode)
{
- d_ptr->m_selectionMode = mode;
- // Disable zoom if selection mode changes
- d_ptr->closeZoomMode();
- // Create zoom selection if there isn't one
- if (mode >= ModeZoomRow && !d_ptr->m_zoomSelection)
- d_ptr->m_zoomSelection = new QDataRow();
+ d_ptr->m_shared->setSelectionMode(mode);
}
+/*!
+ * \return \c SelectionMode.
+ */
SelectionMode Q3DBars::selectionMode()
{
- return d_ptr->m_selectionMode;
+ return d_ptr->m_shared->selectionMode();
}
+/*!
+ * \property Q3DBars::windowTitle
+ *
+ * \a title QString label to be used as window title.
+ *
+ * Sets the window title. The default is application executable name.
+ */
void Q3DBars::setWindowTitle(const QString &title)
{
setTitle(title);
@@ -1831,562 +487,239 @@ QString Q3DBars::windowTitle()
return title();
}
+/*!
+ * \a objFileName File name of a mesh object. Object needs to be in Wavefront obj format
+ * and include vertices, normals and UVs. It also needs to be in triangles.
+ *
+ * Override bar type with an object mesh. \sa setBarType()
+ */
+void Q3DBars::setMeshFileName(const QString &objFileName)
+{
+ d_ptr->m_shared->setMeshFileName(objFileName);
+}
+
+/*!
+ * \property Q3DBars::fontSize
+ *
+ * \a fontsize Size of the font.
+ *
+ * Sets font size.
+ */
void Q3DBars::setFontSize(float fontsize)
{
- d_ptr->m_font.setPointSizeF(fontsize);
- d_ptr->m_drawer->setFont(d_ptr->m_font);
+ d_ptr->m_shared->setFontSize(fontsize);
}
float Q3DBars::fontSize()
{
- return d_ptr->m_font.pointSizeF();
+ return d_ptr->m_shared->fontSize();
}
+/*!
+ * \property Q3DBars::font
+ *
+ * \a font QFont to be used for labels. \c Arial by default.
+ *
+ * Sets the font for labels.
+ */
void Q3DBars::setFont(const QFont &font)
{
- d_ptr->m_font = font;
- d_ptr->m_drawer->setFont(font);
+ d_ptr->m_shared->setFont(font);
}
QFont Q3DBars::font()
{
- return d_ptr->m_font;
+ return d_ptr->m_shared->font();
}
+/*!
+ * \a transparency Transparency level of labels from \c LabelTransparency.
+ * \c TransparencyFromTheme by default.
+ *
+ * Sets label transparency.
+ */
void Q3DBars::setLabelTransparency(LabelTransparency transparency)
{
- d_ptr->m_labelTransparency = transparency;
- d_ptr->m_drawer->setTransparency(transparency);
+ d_ptr->m_shared->setLabelTransparency(transparency);
}
+/*!
+ * \return \c LabelTransparency.
+ */
LabelTransparency Q3DBars::labelTransparency()
{
- return d_ptr->m_labelTransparency;
+ return d_ptr->m_shared->labelTransparency();
}
+/*!
+ * \property Q3DBars::grid
+ *
+ * \a enable Flag to enable or disable grid. \c true by default.
+ *
+ * Sets grid drawing on or off.
+ */
void Q3DBars::setGridEnabled(bool enable)
{
- d_ptr->m_gridEnabled = enable;
+ d_ptr->m_shared->setGridEnabled(enable);
}
bool Q3DBars::gridEnabled()
{
- return d_ptr->m_gridEnabled;
+ return d_ptr->m_shared->gridEnabled();
}
+/*!
+ * \property Q3DBars::background
+ *
+ * \a enable Flag to enable or disable background. \c true by default.
+ *
+ * Sets backround rendering on or off.
+ */
void Q3DBars::setBackgroundEnabled(bool enable)
{
- if (d_ptr->m_bgrEnabled != enable) {
- d_ptr->m_bgrEnabled = enable;
- // Load changed bar type
- d_ptr->loadBarMesh();
- }
+ d_ptr->m_shared->setBackgroundEnabled(enable);
}
bool Q3DBars::backgroundEnabled()
{
- return d_ptr->m_bgrEnabled;
+ return d_ptr->m_shared->backgroundEnabled();
}
+/*!
+ * \a quality Shadow quality from \c ShadowQuality. \c ShadowLow by default.
+ */
void Q3DBars::setShadowQuality(ShadowQuality quality)
{
- d_ptr->m_shadowQuality = quality;
- switch (quality) {
- case ShadowLow:
- d_ptr->m_shadowQualityToShader = 33.3f;
- break;
- case ShadowMedium:
- d_ptr->m_shadowQualityToShader = 100.0f;
- break;
- case ShadowHigh:
- d_ptr->m_shadowQualityToShader = 200.0f;
- break;
- default:
- d_ptr->m_shadowQualityToShader = 0.0f;
- break;
- }
- if (d_ptr->m_isInitialized) {
-#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->m_shadowQuality > ShadowNone) {
- // Re-init depth buffer
- d_ptr->initDepthBuffer();
- // Re-init shaders
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- }
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- } else {
- // Re-init shaders
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentColorOnY"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
-#else
- if (!d_ptr->m_theme->m_uniformColor) {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentColorOnYES2"));
- } else {
- d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
- }
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
-#endif
- }
+ d_ptr->m_shared->setShadowQuality(quality);
}
+/*!
+ * \return \c ShadowQuality.
+ */
ShadowQuality Q3DBars::shadowQuality()
{
- return d_ptr->m_shadowQuality;
+ return d_ptr->m_shared->shadowQuality();
}
+/*!
+ * \a tickCount How many ticks will be drawn. \c 5 by default.
+ *
+ * \a step How large a step each tick 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 tick count and step. Note; tickCount * step should be the maximum possible value of data
+ * set.
+ */
void Q3DBars::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum)
{
- d_ptr->m_tickCount = tickCount;
- d_ptr->m_tickStep = step;
- if (tickCount > 0 && step > 0) {
- d_ptr->m_heightNormalizer = tickCount * step;
- d_ptr->calculateHeightAdjustment(QPair<float, float>(minimum, d_ptr->m_heightNormalizer));
- }
+ d_ptr->m_shared->setTickCount(tickCount, step, minimum);
}
+/*!
+ * \a dataRow A vector of floats representing a single row of data. Sample space must be large
+ * enough to hold the row.
+ *
+ * \a labelRow A QString label for the row.
+ *
+ * \a labelsColumn A vector of strings, one for each item in the row.
+ *
+ * Add a row of data. Each new row is added to the front of the sample space, moving previous
+ * rows back (if sample space is more than one row deep).
+ */
void Q3DBars::addDataRow(const QVector<float> &dataRow, const QString &labelRow,
const QVector<QString> &labelsColumn)
{
- // Convert to QDataRow and add to QDataSet
- QDataRow *row = new QDataRow(labelRow);
- for (int i = 0; i < dataRow.size(); i++)
- row->addItem(new QDataItem(dataRow.at(i)));
- row->d_ptr->verifySize(d_ptr->m_sampleCount.first);
- d_ptr->m_dataSet->addRow(row);
- d_ptr->handleLimitChange();
- d_ptr->m_dataSet->setLabels(d_ptr->m_axisLabelX, d_ptr->m_axisLabelZ, d_ptr->m_axisLabelY,
- QVector<QString>(), labelsColumn);
- d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second);
+ d_ptr->m_shared->addDataRow(dataRow, labelRow, labelsColumn);
}
+/*!
+ * \a dataRow A vector of QDataItems representing a single row of data. Sample space must be
+ * large enough to hold the row. Ownership of QDataItems is transferred to Q3DBars.
+ *
+ * \a labelRow A QString label for the row.
+ *
+ * \a labelsColumn A vector of strings, one for each item in the row.
+ *
+ * Add a row of data. Each new row is added to the front of the sample space, moving previous
+ * rows back (if sample space is more than one row deep).
+ */
void Q3DBars::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow,
const QVector<QString> &labelsColumn)
{
- // Convert to QDataRow and add to QDataSet
- QDataRow *row = new QDataRow(labelRow);
- for (int i = 0; i < dataRow.size(); i++)
- row->addItem(dataRow.at(i));
- row->d_ptr->verifySize(d_ptr->m_sampleCount.first);
- d_ptr->m_dataSet->addRow(row);
- d_ptr->handleLimitChange();
- d_ptr->m_dataSet->setLabels(d_ptr->m_axisLabelX, d_ptr->m_axisLabelZ, d_ptr->m_axisLabelY,
- QVector<QString>(), labelsColumn);
- d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second);
+ d_ptr->m_shared->addDataRow(dataRow, labelRow, labelsColumn);
}
+/*!
+ * \a dataRow A QDataRow instance representing a single row of data. Sample space must be
+ * large enough to hold the row. Ownership of QDataRow is transferred to Q3DBars.
+ *
+ * Add a row of data. Each new row is added to the front of the sample space, moving previous
+ * rows back (if sample space is more than one row deep).
+ */
void Q3DBars::addDataRow(QDataRow *dataRow)
{
- QDataRow *row = dataRow;
- // Check that the input data fits into sample space, and resize if it doesn't
- row->d_ptr->verifySize(d_ptr->m_sampleCount.first);
- // With each new row, the previous data row must be moved back
- // ie. we need as many vectors as we have rows in the sample space
- d_ptr->m_dataSet->addRow(row);
- // if the added data pushed us over sample space, remove the oldest data set
- d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second);
- d_ptr->handleLimitChange();
+ d_ptr->m_shared->addDataRow(dataRow);
}
+/*!
+ * \a data A vector of vector of floats representing the whole data set. Sample space must be
+ * large enough to hold the set.
+ *
+ * \a labelsRow A vector of strings, one for each column in the row.
+ *
+ * \a labelsColumn A vector of strings, one for each row in the column.
+ *
+ * Adds a whole data set at once. If an old data set exists, it is deleted and replaced with the
+ * new one.
+ */
void Q3DBars::addDataSet(const QVector< QVector<float> > &data, const QVector<QString> &labelsRow,
const QVector<QString> &labelsColumn)
{
- // Copy axis labels
- QString xAxis;
- QString zAxis;
- QString yAxis;
- d_ptr->m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis);
- // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
- d_ptr->closeZoomMode();
- // Delete old data set
- delete d_ptr->m_dataSet;
- d_ptr->m_dataSet = new QDataSet();
- // Give drawer to data set
- d_ptr->m_dataSet->d_ptr->setDrawer(d_ptr->m_drawer);
- // Convert to QDataRow and add to QDataSet
- QDataRow *row;
- for (int rowNr = 0; rowNr < data.size(); rowNr++) {
- if (labelsRow.size() >= (rowNr + 1))
- row = new QDataRow(labelsRow.at(rowNr));
- else
- row = new QDataRow();
- for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++)
- row->addItem(new QDataItem(data.at(rowNr).at(colNr)));
- row->d_ptr->verifySize(d_ptr->m_sampleCount.first);
- d_ptr->m_dataSet->addRow(row);
- row++;
- }
- d_ptr->handleLimitChange();
- d_ptr->m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn);
- d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second);
+ d_ptr->m_shared->addDataSet(data, labelsRow, labelsColumn);
}
+/*!
+ * \a data A vector of vector of QDataItems representing the whole data set. Sample space must
+ * be large enough to hold the set. Ownership of QDataItems is transferred to Q3DBars.
+ *
+ * \a labelsRow A vector of strings, one for each column in the row.
+ *
+ * \a labelsColumn A vector of strings, one for each row in the column.
+ *
+ * Adds a whole data set at once. If an old data set exists, it is deleted and replaced with the
+ * new one.
+ */
void Q3DBars::addDataSet(const QVector< QVector<QDataItem*> > &data,
const QVector<QString> &labelsRow,
const QVector<QString> &labelsColumn)
{
- // Copy axis labels
- QString xAxis;
- QString zAxis;
- QString yAxis;
- d_ptr->m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis);
- // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
- d_ptr->closeZoomMode();
- // Delete old data set
- delete d_ptr->m_dataSet;
- d_ptr->m_dataSet = new QDataSet();
- // Give drawer to data set
- d_ptr->m_dataSet->d_ptr->setDrawer(d_ptr->m_drawer);
- // Convert to QDataRow and add to QDataSet
- QDataRow *row;
- for (int rowNr = 0; rowNr < data.size(); rowNr++) {
- if (labelsRow.size() >= (rowNr + 1))
- row = new QDataRow(labelsRow.at(rowNr));
- else
- row = new QDataRow();
- for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++)
- row->addItem(data.at(rowNr).at(colNr));
- row->d_ptr->verifySize(d_ptr->m_sampleCount.first);
- d_ptr->m_dataSet->addRow(row);
- row++;
- }
- d_ptr->handleLimitChange();
- d_ptr->m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn);
- d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second);
+ d_ptr->m_shared->addDataSet(data, labelsRow, labelsColumn);
}
-void Q3DBars::addDataSet(QDataSet* dataSet)
+/*!
+ * \a dataSet A QDataSet instance holding the whole data set. Sample space must
+ * be large enough to hold the set. Ownership of QDataSet is transferred to Q3DBars.
+ *
+ * Adds a whole data set at once. If an old data set exists, it is deleted and replaced with the
+ * new one.
+ */
+void Q3DBars::addDataSet(QDataSet *dataSet)
{
- // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
- d_ptr->closeZoomMode();
- // Delete old data set
- delete d_ptr->m_dataSet;
- // Check sizes
- dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second, d_ptr->m_sampleCount.first);
- // Take ownership of given set
- d_ptr->m_dataSet = dataSet;
- d_ptr->handleLimitChange();
- // Give drawer to data set
- d_ptr->m_dataSet->d_ptr->setDrawer(d_ptr->m_drawer);
+ d_ptr->m_shared->addDataSet(dataSet);
}
-Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q)
+Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect, GLuint fbohandle)
: q_ptr(q),
- m_paintDevice(0),
- m_barShader(0),
- m_depthShader(0),
- m_selectionShader(0),
- m_backgroundShader(0),
- m_labelShader(0),
- m_barObj(0),
- m_backgroundObj(0),
- m_gridLineObj(0),
- m_labelObj(0),
- m_sampleCount(0, 0),
- m_objFile(QStringLiteral(":/defaultMeshes/bar")),
- m_mousePressed(MouseNone),
- m_mousePos(QPoint(0, 0)),
- m_zoomLevel(100),
- m_zoomAdjustment(1.0f),
- m_horizontalRotation(-45.0f),
- m_verticalRotation(15.0f),
- m_barThickness(QSizeF(0.75f, 0.75f)),
- m_barSpacing(m_barThickness * 3.0f),
- m_heightNormalizer(0.0f),
- m_yAdjustment(0.0f),
- m_rowWidth(0),
- m_columnDepth(0),
- m_maxDimension(0),
- m_scaleX(0),
- m_scaleZ(0),
- m_scaleFactor(0),
- m_maxSceneSize(40.0),
- m_theme(new Theme()),
- m_isInitialized(false),
- m_selectionMode(ModeBar),
- m_selectedBar(0),
- m_zoomSelection(0),
- m_dataSet(new QDataSet()),
- m_axisLabelX(QStringLiteral("X")),
- m_axisLabelZ(QStringLiteral("Z")),
- m_axisLabelY(QStringLiteral("Y")),
- #ifdef USE_QML2_VERSION
- m_sceneViewPort(0, 0, 800, 500),
- #else
- m_sceneViewPort(0, 0, q->width(), q->height()),
- #endif
- m_zoomViewPort(0, 0, q->width(), q->height()),
- m_zoomActivated(false),
- m_textureHelper(new TextureHelper()),
- m_labelTransparency(TransparencyFromTheme),
- m_font(QFont(QStringLiteral("Arial"))),
- m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)),
- m_xFlipped(false),
- m_zFlipped(false),
- m_yFlipped(false),
- m_bgrTexture(0),
- m_depthTexture(0),
- m_selectionTexture(0),
- m_depthFrameBuffer(0),
- m_selectionFrameBuffer(0),
- m_selectionDepthBuffer(0),
- m_updateLabels(false),
- m_gridEnabled(true),
- m_bgrEnabled(true),
- m_shadowQuality(ShadowLow),
- m_shadowQualityToShader(33.3f),
- m_tickCount(0),
- m_tickStep(0),
- m_negativeValues(false)
+ m_shared(new Bars3dShared(rect, fbohandle))
{
- m_dataSet->d_ptr->setDrawer(m_drawer);
- QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Q3DBarsPrivate::updateTextures);
}
Q3DBarsPrivate::~Q3DBarsPrivate()
{
qDebug() << "Destroying Q3DBarsPrivate";
-#ifndef USE_HAX0R_SELECTION
- m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
- m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
- m_textureHelper->deleteTexture(&m_selectionTexture);
-#endif
- m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
- m_textureHelper->deleteTexture(&m_bgrTexture);
- delete m_dataSet;
- if (m_zoomSelection) {
- m_zoomSelection->d_ptr->clear();
- delete m_zoomSelection;
- }
- delete m_barShader;
- delete m_depthShader;
- delete m_selectionShader;
- delete m_backgroundShader;
- delete m_barObj;
- delete m_backgroundObj;
- delete m_gridLineObj;
- delete m_textureHelper;
- delete m_drawer;
-}
-
-void Q3DBarsPrivate::loadBarMesh()
-{
- QString objectFileName = m_objFile;
- if (m_barObj)
- delete m_barObj;
- // If background is disabled, load full version of bar mesh
- if (!m_bgrEnabled)
- objectFileName.append(QStringLiteral("Full"));
- m_barObj = new ObjectHelper(objectFileName);
- m_barObj->load();
-}
-
-void Q3DBarsPrivate::loadBackgroundMesh()
-{
- if (m_backgroundObj)
- delete m_backgroundObj;
- if (m_negativeValues)
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground"));
- else
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background"));
- m_backgroundObj->load();
-}
-
-void Q3DBarsPrivate::loadGridLineMesh()
-{
- if (m_gridLineObj)
- delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
- m_gridLineObj->load();
-}
-
-void Q3DBarsPrivate::loadLabelMesh()
-{
- if (m_labelObj)
- delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
- m_labelObj->load();
-}
-
-void Q3DBarsPrivate::initShaders(const QString &vertexShader, const QString &fragmentShader)
-{
- if (m_barShader)
- delete m_barShader;
- m_barShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader);
- m_barShader->initialize();
-}
-
-void Q3DBarsPrivate::initSelectionShader()
-{
- if (m_selectionShader)
- delete m_selectionShader;
- m_selectionShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexSelection"),
- QStringLiteral(":/shaders/fragmentSelection"));
- m_selectionShader->initialize();
-}
-
-void Q3DBarsPrivate::initSelectionBuffer()
-{
-#ifndef USE_HAX0R_SELECTION
- if (m_selectionTexture) {
- m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
- m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
- m_textureHelper->deleteTexture(&m_selectionTexture);
- }
- m_selectionTexture = m_textureHelper->createSelectionTexture(q_ptr->size(),
- m_selectionFrameBuffer,
- m_selectionDepthBuffer);
-#endif
-}
-
-#if !defined(QT_OPENGL_ES_2)
-void Q3DBarsPrivate::initDepthShader()
-{
- if (m_depthShader)
- delete m_depthShader;
- m_depthShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexDepth"),
- QStringLiteral(":/shaders/fragmentDepth"));
- m_depthShader->initialize();
-}
-
-void Q3DBarsPrivate::initDepthBuffer()
-{
- if (m_depthTexture) {
- m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
- m_textureHelper->deleteTexture(&m_depthTexture);
- }
- m_depthTexture = m_textureHelper->createDepthTexture(q_ptr->size(), m_depthFrameBuffer,
- m_shadowQuality);
-}
-#endif
-
-void Q3DBarsPrivate::initBackgroundShaders(const QString &vertexShader,
- const QString &fragmentShader)
-{
- if (m_backgroundShader)
- delete m_backgroundShader;
- m_backgroundShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader);
- m_backgroundShader->initialize();
-}
-
-void Q3DBarsPrivate::initLabelShaders(const QString &vertexShader, const QString &fragmentShader)
-{
- if (m_labelShader)
- delete m_labelShader;
- m_labelShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader);
- m_labelShader->initialize();
-}
-
-void Q3DBarsPrivate::updateTextures()
-{
- // Drawer has changed; this flag needs to be checked when checking if we need to update labels
- m_updateLabels = true;
-}
-
-void Q3DBarsPrivate::calculateSceneScalingFactors()
-{
- // Calculate scene scaling and translation factors
- m_rowWidth = ((m_sampleCount.first + 1) * m_barSpacing.width()) / 2.0f;
- m_columnDepth = ((m_sampleCount.second + 1) * m_barSpacing.height()) / 2.0f;
- m_maxDimension = qMax(m_rowWidth, m_columnDepth);
- m_scaleFactor = qMin((m_sampleCount.first * (m_maxDimension / m_maxSceneSize)),
- (m_sampleCount.second * (m_maxDimension / m_maxSceneSize)));
- m_scaleX = m_barThickness.width() / m_scaleFactor;
- m_scaleZ = m_barThickness.height() / m_scaleFactor;
- //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor;
- //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor;
- //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension;
-}
-
-void Q3DBarsPrivate::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits)
-{
- // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer
- m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer);
- //qDebug() << m_yAdjustment;
-}
-
-Q3DBarsPrivate::SelectionType Q3DBarsPrivate::isSelected(GLint row, GLint bar,
- const QVector3D &selection)
-{
- //static QVector3D prevSel = selection; // TODO: For debugging
- SelectionType isSelectedType = SelectionNone;
-#ifdef USE_HAX0R_SELECTION
- if (selection == Utils::vectorFromColor(m_theme->m_windowColor))
-#else
- if (selection == skipColor)
-#endif
- return isSelectedType; // skip window
-
-//#if !defined(QT_OPENGL_ES_2)
-// QVector3D current = QVector3D((GLuint)row, (GLuint)bar, 0);
-//#else
- QVector3D current = QVector3D((GLubyte)row, (GLubyte)bar, 0);
-//#endif
-
- // TODO: For debugging
- //if (selection != prevSel) {
- // qDebug() << "current" << current.x() << current .y() << current.z();
- // qDebug() << "selection" << selection.x() << selection .y() << selection.z();
- // prevSel = selection;
- //}
- if (current == selection)
- isSelectedType = SelectionBar;
- else if (current.y() == selection.y() && (m_selectionMode == ModeBarAndColumn
- || m_selectionMode == ModeBarRowAndColumn
- || m_selectionMode == ModeZoomColumn))
- isSelectedType = SelectionColumn;
- else if (current.x() == selection.x() && (m_selectionMode == ModeBarAndRow
- || m_selectionMode == ModeBarRowAndColumn
- || m_selectionMode == ModeZoomRow))
- isSelectedType = SelectionRow;
- return isSelectedType;
-}
-
-void Q3DBarsPrivate::handleLimitChange()
-{
- // Get the limits
- QPair<GLfloat, GLfloat> limits = m_dataSet->d_ptr->limitValues();
-
- // TODO: What if we have only negative values?
-
- // Check if we have negative values
- if (limits.first < 0 && !m_negativeValues) {
- m_negativeValues = true;
- // Reload background
- loadBackgroundMesh();
- } else if (limits.first >= 0 && m_negativeValues) {
- m_negativeValues = false;
- // Reload background
- loadBackgroundMesh();
- }
-
- // Don't auto-adjust height if tick count is set
- if (m_tickCount == 0) {
- m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first));
- calculateHeightAdjustment(limits);
- }
-}
-
-void Q3DBarsPrivate::closeZoomMode()
-{
- m_zoomActivated = false;
- m_sceneViewPort = QRect(0, 0, q_ptr->width(), q_ptr->height());
+ delete m_shared;
}
QTENTERPRISE_DATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h
index 265df734..03635e4d 100644
--- a/src/datavis3d/engine/q3dbars.h
+++ b/src/datavis3d/engine/q3dbars.h
@@ -48,8 +48,6 @@
#include <QFont>
-class QOpenGLShaderProgram;
-
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
class Q3DBarsPrivate;
@@ -68,15 +66,12 @@ class QTENTERPRISE_DATAVIS3D_EXPORT Q3DBars : public Q3DWindow
Q_PROPERTY(bool background READ backgroundEnabled WRITE setBackgroundEnabled)
public:
- explicit Q3DBars();
+ explicit Q3DBars(GLuint fbohandle = 0, const QSize &windowsize = QSize());
~Q3DBars();
- void initialize();
- void render();
-
// Add a row of data. Each new row is added to the front of the sample space, moving previous
// rows back (if sample space is more than one row deep)
- Q_INVOKABLE void addDataRow(const QVector<GLfloat> &dataRow,
+ Q_INVOKABLE void addDataRow(const QVector<float> &dataRow,
const QString &labelRow = QString(),
const QVector<QString> &labelsColumn = QVector<QString>());
// ownership of dataItems is transferred
@@ -87,7 +82,7 @@ public:
Q_INVOKABLE void addDataRow(QDataRow *dataRow);
// Add complete data set at a time, as a vector of data rows
- Q_INVOKABLE void addDataSet(const QVector< QVector<GLfloat> > &data,
+ Q_INVOKABLE void addDataSet(const QVector< QVector<float> > &data,
const QVector<QString> &labelsRow = QVector<QString>(),
const QVector<QString> &labelsColumn = QVector<QString>());
@@ -108,9 +103,6 @@ public:
// bar type; bars (=cubes), pyramids, cones, cylinders, etc.
Q_INVOKABLE void setBarType(BarStyle style, bool smooth = false);
- // override bar type with own mesh
- Q_INVOKABLE void setMeshFileName(const QString &objFileName);
-
// how many samples per row and column, and names for axes
Q_INVOKABLE void setupSampleSpace(int samplesRow, int samplesColumn,
const QString &labelRow = QString(),
@@ -139,6 +131,8 @@ public:
// important to set if values can be negative.
Q_INVOKABLE void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f);
+ // override bar type with own mesh
+ Q_INVOKABLE void setMeshFileName(const QString &objFileName);
// TODO: light placement API
// Change selection mode; single bar, bar and row, bar and column, or all
@@ -165,6 +159,11 @@ public:
void setGridEnabled(bool enable);
bool gridEnabled();
+ // TODO: Do these need to be public? Where are they called from?
+ // Size
+ void setWidth(const int width);
+ void setHeight(const int height);
+
// Enable or disable background mesh
void setBackgroundEnabled(bool enable);
bool backgroundEnabled();
@@ -174,6 +173,9 @@ public:
ShadowQuality shadowQuality();
protected:
+ void initialize();
+ void render();
+
#if defined(Q_OS_ANDROID)
void mouseDoubleClickEvent(QMouseEvent *event);
void touchEvent(QTouchEvent *event);
diff --git a/src/datavis3d/engine/q3dbars_p.h b/src/datavis3d/engine/q3dbars_p.h
index 33153b60..f5d0cf38 100644
--- a/src/datavis3d/engine/q3dbars_p.h
+++ b/src/datavis3d/engine/q3dbars_p.h
@@ -52,10 +52,8 @@
#ifndef Q3DBARS_p_H
#define Q3DBARS_p_H
-#include "qdatavis3dglobal.h"
+#include "bars3dshared_p.h"
#include "qdatavis3namespace.h"
-#include <QOpenGLFunctions>
-#include <QFont>
class QOpenGLPaintDevice;
@@ -65,122 +63,15 @@ class QSizeF;
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
class Q3DBars;
-class QDataItem;
-class QDataRow;
-class QDataSet;
-class ShaderHelper;
-class ObjectHelper;
-class TextureHelper;
-class Theme;
-class Drawer;
class Q3DBarsPrivate : public QObject
{
public:
- enum SelectionType {
- SelectionNone = 0,
- SelectionBar,
- SelectionRow,
- SelectionColumn
- };
-
- enum MousePressType {
- MouseNone = 0,
- MouseOnScene,
- MouseOnOverview,
- MouseOnZoom,
- MouseRotating,
- MouseOnPinch
- };
-
-public:
- Q3DBarsPrivate(Q3DBars *q);
+ Q3DBarsPrivate(Q3DBars *q, QRect rect, GLuint fbohandle);
~Q3DBarsPrivate();
- void loadBarMesh();
- void loadBackgroundMesh();
- void loadGridLineMesh();
- void loadLabelMesh();
- void initShaders(const QString &vertexShader, const QString &fragmentShader);
- void initSelectionShader();
- void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
- void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
- void initSelectionBuffer();
-#if !defined(QT_OPENGL_ES_2)
- void initDepthShader();
- void initDepthBuffer();
-#endif
- void updateTextures();
- void calculateSceneScalingFactors();
- void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits);
- SelectionType isSelected(GLint row, GLint bar, const QVector3D &selection);
- void handleLimitChange();
- void closeZoomMode();
-
Q3DBars *q_ptr;
-
- QOpenGLPaintDevice *m_paintDevice;
- ShaderHelper *m_barShader;
- ShaderHelper *m_depthShader;
- ShaderHelper *m_selectionShader;
- ShaderHelper *m_backgroundShader;
- ShaderHelper *m_labelShader;
- ObjectHelper *m_barObj;
- ObjectHelper *m_backgroundObj;
- ObjectHelper *m_gridLineObj;
- ObjectHelper *m_labelObj;
- QPair<int, int> m_sampleCount;
- QString m_objFile;
- MousePressType m_mousePressed;
- QPoint m_mousePos;
- GLint m_zoomLevel;
- GLfloat m_zoomAdjustment;
- GLfloat m_horizontalRotation;
- GLfloat m_verticalRotation;
- QSizeF m_barThickness;
- QSizeF m_barSpacing;
- GLfloat m_heightNormalizer;
- GLfloat m_yAdjustment;
- GLfloat m_rowWidth;
- GLfloat m_columnDepth;
- GLfloat m_maxDimension;
- GLfloat m_scaleX;
- GLfloat m_scaleZ;
- GLfloat m_scaleFactor;
- GLfloat m_maxSceneSize;
- Theme *m_theme;
- bool m_isInitialized;
- SelectionMode m_selectionMode;
- QDataItem *m_selectedBar;
- QDataRow *m_zoomSelection;
- QDataSet *m_dataSet;
- QString m_axisLabelX;
- QString m_axisLabelZ;
- QString m_axisLabelY;
- QRect m_sceneViewPort;
- QRect m_zoomViewPort;
- bool m_zoomActivated;
- TextureHelper *m_textureHelper;
- LabelTransparency m_labelTransparency;
- QFont m_font;
- Drawer *m_drawer;
- bool m_xFlipped;
- bool m_zFlipped;
- bool m_yFlipped;
- GLuint m_bgrTexture;
- GLuint m_depthTexture;
- GLuint m_selectionTexture;
- GLuint m_depthFrameBuffer;
- GLuint m_selectionFrameBuffer;
- GLuint m_selectionDepthBuffer;
- bool m_updateLabels;
- bool m_gridEnabled;
- bool m_bgrEnabled;
- ShadowQuality m_shadowQuality;
- GLfloat m_shadowQualityToShader;
- GLint m_tickCount;
- GLfloat m_tickStep;
- bool m_negativeValues;
+ Bars3dShared *m_shared;
};
QTENTERPRISE_DATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp
index ad864042..0a1ca7ff 100644
--- a/src/datavis3d/engine/q3dmaps.cpp
+++ b/src/datavis3d/engine/q3dmaps.cpp
@@ -52,6 +52,7 @@
#include "utils_p.h"
#include "drawer_p.h"
+#include <QOpenGLFunctions>
#include <QMatrix4x4>
#include <QOpenGLPaintDevice>
#include <QPainter>
@@ -84,15 +85,39 @@ const GLfloat gridLineWidth = 0.005f;
GLfloat distanceMod = 0.0f;
static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color
+/*!
+ * \class Q3DMaps
+ * \inmodule QtDataVis3D
+ * \brief The Q3DMaps class provides methods for rendering 3D bars on maps or other planes.
+ * \since 1.0.0
+ *
+ * This class enables developers to render bars or objects on maps or other planes in 3D and to
+ * view them by rotating the scene freely. Methods are provided for changing object types, themes
+ * and so on.
+ *
+ * See methods themselves for more complete description.
+ *
+ * \sa Q3DBars, {Qt Data Visualization 3D C++ Classes}
+ */
+
+/*!
+ * Constructs Q3DMaps.
+ */
Q3DMaps::Q3DMaps()
: d_ptr(new Q3DMapsPrivate(this))
{
}
+/*!
+ * Destructs Q3DMaps.
+ */
Q3DMaps::~Q3DMaps()
{
}
+/*!
+ * \internal
+ */
void Q3DMaps::initialize()
{
// Initialize shaders
@@ -184,12 +209,17 @@ void Q3DMaps::initialize()
// Set initialized -flag
d_ptr->m_isInitialized = true;
+ d_ptr->m_drawer->initializeOpenGL();
+
// Update default light position
#ifndef USE_WIDER_SHADOWS
distanceMod = 1.0f;
#endif
}
+/*!
+ * \internal
+ */
void Q3DMaps::render()
{
if (!d_ptr->m_isInitialized)
@@ -218,6 +248,9 @@ void Q3DMaps::render()
drawScene();
}
+/*!
+ * \internal
+ */
void Q3DMaps::drawScene()
{
// Set clear color
@@ -922,6 +955,9 @@ void Q3DMaps::drawScene()
}
#if defined(Q_OS_ANDROID)
+/*!
+ * \internal
+ */
void Q3DMaps::mouseDoubleClickEvent(QMouseEvent *event)
{
if (!d_ptr->m_zoomActivated) {
@@ -931,6 +967,9 @@ void Q3DMaps::mouseDoubleClickEvent(QMouseEvent *event)
}
}
+/*!
+ * \internal
+ */
void Q3DMaps::touchEvent(QTouchEvent *event)
{
static int prevDistance = 0;
@@ -960,6 +999,9 @@ void Q3DMaps::touchEvent(QTouchEvent *event)
}
#endif
+/*!
+ * \internal
+ */
void Q3DMaps::mousePressEvent(QMouseEvent *event)
{
if (Qt::LeftButton == event->button()) {
@@ -998,6 +1040,9 @@ void Q3DMaps::mousePressEvent(QMouseEvent *event)
CameraHelper::updateMousePos(d_ptr->m_mousePos);
}
+/*!
+ * \internal
+ */
void Q3DMaps::mouseReleaseEvent(QMouseEvent *event)
{
//qDebug() << "mouse button released" << event->button();
@@ -1009,6 +1054,9 @@ void Q3DMaps::mouseReleaseEvent(QMouseEvent *event)
d_ptr->m_mousePressed = Q3DMapsPrivate::MouseNone;
}
+/*!
+ * \internal
+ */
void Q3DMaps::mouseMoveEvent(QMouseEvent *event)
{
if (Q3DMapsPrivate::MouseRotating == d_ptr->m_mousePressed) {
@@ -1032,6 +1080,9 @@ void Q3DMaps::mouseMoveEvent(QMouseEvent *event)
#endif
}
+/*!
+ * \internal
+ */
void Q3DMaps::wheelEvent(QWheelEvent *event)
{
if (d_ptr->m_zoomLevel > 100)
@@ -1046,6 +1097,9 @@ void Q3DMaps::wheelEvent(QWheelEvent *event)
d_ptr->m_zoomLevel = 10;
}
+/*!
+ * \internal
+ */
void Q3DMaps::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
@@ -1580,6 +1634,7 @@ void Q3DMapsPrivate::initSelectionShader()
void Q3DMapsPrivate::initSelectionBuffer()
{
if (m_selectionTexture) {
+
m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
m_textureHelper->deleteTexture(&m_selectionTexture);
diff --git a/src/datavis3d/engine/q3dmaps.h b/src/datavis3d/engine/q3dmaps.h
index d9880d3a..67c8860b 100644
--- a/src/datavis3d/engine/q3dmaps.h
+++ b/src/datavis3d/engine/q3dmaps.h
@@ -80,10 +80,6 @@ public:
explicit Q3DMaps();
~Q3DMaps();
- void initialize();
- void render();
- void render(QPainter *painter);
-
// Add data item. New data item is appended to old data.
// ownership of data is transferred
Q_INVOKABLE bool addDataItem(QDataItem *dataItem);
@@ -159,6 +155,9 @@ public:
ShadowQuality shadowQuality();
protected:
+ void initialize();
+ void render();
+
#if defined(Q_OS_ANDROID)
void mouseDoubleClickEvent(QMouseEvent *event);
void touchEvent(QTouchEvent *event);
diff --git a/src/datavis3d/engine/q3dwindow.cpp b/src/datavis3d/engine/q3dwindow.cpp
index 869dc328..af975cb1 100644
--- a/src/datavis3d/engine/q3dwindow.cpp
+++ b/src/datavis3d/engine/q3dwindow.cpp
@@ -52,6 +52,24 @@
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
+/*!
+ * \class Q3DWindow
+ * \inmodule QtDataVis3D
+ * \brief The Q3DWindow class provides a window and render loop.
+ * \since 1.0.0
+ *
+ * This class creates a QWindow and provides render loop for visualization types inheriting it.
+ * \warning This class is not intended to be used directly by developers.
+ *
+ * \sa Q3DBars, Q3DMaps, {Qt Data Visualization 3D C++ Classes}
+ */
+
+/*!
+ * \a parent A QWindow parent.
+ *
+ * Constructs Q3DWindow. It creates a QWindow and an OpenGL context. It also sets surface
+ * format and initializes OpenGL functions for use.
+ */
Q3DWindow::Q3DWindow(QWindow *parent)
: QWindow(parent),
d_ptr(new Q3DWindowPrivate(this))
@@ -70,26 +88,29 @@ Q3DWindow::Q3DWindow(QWindow *parent)
create();
-#ifndef USE_QML2_VERSION
d_ptr->m_context->setFormat(requestedFormat());
d_ptr->m_context->create();
d_ptr->m_context->makeCurrent(this);
-#endif
+ qDebug() << "initializeOpenGLFunctions()";
initializeOpenGLFunctions();
-#ifndef USE_QML2_VERSION
initialize();
-#endif
}
+/*!
+ * Destroys Q3DWindow.
+ */
Q3DWindow::~Q3DWindow()
{
}
+/*!
+ * \internal
+ */
void Q3DWindow::initialize()
{
- const GLubyte* version = glGetString(GL_VERSION);
+ const GLubyte *version = glGetString(GL_VERSION);
qDebug() << "OpenGL version:" << (const char *)version;
version = glGetString(GL_SHADING_LANGUAGE_VERSION);
qDebug() << "GLSL version:" << (const char *)version;
@@ -102,10 +123,16 @@ void Q3DWindow::initialize()
setAnimating(true);
}
+/*!
+ * \internal
+ */
void Q3DWindow::render()
{
}
+/*!
+ * \internal
+ */
void Q3DWindow::renderLater()
{
if (!d_ptr->m_updatePending) {
@@ -114,6 +141,9 @@ void Q3DWindow::renderLater()
}
}
+/*!
+ * \internal
+ */
bool Q3DWindow::event(QEvent *event)
{
switch (event->type()) {
@@ -125,6 +155,9 @@ bool Q3DWindow::event(QEvent *event)
}
}
+/*!
+ * \internal
+ */
void Q3DWindow::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);
@@ -133,6 +166,9 @@ void Q3DWindow::exposeEvent(QExposeEvent *event)
renderNow();
}
+/*!
+ * \internal
+ */
void Q3DWindow::renderNow()
{
if (!isExposed())
@@ -157,6 +193,9 @@ void Q3DWindow::renderNow()
renderLater();
}
+/*!
+ * \internal
+ */
void Q3DWindow::setAnimating(bool animating)
{
d_ptr->m_animating = animating;
diff --git a/src/datavis3d/engine/q3dwindow.h b/src/datavis3d/engine/q3dwindow.h
index edabcf76..bf7d8f74 100644
--- a/src/datavis3d/engine/q3dwindow.h
+++ b/src/datavis3d/engine/q3dwindow.h
@@ -56,21 +56,20 @@ class Q3DWindowPrivate;
class QTENTERPRISE_DATAVIS3D_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
+
public:
explicit Q3DWindow(QWindow *parent = 0);
~Q3DWindow();
- virtual void render();
-
- virtual void initialize();
-
- void setAnimating(bool animating);
-
-public slots:
+private slots:
void renderLater();
void renderNow();
protected:
+ virtual void render();
+ virtual void initialize();
+
+ void setAnimating(bool animating);
bool event(QEvent *event);
void exposeEvent(QExposeEvent *event);
diff --git a/src/datavis3d/engine/qdataitem.cpp b/src/datavis3d/engine/qdataitem.cpp
index 8134fcb5..883c190c 100644
--- a/src/datavis3d/engine/qdataitem.cpp
+++ b/src/datavis3d/engine/qdataitem.cpp
@@ -47,15 +47,46 @@
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
+/*!
+ * \class QDataItem
+ * \inmodule QtDataVis3D
+ * \brief The QDataItem class provides a container for data to be added to graphs.
+ * \since 1.0.0
+ *
+ * A QDataItem holds data for a single bar in a Q3DMaps or Q3DBars graph.
+ *
+ * \sa QDataRow, QDataSet, {Qt Data Visualization 3D C++ Classes}
+ */
+
+/*!
+ * \a value A float value of the data item.
+ *
+ * \a label A QString label for the item.
+ *
+ * Constructs QDataItem.
+ */
QDataItem::QDataItem(float value, const QString &label)
: d_ptr(new QDataItemPrivate(this, value, label))
{
}
+/*!
+ * Destroys QDataItem.
+ */
QDataItem::~QDataItem()
{
}
+/*!
+ * \property QDataItem::label
+ *
+ * \a label A QString label for the data item. Unit, for example.
+ *
+ * \a prepend A flag to indicate if the label is to be prepended or appended to the value.
+ * \c false by default.
+ *
+ * Sets label for the data item.
+ */
void QDataItem::setLabel(const QString &label, bool prepend)
{
d_ptr->m_labelString = label;
@@ -67,11 +98,25 @@ QString QDataItem::label()
return d_ptr->m_labelString;
}
+/*!
+ * \property QDataItem::value
+ *
+ * \a value A float value for the data item.
+ *
+ * Sets value for the data item.
+ */
void QDataItem::setValue(float value)
{
d_ptr->m_value = value;
}
+/*!
+ * \overload QDataItem::value
+ *
+ * \a value An int value for the data item.
+ *
+ * Sets value for the data item.
+ */
void QDataItem::setValue(int value)
{
d_ptr->m_value = (float)value;
@@ -82,11 +127,25 @@ float QDataItem::value()
return d_ptr->m_value;
}
+/*!
+ * \property QDataItem::position
+ *
+ * \a position A QPointF position for the data item.
+ *
+ * Sets position for the data item. Has no effect in Q3DBars.
+ */
void QDataItem::setPosition(const QPointF &position)
{
d_ptr->m_position = position;
}
+/*!
+ * \overload QDataItem::position
+ *
+ * \a position A QPoint position for the data item.
+ *
+ * Sets position for the data item. Has no effect in Q3DBars.
+ */
void QDataItem::setPosition(const QPoint &position)
{
d_ptr->m_position = (QPointF)position;
diff --git a/src/datavis3d/engine/qdataitem.h b/src/datavis3d/engine/qdataitem.h
index 0106502f..7c8302f4 100644
--- a/src/datavis3d/engine/qdataitem.h
+++ b/src/datavis3d/engine/qdataitem.h
@@ -60,13 +60,13 @@ class QTENTERPRISE_DATAVIS3D_EXPORT QDataItem : public QObject
Q_PROPERTY(QString label READ label WRITE setLabel)
Q_PROPERTY(float value READ value WRITE setValue)
Q_PROPERTY(int value READ value WRITE setValue)
- Q_PROPERTY(int value READ value WRITE setValue)
Q_PROPERTY(QPointF position READ position WRITE setPosition)
public:
explicit QDataItem(float value = 0.0f, const QString &label = QString());
~QDataItem();
+ // TODO: Provide a Q_INVOKABLE version of this, or move prepend to it's own property.
void setLabel(const QString &label, bool prepend = false); // label for value, unit for example
QString label();
void setValue(float value);
@@ -79,8 +79,7 @@ public:
private:
QScopedPointer<QDataItemPrivate> d_ptr;
- friend class Q3DBars;
- friend class Q3DBarsPrivate;
+ friend class Bars3dShared;
friend class Q3DMaps;
friend class Q3DMapsPrivate;
friend class QDataRowPrivate;
diff --git a/src/datavis3d/engine/qdatarow.cpp b/src/datavis3d/engine/qdatarow.cpp
index 79bc48e1..6bdd6d14 100644
--- a/src/datavis3d/engine/qdatarow.cpp
+++ b/src/datavis3d/engine/qdatarow.cpp
@@ -48,15 +48,44 @@
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
+/*!
+ * \class QDataRow
+ * \inmodule QtDataVis3D
+ * \brief The QDataRow class provides a container for data items to be added to graphs.
+ * \since 1.0.0
+ *
+ * A QDataRow is a container for all data to be added to a Q3DMaps instance, or a single row to
+ * be added to a QDataSet. It holds instances of QDataItem and has no knowledge of possible
+ * sample space sizes set for a Q3DBars instance. The ownership of QDataItem added is transferred
+ * to QDataRow.
+ *
+ * \sa QDataItem, QDataSet, {Qt Data Visualization 3D C++ Classes}
+ */
+
+/*!
+ * \a label A QString label for the row.
+ *
+ * Constructs QDataRow.
+ */
QDataRow::QDataRow(const QString &label)
: d_ptr(new QDataRowPrivate(this, label))
{
}
+/*!
+ * Destroys QDataRow and all instances of QDataItem it may hold.
+ */
QDataRow::~QDataRow()
{
}
+/*!
+ * \property QDataRow::label
+ *
+ * \a label A QString label for the row.
+ *
+ * Sets a label for the row.
+ */
void QDataRow::setLabel(const QString &label)
{
d_ptr->m_label = label;
@@ -67,6 +96,11 @@ QString QDataRow::label()
return d_ptr->m_label;
}
+/*!
+ * \a item A QDataItem instance.
+ *
+ * Adds a QDataItem to the QDataRow. Ownership of QDataItem is transferred to QDataRow.
+ */
void QDataRow::addItem(QDataItem *item)
{
d_ptr->m_row.prepend(item);
diff --git a/src/datavis3d/engine/qdatarow.h b/src/datavis3d/engine/qdatarow.h
index 2cdccfb5..72fa5f55 100644
--- a/src/datavis3d/engine/qdatarow.h
+++ b/src/datavis3d/engine/qdatarow.h
@@ -67,8 +67,7 @@ public:
private:
QScopedPointer<QDataRowPrivate> d_ptr;
- friend class Q3DBars;
- friend class Q3DBarsPrivate;
+ friend class Bars3dShared;
friend class Q3DMaps;
friend class Q3DMapsPrivate;
friend class QDataSetPrivate;
diff --git a/src/datavis3d/engine/qdataset.cpp b/src/datavis3d/engine/qdataset.cpp
index ab892127..6fd59baf 100644
--- a/src/datavis3d/engine/qdataset.cpp
+++ b/src/datavis3d/engine/qdataset.cpp
@@ -53,17 +53,47 @@ QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
const QString empty;
+/*!
+ * \class QDataSet
+ * \inmodule QtDataVis3D
+ * \brief The QDataSet class provides a container for data rows to be added to graphs.
+ * \since 1.0.0
+ *
+ * A QDataSet is a container for data to be added into a Q3DBars instance. It holds instances of
+ * QDataRow and has no knowledge of sample space size set for Q3DBars. The ownership of QDataRow
+ * added is transferred to QDataSet.
+ *
+ * \sa QDataItem, QDataRow, {Qt Data Visualization 3D C++ Classes}
+ */
+
+/*!
+ * Constructs QDataSet.
+ */
QDataSet::QDataSet()
: d_ptr(new QDataSetPrivate(this))
{
- //qDebug("QDataSet");
}
+/*!
+ * Destroys QDataSet, including all QDataRow instances it may hold.
+ */
QDataSet::~QDataSet()
{
- //qDebug("~QDataSet");
}
+/*!
+ * \a xAxis A QString label for x axis.
+ *
+ * \a zAxis A QString label for z axis.
+ *
+ * \a yAxis A QString label for y axis.
+ *
+ * \a labelsRow A QVector of QStrings, one for each row.
+ *
+ * \a labelsColumn A QVector of QStrings, one for each column.
+ *
+ * Sets labels for the QDataSet.
+ */
void QDataSet::setLabels(const QString &xAxis,
const QString &zAxis,
const QString &yAxis,
@@ -106,6 +136,12 @@ void QDataSet::setLabels(const QString &xAxis,
}
}
+/*!
+ * \a row A QDataRow instance.
+ *
+ * Adds a QDataRow instance to QDataSet. Ownership of the QDataRow instance is transferred to
+ * QDataSet.
+ */
void QDataSet::addRow(QDataRow *row)
{
d_ptr->m_set.prepend(row);
diff --git a/src/datavis3d/engine/qdataset.h b/src/datavis3d/engine/qdataset.h
index f0061ad8..e645bc16 100644
--- a/src/datavis3d/engine/qdataset.h
+++ b/src/datavis3d/engine/qdataset.h
@@ -71,8 +71,7 @@ public:
private:
QScopedPointer<QDataSetPrivate> d_ptr;
- friend class Q3DBars;
- friend class Q3DBarsPrivate;
+ friend class Bars3dShared;
friend class Q3DMaps;
friend class Q3DMapsPrivate;
};
diff --git a/src/datavis3d/engine/theme_p.h b/src/datavis3d/engine/theme_p.h
index 9ed97e6b..234d4709 100644
--- a/src/datavis3d/engine/theme_p.h
+++ b/src/datavis3d/engine/theme_p.h
@@ -69,8 +69,7 @@ public:
void useTheme(ColorTheme theme);
private:
- friend class Q3DBars;
- friend class Q3DBarsPrivate;
+ friend class Bars3dShared;
friend class Q3DMaps;
friend class Q3DMapsPrivate;
friend class Drawer;
diff --git a/src/datavis3d/global/qdatavis3dglobal.h b/src/datavis3d/global/qdatavis3dglobal.h
index c57d5101..308e8607 100644
--- a/src/datavis3d/global/qdatavis3dglobal.h
+++ b/src/datavis3d/global/qdatavis3dglobal.h
@@ -18,8 +18,8 @@
**
****************************************************************************/
-#ifndef QVIS3DGLOBAL_H
-#define QVIS3DGLOBAL_H
+#ifndef QDATAVIS3DGLOBAL_H
+#define QDATAVIS3DGLOBAL_H
#include <qglobal.h>
diff --git a/src/datavis3d/utils/objecthelper.cpp b/src/datavis3d/utils/objecthelper.cpp
index eaae52be..d280abf8 100644
--- a/src/datavis3d/utils/objecthelper.cpp
+++ b/src/datavis3d/utils/objecthelper.cpp
@@ -56,7 +56,6 @@ ObjectHelper::ObjectHelper(const QString &objectFile)
m_indexCount(0),
m_meshDataLoaded(false)
{
- initializeOpenGLFunctions();
}
ObjectHelper::~ObjectHelper()
@@ -74,6 +73,7 @@ void ObjectHelper::setObjectFile(const QString &objectFile)
void ObjectHelper::load()
{
+ initializeOpenGLFunctions();
if (m_meshDataLoaded) {
// Delete old data
glDeleteBuffers(1, &m_vertexbuffer);
diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavis3d/utils/texturehelper.cpp
index cb08b17c..3d827c50 100644
--- a/src/datavis3d/utils/texturehelper.cpp
+++ b/src/datavis3d/utils/texturehelper.cpp
@@ -235,7 +235,6 @@ GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- // Use the following line if using shader's version 2 of shadowing, comment out if not
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size.width() * textureSize,
size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
diff --git a/src/datavis3dqml2/datavis3dqml2.pro b/src/datavis3dqml2/datavis3dqml2.pro
index 2f0c6300..59abef57 100644
--- a/src/datavis3dqml2/datavis3dqml2.pro
+++ b/src/datavis3dqml2/datavis3dqml2.pro
@@ -13,20 +13,17 @@ INCLUDEPATH += ../datavis3d/engine
SOURCES += \
datavis3dqml2_plugin.cpp \
- datavisview.cpp \
- scenerenderernode.cpp \
declarativebars.cpp \
- declarativemaps.cpp #\
+ declarativemaps.cpp #\
#declarativedataitem.cpp \
#declarativedatarow.cpp \
#declarativedataset.cpp
HEADERS += \
datavis3dqml2_plugin.h \
- datavisview.h \
- scenerenderernode_p.h \
declarativebars.h \
- declarativemaps.h #\
+ declarativemaps.h \ #\
+ declarativebars_p.h
#declarativedataitem.h \
#declarativedatarow.h \
#declarativedataset.h
diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.cpp b/src/datavis3dqml2/datavis3dqml2_plugin.cpp
index 9ff0c6c1..86923cde 100644
--- a/src/datavis3dqml2/datavis3dqml2_plugin.cpp
+++ b/src/datavis3dqml2/datavis3dqml2_plugin.cpp
@@ -40,21 +40,21 @@
****************************************************************************/
#include "datavis3dqml2_plugin.h"
-#include "datavisview.h"
#include <qqml.h>
-
+#include <QDebug>
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
void Datavis3dqml2Plugin::registerTypes(const char *uri)
{
+ qDebug() << "Datavis3dqml2Plugin::registerTypes()";
+
// @uri com.digia.QtDataVis3D
- qmlRegisterType<DataVisView>(uri, 1, 0, "DataVisView");
- qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars");
- qmlRegisterType<DeclarativeMaps>(uri, 1, 0, "Maps");
qmlRegisterType<QDataItem>(uri, 1, 0, "DataItem");
qmlRegisterType<QDataRow>(uri, 1, 0, "DataRow");
qmlRegisterType<QDataSet>(uri, 1, 0, "DataSet");
+
+ qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars3D");
}
//#include "moc_datavis3dqml2_plugin.cpp"
diff --git a/src/datavis3dqml2/declarativebars.cpp b/src/datavis3dqml2/declarativebars.cpp
index aac8b1d9..3194baa5 100644
--- a/src/datavis3dqml2/declarativebars.cpp
+++ b/src/datavis3dqml2/declarativebars.cpp
@@ -40,47 +40,341 @@
****************************************************************************/
#include "declarativebars.h"
+#include "bars3dshared_p.h"
+#include <QtQuick/QQuickWindow>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QOpenGLContext>
+#include <QGuiApplication>
+#include <QThread>
#include <QDebug>
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-DeclarativeBars::DeclarativeBars()
+DeclarativeBars::DeclarativeBars(QQuickItem *parent): QQuickItem(parent), m_cachedState(new DeclarativeBarsCachedStatePrivate()), m_shared(0)
{
+ setFlags(QQuickItem::ItemHasContents);
+
+ setRotation(180.0);
+ setAntialiasing(true);
+ setSmooth(true);
}
DeclarativeBars::~DeclarativeBars()
{
+ delete m_shared;
+}
+
+QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ qDebug() << "Enter DeclarativeBars::updatePaintNode";
+ // Delete old node and recreate it. This function gets called when window geometry changes.
+ if (oldNode)
+ delete oldNode;
+
+ if (!m_shared)
+ m_shared = new Bars3dShared(boundingRect().toRect());
+
+ // Lazy initialization of shared object on the SGRenderThread
+ m_shared->initializeOpenGL();
+
+ // We need to create a node class that does the rendering (ie. a node that "captures" the rendering we do)
+ qDebug() << "DeclarativeBars::updatePaintNode Creating new node";
+
+ // Create the new render node
+ DeclarativeBarsRenderer *node = new DeclarativeBarsRenderer(window(), m_shared);
+ node->setRect(boundingRect());
+ m_shared->setBoundingRect(boundingRect().toRect());
+
+ if (m_cachedState->m_isSampleSpaceSet) {
+ m_shared->setupSampleSpace(m_cachedState->m_samplesRow, m_cachedState->m_samplesColumn, m_cachedState->m_labelRow, m_cachedState->m_labelColumn, m_cachedState->m_labelHeight);
+ m_cachedState->m_isSampleSpaceSet = false;
+ }
+
+ if (m_cachedState->m_dataRow) {
+ m_shared->addDataRow(m_cachedState->m_dataRow);
+ m_cachedState->m_dataRow = 0;
+ }
+
+ if (m_cachedState->m_isSelectionModeSet) {
+ m_shared->setSelectionMode(m_cachedState->m_selectionMode);
+ m_cachedState->m_isSelectionModeSet = false;
+ }
+
+ if (m_cachedState->m_isLabelTransparencySet) {
+ m_shared->setLabelTransparency(m_cachedState->m_labelTransparency);
+ m_cachedState->m_isLabelTransparencySet = false;
+ }
+
+ if (m_cachedState->m_isShadowQualitySet) {
+ m_shared->setShadowQuality(m_cachedState->m_shadowQuality);
+ m_cachedState->m_isShadowQualitySet = false;
+ }
+
+ if (m_cachedState->m_isGridSet) {
+ m_shared->setGridEnabled(m_cachedState->m_isGridEnabled);
+ m_cachedState->m_isGridSet = false;
+ }
+
+ qDebug() << "Exit DeclarativeBars::updatePaintNode";
+ return node;
+}
+
+void DeclarativeBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative)
+{
+ m_shared->setBarSpecs(thickness, spacing, relative);
+}
+
+void DeclarativeBars::setBarType(BarStyle style, bool smooth)
+{
+ m_shared->setBarType(style, smooth);
+}
+
+void DeclarativeBars::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow,
+ const QString &labelColumn, const QString &labelHeight)
+{
+ m_cachedState->m_samplesRow = samplesRow;
+ m_cachedState->m_samplesColumn = samplesColumn;
+ m_cachedState->m_labelRow = labelRow;
+ m_cachedState->m_labelColumn = labelColumn;
+ m_cachedState->m_labelHeight = labelHeight;
+ m_cachedState->m_isSampleSpaceSet = true;
+}
+
+
+void DeclarativeBars::setCameraPreset(CameraPreset preset)
+{
+ m_shared->setCameraPreset(preset);
+}
+
+void DeclarativeBars::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance)
+{
+ m_shared->setCameraPosition(horizontal, vertical, distance);
+}
+
+void DeclarativeBars::setTheme(ColorTheme theme)
+{
+ m_shared->setTheme(theme);
+}
+
+void DeclarativeBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform)
+{
+ m_shared->setBarColor(baseColor, heightColor, depthColor, uniform);
+}
+
+
+void DeclarativeBars::setFontSize(float fontsize)
+{
+ m_shared->setFontSize(fontsize);
+}
+
+float DeclarativeBars::fontSize()
+{
+ return m_shared->fontSize();
+}
+
+void DeclarativeBars::setFont(const QFont &font)
+{
+ m_shared->setFont(font);
+}
+
+QFont DeclarativeBars::font()
+{
+ return m_shared->font();
+}
+
+void DeclarativeBars::setLabelTransparency(DeclarativeBars::LabelTransparency transparency)
+{
+ m_cachedState->m_labelTransparency = QtDataVis3D::LabelTransparency(transparency);
+ m_cachedState->m_isLabelTransparencySet = true;
+}
+
+DeclarativeBars::LabelTransparency DeclarativeBars::labelTransparency()
+{
+ return DeclarativeBars::LabelTransparency(m_shared->labelTransparency());
+}
+
+void DeclarativeBars::setGridEnabled(bool enable)
+{
+ m_cachedState->m_isGridEnabled = enable;
+ m_cachedState->m_isGridSet = true;
}
-void DeclarativeBars::setSelMode(DeclarativeBars::SelectionMode mode)
+bool DeclarativeBars::gridEnabled()
{
- setSelectionMode(QtDataVis3D::SelectionMode(mode));
+ return m_shared->gridEnabled();
}
-DeclarativeBars::SelectionMode DeclarativeBars::selMode()
+void DeclarativeBars::setBackgroundEnabled(bool enable)
{
- return DeclarativeBars::SelectionMode(selectionMode());
+ m_shared->setBackgroundEnabled(enable);
}
-void DeclarativeBars::setTransparency(DeclarativeBars::LabelTransparency transparency)
+bool DeclarativeBars::backgroundEnabled()
{
- setLabelTransparency(QtDataVis3D::LabelTransparency(transparency));
+ return m_shared->backgroundEnabled();
}
-DeclarativeBars::LabelTransparency DeclarativeBars::transparency()
+void DeclarativeBars::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum)
{
- return DeclarativeBars::LabelTransparency(labelTransparency());
+ m_shared->setTickCount(tickCount, step, minimum);
+}
+
+void DeclarativeBars::addDataRow(const QVector<float> &dataRow, const QString &labelRow,
+ const QVector<QString> &labelsColumn)
+{
+ qDebug() << "Enter DeclarativeBars::addDataRow(const QVector<float> &dataRow...)";
+ m_shared->addDataRow(dataRow, labelRow, labelsColumn);
+}
+
+void DeclarativeBars::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow,
+ const QVector<QString> &labelsColumn)
+{
+ qDebug() << "Enter DeclarativeBars::addDataRow(const QVector<QDataItem*> &dataRow...)";
+ m_shared->addDataRow(dataRow, labelRow, labelsColumn);
+}
+
+void DeclarativeBars::addDataRow(QDataRow *dataRow)
+{
+ qDebug() << "Enter DeclarativeBars::addDataRow(QDataRow *dataRow)";
+ m_cachedState->m_dataRow = dataRow;
+}
+
+void DeclarativeBars::addDataSet(const QVector< QVector<float> > &data, const QVector<QString> &labelsRow,
+ const QVector<QString> &labelsColumn)
+{
+ m_shared->addDataSet(data, labelsRow,labelsColumn);
+}
+
+void DeclarativeBars::addDataSet(const QVector< QVector<QDataItem*> > &data,
+ const QVector<QString> &labelsRow,
+ const QVector<QString> &labelsColumn)
+{
+ m_shared->addDataSet(data, labelsRow, labelsColumn);
+}
+
+void DeclarativeBars::addDataSet(QDataSet* dataSet)
+{
+ m_shared->addDataSet(dataSet);
+}
+
+void DeclarativeBars::setSelectionMode(DeclarativeBars::SelectionMode mode)
+{
+ m_cachedState->m_selectionMode = QtDataVis3D::SelectionMode(mode);
+ m_cachedState->m_isSelectionModeSet = true;
+}
+
+DeclarativeBars::SelectionMode DeclarativeBars::selectionMode()
+{
+ return DeclarativeBars::SelectionMode(m_shared->selectionMode());
}
void DeclarativeBars::setShadow(DeclarativeBars::ShadowQuality quality)
{
- setShadowQuality(QtDataVis3D::ShadowQuality(quality));
+ m_cachedState->m_shadowQuality = QtDataVis3D::ShadowQuality(quality);
+ m_cachedState->m_isShadowQualitySet = true;
}
DeclarativeBars::ShadowQuality DeclarativeBars::shadow()
{
- return DeclarativeBars::ShadowQuality(shadowQuality());
+ return DeclarativeBars::ShadowQuality(m_shared->shadowQuality());
+}
+
+void DeclarativeBars::setMeshFileName(const QString &objFileName)
+{
+ m_shared->setMeshFileName(objFileName);
+}
+
+
+
+
+DeclarativeBarsRenderer::DeclarativeBarsRenderer(QQuickWindow *window, Bars3dShared *renderer)
+ : m_fbo(0),
+ m_texture(0),
+ m_window(window),
+ m_barsRenderer(renderer)
+{
+ qDebug() << "DeclarativeBarsRenderer::DeclarativeBarsRenderer()";
+ connect(m_window, SIGNAL(beforeRendering()), this, SLOT(render()), Qt::DirectConnection);
+ qDebug() << "QQuickWindow::openglContext()->thread()" << m_window->openglContext()->thread();
+ qDebug() << "QGuiApplication::instance()->thread()" << QGuiApplication::instance()->thread();
}
+DeclarativeBarsRenderer::~DeclarativeBarsRenderer()
+{
+ delete m_texture;
+ delete m_fbo;
+}
+
+void DeclarativeBarsRenderer::render()
+{
+ static bool firstRender = true;
+ if (firstRender) qDebug() << "DeclarativeBarsRenderer::render() running on thread "<< QThread::currentThread();
+ firstRender = false;
+
+ QSize size = rect().size().toSize();
+
+ if (!m_fbo) {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ m_fbo = new QOpenGLFramebufferObject(size, format);
+ m_texture = m_window->createTextureFromId(m_fbo->texture(), size);
+
+ // TODO: If we create the vis3d this way, how do we connect it with QML?
+ // Should we create it at QML and give it to DataVisView using a property (setVisualizer or similar)?
+ // DataVisView can then give it here as an argument in constructor?
+
+ // TODO: For testing. Add some data to scene.
+ QVector< QVector<float> > data;
+ QVector<float> row;
+ for (float j = 0.0f; j < 5.0f; j++) {
+ for (float i = 0.0f; i < 5.0f; i++)
+ row.append(j / 10.0f + i / 10.0f);
+ data.append(row);
+ row.clear();
+ }
+
+ setTexture(m_texture);
+ }
+
+ m_fbo->bind();
+
+ // SGRendering State resets between calls...
+ glDepthMask(true);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+ // Emulate mouse movement
+ // TODO: Remove this and implement properly
+ static int rot = 0;
+ rot += 5;
+ if (rot > 2870) rot = 0;
+ m_barsRenderer->m_mousePos.setX(rot);
+ m_barsRenderer->m_mousePos.setY(100);
+
+ // Call the shared rendering function
+ m_barsRenderer->render();
+
+ m_fbo->bindDefault();
+
+ m_window->update();
+}
+
+
+DeclarativeBarsCachedStatePrivate::DeclarativeBarsCachedStatePrivate() :
+ m_isSampleSpaceSet(false),
+ m_labelRow(QStringLiteral("")),
+ m_labelColumn(QStringLiteral("")),
+ m_labelHeight(QStringLiteral("")),
+ m_dataRow(0)
+{
+}
+
+DeclarativeBarsCachedStatePrivate::~DeclarativeBarsCachedStatePrivate()
+{
+}
+
+
QTENTERPRISE_DATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3dqml2/declarativebars.h b/src/datavis3dqml2/declarativebars.h
index 99c95e5c..8194cd7d 100644
--- a/src/datavis3dqml2/declarativebars.h
+++ b/src/datavis3dqml2/declarativebars.h
@@ -42,22 +42,38 @@
#ifndef DECLARATIVEBARS_H
#define DECLARATIVEBARS_H
-#include "QtDataVis3D/qdatavis3dglobal.h"
-#include "QtDataVis3D/qdatavis3namespace.h"
-#include "q3dbars.h"
+#include "bars3dshared_p.h"
+#include "qdatavis3dglobal.h"
+#include "qdatavis3namespace.h"
+#include "declarativebars_p.h"
+
+#include <qsgsimpletexturenode.h>
+#include <QQuickItem>
+#include <QObject>
+
+class QOpenGLFramebufferObject;
+class QSGTexture;
+class QQuickWindow;
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-class DeclarativeBars : public Q3DBars
+class DeclarativeBars : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(SelectionMode selectionMode READ selMode WRITE setSelMode)
- Q_PROPERTY(LabelTransparency labelTransparency READ transparency WRITE setTransparency)
+ Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
+ Q_PROPERTY(LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency)
Q_PROPERTY(ShadowQuality shadowQuality READ shadow WRITE setShadow)
+ Q_PROPERTY(bool grid READ gridEnabled WRITE setGridEnabled)
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(int height READ height WRITE setHeight)
Q_ENUMS(SelectionMode)
Q_ENUMS(ShadowQuality)
Q_ENUMS(LabelTransparency)
+protected:
+ Bars3dShared *m_shared;
+ DeclarativeBarsCachedStatePrivate *m_cachedState;
+
public:
// Duplicated here to be able to use the same enums
enum SelectionMode {
@@ -84,22 +100,134 @@ public:
};
public:
- explicit DeclarativeBars();
+ explicit DeclarativeBars(QQuickItem *parent = 0);
~DeclarativeBars();
+ // Add a row of data. Each new row is added to the front of the sample space, moving previous
+ // rows back (if sample space is more than one row deep)
+ Q_INVOKABLE void addDataRow(const QVector<GLfloat> &dataRow,
+ const QString &labelRow = QString(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+ // ownership of dataItems is transferred
+ Q_INVOKABLE void addDataRow(const QVector<QDataItem*> &dataRow,
+ const QString &labelRow = QString(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+ // ownership of dataRow is transferred
+ Q_INVOKABLE void addDataRow(QDataRow *dataRow);
+
+ // Add complete data set at a time, as a vector of data rows
+ Q_INVOKABLE void addDataSet(const QVector< QVector<GLfloat> > &data,
+ const QVector<QString> &labelsRow = QVector<QString>(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+
+ // ownership of dataItems is transferred
+ Q_INVOKABLE void addDataSet(const QVector< QVector<QDataItem*> > &data,
+ const QVector<QString> &labelsRow = QVector<QString>(),
+ const QVector<QString> &labelsColumn = QVector<QString>());
+ // ownership of dataSet is transferred
+ Q_INVOKABLE void addDataSet(QDataSet* dataSet);
+
+ // bar thickness, spacing between bars, and is spacing relative to thickness or absolute
+ // y -component sets the thickness/spacing of z -direction
+ // With relative 0.0f means side-to-side, 1.0f = one thickness in between
+ Q_INVOKABLE void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f),
+ QSizeF spacing = QSizeF(1.0f, 1.0f),
+ bool relative = true);
+
+ // bar type; bars (=cubes), pyramids, cones, cylinders, etc.
+ Q_INVOKABLE void setBarType(BarStyle style, bool smooth = false);
+
+ // override bar type with own mesh
+ Q_INVOKABLE void setMeshFileName(const QString &objFileName);
+
+ // how many samples per row and column, and names for axes
+ Q_INVOKABLE void setupSampleSpace(int samplesRow, int samplesColumn,
+ const QString &labelRow = QString(),
+ const QString &labelColumn = QString(),
+ const QString &labelHeight = QString());
+
+ // Select preset camera placement
+ Q_INVOKABLE void setCameraPreset(CameraPreset preset);
+
+ // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and
+ // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in
+ // percentage (10...500))
+ Q_INVOKABLE void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100);
+
+ // Set theme (bar colors, shaders, window color, background colors, light intensity and text
+ // colors are affected)
+ Q_INVOKABLE void setTheme(ColorTheme theme);
+
+ // Set color if you don't want to use themes. Set uniform to false if you want the (height)
+ // color to change from bottom to top
+ Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor,
+ bool uniform = true);
+
+ // Set tick count and step. Note; tickCount * 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.
+ Q_INVOKABLE void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f);
+
+ // TODO: light placement API
+
// Change selection mode; single bar, bar and row, bar and column, or all
- void setSelMode(DeclarativeBars::SelectionMode mode);
- DeclarativeBars::SelectionMode selMode();
+ void setSelectionMode(SelectionMode mode);
+ SelectionMode selectionMode();
+
+ // Font size adjustment
+ void setFontSize(float fontsize);
+ float fontSize();
+
+ // Set font
+ void setFont(const QFont &font);
+ QFont font();
// Label transparency adjustment
- void setTransparency(DeclarativeBars::LabelTransparency transparency);
- DeclarativeBars::LabelTransparency transparency();
+ void setLabelTransparency(LabelTransparency transparency);
+ LabelTransparency labelTransparency();
+
+ // Enable or disable background grid
+ void setGridEnabled(bool enable);
+ bool gridEnabled();
+
+ // Enable or disable background mesh
+ void setBackgroundEnabled(bool enable);
+ bool backgroundEnabled();
+
+ // Adjust shadow quality
+ void setShadowQuality(ShadowQuality quality);
+ ShadowQuality shadowQuality();
// Adjust shadow quality
void setShadow(DeclarativeBars::ShadowQuality quality);
DeclarativeBars::ShadowQuality shadow();
+
+ protected:
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
+
+};
+
+// TODO: If we use texture node, our rendering is done into a texture that is then drawn to the
+// qquickwindow -> selection will not work
+class DeclarativeBarsRenderer : public QObject, public QSGSimpleTextureNode
+{
+ Q_OBJECT
+
+public:
+ DeclarativeBarsRenderer(QQuickWindow *window, Bars3dShared *shared);
+ ~DeclarativeBarsRenderer();
+
+public slots:
+ void render();
+
+private:
+ QOpenGLFramebufferObject *m_fbo;
+ QSGTexture *m_texture;
+ QQuickWindow *m_window;
+ Bars3dShared *m_barsRenderer;
};
QTENTERPRISE_DATAVIS3D_END_NAMESPACE
+QTENTERPRISE_DATAVIS3D_USE_NAMESPACE
#endif
diff --git a/src/datavis3dqml2/scenerenderernode_p.h b/src/datavis3dqml2/declarativebars_p.h
index aa59b9c1..62dcc708 100644
--- a/src/datavis3dqml2/scenerenderernode_p.h
+++ b/src/datavis3dqml2/declarativebars_p.h
@@ -49,46 +49,48 @@
//
// We mean it.
-#ifndef SCENERENDERERNODE_P_H
-#define SCENERENDERERNODE_P_H
+#ifndef DECLARATIVEBARS_P_H
+#define DECLARATIVEBARS_P_H
#include "QtDataVis3D/qdatavis3dglobal.h"
-
-#include <QObject>
-#include <qsgsimpletexturenode.h>
-
-class QOpenGLFramebufferObject;
-class QSGTexture;
-class QQuickWindow;
+#include "QtDataVis3D/qdatavis3namespace.h"
+#include <QString>
QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-class Q3DBars;
-//class Q3DMaps;
+class QDataRow;
-// TODO: If we use texture node, our rendering is done into a texture that is then drawn to the
-// qquickwindow -> selection will not work
-// TODO: Check if better ones are available
-class SceneRendererNode : public QObject, public QSGSimpleTextureNode
+class DeclarativeBarsCachedStatePrivate
{
- Q_OBJECT
-
public:
- SceneRendererNode(QQuickWindow *window);
- ~SceneRendererNode();
+ explicit DeclarativeBarsCachedStatePrivate();
+ ~DeclarativeBarsCachedStatePrivate();
+
+ bool m_isSampleSpaceSet;
+ int m_cachedState;
+ int m_samplesRow;
+ int m_samplesColumn;
+ QString m_labelRow;
+ QString m_labelColumn;
+ QString m_labelHeight;
+
+ QDataRow *m_dataRow;
-public slots:
- void render();
+ bool m_isSelectionModeSet;
+ SelectionMode m_selectionMode;
-private:
- QOpenGLFramebufferObject *m_fbo;
- QSGTexture *m_texture;
- QQuickWindow *m_window;
- Q3DBars *m_scene;
- //Q3DMaps *m_scene;
+ bool m_isLabelTransparencySet;
+ LabelTransparency m_labelTransparency;
+
+ bool m_isShadowQualitySet;
+ ShadowQuality m_shadowQuality;
+
+
+ bool m_isGridSet;
+ bool m_isGridEnabled;
};
QTENTERPRISE_DATAVIS3D_END_NAMESPACE
+QTENTERPRISE_DATAVIS3D_USE_NAMESPACE
-#endif
-
+#endif // DECLARATIVEBARS_P_H
diff --git a/src/datavis3dqml2/scenerenderernode.cpp b/src/datavis3dqml2/scenerenderernode.cpp
deleted file mode 100644
index 778cedbe..00000000
--- a/src/datavis3dqml2/scenerenderernode.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtDataVis3D module.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "scenerenderernode_p.h"
-
-#include <QtQuick/QQuickWindow>
-#include <QtGui/QOpenGLFramebufferObject>
-#include "q3dbars.h"
-//#include "q3dmaps.h"
-
-QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE
-
-SceneRendererNode::SceneRendererNode(QQuickWindow *window)
- : m_fbo(0),
- m_texture(0),
- m_window(window),
- m_scene(0)
-{
- connect(m_window, SIGNAL(beforeRendering()), this, SLOT(render()));
-}
-
-SceneRendererNode::~SceneRendererNode()
-{
- delete m_texture;
- delete m_fbo;
- delete m_scene;
-}
-
-void SceneRendererNode::render()
-{
- QSize size = rect().size().toSize();
-
- if (!m_fbo) {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- m_fbo = new QOpenGLFramebufferObject(size, format);
- m_texture = m_window->createTextureFromId(m_fbo->texture(), size);
- // TODO: If we create the vis3d this way, how do we connect it with QML?
- // Should we create it at QML and give it to DataVisView using a property (setVisualizer or similar)?
- // DataVisView can then give it here as an argument in constructor?
-
- m_scene = new Q3DBars();
- m_scene->setSelectionMode(ModeNone);
- m_scene->setShadowQuality(ShadowNone);
- m_scene->setTheme(ThemeSystem);
- m_scene->initialize();
-
- // TODO: For testing. Add some data to scene.
- QVector< QVector<float> > data;
- QVector<float> row;
- for (float j = 0.0f; j < 5.0f; j++) {
- for (float i = 0.0f; i < 5.0f; i++)
- row.append(j / 10.0f + i / 10.0f);
- data.append(row);
- row.clear();
- }
- // Set up sample space based on inserted data
- m_scene->setupSampleSpace(5, 5);
- // Add data to chart
- m_scene->addDataSet(data);
- m_scene->setBarType(Cones);
-
- //m_scene = new Q3DMaps();
- setTexture(m_texture);
- }
-
- m_fbo->bind();
-
- // TODO: Render here, or "capture" the rendering we do at Q3DBars/Q3DMaps
- m_scene->render();
-
- m_fbo->bindDefault();
-
- m_window->update();
-}
-
-QTENTERPRISE_DATAVIS3D_END_NAMESPACE
-
-