mirror of https://github.com/qt/qtdatavis3d.git
Revamp perf test
Fixes: QTBUG-121316 Change-Id: Ia2c77726e45accee59aa06ea1dc82db26ddac0c5 Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
This commit is contained in:
parent
08a0d6f7ba
commit
2542cd0616
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
||||
for (uint i = 0; i < count; i++) {
|
||||
ptrToDataArray->setPosition(QVector3D(QRandomGenerator::global()->generateDouble(),
|
||||
QRandomGenerator::global()->generateDouble(),
|
||||
QRandomGenerator::global()->generateDouble()));
|
||||
ptrToDataArray++;
|
||||
if (m_surfaceResetArray) {
|
||||
for (auto row : *m_surfaceResetArray)
|
||||
row->clear();
|
||||
m_surfaceResetArray->clear();
|
||||
}
|
||||
|
||||
series->dataProxy()->resetArray(dataArray);
|
||||
}
|
||||
|
||||
void DataGenerator::add(QScatter3DSeries *series, uint count)
|
||||
{
|
||||
QScatterDataArray appendArray;
|
||||
appendArray.resize(count);
|
||||
|
||||
m_surfaceResetArray = new QSurfaceDataArray;
|
||||
m_surfaceResetArray->reserve(count);
|
||||
for (uint i = 0; i < count; i++) {
|
||||
appendArray[i].setPosition(QVector3D(QRandomGenerator::global()->generateDouble(),
|
||||
QRandomGenerator::global()->generateDouble(),
|
||||
QRandomGenerator::global()->generateDouble()));
|
||||
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()->addItems(appendArray);
|
||||
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::writeLine(int itemCount, float fps)
|
||||
void DataGenerator::generateScatterData(QScatter3DSeries *series, uint 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++) {
|
||||
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()->resetArray(m_surfaceResetArray);
|
||||
|
||||
index++;
|
||||
if (index >= m_cacheCount)
|
||||
index = 0;
|
||||
}
|
||||
void DataGenerator::updateScatterData(QScatter3DSeries *series)
|
||||
{
|
||||
if (!series || series->dataProxy()->array()->count() == 0)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
out << fpsString;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
id: buttonPanel
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
spacing: 10
|
||||
visible: autoTest.finished
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
theme: Theme3D {
|
||||
type: Theme3D.ThemeRetro
|
||||
colorStyle: Theme3D.ColorStyleRangeGradient
|
||||
baseGradients: customGradient
|
||||
|
||||
ColorGradient {
|
||||
id: customGradient
|
||||
ColorGradientStop { position: 1.0; color: "red" }
|
||||
ColorGradientStop { position: 0.0; color: "blue" }
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
Scatter3DSeries {
|
||||
id: scatterSeries
|
||||
mesh: Abstract3DSeries.MeshSphere
|
||||
}
|
||||
|
||||
Component.onCompleted: dataGenerator.generateData(scatterSeries, itemCount);
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "meshsphere"
|
||||
StateChangeScript {
|
||||
name: "doSphere"
|
||||
script: {
|
||||
console.log("Do the sphere");
|
||||
scatterSeries.mesh = Abstract3DSeries.MeshSphere;
|
||||
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)
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "meshcube"
|
||||
StateChangeScript {
|
||||
name: "doCube"
|
||||
script: {
|
||||
console.log("Do the cube");
|
||||
scatterSeries.mesh = Abstract3DSeries.MeshCube;
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "meshpyramid"
|
||||
StateChangeScript {
|
||||
name: "doPyramid"
|
||||
script: {
|
||||
console.log("Do the pyramid");
|
||||
scatterSeries.mesh = Abstract3DSeries.MeshPyramid;
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "meshpoint"
|
||||
StateChangeScript {
|
||||
name: "doPoint"
|
||||
script: {
|
||||
console.log("Do the point");
|
||||
scatterSeries.mesh = Abstract3DSeries.MeshPoint;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.ThemeQt
|
||||
colorStyle: Theme3D.ColorStyleRangeGradient
|
||||
baseGradients: surfaceGradient
|
||||
|
||||
ColorGradient {
|
||||
id: surfaceGradient
|
||||
ColorGradientStop { position: 1.0; color: "red" }
|
||||
ColorGradientStop { position: 0.0; color: "blue" }
|
||||
}
|
||||
}
|
||||
|
||||
Surface3DSeries {
|
||||
id: surfaceSeries
|
||||
dataProxy.onArrayReset: tests.dataPoints = dataProxy.columnCount * dataProxy.rowCount
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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" }
|
||||
}
|
||||
}
|
||||
Scatter3DSeries {
|
||||
id: scatterSeries
|
||||
dataProxy.onArrayReset: tests.dataPoints = dataProxy.itemCount
|
||||
itemSize: 0.1
|
||||
}
|
||||
onCurrentFpsChanged: {
|
||||
tests.currentFps = currentFps
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue