summaryrefslogtreecommitdiffstats
path: root/tests/manual/volumetrictest
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/volumetrictest')
-rw-r--r--tests/manual/volumetrictest/cubeFilledFlat.obj54
-rw-r--r--tests/manual/volumetrictest/logo.pngbin0 -> 2205 bytes
-rw-r--r--tests/manual/volumetrictest/logo_no_padding.pngbin0 -> 2278 bytes
-rw-r--r--tests/manual/volumetrictest/main.cpp171
-rw-r--r--tests/manual/volumetrictest/volumetrictest.cpp719
-rw-r--r--tests/manual/volumetrictest/volumetrictest.h82
-rw-r--r--tests/manual/volumetrictest/volumetrictest.pro14
-rw-r--r--tests/manual/volumetrictest/volumetrictest.qrc7
8 files changed, 1047 insertions, 0 deletions
diff --git a/tests/manual/volumetrictest/cubeFilledFlat.obj b/tests/manual/volumetrictest/cubeFilledFlat.obj
new file mode 100644
index 00000000..108cf7ac
--- /dev/null
+++ b/tests/manual/volumetrictest/cubeFilledFlat.obj
@@ -0,0 +1,54 @@
+# Blender v2.66 (sub 0) OBJ File: 'cube_filled.blend'
+# www.blender.org
+o Cube
+v -1.000000 -1.000000 1.000000
+v -1.000000 -1.000000 -1.000000
+v 1.000000 -1.000000 -1.000000
+v 1.000000 -1.000000 1.000000
+v -1.000000 1.000000 1.000000
+v -1.000000 1.000000 -1.000000
+v 1.000000 1.000000 -1.000000
+v 1.000000 1.000000 1.000000
+vt 0.666667 0.332314
+vt 0.334353 0.333333
+vt 0.665647 0.000000
+vt 0.001020 0.333333
+vt 0.000000 0.001020
+vt 0.333333 0.332314
+vt 0.333333 0.665647
+vt 0.001019 0.666667
+vt 0.000000 0.334353
+vt 0.334353 0.666667
+vt 0.333333 0.334353
+vt 0.665647 0.333333
+vt 0.333333 0.667686
+vt 0.665647 0.666667
+vt 0.666667 0.998980
+vt 0.667686 0.333333
+vt 0.666667 0.001019
+vt 0.998980 0.000000
+vt 0.333333 0.001019
+vt 0.332314 0.000000
+vt 0.332314 0.333333
+vt 0.666667 0.665647
+vt 0.334353 1.000000
+vt 1.000000 0.332314
+vn -1.000000 0.000000 0.000000
+vn 0.000000 0.000000 -1.000000
+vn 1.000000 -0.000000 0.000000
+vn 0.000000 0.000000 1.000000
+vn 0.000000 1.000000 0.000000
+vn -0.000000 -1.000000 -0.000000
+s off
+f 5/1/1 6/2/1 1/3/1
+f 6/4/2 7/5/2 2/6/2
+f 7/7/3 8/8/3 4/9/3
+f 8/10/4 5/11/4 1/12/4
+f 8/13/5 7/14/5 6/15/5
+f 2/16/6 3/17/6 4/18/6
+f 6/2/1 2/19/1 1/3/1
+f 7/5/2 3/20/2 2/6/2
+f 3/21/3 7/7/3 4/9/3
+f 4/22/4 8/10/4 1/12/4
+f 5/23/5 8/13/5 6/15/5
+f 1/24/6 2/16/6 4/18/6
diff --git a/tests/manual/volumetrictest/logo.png b/tests/manual/volumetrictest/logo.png
new file mode 100644
index 00000000..1e7ed4cf
--- /dev/null
+++ b/tests/manual/volumetrictest/logo.png
Binary files differ
diff --git a/tests/manual/volumetrictest/logo_no_padding.png b/tests/manual/volumetrictest/logo_no_padding.png
new file mode 100644
index 00000000..714234aa
--- /dev/null
+++ b/tests/manual/volumetrictest/logo_no_padding.png
Binary files differ
diff --git a/tests/manual/volumetrictest/main.cpp b/tests/manual/volumetrictest/main.cpp
new file mode 100644
index 00000000..0c3c2852
--- /dev/null
+++ b/tests/manual/volumetrictest/main.cpp
@@ -0,0 +1,171 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Data Visualization module.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+******************************************************************************/
+
+#include "volumetrictest.h"
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QRadioButton>
+#include <QtWidgets/QSlider>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QPushButton>
+#include <QtGui/QScreen>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ //Q3DScatter *graph = new Q3DScatter();
+ //Q3DSurface *graph = new Q3DSurface();
+ Q3DBars *graph = new Q3DBars();
+ QWidget *container = QWidget::createWindowContainer(graph);
+
+ QSize screenSize = graph->screen()->size();
+ container->setMinimumSize(QSize(screenSize.width() / 4, screenSize.height() / 4));
+ container->setMaximumSize(screenSize);
+ container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ container->setFocusPolicy(Qt::StrongFocus);
+
+ QWidget *widget = new QWidget;
+ QHBoxLayout *hLayout = new QHBoxLayout(widget);
+ QVBoxLayout *vLayout = new QVBoxLayout();
+ hLayout->addWidget(container, 1);
+ hLayout->addLayout(vLayout);
+
+ widget->setWindowTitle(QStringLiteral("Volumetric TEST"));
+ widget->resize(QSize(screenSize.width() / 1.5, screenSize.height() / 1.5));
+
+ QCheckBox *sliceXCheckBox = new QCheckBox(widget);
+ sliceXCheckBox->setText(QStringLiteral("Slice volume on X axis"));
+ sliceXCheckBox->setChecked(false);
+ QCheckBox *sliceYCheckBox = new QCheckBox(widget);
+ sliceYCheckBox->setText(QStringLiteral("Slice volume on Y axis"));
+ sliceYCheckBox->setChecked(false);
+ QCheckBox *sliceZCheckBox = new QCheckBox(widget);
+ sliceZCheckBox->setText(QStringLiteral("Slice volume on Z axis"));
+ sliceZCheckBox->setChecked(false);
+
+ QSlider *sliceXSlider = new QSlider(Qt::Horizontal, widget);
+ sliceXSlider->setMinimum(0);
+ sliceXSlider->setMaximum(1024);
+ sliceXSlider->setValue(512);
+ sliceXSlider->setEnabled(true);
+ QSlider *sliceYSlider = new QSlider(Qt::Horizontal, widget);
+ sliceYSlider->setMinimum(0);
+ sliceYSlider->setMaximum(1024);
+ sliceYSlider->setValue(512);
+ sliceYSlider->setEnabled(true);
+ QSlider *sliceZSlider = new QSlider(Qt::Horizontal, widget);
+ sliceZSlider->setMinimum(0);
+ sliceZSlider->setMaximum(1024);
+ sliceZSlider->setValue(512);
+ sliceZSlider->setEnabled(true);
+
+ QLabel *fpsLabel = new QLabel(QStringLiteral("Fps: "), widget);
+
+ QLabel *sliceImageXLabel = new QLabel(widget);
+ QLabel *sliceImageYLabel = new QLabel(widget);
+ QLabel *sliceImageZLabel = new QLabel(widget);
+ sliceImageXLabel->setMinimumSize(QSize(200, 100));
+ sliceImageYLabel->setMinimumSize(QSize(200, 200));
+ sliceImageZLabel->setMinimumSize(QSize(200, 100));
+ sliceImageXLabel->setMaximumSize(QSize(200, 100));
+ sliceImageYLabel->setMaximumSize(QSize(200, 200));
+ sliceImageZLabel->setMaximumSize(QSize(200, 100));
+ sliceImageXLabel->setFrameShape(QFrame::Box);
+ sliceImageYLabel->setFrameShape(QFrame::Box);
+ sliceImageZLabel->setFrameShape(QFrame::Box);
+ sliceImageXLabel->setScaledContents(true);
+ sliceImageYLabel->setScaledContents(true);
+ sliceImageZLabel->setScaledContents(true);
+
+ QPushButton *testSubTextureSetting = new QPushButton(widget);
+ testSubTextureSetting->setText(QStringLiteral("Test subtexture settings"));
+
+ QLabel *rangeSliderLabel = new QLabel(QStringLiteral("Adjust ranges:"), widget);
+
+ QSlider *rangeXSlider = new QSlider(Qt::Horizontal, widget);
+ rangeXSlider->setMinimum(0);
+ rangeXSlider->setMaximum(1024);
+ rangeXSlider->setValue(512);
+ rangeXSlider->setEnabled(true);
+ QSlider *rangeYSlider = new QSlider(Qt::Horizontal, widget);
+ rangeYSlider->setMinimum(0);
+ rangeYSlider->setMaximum(1024);
+ rangeYSlider->setValue(512);
+ rangeYSlider->setEnabled(true);
+ QSlider *rangeZSlider = new QSlider(Qt::Horizontal, widget);
+ rangeZSlider->setMinimum(0);
+ rangeZSlider->setMaximum(1024);
+ rangeZSlider->setValue(512);
+ rangeZSlider->setEnabled(true);
+
+ QPushButton *testBoundsSetting = new QPushButton(widget);
+ testBoundsSetting->setText(QStringLiteral("Test data bounds"));
+
+ vLayout->addWidget(fpsLabel);
+ vLayout->addWidget(sliceXCheckBox);
+ vLayout->addWidget(sliceXSlider);
+ vLayout->addWidget(sliceImageXLabel);
+ vLayout->addWidget(sliceYCheckBox);
+ vLayout->addWidget(sliceYSlider);
+ vLayout->addWidget(sliceImageYLabel);
+ vLayout->addWidget(sliceZCheckBox);
+ vLayout->addWidget(sliceZSlider);
+ vLayout->addWidget(sliceImageZLabel);
+ vLayout->addWidget(rangeSliderLabel);
+ vLayout->addWidget(rangeXSlider);
+ vLayout->addWidget(rangeYSlider);
+ vLayout->addWidget(rangeZSlider);
+ vLayout->addWidget(testBoundsSetting);
+ vLayout->addWidget(testSubTextureSetting, 1, Qt::AlignTop);
+
+ VolumetricModifier *modifier = new VolumetricModifier(graph);
+ modifier->setFpsLabel(fpsLabel);
+ modifier->setSliceLabels(sliceImageXLabel, sliceImageYLabel, sliceImageZLabel);
+
+ QObject::connect(sliceXCheckBox, &QCheckBox::stateChanged, modifier,
+ &VolumetricModifier::sliceX);
+ QObject::connect(sliceYCheckBox, &QCheckBox::stateChanged, modifier,
+ &VolumetricModifier::sliceY);
+ QObject::connect(sliceZCheckBox, &QCheckBox::stateChanged, modifier,
+ &VolumetricModifier::sliceZ);
+ QObject::connect(sliceXSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustSliceX);
+ QObject::connect(sliceYSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustSliceY);
+ QObject::connect(sliceZSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustSliceZ);
+ QObject::connect(testSubTextureSetting, &QPushButton::clicked, modifier,
+ &VolumetricModifier::testSubtextureSetting);
+ QObject::connect(rangeXSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustRangeX);
+ QObject::connect(rangeYSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustRangeY);
+ QObject::connect(rangeZSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustRangeZ);
+ QObject::connect(testBoundsSetting, &QPushButton::clicked, modifier,
+ &VolumetricModifier::testBoundsSetting);
+
+ widget->show();
+ return app.exec();
+}
diff --git a/tests/manual/volumetrictest/volumetrictest.cpp b/tests/manual/volumetrictest/volumetrictest.cpp
new file mode 100644
index 00000000..e124c6ad
--- /dev/null
+++ b/tests/manual/volumetrictest/volumetrictest.cpp
@@ -0,0 +1,719 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Data Visualization module.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+******************************************************************************/
+
+#include "volumetrictest.h"
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/qvalue3daxis.h>
+#include <QtDataVisualization/q3dscene.h>
+#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/q3dtheme.h>
+#include <QtDataVisualization/qcustom3dlabel.h>
+#include <QtCore/qmath.h>
+#include <QtGui/QRgb>
+#include <QtGui/QImage>
+#include <QtWidgets/QLabel>
+#include <QtCore/QDebug>
+
+using namespace QtDataVisualization;
+
+const int imageCount = 512;
+const float xMiddle = 100.0f;
+const float yMiddle = 2.5f;
+const float zMiddle = 100.0f;
+const float xRange = 40.0f;
+const float yRange = 7.5f;
+const float zRange = 20.0f;
+
+VolumetricModifier::VolumetricModifier(QAbstract3DGraph *scatter)
+ : m_graph(scatter),
+ m_volumeItem(0),
+ m_volumeItem2(0),
+ m_volumeItem3(0),
+ m_sliceIndexX(0),
+ m_sliceIndexY(0),
+ m_sliceIndexZ(0)
+{
+ m_graph->activeTheme()->setType(Q3DTheme::ThemeQt);
+ //m_graph->activeTheme()->setType(Q3DTheme::ThemeIsabelle);
+ m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityNone);
+ m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
+ m_graph->setOrthoProjection(true);
+ //m_graph->scene()->activeCamera()->setTarget(QVector3D(-2.0f, 1.0f, 2.0f));
+ m_scatterGraph = qobject_cast<Q3DScatter *>(m_graph);
+ m_surfaceGraph = qobject_cast<Q3DSurface *>(m_graph);
+ m_barGraph = qobject_cast<Q3DBars *>(m_graph);
+ if (m_scatterGraph) {
+ m_scatterGraph->axisX()->setRange(xMiddle - xRange, xMiddle + xRange);
+ m_scatterGraph->axisX()->setSegmentCount(8);
+ m_scatterGraph->axisY()->setRange(yMiddle - yRange, yMiddle + yRange);
+ m_scatterGraph->axisY()->setSegmentCount(3);
+ m_scatterGraph->axisZ()->setRange(zMiddle - zRange, zMiddle + zRange);
+ m_scatterGraph->axisZ()->setSegmentCount(8);
+ } else if (m_surfaceGraph) {
+ m_surfaceGraph->axisX()->setRange(xMiddle - xRange, xMiddle + xRange);
+ m_surfaceGraph->axisX()->setSegmentCount(8);
+ m_surfaceGraph->axisY()->setRange(yMiddle - yRange, yMiddle + yRange);
+ m_surfaceGraph->axisY()->setSegmentCount(3);
+ m_surfaceGraph->axisZ()->setRange(zMiddle - zRange, zMiddle + zRange);
+ m_surfaceGraph->axisZ()->setSegmentCount(8);
+ } else if (m_barGraph) {
+ QStringList rowLabels;
+ QStringList columnLabels;
+ for (int i = 0; i < xMiddle + xRange; i++) {
+ if (i % 5 == 0)
+ columnLabels << QString::number(i);
+ else
+ columnLabels << QString();
+ }
+ for (int i = 0; i < zMiddle + zRange; i++) {
+ if (i % 5 == 0)
+ rowLabels << QString::number(i);
+ else
+ rowLabels << QString();
+ }
+
+ QBar3DSeries *series = new QBar3DSeries;
+ QBarDataArray *array = new QBarDataArray();
+ array->reserve(zRange * 2 + 1);
+ for (int i = 0; i < zRange * 2 + 1; i++)
+ array->append(new QBarDataRow(xRange * 2 + 1));
+
+ series->dataProxy()->resetArray(array, rowLabels, columnLabels);
+ m_barGraph->addSeries(series);
+
+ m_barGraph->columnAxis()->setRange(xMiddle - xRange, xMiddle + xRange);
+ m_barGraph->valueAxis()->setRange(yMiddle - yRange, yMiddle + yRange);
+ m_barGraph->rowAxis()->setRange(zMiddle - zRange, zMiddle + zRange);
+ //m_barGraph->setReflection(true);
+ }
+ m_graph->activeTheme()->setBackgroundEnabled(false);
+
+ createVolume();
+ createAnotherVolume();
+ createYetAnotherVolume();
+
+// m_volumeItem->setUseHighDefShader(false);
+// m_volumeItem2->setUseHighDefShader(false);
+// m_volumeItem3->setUseHighDefShader(false);
+
+ m_volumeItem->setScalingAbsolute(false);
+ m_volumeItem2->setScalingAbsolute(false);
+ m_volumeItem3->setScalingAbsolute(false);
+ m_volumeItem->setPositionAbsolute(false);
+ m_volumeItem2->setPositionAbsolute(false);
+ m_volumeItem3->setPositionAbsolute(false);
+
+
+ m_plainItem = new QCustom3DItem;
+ QImage texture(2, 2, QImage::Format_ARGB32);
+ texture.fill(QColor(200, 200, 200, 130));
+ m_plainItem->setMeshFile(QStringLiteral(":/mesh"));
+ m_plainItem->setTextureImage(texture);
+ m_plainItem->setRotation(m_volumeItem->rotation());
+ m_plainItem->setPosition(QVector3D(xMiddle + xRange / 2.0f, yMiddle + yRange / 2.0f, zMiddle));
+ m_plainItem->setScaling(QVector3D(20.0f, 5.0f, 10.0f));
+ m_plainItem->setScalingAbsolute(false);
+
+ m_graph->addCustomItem(m_volumeItem);
+ m_graph->addCustomItem(m_volumeItem2);
+ m_graph->addCustomItem(m_volumeItem3);
+ m_graph->addCustomItem(m_plainItem);
+ //m_graph->setMeasureFps(true);
+
+ // Create label to cut through the volume 3
+ QCustom3DLabel *label = new QCustom3DLabel;
+ label->setText(QStringLiteral("FOO BAR - FOO BAR - FOO BAR"));
+ QFont font;
+ font.setPixelSize(100);
+ label->setFont(font);
+ label->setScaling(QVector3D(2.0f, 2.0f, 0.0f));
+ label->setRotationAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), 45.0f);
+ label->setPosition(m_volumeItem3->position());
+ label->setPositionAbsolute(false);
+ label->setScalingAbsolute(true);
+
+ m_graph->addCustomItem(label);
+
+ QObject::connect(m_graph, &QAbstract3DGraph::currentFpsChanged, this,
+ &VolumetricModifier::handleFpsChange);
+// QObject::connect(m_graph->scene(), &Q3DScene::viewportChanged, this,
+// &VolumetricModifier::handleFpsChange);
+}
+
+VolumetricModifier::~VolumetricModifier()
+{
+ delete m_graph;
+}
+
+void VolumetricModifier::setFpsLabel(QLabel *fpsLabel)
+{
+ m_fpsLabel = fpsLabel;
+}
+
+void VolumetricModifier::sliceX(int enabled)
+{
+ m_volumeItem->setSliceIndexX(enabled ? m_sliceIndexX : -1);
+ m_volumeItem2->setSliceIndexX(enabled ? m_sliceIndexX : -1);
+}
+
+void VolumetricModifier::sliceY(int enabled)
+{
+ m_volumeItem->setSliceIndexY(enabled ? m_sliceIndexY : -1);
+ m_volumeItem2->setSliceIndexY(enabled ? m_sliceIndexY : -1);
+}
+
+void VolumetricModifier::sliceZ(int enabled)
+{
+ m_volumeItem->setSliceIndexZ(enabled ? m_sliceIndexZ : -1);
+ m_volumeItem2->setSliceIndexZ(enabled ? m_sliceIndexZ : -1);
+}
+
+void VolumetricModifier::adjustSliceX(int value)
+{
+ m_sliceIndexX = int(float(value) / (1024.0f / m_volumeItem->textureWidth()));
+ if (m_sliceIndexX == m_volumeItem->textureWidth())
+ m_sliceIndexX--;
+ qDebug() << "m_sliceIndexX:" << m_sliceIndexX;
+ if (m_volumeItem->sliceIndexX() != -1) {
+ m_volumeItem->setSliceIndexX(m_sliceIndexX);
+ m_volumeItem2->setSliceIndexX(m_sliceIndexX);
+ }
+ m_sliceLabelX->setPixmap(QPixmap::fromImage(
+ m_volumeItem->renderSlice(Qt::XAxis, m_sliceIndexX)));
+
+}
+
+void VolumetricModifier::adjustSliceY(int value)
+{
+ m_sliceIndexY = int(float(value) / (1024.0f / m_volumeItem->textureHeight()));
+ if (m_sliceIndexY == m_volumeItem->textureHeight())
+ m_sliceIndexY--;
+ qDebug() << "m_sliceIndexY:" << m_sliceIndexY;
+ if (m_volumeItem->sliceIndexY() != -1) {
+ m_volumeItem->setSliceIndexY(m_sliceIndexY);
+ m_volumeItem2->setSliceIndexY(m_sliceIndexY);
+ }
+ m_sliceLabelY->setPixmap(QPixmap::fromImage(
+ m_volumeItem->renderSlice(Qt::YAxis, m_sliceIndexY)));
+}
+
+void VolumetricModifier::adjustSliceZ(int value)
+{
+ m_sliceIndexZ = int(float(value) / (1024.0f / m_volumeItem->textureDepth()));
+ if (m_sliceIndexZ == m_volumeItem->textureDepth())
+ m_sliceIndexZ--;
+ qDebug() << "m_sliceIndexZ:" << m_sliceIndexZ;
+ if (m_volumeItem->sliceIndexZ() != -1) {
+ m_volumeItem->setSliceIndexZ(m_sliceIndexZ);
+ m_volumeItem2->setSliceIndexZ(m_sliceIndexZ);
+ }
+ m_sliceLabelZ->setPixmap(QPixmap::fromImage(
+ m_volumeItem->renderSlice(Qt::ZAxis, m_sliceIndexZ)));
+}
+
+void VolumetricModifier::handleFpsChange()
+{
+ const QString fpsFormat = QStringLiteral("Fps: %1");
+ int fps10 = int(m_graph->currentFps() * 10.0);
+ m_fpsLabel->setText(fpsFormat.arg(QString::number(qreal(fps10) / 10.0)));
+// const QString sceneDimensionsFormat = QStringLiteral("%1 x %2");
+// m_fpsLabel->setText(sceneDimensionsFormat
+// .arg(m_graph->scene()->viewport().width())
+ // .arg(m_graph->scene()->viewport().height()));
+}
+
+void VolumetricModifier::testSubtextureSetting()
+{
+ // Setting the rendered Slice as subtexture should result in identical volume
+ QVector<uchar> dataBefore = *m_volumeItem->textureData();
+ dataBefore[0] = dataBefore.at(0); // Make sure we are detached
+
+ checkRenderCase(1, Qt::XAxis, 56, dataBefore, m_volumeItem);
+ checkRenderCase(2, Qt::YAxis, 64, dataBefore, m_volumeItem);
+ checkRenderCase(3, Qt::ZAxis, 87, dataBefore, m_volumeItem);
+
+ checkRenderCase(4, Qt::XAxis, 0, dataBefore, m_volumeItem);
+ checkRenderCase(5, Qt::YAxis, 0, dataBefore, m_volumeItem);
+ checkRenderCase(6, Qt::ZAxis, 0, dataBefore, m_volumeItem);
+
+ checkRenderCase(7, Qt::XAxis, m_volumeItem->textureWidth() - 1, dataBefore, m_volumeItem);
+ checkRenderCase(8, Qt::YAxis, m_volumeItem->textureHeight() - 1, dataBefore, m_volumeItem);
+ checkRenderCase(9, Qt::ZAxis, m_volumeItem->textureDepth() - 1, dataBefore, m_volumeItem);
+
+ dataBefore = *m_volumeItem2->textureData();
+ dataBefore[0] = dataBefore.at(0); // Make sure we are detached
+
+ checkRenderCase(11, Qt::XAxis, 56, dataBefore, m_volumeItem2);
+ checkRenderCase(12, Qt::YAxis, 64, dataBefore, m_volumeItem2);
+ checkRenderCase(13, Qt::ZAxis, 87, dataBefore, m_volumeItem2);
+
+ checkRenderCase(14, Qt::XAxis, 0, dataBefore, m_volumeItem2);
+ checkRenderCase(15, Qt::YAxis, 0, dataBefore, m_volumeItem2);
+ checkRenderCase(16, Qt::ZAxis, 0, dataBefore, m_volumeItem2);
+
+ checkRenderCase(17, Qt::XAxis, m_volumeItem2->textureWidth() - 1, dataBefore, m_volumeItem2);
+ checkRenderCase(18, Qt::YAxis, m_volumeItem2->textureHeight() - 1, dataBefore, m_volumeItem2);
+ checkRenderCase(19, Qt::ZAxis, m_volumeItem2->textureDepth() - 1, dataBefore, m_volumeItem2);
+
+ // Do some visible swaps on volume 3
+ QImage slice = m_volumeItem3->renderSlice(Qt::XAxis, 144);
+ slice = slice.mirrored();
+ m_volumeItem3->setSubTextureData(Qt::XAxis, 144, slice);
+
+ slice = m_volumeItem3->renderSlice(Qt::YAxis, 80);
+ slice = slice.mirrored();
+ m_volumeItem3->setSubTextureData(Qt::YAxis, 80, slice);
+
+ slice = m_volumeItem3->renderSlice(Qt::ZAxis, 190);
+ slice = slice.mirrored(true, false);
+ m_volumeItem3->setSubTextureData(Qt::ZAxis, 190, slice);
+}
+
+void VolumetricModifier::adjustRangeX(int value)
+{
+ float adjustment = float(value - 512) / 10.0f;
+ if (m_scatterGraph)
+ m_scatterGraph->axisX()->setRange(xMiddle + adjustment - xRange, xMiddle + adjustment + xRange);
+ if (m_surfaceGraph)
+ m_surfaceGraph->axisX()->setRange(xMiddle + adjustment - xRange, xMiddle + adjustment + xRange);
+ if (m_barGraph)
+ m_barGraph->columnAxis()->setRange(xMiddle + adjustment - xRange, xMiddle + adjustment + xRange);
+}
+
+void VolumetricModifier::adjustRangeY(int value)
+{
+ float adjustment = float(value - 512) / 10.0f;
+ if (m_scatterGraph)
+ m_scatterGraph->axisY()->setRange(yMiddle + adjustment - yRange, yMiddle + adjustment + yRange);
+ if (m_surfaceGraph)
+ m_surfaceGraph->axisY()->setRange(yMiddle + adjustment - yRange, yMiddle + adjustment + yRange);
+ if (m_barGraph)
+ m_barGraph->valueAxis()->setRange(yMiddle + adjustment - yRange, yMiddle + adjustment + yRange);
+}
+
+void VolumetricModifier::adjustRangeZ(int value)
+{
+ float adjustment = float(value - 512) / 10.0f;
+ if (m_scatterGraph)
+ m_scatterGraph->axisZ()->setRange(zMiddle + adjustment - zRange, zMiddle + adjustment + zRange);
+ if (m_surfaceGraph)
+ m_surfaceGraph->axisZ()->setRange(zMiddle + adjustment - zRange, zMiddle + adjustment + zRange);
+ if (m_barGraph)
+ m_barGraph->rowAxis()->setRange(zMiddle + adjustment - zRange, zMiddle + adjustment + zRange);
+}
+
+void VolumetricModifier::testBoundsSetting()
+{
+ static QVector3D scaling1 = m_volumeItem->scaling();
+ static QVector3D scaling2 = m_volumeItem2->scaling();
+ static QVector3D scaling3 = m_volumeItem3->scaling();
+ static QVector3D scaleVector = QVector3D(0.5f, 0.3f, 0.2f);
+
+ if (m_volumeItem->isScalingAbsolute()) {
+ m_volumeItem->setScalingAbsolute(false);
+ m_volumeItem2->setScalingAbsolute(false);
+ m_volumeItem3->setScalingAbsolute(false);
+
+ m_volumeItem->setScaling(scaling1);
+ m_volumeItem2->setScaling(scaling2);
+ m_volumeItem3->setScaling(scaling3);
+ } else {
+ m_volumeItem->setScalingAbsolute(true);
+ m_volumeItem2->setScalingAbsolute(true);
+ m_volumeItem3->setScalingAbsolute(true);
+
+ m_volumeItem->setScaling(scaleVector);
+ m_volumeItem2->setScaling(scaleVector);
+ m_volumeItem3->setScaling(scaleVector);
+ }
+}
+
+void VolumetricModifier::checkRenderCase(int id, Qt::Axis axis, int index,
+ const QVector<uchar> &dataBefore,
+ QCustom3DVolume *volumeItem)
+{
+ QImage slice = volumeItem->renderSlice(axis, index);
+ volumeItem->setSubTextureData(axis, index, slice);
+
+ if (dataBefore == *volumeItem->textureData())
+ qDebug() << __FUNCTION__ << "Case:" << id << "Vectors identical";
+ else
+ qDebug() << __FUNCTION__ << "Case:" << id << "BUG: VECTORS DIFFER!";
+}
+
+void VolumetricModifier::createVolume()
+{
+ m_volumeItem = new QCustom3DVolume;
+ m_volumeItem->setTextureFormat(QImage::Format_ARGB32);
+ m_volumeItem->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 20.0f));
+ m_volumeItem->setPosition(QVector3D(xMiddle - (xRange / 2.0f), yMiddle + (yRange / 2.0f), zMiddle));
+ //m_volumeItem->setPosition(QVector3D(xMiddle, yMiddle, zMiddle));
+ m_volumeItem->setDrawSliceFrames(true);
+ m_volumeItem->setDrawSlices(true);
+
+ QImage logo;
+ logo.load(QStringLiteral(":/logo_no_padding.png"));
+ //logo.load(QStringLiteral(":/logo.png"));
+ qDebug() << "image dimensions:" << logo.width() << logo.height()
+ << logo.byteCount() << (logo.width() * logo.height())
+ << logo.bytesPerLine();
+
+ QVector<QImage *> imageArray(imageCount);
+ for (int i = 0; i < imageCount; i++) {
+ QImage *newImage = new QImage(logo);
+ imageArray[i] = newImage;
+ }
+
+ m_volumeItem->createTextureData(imageArray);
+
+ for (int i = 0; i < imageCount; i++)
+ delete imageArray[i];
+
+ m_sliceIndexX = m_volumeItem->textureWidth() / 2;
+ m_sliceIndexY = m_volumeItem->textureWidth() / 2;
+ m_sliceIndexZ = m_volumeItem->textureWidth() / 2;
+
+ QVector<QRgb> colorTable = m_volumeItem->colorTable();
+
+ // Hack some alpha to the picture
+ for (int i = 0; i < colorTable.size(); i++) {
+ if (qAlpha(colorTable.at(i)) > 0) {
+ colorTable[i] = qRgba(qRed(colorTable.at(i)),
+ qGreen(colorTable.at(i)),
+ qBlue(colorTable.at(i)),
+ 50);
+ }
+ }
+
+ colorTable.append(qRgba(0, 0, 0, 0));
+ colorTable.append(qRgba(255, 0, 0, 255));
+ colorTable.append(qRgba(0, 255, 0, 255));
+ colorTable.append(qRgba(0, 0, 255, 255));
+
+ m_volumeItem->setColorTable(colorTable);
+ int alphaIndex = colorTable.size() - 4;
+ int redIndex = colorTable.size() - 3;
+ int greenIndex = colorTable.size() - 2;
+ int blueIndex = colorTable.size() - 1;
+ int width = m_volumeItem->textureDataWidth();
+ int height = m_volumeItem->textureHeight();
+ int depth = m_volumeItem->textureDepth();
+ int frameSize = width * height;
+ qDebug() << width << height << depth << m_volumeItem->textureData()->size();
+ m_volumeItem->setScaling(QVector3D(xRange, yRange, zRange) / 2.0f);
+
+ uchar *data = m_volumeItem->textureData()->data();
+ uchar *p = data;
+
+ // Change one picture using subtexture replacement
+ QImage flipped = logo.mirrored();
+ m_volumeItem->setSubTextureData(Qt::ZAxis, 100, flipped);
+
+ // Clean up the two extra pixels
+ p = data + width - 1;
+ for (int k = 0; k < depth; k++) {
+ for (int j = 0; j < height; j++) {
+ *p = alphaIndex;
+ p += width;
+ }
+ }
+ p = data + width - 2;
+ for (int k = 0; k < depth; k++) {
+ for (int j = 0; j < height; j++) {
+ *p = alphaIndex;
+ p += width;
+ }
+ }
+ // Red first subtexture
+ p = data;
+ for (int j = 0; j < height; j++) {
+ for (int i = 0; i < width; i++) {
+ *p = redIndex;
+ p++;
+ }
+ }
+
+ // Red last subtexture
+// p = data + frameSize * (imageCount - 1);
+// for (int j = 0; j < height; j++) {
+// for (int i = 0; i < width; i++) {
+// *p = redIndex;
+// p++;
+// }
+// }
+
+// // Blue second to last subtexture
+// p = data + frameSize * (imageCount - 2);
+// for (int j = 0; j < height; j++) {
+// for (int i = 0; i < width; i++) {
+// *p = blueIndex;
+// p++;
+// }
+// }
+
+ // Blue x = 0
+// p = data;
+// for (int k = 0; k < depth; k++) {
+// for (int j = 0; j < height; j++) {
+// *p = blueIndex;
+// p += width;
+// }
+// }
+
+ // Blue x = max
+ p = data + width - 1;
+ for (int k = 0; k < depth; k++) {
+ for (int j = 0; j < height; j++) {
+ *p = blueIndex;
+ p += width;
+ }
+ }
+ // green x = max - 1
+ p = data + width - 2;
+ for (int k = 0; k < depth; k++) {
+ for (int j = 0; j < height; j++) {
+ *p = greenIndex;
+ p += width;
+ }
+ }
+
+ // Green y = 0
+ p = data;
+ for (int k = 0; k < depth; k++) {
+ for (int i = 0; i < width; i++) {
+ *p = greenIndex;
+ p++;
+ }
+ p += (frameSize - width);
+ }
+
+ // Green y = max
+// p = data + frameSize - width;
+// for (int k = 0; k < depth; k++) {
+// for (int i = 0; i < width; i++) {
+// *p = greenIndex;
+// p++;
+// }
+// p += (frameSize - width);
+// }
+}
+
+void VolumetricModifier::createAnotherVolume()
+{
+ m_volumeItem2 = new QCustom3DVolume;
+ m_volumeItem2->setTextureFormat(QImage::Format_ARGB32);
+ m_volumeItem2->setPosition(QVector3D(xMiddle + (xRange / 2.0f), yMiddle - (yRange / 2.0f), zMiddle));
+
+ QImage logo;
+ logo.load(QStringLiteral(":/logo_no_padding.png"));
+ //logo.load(QStringLiteral(":/logo.png"));
+ logo = logo.convertToFormat(QImage::Format_ARGB8555_Premultiplied);
+ qDebug() << "second image dimensions:" << logo.width() << logo.height()
+ << logo.byteCount() << (logo.width() * logo.height())
+ << logo.bytesPerLine();
+
+ logo.save("d:/qt/goobar.png");
+
+ QVector<QImage *> imageArray(imageCount);
+ for (int i = 0; i < imageCount; i++) {
+ QImage *newImage = new QImage(logo);
+ imageArray[i] = newImage;
+ }
+
+ m_volumeItem2->createTextureData(imageArray);
+
+ for (int i = 0; i < imageCount; i++)
+ delete imageArray[i];
+
+ m_sliceIndexX = m_volumeItem2->textureWidth() / 2;
+ m_sliceIndexY = m_volumeItem2->textureWidth() / 2;
+ m_sliceIndexZ = m_volumeItem2->textureWidth() / 2;
+
+ int width = m_volumeItem2->textureWidth();
+ int height = m_volumeItem2->textureHeight();
+ int depth = m_volumeItem2->textureDepth();
+ qDebug() << width << height << depth << m_volumeItem2->textureData()->size();
+ m_volumeItem2->setScaling(QVector3D(float(width) / float(depth) * xRange * 2.0f,
+ float(height) / float(depth) * yRange * 2.0f,
+ zRange * 2.0f));
+
+ // Change one picture using subtexture replacement
+ QImage flipped = logo.mirrored();
+ m_volumeItem2->setSubTextureData(Qt::ZAxis, 100, flipped);
+ //m_volumeItem2->setAlphaMultiplier(0.2f);
+ m_volumeItem2->setPreserveOpacity(false);
+}
+
+void VolumetricModifier::createYetAnotherVolume()
+{
+ m_volumeItem3 = new QCustom3DVolume;
+ m_volumeItem3->setTextureFormat(QImage::Format_Indexed8);
+// m_volumeItem2->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 10.0f));
+ m_volumeItem3->setPosition(QVector3D(xMiddle - (xRange / 2.0f), yMiddle - (yRange / 2.0f), zMiddle));
+
+// m_volumeItem3->setTextureDimensions(m_volumeItem->textureDataWidth(),
+// m_volumeItem->textureHeight(),
+// m_volumeItem->textureDepth());
+ m_volumeItem3->setTextureDimensions(200, 200, 200);
+
+ QVector<uchar> *tdata = new QVector<uchar>(m_volumeItem3->textureDataWidth()
+ * m_volumeItem3->textureHeight()
+ * m_volumeItem3->textureDepth());
+ tdata->fill(0);
+ m_volumeItem3->setTextureData(tdata);
+
+ m_sliceIndexX = m_volumeItem3->textureWidth() / 2;
+ m_sliceIndexY = m_volumeItem3->textureWidth() / 2;
+ m_sliceIndexZ = m_volumeItem3->textureWidth() / 2;
+
+ QVector<QRgb> colorTable = m_volumeItem->colorTable();
+ colorTable[0] = qRgba(0, 0, 0, 0);
+ m_volumeItem3->setColorTable(colorTable);
+ int redIndex = colorTable.size() - 3;
+ int greenIndex = colorTable.size() - 2;
+ int blueIndex = colorTable.size() - 1;
+ int width = m_volumeItem3->textureDataWidth();
+ int height = m_volumeItem3->textureHeight();
+ int depth = m_volumeItem3->textureDepth();
+ int frameSize = width * height;
+ qDebug() << width << height << depth << m_volumeItem3->textureData()->size();
+ m_volumeItem3->setScaling(m_volumeItem->scaling());
+
+ uchar *data = tdata->data();
+ uchar *p = data;
+
+ // Red first subtexture
+// for (int j = 0; j < height; j++) {
+// for (int i = 0; i < width; i++) {
+// *p = redIndex;
+// p++;
+// }
+// }
+
+ // Red last subtexture
+ p = data + frameSize * (depth - 1);
+ for (int j = 0; j < height; j++) {
+ for (int i = 0; i < width; i++) {
+ *p = redIndex;
+ p++;
+ }
+ }
+
+ // green edge
+ p = data + frameSize * (depth - 1);
+ for (int i = 0; i < width; i++) {
+ *p = greenIndex;
+ p++;
+ }
+ for (int j = 2; j < height; j++) {
+ *p = greenIndex;
+ p += width - 1;
+ *p = j % 7 ? greenIndex : blueIndex;
+ p++;
+ }
+ for (int i = 0; i < width; i++) {
+ *p = greenIndex;
+ p++;
+ }
+
+// // Blue second to last subtexture
+// p = data + frameSize * (depth - 2);
+// for (int j = 0; j < height; j++) {
+// for (int i = 0; i < width; i++) {
+// *p = blueIndex;
+// p++;
+// }
+// }
+
+// // green third to last subtexture
+// p = data + frameSize * (depth - 3);
+// for (int j = 0; j < height; j++) {
+// for (int i = 0; i < width; i++) {
+// *p = greenIndex;
+// p++;
+// }
+// }
+
+ // Blue x = 0
+ p = data;
+ for (int k = 0; k < depth; k++) {
+ for (int j = 0; j < height; j++) {
+ *p = blueIndex;
+ p += width;
+ }
+ }
+
+// // Blue x = max
+// p = data + width - 1;
+// for (int k = 0; k < depth; k++) {
+// for (int j = 0; j < height; j++) {
+// *p = blueIndex;
+// p += width;
+// }
+// }
+
+ // Green y = 0
+// p = data;
+// for (int k = 0; k < depth; k++) {
+// for (int i = 0; i < width; i++) {
+// *p = greenIndex;
+// p++;
+// }
+// p += (frameSize - width);
+// }
+
+// // Green y = max
+ p = data + frameSize - width;
+ for (int k = 0; k < depth; k++) {
+ for (int i = 0; i < width; i++) {
+ *p = greenIndex;
+ p++;
+ }
+ p += (frameSize - width);
+ }
+
+
+// // Fill with alternating pixels
+// p = data;
+// for (int k = 0; k < (depth * width * height / 4); k++) {
+// *p = greenIndex;
+// p++;
+// *p = greenIndex;
+// p++;
+// *p = blueIndex;
+// p++;
+// *p = redIndex;
+// p++;
+// }
+
+
+}
+
+void VolumetricModifier::setSliceLabels(QLabel *xLabel, QLabel *yLabel, QLabel *zLabel)
+{
+ m_sliceLabelX = xLabel;
+ m_sliceLabelY = yLabel;
+ m_sliceLabelZ = zLabel;
+
+ adjustSliceX(512);
+ adjustSliceY(512);
+ adjustSliceZ(512);
+}
diff --git a/tests/manual/volumetrictest/volumetrictest.h b/tests/manual/volumetrictest/volumetrictest.h
new file mode 100644
index 00000000..69cf2010
--- /dev/null
+++ b/tests/manual/volumetrictest/volumetrictest.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Data Visualization module.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+******************************************************************************/
+
+#ifndef VOLUMETRICMODIFIER_H
+#define VOLUMETRICMODIFIER_H
+
+#include <QtDataVisualization/qcustom3dvolume.h>
+#include <QtDataVisualization/qcustom3ditem.h>
+#include <QtDataVisualization/q3dscatter.h>
+#include <QtDataVisualization/q3dsurface.h>
+#include <QtDataVisualization/q3dbars.h>
+#include <QtWidgets/QLabel>
+
+using namespace QtDataVisualization;
+
+class VolumetricModifier : public QObject
+{
+ Q_OBJECT
+public:
+ explicit VolumetricModifier(QAbstract3DGraph *scatter);
+ ~VolumetricModifier();
+
+ void setFpsLabel(QLabel *fpsLabel);
+ void setSliceLabels(QLabel *xLabel, QLabel *yLabel, QLabel *zLabel);
+
+public Q_SLOTS:
+ void sliceX(int enabled);
+ void sliceY(int enabled);
+ void sliceZ(int enabled);
+ void adjustSliceX(int value);
+ void adjustSliceY(int value);
+ void adjustSliceZ(int value);
+ void handleFpsChange();
+ void testSubtextureSetting();
+ void adjustRangeX(int value);
+ void adjustRangeY(int value);
+ void adjustRangeZ(int value);
+ void testBoundsSetting();
+
+private:
+ void createVolume();
+ void createAnotherVolume();
+ void createYetAnotherVolume();
+ void checkRenderCase(int id, Qt::Axis axis, int index, const QVector<uchar> &dataBefore,
+ QCustom3DVolume *volumeItem);
+
+ QAbstract3DGraph *m_graph;
+ Q3DScatter *m_scatterGraph;
+ Q3DSurface *m_surfaceGraph;
+ Q3DBars *m_barGraph;
+ QCustom3DVolume *m_volumeItem;
+ QCustom3DVolume *m_volumeItem2;
+ QCustom3DVolume *m_volumeItem3;
+ QCustom3DItem *m_plainItem;
+ int m_sliceIndexX;
+ int m_sliceIndexY;
+ int m_sliceIndexZ;
+ QLabel *m_fpsLabel;
+ QLabel *m_sliceLabelX;
+ QLabel *m_sliceLabelY;
+ QLabel *m_sliceLabelZ;
+};
+
+#endif
diff --git a/tests/manual/volumetrictest/volumetrictest.pro b/tests/manual/volumetrictest/volumetrictest.pro
new file mode 100644
index 00000000..df3ef0dd
--- /dev/null
+++ b/tests/manual/volumetrictest/volumetrictest.pro
@@ -0,0 +1,14 @@
+!include( ../tests.pri ) {
+ error( "Couldn't find the tests.pri file!" )
+}
+
+SOURCES += main.cpp volumetrictest.cpp
+HEADERS += volumetrictest.h
+
+QT += widgets
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
+
+RESOURCES += \
+ volumetrictest.qrc
diff --git a/tests/manual/volumetrictest/volumetrictest.qrc b/tests/manual/volumetrictest/volumetrictest.qrc
new file mode 100644
index 00000000..7cd8533b
--- /dev/null
+++ b/tests/manual/volumetrictest/volumetrictest.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>logo.png</file>
+ <file alias="mesh">cubeFilledFlat.obj</file>
+ <file>logo_no_padding.png</file>
+ </qresource>
+</RCC>