From 2f0d6b9c75f87a9c3e81ccfe25028823358a48ff Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 9 Aug 2015 23:00:51 -0400 Subject: [PATCH] Re-usable WaterfallPanel to replace WaterfallContext --- CMakeLists.txt | 6 +- src/panel/SpectrumPanel.cpp | 2 + src/panel/SpectrumPanel.h | 7 + .../WaterfallPanel.cpp} | 132 ++++++++++-------- src/panel/WaterfallPanel.h | 25 ++++ src/ui/GLPanel.cpp | 2 + src/visual/WaterfallCanvas.cpp | 42 +++--- src/visual/WaterfallCanvas.h | 6 +- src/visual/WaterfallContext.h | 25 ---- 9 files changed, 139 insertions(+), 108 deletions(-) create mode 100644 src/panel/SpectrumPanel.cpp create mode 100644 src/panel/SpectrumPanel.h rename src/{visual/WaterfallContext.cpp => panel/WaterfallPanel.cpp} (76%) create mode 100644 src/panel/WaterfallPanel.h delete mode 100644 src/visual/WaterfallContext.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d16cd6..e0e0db1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,6 +245,8 @@ SET (cubicsdr_sources src/util/GLFont.cpp src/util/DataTree.cpp src/panel/ScopePanel.cpp + src/panel/SpectrumPanel.cpp + src/panel/WaterfallPanel.cpp src/visual/ColorTheme.cpp src/visual/PrimaryGLContext.cpp src/visual/InteractiveCanvas.cpp @@ -259,7 +261,6 @@ SET (cubicsdr_sources src/visual/SpectrumCanvas.cpp src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp - src/visual/WaterfallContext.cpp src/process/VisualProcessor.cpp src/process/ScopeVisualProcessor.cpp src/process/SpectrumVisualProcessor.cpp @@ -298,6 +299,8 @@ SET (cubicsdr_headers src/util/GLFont.h src/util/DataTree.h src/panel/ScopePanel.h + src/panel/SpectrumPanel.h + src/panel/WaterfallPanel.h src/visual/ColorTheme.h src/visual/PrimaryGLContext.h src/visual/InteractiveCanvas.h @@ -312,7 +315,6 @@ SET (cubicsdr_headers src/visual/SpectrumCanvas.h src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h - src/visual/WaterfallContext.h src/process/VisualProcessor.h src/process/ScopeVisualProcessor.h src/process/SpectrumVisualProcessor.h diff --git a/src/panel/SpectrumPanel.cpp b/src/panel/SpectrumPanel.cpp new file mode 100644 index 0000000..853a805 --- /dev/null +++ b/src/panel/SpectrumPanel.cpp @@ -0,0 +1,2 @@ +#include "SpectrumPanel.h" + diff --git a/src/panel/SpectrumPanel.h b/src/panel/SpectrumPanel.h new file mode 100644 index 0000000..a72c79f --- /dev/null +++ b/src/panel/SpectrumPanel.h @@ -0,0 +1,7 @@ +#pragma once + +#include "GLPanel.h" + +class SpectrumPanel : public GLPanel { + +}; \ No newline at end of file diff --git a/src/visual/WaterfallContext.cpp b/src/panel/WaterfallPanel.cpp similarity index 76% rename from src/visual/WaterfallContext.cpp rename to src/panel/WaterfallPanel.cpp index 8ba0f45..b018736 100644 --- a/src/visual/WaterfallContext.cpp +++ b/src/panel/WaterfallPanel.cpp @@ -1,34 +1,35 @@ -#include "WaterfallContext.h" -#include "WaterfallCanvas.h" -#include "CubicSDR.h" +#include "WaterfallPanel.h" -WaterfallContext::WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext) : - PrimaryGLContext(canvas, sharedContext), fft_size(0), waterfall_lines(0), waterfall_slice(NULL), activeTheme(NULL) { +WaterfallPanel::WaterfallPanel() : GLPanel(), fft_size(0), waterfall_lines(0), waterfall_slice(NULL), activeTheme(NULL) { for (int i = 0; i < 2; i++) { waterfall[i] = 0; } } -void WaterfallContext::Setup(int fft_size_in, int num_waterfall_lines_in) { +void WaterfallPanel::setup(int fft_size_in, int num_waterfall_lines_in) { waterfall_lines = num_waterfall_lines_in; fft_size = fft_size_in; - + + if (points.size() != fft_size) { + points.resize(fft_size); + } + for (int i = 0; i < 2; i++) { if (waterfall[i]) { glDeleteTextures(1, &waterfall[i]); waterfall[i] = 0; } - + waterfall_ofs[i] = waterfall_lines - 1; } } -void WaterfallContext::refreshTheme() { +void WaterfallPanel::refreshTheme() { glEnable (GL_TEXTURE_2D); - + for (int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, waterfall[i]); - + glPixelTransferi(GL_MAP_COLOR, GL_TRUE); glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, &(ThemeMgr::mgr.currentTheme->waterfallGradient.getRed())[0]); glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, &(ThemeMgr::mgr.currentTheme->waterfallGradient.getGreen())[0]); @@ -36,81 +37,100 @@ void WaterfallContext::refreshTheme() { } } -void WaterfallContext::Draw(std::vector &points, bool step) { +void WaterfallPanel::setPoints(std::vector &points) { + int halfPts = points.size()/2; + if (halfPts == fft_size) { + for (int i = 0; i < fft_size; i++) { + this->points[i] = points[i*2+1]; + } + } else { + this->points.assign(points.begin(), points.end()); + } +} +void WaterfallPanel::step() { int half_fft_size = fft_size / 2; - glEnable (GL_TEXTURE_2D); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); - if (!waterfall[0]) { glGenTextures(2, waterfall); - + unsigned char *waterfall_tex; - + waterfall_tex = new unsigned char[half_fft_size * waterfall_lines]; memset(waterfall_tex, 0, half_fft_size * waterfall_lines); - + for (int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, waterfall[i]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - + glBindTexture(GL_TEXTURE_2D, waterfall[i]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, half_fft_size, waterfall_lines, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_tex); } - - if (waterfall_slice != NULL) { - delete waterfall_slice; - } - waterfall_slice = new unsigned char[half_fft_size]; - + + if (waterfall_slice != NULL) { + delete waterfall_slice; + } + waterfall_slice = new unsigned char[half_fft_size]; + delete[] waterfall_tex; } + + if (points.size()) { + for (int j = 0; j < 2; j++) { + for (int i = 0, iMax = half_fft_size; i < iMax; i++) { + float v = points[j * half_fft_size + i]; + + float wv = v < 0 ? 0 : (v > 0.99 ? 0.99 : v); + + waterfall_slice[i] = (unsigned char) floor(wv * 255.0); + } + + glBindTexture(GL_TEXTURE_2D, waterfall[j]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, waterfall_ofs[j], half_fft_size, 1, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_slice); + + if (waterfall_ofs[j] == 0) { + waterfall_ofs[j] = waterfall_lines; + } + + waterfall_ofs[j]--; + } + } +} +void WaterfallPanel::drawPanelContents() { + if (!waterfall[0]) { + return; + } + + int half_fft_size = fft_size / 2; + + glLoadMatrixf(transform); + + glEnable (GL_TEXTURE_2D); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + if (activeTheme != ThemeMgr::mgr.currentTheme) { refreshTheme(); activeTheme = ThemeMgr::mgr.currentTheme; } - - if (points.size()) { - for (int j = 0; j < 2; j++) { - for (int i = 0, iMax = half_fft_size; i < iMax; i++) { - float v = points[(j * half_fft_size + i) * 2 + 1]; - - float wv = v < 0 ? 0 : (v > 0.99 ? 0.99 : v); - - waterfall_slice[i] = (unsigned char) floor(wv * 255.0); - } - - glBindTexture(GL_TEXTURE_2D, waterfall[j]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, waterfall_ofs[j], half_fft_size, 1, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_slice); - - if (waterfall_ofs[j] == 0) { - waterfall_ofs[j] = waterfall_lines; - } - - waterfall_ofs[j]--; - } - } - glColor3f(1.0, 1.0, 1.0); - + GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); - + float viewWidth = (float) vp[2]; - + // some bias to prevent seams at odd scales float half_pixel = 1.0 / viewWidth; float half_texel = 1.0 / (float) half_fft_size; float vtexel = 1.0 / (float) waterfall_lines; float vofs = (float) (waterfall_ofs[0] + 1) * vtexel; - + glBindTexture(GL_TEXTURE_2D, waterfall[0]); glBegin (GL_QUADS); glTexCoord2f(0.0 + half_texel, 1.0 + vofs); @@ -122,7 +142,7 @@ void WaterfallContext::Draw(std::vector &points, bool step) { glTexCoord2f(0.0 + half_texel, 0.0 + vofs); glVertex3f(-1.0, 1.0, 0.0); glEnd(); - + vofs = (float) (waterfall_ofs[1] + 1) * vtexel; glBindTexture(GL_TEXTURE_2D, waterfall[1]); glBegin(GL_QUADS); @@ -135,9 +155,9 @@ void WaterfallContext::Draw(std::vector &points, bool step) { glTexCoord2f(0.0 + half_texel, 0.0 + vofs); glVertex3f(0.0 - half_pixel, 1.0, 0.0); glEnd(); - + glBindTexture(GL_TEXTURE_2D, 0); - + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); -} +} \ No newline at end of file diff --git a/src/panel/WaterfallPanel.h b/src/panel/WaterfallPanel.h new file mode 100644 index 0000000..b172635 --- /dev/null +++ b/src/panel/WaterfallPanel.h @@ -0,0 +1,25 @@ +#pragma once + +#include "GLPanel.h" + +class WaterfallPanel : public GLPanel { +public: + WaterfallPanel(); + void setup(int fft_size_in, int num_waterfall_lines_in); + void refreshTheme(); + void setPoints(std::vector &points); + void step(); + void drawPanelContents(); + + std::vector points; + bool needsUpdate; + +private: + GLuint waterfall[2]; + int waterfall_ofs[2]; + int fft_size; + int waterfall_lines; + unsigned char *waterfall_slice; + + ColorTheme *activeTheme; +}; \ No newline at end of file diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index ae44400..c7e2bca 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -13,6 +13,8 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transf fill[1] = RGB3f(0.1,0.1,0.1); borderColor = RGB3f(0.8, 0.8, 0.8); setCoordinateSystem(GLPANEL_Y_UP); + setMarginPx(0); + setBorderPx(0); } void GLPanel::genArrays() { diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index be6639e..e9a93ff 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -35,10 +35,10 @@ EVT_MOUSEWHEEL(WaterfallCanvas::OnMouseWheelMoved) wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines( - 0), mouseZoom(1), zoom(1), hoverAlpha(1.0), dragOfs(0) { + InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0), + dragOfs(0), mouseZoom(1), zoom(1), hoverAlpha(1.0) { - glContext = new WaterfallContext(this, &wxGetApp().GetContext(this)); + glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this)); SetCursor(wxCURSOR_CROSS); } @@ -53,7 +53,7 @@ void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) { fft_size = fft_size_in; waterfall_lines = waterfall_lines_in; - glContext->Setup(fft_size, waterfall_lines); + waterfallPanel.setup(fft_size, waterfall_lines); } WaterfallCanvas::DragState WaterfallCanvas::getDragState() { @@ -135,30 +135,28 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; } } - - bool step = false; - if (!visualDataQueue.empty()) { - SpectrumVisualData *vData; - - visualDataQueue.pop(vData); - - if (!vData) { - return; - } - - spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); - - vData->decRefCount(); - step = true; - } - glContext->SetCurrent(*this); initGLExtensions(); glViewport(0, 0, ClientSize.x, ClientSize.y); + if (!visualDataQueue.empty()) { + SpectrumVisualData *vData; + + visualDataQueue.pop(vData); + + if (vData) { + waterfallPanel.setPoints(vData->spectrum_points); + waterfallPanel.step(); + } + + vData->decRefCount(); + } + glContext->BeginDraw(0,0,0); - glContext->Draw(spectrum_points, step); + + waterfallPanel.calcTransform(CubicVR::mat4::identity()); + waterfallPanel.draw(); std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index e7f3384..b570ffb 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -7,9 +7,9 @@ #include #include "InteractiveCanvas.h" -#include "WaterfallContext.h" #include "MouseTracker.h" #include "SpectrumCanvas.h" +#include "WaterfallPanel.h" class WaterfallCanvas: public InteractiveCanvas { @@ -47,8 +47,8 @@ private: std::vector spectrum_points; SpectrumCanvas *spectrumCanvas; - - WaterfallContext *glContext; + PrimaryGLContext *glContext; + WaterfallPanel waterfallPanel; DragState dragState; DragState nextDragState; diff --git a/src/visual/WaterfallContext.h b/src/visual/WaterfallContext.h deleted file mode 100644 index e993747..0000000 --- a/src/visual/WaterfallContext.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "PrimaryGLContext.h" -#include "Gradient.h" -#include "ColorTheme.h" - -class WaterfallCanvas; - -class WaterfallContext: public PrimaryGLContext { -public: - WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext); - - void Draw(std::vector &points, bool step); - void Setup(int fft_size_in, int num_waterfall_lines_in); - void refreshTheme(); - -private: - GLuint waterfall[2]; - int waterfall_ofs[2]; - int fft_size; - int waterfall_lines; - unsigned char *waterfall_slice; - - ColorTheme *activeTheme; -};