1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "volumetrictest.h"
31#include <QtDataVisualization/qbar3dseries.h>
32#include <QtDataVisualization/qvalue3daxis.h>
33#include <QtDataVisualization/q3dscene.h>
34#include <QtDataVisualization/q3dcamera.h>
35#include <QtDataVisualization/q3dtheme.h>
36#include <QtDataVisualization/qcustom3dlabel.h>
37#include <QtCore/qmath.h>
38#include <QtGui/QRgb>
39#include <QtGui/QImage>
40#include <QtWidgets/QLabel>
41#include <QtCore/QDebug>
42
43using namespace QtDataVisualization;
44
45const int imageCount = 512;
46const float xMiddle = 100.0f;
47const float yMiddle = 2.5f;
48const float zMiddle = 100.0f;
49const float xRange = 40.0f;
50const float yRange = 7.5f;
51const float zRange = 20.0f;
52
53VolumetricModifier::VolumetricModifier(QAbstract3DGraph *scatter)
54 : m_graph(scatter),
55 m_volumeItem(0),
56 m_volumeItem2(0),
57 m_volumeItem3(0),
58 m_sliceIndexX(0),
59 m_sliceIndexY(0),
60 m_sliceIndexZ(0)
61{
62 m_graph->activeTheme()->setType(Q3DTheme::ThemeQt);
63 //m_graph->activeTheme()->setType(Q3DTheme::ThemeIsabelle);
64 m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityNone);
65 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
66 m_graph->setOrthoProjection(true);
67 //m_graph->scene()->activeCamera()->setTarget(QVector3D(-2.0f, 1.0f, 2.0f));
68 m_scatterGraph = qobject_cast<Q3DScatter *>(object: m_graph);
69 m_surfaceGraph = qobject_cast<Q3DSurface *>(object: m_graph);
70 m_barGraph = qobject_cast<Q3DBars *>(object: m_graph);
71 if (m_scatterGraph) {
72 m_scatterGraph->axisX()->setRange(min: xMiddle - xRange, max: xMiddle + xRange);
73 m_scatterGraph->axisX()->setSegmentCount(8);
74 m_scatterGraph->axisY()->setRange(min: yMiddle - yRange, max: yMiddle + yRange);
75 m_scatterGraph->axisY()->setSegmentCount(3);
76 m_scatterGraph->axisZ()->setRange(min: zMiddle - zRange, max: zMiddle + zRange);
77 m_scatterGraph->axisZ()->setSegmentCount(8);
78 } else if (m_surfaceGraph) {
79 m_surfaceGraph->axisX()->setRange(min: xMiddle - xRange, max: xMiddle + xRange);
80 m_surfaceGraph->axisX()->setSegmentCount(8);
81 m_surfaceGraph->axisY()->setRange(min: yMiddle - yRange, max: yMiddle + yRange);
82 m_surfaceGraph->axisY()->setSegmentCount(3);
83 m_surfaceGraph->axisZ()->setRange(min: zMiddle - zRange, max: zMiddle + zRange);
84 m_surfaceGraph->axisZ()->setSegmentCount(8);
85 } else if (m_barGraph) {
86 QStringList rowLabels;
87 QStringList columnLabels;
88 for (int i = 0; i < xMiddle + xRange; i++) {
89 if (i % 5 == 0)
90 columnLabels << QString::number(i);
91 else
92 columnLabels << QString();
93 }
94 for (int i = 0; i < zMiddle + zRange; i++) {
95 if (i % 5 == 0)
96 rowLabels << QString::number(i);
97 else
98 rowLabels << QString();
99 }
100
101 QBar3DSeries *series = new QBar3DSeries;
102 QBarDataArray *array = new QBarDataArray();
103 array->reserve(alloc: zRange * 2 + 1);
104 for (int i = 0; i < zRange * 2 + 1; i++)
105 array->append(t: new QBarDataRow(xRange * 2 + 1));
106
107 series->dataProxy()->resetArray(newArray: array, rowLabels, columnLabels);
108 m_barGraph->addSeries(series);
109
110 m_barGraph->columnAxis()->setRange(min: xMiddle - xRange, max: xMiddle + xRange);
111 m_barGraph->valueAxis()->setRange(min: yMiddle - yRange, max: yMiddle + yRange);
112 m_barGraph->rowAxis()->setRange(min: zMiddle - zRange, max: zMiddle + zRange);
113 //m_barGraph->setReflection(true);
114 }
115 m_graph->activeTheme()->setBackgroundEnabled(false);
116
117 createVolume();
118 createAnotherVolume();
119 createYetAnotherVolume();
120
121// m_volumeItem->setUseHighDefShader(false);
122// m_volumeItem2->setUseHighDefShader(false);
123// m_volumeItem3->setUseHighDefShader(false);
124
125 m_volumeItem->setScalingAbsolute(false);
126 m_volumeItem2->setScalingAbsolute(false);
127 m_volumeItem3->setScalingAbsolute(false);
128 m_volumeItem->setPositionAbsolute(false);
129 m_volumeItem2->setPositionAbsolute(false);
130 m_volumeItem3->setPositionAbsolute(false);
131
132
133 m_plainItem = new QCustom3DItem;
134 QImage texture(2, 2, QImage::Format_ARGB32);
135 texture.fill(color: QColor(200, 200, 200, 130));
136 m_plainItem->setMeshFile(QStringLiteral(":/mesh"));
137 m_plainItem->setTextureImage(texture);
138 m_plainItem->setRotation(m_volumeItem->rotation());
139 m_plainItem->setPosition(QVector3D(xMiddle + xRange / 2.0f, yMiddle + yRange / 2.0f, zMiddle));
140 m_plainItem->setScaling(QVector3D(20.0f, 5.0f, 10.0f));
141 m_plainItem->setScalingAbsolute(false);
142
143 m_graph->addCustomItem(item: m_volumeItem);
144 m_graph->addCustomItem(item: m_volumeItem2);
145 m_graph->addCustomItem(item: m_volumeItem3);
146 m_graph->addCustomItem(item: m_plainItem);
147 //m_graph->setMeasureFps(true);
148
149 // Create label to cut through the volume 3
150 QCustom3DLabel *label = new QCustom3DLabel;
151 label->setText(QStringLiteral("FOO BAR - FOO BAR - FOO BAR"));
152 QFont font;
153 font.setPixelSize(100);
154 label->setFont(font);
155 label->setScaling(QVector3D(2.0f, 2.0f, 0.0f));
156 label->setRotationAxisAndAngle(axis: QVector3D(0.0f, 1.0f, 0.0f), angle: 45.0f);
157 label->setPosition(m_volumeItem3->position());
158 label->setPositionAbsolute(false);
159 label->setScalingAbsolute(true);
160
161 m_graph->addCustomItem(item: label);
162
163 QObject::connect(sender: m_graph, signal: &QAbstract3DGraph::currentFpsChanged, receiver: this,
164 slot: &VolumetricModifier::handleFpsChange);
165// QObject::connect(m_graph->scene(), &Q3DScene::viewportChanged, this,
166// &VolumetricModifier::handleFpsChange);
167}
168
169VolumetricModifier::~VolumetricModifier()
170{
171 delete m_graph;
172}
173
174void VolumetricModifier::setFpsLabel(QLabel *fpsLabel)
175{
176 m_fpsLabel = fpsLabel;
177}
178
179void VolumetricModifier::sliceX(int enabled)
180{
181 m_volumeItem->setSliceIndexX(enabled ? m_sliceIndexX : -1);
182 m_volumeItem2->setSliceIndexX(enabled ? m_sliceIndexX : -1);
183}
184
185void VolumetricModifier::sliceY(int enabled)
186{
187 m_volumeItem->setSliceIndexY(enabled ? m_sliceIndexY : -1);
188 m_volumeItem2->setSliceIndexY(enabled ? m_sliceIndexY : -1);
189}
190
191void VolumetricModifier::sliceZ(int enabled)
192{
193 m_volumeItem->setSliceIndexZ(enabled ? m_sliceIndexZ : -1);
194 m_volumeItem2->setSliceIndexZ(enabled ? m_sliceIndexZ : -1);
195}
196
197void VolumetricModifier::adjustSliceX(int value)
198{
199 m_sliceIndexX = int(float(value) / (1024.0f / m_volumeItem->textureWidth()));
200 if (m_sliceIndexX == m_volumeItem->textureWidth())
201 m_sliceIndexX--;
202 qDebug() << "m_sliceIndexX:" << m_sliceIndexX;
203 if (m_volumeItem->sliceIndexX() != -1) {
204 m_volumeItem->setSliceIndexX(m_sliceIndexX);
205 m_volumeItem2->setSliceIndexX(m_sliceIndexX);
206 }
207 m_sliceLabelX->setPixmap(QPixmap::fromImage(
208 image: m_volumeItem->renderSlice(axis: Qt::XAxis, index: m_sliceIndexX)));
209
210}
211
212void VolumetricModifier::adjustSliceY(int value)
213{
214 m_sliceIndexY = int(float(value) / (1024.0f / m_volumeItem->textureHeight()));
215 if (m_sliceIndexY == m_volumeItem->textureHeight())
216 m_sliceIndexY--;
217 qDebug() << "m_sliceIndexY:" << m_sliceIndexY;
218 if (m_volumeItem->sliceIndexY() != -1) {
219 m_volumeItem->setSliceIndexY(m_sliceIndexY);
220 m_volumeItem2->setSliceIndexY(m_sliceIndexY);
221 }
222 m_sliceLabelY->setPixmap(QPixmap::fromImage(
223 image: m_volumeItem->renderSlice(axis: Qt::YAxis, index: m_sliceIndexY)));
224}
225
226void VolumetricModifier::adjustSliceZ(int value)
227{
228 m_sliceIndexZ = int(float(value) / (1024.0f / m_volumeItem->textureDepth()));
229 if (m_sliceIndexZ == m_volumeItem->textureDepth())
230 m_sliceIndexZ--;
231 qDebug() << "m_sliceIndexZ:" << m_sliceIndexZ;
232 if (m_volumeItem->sliceIndexZ() != -1) {
233 m_volumeItem->setSliceIndexZ(m_sliceIndexZ);
234 m_volumeItem2->setSliceIndexZ(m_sliceIndexZ);
235 }
236 m_sliceLabelZ->setPixmap(QPixmap::fromImage(
237 image: m_volumeItem->renderSlice(axis: Qt::ZAxis, index: m_sliceIndexZ)));
238}
239
240void VolumetricModifier::handleFpsChange()
241{
242 const QString fpsFormat = QStringLiteral("Fps: %1");
243 int fps10 = int(m_graph->currentFps() * 10.0);
244 m_fpsLabel->setText(fpsFormat.arg(a: QString::number(qreal(fps10) / 10.0)));
245// const QString sceneDimensionsFormat = QStringLiteral("%1 x %2");
246// m_fpsLabel->setText(sceneDimensionsFormat
247// .arg(m_graph->scene()->viewport().width())
248 // .arg(m_graph->scene()->viewport().height()));
249}
250
251void VolumetricModifier::testSubtextureSetting()
252{
253 // Setting the rendered Slice as subtexture should result in identical volume
254 QVector<uchar> dataBefore = *m_volumeItem->textureData();
255 dataBefore[0] = dataBefore.at(i: 0); // Make sure we are detached
256
257 checkRenderCase(id: 1, axis: Qt::XAxis, index: 56, dataBefore, volumeItem: m_volumeItem);
258 checkRenderCase(id: 2, axis: Qt::YAxis, index: 64, dataBefore, volumeItem: m_volumeItem);
259 checkRenderCase(id: 3, axis: Qt::ZAxis, index: 87, dataBefore, volumeItem: m_volumeItem);
260
261 checkRenderCase(id: 4, axis: Qt::XAxis, index: 0, dataBefore, volumeItem: m_volumeItem);
262 checkRenderCase(id: 5, axis: Qt::YAxis, index: 0, dataBefore, volumeItem: m_volumeItem);
263 checkRenderCase(id: 6, axis: Qt::ZAxis, index: 0, dataBefore, volumeItem: m_volumeItem);
264
265 checkRenderCase(id: 7, axis: Qt::XAxis, index: m_volumeItem->textureWidth() - 1, dataBefore, volumeItem: m_volumeItem);
266 checkRenderCase(id: 8, axis: Qt::YAxis, index: m_volumeItem->textureHeight() - 1, dataBefore, volumeItem: m_volumeItem);
267 checkRenderCase(id: 9, axis: Qt::ZAxis, index: m_volumeItem->textureDepth() - 1, dataBefore, volumeItem: m_volumeItem);
268
269 dataBefore = *m_volumeItem2->textureData();
270 dataBefore[0] = dataBefore.at(i: 0); // Make sure we are detached
271
272 checkRenderCase(id: 11, axis: Qt::XAxis, index: 56, dataBefore, volumeItem: m_volumeItem2);
273 checkRenderCase(id: 12, axis: Qt::YAxis, index: 64, dataBefore, volumeItem: m_volumeItem2);
274 checkRenderCase(id: 13, axis: Qt::ZAxis, index: 87, dataBefore, volumeItem: m_volumeItem2);
275
276 checkRenderCase(id: 14, axis: Qt::XAxis, index: 0, dataBefore, volumeItem: m_volumeItem2);
277 checkRenderCase(id: 15, axis: Qt::YAxis, index: 0, dataBefore, volumeItem: m_volumeItem2);
278 checkRenderCase(id: 16, axis: Qt::ZAxis, index: 0, dataBefore, volumeItem: m_volumeItem2);
279
280 checkRenderCase(id: 17, axis: Qt::XAxis, index: m_volumeItem2->textureWidth() - 1, dataBefore, volumeItem: m_volumeItem2);
281 checkRenderCase(id: 18, axis: Qt::YAxis, index: m_volumeItem2->textureHeight() - 1, dataBefore, volumeItem: m_volumeItem2);
282 checkRenderCase(id: 19, axis: Qt::ZAxis, index: m_volumeItem2->textureDepth() - 1, dataBefore, volumeItem: m_volumeItem2);
283
284 // Do some visible swaps on volume 3
285 QImage slice = m_volumeItem3->renderSlice(axis: Qt::XAxis, index: 144);
286 slice = slice.mirrored();
287 m_volumeItem3->setSubTextureData(axis: Qt::XAxis, index: 144, image: slice);
288
289 slice = m_volumeItem3->renderSlice(axis: Qt::YAxis, index: 80);
290 slice = slice.mirrored();
291 m_volumeItem3->setSubTextureData(axis: Qt::YAxis, index: 80, image: slice);
292
293 slice = m_volumeItem3->renderSlice(axis: Qt::ZAxis, index: 190);
294 slice = slice.mirrored(horizontally: true, vertically: false);
295 m_volumeItem3->setSubTextureData(axis: Qt::ZAxis, index: 190, image: slice);
296}
297
298void VolumetricModifier::adjustRangeX(int value)
299{
300 float adjustment = float(value - 512) / 10.0f;
301 if (m_scatterGraph)
302 m_scatterGraph->axisX()->setRange(min: xMiddle + adjustment - xRange, max: xMiddle + adjustment + xRange);
303 if (m_surfaceGraph)
304 m_surfaceGraph->axisX()->setRange(min: xMiddle + adjustment - xRange, max: xMiddle + adjustment + xRange);
305 if (m_barGraph)
306 m_barGraph->columnAxis()->setRange(min: xMiddle + adjustment - xRange, max: xMiddle + adjustment + xRange);
307}
308
309void VolumetricModifier::adjustRangeY(int value)
310{
311 float adjustment = float(value - 512) / 10.0f;
312 if (m_scatterGraph)
313 m_scatterGraph->axisY()->setRange(min: yMiddle + adjustment - yRange, max: yMiddle + adjustment + yRange);
314 if (m_surfaceGraph)
315 m_surfaceGraph->axisY()->setRange(min: yMiddle + adjustment - yRange, max: yMiddle + adjustment + yRange);
316 if (m_barGraph)
317 m_barGraph->valueAxis()->setRange(min: yMiddle + adjustment - yRange, max: yMiddle + adjustment + yRange);
318}
319
320void VolumetricModifier::adjustRangeZ(int value)
321{
322 float adjustment = float(value - 512) / 10.0f;
323 if (m_scatterGraph)
324 m_scatterGraph->axisZ()->setRange(min: zMiddle + adjustment - zRange, max: zMiddle + adjustment + zRange);
325 if (m_surfaceGraph)
326 m_surfaceGraph->axisZ()->setRange(min: zMiddle + adjustment - zRange, max: zMiddle + adjustment + zRange);
327 if (m_barGraph)
328 m_barGraph->rowAxis()->setRange(min: zMiddle + adjustment - zRange, max: zMiddle + adjustment + zRange);
329}
330
331void VolumetricModifier::testBoundsSetting()
332{
333 static QVector3D scaling1 = m_volumeItem->scaling();
334 static QVector3D scaling2 = m_volumeItem2->scaling();
335 static QVector3D scaling3 = m_volumeItem3->scaling();
336 static QVector3D scaleVector = QVector3D(0.5f, 0.3f, 0.2f);
337
338 if (m_volumeItem->isScalingAbsolute()) {
339 m_volumeItem->setScalingAbsolute(false);
340 m_volumeItem2->setScalingAbsolute(false);
341 m_volumeItem3->setScalingAbsolute(false);
342
343 m_volumeItem->setScaling(scaling1);
344 m_volumeItem2->setScaling(scaling2);
345 m_volumeItem3->setScaling(scaling3);
346 } else {
347 m_volumeItem->setScalingAbsolute(true);
348 m_volumeItem2->setScalingAbsolute(true);
349 m_volumeItem3->setScalingAbsolute(true);
350
351 m_volumeItem->setScaling(scaleVector);
352 m_volumeItem2->setScaling(scaleVector);
353 m_volumeItem3->setScaling(scaleVector);
354 }
355}
356
357void VolumetricModifier::checkRenderCase(int id, Qt::Axis axis, int index,
358 const QVector<uchar> &dataBefore,
359 QCustom3DVolume *volumeItem)
360{
361 QImage slice = volumeItem->renderSlice(axis, index);
362 volumeItem->setSubTextureData(axis, index, image: slice);
363
364 if (dataBefore == *volumeItem->textureData())
365 qDebug() << __FUNCTION__ << "Case:" << id << "Vectors identical";
366 else
367 qDebug() << __FUNCTION__ << "Case:" << id << "BUG: VECTORS DIFFER!";
368}
369
370void VolumetricModifier::createVolume()
371{
372 m_volumeItem = new QCustom3DVolume;
373 m_volumeItem->setTextureFormat(QImage::Format_ARGB32);
374 m_volumeItem->setRotation(QQuaternion::fromAxisAndAngle(x: 1.0f, y: 1.0f, z: 0.0f, angle: 20.0f));
375 m_volumeItem->setPosition(QVector3D(xMiddle - (xRange / 2.0f), yMiddle + (yRange / 2.0f), zMiddle));
376 //m_volumeItem->setPosition(QVector3D(xMiddle, yMiddle, zMiddle));
377 m_volumeItem->setDrawSliceFrames(true);
378 m_volumeItem->setDrawSlices(true);
379
380 QImage ;
381 logo.load(QStringLiteral(":/logo_no_padding.png"));
382 //logo.load(QStringLiteral(":/logo.png"));
383 qDebug() << "image dimensions:" << logo.width() << logo.height()
384 << logo.sizeInBytes() << (logo.width() * logo.height())
385 << logo.bytesPerLine();
386
387 QVector<QImage *> imageArray(imageCount);
388 for (int i = 0; i < imageCount; i++) {
389 QImage *newImage = new QImage(logo);
390 imageArray[i] = newImage;
391 }
392
393 m_volumeItem->createTextureData(images: imageArray);
394
395 for (int i = 0; i < imageCount; i++)
396 delete imageArray[i];
397
398 m_sliceIndexX = m_volumeItem->textureWidth() / 2;
399 m_sliceIndexY = m_volumeItem->textureWidth() / 2;
400 m_sliceIndexZ = m_volumeItem->textureWidth() / 2;
401
402 QVector<QRgb> colorTable = m_volumeItem->colorTable();
403
404 // Hack some alpha to the picture
405 for (int i = 0; i < colorTable.size(); i++) {
406 if (qAlpha(rgb: colorTable.at(i)) > 0) {
407 colorTable[i] = qRgba(r: qRed(rgb: colorTable.at(i)),
408 g: qGreen(rgb: colorTable.at(i)),
409 b: qBlue(rgb: colorTable.at(i)),
410 a: 50);
411 }
412 }
413
414 colorTable.append(t: qRgba(r: 0, g: 0, b: 0, a: 0));
415 colorTable.append(t: qRgba(r: 255, g: 0, b: 0, a: 255));
416 colorTable.append(t: qRgba(r: 0, g: 255, b: 0, a: 255));
417 colorTable.append(t: qRgba(r: 0, g: 0, b: 255, a: 255));
418
419 m_volumeItem->setColorTable(colorTable);
420 int alphaIndex = colorTable.size() - 4;
421 int redIndex = colorTable.size() - 3;
422 int greenIndex = colorTable.size() - 2;
423 int blueIndex = colorTable.size() - 1;
424 int width = m_volumeItem->textureDataWidth();
425 int height = m_volumeItem->textureHeight();
426 int depth = m_volumeItem->textureDepth();
427 int frameSize = width * height;
428 qDebug() << width << height << depth << m_volumeItem->textureData()->size();
429 m_volumeItem->setScaling(QVector3D(xRange, yRange, zRange) / 2.0f);
430
431 uchar *data = m_volumeItem->textureData()->data();
432 uchar *p = data;
433
434 // Change one picture using subtexture replacement
435 QImage flipped = logo.mirrored();
436 m_volumeItem->setSubTextureData(axis: Qt::ZAxis, index: 100, image: flipped);
437
438 // Clean up the two extra pixels
439 p = data + width - 1;
440 for (int k = 0; k < depth; k++) {
441 for (int j = 0; j < height; j++) {
442 *p = alphaIndex;
443 p += width;
444 }
445 }
446 p = data + width - 2;
447 for (int k = 0; k < depth; k++) {
448 for (int j = 0; j < height; j++) {
449 *p = alphaIndex;
450 p += width;
451 }
452 }
453 // Red first subtexture
454 p = data;
455 for (int j = 0; j < height; j++) {
456 for (int i = 0; i < width; i++) {
457 *p = redIndex;
458 p++;
459 }
460 }
461
462 // Red last subtexture
463// p = data + frameSize * (imageCount - 1);
464// for (int j = 0; j < height; j++) {
465// for (int i = 0; i < width; i++) {
466// *p = redIndex;
467// p++;
468// }
469// }
470
471// // Blue second to last subtexture
472// p = data + frameSize * (imageCount - 2);
473// for (int j = 0; j < height; j++) {
474// for (int i = 0; i < width; i++) {
475// *p = blueIndex;
476// p++;
477// }
478// }
479
480 // Blue x = 0
481// p = data;
482// for (int k = 0; k < depth; k++) {
483// for (int j = 0; j < height; j++) {
484// *p = blueIndex;
485// p += width;
486// }
487// }
488
489 // Blue x = max
490 p = data + width - 1;
491 for (int k = 0; k < depth; k++) {
492 for (int j = 0; j < height; j++) {
493 *p = blueIndex;
494 p += width;
495 }
496 }
497 // green x = max - 1
498 p = data + width - 2;
499 for (int k = 0; k < depth; k++) {
500 for (int j = 0; j < height; j++) {
501 *p = greenIndex;
502 p += width;
503 }
504 }
505
506 // Green y = 0
507 p = data;
508 for (int k = 0; k < depth; k++) {
509 for (int i = 0; i < width; i++) {
510 *p = greenIndex;
511 p++;
512 }
513 p += (frameSize - width);
514 }
515
516 // Green y = max
517// p = data + frameSize - width;
518// for (int k = 0; k < depth; k++) {
519// for (int i = 0; i < width; i++) {
520// *p = greenIndex;
521// p++;
522// }
523// p += (frameSize - width);
524// }
525}
526
527void VolumetricModifier::createAnotherVolume()
528{
529 m_volumeItem2 = new QCustom3DVolume;
530 m_volumeItem2->setTextureFormat(QImage::Format_ARGB32);
531 m_volumeItem2->setPosition(QVector3D(xMiddle + (xRange / 2.0f), yMiddle - (yRange / 2.0f), zMiddle));
532
533 QImage ;
534 logo.load(QStringLiteral(":/logo_no_padding.png"));
535 //logo.load(QStringLiteral(":/logo.png"));
536 logo = logo.convertToFormat(f: QImage::Format_ARGB8555_Premultiplied);
537 qDebug() << "second image dimensions:" << logo.width() << logo.height()
538 << logo.sizeInBytes() << (logo.width() * logo.height())
539 << logo.bytesPerLine();
540
541 logo.save(fileName: "d:/qt/goobar.png");
542
543 QVector<QImage *> imageArray(imageCount);
544 for (int i = 0; i < imageCount; i++) {
545 QImage *newImage = new QImage(logo);
546 imageArray[i] = newImage;
547 }
548
549 m_volumeItem2->createTextureData(images: imageArray);
550
551 for (int i = 0; i < imageCount; i++)
552 delete imageArray[i];
553
554 m_sliceIndexX = m_volumeItem2->textureWidth() / 2;
555 m_sliceIndexY = m_volumeItem2->textureWidth() / 2;
556 m_sliceIndexZ = m_volumeItem2->textureWidth() / 2;
557
558 int width = m_volumeItem2->textureWidth();
559 int height = m_volumeItem2->textureHeight();
560 int depth = m_volumeItem2->textureDepth();
561 qDebug() << width << height << depth << m_volumeItem2->textureData()->size();
562 m_volumeItem2->setScaling(QVector3D(float(width) / float(depth) * xRange * 2.0f,
563 float(height) / float(depth) * yRange * 2.0f,
564 zRange * 2.0f));
565
566 // Change one picture using subtexture replacement
567 QImage flipped = logo.mirrored();
568 m_volumeItem2->setSubTextureData(axis: Qt::ZAxis, index: 100, image: flipped);
569 //m_volumeItem2->setAlphaMultiplier(0.2f);
570 m_volumeItem2->setPreserveOpacity(false);
571}
572
573void VolumetricModifier::createYetAnotherVolume()
574{
575 m_volumeItem3 = new QCustom3DVolume;
576 m_volumeItem3->setTextureFormat(QImage::Format_Indexed8);
577// m_volumeItem2->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 10.0f));
578 m_volumeItem3->setPosition(QVector3D(xMiddle - (xRange / 2.0f), yMiddle - (yRange / 2.0f), zMiddle));
579
580// m_volumeItem3->setTextureDimensions(m_volumeItem->textureDataWidth(),
581// m_volumeItem->textureHeight(),
582// m_volumeItem->textureDepth());
583 m_volumeItem3->setTextureDimensions(width: 200, height: 200, depth: 200);
584
585 QVector<uchar> *tdata = new QVector<uchar>(m_volumeItem3->textureDataWidth()
586 * m_volumeItem3->textureHeight()
587 * m_volumeItem3->textureDepth());
588 tdata->fill(from: 0);
589 m_volumeItem3->setTextureData(tdata);
590
591 m_sliceIndexX = m_volumeItem3->textureWidth() / 2;
592 m_sliceIndexY = m_volumeItem3->textureWidth() / 2;
593 m_sliceIndexZ = m_volumeItem3->textureWidth() / 2;
594
595 QVector<QRgb> colorTable = m_volumeItem->colorTable();
596 colorTable[0] = qRgba(r: 0, g: 0, b: 0, a: 0);
597 m_volumeItem3->setColorTable(colorTable);
598 int redIndex = colorTable.size() - 3;
599 int greenIndex = colorTable.size() - 2;
600 int blueIndex = colorTable.size() - 1;
601 int width = m_volumeItem3->textureDataWidth();
602 int height = m_volumeItem3->textureHeight();
603 int depth = m_volumeItem3->textureDepth();
604 int frameSize = width * height;
605 qDebug() << width << height << depth << m_volumeItem3->textureData()->size();
606 m_volumeItem3->setScaling(m_volumeItem->scaling());
607
608 uchar *data = tdata->data();
609 uchar *p = data;
610
611 // Red first subtexture
612// for (int j = 0; j < height; j++) {
613// for (int i = 0; i < width; i++) {
614// *p = redIndex;
615// p++;
616// }
617// }
618
619 // Red last subtexture
620 p = data + frameSize * (depth - 1);
621 for (int j = 0; j < height; j++) {
622 for (int i = 0; i < width; i++) {
623 *p = redIndex;
624 p++;
625 }
626 }
627
628 // green edge
629 p = data + frameSize * (depth - 1);
630 for (int i = 0; i < width; i++) {
631 *p = greenIndex;
632 p++;
633 }
634 for (int j = 2; j < height; j++) {
635 *p = greenIndex;
636 p += width - 1;
637 *p = j % 7 ? greenIndex : blueIndex;
638 p++;
639 }
640 for (int i = 0; i < width; i++) {
641 *p = greenIndex;
642 p++;
643 }
644
645// // Blue second to last subtexture
646// p = data + frameSize * (depth - 2);
647// for (int j = 0; j < height; j++) {
648// for (int i = 0; i < width; i++) {
649// *p = blueIndex;
650// p++;
651// }
652// }
653
654// // green third to last subtexture
655// p = data + frameSize * (depth - 3);
656// for (int j = 0; j < height; j++) {
657// for (int i = 0; i < width; i++) {
658// *p = greenIndex;
659// p++;
660// }
661// }
662
663 // Blue x = 0
664 p = data;
665 for (int k = 0; k < depth; k++) {
666 for (int j = 0; j < height; j++) {
667 *p = blueIndex;
668 p += width;
669 }
670 }
671
672// // Blue x = max
673// p = data + width - 1;
674// for (int k = 0; k < depth; k++) {
675// for (int j = 0; j < height; j++) {
676// *p = blueIndex;
677// p += width;
678// }
679// }
680
681 // Green y = 0
682// p = data;
683// for (int k = 0; k < depth; k++) {
684// for (int i = 0; i < width; i++) {
685// *p = greenIndex;
686// p++;
687// }
688// p += (frameSize - width);
689// }
690
691// // Green y = max
692 p = data + frameSize - width;
693 for (int k = 0; k < depth; k++) {
694 for (int i = 0; i < width; i++) {
695 *p = greenIndex;
696 p++;
697 }
698 p += (frameSize - width);
699 }
700
701
702// // Fill with alternating pixels
703// p = data;
704// for (int k = 0; k < (depth * width * height / 4); k++) {
705// *p = greenIndex;
706// p++;
707// *p = greenIndex;
708// p++;
709// *p = blueIndex;
710// p++;
711// *p = redIndex;
712// p++;
713// }
714
715
716}
717
718void VolumetricModifier::setSliceLabels(QLabel *xLabel, QLabel *yLabel, QLabel *zLabel)
719{
720 m_sliceLabelX = xLabel;
721 m_sliceLabelY = yLabel;
722 m_sliceLabelZ = zLabel;
723
724 adjustSliceX(value: 512);
725 adjustSliceY(value: 512);
726 adjustSliceZ(value: 512);
727}
728

source code of qtdatavis3d/tests/manual/volumetrictest/volumetrictest.cpp