mirror of https://github.com/qt/qtdatavis3d.git
QML support for volume items
Change-Id: I4061bfd4d288aabaea76847c9f692e71ecf5f94c Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
This commit is contained in:
parent
57726e6752
commit
d85e665b11
|
|
@ -119,6 +119,7 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri)
|
|||
// New types
|
||||
qmlRegisterType<Q3DInputHandler>(uri, 1, 2, "InputHandler3D");
|
||||
qmlRegisterType<QTouch3DInputHandler>(uri, 1, 2, "TouchInputHandler3D");
|
||||
qmlRegisterType<QCustom3DVolume>(uri, 1, 2, "Custom3DVolume");
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_DATAVISUALIZATION
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "declarativescene_p.h"
|
||||
#include "qcustom3ditem.h"
|
||||
#include "qcustom3dlabel.h"
|
||||
#include "qcustom3dvolume.h"
|
||||
|
||||
#include <QtQml/QQmlExtensionPlugin>
|
||||
|
||||
|
|
@ -103,6 +104,7 @@ QML_DECLARE_TYPE(QTouch3DInputHandler)
|
|||
|
||||
QML_DECLARE_TYPE(QCustom3DItem)
|
||||
QML_DECLARE_TYPE(QCustom3DLabel)
|
||||
QML_DECLARE_TYPE(QCustom3DVolume)
|
||||
|
||||
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc
|
||||
** All rights reserved.
|
||||
** For any questions to Digia, please use contact form at http://qt.digia.com
|
||||
**
|
||||
** This file is part of the QtDataVisualization module.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise licenses may use this file in
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please use
|
||||
** contact form at http://qt.digia.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "datasource.h"
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QtGui/QRgb>
|
||||
#include <QtGui/QVector3D>
|
||||
|
||||
using namespace QtDataVisualization;
|
||||
|
||||
Q_DECLARE_METATYPE(QCustom3DVolume *)
|
||||
|
||||
DataSource::DataSource(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
qRegisterMetaType<QCustom3DVolume *>();
|
||||
}
|
||||
|
||||
DataSource::~DataSource()
|
||||
{
|
||||
}
|
||||
|
||||
void DataSource::fillVolume(QCustom3DVolume *volumeItem)
|
||||
{
|
||||
// Generate example texture data for an half-ellipsoid with a section missing.
|
||||
// This can take a while if the dimensions are large, so we support incremental data generation.
|
||||
|
||||
int index = 0;
|
||||
int textureSize = 256;
|
||||
QVector3D midPoint(float(textureSize) / 2.0f,
|
||||
float(textureSize) / 2.0f,
|
||||
float(textureSize) / 2.0f);
|
||||
|
||||
QVector<uchar> *textureData = new QVector<uchar>(textureSize * textureSize * textureSize / 2);
|
||||
for (int i = 0; i < textureSize; i++) {
|
||||
for (int j = 0; j < textureSize / 2; j++) {
|
||||
for (int k = 0; k < textureSize; k++) {
|
||||
int colorIndex = 0;
|
||||
// Take a section out of the ellipsoid
|
||||
if (i >= textureSize / 2 || j >= textureSize / 4 || k >= textureSize / 2) {
|
||||
QVector3D distVec = QVector3D(float(k), float(j * 2), float(i)) - midPoint;
|
||||
float adjLen = qMin(255.0f, (distVec.length() * 512.0f / float(textureSize)));
|
||||
colorIndex = 255 - int(adjLen);
|
||||
}
|
||||
|
||||
(*textureData)[index] = colorIndex;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
volumeItem->setScaling(QVector3D(2.0f, 1.0f, 2.0f));
|
||||
volumeItem->setTextureWidth(textureSize);
|
||||
volumeItem->setTextureHeight(textureSize / 2);
|
||||
volumeItem->setTextureDepth(textureSize);
|
||||
volumeItem->setTextureFormat(QImage::Format_Indexed8);
|
||||
volumeItem->setTextureData(textureData);
|
||||
|
||||
QVector<QRgb> colorTable(256);
|
||||
|
||||
for (int i = 1; i < 256; i++) {
|
||||
if (i < 15)
|
||||
colorTable[i] = qRgba(0, 0, 0, 0);
|
||||
else if (i < 60)
|
||||
colorTable[i] = qRgba((i * 2) + 120, 0, 0, 15);
|
||||
else if (i < 120)
|
||||
colorTable[i] = qRgba(0, ((i - 60) * 2) + 120, 0, 50);
|
||||
else if (i < 180)
|
||||
colorTable[i] = qRgba(0, 0, ((i - 120) * 2) + 120, 255);
|
||||
else
|
||||
colorTable[i] = qRgba(i, i, i, 255);
|
||||
}
|
||||
|
||||
volumeItem->setColorTable(colorTable);
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc
|
||||
** All rights reserved.
|
||||
** For any questions to Digia, please use contact form at http://qt.digia.com
|
||||
**
|
||||
** This file is part of the QtDataVisualization module.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise licenses may use this file in
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please use
|
||||
** contact form at http://qt.digia.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DATASOURCE_H
|
||||
#define DATASOURCE_H
|
||||
|
||||
#include <QtDataVisualization/QCustom3DVolume>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
using namespace QtDataVisualization;
|
||||
|
||||
class DataSource : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DataSource(QObject *parent = 0);
|
||||
virtual ~DataSource();
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void fillVolume(QCustom3DVolume *volumeItem);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc
|
||||
** All rights reserved.
|
||||
** For any questions to Digia, please use contact form at http://qt.digia.com
|
||||
**
|
||||
** This file is part of the QtDataVisualization module.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise licenses may use this file in
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please use
|
||||
** contact form at http://qt.digia.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "datasource.h"
|
||||
|
||||
#include <QtDataVisualization/qutils.h>
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtQml/QQmlContext>
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <QtQml/QQmlEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQuickView viewer;
|
||||
|
||||
// The following are needed to make examples run without having to install the module
|
||||
// in desktop environments.
|
||||
#ifdef Q_OS_WIN
|
||||
QString extraImportPath(QStringLiteral("%1/../../../%2"));
|
||||
#else
|
||||
QString extraImportPath(QStringLiteral("%1/../../%2"));
|
||||
#endif
|
||||
viewer.engine()->addImportPath(extraImportPath.arg(QGuiApplication::applicationDirPath(),
|
||||
QString::fromLatin1("qml")));
|
||||
QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);
|
||||
|
||||
viewer.setTitle(QStringLiteral("QML volume example"));
|
||||
|
||||
DataSource dataSource;
|
||||
viewer.rootContext()->setContextProperty("dataSource", &dataSource);
|
||||
|
||||
viewer.setSource(QUrl("qrc:/qml/qmlvolume/main.qml"));
|
||||
viewer.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
viewer.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc
|
||||
** All rights reserved.
|
||||
** For any questions to Digia, please use contact form at http://qt.digia.com
|
||||
**
|
||||
** This file is part of the QtDataVisualization module.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise licenses may use this file in
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please use
|
||||
** contact form at http://qt.digia.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Controls.Styles 1.0
|
||||
|
||||
Item {
|
||||
id: newbutton
|
||||
|
||||
property alias text: buttonText.text
|
||||
|
||||
signal clicked
|
||||
|
||||
implicitWidth: buttonText.implicitWidth + 5
|
||||
implicitHeight: buttonText.implicitHeight + 10
|
||||
|
||||
Button {
|
||||
id: buttonText
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
style: ButtonStyle {
|
||||
label: Component {
|
||||
Text {
|
||||
text: buttonText.text
|
||||
clip: true
|
||||
wrapMode: Text.WordWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: newbutton.clicked()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc
|
||||
** All rights reserved.
|
||||
** For any questions to Digia, please use contact form at http://qt.digia.com
|
||||
**
|
||||
** This file is part of the QtDataVisualization module.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise licenses may use this file in
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please use
|
||||
** contact form at http://qt.digia.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 1.0
|
||||
import QtDataVisualization 1.2
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: mainView
|
||||
width: 1280
|
||||
height: 1024
|
||||
|
||||
Item {
|
||||
id: dataView
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
height: parent.height - buttonLayout.height
|
||||
|
||||
Surface3D {
|
||||
id: surfaceGraph
|
||||
|
||||
width: dataView.width
|
||||
height: dataView.height
|
||||
orthoProjection: true
|
||||
measureFps: true
|
||||
|
||||
onCurrentFpsChanged: {
|
||||
if (fps > 10)
|
||||
fpsText.text = "FPS: " + Math.round(surfaceGraph.currentFps)
|
||||
else
|
||||
fpsText.text = "FPS: " + Math.round(surfaceGraph.currentFps * 10.0) / 10.0
|
||||
}
|
||||
|
||||
Surface3DSeries {
|
||||
id: surfaceSeries
|
||||
drawMode: Surface3DSeries.DrawSurface;
|
||||
flatShadingEnabled: false;
|
||||
meshSmooth: true
|
||||
itemLabelFormat: "@xLabel, @zLabel: @yLabel"
|
||||
itemLabelVisible: false
|
||||
|
||||
onItemLabelChanged: {
|
||||
if (surfaceSeries.selectedPoint === surfaceSeries.invalidSelectionPosition)
|
||||
selectionText.text = "No selection"
|
||||
else
|
||||
selectionText.text = surfaceSeries.itemLabel
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
mainView.createVolume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
color: surfaceGraph.theme.backgroundColor
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
RowLayout {
|
||||
id: sliderLayout
|
||||
anchors.top: parent.top
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 150
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: fpsText.implicitWidth + 10
|
||||
Layout.maximumWidth: fpsText.implicitWidth + 10
|
||||
Layout.minimumHeight: 50
|
||||
Layout.maximumHeight: 50
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
border.color: "gray"
|
||||
border.width: 1
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
id: fpsText
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: buttonLayout
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 50
|
||||
anchors.bottom: parent.bottom
|
||||
spacing: 0
|
||||
|
||||
NewButton {
|
||||
id: sliceButton
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: "Slice"
|
||||
|
||||
onClicked: {
|
||||
if (volumeItem.sliceIndexZ == -1)
|
||||
volumeItem.sliceIndexZ = 128
|
||||
else
|
||||
volumeItem.sliceIndexZ = -1
|
||||
}
|
||||
}
|
||||
NewButton {
|
||||
id: exitButton
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: "Quit"
|
||||
|
||||
onClicked: Qt.quit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Custom3DVolume {
|
||||
id: volumeItem
|
||||
alphaMultiplier: 0.3
|
||||
preserveOpacity: true
|
||||
useHighDefShader: false
|
||||
}
|
||||
|
||||
function createVolume() {
|
||||
surfaceGraph.addCustomItem(volumeItem)
|
||||
dataSource.fillVolume(volumeItem)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
!include( ../tests.pri ) {
|
||||
error( "Couldn't find the tests.pri file!" )
|
||||
}
|
||||
|
||||
QT += datavisualization
|
||||
|
||||
# The .cpp file which was generated for your project. Feel free to hack it.
|
||||
SOURCES += main.cpp \
|
||||
datasource.cpp
|
||||
HEADERS += datasource.h
|
||||
|
||||
RESOURCES += qmlvolume.qrc
|
||||
|
||||
OTHER_FILES += doc/src/* \
|
||||
doc/images/* \
|
||||
qml/qmlvolume/*
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>qml/qmlvolume/main.qml</file>
|
||||
<file>qml/qmlvolume/NewButton.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
@ -17,7 +17,8 @@ SUBDIRS += barstest \
|
|||
qmlmultiwindow \
|
||||
itemmodeltest \
|
||||
qmlmultitest \
|
||||
volumetrictest
|
||||
volumetrictest \
|
||||
qmlvolume
|
||||
|
||||
#SUBDIRS += kinectsurface
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue