/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Data Visualization module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "volumetric.h"#include <QtDataVisualization/qvalue3daxis.h>#include <QtDataVisualization/q3dscene.h>#include <QtDataVisualization/q3dcamera.h>#include <QtDataVisualization/q3dtheme.h>#include <QtDataVisualization/qcustom3dlabel.h>#include <QtDataVisualization/q3dscatter.h>#include <QtDataVisualization/q3dinputhandler.h>#include <QtCore/qmath.h>#include <QtWidgets/QLabel>#include <QtWidgets/QRadioButton>#include <QtWidgets/QSlider>#include <QtCore/QDebug>#include <QtGui/QOpenGLContext>usingnamespaceQtDataVisualization;
constint lowDetailSize(128);
constint mediumDetailSize(256);
constint highDetailSize(512);
constint colorTableSize(256);
constint layerDataSize(512);
constint mineShaftDiameter(1);
constint airColorIndex(254);
constint mineShaftColorIndex(255);
constint layerColorThickness(60);
constint heightToColorDiv(140);
constint magmaColorsMin(0);
constint magmaColorsMax(layerColorThickness);
constint aboveWaterGroundColorsMin(magmaColorsMax +1);
constint aboveWaterGroundColorsMax(aboveWaterGroundColorsMin + layerColorThickness);
constint underWaterGroundColorsMin(aboveWaterGroundColorsMax +1);
constint underWaterGroundColorsMax(underWaterGroundColorsMin + layerColorThickness);
constint waterColorsMin(underWaterGroundColorsMax +1);
constint waterColorsMax(waterColorsMin + layerColorThickness);
constint terrainTransparency(12);
static bool isOpenGLES()
{
#if defined(QT_OPENGL_ES_2)returntrue;
#elif (QT_VERSION < QT_VERSION_CHECK(5, 3, 0))returnfalse;
#elsereturnQOpenGLContext::currentContext()->isOpenGLES();
#endif
}
VolumetricModifier::VolumetricModifier(Q3DScatter*scatter)
: m_graph(scatter),
m_volumeItem(0),
m_sliceIndexX(lowDetailSize /2),
m_sliceIndexY(lowDetailSize /4),
m_sliceIndexZ(lowDetailSize /2),
m_slicingX(false),
m_slicingY(false),
m_slicingZ(false),
m_mediumDetailRB(0),
m_highDetailRB(0),
m_lowDetailData(0),
m_mediumDetailData(0),
m_highDetailData(0),
m_mediumDetailIndex(0),
m_highDetailIndex(0),
m_mediumDetailShaftIndex(0),
m_highDetailShaftIndex(0),
m_sliceSliderX(0),
m_sliceSliderY(0),
m_sliceSliderZ(0),
m_usingPrimaryTable(true),
m_sliceLabelX(0),
m_sliceLabelY(0),
m_sliceLabelZ(0)
{
m_graph->activeTheme()->setType(Q3DTheme::ThemeQt);
m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityNone);
m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
m_graph->setOrthoProjection(true);
m_graph->activeTheme()->setBackgroundEnabled(false);
// Only allow zooming at the center and limit the zoom to 200% to avoid clipping issuesstatic_cast<Q3DInputHandler*>(m_graph->activeInputHandler())->setZoomAtTargetEnabled(false);
m_graph->scene()->activeCamera()->setMaxZoomLevel(200.0f);
toggleAreaAll(true);
if (!isOpenGLES()) {
m_lowDetailData =newQVector<uchar>(lowDetailSize * lowDetailSize * lowDetailSize /2);
m_mediumDetailData =newQVector<uchar>(mediumDetailSize * mediumDetailSize * mediumDetailSize /2);
m_highDetailData =newQVector<uchar>(highDetailSize * highDetailSize * highDetailSize /2);
initHeightMap(QStringLiteral(":/heightmaps/layer_ground.png"), m_groundLayer);
initHeightMap(QStringLiteral(":/heightmaps/layer_water.png"), m_waterLayer);
initHeightMap(QStringLiteral(":/heightmaps/layer_magma.png"), m_magmaLayer);
initMineShaftArray();
createVolume(lowDetailSize,0, lowDetailSize, m_lowDetailData);
excavateMineShaft(lowDetailSize,0, m_mineShaftArray.size(), m_lowDetailData);
m_volumeItem =new QCustom3DVolume;
// Adjust water level to zero with a minor tweak to y-coordinate position and scaling
m_volumeItem->setScaling(
QVector3D(m_graph->axisX()->max() - m_graph->axisX()->min(),
(m_graph->axisY()->max() - m_graph->axisY()->min()) *0.91f,
m_graph->axisZ()->max() - m_graph->axisZ()->min()));
m_volumeItem->setPosition(
QVector3D((m_graph->axisX()->max() + m_graph->axisX()->min()) /2.0f,-0.045f* (m_graph->axisY()->max() - m_graph->axisY()->min()) +
(m_graph->axisY()->max() + m_graph->axisY()->min()) /2.0f,
(m_graph->axisZ()->max() + m_graph->axisZ()->min()) /2.0f));
m_volumeItem->setScalingAbsolute(false);
m_volumeItem->setTextureWidth(lowDetailSize);
m_volumeItem->setTextureHeight(lowDetailSize /2);
m_volumeItem->setTextureDepth(lowDetailSize);
m_volumeItem->setTextureFormat(QImage::Format_Indexed8);
m_volumeItem->setTextureData(newQVector<uchar>(*m_lowDetailData));
// Generate color tables.
m_colorTable1.resize(colorTableSize);
m_colorTable2.resize(colorTableSize);
for (int i =0; i < colorTableSize -2; i++) {
if (i < magmaColorsMax) {
m_colorTable1[i]=qRgba(130- (i *2),0,0,255);
} elseif (i < aboveWaterGroundColorsMax) {
m_colorTable1[i]=qRgba((i - magmaColorsMax) *4,
((i - magmaColorsMax) *2) +120,
(i - magmaColorsMax) *5, terrainTransparency);
} elseif (i < underWaterGroundColorsMax) {
m_colorTable1[i]=qRgba(((layerColorThickness - i - aboveWaterGroundColorsMax)) +70,
((layerColorThickness - i - aboveWaterGroundColorsMax) *2) +20,
((layerColorThickness - i - aboveWaterGroundColorsMax)) +50,
terrainTransparency);
} elseif (i < waterColorsMax) {
m_colorTable1[i]=qRgba(0,0, ((i - underWaterGroundColorsMax) *2) +120,
terrainTransparency);
} else {
m_colorTable1[i]=qRgba(0,0,0,0); // Not used
}
}
m_colorTable1[airColorIndex]=qRgba(0,0,0,0);
m_colorTable1[mineShaftColorIndex]=qRgba(50,50,50,255);
// The alternate color table just has gray gradients for all terrain except waterfor (int i =0; i < colorTableSize -2; i++) {
if (i < magmaColorsMax) {
m_colorTable2[i]=qRgba(((i - aboveWaterGroundColorsMax) *2),
((i - aboveWaterGroundColorsMax) *2),
((i - aboveWaterGroundColorsMax) *2),255);
} elseif (i < underWaterGroundColorsMax) {
m_colorTable2[i]=qRgba(((i - aboveWaterGroundColorsMax) *2),
((i - aboveWaterGroundColorsMax) *2),
((i - aboveWaterGroundColorsMax) *2), terrainTransparency);
} elseif (i < waterColorsMax) {
m_colorTable2[i]=qRgba(0,0, ((i - underWaterGroundColorsMax) *2) +120,
terrainTransparency);
} else {
m_colorTable2[i]=qRgba(0,0,0,0); // Not used
}
}
m_colorTable2[airColorIndex]=qRgba(0,0,0,0);
m_colorTable2[mineShaftColorIndex]=qRgba(255,255,0,255);
m_volumeItem->setColorTable(m_colorTable1);
m_volumeItem->setSliceFrameGaps(QVector3D(0.01f,0.02f,0.01f));
m_volumeItem->setSliceFrameThicknesses(QVector3D(0.0025f,0.005f,0.0025f));
m_volumeItem->setSliceFrameWidths(QVector3D(0.0025f,0.005f,0.0025f));
m_volumeItem->setDrawSliceFrames(false);
handleSlicingChanges();
m_graph->addCustomItem(m_volumeItem);
m_timer.start(0);
} else {
// OpenGL ES2 doesn't support 3D textures, so show a warning label instead
QCustom3DLabel *warningLabel =new QCustom3DLabel(
"QCustom3DVolume is not supported with OpenGL ES2",QFont(),
QVector3D(0.0f,0.5f,0.0f),
QVector3D(1.5f,1.5f,0.0f),QQuaternion());
warningLabel->setPositionAbsolute(true);
warningLabel->setFacingCamera(true);
m_graph->addCustomItem(warningLabel);
}
QObject::connect(m_graph,&QAbstract3DGraph::currentFpsChanged,this,&VolumetricModifier::handleFpsChange);
QObject::connect(&m_timer,&QTimer::timeout,this,&VolumetricModifier::handleTimeout);
}
VolumetricModifier::~VolumetricModifier()
{
delete m_graph;
}
void VolumetricModifier::setFpsLabel(QLabel*fpsLabel)
{
m_fpsLabel = fpsLabel;
}
void VolumetricModifier::setMediumDetailRB(QRadioButton*button)
{
m_mediumDetailRB = button;
}
void VolumetricModifier::setHighDetailRB(QRadioButton*button)
{
m_highDetailRB = button;
}
void VolumetricModifier::setSliceLabels(QLabel*xLabel,QLabel*yLabel,QLabel*zLabel)
{
m_sliceLabelX = xLabel;
m_sliceLabelY = yLabel;
m_sliceLabelZ = zLabel;
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
void VolumetricModifier::setAlphaMultiplierLabel(QLabel*label)
{
m_alphaMultiplierLabel = label;
}
void VolumetricModifier::sliceX(int enabled)
{
m_slicingX = enabled;
handleSlicingChanges();
}
void VolumetricModifier::sliceY(int enabled)
{
m_slicingY = enabled;
handleSlicingChanges();
}
void VolumetricModifier::sliceZ(int enabled)
{
m_slicingZ = enabled;
handleSlicingChanges();
}
void VolumetricModifier::adjustSliceX(int value)
{
if (m_volumeItem) {
m_sliceIndexX = value / (1024/ m_volumeItem->textureWidth());
if (m_sliceIndexX == m_volumeItem->textureWidth())
m_sliceIndexX--;
if (m_volumeItem->sliceIndexX() !=-1)
m_volumeItem->setSliceIndexX(m_sliceIndexX);
m_sliceLabelX->setPixmap(
QPixmap::fromImage(m_volumeItem->renderSlice(Qt::XAxis, m_sliceIndexX)));
}
}
void VolumetricModifier::adjustSliceY(int value)
{
if (m_volumeItem) {
m_sliceIndexY = value / (1024/ m_volumeItem->textureHeight());
if (m_sliceIndexY == m_volumeItem->textureHeight())
m_sliceIndexY--;
if (m_volumeItem->sliceIndexY() !=-1)
m_volumeItem->setSliceIndexY(m_sliceIndexY);
m_sliceLabelY->setPixmap(
QPixmap::fromImage(m_volumeItem->renderSlice(Qt::YAxis, m_sliceIndexY)));
}
}
void VolumetricModifier::adjustSliceZ(int value)
{
if (m_volumeItem) {
m_sliceIndexZ = value / (1024/ m_volumeItem->textureDepth());
if (m_sliceIndexZ == m_volumeItem->textureDepth())
m_sliceIndexZ--;
if (m_volumeItem->sliceIndexZ() !=-1)
m_volumeItem->setSliceIndexZ(m_sliceIndexZ);
m_sliceLabelZ->setPixmap(
QPixmap::fromImage(m_volumeItem->renderSlice(Qt::ZAxis, m_sliceIndexZ)));
}
}
void VolumetricModifier::handleFpsChange(qreal fps)
{
constQString fpsFormat =QStringLiteral("FPS: %1");
int fps10 =int(fps *10.0);
m_fpsLabel->setText(fpsFormat.arg(qreal(fps10) /10.0));
}
void VolumetricModifier::handleTimeout()
{
if (!m_mediumDetailRB->isEnabled()) {
if (m_mediumDetailIndex != mediumDetailSize) {
m_mediumDetailIndex = createVolume(mediumDetailSize, m_mediumDetailIndex,4,
m_mediumDetailData);
} elseif (m_mediumDetailShaftIndex != m_mineShaftArray.size()) {
m_mediumDetailShaftIndex = excavateMineShaft(mediumDetailSize, m_mediumDetailShaftIndex,1, m_mediumDetailData );
} else {
m_mediumDetailRB->setEnabled(true);
QString label =QStringLiteral("Medium (%1x%2x%1)");
m_mediumDetailRB->setText(label.arg(mediumDetailSize).arg(mediumDetailSize /2));
}
} elseif (!m_highDetailRB->isEnabled()) {
if (m_highDetailIndex != highDetailSize) {
m_highDetailIndex = createVolume(highDetailSize, m_highDetailIndex,1,
m_highDetailData);
} elseif (m_highDetailShaftIndex != m_mineShaftArray.size()) {
m_highDetailShaftIndex = excavateMineShaft(highDetailSize, m_highDetailShaftIndex,1,
m_highDetailData);
} else {
m_highDetailRB->setEnabled(true);
QString label =QStringLiteral("High (%1x%2x%1)");
m_highDetailRB->setText(label.arg(highDetailSize).arg(highDetailSize /2));
m_timer.stop();
}
}
}
void VolumetricModifier::toggleLowDetail(bool enabled)
{
if (enabled && m_volumeItem) {
m_volumeItem->setTextureData(newQVector<uchar>(*m_lowDetailData));
m_volumeItem->setTextureDimensions(lowDetailSize, lowDetailSize /2, lowDetailSize);
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::toggleMediumDetail(bool enabled)
{
if (enabled && m_volumeItem) {
m_volumeItem->setTextureData(newQVector<uchar>(*m_mediumDetailData));
m_volumeItem->setTextureDimensions(mediumDetailSize, mediumDetailSize /2, mediumDetailSize);
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::toggleHighDetail(bool enabled)
{
if (enabled && m_volumeItem) {
m_volumeItem->setTextureData(newQVector<uchar>(*m_highDetailData));
m_volumeItem->setTextureDimensions(highDetailSize, highDetailSize /2, highDetailSize);
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::setFpsMeasurement(bool enabled)
{
m_graph->setMeasureFps(enabled);
if (enabled)
m_fpsLabel->setText(QStringLiteral("Measuring..."));
else
m_fpsLabel->setText(QString());
}
void VolumetricModifier::setSliceSliders(QSlider*sliderX,QSlider*sliderY,QSlider*sliderZ)
{
m_sliceSliderX = sliderX;
m_sliceSliderY = sliderY;
m_sliceSliderZ = sliderZ;
// Set sliders to interesting values
m_sliceSliderX->setValue(715);
m_sliceSliderY->setValue(612);
m_sliceSliderZ->setValue(715);
}
void VolumetricModifier::changeColorTable(int enabled)
{
if (m_volumeItem) {
if (enabled)
m_volumeItem->setColorTable(m_colorTable2);
else
m_volumeItem->setColorTable(m_colorTable1);
m_usingPrimaryTable =!enabled;
// Rerender image labels
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::setPreserveOpacity(bool enabled)
{
if (m_volumeItem) {
m_volumeItem->setPreserveOpacity(enabled);
// Rerender image labels
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::setTransparentGround(bool enabled)
{
if (m_volumeItem) {
int newAlpha = enabled ? terrainTransparency : 255;
for (int i = aboveWaterGroundColorsMin; i < underWaterGroundColorsMax; i++) {
QRgb oldColor1 = m_colorTable1.at(i);
QRgb oldColor2 = m_colorTable2.at(i);
m_colorTable1[i]=qRgba(qRed(oldColor1),qGreen(oldColor1),qBlue(oldColor1), newAlpha);
m_colorTable2[i]=qRgba(qRed(oldColor2),qGreen(oldColor2),qBlue(oldColor2), newAlpha);
}
if (m_usingPrimaryTable)
m_volumeItem->setColorTable(m_colorTable1);
else
m_volumeItem->setColorTable(m_colorTable2);
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::setUseHighDefShader(bool enabled)
{
if (m_volumeItem) {
m_volumeItem->setUseHighDefShader(enabled);
}
}
void VolumetricModifier::adjustAlphaMultiplier(int value)
{
if (m_volumeItem) {
float mult;
if (value >100)
mult =float(value -99) /2.0f;
else
mult =float(value) /float(500- value *4);
m_volumeItem->setAlphaMultiplier(mult);
QString labelFormat =QStringLiteral("Alpha multiplier: %1");
m_alphaMultiplierLabel->setText(labelFormat.arg(
QString::number(m_volumeItem->alphaMultiplier(),'f',3)));
// Rerender image labels
adjustSliceX(m_sliceSliderX->value());
adjustSliceY(m_sliceSliderY->value());
adjustSliceZ(m_sliceSliderZ->value());
}
}
void VolumetricModifier::toggleAreaAll(bool enabled)
{
if (enabled) {
m_graph->axisX()->setRange(0.0f,1000.0f);
m_graph->axisY()->setRange(-600.0f,600.0f);
m_graph->axisZ()->setRange(0.0f,1000.0f);
m_graph->axisX()->setSegmentCount(5);
m_graph->axisY()->setSegmentCount(6);
m_graph->axisZ()->setSegmentCount(5);
}
}
void VolumetricModifier::toggleAreaMine(bool enabled)
{
if (enabled) {
m_graph->axisX()->setRange(350.0f,850.0f);
m_graph->axisY()->setRange(-500.0f,100.0f);
m_graph->axisZ()->setRange(350.0f,900.0f);
m_graph->axisX()->setSegmentCount(10);
m_graph->axisY()->setSegmentCount(6);
m_graph->axisZ()->setSegmentCount(11);
}
}
void VolumetricModifier::toggleAreaMountain(bool enabled)
{
if (enabled) {
m_graph->axisX()->setRange(300.0f,600.0f);
m_graph->axisY()->setRange(-100.0f,400.0f);
m_graph->axisZ()->setRange(300.0f,600.0f);
m_graph->axisX()->setSegmentCount(9);
m_graph->axisY()->setSegmentCount(5);
m_graph->axisZ()->setSegmentCount(9);
}
}
void VolumetricModifier::setDrawSliceFrames(int enabled)
{
if (m_volumeItem)
m_volumeItem->setDrawSliceFrames(enabled);
}
void VolumetricModifier::initHeightMap(QString fileName,QVector<uchar>&layerData)
{
QImage heightImage(fileName);
layerData.resize(layerDataSize * layerDataSize);
constuchar*bits = heightImage.bits();
int index =0;
QVector<QRgb> colorTable = heightImage.colorTable();
for (int i =0; i < layerDataSize; i++) {
for (int j =0; j < layerDataSize; j++) {
layerData[index]=qRed(colorTable.at(bits[index]));
index++;
}
}
}
int VolumetricModifier::createVolume(int textureSize,int startIndex,int count,QVector<uchar>*textureData)
{
// Generate volume from layer data.int index = startIndex * textureSize * textureSize /2.0f;
int endIndex = startIndex + count;
if (endIndex > textureSize)
endIndex = textureSize;
QVector<uchar> magmaHeights(textureSize);
QVector<uchar> waterHeights(textureSize);
QVector<uchar> groundHeights(textureSize);
float multiplier =float(layerDataSize) /float(textureSize);
for (int i = startIndex; i < endIndex; i++) {
// Generate layer height arraysfor (int l =0; l < textureSize; l++) {
int layerIndex = (int(i * multiplier) * layerDataSize +int(l * multiplier));
magmaHeights[l]=int(m_magmaLayer.at(layerIndex));
waterHeights[l]=int(m_waterLayer.at(layerIndex));
groundHeights[l]=int(m_groundLayer.at(layerIndex));
}
for (int j =0; j < textureSize /2; j++) {
for (int k =0; k < textureSize; k++) {
int colorIndex;
int height((layerDataSize - (j *2* multiplier)) /2);
if (height < magmaHeights.at(k)) {
// Magma layer
colorIndex =int((float(height) / heightToColorDiv)
*float(layerColorThickness)) + magmaColorsMin;
} elseif (height < groundHeights.at(k) && height < waterHeights.at(k)) {
// Ground layer below water
colorIndex =int((float(waterHeights.at(k) - height) / heightToColorDiv)
*float(layerColorThickness)) + underWaterGroundColorsMin;
} elseif (height < waterHeights.at(k)) {
// Water layer where water goes over ground
colorIndex =int((float(height - magmaHeights.at(k)) / heightToColorDiv)
*float(layerColorThickness)) + waterColorsMin;
} elseif (height <= groundHeights.at(k)) {
// Ground above water
colorIndex =int((float(height - waterHeights.at(k)) / heightToColorDiv)
*float(layerColorThickness)) + aboveWaterGroundColorsMin;
} else {
// Rest is air
colorIndex = airColorIndex;
}
(*textureData)[index]= colorIndex;
index++;
}
}
}
return endIndex;
}
int VolumetricModifier::excavateMineShaft(int textureSize,int startIndex,int count,QVector<uchar>*textureData)
{
int endIndex = startIndex + count;
if (endIndex > m_mineShaftArray.size())
endIndex = m_mineShaftArray.size();
int shaftSize = mineShaftDiameter * textureSize / lowDetailSize;
for (int i = startIndex; i < endIndex; i++) {
QVector3D shaftStart(m_mineShaftArray.at(i).first);
QVector3D shaftEnd(m_mineShaftArray.at(i).second);
int shaftLen = (shaftEnd - shaftStart).length() * lowDetailSize;
int dataX = shaftStart.x() * textureSize - (shaftSize /2);
int dataY = (shaftStart.y() * textureSize - (shaftSize /2)) /2;
int dataZ = shaftStart.z() * textureSize - (shaftSize /2);
int dataIndex = dataX + (dataY * textureSize) + dataZ * (textureSize * textureSize /2);
if (shaftStart.x() != shaftEnd.x()) {
for (int j =0; j <= shaftLen; j++) {
excavateMineBlock(textureSize, dataIndex, shaftSize, textureData);
dataIndex += shaftSize;
}
} elseif (shaftStart.y() != shaftEnd.y()) {
shaftLen /=2; // Vertical shafts are half as longfor (int j =0; j <= shaftLen; j++) {
excavateMineBlock(textureSize, dataIndex, shaftSize, textureData);
dataIndex += textureSize * shaftSize;
}
} else {
for (int j =0; j <= shaftLen; j++) {
excavateMineBlock(textureSize, dataIndex, shaftSize, textureData);
dataIndex += (textureSize * textureSize /2) * shaftSize;
}
}
}
return endIndex;
}
void VolumetricModifier::excavateMineBlock(int textureSize,int dataIndex,int size,QVector<uchar>*textureData)
{
for (int k =0; k < size; k++) {
int curIndex = dataIndex + (k * textureSize * textureSize /2);
for (int l =0; l < size; l++) {
curIndex = dataIndex + (k * textureSize * textureSize /2)
+ (l * textureSize);
for (int m =0; m < size; m++) {
if (textureData->at(curIndex) != airColorIndex)
(*textureData)[curIndex]= mineShaftColorIndex;
curIndex++;
}
}
}
}
void VolumetricModifier::handleSlicingChanges()
{
if (m_volumeItem) {
if (m_slicingX || m_slicingY || m_slicingZ) {
// Only show slices of selected dimensions
m_volumeItem->setDrawSlices(true);
m_volumeItem->setSliceIndexX(m_slicingX ? m_sliceIndexX : -1);
m_volumeItem->setSliceIndexY(m_slicingY ? m_sliceIndexY : -1);
m_volumeItem->setSliceIndexZ(m_slicingZ ? m_sliceIndexZ : -1);
} else {
// Show slice frames for all dimenstions when not actually slicing
m_volumeItem->setDrawSlices(false);
m_volumeItem->setSliceIndexX(m_sliceIndexX);
m_volumeItem->setSliceIndexY(m_sliceIndexY);
m_volumeItem->setSliceIndexZ(m_sliceIndexZ);
}
}
}
void VolumetricModifier::initMineShaftArray()
{
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.7f,0.1f,0.7f),
QVector3D(0.7f,0.8f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.7f,0.7f,0.5f),
QVector3D(0.7f,0.7f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.4f,0.7f,0.7f),
QVector3D(0.7f,0.7f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.4f,0.7f,0.7f),
QVector3D(0.4f,0.7f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.45f,0.7f,0.7f),
QVector3D(0.45f,0.7f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.5f,0.7f,0.7f),
QVector3D(0.5f,0.7f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.55f,0.7f,0.7f),
QVector3D(0.55f,0.7f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.7f),
QVector3D(0.6f,0.7f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.65f,0.7f,0.7f),
QVector3D(0.65f,0.7f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.5f,0.6f,0.7f),
QVector3D(0.7f,0.6f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.5f,0.6f,0.7f),
QVector3D(0.5f,0.6f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.55f,0.6f,0.7f),
QVector3D(0.55f,0.6f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.7f),
QVector3D(0.6f,0.6f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.65f,0.6f,0.7f),
QVector3D(0.65f,0.6f,0.8f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.7f,0.6f,0.4f),
QVector3D(0.7f,0.6f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.45f),
QVector3D(0.8f,0.6f,0.45f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.5f),
QVector3D(0.8f,0.6f,0.5f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.55f),
QVector3D(0.8f,0.6f,0.55f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.6f),
QVector3D(0.8f,0.6f,0.6f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.65f),
QVector3D(0.8f,0.6f,0.65f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.6f,0.7f),
QVector3D(0.8f,0.6f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.7f,0.7f,0.4f),
QVector3D(0.7f,0.7f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.45f),
QVector3D(0.8f,0.7f,0.45f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.5f),
QVector3D(0.8f,0.7f,0.5f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.55f),
QVector3D(0.8f,0.7f,0.55f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.6f),
QVector3D(0.8f,0.7f,0.6f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.65f),
QVector3D(0.8f,0.7f,0.65f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.7f,0.7f),
QVector3D(0.8f,0.7f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.7f,0.8f,0.5f),
QVector3D(0.7f,0.8f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.8f,0.55f),
QVector3D(0.8f,0.8f,0.55f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.8f,0.6f),
QVector3D(0.8f,0.8f,0.6f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.8f,0.65f),
QVector3D(0.8f,0.8f,0.65f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.6f,0.8f,0.7f),
QVector3D(0.8f,0.8f,0.7f));
m_mineShaftArray <<QPair<QVector3D, QVector3D>(QVector3D(0.7f,0.1f,0.4f),
QVector3D(0.7f,0.7f,0.4f));
}