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/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..9a07717b4 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -69,5 +69,7 @@
qml/opengl/polarplot/fragment.glsl
qml/opengl/polarplot/vertex.glsl
+ qml/opengl/waterfallplot/fragment.glsl
+ qml/opengl/waterfallplot/vertex.glsl
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();