diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-08-22 13:19:18 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-08-22 14:47:54 +0300 |
commit | ae411d84b9eac08c217bdda3aa5fbc6f39d03d85 (patch) | |
tree | ff929c13722fe6f90412f8da473445dc92800fd4 | |
parent | 8fab0a9cfcbed9deb47f4a9bd101434985c1c611 (diff) |
Tweak volume shaders.
Also fix custom object default texture.
Change-Id: Iba9ff6afb807d9f7a4e1f58b0e5fb4bca4c9c431
Reviewed-by: Mika Salmela <mika.salmela@digia.com>
-rw-r--r-- | src/datavisualization/data/customrenderitem.cpp | 18 | ||||
-rw-r--r-- | src/datavisualization/data/qcustom3ditem.cpp | 2 | ||||
-rw-r--r-- | src/datavisualization/engine/shaders/texture3d.frag | 136 | ||||
-rw-r--r-- | src/datavisualization/engine/shaders/texture3dslice.frag | 27 | ||||
-rw-r--r-- | tests/volumetrictest/cubeFilledFlat.obj | 54 | ||||
-rw-r--r-- | tests/volumetrictest/main.cpp | 3 | ||||
-rw-r--r-- | tests/volumetrictest/volumetrictest.cpp | 293 | ||||
-rw-r--r-- | tests/volumetrictest/volumetrictest.h | 7 | ||||
-rw-r--r-- | tests/volumetrictest/volumetrictest.qrc | 1 |
9 files changed, 413 insertions, 128 deletions
diff --git a/src/datavisualization/data/customrenderitem.cpp b/src/datavisualization/data/customrenderitem.cpp index b96a4957..3eb68845 100644 --- a/src/datavisualization/data/customrenderitem.cpp +++ b/src/datavisualization/data/customrenderitem.cpp @@ -52,13 +52,17 @@ void CustomRenderItem::setMesh(const QString &meshFile) void CustomRenderItem::setColorTable(const QVector<QRgb> &colors) { - m_colorTable.resize(colors.size()); - for (int i = 0; i < m_colorTable.size(); i++) { - const QRgb &rgb = colors.at(i); - m_colorTable[i] = QVector4D(float(qRed(rgb)) / 255.0f, - float(qGreen(rgb)) / 255.0f, - float(qBlue(rgb)) / 255.0f, - float(qAlpha(rgb)) / 255.0f); + m_colorTable.resize(256); + for (int i = 0; i < 256; i++) { + if (i < colors.size()) { + const QRgb &rgb = colors.at(i); + m_colorTable[i] = QVector4D(float(qRed(rgb)) / 255.0f, + float(qGreen(rgb)) / 255.0f, + float(qBlue(rgb)) / 255.0f, + float(qAlpha(rgb)) / 255.0f); + } else { + m_colorTable[i] = QVector4D(0.0f, 0.0f, 0.0f, 0.0f); + } } } diff --git a/src/datavisualization/data/qcustom3ditem.cpp b/src/datavisualization/data/qcustom3ditem.cpp index 1d419cee..cb843b62 100644 --- a/src/datavisualization/data/qcustom3ditem.cpp +++ b/src/datavisualization/data/qcustom3ditem.cpp @@ -367,6 +367,7 @@ QString QCustom3DItem::textureFile() const QCustom3DItemPrivate::QCustom3DItemPrivate(QCustom3DItem *q) : q_ptr(q), + m_textureImage(QImage(1, 1, QImage::Format_ARGB32)), m_position(QVector3D(0.0f, 0.0f, 0.0f)), m_positionAbsolute(false), m_scaling(QVector3D(0.1f, 0.1f, 0.1f)), @@ -382,6 +383,7 @@ QCustom3DItemPrivate::QCustom3DItemPrivate(QCustom3DItem *q, const QString &mesh const QVector3D &position, const QVector3D &scaling, const QQuaternion &rotation) : q_ptr(q), + m_textureImage(QImage(1, 1, QImage::Format_ARGB32)), m_meshFile(meshFile), m_position(position), m_positionAbsolute(false), diff --git a/src/datavisualization/engine/shaders/texture3d.frag b/src/datavisualization/engine/shaders/texture3d.frag index e56506ff..90876596 100644 --- a/src/datavisualization/engine/shaders/texture3d.frag +++ b/src/datavisualization/engine/shaders/texture3d.frag @@ -12,78 +12,90 @@ uniform highp int sampleCount; // This is the maximum sample count const highp float alphaThreshold = 0.0001; void main() { - // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1 - - // Find out where ray intersects the object highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); - highp vec3 invRayDir = 1.0 / rayDir; - highp vec3 minCorner = vec3(-1.0); - highp vec3 maxCorner = vec3(1.0); - highp vec3 t1 = invRayDir * (minCorner - pos); - highp vec3 t2 = invRayDir * (maxCorner - pos); - highp vec3 tmin = min(t1, t2); - highp vec3 tmax = max(t1, t2); - highp vec2 t = max(tmin.xx, tmin.yz); - t = min(tmax.xx, tmax.yz); - float tFar = min(t.x, t.y); - highp vec3 rayStart = pos; + vec3 rayStart = pos; // Flip Y and Z so QImage bits work directly for texture and first image is in the front + rayDir.yz = -rayDir.yz; rayStart.yz = -rayStart.yz; - highp vec3 rayStop = pos + rayDir * tFar; - rayStop.yz = -rayStop.yz; - - // Convert intersections to texture coords - rayStart = 0.5 * (rayStart + 1.0); - rayStop = 0.5 * (rayStop + 1.0); - - highp vec3 ray = rayStop - rayStart; - highp float fullDist = length(ray); - highp float rayX = abs(ray.x) * textureDimensions.x; - highp float rayY = abs(ray.y) * textureDimensions.y; - highp float rayZ = abs(ray.z) * textureDimensions.z; - - highp float maxRayDim = max(rayX, rayY); - maxRayDim = max(maxRayDim, rayZ); - - highp vec3 step = ray / maxRayDim; - highp float stepSize = abs(fullDist / maxRayDim); - - // Offset a fraction of a step so we are not exactly on a texel boundary. - highp vec3 curPos = rayStart - (0.5 * step); - // Adjust alpha multiplier according to the step size to get uniform alpha effect - // regardless of the ray angle. - highp float alphaMultiplier = stepSize / (1.0 / sampleCount); + // Calculate ray intersection endpoint + vec3 rayStop; + if (rayDir.x == 0.0) { + rayStop.yz = rayStart.yz; + rayStop.x = -rayStart.x; + } else if (rayDir.y == 0.0) { + rayStop.xz = rayStart.xz; + rayStop.y = -rayStart.y; + } else if (rayDir.z == 0.0) { + rayStop.xy = rayStart.xy; + rayStop.z = -rayStart.z; + } else { + highp vec3 boxBounds = vec3(1.0, 1.0, 1.0); + highp vec3 invRayDir = 1.0 / rayDir; + if (rayDir.x < 0) + boxBounds.x = -1.0; + if (rayDir.y < 0) + boxBounds.y = -1.0; + if (rayDir.z < 0) + boxBounds.z = -1.0; + highp vec3 t = (boxBounds - rayStart) * invRayDir; + highp float minT = min(t.x, t.y); + minT = min(minT, t.z); + rayStop = rayStart + minT * rayDir; + } - highp float totalDist = 0.0; - highp float totalAlpha = 0.0; highp vec4 destColor = vec4(0, 0, 0, 0); - highp vec4 curColor = vec4(0, 0, 0, 0); - highp vec3 curRgb = vec3(0, 0, 0); - highp float curAlpha = 0.0; - - for (int i = 0; i < sampleCount; i++) { - curColor = texture3D(textureSampler, curPos); - if (color8Bit != 0) - curColor = colorIndex[int(curColor.r * 255.0)]; + highp float totalAlpha = 0.0; - if (curColor.a == 1.0) - curAlpha = 1.0; - else - curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0); - if (curAlpha > alphaThreshold) { - curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha); - destColor.rgb += curRgb; - totalAlpha += curAlpha; - } - curPos += step; - totalDist += stepSize; - if (totalDist > fullDist || totalAlpha >= 1.0) { - break; + if (rayStart != rayStop) { + // Convert intersections to texture coords + rayStart = 0.5 * (rayStart + 1.0); + rayStop = 0.5 * (rayStop + 1.0); + + highp vec3 ray = rayStop - rayStart; + highp float fullDist = abs(length(ray)); + highp float rayX = abs(ray.x) * textureDimensions.x; + highp float rayY = abs(ray.y) * textureDimensions.y; + highp float rayZ = abs(ray.z) * textureDimensions.z; + highp float maxRayDim = max(rayX, rayY); + maxRayDim = max(maxRayDim, rayZ); + int maxCount = int(floor(maxRayDim)); + + highp vec3 step = ray / maxRayDim; + highp float stepSize = fullDist / maxRayDim; + + rayStart += (step * 0.001); + highp vec3 curPos = rayStart; + + // Adjust alpha multiplier according to the step size to get uniform alpha effect + // regardless of the ray angle. + highp float alphaMultiplier = stepSize / (1.0 / sampleCount); + + highp vec4 curColor = vec4(0, 0, 0, 0); + highp vec3 curRgb = vec3(0, 0, 0); + highp float curAlpha = 0.0; + + // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1 + for (int i = 0; i < sampleCount; i++) { + curColor = texture3D(textureSampler, curPos); + if (color8Bit != 0) + curColor = colorIndex[int(curColor.r * 255.0)]; + + if (curColor.a == 1.0) + curAlpha = 1.0; + else + curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0); + if (curAlpha > alphaThreshold) { + curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha); + destColor.rgb += curRgb; + totalAlpha += curAlpha; + } + if (i == maxCount || totalAlpha >= 1.0) + break; + curPos += step; } } destColor.a = totalAlpha; gl_FragColor = clamp(destColor, 0.0, 1.0); } - diff --git a/src/datavisualization/engine/shaders/texture3dslice.frag b/src/datavisualization/engine/shaders/texture3dslice.frag index e095bc5f..409ab41d 100644 --- a/src/datavisualization/engine/shaders/texture3dslice.frag +++ b/src/datavisualization/engine/shaders/texture3dslice.frag @@ -15,24 +15,27 @@ const highp vec3 zPlaneNormal = vec3(0, 0, 1.0); const highp float alphaThreshold = 0.0001; void main() { - // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1 - // Find out where ray intersects the slice planes highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); + rayDir = normalize(rayDir); highp vec3 rayStart = pos; // Flip Y and Z so QImage bits work directly for texture and first image is in the front rayStart.yz = -rayStart.yz; rayDir.yz = -rayDir.yz; - highp vec3 invRayDir = 1.0 / rayDir; - highp vec3 minCorner = vec3(-1.0); - highp vec3 maxCorner = vec3(1.0); - highp vec3 t1 = invRayDir * (minCorner - rayStart); - highp vec3 t2 = invRayDir * (maxCorner - rayStart); - highp vec3 tmin = min(t1, t2); - highp vec3 tmax = max(t1, t2); - highp vec2 t = max(tmin.xx, tmin.yz); - t = min(tmax.xx, tmax.yz); - float tFar = min(t.x, t.y); + highp float tFar = 2.0f; + if (rayDir.x != 0.0 && rayDir.y != 0.0 && rayDir.z != 0.0) { + highp vec3 boxBounds = vec3(1.0, 1.0, 1.0); + highp vec3 invRayDir = 1.0 / rayDir; + if (rayDir.x < 0) + boxBounds.x = -1.0; + if (rayDir.y < 0) + boxBounds.y = -1.0; + if (rayDir.z < 0) + boxBounds.z = -1.0; + highp vec3 t = (boxBounds - rayStart) * invRayDir; + tFar = max(t.x, t.y); + tFar = max(tFar, t.z); + } highp vec3 xPoint = vec3(volumeSliceIndices.x, 0, 0); highp vec3 yPoint = vec3(0, volumeSliceIndices.y, 0); diff --git a/tests/volumetrictest/cubeFilledFlat.obj b/tests/volumetrictest/cubeFilledFlat.obj new file mode 100644 index 00000000..108cf7ac --- /dev/null +++ b/tests/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/volumetrictest/main.cpp b/tests/volumetrictest/main.cpp index 46edf576..a15caf88 100644 --- a/tests/volumetrictest/main.cpp +++ b/tests/volumetrictest/main.cpp @@ -35,7 +35,7 @@ int main(int argc, char **argv) QWidget *container = QWidget::createWindowContainer(graph); QSize screenSize = graph->screen()->size(); - container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5)); + container->setMinimumSize(QSize(screenSize.width() / 4, screenSize.height() / 4)); container->setMaximumSize(screenSize); container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); container->setFocusPolicy(Qt::StrongFocus); @@ -47,6 +47,7 @@ int main(int argc, char **argv) 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")); diff --git a/tests/volumetrictest/volumetrictest.cpp b/tests/volumetrictest/volumetrictest.cpp index 04aad052..701cfc04 100644 --- a/tests/volumetrictest/volumetrictest.cpp +++ b/tests/volumetrictest/volumetrictest.cpp @@ -34,11 +34,14 @@ const int imageCount = 512; VolumetricModifier::VolumetricModifier(Q3DScatter *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); @@ -46,15 +49,27 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter) createVolume(); createAnotherVolume(); + createYetAnotherVolume(); + + 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(m_volumeItem->position() + QVector3D(0.8f, 0.0f, 0.0f)); + m_plainItem->setScaling(m_volumeItem->scaling()); m_graph->addCustomItem(m_volumeItem); m_graph->addCustomItem(m_volumeItem2); - m_graph->setMeasureFps(true); + m_graph->addCustomItem(m_volumeItem3); + m_graph->addCustomItem(m_plainItem); + //m_graph->setMeasureFps(true); - QObject::connect(m_graph->scene()->activeCamera(), &Q3DCamera::zoomLevelChanged, this, - &VolumetricModifier::handleZoomLevelChange); QObject::connect(m_graph, &QAbstract3DGraph::currentFpsChanged, this, &VolumetricModifier::handleFpsChange); +// QObject::connect(m_graph->scene(), &Q3DScene::viewportChanged, this, +// &VolumetricModifier::handleFpsChange); } VolumetricModifier::~VolumetricModifier() @@ -121,26 +136,23 @@ void VolumetricModifier::adjustSliceZ(int value) } } -void VolumetricModifier::handleZoomLevelChange() -{ - // Zooming inside volumetric object causes ugly clipping issues, so restrict zoom level a bit - if (m_graph->scene()->activeCamera()->zoomLevel() > 220) - m_graph->scene()->activeCamera()->setZoomLevel(220); -} - -void VolumetricModifier::handleFpsChange(qreal fps) +void VolumetricModifier::handleFpsChange() { const QString fpsFormat = QStringLiteral("Fps: %1"); - int fps10 = int(fps * 10.0); + 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::createVolume() { m_volumeItem = new QCustom3DVolume; m_volumeItem->setTextureFormat(QImage::Format_ARGB32); - m_volumeItem->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 10.0f)); - m_volumeItem->setPosition(QVector3D(-0.5f, 0.0f, 0.0f)); +// m_volumeItem->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 10.0f)); + m_volumeItem->setPosition(QVector3D(-0.5f, 0.6f, 0.0f)); QImage logo; logo.load(QStringLiteral(":/logo.png")); @@ -161,10 +173,24 @@ void VolumetricModifier::createVolume() 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; @@ -173,18 +199,44 @@ void VolumetricModifier::createVolume() int depth = m_volumeItem->textureDepth(); int frameSize = width * height; qDebug() << width << height << depth << m_volumeItem->textureData()->size(); - m_volumeItem->setScaling(QVector3D(float(width) / float(depth) * 2.0f, - float(height) / float(depth) * 2.0f, - 2.0f)); +// m_volumeItem->setScaling(QVector3D(float(width) / float(depth) * 2.0f, +// float(height) / float(depth) * 2.0f, +// 2.0f)); + m_volumeItem->setScaling(QVector3D(0.4f, 0.4f, 0.4f)); uchar *data = m_volumeItem->textureData()->data(); uchar *p = data; // Change one picture using subtexture replacement - QImage flipped = logo.mirrored(); - m_volumeItem->setSubTextureData(101, flipped); +// QImage flipped = logo.mirrored(); +// m_volumeItem->setSubTextureData(101, 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; @@ -192,45 +244,43 @@ void VolumetricModifier::createVolume() // } // } - // 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; +// 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; } } - - // Blue x = max - p = data + width - 1; + // green x = max - 1 + p = data + width - 2; for (int k = 0; k < depth; k++) { for (int j = 0; j < height; j++) { - *p = blueIndex; + *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; + p = data; for (int k = 0; k < depth; k++) { for (int i = 0; i < width; i++) { *p = greenIndex; @@ -238,13 +288,23 @@ void VolumetricModifier::createVolume() } 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(0.5f, 0.0f, 0.0f)); + m_volumeItem2->setPosition(QVector3D(0.5f, -0.5f, 0.0f)); QImage logo; logo.load(QStringLiteral(":/logo.png")); @@ -280,3 +340,148 @@ void VolumetricModifier::createAnotherVolume() m_volumeItem2->setSubTextureData(101, flipped); } +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(-0.5f, -0.6f, 0.0f)); + +// 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++; +// } + + +} + diff --git a/tests/volumetrictest/volumetrictest.h b/tests/volumetrictest/volumetrictest.h index 677a1231..40d88192 100644 --- a/tests/volumetrictest/volumetrictest.h +++ b/tests/volumetrictest/volumetrictest.h @@ -21,6 +21,7 @@ #include <QtDataVisualization/q3dscatter.h> #include <QtDataVisualization/qcustom3dvolume.h> +#include <QtDataVisualization/qcustom3ditem.h> class QLabel; @@ -42,16 +43,18 @@ public slots: void adjustSliceX(int value); void adjustSliceY(int value); void adjustSliceZ(int value); - void handleZoomLevelChange(); - void handleFpsChange(qreal fps); + void handleFpsChange(); private: void createVolume(); void createAnotherVolume(); + void createYetAnotherVolume(); Q3DScatter *m_graph; QCustom3DVolume *m_volumeItem; QCustom3DVolume *m_volumeItem2; + QCustom3DVolume *m_volumeItem3; + QCustom3DItem *m_plainItem; int m_sliceIndexX; int m_sliceIndexY; int m_sliceIndexZ; diff --git a/tests/volumetrictest/volumetrictest.qrc b/tests/volumetrictest/volumetrictest.qrc index 90517ff1..5b9623f0 100644 --- a/tests/volumetrictest/volumetrictest.qrc +++ b/tests/volumetrictest/volumetrictest.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/"> <file>logo.png</file> + <file alias="mesh">cubeFilledFlat.obj</file> </qresource> </RCC> |