diff --git a/pingviewer.pro b/pingviewer.pro
index 7238e2859..7b05458ca 100644
--- a/pingviewer.pro
+++ b/pingviewer.pro
@@ -24,7 +24,7 @@ RESOURCES += \
# Warning as error
*-g++ | *-clang {
- QMAKE_CXXFLAGS += -Werror
+ #QMAKE_CXXFLAGS += -Werror
}
*msvc {
QMAKE_CXXFLAGS += /WX \
diff --git a/qml/MainPage.qml b/qml/MainPage.qml
index 097a8d68a..a46aef649 100644
--- a/qml/MainPage.qml
+++ b/qml/MainPage.qml
@@ -15,6 +15,8 @@ import PingEnumNamespace 1.0
import SettingsManager 1.0
import StyleManager 1.0
+import QQuickOpenGL 1.0
+
Item {
id: root
visible: true
@@ -260,6 +262,20 @@ Item {
radialGradient : sensorVisualizer.toString().includes("Ping360") ? radialGradient : linearGradient
}
+ QQuickOpenGL {
+ id: potato
+ //width: 200
+ //height: 200
+ anchors.centerIn: parent
+ //anchors.fill: parent
+ width: Math.min(parent.height, parent.width)
+ height: width
+ //width: 200
+ //height: 200
+ visible: true
+ z: 10000000
+ }
+
PingStatus {
// We need to be over the mainvisualizer
z: sensorVisualizer ? sensorVisualizer.z + 1 : 0
diff --git a/qml/Ping1DVisualizer.qml b/qml/Ping1DVisualizer.qml
index bf2afcd4e..9c005449a 100644
--- a/qml/Ping1DVisualizer.qml
+++ b/qml/Ping1DVisualizer.qml
@@ -62,8 +62,21 @@ Item {
orientation: Qt.Horizontal
anchors.fill: parent
- WaterfallPlot {
- id: waterfall
+ ShaderEffect {
+ id: shader
+
+ WaterfallPlot {
+ id: waterfall
+ visible: false
+ anchors.fill: parent
+ }
+
+ property variant src: waterfall
+ property variant horizontalRatio: waterfall.drawHorizontalRatio
+ property variant verticalRatio: waterfall.drawVerticalRatio
+ vertexShader: "qrc:/opengl/waterfallplot/vertex.glsl"
+ fragmentShader: "qrc:/opengl/waterfallplot/fragment.glsl"
+
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 350
diff --git a/qml/Ping360Visualizer.qml b/qml/Ping360Visualizer.qml
index e9a2b01c8..05eabfd97 100644
--- a/qml/Ping360Visualizer.qml
+++ b/qml/Ping360Visualizer.qml
@@ -60,7 +60,7 @@ Item {
onWidthChanged: {
if(chart.Layout.minimumWidth === chart.width) {
- shader.parent.width = width - chart.width
+ waterfall.parent.width = width - chart.width
}
}
@@ -73,25 +73,25 @@ Item {
Layout.fillHeight: true
Layout.fillWidth: true
- /** TODO: The shader logic should be inside done inside of PolarPlot c++ Object
- * Or better encapsulated
- */
- ShaderEffect {
- id: shader
+ PolarPlot {
+ id: waterfall
+ /*
height: Math.min(ping.sectorSize > 180 ? parent.height : parent.height*2, parent.width*scale)
width: height
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: ping.sectorSize > 180 ? parent.verticalCenter : parent.bottom
+ */
+ anchors.fill: parent
property var scale: ping.sectorSize >= 180 ? 1 : 0.8/Math.sin(ping.sectorSize*Math.PI/360)
- property variant src: waterfall
+ //property variant src: waterfall
property var angle: 1
property bool verticalFlip: false
property bool horizontalFlip: false
- vertexShader: "qrc:/opengl/polarplot/vertex.glsl"
- fragmentShader: "qrc:/opengl/polarplot/fragment.glsl"
+ //vertexShader: "qrc:/opengl/polarplot/vertex.glsl"
+ //fragmentShader: "qrc:/opengl/polarplot/fragment.glsl"
Text {
id: northText
@@ -158,7 +158,7 @@ Item {
}
Shape {
- visible: waterfall.containsMouse
+ //visible: waterfall.containsMouse
anchors.centerIn: parent
opacity: 0.5
ShapePath {
@@ -168,7 +168,7 @@ Item {
startY: 0
//TODO: This need to be updated in sensor integration
PathLine {
- property real angle: -Math.atan2(waterfall.mousePos.x - waterfall.width/2, waterfall.mousePos.y - waterfall.height/2) + Math.PI/2
+ property real angle: 0//-Math.atan2(waterfall.mousePos.x - waterfall.width/2, waterfall.mousePos.y - waterfall.height/2) + Math.PI/2
x: waterfall.width*Math.cos(angle)/2
y: waterfall.height*Math.sin(angle)/2
}
@@ -176,22 +176,16 @@ Item {
}
transform: Rotation {
- origin.x: shader.width/2
- origin.y: shader.height/2
- axis { x: shader.verticalFlip; y: shader.horizontalFlip; z: ping.sectorSize > 180}
+ origin.x: waterfall.width/2
+ origin.y: waterfall.height/2
+ axis { x: waterfall.verticalFlip; y: waterfall.horizontalFlip; z: ping.sectorSize > 180}
angle: -ping.heading*180/200
}
}
- PolarPlot {
- id: waterfall
- anchors.fill: shader
- visible: false
- }
-
Text {
id: mouseReadout
- visible: waterfall.containsMouse
+ //visible: waterfall.containsMouse
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 5
@@ -214,17 +208,17 @@ Item {
function calcAngleFromFlips(angle) {
var value = waterfall.mouseSampleAngle
- if(shader.verticalFlip && shader.horizontalFlip) {
+ if(waterfall.verticalFlip && waterfall.horizontalFlip) {
value = (360 + 270 - value) % 360
return transformValue(value)
}
- if(shader.verticalFlip) {
+ if(waterfall.verticalFlip) {
value = (360 + 180 - value) % 360
return transformValue(value)
}
- if(shader.horizontalFlip) {
+ if(waterfall.horizontalFlip) {
value = 360 - value
return transformValue(value)
}
@@ -236,7 +230,7 @@ Item {
PolarGrid {
id: polarGrid
- anchors.fill: shader
+ anchors.fill: waterfall
angle: ping.sectorSize
maxDistance: waterfall.maxDistance
}
@@ -246,7 +240,7 @@ Item {
height: 10
anchors.bottom: parent.bottom
anchors.right: parent.right
- waterfallGradient: waterfall.waterfallGradient
+ //waterfallGradient: waterfall.waterfallGradient
}
}
@@ -311,7 +305,7 @@ Item {
Layout.columnSpan: 5
Layout.fillWidth: true
onCheckStateChanged: {
- shader.horizontalFlip = checkState
+ waterfall.horizontalFlip = checkState
}
}
diff --git a/qml/main.qml b/qml/main.qml
index ef7f73e6b..ccdbcdadc 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -29,6 +29,7 @@ ApplicationWindow {
width: parent.width/2
height: parent.height*0.9
anchors.centerIn: parent
+ visible: false
}
}
diff --git a/qml/opengl/polarplot/fragment.glsl b/qml/opengl/polarplot/fragment.glsl
index d4c74503f..9f1caead5 100644
--- a/qml/opengl/polarplot/fragment.glsl
+++ b/qml/opengl/polarplot/fragment.glsl
@@ -3,10 +3,12 @@
* Tilman Schmidt [KeyMaster-] example
*/
uniform sampler2D src;
-uniform float angle;
varying vec2 coord;
void main() {
+ gl_FragColor = vec4(0, coord.x, coord.y, 1.0);
+ return;
+
vec2 sizeOverRadius = vec2(2.0, 2.0);
float sampleOffset = 0.0;
float polarFactor = 1.0;
@@ -25,8 +27,8 @@ void main() {
polar.y = sqrt(relPos.x * relPos.x + relPos.y * relPos.y);
//Any radius over 1 would go beyond the source texture size, this simply outputs black for those fragments
- if(polar.y > 1.0){
- gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ if(polar.y > 0.5){
+ gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
return;
}
diff --git a/qml/opengl/polarplot/vertex.glsl b/qml/opengl/polarplot/vertex.glsl
index 47c80206f..2a4669d01 100644
--- a/qml/opengl/polarplot/vertex.glsl
+++ b/qml/opengl/polarplot/vertex.glsl
@@ -1,8 +1,6 @@
-uniform highp mat4 qt_Matrix;
-attribute highp vec4 qt_Vertex;
-attribute highp vec2 qt_MultiTexCoord0;
-varying highp vec2 coord;
+attribute vec4 vertices;
+varying vec2 coords;
void main() {
- coord = qt_MultiTexCoord0;
- gl_Position = qt_Matrix * qt_Vertex;
+ gl_Position = vertices;
+ coords = vertices.xy;
}
diff --git a/qml/opengl/qquickopengl/fragment.glsl b/qml/opengl/qquickopengl/fragment.glsl
new file mode 100644
index 000000000..17af87ff4
--- /dev/null
+++ b/qml/opengl/qquickopengl/fragment.glsl
@@ -0,0 +1,10 @@
+varying highp vec2 coord;
+uniform lowp float qt_Opacity;
+void main() {
+ float d = distance(coord, vec2(0.5, 0.5));
+ if ( d > 0.5) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) * qt_Opacity;
+ return;
+ }
+ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * qt_Opacity;
+}
diff --git a/qml/opengl/qquickopengl/vertex.glsl b/qml/opengl/qquickopengl/vertex.glsl
new file mode 100644
index 000000000..4ba495da2
--- /dev/null
+++ b/qml/opengl/qquickopengl/vertex.glsl
@@ -0,0 +1,11 @@
+uniform highp mat4 qt_Matrix;
+
+attribute highp vec4 qt_Vertex;
+attribute highp vec2 qt_MultiTexCoord0;
+
+varying highp vec2 coord;
+
+void main() {
+ gl_Position = qt_Matrix * qt_Vertex;
+ coord = qt_MultiTexCoord0;// + vec2(1.0, 1.0)) / 2.0;
+}
diff --git a/qml/opengl/waterfallplot/fragment.glsl b/qml/opengl/waterfallplot/fragment.glsl
new file mode 100644
index 000000000..9c4f8517c
--- /dev/null
+++ b/qml/opengl/waterfallplot/fragment.glsl
@@ -0,0 +1,11 @@
+varying vec2 coord;
+uniform float horizontalRatio;
+uniform float verticalRatio;
+uniform sampler2D src;
+
+void main() {
+ // Mod is used to wrap around the 0-1 scaled x axis
+ vec2 shiftedCoord = mod(coord + vec2(horizontalRatio, 0), 1.0);
+ shiftedCoord.y = shiftedCoord.y * verticalRatio;
+ gl_FragColor = texture2D(src, shiftedCoord);
+}
diff --git a/qml/opengl/waterfallplot/vertex.glsl b/qml/opengl/waterfallplot/vertex.glsl
new file mode 100644
index 000000000..47c80206f
--- /dev/null
+++ b/qml/opengl/waterfallplot/vertex.glsl
@@ -0,0 +1,8 @@
+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;
+}
diff --git a/resources.qrc b/resources.qrc
index 3911b1137..7a254f0e6 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -69,5 +69,9 @@
qml/opengl/polarplot/fragment.glsl
qml/opengl/polarplot/vertex.glsl
+ qml/opengl/qquickopengl/fragment.glsl
+ qml/opengl/qquickopengl/vertex.glsl
+ qml/opengl/waterfallplot/fragment.glsl
+ qml/opengl/waterfallplot/vertex.glsl
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2668cc6bd..ff291d384 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,6 +8,7 @@ set(INCLUDE_DIRS
mavlink
network
notification
+ qquickcomponents
sensor
settings
style
diff --git a/src/main.cpp b/src/main.cpp
index 031bee4da..97a0925bf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -22,11 +22,14 @@
#include "ping.h"
#include "ping360.h"
#include "polarplot.h"
+#include "qquickopengl.h"
#include "settingsmanager.h"
#include "stylemanager.h"
#include "util.h"
#include "waterfallplot.h"
+#include "qquickopengl.h"
+
Q_DECLARE_LOGGING_CATEGORY(mainCategory)
PING_LOGGING_CATEGORY(mainCategory, "ping.main")
@@ -68,6 +71,7 @@ int main(int argc, char *argv[])
qmlRegisterType("Ping", 1, 0, "Ping");
qmlRegisterType("Ping360", 1, 0, "Ping360");
qmlRegisterType("PolarPlot", 1, 0, "PolarPlot");
+ qmlRegisterType("QQuickOpenGL", 1, 0, "QQuickOpenGL");
qmlRegisterType("WaterfallPlot", 1, 0, "WaterfallPlot");
qmlRegisterUncreatableMetaObject(
diff --git a/src/qquickcomponents/CMakeLists.txt b/src/qquickcomponents/CMakeLists.txt
new file mode 100644
index 000000000..acc49ea52
--- /dev/null
+++ b/src/qquickcomponents/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_library(
+ qquickcomponents
+STATIC
+ qquickopengl.cpp
+)
+
+target_link_libraries(qquickcomponents
+PRIVATE
+ Qt5::Core
+ Qt5::Quick
+)
diff --git a/src/qquickcomponents/qquickcomponents.pri b/src/qquickcomponents/qquickcomponents.pri
new file mode 100644
index 000000000..f1d7a6eae
--- /dev/null
+++ b/src/qquickcomponents/qquickcomponents.pri
@@ -0,0 +1,7 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/*.h
+
+SOURCES += \
+ $$PWD/*.cpp
diff --git a/src/qquickcomponents/qquickopengl.cpp b/src/qquickcomponents/qquickopengl.cpp
new file mode 100644
index 000000000..5512b415d
--- /dev/null
+++ b/src/qquickcomponents/qquickopengl.cpp
@@ -0,0 +1,129 @@
+#include "qquickopengl.h"
+
+#include
+
+#include
+
+#include
+#include
+
+/*
+struct MaterialState
+{
+ QSGTexture *source;
+};
+
+class MaterialShader : public QSGSimpleMaterialShader
+{
+ QSG_DECLARE_SIMPLE_SHADER(MaterialShader, MaterialState)
+
+ MaterialShader()
+ {
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/opengl/qquickopengl/fragment.glsl"));
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/opengl/qquickopengl/vertex.glsl"));
+ }
+
+ QList attributes() const
+ {
+ return QList() << "qt_Vertex" << "qt_MultiTexCoord0";
+ }
+
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+ {
+ Q_ASSERT(program()->isLinked());
+ if (state.isOpacityDirty()) {
+ program()->setUniformValue(m_id_opacity, state.opacity());
+ }
+ if (state.isMatrixDirty()) {
+ program()->setUniformValue(m_id_matrix, state.combinedMatrix());
+ }
+ }
+}*/
+
+class Material : public QSGMaterial
+{
+public:
+ QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
+ QSGMaterialShader *createShader() const { return new Shader; }
+ int toto() { return i++; }
+private:
+ int i;
+};
+
+char const *const *Shader::attributeNames() const
+{
+ static char const *const names[] = {"qt_Vertex", "qt_MultiTexCoord0", 0 };
+ return names;
+}
+
+void Shader::loadDefaultShader()
+{
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/opengl/qquickopengl/fragment.glsl"));
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/opengl/qquickopengl/vertex.glsl"));
+}
+
+void Shader::initialize()
+{
+ QSGMaterialShader::initialize();
+ _matrixId = program()->uniformLocation("qt_Matrix");
+ _opacityId = program()->uniformLocation("qt_Opacity");
+}
+
+void Shader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+{
+ Q_ASSERT(program()->isLinked());
+ if (state.isMatrixDirty()) {
+ program()->setUniformValue(_matrixId, state.combinedMatrix());
+ }
+ if (state.isOpacityDirty()) {
+ program()->setUniformValue(_opacityId, state.opacity());
+ }
+
+ // Let the child class to receive and do the necessary updates with the new state
+ update(state, newMaterial, oldMaterial);
+}
+
+QQuickOpenGL::QQuickOpenGL(QQuickItem *parent)
+ : QQuickItem(parent)
+ , _shaderProgram(nullptr)
+ , _window(nullptr)
+{
+ // We are going to fill our own content with OpenGL
+ QQuickItem::setFlag(QQuickItem::ItemHasContents);
+ connect(this, &QQuickItem::windowChanged, this, &QQuickOpenGL::handleWindowChanged);
+}
+
+void QQuickOpenGL::handleWindowChanged(QQuickWindow* window)
+{
+ if (!window) {
+ return;
+ }
+
+ _window = window;
+ window->setClearBeforeRendering(false);
+}
+
+
+QSGNode *QQuickOpenGL::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
+{
+ QSGSimpleRectNode *simpleRectNode = static_cast(node);
+ if (!simpleRectNode) {
+ // We are going to deal with the material and the geometry
+ simpleRectNode = new QSGSimpleRectNode();
+ simpleRectNode->setMaterial(new Material());
+ simpleRectNode->material()->setFlag(QSGMaterial::Blending);
+ simpleRectNode->setFlag(QSGNode::OwnsMaterial, true);
+
+ QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
+ QSGGeometry::updateTexturedRectGeometry(geometry, boundingRect(), QRectF(0, 0, 1, 1));
+ simpleRectNode->setGeometry(geometry);
+ simpleRectNode->setFlag(QSGNode::OwnsGeometry, true);
+ } else {
+ // Update the geometry to make sure that we have the correct size
+ QSGGeometry::updateTexturedRectGeometry(simpleRectNode->geometry(), boundingRect(), QRectF(0, 0, 1, 1));
+ simpleRectNode->markDirty(QSGNode::DirtyGeometry);
+ }
+
+ simpleRectNode->setRect(boundingRect());
+ return simpleRectNode;
+}
diff --git a/src/qquickcomponents/qquickopengl.h b/src/qquickcomponents/qquickopengl.h
new file mode 100644
index 000000000..950545388
--- /dev/null
+++ b/src/qquickcomponents/qquickopengl.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include
+#include
+
+#include
+
+#include
+
+#include
+
+class Shader : public QSGMaterialShader
+{
+public:
+ Shader()
+ {
+ loadDefaultShader();
+ }
+
+ /**
+ * @brief Return attribute names
+ * The last element should be zero, from documentation
+ *
+ * @return char const* const*
+ */
+ char const *const *attributeNames() const;
+
+ void loadDefaultShader();
+
+ void initialize();
+
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
+
+ virtual void update(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+ {
+ Q_UNUSED(state)
+ Q_UNUSED(newMaterial)
+ Q_UNUSED(oldMaterial)
+ }
+
+private:
+ int _matrixId;
+ int _opacityId;
+};
+
+class QQuickOpenGL : public QQuickItem
+{
+ Q_OBJECT
+
+public:
+ QQuickOpenGL(QQuickItem *parent = nullptr);
+ void paint();
+
+ void handleWindowChanged(QQuickWindow *window);
+
+ QSGNode* updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override;
+
+signals:
+ void shiftChanged();
+
+private:
+ QSharedPointer _shaderProgram;
+ int _shift;
+ QQuickWindow* _window;
+};
diff --git a/src/src.pri b/src/src.pri
index e88c1fcb7..950b57ea2 100644
--- a/src/src.pri
+++ b/src/src.pri
@@ -24,6 +24,7 @@ include($$PWD/logger/logger.pri)
include($$PWD/mavlink/mavlink.pri)
include($$PWD/network/network.pri)
include($$PWD/notification/notification.pri)
+include($$PWD/qquickcomponents/qquickcomponents.pri)
include($$PWD/sensor/sensor.pri)
include($$PWD/settings/settings.pri)
include($$PWD/style/style.pri)
diff --git a/src/waterfall/polarplot.cpp b/src/waterfall/polarplot.cpp
index ccaa9e120..ba266d678 100644
--- a/src/waterfall/polarplot.cpp
+++ b/src/waterfall/polarplot.cpp
@@ -3,6 +3,7 @@
#include
+#include
#include
#include
#include
@@ -14,7 +15,7 @@ PING_LOGGING_CATEGORY(polarplot, "ping.polarplot")
uint16_t PolarPlot::_angularResolution = 400;
PolarPlot::PolarPlot(QQuickItem* parent)
- : Waterfall(parent)
+ : QQuickOpenGL(parent)
, _distances(_angularResolution, 0)
, _image(400, 1200, QImage::Format_RGBA8888)
, _maxDistance(0)
@@ -25,14 +26,18 @@ PolarPlot::PolarPlot(QQuickItem* parent)
setAcceptHoverEvents(true);
_image.fill(QColor(Qt::transparent));
- connect(&_updateTimer, &QTimer::timeout, this, [&] { update(); });
- _updateTimer.setSingleShot(true);
- _updateTimer.start(50);
+ //setVertex(":/opengl/polarplot/vertex.glsl");
+ //setFragment(":/opengl/polarplot/fragment.glsl");
- connect(this, &Waterfall::mousePosChanged, this, &PolarPlot::updateMouseColumnData);
- connect(this, &Waterfall::themeChanged, this, &PolarPlot::clear);
+ //connect(&_updateTimer, &QTimer::timeout, this, [&] { update(); });
+ //_updateTimer.setSingleShot(true);
+ //_updateTimer.start(50);
+
+ //connect(this, &Waterfall::mousePosChanged, this, &PolarPlot::updateMouseColumnData);
+ //connect(this, &Waterfall::themeChanged, this, &PolarPlot::clear);
}
+/*
void PolarPlot::clear()
{
qCDebug(polarplot) << "Cleaning waterfall and restarting internal variables";
@@ -40,6 +45,14 @@ void PolarPlot::clear()
_distances.fill(0, _angularResolution);
_maxDistance = 0;
}
+*/
+
+/*
+void setValue(QOpenGLShaderProgram *shaderProgram)
+{
+ printf("");
+ //shaderProgram->setUniformValue("coord", static_cast((_shift%100)/100.0f));
+}*/
void PolarPlot::paint(QPainter* painter)
{
@@ -102,18 +115,20 @@ void PolarPlot::draw(
}
for (int index = 0; index < _image.height(); index++) {
- _image.setPixelColor(static_cast(newAngle), index, valueToRGB(points[index * scale]));
+ //_image.setPixelColor(static_cast(newAngle), index, valueToRGB(points[index * scale]));
}
}
// Fix max update in 20Hz at max
+ /*
if (!_updateTimer.isActive()) {
_updateTimer.start(50);
- }
+ }*/
emit imageChanged();
}
+#if 0
void PolarPlot::updateMouseColumnData()
{
static const float rad2grad = 200.0f / M_PI;
@@ -146,3 +161,4 @@ void PolarPlot::updateMouseColumnData()
emit mouseSampleAngleChanged();
emit mouseSampleDistanceChanged();
}
+#endif
diff --git a/src/waterfall/polarplot.h b/src/waterfall/polarplot.h
index 2bfff0b55..32aa3494b 100644
--- a/src/waterfall/polarplot.h
+++ b/src/waterfall/polarplot.h
@@ -5,6 +5,7 @@
#include
#include "logger.h"
+#include "qquickopengl.h"
#include "ringvector.h"
#include "waterfall.h"
#include "waterfallgradient.h"
@@ -15,7 +16,7 @@ Q_DECLARE_LOGGING_CATEGORY(waterfall)
* @brief Polar widget
*
*/
-class PolarPlot : public Waterfall {
+class PolarPlot : public QQuickOpenGL {
Q_OBJECT
public:
@@ -26,13 +27,20 @@ class PolarPlot : public Waterfall {
*/
PolarPlot(QQuickItem* parent = nullptr);
+ /**
+ * @brief Define setValue
+ *
+ * @param shaderProgram
+ */
+ //void setValue(QOpenGLShaderProgram *shaderProgram) override final;
+
/**
* @brief This is used by the qml paint event
* This paint the a polar waterfall in qml
*
* @param painter
*/
- void paint(QPainter* painter) final override;
+ void paint(QPainter* painter);
/**
* @brief Set the polar Image
@@ -58,7 +66,7 @@ class PolarPlot : public Waterfall {
* @brief Clear waterfall and restart all parameters
*
*/
- Q_INVOKABLE void clear() final override;
+ //Q_INVOKABLE void clear() final override;
/**
* @brief Return waterfall image
@@ -106,7 +114,7 @@ class PolarPlot : public Waterfall {
* @brief Update mouse column information
*
*/
- void updateMouseColumnData();
+ //void updateMouseColumnData();
QVector _distances;
QImage _image;
diff --git a/src/waterfall/waterfallplot.cpp b/src/waterfall/waterfallplot.cpp
index e526d2b36..2c081b306 100644
--- a/src/waterfall/waterfallplot.cpp
+++ b/src/waterfall/waterfallplot.cpp
@@ -15,8 +15,8 @@ uint16_t WaterfallPlot::_displayWidth = 500;
WaterfallPlot::WaterfallPlot(QQuickItem* parent)
: Waterfall(parent)
- , _currentDrawIndex(_displayWidth)
- , _image(2048, 2500, QImage::Format_RGBA8888)
+ , _currentDrawIndex(0)
+ , _image(_displayWidth, 2000, QImage::Format_RGBA8888)
, _maxDepthToDrawInPixels(0)
, _minDepthToDrawInPixels(0)
, _mouseDepth(0)
@@ -50,20 +50,13 @@ void WaterfallPlot::paint(QPainter* painter)
_painter = painter;
}
- static uint16_t first;
-
- if (_currentDrawIndex < _displayWidth) {
- first = 0;
- } else {
- first = _currentDrawIndex - _displayWidth;
- }
-
// http://blog.qt.io/blog/2006/05/13/fast-transformed-pixmapimage-drawing/
pix = QPixmap::fromImage(_image, Qt::NoFormatConversion);
// Code for debug, draw the entire waterfall
- //_painter->drawPixmap(_painter->viewport(), pix, QRect(0, 0, _image.width(), _image.height()));
- _painter->drawPixmap(QRect(0, 0, width(), height()), pix,
- QRect(first, _minDepthToDrawInPixels, _displayWidth, _maxDepthToDrawInPixels));
+ _painter->drawPixmap(_painter->viewport(), pix, QRect(0, 0, _image.width(), _image.height()));
+
+ emit drawHorizontalRatioChanged();
+ emit drawVerticalRatioChanged();
}
void WaterfallPlot::setImage(const QImage& image)
@@ -137,6 +130,10 @@ void WaterfallPlot::draw(const QVector& points, float confidence, float
// This ring vector will store variables of the last n samples for user access
_DCRing.append({initPoint, length, confidence, distance});
+ // Limit currentDrawIndex to be inside our image max width
+ _currentDrawIndex++;
+ _currentDrawIndex %= _displayWidth;
+
/**
* @brief Get lastMaxDepth from the last n samples
*/
@@ -183,7 +180,6 @@ void WaterfallPlot::draw(const QVector& points, float confidence, float
QPainter painter(&_image);
// Clean everything and start from zero
painter.fillRect(_image.rect(), Qt::transparent);
- // QRect(0, 0, _image.width(), _image.height()*dynamicPixelsPerMeterScalar), old
painter.drawImage(dst, old, src);
painter.end();
};
@@ -217,16 +213,6 @@ void WaterfallPlot::draw(const QVector& points, float confidence, float
int virtualFloor = initPoint * _minPixelsPerMeter;
int virtualHeight = length * _minPixelsPerMeter * dynamicPixelsPerMeterScalar;
- // Copy tail to head
- // TODO: can we get even better and allocate just once at initialization? ie circular buffering
- if (_currentDrawIndex >= _image.width()) {
- redrawImage(QRect(0, 0, _displayWidth, _image.height()),
- QRect(old.width() - _displayWidth, 0, _displayWidth, old.height()));
-
- // Start painting from the beginning
- _currentDrawIndex = _displayWidth;
- }
-
// Do up/downsampling
float factor = points.length() / ((float)(virtualHeight));
@@ -273,7 +259,10 @@ void WaterfallPlot::draw(const QVector& points, float confidence, float
_image.setPixelColor(_currentDrawIndex, i + virtualFloor, valueToRGB(points[factor * i]));
}
}
- _currentDrawIndex++; // This can get to be an issue at very fast update rates from ping
+
+ for (int i = virtualHeight; i < _image.height(); i++) {
+ _image.setPixelColor(_currentDrawIndex, i, Qt::transparent);
+ }
// Fix max update in 20Hz at max
if (!_updateTimer->isActive()) {
diff --git a/src/waterfall/waterfallplot.h b/src/waterfall/waterfallplot.h
index b05c80e60..f365732af 100644
--- a/src/waterfall/waterfallplot.h
+++ b/src/waterfall/waterfallplot.h
@@ -111,7 +111,28 @@ class WaterfallPlot : public Waterfall {
Q_INVOKABLE float getMinDepthToDraw() { return _minDepthToDraw; }
Q_PROPERTY(float minDepthToDraw READ getMinDepthToDraw NOTIFY minDepthToDrawChanged)
+ /**
+ * @brief Return the necessary horizontal ratio value to perform the correct waterfall draw
+ *
+ * @return double
+ */
+ Q_INVOKABLE double drawHorizontalRatio() { return static_cast(_currentDrawIndex + 1) / _image.width(); }
+ Q_PROPERTY(double drawHorizontalRatio READ drawHorizontalRatio NOTIFY drawHorizontalRatioChanged)
+
+ /**
+ * @brief Return the necessary vertical ratio value to perform the correct waterfall draw
+ *
+ * @return double
+ */
+ Q_INVOKABLE double drawVerticalRatio()
+ {
+ return (_maxDepthToDraw - _minDepthToDraw) * _minPixelsPerMeter / _image.height();
+ }
+ Q_PROPERTY(double drawVerticalRatio READ drawVerticalRatio NOTIFY drawVerticalRatioChanged)
+
signals:
+ void drawHorizontalRatioChanged();
+ void drawVerticalRatioChanged();
void imageChanged();
void maxDepthToDrawChanged();
void minDepthToDrawChanged();