diff options
Diffstat (limited to 'tradeshow/enterprise-kinectdatavis')
29 files changed, 2078 insertions, 0 deletions
diff --git a/tradeshow/enterprise-kinectdatavis/AttitudeIndicator.qml b/tradeshow/enterprise-kinectdatavis/AttitudeIndicator.qml new file mode 100644 index 0000000..e9750d6 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/AttitudeIndicator.qml @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.1 + +Item { + id: main + property vector3d accel + property real roll: Math.atan(-accel.x / accel.y) + property real pitch: Math.atan(accel.z / accel.y) + + property real squareSize: Math.min(width, height) + Item { + clip: true + width: squareSize + height: squareSize + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + Item { + id: rollDisplay + anchors.fill: parent + + rotation: main.roll * (180/Math.PI) + + Item { + id: pitchDisplay + width: parent.width + height: parent.height + + property real sensorDegToHeightRatio: 1/50 * height + property real heightFor90Degrees: 90 * sensorDegToHeightRatio + y: main.pitch * (180/Math.PI) * sensorDegToHeightRatio + + Rectangle { + id: sky + y: -height + width: parent.width + height: pitchDisplay.heightFor90Degrees + parent.height / 2 + color: '#66B2FF' + } + Rectangle { + id: ground + y: parent.height + width: parent.width + height: pitchDisplay.heightFor90Degrees + parent.height / 2 + color: '#664000' + } + Canvas { + anchors.fill: parent + + function drawGraduation(ctx, lineHalfWidth, centerX, y) { + ctx.beginPath() + ctx.moveTo(centerX - lineHalfWidth, y) + ctx.lineTo(centerX + lineHalfWidth, y) + ctx.stroke(); + } + onPaint: { + var ctx = getContext('2d') + var centerX = width / 2 + var centerY = height / 2 + + ctx.fillStyle = sky.color + var grd = ctx.createLinearGradient(0, 0, 0, centerY); + grd.addColorStop(0, sky.color); + grd.addColorStop(1, Qt.darker(sky.color, 1.5)); + ctx.fillStyle = grd; + ctx.fillRect(0, 0, width, centerY) + ctx.fillStyle = ground.color + var grd = ctx.createLinearGradient(0, centerY, 0, height); + grd.addColorStop(0, Qt.lighter(ground.color, 1.5)); + grd.addColorStop(1, ground.color); + ctx.fillStyle = grd; + ctx.fillRect(0, centerY, width, height) + + // Horizon line + ctx.strokeStyle = 'white' + ctx.lineWidth = 4 + ctx.moveTo(0, centerY) + ctx.lineTo(width, centerY) + ctx.stroke(); + + // Graduation + var lineHalfWidth = width / 16 + var shortLineHalfWidth = width / 32 + ctx.lineWidth = 2 + drawGraduation(ctx, lineHalfWidth, centerX, centerY - 5 * pitchDisplay.sensorDegToHeightRatio) + drawGraduation(ctx, lineHalfWidth*1.5, centerX, centerY - 10 * pitchDisplay.sensorDegToHeightRatio) + drawGraduation(ctx, lineHalfWidth, centerX, centerY + 5 * pitchDisplay.sensorDegToHeightRatio) + drawGraduation(ctx, lineHalfWidth*1.5, centerX, centerY + 10 * pitchDisplay.sensorDegToHeightRatio) + ctx.lineWidth = 1 + drawGraduation(ctx, shortLineHalfWidth, centerX, centerY - 2.5 * pitchDisplay.sensorDegToHeightRatio) + drawGraduation(ctx, shortLineHalfWidth, centerX, centerY - 7.5 * pitchDisplay.sensorDegToHeightRatio) + drawGraduation(ctx, shortLineHalfWidth, centerX, centerY + 2.5 * pitchDisplay.sensorDegToHeightRatio) + drawGraduation(ctx, shortLineHalfWidth, centerX, centerY + 7.5 * pitchDisplay.sensorDegToHeightRatio) + } + } + } + Canvas { + id: rollFrame + property real holeRadius: width * 0.8 / 2 + anchors.fill: parent + function drawLineToRadian(ctx, centerX, centerY, radian, radius) { + ctx.beginPath() + ctx.moveTo(centerX, centerY) + var x = radius * Math.cos(radian) + centerX + var y = -radius * Math.sin(radian) + centerY + ctx.lineTo(x, y) + ctx.stroke(); + } + onPaint: { + var ctx = getContext('2d') + ctx.save() + var grd = ctx.createLinearGradient(0, 0, width, height); + grd.addColorStop(0, '#404040'); + grd.addColorStop(1, '#202020'); + ctx.fillStyle = grd; + ctx.fillRect(0, 0, width, height) + + ctx.strokeStyle = 'white' + ctx.lineWidth = 4 + ctx.moveTo(0, height / 2) + ctx.lineTo(width, height / 2) + ctx.stroke(); + + var centerX = width / 2 + var centerY = height / 2 + var longRadius = width / 2 + var mediumRadius = width * 0.95 / 2 + var shortRadius = width * 0.9 / 2 + ctx.strokeStyle = 'white' + ctx.lineWidth = 4 + drawLineToRadian(ctx, centerX, centerY, Math.PI*0/6, longRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*1/6, mediumRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*2/6, mediumRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*3/6, longRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*4/6, mediumRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*5/6, mediumRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*6/6, longRadius) + ctx.lineWidth = 1 + drawLineToRadian(ctx, centerX, centerY, Math.PI*7/18, shortRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*8/18, shortRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*10/18, shortRadius) + drawLineToRadian(ctx, centerX, centerY, Math.PI*11/18, shortRadius) + + // Punch a hole for the pitch display + ctx.lineWidth = 4 + var grd = ctx.createLinearGradient(0, 0, width, height); + grd.addColorStop(0, '#474747'); + grd.addColorStop(1, '#272727'); + ctx.strokeStyle = grd; + ctx.fillStyle = 'transparent' + ctx.globalCompositeOperation = 'copy' + ctx.beginPath() + ctx.arc(width / 2, height / 2, holeRadius, 0, 2*Math.PI) + ctx.closePath() + ctx.fill(); + ctx.stroke(); + + // Stroke the hole again, but only for the shadow this time. + // Keep only pixels within the transparent hole. + ctx.globalCompositeOperation = 'destination-over' + ctx.shadowBlur = 3; + ctx.shadowColor = "#ff000000"; + ctx.shadowOffsetX = ctx.shadowOffsetY = ctx.lineWidth / 2 + ctx.stroke(); + ctx.restore() + } + } + } + Canvas { + id: frame + anchors.fill: parent + onPaint: { + var ctx = getContext('2d') + var centerX = width / 2 + var centerY = height / 2 + var holeHalfWidth = width / 2 + ctx.save() + ctx.fillStyle = '#101010' + ctx.fillRect(x, y, width, height) + + // Punch a hole to see layers under. + ctx.strokeStyle = '#272727' + ctx.fillStyle = 'transparent' + ctx.globalCompositeOperation = 'copy' + ctx.beginPath(); + ctx.arc(centerX, centerY, holeHalfWidth, 0, 2*Math.PI); + ctx.fill(); + ctx.stroke(); + ctx.globalCompositeOperation = 'source-over' + + // Shadow for the cross and arrow + ctx.shadowBlur = 3; + ctx.shadowColor = "#70000000"; + ctx.shadowOffsetX = ctx.shadowOffsetY = 3 + + // The center cross + var crossHalfWidth = width / 4 + ctx.strokeStyle = 'yellow' + ctx.lineCap="round"; + ctx.beginPath(); + ctx.lineWidth = 3 + ctx.moveTo(centerX, centerY - crossHalfWidth) + ctx.lineTo(centerX, centerY + crossHalfWidth) + ctx.stroke(); + ctx.moveTo(centerX - crossHalfWidth, centerY) + ctx.lineTo(centerX + crossHalfWidth, centerY) + ctx.stroke(); + + // The arrow the the roll scale + var arrowHalfWidth = width / 64 + var arrowHeight = height / 16 + var arrowTop = centerY - rollFrame.holeRadius - arrowHeight / 3 + ctx.fillStyle = 'white' + ctx.beginPath(); + ctx.moveTo(centerX, arrowTop); + ctx.lineTo(centerX - arrowHalfWidth, arrowTop + arrowHeight); + ctx.lineTo(centerX + arrowHalfWidth, arrowTop + arrowHeight); + ctx.fill(); + ctx.restore() + } + } + } +} diff --git a/tradeshow/enterprise-kinectdatavis/ErrorPanel.qml b/tradeshow/enterprise-kinectdatavis/ErrorPanel.qml new file mode 100644 index 0000000..de7392e --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/ErrorPanel.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.1 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.0 + +Rectangle { + property alias text: label.text + border.color: label.color + color: '#afffffff' + radius: 10 + height: label.implicitHeight * 2 + + Label { + id: label + anchors.left: parent.left + anchors.right: parent.right + y: implicitHeight / 2 + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + font.pointSize: 18 + font.bold: true + + SequentialAnimation on color { + loops: Animation.Infinite + ColorAnimation { + to: "red" + duration: 2000 + } + ColorAnimation { + to: "black" + duration: 2000 + } + } + } +} diff --git a/tradeshow/enterprise-kinectdatavis/Freenect/qmldir b/tradeshow/enterprise-kinectdatavis/Freenect/qmldir new file mode 100644 index 0000000..7f85bc2 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/Freenect/qmldir @@ -0,0 +1,2 @@ +module Freenect +plugin quickfreenect diff --git a/tradeshow/enterprise-kinectdatavis/Header.qml b/tradeshow/enterprise-kinectdatavis/Header.qml new file mode 100644 index 0000000..b8a6bb6 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/Header.qml @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.1 +import QtQuick.Controls 1.2 + +Label { + font.pointSize: 18 + font.bold: true + color: "lightgrey" + style: Text.Raised + styleColor: '#707070' +} diff --git a/tradeshow/enterprise-kinectdatavis/Noise.qml b/tradeshow/enterprise-kinectdatavis/Noise.qml new file mode 100644 index 0000000..eace7c2 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/Noise.qml @@ -0,0 +1,111 @@ +/* +Copyright (C) 2011 by Ashima Arts (Simplex noise) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +import QtQuick 2.1 + +ShaderEffect { + property real time + NumberAnimation on time { + loops: Animation.Infinite + duration: 1000 + from: 30 + to: 200 + } + vertexShader: " + uniform highp mat4 qt_Matrix; + attribute highp vec4 qt_Vertex; + attribute highp vec2 qt_MultiTexCoord0; + varying highp vec2 coord; + void main() { + coord = qt_MultiTexCoord0; + gl_Position = qt_Matrix * qt_Vertex; + }" + fragmentShader: " + varying highp vec2 coord; + uniform lowp float qt_Opacity; + uniform highp float time; + uniform lowp float width; + uniform lowp float height; + + vec3 mod289(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; + } + vec2 mod289(vec2 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; + } + vec3 permute(vec3 x) { + return mod289(((x*34.0)+1.0)*x); + } + float snoise(vec2 v) + { + const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0 + 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) + -0.577350269189626, // -1.0 + 2.0 * C.x + 0.024390243902439); // 1.0 / 41.0 + // First corner + vec2 i = floor(v + dot(v, C.yy) ); + vec2 x0 = v - i + dot(i, C.xx); + + // Other corners + vec2 i1; + //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 + //i1.y = 1.0 - i1.x; + i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + // x0 = x0 - 0.0 + 0.0 * C.xx ; + // x1 = x0 - i1 + 1.0 * C.xx ; + // x2 = x0 - 1.0 + 2.0 * C.xx ; + vec4 x12 = x0.xyxy + C.xxzz; + x12.xy -= i1; + + // Permutations + i = mod289(i); // Avoid truncation effects in permutation + vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + + i.x + vec3(0.0, i1.x, 1.0 )); + + vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); + m = m*m ; + m = m*m ; + + // Gradients: 41 points uniformly over a line, mapped onto a diamond. + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) + vec3 x = 2.0 * fract(p * C.www) - 1.0; + vec3 h = abs(x) - 0.5; + vec3 ox = floor(x + 0.5); + vec3 a0 = x - ox; + + // Normalise gradients implicitly by scaling m + // Approximation of: m *= inversesqrt( a0*a0 + h*h ); + m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); + + // Compute final noise value at P + vec3 g; + g.x = a0.x * x0.x + h.x * x0.y; + g.yz = a0.yz * x12.xz + h.yz * x12.yw; + return 130.0 * dot(m, g); + } + + void main() { + float n = snoise((coord + vec2(mod(time, 12.12), 0.0)) * (vec2(width, height) / 5.0)); + n = n * 0.6 + 0.4; + gl_FragColor = vec4(n, n, n, 1.0) * qt_Opacity; + }" +} diff --git a/tradeshow/enterprise-kinectdatavis/Panel.qml b/tradeshow/enterprise-kinectdatavis/Panel.qml new file mode 100644 index 0000000..4171a33 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/Panel.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.1 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.0 + +Item { + id: main + default property alias content: container.children + property real margin: 25 + property string title + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.preferredWidth: (container.Layout.preferredWidth == -1 ? container.implicitWidth : container.Layout.preferredWidth) + margin * 2 + Layout.preferredHeight: (container.Layout.preferredHeight == -1 ? container.implicitHeight : container.Layout.preferredHeight) + margin * 2 + Layout.minimumWidth: container.Layout.minimumWidth + margin * 2 + Layout.minimumHeight: container.Layout.minimumHeight + margin * 2 + + Rectangle { + anchors.fill: parent + color: '#101010' + radius: 10 + ColumnLayout { + id: container + anchors.fill: parent + anchors.margins: main.margin + Header { + text: main.title + visible: text + } + } + } +} diff --git a/tradeshow/enterprise-kinectdatavis/README b/tradeshow/enterprise-kinectdatavis/README new file mode 100644 index 0000000..87cd307 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/README @@ -0,0 +1,14 @@ +The demo builds libfreenect from a submodule and link to the static library version into a QtQuick plugin. + +To run the demo on desktop run: + +git submodule update --init +qmake && make && ./runHere.sh + +To install on the device do (with the cross-compiled Qt's qmake): + +git submodule update --init +~/Qt/Boot2Qt-4.x/imx6qsabresd-eLinux/qt5/bin/qmake && make && ./deploy.sh + + +The deploy.sh script will also take care of installing the udev rule necessary to have access to the Kinect through USB. diff --git a/tradeshow/enterprise-kinectdatavis/RangeSlider.qml b/tradeshow/enterprise-kinectdatavis/RangeSlider.qml new file mode 100644 index 0000000..b39d658 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/RangeSlider.qml @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.1 + +Item { + id: main + property real minimumValue: 1 + property real maximumValue: 2048 + property real valueSpacing: 50 + property real lowValue: minimumValue + property real highValue: maximumValue + + implicitHeight: 50 + Component { + id: handleComponent + Image { + property alias touchPoint: lowTouchPoint + anchors.fill: parent + source: "handle.png" + MultiPointTouchArea { + id: lowTouchArea + anchors.fill: parent + touchPoints: [ + TouchPoint { + id: lowTouchPoint + property real draggedX: pressed ? sceneX - _startSceneX : 0 + property real baseX: pressed ? _startBaseX : _handleItem.x + property real _startSceneX + property real _startBaseX + + onSceneXChanged: updateHandlesPosFromDrag() + onPressedChanged: { + _startBaseX = _handleItem.x + _startSceneX = lowTouchArea.mapToItem(null, x).x + } + } + ] + } + } + } + Rectangle { + anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter } + height: 10 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightgrey" } + GradientStop { position: 1.0; color: "grey" } + } + radius: 4 + } + Rectangle { + anchors { verticalCenter: parent.verticalCenter; left: lowHandle.horizontalCenter; right: highHandle.horizontalCenter } + height: 20 + gradient: Gradient { + GradientStop { position: 0.0; color: "#006CD9" } + GradientStop { position: 1.0; color: "#00407F" } + } + } + Loader { + id: lowHandle + property var touchPoint: item.touchPoint + + anchors { top: parent.top; bottom: parent.bottom } + width: height + sourceComponent: handleComponent + + property bool _hInvertComponent: false + property Item _handleItem: this + + onXChanged: if (!_programmaticalChange) lowValue = _convert(lowHandle.x, _minimumLowPos, _maximumLowPos, minimumValue, maximumValue - valueSpacing) + } + Loader { + id: highHandle + property var touchPoint: item.touchPoint + + anchors { top: parent.top; bottom: parent.bottom } + width: height + sourceComponent: handleComponent + + property bool _hInvertComponent: true + property Item _handleItem: this + + onXChanged: if (!_programmaticalChange) highValue = _convert(highHandle.x, _minimumHighPos, _maximumHighPos, minimumValue + valueSpacing, maximumValue) + } + + property bool _programmaticalChange: false + property real _minimumLowPos: -lowHandle.width / 2 + property real _maximumHighPos: main.width - highHandle.width / 2 + property real _maximumLowPos: _maximumHighPos - lowHandle.width + property real _minimumHighPos: _minimumLowPos + lowHandle.width + on_MaximumLowPosChanged: updateHandlesPosFromLimits() + on_MaximumHighPosChanged: updateHandlesPosFromLimits() + + function _convert(src, srcMin, srcMax, dstMin, dstMax) { + return (src - srcMin) / (srcMax - srcMin) * (dstMax - dstMin) + dstMin + } + function updateHandlesPosFromDrag() { + var lowX, highX; + if (lowHandle.touchPoint.baseX + lowHandle.touchPoint.draggedX > highHandle.touchPoint.baseX + highHandle.touchPoint.draggedX - lowHandle.width) { + var overdrag = lowHandle.touchPoint.baseX + lowHandle.touchPoint.draggedX - (highHandle.touchPoint.baseX + highHandle.touchPoint.draggedX - lowHandle.width) + // Not perfect when only one touch point is pressed, but works well enough. + var handleOverdragAdj = overdrag / 2 + lowX = lowHandle.touchPoint.baseX + lowHandle.touchPoint.draggedX - handleOverdragAdj + highX = highHandle.touchPoint.baseX + highHandle.touchPoint.draggedX + handleOverdragAdj + } else { + lowX = lowHandle.touchPoint.baseX + lowHandle.touchPoint.draggedX + highX = highHandle.touchPoint.baseX + highHandle.touchPoint.draggedX + } + if (lowX < _minimumLowPos) + lowX = _minimumLowPos + if (highX < lowX + lowHandle.width) + highX = lowX + lowHandle.width + if (highX > _maximumHighPos) + highX = _maximumHighPos + if (lowX > highX - lowHandle.width) + lowX = highX - lowHandle.width + lowHandle.x = lowX + highHandle.x = highX + } + function updateHandlesPosFromLimits() { + _programmaticalChange = true + lowHandle.x = _convert(lowValue, minimumValue, maximumValue - valueSpacing, _minimumLowPos, _maximumLowPos) + highHandle.x = _convert(highValue - valueSpacing, minimumValue, maximumValue - valueSpacing, _minimumHighPos, _maximumHighPos) + _programmaticalChange = false + } +} diff --git a/tradeshow/enterprise-kinectdatavis/deploy.sh b/tradeshow/enterprise-kinectdatavis/deploy.sh new file mode 100755 index 0000000..b825add --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/deploy.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +B2QT_DEPLOYPATH=/data/user/qt/enterprise-kinectdatavis +B2QT_PLUGINDEPLOYPATH=/data/user/qt/qmlplugins/Freenect + +adb push Freenect $B2QT_PLUGINDEPLOYPATH + +adb shell mkdir -p $B2QT_DEPLOYPATH +find -name "*.qml" -exec adb push {} $B2QT_DEPLOYPATH/ \; +find -name "*.js" -exec adb push {} $B2QT_DEPLOYPATH/ \; +adb push title.txt $B2QT_DEPLOYPATH/ +adb push description.txt $B2QT_DEPLOYPATH/ +adb push preview_l.jpg $B2QT_DEPLOYPATH/ +adb push handle.png $B2QT_DEPLOYPATH/ + +adb push src/libfreenect/platform/linux/udev/51-kinect.rules /etc/udev/rules.d/51-demo-kinect.rules diff --git a/tradeshow/enterprise-kinectdatavis/description.txt b/tradeshow/enterprise-kinectdatavis/description.txt new file mode 100644 index 0000000..88e4324 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/description.txt @@ -0,0 +1 @@ +Show an example of external sensor data integration in a QtQuick user interface. diff --git a/tradeshow/enterprise-kinectdatavis/enterprise-kinectdatavis.pro b/tradeshow/enterprise-kinectdatavis/enterprise-kinectdatavis.pro new file mode 100644 index 0000000..069da53 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/enterprise-kinectdatavis.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += src diff --git a/tradeshow/enterprise-kinectdatavis/handle.png b/tradeshow/enterprise-kinectdatavis/handle.png Binary files differnew file mode 100644 index 0000000..a8a5827 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/handle.png diff --git a/tradeshow/enterprise-kinectdatavis/handle.svg b/tradeshow/enterprise-kinectdatavis/handle.svg new file mode 100644 index 0000000..b9df2de --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/handle.svg @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="50" + height="50" + id="svg3905" + version="1.1" + inkscape:version="0.48.5 r10040" + sodipodi:docname="handle.svg" + inkscape:export-filename="/home/joce/dev/freenectdemo/handle.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs3907"> + <linearGradient + id="linearGradient4570"> + <stop + id="stop4572" + offset="0" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + <stop + style="stop-color:#7f7f7f;stop-opacity:1;" + offset="0.07894737" + id="stop4574" /> + <stop + id="stop4576" + offset="0.91666669" + style="stop-color:#646464;stop-opacity:1;" /> + <stop + id="stop4578" + offset="1" + style="stop-color:#c0c0c0;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient4536"> + <stop + style="stop-color:#797979;stop-opacity:1;" + offset="0" + id="stop4538" /> + <stop + id="stop4540" + offset="0.07894737" + style="stop-color:#959595;stop-opacity:1;" /> + <stop + style="stop-color:#7d7d7d;stop-opacity:1;" + offset="0.91666669" + id="stop4542" /> + <stop + style="stop-color:#c2c2c2;stop-opacity:1;" + offset="1" + id="stop4544" /> + </linearGradient> + <linearGradient + id="linearGradient4442"> + <stop + id="stop4444" + offset="0" + style="stop-color:#c4c4c4;stop-opacity:1;" /> + <stop + style="stop-color:#959595;stop-opacity:1;" + offset="0.28571379" + id="stop4446" /> + <stop + id="stop4452" + offset="0.87499958" + style="stop-color:#7d7d7d;stop-opacity:1;" /> + <stop + id="stop4448" + offset="1" + style="stop-color:#666666;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient4426"> + <stop + style="stop-color:#c4c4c4;stop-opacity:1;" + offset="0" + id="stop4428" /> + <stop + id="stop4440" + offset="0.5" + style="stop-color:#959595;stop-opacity:1;" /> + <stop + style="stop-color:#7d7d7d;stop-opacity:1;" + offset="0.75" + id="stop4450" /> + <stop + style="stop-color:#666666;stop-opacity:1;" + offset="1" + id="stop4430" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4536" + id="linearGradient4534" + x1="25" + y1="43" + x2="25" + y2="7" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,1002.3622)" /> + <filter + inkscape:collect="always" + id="filter4548" + x="-0.6" + width="2.2" + y="-0.15" + height="1.3"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="2.5" + id="feGaussianBlur4550" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4570" + id="linearGradient4554" + gradientUnits="userSpaceOnUse" + x1="25" + y1="43" + x2="25" + y2="7" + gradientTransform="matrix(0.22344523,0,0,0.22344523,-30.586132,-1032.9483)" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="7.9195959" + inkscape:cx="0.87176833" + inkscape:cy="25.850901" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1560" + inkscape:window-height="919" + inkscape:window-x="271" + inkscape:window-y="149" + inkscape:window-maximized="0" + inkscape:snap-global="false"> + <inkscape:grid + type="xygrid" + id="grid3913" + empspacing="5" + visible="true" + enabled="true" + snapvisiblegridlinesonly="true" /> + </sodipodi:namedview> + <metadata + id="metadata3910"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1002.3622)"> + <rect + ry="5" + y="1007.3622" + x="20" + height="40" + width="10" + id="rect4546" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter4548)" /> + <rect + style="fill:url(#linearGradient4534);fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect4526" + width="10" + height="40" + x="20" + y="1007.3622" + ry="5" /> + <rect + ry="1.1172261" + y="-1031.8312" + x="-26.117226" + height="8.937809" + width="2.2344522" + id="rect4552" + style="fill:url(#linearGradient4554);fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="scale(-1,-1)" /> + </g> +</svg> diff --git a/tradeshow/enterprise-kinectdatavis/main.qml b/tradeshow/enterprise-kinectdatavis/main.qml new file mode 100644 index 0000000..ab58031 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/main.qml @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.1 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.0 +import QtQuick.Window 2.1 +import QtDataVisualization 1.0 +import Freenect 1.0 + +Rectangle { + id: root + width: 1280 + height: 800 + color: 'black' + + FreenectState { + id: freenectState + } + + GridLayout { + anchors.fill: parent + anchors.margins: 20 + columnSpacing: 10 + rowSpacing: 10 + columns: 2 + rows: 2 + Panel { + Layout.rowSpan: 2 + // Put "pressure" to overweigh all implicitWidths of the right column. + Layout.preferredWidth: 999999 + title: "Depth" + + ColumnLayout { + Item { + Layout.fillHeight: true + Layout.fillWidth: true + + Surface3D { + id: surfaceGraph + anchors.fill: parent + theme: Theme3D { + type: Theme3D.ThemeIsabelle + colorStyle: Theme3D.ColorStyleRangeGradient + baseGradients: [thermalGradient] + ColorGradient { + id: thermalGradient + ColorGradientStop { position: 0; color: "black" } + ColorGradientStop { position: 1/3; color: "blue" } + ColorGradientStop { position: 2/3; color: "red" } + ColorGradientStop { position: 1; color: "yellow" } + } + } + shadowQuality: AbstractGraph3D.ShadowQualityNone + selectionMode: AbstractGraph3D.SelectionNone + scene.activeCamera.cameraPreset: Camera3D.CameraPresetFrontHigh + scene.activeCamera.zoomLevel: 175 + axisY.min: clipSlider.maximumValue - clipSlider.highValue + axisY.max: clipSlider.maximumValue - clipSlider.lowValue + axisY.labelFormat: "%i" + axisX.labelFormat: "" + axisZ.labelFormat: "" + + Surface3DSeries { + id: surfaceSeries + flatShadingEnabled: false + drawMode: Surface3DSeries.DrawSurface + dataProxy: FreenectDepthDataProxy { + highClip: surfaceGraph.axisY.max + } + } + } + ErrorPanel { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: freenectState.errorString + visible: text + } + } + RowLayout { + spacing: 10 + Label { + color: "lightgrey" + text: "Near" + } + RangeSlider { + id: clipSlider + Layout.fillWidth: true + } + Label { + color: "lightgrey" + text: "Far" + } + } + } + } + Panel { + id: videoCell + Layout.preferredHeight: 1 + ColumnLayout { + RowLayout { + Header { + text: "Video" + } + Item { Layout.fillWidth: true } + Text { + text: "IR: " + color: "lightgrey" + } + Switch { id: streamTypeSwitch } + } + FreenectVideoOutput { + id: videoOutput + Layout.fillHeight: true + Layout.preferredWidth: height * 4 / 3 + Layout.alignment: Qt.AlignHCenter + streamType: streamTypeSwitch.checked ? FreenectVideoOutput.VideoIR : FreenectVideoOutput.VideoRGB + Noise { + anchors.fill: parent + visible: !videoOutput.streaming + } + } + } + } + Panel { + title: "Tilt" + Layout.preferredHeight: videoCell.Layout.preferredHeight + RowLayout { + Item { Layout.fillWidth: true } + AttitudeIndicator { + id: attitude + Layout.fillHeight: true + Layout.fillWidth: true + Layout.preferredWidth: 200 + Layout.preferredHeight: 200 + accel: freenectState.accelVector + } + Slider { + id: tiltSlider + Layout.fillHeight: true + orientation: Qt.Vertical + + minimumValue: freenectState.minMotorTilt + maximumValue: freenectState.maxMotorTilt + Binding { target: freenectState; property: "motorTilt"; value: tiltSlider.value } + } + } + } + } +} diff --git a/tradeshow/enterprise-kinectdatavis/preview_l.jpg b/tradeshow/enterprise-kinectdatavis/preview_l.jpg Binary files differnew file mode 100644 index 0000000..fa449dd --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/preview_l.jpg diff --git a/tradeshow/enterprise-kinectdatavis/runHere.sh b/tradeshow/enterprise-kinectdatavis/runHere.sh new file mode 100755 index 0000000..d6c1a21 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/runHere.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +qmlscene -I . main.qml diff --git a/tradeshow/enterprise-kinectdatavis/src/libfreenect b/tradeshow/enterprise-kinectdatavis/src/libfreenect new file mode 160000 +Subproject 846b6bf1a3790a69f565238f905b270eaf2fda4 diff --git a/tradeshow/enterprise-kinectdatavis/src/libfreenect.pro b/tradeshow/enterprise-kinectdatavis/src/libfreenect.pro new file mode 100644 index 0000000..4930236 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/libfreenect.pro @@ -0,0 +1,31 @@ +cmake_args = -DBUILD_EXAMPLES=OFF -DBUILD_CPP=OFF -DBUILD_FAKENECT=OFF -DBUILD_C_SYNC=OFF +cross_compile { + cmake_args += -DCMAKE_SYSTEM_NAME=Linux + cmake_args += -DCMAKE_SYSTEM_PROCESSOR=arm + cmake_args += -DCMAKE_CXX_COMPILER=$$QMAKE_CXX + cmake_args += -DCMAKE_C_COMPILER=$$QMAKE_CC + cmake_args += -DCMAKE_FIND_ROOT_PATH=$$[QT_SYSROOT] + cmake_args += -DCMAKE_CXX_FLAGS="--sysroot=$$[QT_SYSROOT]" + cmake_args += -DCMAKE_C_FLAGS="--sysroot=$$[QT_SYSROOT]" +} + +!exists("$$PWD/libfreenect/CMakeLists.txt"): { + warning("You forgot to update the git submodule, I'll do that for you...") + system("git submodule update --init") + system("cd libfreenect && git apply ../../patches/0*") +} + +system("cd libfreenect && cmake . $$cmake_args") + +build_pass|!debug_and_release { + make.target = invoke_make + # Build only the static lib to avoid linking to the shared one later on. + make.commands = make -C libfreenect freenectstatic + QMAKE_EXTRA_TARGETS += make + + build_pass:build_all: default_target.target = all + else: default_target.target = first + default_target.depends = make + + QMAKE_EXTRA_TARGETS += default_target +} diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/plugin.cpp b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/plugin.cpp new file mode 100644 index 0000000..926e94f --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/plugin.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtQml/QQmlExtensionPlugin> +#include <QtQml/qqml.h> + +#include "qquickfreenectstate.h" +#include "qquickfreenectbackend.h" +#include "qquickfreenectdepthdataproxy.h" +#include "qquickfreenectvideooutput.h" + +class QExampleQmlPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + void registerTypes(const char *uri) + { + qmlRegisterType<QQuickFreenectDepthDataProxy>(uri, 1, 0, "FreenectDepthDataProxy"); + qmlRegisterType<QQuickFreenectState>(uri, 1, 0, "FreenectState"); + qmlRegisterType<QQuickFreenectVideoOutput>(uri, 1, 0, "FreenectVideoOutput"); + } +}; + + +#include "plugin.moc" diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectbackend.cpp b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectbackend.cpp new file mode 100644 index 0000000..e32c20a --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectbackend.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qquickfreenectbackend.h" + +#include <QElapsedTimer> +#include <QVector3D> +#include "libfreenect.h" + +static std::weak_ptr<QQuickFreenectBackend> s_instance; + +std::shared_ptr<QQuickFreenectBackend> QQuickFreenectBackend::instance() +{ + std::shared_ptr<QQuickFreenectBackend> ret = s_instance.lock(); + if (!ret) + s_instance = ret = std::shared_ptr<QQuickFreenectBackend>(new QQuickFreenectBackend); + return ret; +} + +QQuickFreenectBackend::QQuickFreenectBackend() +{ + start(); +} + +QQuickFreenectBackend::~QQuickFreenectBackend() +{ + m_exitRequested = true; + wait(); + s_instance.reset(); +} + +uint8_t *QQuickFreenectBackend::pickVideoFrontBuffer() +{ + QMutexLocker lock(&m_mutex); + if (m_gotVideoFrame) { + std::swap(m_videoMid, m_videoFront); + m_gotVideoFrame = false; + return m_videoFront; + } + return 0; +} + +void QQuickFreenectBackend::run() +{ + freenect_context *f_ctx; + freenect_device *f_dev = 0; + QVector3D accelVectorAccum; + QVector3D emittedAccelVector; + QElapsedTimer accelVectorTimer; + + accelVectorTimer.start(); + + if (freenect_init(&f_ctx, NULL) < 0) { + emit errorStringValue(QStringLiteral("Initialization of libfreenect failed, please restart.")); + qWarning("freenect_init() failed"); + return; + } + +#ifndef QT_NO_DEBUG + freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG); +#endif + freenect_select_subdevices(f_ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA)); + + int numDevices = freenect_num_devices(f_ctx); + if (!numDevices) { + emit errorStringValue(QStringLiteral("WARNING!\nNo Kinect detected, waiting for device...")); + qWarning("WARNING: No Kinect detected, make sure that udev permissions are set properly. See <src/libfreenect/platform/linux/udev/README>."); + } + + int status = 0; + while (!m_exitRequested && status >= 0) { + // Set up the device + if (!f_dev) { + if (!(numDevices = freenect_num_devices(f_ctx))) { + timeval timeout{1, 0}; + status = freenect_process_events_timeout(f_ctx, &timeout); + continue; + } + + if (numDevices > 1) + qWarning("WARNING: More than one Kinect detected, using the first available."); + if (freenect_open_device(f_ctx, &f_dev, 0) < 0) { + emit errorStringValue(QStringLiteral("ERROR!\nCould open device. Please restart.")); + freenect_shutdown(f_ctx); + return; + } + + freenect_set_user(f_dev, this); + freenect_set_led(f_dev,LED_RED); + freenect_set_depth_callback(f_dev, depth_cb); + freenect_set_video_callback(f_dev, video_cb); + // Success. + emit errorStringValue(QString()); + } + + // Set up the depth stream + if (m_currentDepthStreamEnabled != m_requestedDepthStreamEnabled) { + if (m_requestedDepthStreamEnabled) { + freenect_set_depth_mode(f_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); + m_depthBuffer = (uint16_t*)malloc(freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT).bytes); + freenect_set_depth_buffer(f_dev, m_depthBuffer); + freenect_start_depth(f_dev); + } else { + freenect_stop_depth(f_dev); + free(m_depthBuffer); + } + m_currentDepthStreamEnabled = m_requestedDepthStreamEnabled; + } + + // Set up the video stream + if (m_currentVideoStream != m_requestedVideoStream) { + freenect_stop_video(f_dev); + // FIXME: Use YUV or BAYER instead. + freenect_video_format videoFormat = m_requestedVideoStream == QQuickFreenectVideoOutput::VideoRGB ? FREENECT_VIDEO_RGB : FREENECT_VIDEO_IR_8BIT; + free(m_videoBack); + free(m_videoMid); + free(m_videoFront); + m_videoBack = (uint8_t*)malloc(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, videoFormat).bytes); + m_videoMid = (uint8_t*)malloc(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, videoFormat).bytes); + m_videoFront = (uint8_t*)malloc(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, videoFormat).bytes); + freenect_set_video_mode(f_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, videoFormat)); + freenect_set_video_buffer(f_dev, m_videoBack); + freenect_start_video(f_dev); + m_currentVideoStream = m_requestedVideoStream; + } + + if (m_requestedTiltDegrees != m_currentTiltDegrees) { + freenect_set_tilt_degs(f_dev, m_requestedTiltDegrees); + m_currentTiltDegrees = m_requestedTiltDegrees; + } + + double dx, dy, dz; + freenect_update_tilt_state(f_dev); + freenect_get_mks_accel(freenect_get_tilt_state(f_dev), &dx, &dy, &dz); + // Weighted average of value updates over the last 100ms to flatten the noise. + float newVecRatio = std::min(100, (int)accelVectorTimer.elapsed()) / 100.; + accelVectorAccum = accelVectorAccum * (1. - newVecRatio) + QVector3D(dx, dy, dz) * newVecRatio; + accelVectorTimer.restart(); + if (accelVectorAccum != emittedAccelVector) { + emit accelVectorValue(accelVectorAccum); + emittedAccelVector = accelVectorAccum; + } + + // New accelerometer values seem to be available every ~5ms, make sure we come back to pick them. + timeval timeout{0, 5000}; + status = freenect_process_events_timeout(f_ctx, &timeout); + } + + if (status < 0) { + emit errorStringValue(QStringLiteral("ERROR!\nCould not read from device.")); + freenect_shutdown(f_ctx); + return; + } + + if (f_dev) { + freenect_stop_depth(f_dev); + freenect_stop_video(f_dev); + freenect_set_led(f_dev, LED_BLINK_GREEN); + + freenect_close_device(f_dev); + } + freenect_shutdown(f_ctx); + free(m_videoBack); + free(m_videoMid); + free(m_videoFront); + free(m_depthBuffer); +} + +void QQuickFreenectBackend::depth_cb(freenect_device *dev, void *buffer, uint32_t timestamp) +{ + Q_UNUSED(buffer) + Q_UNUSED(timestamp) + QQuickFreenectBackend *that = static_cast<QQuickFreenectBackend *>(freenect_get_user(dev)); + ++that->m_depthFrameId; + emit that->depthFrameReady(); +} + +void QQuickFreenectBackend::video_cb(freenect_device *dev, void *buffer, uint32_t timestamp) +{ + Q_UNUSED(buffer) + Q_UNUSED(timestamp) + QQuickFreenectBackend *that = static_cast<QQuickFreenectBackend *>(freenect_get_user(dev)); + { + QMutexLocker lock(&that->m_mutex); + Q_ASSERT(that->m_videoBack == buffer); + freenect_set_video_buffer(dev, that->m_videoMid); + std::swap(that->m_videoBack, that->m_videoMid); + + // Don't notify if a stream change was requested + if (that->m_currentVideoStream == that->m_requestedVideoStream) { + that->m_gotVideoFrame = true; + emit that->videoFrameReady(); + } + } +} diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectbackend.h b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectbackend.h new file mode 100644 index 0000000..07fbaa5 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectbackend.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QQUICKFREENECTBACKEND_H +#define QQUICKFREENECTBACKEND_H + +#include "qquickfreenectvideooutput.h" + +#include <QMutex> +#include <QSize> +#include <QThread> +#include <memory> + +class QVector3D; +struct _freenect_context; +typedef struct _freenect_context freenect_context; +struct _freenect_device; +typedef struct _freenect_device freenect_device; + +class QQuickFreenectBackend : public QThread { + Q_OBJECT +public: + static std::shared_ptr<QQuickFreenectBackend> instance(); + ~QQuickFreenectBackend(); + + void requestTiltDegrees(double degrees) { m_requestedTiltDegrees = degrees; } + void requestDepthStreamEnabled() { m_requestedDepthStreamEnabled = true; } + void requestVideoStreamType(QQuickFreenectVideoOutput::StreamType type) { m_requestedVideoStream = type; } + unsigned depthFrameId() const { return m_depthFrameId; } + QQuickFreenectVideoOutput::StreamType requestedVideoStreamType() const { return m_requestedVideoStream; } + + QSize depthBufferSize() const { return {640, 480}; } + uint16_t *depthBuffer() { return m_depthBuffer; } + QQuickFreenectVideoOutput::StreamType videoFrontBufferStreamType() const { return m_currentVideoStream; } + uint8_t *pickVideoFrontBuffer(); + + void run() override; + +signals: + void videoFrameReady(); + void depthFrameReady(); + void accelVectorValue(const QVector3D&); + void errorStringValue(const QString&); + +private: + QQuickFreenectBackend(); + static void depth_cb(freenect_device *dev, void *buffer, uint32_t timestamp); + static void video_cb(freenect_device *dev, void *buffer, uint32_t timestamp); + + uint8_t *m_videoBack = 0; + uint8_t *m_videoMid = 0; + uint8_t *m_videoFront = 0; + uint16_t *m_depthBuffer = 0; + double m_requestedTiltDegrees = 0; + double m_currentTiltDegrees = 0; + bool m_requestedDepthStreamEnabled = false; + bool m_currentDepthStreamEnabled = false; + QQuickFreenectVideoOutput::StreamType m_requestedVideoStream = QQuickFreenectVideoOutput::VideoOff; + QQuickFreenectVideoOutput::StreamType m_currentVideoStream = QQuickFreenectVideoOutput::VideoOff; + bool m_gotVideoFrame = false; + bool m_exitRequested = false; + unsigned m_depthFrameId = 0; + QMutex m_mutex; +}; + +#endif diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectdepthdataproxy.cpp b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectdepthdataproxy.cpp new file mode 100644 index 0000000..0a36b04 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectdepthdataproxy.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qquickfreenectdepthdataproxy.h" + +#include "libfreenect.h" + +QQuickFreenectDepthDataProxy::QQuickFreenectDepthDataProxy() + : m_backend(QQuickFreenectBackend::instance()) +{ + connect(m_backend.get(), SIGNAL(depthFrameReady()), SLOT(updateData())); + connect(this, SIGNAL(highClipChanged()), SLOT(updateData())); + + m_dataArray = new QtDataVisualization::QSurfaceDataArray; + m_dataArray->reserve(height); + for (int y = 0; y < height; ++y) + m_dataArray->append(new QtDataVisualization::QSurfaceDataRow(width)); + resetArray(m_dataArray); + m_backend->requestDepthStreamEnabled(); +} + +void QQuickFreenectDepthDataProxy::updateData() +{ + unsigned frameId = m_backend->depthFrameId(); + if (m_lastUpdateFrameId == frameId) + return; + + uint16_t *buffer = m_backend->depthBuffer(); + QSize bufferSize = m_backend->depthBufferSize(); + int widthRatio = bufferSize.width() / width; + int heightRatio = bufferSize.height() / height; + for (int y = 0; y < height; ++y) { + auto proxyRow = (*m_dataArray)[y]; + for (int x = 0; x < width; ++x) { + uint16_t data = buffer[(height - 1 - y)*widthRatio * bufferSize.width() + x*heightRatio]; + data = std::min(m_highClip, data != FREENECT_DEPTH_RAW_NO_VALUE ? FREENECT_DEPTH_RAW_MAX_VALUE - data : 0); + (*proxyRow)[x].setPosition(QVector3D(x, data, y)); + } + } + resetArray(m_dataArray); + m_lastUpdateFrameId = frameId; +} diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectdepthdataproxy.h b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectdepthdataproxy.h new file mode 100644 index 0000000..dad2376 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectdepthdataproxy.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QQUICLFREENECTDEPTHDATAPROXY_H +#define QQUICLFREENECTDEPTHDATAPROXY_H + +#include "qquickfreenectbackend.h" + +#include <QSurfaceDataItem> +#include <QSurfaceDataProxy> +#include <QVector> + +class QQuickFreenectDepthDataProxy : public QtDataVisualization::QSurfaceDataProxy { + Q_OBJECT + Q_PROPERTY(int highClip READ highClip WRITE setHighClip NOTIFY highClipChanged) +public: + QQuickFreenectDepthDataProxy(); + int highClip() const { return m_highClip; } + void setHighClip(int highClip) { + if (highClip == m_highClip) + return; + m_highClip = highClip; + m_lastUpdateFrameId = 0; + emit highClipChanged(); + } + +signals: + void highClipChanged(); + +private slots: + void updateData(); + +private: + std::shared_ptr<QQuickFreenectBackend> m_backend; + const int width = 160; + const int height = 120; + QtDataVisualization::QSurfaceDataArray *m_dataArray; + bool m_lastUpdateFrameId = 0; + int m_highClip = 2048; +}; + +#endif diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectstate.h b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectstate.h new file mode 100644 index 0000000..fcedc5b --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectstate.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QQUICKFREENECTSTATE_H +#define QQUICKFREENECTSTATE_H + +#include "qquickfreenectbackend.h" + +#include <QObject> +#include <QVector3D> + +class QQuickFreenectState : public QObject { + Q_OBJECT + Q_PROPERTY(QVector3D accelVector READ accelVector NOTIFY accelVectorChanged) + Q_PROPERTY(double motorTilt READ motorTilt WRITE setMotorTilt NOTIFY motorTiltChanged) + Q_PROPERTY(qreal minMotorTilt READ minMotorTilt CONSTANT) + Q_PROPERTY(qreal maxMotorTilt READ maxMotorTilt CONSTANT) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged) + +public: + QQuickFreenectState() + : m_backend(QQuickFreenectBackend::instance()) { + connect(m_backend.get(), SIGNAL(accelVectorValue(const QVector3D&)), SLOT(updateAccelVector(const QVector3D&))); + connect(m_backend.get(), SIGNAL(errorStringValue(const QString&)), SLOT(updateErrorString(const QString&))); + } + + QVector3D accelVector() const { return m_accelVector; } + + void setMotorTilt(double motorTilt) { + QQuickFreenectBackend::instance()->requestTiltDegrees(motorTilt); + m_motorTilt = motorTilt; + emit motorTiltChanged(); + } + bool motorTilt() const { return m_motorTilt; } + QString errorString() const { return m_errorString; } + qreal minMotorTilt() const { return -30; } + qreal maxMotorTilt() const { return 30; } + +signals: + void accelVectorChanged(); + void motorTiltChanged(); + void errorStringChanged(); + +private slots: + void updateAccelVector(const QVector3D &accelVector) { + m_accelVector = accelVector; + emit accelVectorChanged(); + } + void updateErrorString(const QString &errorString) { + m_errorString = errorString; + emit errorStringChanged(); + } + +private: + std::shared_ptr<QQuickFreenectBackend> m_backend; + QVector3D m_accelVector{0, 1, 0}; + double m_motorTilt; + QString m_errorString; +}; + +#endif diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectvideooutput.cpp b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectvideooutput.cpp new file mode 100644 index 0000000..408b0f4 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectvideooutput.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qquickfreenectvideooutput.h" + +#include "qquickfreenectbackend.h" + +#include <QQuickWindow> +#include <QSGSimpleTextureNode> +#include <memory> + +class TextureOwningNode : public QSGSimpleTextureNode { + std::unique_ptr<QSGTexture> m_texture; +public: + TextureOwningNode() { + } + void setTexture(QSGTexture *texture) { + QSGSimpleTextureNode::setTexture(texture); + m_texture.reset(texture); + } +}; + +QQuickFreenectVideoOutput::QQuickFreenectVideoOutput() + : m_backend(QQuickFreenectBackend::instance()) +{ + setFlag(ItemHasContents); + connect(m_backend.get(), SIGNAL(videoFrameReady()), SLOT(onReceivedFrame())); + m_backend->requestVideoStreamType(VideoRGB); +} + +QQuickFreenectVideoOutput::StreamType QQuickFreenectVideoOutput::streamType() const +{ + return m_backend->requestedVideoStreamType(); +} + +void QQuickFreenectVideoOutput::setStreamType(StreamType type) +{ + m_backend->requestVideoStreamType(type); + emit streamTypeChanged(); + m_isStreaming = false; + emit isStreamingChanged(); +} + +QSGNode *QQuickFreenectVideoOutput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + StreamType bufferType = m_backend->videoFrontBufferStreamType(); + const QSize textureSize(640, bufferType == VideoRGB ? 480 : 488); + auto textureNode = static_cast<TextureOwningNode *>(oldNode); + if (!textureNode) { + GLuint texId; + glGenTextures(1, &texId); + QSGTexture *texture = window()->createTextureFromId(texId, textureSize, QQuickWindow::TextureOwnsGLTexture); + + textureNode = new TextureOwningNode; + textureNode->setTexture(texture); + } + + qreal widthRatio = width() / textureSize.width(); + qreal heightRatio = height() / textureSize.height(); + QSizeF nodeSize = QSizeF(textureSize) * std::min(widthRatio, heightRatio); + textureNode->setRect(QRectF(QPointF((width() - nodeSize.width()) / 2, (height() - nodeSize.height()) / 2), nodeSize)); + + if (uint8_t *buffer = m_backend->pickVideoFrontBuffer()) { + GLint bufferFormat = bufferType == VideoRGB ? GL_RGB : GL_LUMINANCE; + glBindTexture(GL_TEXTURE_2D, textureNode->texture()->textureId()); + glTexImage2D(GL_TEXTURE_2D, 0, bufferFormat, textureSize.width(), textureSize.height(), 0, bufferFormat, GL_UNSIGNED_BYTE, buffer); + textureNode->markDirty(QSGNode::DirtyMaterial); + } + + return textureNode; +} + +void QQuickFreenectVideoOutput::onReceivedFrame() +{ + m_isStreaming = true; + emit isStreamingChanged(); + update(); +} diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectvideooutput.h b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectvideooutput.h new file mode 100644 index 0000000..4632117 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/qquickfreenectvideooutput.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: For any questions to Digia, please use the contact form at +** http://www.qt.io +** +** This file is part of the examples of the Qt Enterprise Embedded. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QQUICKFREENECTVIDEOOUTPUT_H +#define QQUICKFREENECTVIDEOOUTPUT_H + +#include <QQuickItem> +#include <memory> + +class QQuickFreenectBackend; + +class QQuickFreenectVideoOutput : public QQuickItem { + Q_OBJECT + Q_PROPERTY(StreamType streamType READ streamType WRITE setStreamType NOTIFY streamTypeChanged) + Q_PROPERTY(bool streaming READ isStreaming NOTIFY isStreamingChanged) + Q_ENUMS(StreamType) + +public: + enum StreamType { + VideoOff, + VideoRGB, + VideoIR + }; + QQuickFreenectVideoOutput(); + + StreamType streamType() const; + void setStreamType(StreamType type); + + bool isStreaming() const { return m_isStreaming; } + + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override; + +private slots: + void onReceivedFrame(); + +signals: + void streamTypeChanged(); + void isStreamingChanged(); + +private: + std::shared_ptr<QQuickFreenectBackend> m_backend; + bool m_isStreaming = false; +}; + +#endif diff --git a/tradeshow/enterprise-kinectdatavis/src/quickfreenect/quickfreenect.pro b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/quickfreenect.pro new file mode 100644 index 0000000..15cf004 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/quickfreenect/quickfreenect.pro @@ -0,0 +1,23 @@ +TEMPLATE = lib + +# Make it easier to run the UI with qmlscene +DESTDIR = ../../Freenect + +QT += quick datavisualization +CONFIG += c++11 link_pkgconfig plugin +PKGCONFIG = libusb-1.0 + +INCLUDEPATH += ../libfreenect/include +LIBS += -L ../libfreenect/lib -lfreenect + +SOURCES += \ + plugin.cpp \ + qquickfreenectbackend.cpp \ + qquickfreenectdepthdataproxy.cpp \ + qquickfreenectvideooutput.cpp + +HEADERS += \ + qquickfreenectbackend.h \ + qquickfreenectdepthdataproxy.h \ + qquickfreenectstate.h \ + qquickfreenectvideooutput.h diff --git a/tradeshow/enterprise-kinectdatavis/src/src.pro b/tradeshow/enterprise-kinectdatavis/src/src.pro new file mode 100644 index 0000000..25bebc1 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/src/src.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs + +libfreenect.file = libfreenect.pro + +quickfreenect.file = quickfreenect/quickfreenect.pro +quickfreenect.depends = libfreenect + +SUBDIRS += libfreenect \ + quickfreenect diff --git a/tradeshow/enterprise-kinectdatavis/title.txt b/tradeshow/enterprise-kinectdatavis/title.txt new file mode 100644 index 0000000..85803e3 --- /dev/null +++ b/tradeshow/enterprise-kinectdatavis/title.txt @@ -0,0 +1 @@ +012. Kinect Data Visualization |