summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.cmake.conf2
-rw-r--r--dependencies.yaml6
-rw-r--r--src/datavisualization/doc/qtdatavis3d.qdocconf7
-rw-r--r--src/datavisualization/doc/src/maintenance-phase.qdocinc6
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-index.qdoc3
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-overview.qdoc2
-rw-r--r--tests/manual/qmlperf/CMakeLists.txt3
-rw-r--r--tests/manual/qmlperf/datagenerator.cpp325
-rw-r--r--tests/manual/qmlperf/datagenerator.h44
-rw-r--r--tests/manual/qmlperf/qml/qmlperf/AutoTest.qml219
-rw-r--r--tests/manual/qmlperf/qml/qmlperf/Tests.qml184
-rw-r--r--tests/manual/qmlperf/qml/qmlperf/main.qml559
12 files changed, 1182 insertions, 178 deletions
diff --git a/.cmake.conf b/.cmake.conf
index dc1d7a92..6792234a 100644
--- a/.cmake.conf
+++ b/.cmake.conf
@@ -1,4 +1,4 @@
-set(QT_REPO_MODULE_VERSION "6.8.0")
+set(QT_REPO_MODULE_VERSION "6.9.0")
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1")
list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_FOREACH=1")
diff --git a/dependencies.yaml b/dependencies.yaml
index b9fb2c5e..7266301a 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -1,10 +1,10 @@
dependencies:
../qtbase:
- ref: f0633e823796775d2c019363ca4f1cb008851402
+ ref: 2d72757875c913939909a1a36fcb123a1e26ac26
required: true
../qtdeclarative:
- ref: 1635ca51f018bbb8d1ea5069a7f2ed8503be8cb9
+ ref: 5ca788a7a2bede98c9c75ce1068fa32fd63478cf
required: false
../qtmultimedia:
- ref: 3873ceb52cfc6205ce56a218fd3f772dcb396b91
+ ref: eefff29f778aa5bec8c52de10058767360c99957
required: false
diff --git a/src/datavisualization/doc/qtdatavis3d.qdocconf b/src/datavisualization/doc/qtdatavis3d.qdocconf
index 952cac3e..8f5034d0 100644
--- a/src/datavisualization/doc/qtdatavis3d.qdocconf
+++ b/src/datavisualization/doc/qtdatavis3d.qdocconf
@@ -16,7 +16,12 @@ exampledirs += ../../../examples/datavisualization \
imagedirs += ../images \
images
-depends = qtcore qtgui qtqml qtquick qtdoc qtcmake qtwidgets
+# Define a custom file name suffix for C++ types as Qt Graphs
+# module declares identically-named, documented types.
+outputsuffixes = CPP
+outputsuffixes.CPP = -qtdatavis
+
+depends = qtcore qtgui qtqml qtquick qtdoc qtcmake qtwidgets qtgraphs
qhp.projects = QtDataVis3D
diff --git a/src/datavisualization/doc/src/maintenance-phase.qdocinc b/src/datavisualization/doc/src/maintenance-phase.qdocinc
new file mode 100644
index 00000000..65cd17b0
--- /dev/null
+++ b/src/datavisualization/doc/src/maintenance-phase.qdocinc
@@ -0,0 +1,6 @@
+\note The Qt Data Visualization module is in the maintenance phase. For new
+projects, consider using the \l {Qt Graphs} module. For 3D rendering, QtGraphs
+uses QtQuick3D, which in turn uses QtRhi. QtRhi relies on each platform's native
+rendering backend (Metal on macOS, DirectX on Windows, OpenGL or Vulkan on
+Linux). To migrate from Qt Data Visualization to Qt Graphs module, refer to
+\l {Qt Graphs Migration from Qt DataVisualization}.
diff --git a/src/datavisualization/doc/src/qtdatavisualization-index.qdoc b/src/datavisualization/doc/src/qtdatavisualization-index.qdoc
index 5896b094..6af8f4e8 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-index.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-index.qdoc
@@ -6,7 +6,6 @@
\page qtdatavisualization-index.html
\brief Provides functionality for 3D visualization.
-
The Qt Data Visualization module enables you to visualize data in 3D as
bar, scatter, and surface graphs. It's especially useful for visualizing
depth maps and large quantities of rapidly changing data, such as data
@@ -16,6 +15,8 @@
Qt Data Visualization is built on Qt 6 and OpenGL to take advantage of
hardware acceleration and Qt Quick.
+ \include maintenance-phase.qdocinc
+
\section1 Using the Module
\section2 QML API
diff --git a/src/datavisualization/doc/src/qtdatavisualization-overview.qdoc b/src/datavisualization/doc/src/qtdatavisualization-overview.qdoc
index 0bf83ec4..f6bbea48 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-overview.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-overview.qdoc
@@ -31,6 +31,8 @@
and viewing 2D slices of the 3D data for increased readability. For more
information, see \l{Qt Data Visualization Interacting with Data}.
+ \include maintenance-phase.qdocinc
+
\section1 Graph Types
The Qt Data Visualization module provides the following 3D graph types:
diff --git a/tests/manual/qmlperf/CMakeLists.txt b/tests/manual/qmlperf/CMakeLists.txt
index 31235e32..b2a90d5f 100644
--- a/tests/manual/qmlperf/CMakeLists.txt
+++ b/tests/manual/qmlperf/CMakeLists.txt
@@ -9,6 +9,7 @@ qt_internal_add_manual_test(qmlperf
datagenerator.cpp datagenerator.h
main.cpp
)
+
target_link_libraries(qmlperf PUBLIC
Qt::Gui
Qt::Qml
@@ -18,6 +19,8 @@ target_link_libraries(qmlperf PUBLIC
set(qmlperf_resource_files
"qml/qmlperf/main.qml"
+ "qml/qmlperf/Tests.qml"
+ "qml/qmlperf/AutoTest.qml"
)
qt_internal_add_resource(qmlperf "qmlperf"
diff --git a/tests/manual/qmlperf/datagenerator.cpp b/tests/manual/qmlperf/datagenerator.cpp
index df00d483..a092e749 100644
--- a/tests/manual/qmlperf/datagenerator.cpp
+++ b/tests/manual/qmlperf/datagenerator.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "datagenerator.h"
@@ -7,62 +7,329 @@
Q_DECLARE_METATYPE(QScatter3DSeries *)
-DataGenerator::DataGenerator(QObject *parent) :
- QObject(parent)
+DataGenerator::DataGenerator(QObject *parent)
+ : QObject(parent)
{
qRegisterMetaType<QScatter3DSeries *>();
-
- m_file = new QFile("results.txt");
- if (!m_file->open(QIODevice::WriteOnly | QIODevice::Text)) {
- delete m_file;
- m_file = 0;
- }
+ qRegisterMetaType<QSurface3DSeries *>();
+ qRegisterMetaType<QBar3DSeries *>();
+ setFilePath(QUrl());
}
DataGenerator::~DataGenerator()
{
m_file->close();
+ m_csv->close();
delete m_file;
+ delete m_csv;
}
-void DataGenerator::generateData(QScatter3DSeries *series, uint count)
+void DataGenerator::generateSurfaceData(QSurface3DSeries *series, uint count)
{
- QScatterDataArray *dataArray = new QScatterDataArray;
- dataArray->resize(count);
- QScatterDataItem *ptrToDataArray = &dataArray->first();
+ if (m_surfaceResetArray) {
+ for (auto row : *m_surfaceResetArray)
+ row->clear();
+ m_surfaceResetArray->clear();
+ }
+ m_surfaceResetArray = new QSurfaceDataArray;
+ m_surfaceResetArray->reserve(count);
for (uint i = 0; i < count; i++) {
- ptrToDataArray->setPosition(QVector3D(QRandomGenerator::global()->generateDouble(),
- QRandomGenerator::global()->generateDouble(),
- QRandomGenerator::global()->generateDouble()));
- ptrToDataArray++;
+ m_surfaceResetArray->append(new QSurfaceDataRow());
+ QSurfaceDataRow *row = m_surfaceResetArray->at(i);
+ row->reserve(count);
+ for (uint j = 0; j < count; j++) {
+ float x = float(j) / float(count);
+ float z = float(i) / float(count);
+ row->append(
+ QSurfaceDataItem(QVector3D(x, QRandomGenerator::global()->generateDouble(), z)));
+ }
}
- series->dataProxy()->resetArray(dataArray);
+ writeLine(QString("Surface Graph: setting %1 points").arg(count * count));
+
+ m_timer.start();
+ series->dataProxy()->resetArray(m_surfaceResetArray);
+ long long nsecs = m_timer.nsecsElapsed();
+
+ writeLine(QString("Took %1 nanoseconds").arg(nsecs));
+
+ populateSurfaceCaches(count);
}
-void DataGenerator::add(QScatter3DSeries *series, uint count)
+void DataGenerator::generateScatterData(QScatter3DSeries *series, uint count)
{
- QScatterDataArray appendArray;
- appendArray.resize(count);
+ if (m_scatterResetArray) {
+ m_scatterResetArray->clear();
+ }
+ m_scatterResetArray = new QScatterDataArray;
+ m_scatterResetArray->reserve(count * count);
+ for (uint i = 0; i < count * count; i++) {
+ m_scatterResetArray->append(
+ QScatterDataItem(QVector3D(QRandomGenerator::global()->generateDouble() * 2 - 1,
+ QRandomGenerator::global()->generateDouble() * 2 - 1,
+ QRandomGenerator::global()->generateDouble() * 2 - 1)));
+ }
+ writeLine(QString("Scatter Graph: setting %1 points").arg(count * count));
+
+ m_timer.start();
+ series->dataProxy()->resetArray(m_scatterResetArray);
+ long long nsecs = m_timer.nsecsElapsed();
+
+ writeLine(QString("Took %1 nanoseconds").arg(nsecs));
+
+ populateScatterCaches(count);
+}
+
+void DataGenerator::generateBarData(QBar3DSeries *series, uint count)
+{
+ if (m_barResetArray) {
+ for (auto row : *m_barResetArray)
+ row->clear();
+ m_barResetArray->clear();
+ }
+
+ m_barResetArray = new QBarDataArray;
+ m_barResetArray->reserve(count);
for (uint i = 0; i < count; i++) {
- appendArray[i].setPosition(QVector3D(QRandomGenerator::global()->generateDouble(),
- QRandomGenerator::global()->generateDouble(),
- QRandomGenerator::global()->generateDouble()));
+ m_barResetArray->append(new QBarDataRow());
+ QBarDataRow *row = m_barResetArray->at(i);
+ row->reserve(count);
+ for (uint j = 0; j < count; j++) {
+ row->append(QBarDataItem(QRandomGenerator::global()->generateDouble()));
+ }
+ }
+
+ writeLine(QString("Bar Graph: setting %1 points").arg(count * count));
+
+ m_timer.start();
+ series->dataProxy()->resetArray(m_barResetArray);
+ long long nsecs = m_timer.nsecsElapsed();
+
+ writeLine(QString("Took %1 nanoseconds").arg(nsecs));
+
+ populateBarChaches(count);
+}
+
+void DataGenerator::updateSurfaceData(QSurface3DSeries *series)
+{
+ if (!series || series->dataProxy()->columnCount() == 0 || series->dataProxy()->rowCount() == 0)
+ return;
+
+ static int index = 0;
+ const QSurfaceDataArray &cache = m_surfaceCaches.at(index);
+ const int rows = cache.count();
+ for (int i = 0; i < rows; i++) {
+ const QSurfaceDataRow &sourceRow = *(cache.at(i));
+ QSurfaceDataRow &row = *(*m_surfaceResetArray)[i];
+ std::copy(sourceRow.cbegin(), sourceRow.cend(), row.begin());
}
- series->dataProxy()->addItems(appendArray);
+ series->dataProxy()->resetArray(m_surfaceResetArray);
+
+ index++;
+ if (index >= m_cacheCount)
+ index = 0;
}
+void DataGenerator::updateScatterData(QScatter3DSeries *series)
+{
+ if (!series || series->dataProxy()->array()->count() == 0)
+ return;
-void DataGenerator::writeLine(int itemCount, float fps)
+ static int index = 0;
+ const QScatterDataArray &cache = m_scatterCaches.at(index);
+
+ const int count = cache.count();
+ for (int i = 0; i < count; i++) {
+ (*m_scatterResetArray)[i].setPosition(cache.at(i).position());
+ }
+
+ series->dataProxy()->resetArray(m_scatterResetArray);
+ index++;
+ if (index >= m_cacheCount)
+ index = 0;
+}
+void DataGenerator::updateBarData(QBar3DSeries *series)
+{
+ static int index = 0;
+ const int rows = series->dataProxy()->rowCount();
+
+ const QBarDataArray &cache = m_barCaches.at(index);
+ for (int i = 0; i < rows; i++) {
+ const QBarDataRow &sourceRow = *(cache.at(i));
+ QBarDataRow &row = *(*m_barResetArray)[i];
+ std::copy(sourceRow.cbegin(), sourceRow.cend(), row.begin());
+ }
+
+ series->dataProxy()->resetArray(m_barResetArray);
+ index++;
+ if (index >= m_cacheCount)
+ index = 0;
+}
+
+void DataGenerator::setFilePath(const QUrl &path)
+{
+ if (m_file) {
+ m_file->close();
+ delete m_file;
+ }
+ if (m_csv) {
+ m_csv->close();
+ delete m_csv;
+ }
+
+ QString pathString = path.toLocalFile();
+ if (!pathString.isEmpty()) {
+ pathString += "/";
+ qDebug() << "Set path to : " << pathString;
+ emit onMessage("Set path to " + pathString);
+ }
+
+ m_file = new QFile(pathString + "results.txt");
+ if (!m_file->open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qDebug() << m_file->errorString();
+ delete m_file;
+ m_file = 0;
+ }
+ m_csv = new QFile(pathString + "measurements.csv");
+ if (!m_csv->open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qDebug() << m_file->errorString();
+ delete m_csv;
+ m_csv = 0;
+ } else {
+ QTextStream out(m_csv);
+ QString headers = QString("Graph type,Number of points,Optimization,MSAA "
+ "Samples,Shadow Quality,Init Time,Average FPS");
+ out << headers << Qt::endl;
+ }
+}
+
+void DataGenerator::writeLine(const QString &line)
{
if (m_file) {
QTextStream out(m_file);
- QString fpsFormatString(QStringLiteral("%1 %2\n"));
- QString fpsString = fpsFormatString.arg(itemCount).arg(fps);
+ qDebug() << line << Qt::endl;
+ out << line << Qt::endl;
+ emit onMessage(line);
+ }
+}
+
+void DataGenerator::writeCSV(const QString &line)
+{
+ if (m_csv) {
+ qDebug() << line << Qt::endl;
+ QTextStream out(m_csv);
+ out << line << Qt::endl;
+ }
+}
- out << fpsString;
+void DataGenerator::populateSurfaceCaches(int sideLength)
+{
+ for (int i = 0; i < m_surfaceCaches.size(); i++) {
+ QSurfaceDataArray &array = m_surfaceCaches[i];
+ array.clear();
+ }
+ m_surfaceCaches.clear();
+
+ // Re-create the cache array
+ m_surfaceCaches.resize(m_cacheCount);
+ for (int i = 0; i < m_cacheCount; i++) {
+ QSurfaceDataArray &array = m_surfaceCaches[i];
+ array.reserve(sideLength);
+ for (int j = 0; j < sideLength; j++) {
+ array.append(new QSurfaceDataRow(sideLength));
+ }
+ }
+
+ //Populate caches
+ for (int i = 0; i < m_cacheCount; i++) {
+ QSurfaceDataArray &cache = m_surfaceCaches[i];
+ float timeStep = float(i) / float(m_cacheCount);
+ for (int j = 0; j < sideLength; j++) {
+ QSurfaceDataRow &row = *(cache[j]);
+ for (int k = 0; k < sideLength; k++) {
+ float x = float(k) / float(sideLength);
+ float z = float(j) / float(sideLength);
+ float y = qSin(2 * M_PI * (x + z + (timeStep))) * 0.5 + 0.5;
+ row[k] = QSurfaceDataItem(QVector3D(x, y, z));
+ }
+ }
+ }
+}
+
+void DataGenerator::populateScatterCaches(int sideLength)
+{
+ for (int i = 0; i < m_scatterCaches.size(); i++) {
+ QScatterDataArray &array = m_scatterCaches[i];
+ array.clear();
+ }
+ m_scatterCaches.clear();
+
+ // Re-create the cache array
+ const int count = sideLength * sideLength;
+ m_scatterCaches.resize(m_cacheCount);
+ for (int i = 0; i < m_cacheCount; i++) {
+ QScatterDataArray &array = m_scatterCaches[i];
+ array.reserve(count);
+ for (int j = 0; j < count; j++) {
+ array.append(QScatterDataItem());
+ }
+ }
+
+ //Populate caches
+ for (int i = 0; i < m_cacheCount; i++) {
+ // time loops from 0 to 4
+ float t = (float(i) * 4) / float(m_cacheCount);
+ QScatterDataArray &cache = m_scatterCaches[i];
+ for (int j = 0; j < sideLength; j++) {
+ for (int k = 0; k < sideLength; k++) {
+ float u = (float(j) / float(sideLength)) * 2 - 1;
+ float v = (float(k) / float(sideLength)) * 2 - 1;
+
+ //create a torus
+ float r1 = 0.7f + 0.1f * qSin(M_PI * (6.0f * u + 0.5f * t));
+ float r2 = 0.15f + 0.05f * qSin(M_PI * (8.0f * u + 4.0f * v + 2.0f * t));
+ float s = r1 + r2 * qCos(M_PI * v);
+
+ float x = s * qSin(M_PI * u);
+ float y = r2 * qSin(M_PI * v);
+ float z = s * qCos(M_PI * u);
+ cache[sideLength * j + k].setPosition(QVector3D(x, y, z));
+ }
+ }
+ }
+}
+
+void DataGenerator::populateBarChaches(int sideLength)
+{
+ for (int i = 0; i < m_barCaches.size(); i++) {
+ QBarDataArray &array = m_barCaches[i];
+ array.clear();
+ }
+ m_barCaches.clear();
+
+ // Re-create the cache array
+ m_barCaches.resize(m_cacheCount);
+ for (int i = 0; i < m_cacheCount; i++) {
+ QBarDataArray &array = m_barCaches[i];
+ array.reserve(sideLength);
+ for (int j = 0; j < sideLength; j++) {
+ array.append(new QBarDataRow(sideLength));
+ }
+ }
+ for (int i = 0; i < m_cacheCount; i++) {
+ QBarDataArray &cache = m_barCaches[i];
+ float timeStep = float(i) / float(m_cacheCount);
+ for (int j = 0; j < sideLength; j++) {
+ QBarDataRow &row = *(cache[j]);
+ for (int k = 0; k < sideLength; k++) {
+ float x = float(j) / float(sideLength);
+ float z = float(k) / float(sideLength);
+ float y = qSin(2 * M_PI * (x + z + (timeStep))) * 0.5 + 0.5;
+ row[k] = QBarDataItem(y);
+ }
+ }
}
}
diff --git a/tests/manual/qmlperf/datagenerator.h b/tests/manual/qmlperf/datagenerator.h
index 99a9dbf7..5e8fe959 100644
--- a/tests/manual/qmlperf/datagenerator.h
+++ b/tests/manual/qmlperf/datagenerator.h
@@ -1,27 +1,53 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DATAGENERATOR_H
#define DATAGENERATOR_H
-#include <QtDataVisualization/QScatter3DSeries>
#include <QtCore/QFile>
+#include <QtDataVisualization>
-class DataGenerator : public QObject
+class DataGenerator : public QObject
{
Q_OBJECT
public:
DataGenerator(QObject *parent = 0);
- virtual ~DataGenerator();
+ ~DataGenerator() override;
public Q_SLOTS:
- void generateData(QScatter3DSeries *series, uint count);
- void add(QScatter3DSeries *series, uint count);
- void writeLine(int itemCount, float fps);
+ void generateSurfaceData(QSurface3DSeries *series, uint count);
+ void generateScatterData(QScatter3DSeries *series, uint count);
+ void generateBarData(QBar3DSeries *series, uint count);
+
+ void updateScatterData(QScatter3DSeries *series);
+ void updateSurfaceData(QSurface3DSeries *series);
+ void updateBarData(QBar3DSeries *series);
+
+ void setFilePath(const QUrl &path);
+ void writeLine(const QString &line);
+ void writeCSV(const QString &line);
+
+Q_SIGNALS:
+ void onMessage(const QString &message);
+ void onCaptureInit(long long nanoseconds);
private:
- QScatter3DSeries m_series;
- QFile *m_file;
+ QFile *m_file = nullptr;
+ QFile *m_csv = nullptr;
+ QElapsedTimer m_timer;
+ int m_cacheCount = 60;
+
+ QList<QSurfaceDataArray> m_surfaceCaches;
+ QList<QScatterDataArray> m_scatterCaches;
+ QList<QBarDataArray> m_barCaches;
+
+ QSurfaceDataArray *m_surfaceResetArray = nullptr;
+ QScatterDataArray *m_scatterResetArray = nullptr;
+ QBarDataArray *m_barResetArray = nullptr;
+
+ void populateSurfaceCaches(int sideLength);
+ void populateScatterCaches(int sideLength);
+ void populateBarChaches(int sideLength);
};
#endif // DATAGENERATOR_H
diff --git a/tests/manual/qmlperf/qml/qmlperf/AutoTest.qml b/tests/manual/qmlperf/qml/qmlperf/AutoTest.qml
new file mode 100644
index 00000000..d860b99a
--- /dev/null
+++ b/tests/manual/qmlperf/qml/qmlperf/AutoTest.qml
@@ -0,0 +1,219 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtDataVisualization
+import "."
+
+Item {
+
+ height: 150
+
+ property list<string> graphTypes: ["Surface", "Scatter", "Bars"]
+ property int currentGraph: 0
+
+ property list<int>dataPoints: [10, 100, 300, 500]
+ property int currentPoints: 0
+
+ property list<string> optimization: ["Default", "Static"]
+ property int currentOptimization: 0
+
+ property list<int> sampleCounts: [0,2,4,8]
+ property int currentSamples: 0
+
+
+ property int shadowQuality
+
+ property bool finished: true
+
+ property int initTime: 0
+
+ function initAutoTest() {
+ //go through each graph iterating over all the variables
+ liveDataCB.checked = true
+ rotateCB.checked = true
+
+ tests.onTestFinished.connect(test)
+ dataGenerator.onCaptureInit.connect(setInitTime)
+
+ finished = false
+
+ currentGraph = 0
+ currentPoints = 0
+ currentOptimization = 0
+ currentSamples= 0
+ shadowQuality = 0
+
+ setParameters()
+ tests.startTest()
+ }
+
+ function test() {
+ //write previous test results
+ var averageFps = tests.averageFps
+ // graph type, num points, optimization, msaa, init time, averagefps
+ var csvLine = graphTypes[currentGraph] + ","
+ + (dataPoints[currentPoints] * dataPoints[currentPoints])+ ","
+ + optimization[currentOptimization] + ","
+ + sampleCounts[currentSamples] + ","
+ + shadowQuality + ","
+ + initTime + ","
+ + averageFps
+
+ dataGenerator.writeCSV(csvLine)
+ increment()
+ setParameters()
+ if (!finished) {
+ tests.startTest()
+ } else {
+ tests.onTestFinished.disconnect(test)
+ dataGenerator.onCaptureInit.disconnect(setInitTime)
+ }
+ }
+
+ function increment() {
+ if (varyShadow.checked) {
+ if (shadowQuality < 6) {
+ shadowQuality++
+ return
+ }
+ shadowQuality = 0
+ }
+
+ if (varySamples.checked) {
+ if (currentSamples < sampleCounts.length -1) {
+ currentSamples ++
+ return
+ }
+ currentSamples = 0
+ }
+
+ if (varyOptimization.checked) {
+ if (currentOptimization < optimization.length -1
+ && tabBar.currentIndex !== 0) {
+ currentOptimization++
+ return
+ }
+ currentOptimization = 0
+ }
+
+ if (varyPoints.checked) {
+ if (currentPoints < dataPoints.length -1) {
+ currentPoints ++
+ return
+ }
+ currentPoints = 0
+ }
+
+ if (varyGraphs.checked) {
+ if (currentGraph < graphTypes.length - 1) {
+ currentGraph++
+ console.log("Switching to " + graphTypes[currentGraph])
+ return
+ }
+ currentGraph = 0
+ }
+
+ dataGenerator.writeLine("Finished all tests!")
+ finished = true
+ }
+
+
+ function setParameters() {
+ if (varyShadow.checked) {
+ surfaceGraph.shadowQuality = shadowQuality
+ scatterGraph.shadowQuality = shadowQuality
+ barGraph.shadowQuality = shadowQuality
+ }
+
+ if (varySamples.checked) {
+ surfaceGraph.msaaSamples = sampleCounts[currentSamples]
+ scatterGraph.msaaSamples = sampleCounts[currentSamples]
+ barGraph.msaaSamples = sampleCounts[currentSamples]
+ }
+
+ if (varyOptimization.checked) {
+ if (optimization[currentOptimization] === "Legacy") {
+ scatterGraph.optimizationHint = AbstractGraph3D.OptimizationHint.Default
+ barGraph.optimizationHint = AbstractGraph3D.OptimizationHint.Default
+ } else {
+ scatterGraph.optimizationHint = AbstractGraph3D.OptimizationHint.Legacy
+ barGraph.optimizationHint = AbstractGraph3D.OptimizationHint.Legacy
+ }
+ }
+
+ if (varyGraphs.checked)
+ tabBar.setCurrentIndex(currentGraph)
+
+ if (varyPoints.checked) {
+ if (tabBar.currentIndex === 0)
+ dataGenerator.generateSurfaceData(surfaceSeries, dataPoints[currentPoints])
+ else if (tabBar.currentIndex === 1)
+ dataGenerator.generateScatterData(scatterSeries, dataPoints[currentPoints])
+ else
+ dataGenerator.generateBarData(barSeries, dataPoints[currentPoints])
+ }
+ }
+
+ function setInitTime(nsecs) {
+ initTime = nsecs
+ }
+
+ Button {
+ id: autoButton
+ text: finished? "Auto Test" : "End test"
+ width: parent.width - 20
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ height: 50
+ onClicked: {
+ if (finished) {
+ dataGenerator.writeLine("Testing configurations...")
+ initAutoTest()
+ } else {
+ finished = true
+ }
+
+ }
+ }
+
+ GridLayout {
+ id: autoTestParams
+ anchors.top: autoButton.bottom
+ anchors.topMargin: 10
+ width: parent.width - 50
+ enabled: finished
+ anchors.horizontalCenter: parent.Center
+ height: 50
+ columns: 2
+ CheckBox {
+ id: varyGraphs
+ text: qsTr("Vary graphs")
+ Layout.alignment: Qt.AlignCenter
+ checked: true
+ }
+ CheckBox {
+ id: varyPoints
+ text: qsTr("Vary points")
+ Layout.alignment: Qt.AlignCenter
+ checked: true
+ }
+ CheckBox {
+ id: varyOptimization
+ text: qsTr("Vary optimization")
+ Layout.alignment: Qt.AlignCenter
+ }
+ CheckBox {
+ id: varySamples
+ text: qsTr("Vary MSAA ")
+ Layout.alignment: Qt.AlignCenter
+ }
+ CheckBox {
+ id: varyShadow
+ text: qsTr("Vary Shadow ")
+ Layout.alignment: Qt.AlignCenter
+ }
+ }
+}
diff --git a/tests/manual/qmlperf/qml/qmlperf/Tests.qml b/tests/manual/qmlperf/qml/qmlperf/Tests.qml
new file mode 100644
index 00000000..dc533641
--- /dev/null
+++ b/tests/manual/qmlperf/qml/qmlperf/Tests.qml
@@ -0,0 +1,184 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtDataVisualization
+import "."
+
+Item {
+ id: tests
+
+ property alias currentFps: fpsText.fps
+ property alias dataPoints: dataPointText.dataPoints
+ property alias buttonVisible: testButton.visible
+ property real averageFps: 0
+
+ signal onTestFinished
+
+ property list<real> fpsCounts: []
+ Component.onCompleted: {
+ dataGenerator.onMessage.connect(addLine)
+ }
+
+ function addLine(line) {
+ logModel.append({'logText':line});
+ }
+
+
+ function startTest() {
+ // logModel.clear()
+ fpsCounts = []
+ dataGenerator.writeLine(" ")
+ switch (tabBar.currentIndex) {
+ case 0:
+ dataGenerator.writeLine("Started surface test with configuration:")
+ break
+ case 1:
+ dataGenerator.writeLine("Started scatter test with configuration:")
+ break
+ case 2:
+ dataGenerator.writeLine("Started bars test with configuration:")
+ break
+ default:
+ break
+ }
+
+ if (tabBar.currentIndex === 0) {
+ dataGenerator.writeLine("Shadow Quality: " + surfaceGraph.shadowQuality)
+ dataGenerator.writeLine("MSAA samples: "
+ + surfaceGraph.msaaSamples)
+ } else if (tabBar.currentIndex === 1) {
+ dataGenerator.writeLine("Shadow Quality: " + scatterGraph.shadowQuality)
+ var optimizationString = scatterGraph.optimizationHint? "Static" : "Default"
+ dataGenerator.writeLine("Optimization: " + optimizationString)
+ dataGenerator.writeLine("MSAA samples: "
+ + scatterGraph.msaaSamples)
+ } else {
+ dataGenerator.writeLine("Shadow Quality: " + scatterGraph.shadowQuality)
+ optimizationString = barGraph.optimizationHint? "Static" : "Default"
+ dataGenerator.writeLine("Optimization: " + optimizationString)
+ dataGenerator.writeLine("MSAA samples: "
+ + barGraph.msaaSamples)
+
+ }
+
+ testTimer.start()
+ }
+
+ Button {
+ id: testButton
+ text: "Test current"
+ onClicked: startTest()
+ height: 50
+ width: parent.width - 20
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+
+ ColumnLayout {
+ id: statsPanel
+ anchors.top: testButton.bottom
+ anchors.topMargin: 20
+ width: parent.width
+ Text {
+ id: statsBanner
+ text: "Statistics"
+ font.bold: true
+ font.pixelSize: 16
+ Layout.fillWidth: true
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ id: fpsText
+ property real fps: 0
+ text: qsTr("FPS: %1").arg(fps)
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+
+ }
+
+ Text {
+ id: dataPointText
+ property int dataPoints: 0
+ text : qsTr("Data Points: %1").arg(dataPoints)
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ id: logBanner
+ text: "Log"
+ font.bold: true
+ font.pixelSize: 16
+ Layout.fillWidth: true
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+
+ Rectangle {
+ id: logBackground
+ Layout.fillWidth: true
+ Layout.preferredHeight: 170
+ Layout.margins: 10
+ color: "forestgreen"
+ ListView {
+ id: logView
+ anchors.fill: parent
+ highlightFollowsCurrentItem: true
+ clip: true
+ delegate: Text {
+ text: logText
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ width: logView.width
+ wrapMode: Text.Wrap
+ }
+
+ model: ListModel {
+ id: logModel
+ }
+
+ onCountChanged: {
+ logView.currentIndex = count - 1
+ }
+ }
+ }
+ }
+
+ Timer {
+ id: testTimer
+ interval: 1000
+ repeat: true
+ onTriggered: {
+ var fps = 0
+ if (tabBar.currentIndex === 0)
+ fps = surfaceGraph.currentFps
+ else if (tabBar.currentIndex === 1)
+ fps = scatterGraph.currentFps
+ else
+ fps = barGraph.currentFps
+
+ if (fps != -1) {
+ fpsCounts.push(fps)
+ dataGenerator.writeLine("FPS: " + fps)
+ }
+ else {
+ dataGenerator.writeLine("Invalid fps reading")
+ }
+
+ if (fpsCounts.length >= 5) {
+ var sum = 0
+ fpsCounts.forEach((element) => sum+=element);
+ averageFps = sum / fpsCounts.length
+ dataGenerator.writeLine("Average FPS: " + averageFps)
+ testTimer.stop()
+ onTestFinished()
+ }
+ }
+ }
+}
diff --git a/tests/manual/qmlperf/qml/qmlperf/main.qml b/tests/manual/qmlperf/qml/qmlperf/main.qml
index 4562e538..ce282e87 100644
--- a/tests/manual/qmlperf/qml/qmlperf/main.qml
+++ b/tests/manual/qmlperf/qml/qmlperf/main.qml
@@ -1,176 +1,467 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtCore
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
-import QtDataVisualization 1.2
+import QtQuick3D.Helpers
+import QtQuick.Dialogs
+import QtDataVisualization
import "."
Item {
- id: mainview
+ id: mainView
width: 1280
height: 1024
- property var itemCount: 1000.0
- property var addItems: 500.0
-
- Button {
- id: changeButton
- width: parent.width / 7
- height: 50
+ TabBar {
+ id: tabBar
+ anchors.top: parent.top
+ anchors.right: panels.left
anchors.left: parent.left
- enabled: true
- text: "Change"
- onClicked: {
- console.log("changeButton clicked");
- if (graphView.state == "meshsphere") {
- graphView.state = "meshcube"
- } else if (graphView.state == "meshcube") {
- graphView.state = "meshpyramid"
- } else if (graphView.state == "meshpyramid") {
- graphView.state = "meshpoint"
- } else if (graphView.state == "meshpoint") {
- graphView.state = "meshsphere"
- }
+ contentHeight: 50
+ TabButton {
+ text: qsTr("Surface")
+ }
+ TabButton {
+ text: qsTr("Scatter")
+ }
+ TabButton {
+ text: qsTr("Bars")
}
}
- Text {
- id: fpsText
- text: "Reading"
- width: (parent.width / 7) * 3
- height: 50
- anchors.left: changeButton.right
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- }
+ Rectangle {
+ id: panels
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ width: parent.width / 5
+ color: "green"
+
+ ColumnLayout {
+ id: buttonPanel
+ anchors.top: parent.top
+ width: parent.width
+ spacing: 10
+ visible: autoTest.finished
- Button {
- id: optimization
- width: parent.width / 7
- height: 50
- anchors.left: fpsText.right
- enabled: true
- text: scatterPlot.optimizationHints === AbstractGraph3D.OptimizationDefault ? "To Static" : "To Default"
- onClicked: {
- console.log("Optimization");
- if (scatterPlot.optimizationHints === AbstractGraph3D.OptimizationDefault) {
- scatterPlot.optimizationHints = AbstractGraph3D.OptimizationStatic;
- optimization.text = "To Default";
- } else {
- scatterPlot.optimizationHints = AbstractGraph3D.OptimizationDefault;
- optimization.text = "To Static";
+ Button {
+ id: shadowToggle
+ property int shadowQuality: 0
+ property string qualityName: "None"
+ text: qsTr("Shadow Quality : %1").arg(qualityName)
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ onClicked: {
+ var nextQuality = (shadowQuality + 1) % 7
+ surfaceGraph.shadowQuality = nextQuality
+ scatterGraph.shadowQuality = nextQuality
+ barGraph.shadowQuality = nextQuality
+ shadowQuality = nextQuality
+ qualityName = barGraph.shadowQuality.toString()
+ console.log("Set shadow quality to " + qualityName)
+ }
+ }
+
+ Button {
+ id: optimizationToggle
+ visible: tabBar.currentIndex > 0
+ property string optimization: "Default"
+ text: qsTr("Optimization: %1").arg(optimization)
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ onClicked: {
+ if (optimization === "Static") {
+ scatterGraph.optimizationHints = AbstractGraph3D.OptimizationDefault
+ barGraph.optimizationHints = AbstractGraph3D.OptimizationDefault
+ optimization= "Default"
+ } else {
+ scatterGraph.optimizationHints = AbstractGraph3D.OptimizationStatic
+ barGraph.optimizationHints = AbstractGraph3D.OptimizationStatic
+ optimization = "Static"
+ }
+ console.log("Set optimization to " + optimization)
+ }
+ }
+
+ Button {
+ id: samplesButton
+ property list<int> samples: [0,2,4,8]
+ property int index: 0
+ text: qsTr("MSAA samples: %1").arg(samples[index])
+
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ onClicked: {
+ index = (index + 1) % 4
+ surfaceGraph.msaaSamples = samples[index]
+ scatterGraph.msaaSamples = samples[index]
+ barGraph.msaaSamples = samples[index]
+ console.log("Set msaa samples to " + samples[index])
+ }
+ }
+
+ Button {
+ id: scatterMesh
+ visible: tabBar.currentIndex === 1
+ property string mesh: "Sphere"
+ text: qsTr("Mesh: %1").arg(mesh)
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ onClicked: {
+ if (mesh === "Sphere") {
+ scatterSeries.mesh = Abstract3DSeries.MeshCube
+ mesh = "Cube"
+ } else if (mesh === "Cube") {
+ scatterSeries.mesh = Abstract3DSeries.MeshPyramid
+ mesh = "Pyramid"
+ } else if (mesh === "Pyramid") {
+ scatterSeries.mesh = Abstract3DSeries.MeshPoint
+ mesh = "Point"
+ } else {
+ scatterSeries.mesh = Abstract3DSeries.MeshSphere
+ mesh = "Sphere"
+ }
+ }
+ }
+
+
+ Button {
+ id: surfaceShadingToggle
+ visible: tabBar.currentIndex <= 2
+ text: qsTr("Flat shading: %1").arg(surfaceSeries.flatShadingEnabled.toString())
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ onClicked: {
+ surfaceSeries.flatShadingEnabled =
+ !surfaceSeries.flatShadingEnabled
+ scatterSeries.meshSmooth = !scatterSeries.meshSmooth
+ }
+ }
+
+ Button {
+ id: gridToggle
+ visible: tabBar.currentIndex === 0
+ property bool gridEnabled
+ text: qsTr("Show grid: %1").arg(gridEnabled.toString())
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ onClicked: {
+ if (surfaceSeries.drawMode & Surface3DSeries.DrawWireframe)
+ surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe;
+ else
+ surfaceSeries.drawMode |= Surface3DSeries.DrawWireframe;
+
+ gridEnabled = surfaceSeries.drawMode & Surface3DSeries.DrawWireframe
+ }
+
+ }
+
+ ColumnLayout {
+ id: pointSetContainer
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+
+
+ Text {
+ id: spinboxTitle
+ text: "Side length"
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ SpinBox {
+ id: sizeField
+ from: 2
+ to: 500
+ stepSize: 20
+ value: 10
+ editable: true
+ Layout.preferredWidth: parent.width
+ }
+
+ Button {
+ id: pointSetButton
+ text: qsTr("Place points");
+ Layout.preferredWidth: parent.width
+ Layout.bottomMargin: 10
+ onClicked: {
+ switch (tabBar.currentIndex) {
+ case 0:
+ dataGenerator.generateSurfaceData(surfaceSeries, sizeField.value)
+ break;
+ case 1:
+ dataGenerator.generateScatterData(scatterSeries, sizeField.value)
+ break;
+ case 2:
+ dataGenerator.generateBarData(barSeries, sizeField.value)
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ GridLayout {
+ id: checkBoxPanel
+ anchors.top: buttonPanel.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: 10
+ visible: autoTest.finished
+ columns: 2
+
+ CheckBox {
+ id: liveDataCB
+ text: qsTr("Live Data")
+ Layout.fillWidth: true
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ }
+ CheckBox {
+ id: rotateCB
+ text: qsTr("Rotation")
+ Layout.fillWidth: true
+ Layout.margins: 10
+ Layout.alignment: Qt.AlignCenter
+ }
+
+ ColumnLayout {
+ id: freqContainer
+ Layout.columnSpan: 2
+ Text {
+ text: qsTr("Frequency: %1").arg(frequencySlider.value)
+ Layout.fillWidth: true
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ Slider {
+ id: frequencySlider
+ from: 1
+ to: 60
+ stepSize: 1
+ value: 30
+ snapMode: Slider.SnapAlways
+ Layout.alignment: Qt.AlignCenter
+ }
}
}
- }
- Button {
- id: itemAdd
- width: parent.width / 7
- height: 50
- anchors.left: optimization.right
- enabled: true
- text: "Add"
- onClicked: {
- itemCount = itemCount + addItems;
- dataGenerator.add(scatterSeries, addItems);
+ AutoTest {
+ id: autoTest
+ width: parent.width
+ anchors.top: checkBoxPanel.bottom
+ anchors.left: parent.left
+ anchors.topMargin: 10
+ }
+
+ Tests {
+ id: tests
+ width: parent.width
+ anchors.top: autoTest.bottom
+ anchors.left: parent.left
+ buttonVisible: autoTest.finished
+ }
+
+ Button {
+ id: pathButton
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ text: "Set logfile path"
+ anchors.margins: 10
+ onClicked: folderDialog.open()
}
}
- Button {
- id: writeLine
- width: parent.width / 7
- height: 50
- anchors.left: itemAdd.right
- enabled: true
- text: "Write"
- onClicked: {
- dataGenerator.writeLine(itemCount, scatterPlot.currentFps.toFixed(1));
+ FolderDialog {
+ id: folderDialog
+ currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
+ onAccepted: dataGenerator.setFilePath(currentFolder)
+ }
+
+ Timer {
+ id: rotationTimer
+ interval: 15
+ running: rotateCB.checked
+ repeat: true
+ onTriggered: {
+ switch (tabBar.currentIndex) {
+ case 0:
+ if (++surfaceGraph.scene.activeCamera.xRotation == 360)
+ surfaceGraph.cameraXRotation = 0;
+ break
+ case 1:
+ if (++scatterGraph.scene.activeCamera.xRotation == 360)
+ scatterGraph.cameraXRotation = 0;
+ break
+ case 2:
+ if (++barGraph.scene.activeCamera.xRotation == 360)
+ barGraph.cameraXRotation = 0;
+ break
+ }
}
}
- Item {
- id: graphView
- width: mainview.width
- height: mainview.height
- anchors.top: changeButton.bottom
- anchors.left: mainview.left
- state: "meshsphere"
-
- Scatter3D {
- id: scatterPlot
- width: graphView.width
- height: graphView.height
- shadowQuality: AbstractGraph3D.ShadowQualityNone
- optimizationHints: AbstractGraph3D.OptimizationDefault
- scene.activeCamera.yRotation: 45.0
- measureFps: true
- onCurrentFpsChanged: {
- fpsText.text = itemCount + " : " + scatterPlot.currentFps.toFixed(1);
+ Timer {
+ id: updateTimer
+ interval: 1000 / frequencySlider.value
+ running: liveDataCB.checked
+ repeat: true
+ onTriggered: {
+ switch (tabBar.currentIndex) {
+ case 0:
+ dataGenerator.updateSurfaceData(surfaceSeries)
+ break
+ case 1:
+ dataGenerator.updateScatterData(scatterSeries)
+ break
+ case 2:
+ dataGenerator.updateBarData(barSeries)
+ break
}
+ }
+ }
+
+
+ StackLayout {
+ anchors.top: tabBar.bottom
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: panels.left
+ currentIndex: tabBar.currentIndex
+
+ Item {
+ id: surfaceTab
+ Surface3D {
+ id: surfaceGraph
+ anchors.fill: parent
+ shadowQuality: AbstractGraph3D.ShadowQualityNone
+ scene.activeCamera.yRotation: 45.0
+ measureFps: true
+
+ axisX.min: 0
+ axisX.max: 1
+ axisY.min: 0
+ axisY.max: 1
+ horizontalAspectRatio: 1.0
+
- theme: Theme3D {
- type: Theme3D.ThemeRetro
- colorStyle: Theme3D.ColorStyleRangeGradient
- baseGradients: customGradient
+ theme : Theme3D {
+ type: Theme3D.ThemeQt
+ colorStyle: Theme3D.ColorStyleRangeGradient
+ baseGradients: surfaceGradient
- ColorGradient {
- id: customGradient
- ColorGradientStop { position: 1.0; color: "red" }
- ColorGradientStop { position: 0.0; color: "blue" }
+ ColorGradient {
+ id: surfaceGradient
+ ColorGradientStop { position: 1.0; color: "red" }
+ ColorGradientStop { position: 0.0; color: "blue" }
+ }
}
- }
- Scatter3DSeries {
- id: scatterSeries
- mesh: Abstract3DSeries.MeshSphere
- }
+ Surface3DSeries {
+ id: surfaceSeries
+ dataProxy.onArrayReset: tests.dataPoints = dataProxy.columnCount * dataProxy.rowCount
+ }
- Component.onCompleted: dataGenerator.generateData(scatterSeries, itemCount);
+ onCurrentFpsChanged: {
+ tests.currentFps = currentFps
+ }
+ }
}
+ Item {
+ id: scatterTab
+ Scatter3D {
+ id: scatterGraph
+ anchors.fill: parent
+ shadowQuality: AbstractGraph3D.ShadowQualityNone
+ scene.activeCamera.yRotation: 45.0
+ aspectRatio: 1.0
+ horizontalAspectRatio: 1.0
+
+ axisY.min: -1
+ axisY.max: 1
+ axisX.min: -1
+ axisX.max: 1
+ axisZ.min: -1
+ axisZ.max: 1
+
+ measureFps: true
+ theme : Theme3D {
+ type: Theme3D.ThemeQt
+ colorStyle: Theme3D.ColorStyleRangeGradient
+ baseGradients: scatterGradient
- states: [
- State {
- name: "meshsphere"
- StateChangeScript {
- name: "doSphere"
- script: {
- console.log("Do the sphere");
- scatterSeries.mesh = Abstract3DSeries.MeshSphere;
+ ColorGradient {
+ id: scatterGradient
+ ColorGradientStop { position: 1.0; color: "yellow" }
+ ColorGradientStop { position: 0.6; color: "red" }
+ ColorGradientStop { position: 0.4; color: "blue" }
+ ColorGradientStop { position: 0.0; color: "green" }
}
}
- },
- State {
- name: "meshcube"
- StateChangeScript {
- name: "doCube"
- script: {
- console.log("Do the cube");
- scatterSeries.mesh = Abstract3DSeries.MeshCube;
- }
+ Scatter3DSeries {
+ id: scatterSeries
+ dataProxy.onArrayReset: tests.dataPoints = dataProxy.itemCount
+ itemSize: 0.1
}
- },
- State {
- name: "meshpyramid"
- StateChangeScript {
- name: "doPyramid"
- script: {
- console.log("Do the pyramid");
- scatterSeries.mesh = Abstract3DSeries.MeshPyramid;
- }
+ onCurrentFpsChanged: {
+ tests.currentFps = currentFps
}
- },
- State {
- name: "meshpoint"
- StateChangeScript {
- name: "doPoint"
- script: {
- console.log("Do the point");
- scatterSeries.mesh = Abstract3DSeries.MeshPoint;
+ }
+ }
+ Item {
+ id: barTab
+ Bars3D {
+ id: barGraph
+ anchors.fill: parent
+ shadowQuality: AbstractGraph3D.ShadowQualityNone
+ scene.activeCamera.yRotation: 45.0
+ measureFps: true
+ valueAxis.min: 0
+ valueAxis.max: 1
+
+ theme : Theme3D {
+ type: Theme3D.ThemeQt
+ colorStyle: Theme3D.ColorStyleRangeGradient
+ baseGradients: barGradient
+
+ ColorGradient{
+ id: barGradient
+ ColorGradientStop { position: 1.0; color: "red" }
+ ColorGradientStop { position: 0.0; color: "blue" }
}
}
+
+ Bar3DSeries {
+ id: barSeries
+ dataProxy.onArrayReset: tests.dataPoints
+ = dataProxy.colCount * dataProxy.rowCount
+
+ }
+
+ onCurrentFpsChanged: {
+ tests.currentFps = currentFps
+ }
}
- ]
+ }
}
}