diff options
Diffstat (limited to 'tradeshow/enterprise-kinectdatavis/src/quickfreenect')
9 files changed, 875 insertions, 0 deletions
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 |