From 93c8ad021e177aed49951bccdb1c184df789fff3 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Tue, 19 Jan 2021 11:06:48 -0800 Subject: [PATCH 01/42] Refactoring palettes.cpp to remove global state --- glvis.cpp | 16 ++- lib/aux_vis.cpp | 47 +++---- lib/aux_vis.hpp | 6 - lib/gl/renderer.hpp | 2 +- lib/openglvis.cpp | 2 + lib/openglvis.hpp | 10 ++ lib/palettes.cpp | 314 +++++++++++++++++++++---------------------- lib/palettes.hpp | 71 +++++++--- lib/sdl.cpp | 7 +- lib/threads.cpp | 6 +- lib/vsdata.cpp | 73 +++++----- lib/vssolution.cpp | 7 +- lib/vssolution3d.cpp | 5 +- lib/vsvector.cpp | 2 +- lib/vsvector3d.cpp | 2 +- 15 files changed, 301 insertions(+), 269 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 55c25476..8b515748 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -160,7 +160,7 @@ bool GLVisInitVis(int field_type) vs->Zoom(1.8); // Use the 'bone' palette when visualizing a 2D mesh only (otherwise // the 'jet-like' palette is used in 2D, see vssolution.cpp). - paletteSet(4); + vs->GetPalette().SetPalette(4); } } else if (mesh->SpaceDimension() == 3) @@ -176,13 +176,13 @@ bool GLVisInitVis(int field_type) if (mesh->Dimension() == 3) { // Use the 'white' palette when visualizing a 3D volume mesh only - paletteSet(11); + vss->GetPalette().SetPalette(11); vss->SetLightMatIdx(4); } else { // Use the 'bone' palette when visualizing a surface mesh only - paletteSet(4); + vss->GetPalette().SetPalette(4); } // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp vss->ToggleDrawAxes(); @@ -703,14 +703,16 @@ void ExecuteScriptCommand() int pal; scr >> pal; cout << "Script: palette: " << pal << endl; - paletteSet(pal-1); + vs->GetPalette().SetPalette(pal); MyExpose(); } else if (word == "palette_repeat") { - scr >> RepeatPaletteTimes; - cout << "Script: palette_repeat: " << RepeatPaletteTimes << endl; - paletteInit(); + int rpt_times; + scr >> rpt_times; + cout << "Script: palette_repeat: " << rpt_times << endl; + vs->GetPalette().SetRepeatTimes(rpt_times); + vs->GetPalette().Init(); MyExpose(); } else if (word == "toggle_attributes") diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 151b1059..d841e35f 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -36,9 +36,6 @@ using namespace mfem; int visualize = 0; VisualizationScene * locscene; -float MatAlpha = 1.0; -float MatAlphaCenter = 0.5; - #ifdef GLVIS_MULTISAMPLE static int glvis_multisample = GLVIS_MULTISAMPLE; #else @@ -82,24 +79,20 @@ int InitVisualization (const char name[], int x, int y, int w, int h) { return 1; } - } else { - wnd->clearEvents(); - paletteRebind(); + cout << "Error: visualization is already up." << endl; + return 1; } #ifdef GLVIS_DEBUG cout << "Window should be up" << endl; #endif - paletteInit(); InitFont(); wnd->getRenderer().setLineWidth(line_w); wnd->getRenderer().setLineWidthMS(line_w_aa); - SetUseTexture(0); - // auxReshapeFunc (MyReshape); // not needed, MyExpose calls it // auxReshapeFunc (NULL); void (*exposeFunc)(void) = MyExpose; @@ -382,6 +375,10 @@ void MyReshape(GLsizei w, GLsizei h) void MyExpose(GLsizei w, GLsizei h) { MyReshape (w, h); + GLuint color_tex = locscene->GetPalette().GetColorTexture(); + GLuint alpha_tex = locscene->GetPalette().GetAlphaTexture(); + wnd->getRenderer().setColorTexture(color_tex); + wnd->getRenderer().setAlphaTexture(alpha_tex); gl3::SceneInfo frame = locscene->GetSceneObjs(); for (auto drawable_ptr : frame.needs_buffering) { @@ -1457,9 +1454,6 @@ void SetWindowTitle(const char *title) } int MySetColorLogscale = 0; -extern int RepeatPaletteTimes; -int PaletteNumColors = 0; -int UseTexture = 0; double GetColorCoord(double val, double min, double max) { @@ -1485,21 +1479,22 @@ double GetColorCoord(double val, double min, double max) void GetColorFromVal(double val, float * rgba) { - int palSize = paletteGetSize(); + int palSize = locscene->GetPalette().GetSize(); + int RepeatPaletteTimes = locscene->GetPalette().GetRepeatTimes(); + const double* palData = locscene->GetPalette().GetData(); val *= 0.999999999 * ( palSize - 1 ) * abs(RepeatPaletteTimes); int i = (int) floor( val ); double t = val - i; - double* pal; + const double* pal; if (((i / (palSize-1)) % 2 == 0 && RepeatPaletteTimes > 0) || ((i / (palSize-1)) % 2 == 1 && RepeatPaletteTimes < 0)) { - pal = paletteGet() + 3 * ( i % (palSize-1) ); + pal = palData + 3 * ( i % (palSize-1) ); } else { - pal = paletteGet() + 3 * ( (palSize-2) - - i % (palSize-1) ); + pal = palData + 3 * ( (palSize-2) - i % (palSize-1) ); t = 1.0 - t; } rgba[0] = (1.0 - t) * pal[0] + t * pal[3]; @@ -1523,22 +1518,18 @@ void MySetColor (gl3::GlBuilder& builder, double val) int GetUseTexture() { - return UseTexture; + return locscene->GetPalette().GetSmoothSetting(); } void SetUseTexture(int ut) { - if (UseTexture != ut) + if (ut == 0) { - UseTexture = ut; - if (UseTexture == 0) - { - paletteUseDiscrete(); - } - else - { - paletteUseSmooth(); - } + locscene->GetPalette().UseDiscrete(); + } + else + { + locscene->GetPalette().UseSmooth(); } } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index e8df5c8e..21e00dcd 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -19,12 +19,6 @@ #include "font.hpp" #include "openglvis.hpp" -extern GLuint fontbase; -extern float MatAlpha; -extern float MatAlphaCenter; -extern int RepeatPaletteTimes; -extern int PaletteNumColors; - /// Initializes the visualization and some keys. int InitVisualization(const char name[], int x, int y, int w, int h); diff --git a/lib/gl/renderer.hpp b/lib/gl/renderer.hpp index 46716ded..84c3a456 100644 --- a/lib/gl/renderer.hpp +++ b/lib/gl/renderer.hpp @@ -121,7 +121,7 @@ class GLDevice } return *this; } - operator GLuint() { return hnd; } + operator GLuint() const { return hnd; } }; static void boCleanup(GLuint vbo_hnd) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index ebc7c480..e4f5d318 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -125,6 +125,8 @@ VisualizationScene::VisualizationScene() _use_cust_l0_pos = false; light_mat_idx = 3; use_light = true; + + palette.Init(); } VisualizationScene::~VisualizationScene() {} diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index 960479db..46ccce8c 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -16,6 +16,7 @@ #include "sdl.hpp" #include "gl/types.hpp" #include "material.hpp" +#include "palettes.hpp" // Visualization header file @@ -132,6 +133,8 @@ class VisualizationScene int light_mat_idx; bool use_light; + PaletteState palette; + gl3::RenderParams GetMeshDrawParams(); glm::mat4 GetModelViewMtx(); @@ -163,6 +166,9 @@ class VisualizationScene glm::mat4 rotmat; glm::mat4 translmat; + float matAlpha = 1.0; + float matAlphaCenter = 0.5; + virtual gl3::SceneInfo GetSceneObjs() = 0; void SetView(double theta, double phi); @@ -186,6 +192,10 @@ class VisualizationScene void SetLight0CustomPos(std::array pos); void ToggleBackground(); + PaletteState& GetPalette() { return palette; } + void GenerateAlphaTexture() + { palette.GenerateAlphaTexture(matAlpha, matAlphaCenter); } + /// This is set by SetVisualizationScene int view; }; diff --git a/lib/palettes.cpp b/lib/palettes.cpp index f916e3b4..e2a8f9c4 100644 --- a/lib/palettes.cpp +++ b/lib/palettes.cpp @@ -7397,110 +7397,109 @@ void Init_Visit_Calewhite_Palette() void Init_Palettes() { - // init rainbow palette - for (int i = 0; i < RGB_Palette_23_Size; i++) + static bool first_init = true; + if (first_init) { - double t = double(i) / (RGB_Palette_23_Size-1), s, r, g, b; - // t *= 3.0; // red to red - t *= 2.5; // red to purple - if (t < 1.0) - { - s = sin(t * M_PI); - if (t < 0.5) - { - r = 1.0; - g = s; - } - else - { - r = s; - g = 1.0; - } - b = 0.0; - } - else if (t < 2.0) + // init rainbow palette + for (int i = 0; i < RGB_Palette_23_Size; i++) { - s = sin((t - 1.0) * M_PI); - if (t < 1.5) - { - g = 1.0; - b = s; - } - else + double t = double(i) / (RGB_Palette_23_Size-1), s, r, g, b; + // t *= 3.0; // red to red + t *= 2.5; // red to purple + if (t < 1.0) { - g = s; - b = 1.0; + s = sin(t * M_PI); + if (t < 0.5) + { + r = 1.0; + g = s; + } + else + { + r = s; + g = 1.0; + } + b = 0.0; } - r = 0.0; - } - else - { - s = sin((t - 2.0) * M_PI); - if (t < 2.5) + else if (t < 2.0) { - r = s; - b = 1.0; + s = sin((t - 1.0) * M_PI); + if (t < 1.5) + { + g = 1.0; + b = s; + } + else + { + g = s; + b = 1.0; + } + r = 0.0; } else { - r = 1.0; - b = s; + s = sin((t - 2.0) * M_PI); + if (t < 2.5) + { + r = s; + b = 1.0; + } + else + { + r = 1.0; + b = s; + } + g = 0.0; } - g = 0.0; + RGB_Palette_23[i][0] = r; + RGB_Palette_23[i][1] = g; + RGB_Palette_23[i][2] = b; } - RGB_Palette_23[i][0] = r; - RGB_Palette_23[i][1] = g; - RGB_Palette_23[i][2] = b; - } - // init vivid palette - const int ns = 7; - const double ts[ns] = { 0., 3./16., 4./16., 1./2., 12./16., 13./16., 1. }; + // init vivid palette + const int ns = 7; + const double ts[ns] = { 0., 3./16., 4./16., 1./2., 12./16., 13./16., 1. }; - const double rs[ns] = { 0.0, 0.0, 0.0, 1.0, 0.9, 1.0, 0.5 }; - const double gs[ns] = { 0.0, 1.0, 0.9, 1.0, 0.0, 0.0, 0.0 }; - const double bs[ns] = { 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0 }; - const double rc[ns-1] = { 1.0, 1.0, 1.3, 1.0, 1.0, 1.2 }; - const double gc[ns-1] = { 1.2, 1.0, 1.0, 1.4, 1.0, 1.0 }; - const double bc[ns-1] = { 1.0, 1.0, 1.0, 1.0, 1.6, 1.0 }; + const double rs[ns] = { 0.0, 0.0, 0.0, 1.0, 0.9, 1.0, 0.5 }; + const double gs[ns] = { 0.0, 1.0, 0.9, 1.0, 0.0, 0.0, 0.0 }; + const double bs[ns] = { 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0 }; + const double rc[ns-1] = { 1.0, 1.0, 1.3, 1.0, 1.0, 1.2 }; + const double gc[ns-1] = { 1.2, 1.0, 1.0, 1.4, 1.0, 1.0 }; + const double bc[ns-1] = { 1.0, 1.0, 1.0, 1.0, 1.6, 1.0 }; - for (int i = 0; i < RGB_Palette_13_Size; i++) - { - double t = double(i) / (RGB_Palette_13_Size-1), r, g, b; - int k; - for (k = 1; k < ns; k++) - if (t >= ts[k-1] && t <= ts[k]) - { - break; - } - t = (t - ts[k-1]) / (ts[k] - ts[k-1]); - r = (1.0 - t) * corr(rc[k-1], rs[k-1]) + t * corr(rc[k-1], rs[k]); - g = (1.0 - t) * corr(gc[k-1], gs[k-1]) + t * corr(gc[k-1], gs[k]); - b = (1.0 - t) * corr(bc[k-1], bs[k-1]) + t * corr(bc[k-1], bs[k]); - RGB_Palette_13[i][0] = corr(1./rc[k-1], r); - RGB_Palette_13[i][1] = corr(1./gc[k-1], g); - RGB_Palette_13[i][2] = corr(1./bc[k-1], b); - } + for (int i = 0; i < RGB_Palette_13_Size; i++) + { + double t = double(i) / (RGB_Palette_13_Size-1), r, g, b; + int k; + for (k = 1; k < ns; k++) + if (t >= ts[k-1] && t <= ts[k]) + { + break; + } + t = (t - ts[k-1]) / (ts[k] - ts[k-1]); + r = (1.0 - t) * corr(rc[k-1], rs[k-1]) + t * corr(rc[k-1], rs[k]); + g = (1.0 - t) * corr(gc[k-1], gs[k-1]) + t * corr(gc[k-1], gs[k]); + b = (1.0 - t) * corr(bc[k-1], bs[k-1]) + t * corr(bc[k-1], bs[k]); + RGB_Palette_13[i][0] = corr(1./rc[k-1], r); + RGB_Palette_13[i][1] = corr(1./gc[k-1], g); + RGB_Palette_13[i][2] = corr(1./bc[k-1], b); + } - Init_Visit_Calewhite_Palette(); + Init_Visit_Calewhite_Palette(); - // init gray palette - for (int i = 0; i < RGB_Palette_36_Size; i++) - { - double t = double(i) / (RGB_Palette_36_Size-1); - RGB_Palette_36[i][0] = t; - RGB_Palette_36[i][1] = t; - RGB_Palette_36[i][2] = t; + // init gray palette + for (int i = 0; i < RGB_Palette_36_Size; i++) + { + double t = double(i) / (RGB_Palette_36_Size-1); + RGB_Palette_36[i][0] = t; + RGB_Palette_36[i][1] = t; + RGB_Palette_36[i][2] = t; + } + first_init = false; } } -bool first_init = true; -GLuint palette_tex[Num_RGB_Palettes][2]; -GLuint alpha_tex; -int curr_palette = 2; -int use_smooth = 0; - -int Choose_Palette() +int PaletteState::ChoosePalette() { const int buflen = 256; char buffer[buflen]; @@ -7541,14 +7540,11 @@ int Choose_Palette() } -int RepeatPaletteTimes = 1; -int MaxTextureSize; -GLenum rgba_internal; - /* * * Generates a discrete texture from the given palette. */ -void PaletteToTextureDiscrete(double * palette, size_t plt_size, GLuint tex) +void PaletteState::ToTextureDiscrete(double * palette, size_t plt_size, + GLuint tex) { vector> texture_buf(plt_size); @@ -7622,7 +7618,8 @@ void PaletteToTextureDiscrete(double * palette, size_t plt_size, GLuint tex) /* * * Generates a smooth texture from the given palette. */ -void PaletteToTextureSmooth(double * palette, size_t plt_size, GLuint tex) +void PaletteState::ToTextureSmooth(double * palette, size_t plt_size, + GLuint tex) { vector> texture_buf(MaxTextureSize); glBindTexture(GL_TEXTURE_2D, tex); @@ -7689,18 +7686,15 @@ void PaletteToTextureSmooth(double * palette, size_t plt_size, GLuint tex) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } -void paletteRebind() +PaletteState::PaletteState() + : palette_tex(Num_RGB_Palettes) + , first_init(false) { - GetAppWindow()->getRenderer() - .setColorTexture(palette_tex[curr_palette][use_smooth]); - GetAppWindow()->getRenderer().setAlphaTexture(alpha_tex); } -GLenum alpha_channel; - -void paletteInit() +void PaletteState::Init() { - if (first_init) + if (!first_init) { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); if (MaxTextureSize < 4096) @@ -7710,81 +7704,73 @@ void paletteInit() MaxTextureSize = std::min(MaxTextureSize, 4096); Init_Palettes(); - glGenTextures(Num_RGB_Palettes * 2, &(palette_tex[0][0])); - glGenTextures(1, &alpha_tex); - first_init = false; - } - GLenum alpha_internal; - if (gl3::GLDevice::useLegacyTextureFmts()) - { - alpha_internal = GL_ALPHA; - alpha_channel = GL_ALPHA; - rgba_internal = GL_RGBA; - } - else - { - // WebGL 2 requires sized internal format for float texture - alpha_internal = GL_R32F; - alpha_channel = GL_RED; - rgba_internal = GL_RGBA32F; - } + GLuint paletteTexIds[Num_RGB_Palettes][2]; + GLuint alphaTexId; - for (int i = 0; i < Num_RGB_Palettes; i++) - { - PaletteToTextureDiscrete(RGB_Palettes[i], RGB_Palettes_Sizes[i], - palette_tex[i][0]); - PaletteToTextureSmooth(RGB_Palettes[i], RGB_Palettes_Sizes[i], - palette_tex[i][1]); - } - // set alpha texture to 1.0 - std::vector alphaTexData(MaxTextureSize * 2); - std::fill(alphaTexData.begin(), alphaTexData.end(), 1.0f); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, alpha_tex); - glTexImage2D(GL_TEXTURE_2D, 0, alpha_internal, MaxTextureSize, 2, 0, - alpha_channel, GL_FLOAT, alphaTexData.data()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glGenTextures(Num_RGB_Palettes * 2, &(paletteTexIds[0][0])); + glGenTextures(1, &alphaTexId); - glActiveTexture(GL_TEXTURE0); - paletteRebind(); -} + for (int ipal = 0; ipal < Num_RGB_Palettes; ipal++) + { + palette_tex[ipal][0] = paletteTexIds[ipal][0]; + palette_tex[ipal][1] = paletteTexIds[ipal][1]; + } + alpha_tex = alphaTexId; -void paletteUseDiscrete() -{ - use_smooth = 0; - paletteRebind(); -} + GLenum alpha_internal; + if (gl3::GLDevice::useLegacyTextureFmts()) + { + alpha_internal = GL_ALPHA; + alpha_channel = GL_ALPHA; + rgba_internal = GL_RGBA; + } + else + { + // WebGL 2 requires sized internal format for float texture + alpha_internal = GL_R32F; + alpha_channel = GL_RED; + rgba_internal = GL_RGBA32F; + } + // set alpha texture to 1.0 + std::vector alphaTexData(MaxTextureSize * 2); + std::fill(alphaTexData.begin(), alphaTexData.end(), 1.0f); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, alpha_tex); + glTexImage2D(GL_TEXTURE_2D, 0, alpha_internal, MaxTextureSize, 2, 0, + alpha_channel, GL_FLOAT, alphaTexData.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -void paletteUseSmooth() -{ - use_smooth = 1; - paletteRebind(); -} + glActiveTexture(GL_TEXTURE0); + first_init = true; + } -void paletteSet(int num) -{ - curr_palette = num; - paletteRebind(); + for (int i = 0; i < Num_RGB_Palettes; i++) + { + ToTextureDiscrete(RGB_Palettes[i], RGB_Palettes_Sizes[i], + palette_tex[i][0]); + ToTextureSmooth(RGB_Palettes[i], RGB_Palettes_Sizes[i], + palette_tex[i][1]); + } } -double * paletteGet() +const double * PaletteState::GetData() const { return RGB_Palettes[curr_palette]; } -int paletteGetSize(int pal) +int PaletteState::GetSize(int pal) const { if (pal == -1) { return RGB_Palettes_Sizes[curr_palette]; } - return RGB_Palettes_Sizes[curr_palette]; + return RGB_Palettes_Sizes[pal]; } -void GenerateAlphaTexture(float matAlpha, float matAlphaCenter) +void PaletteState::GenerateAlphaTexture(float matAlpha, float matAlphaCenter) { std::vector alphaTexData(MaxTextureSize); if (matAlpha >= 1.0) @@ -7818,22 +7804,22 @@ void GenerateAlphaTexture(float matAlpha, float matAlphaCenter) glActiveTexture(GL_TEXTURE0); } -void Next_RGB_Palette() +void PaletteState::NextPalette() { - paletteSet((curr_palette + 1) % Num_RGB_Palettes); + SetPalette((curr_palette + 1) % Num_RGB_Palettes); } -void Prev_RGB_Palette() +void PaletteState::PrevPalette() { - paletteSet((curr_palette == 0) ? Num_RGB_Palettes - 1 : + SetPalette((curr_palette == 0) ? Num_RGB_Palettes - 1 : curr_palette - 1); } -int Select_New_RGB_Palette() +int PaletteState::SelectNewRGBPalette() { - int pal = Choose_Palette(); + int pal = ChoosePalette(); - paletteSet(pal); + SetPalette(pal); return pal; } diff --git a/lib/palettes.hpp b/lib/palettes.hpp index e7bcb283..547a05e2 100644 --- a/lib/palettes.hpp +++ b/lib/palettes.hpp @@ -11,27 +11,62 @@ #ifndef GLVIS_PALETTES_HPP #define GLVIS_PALETTES_HPP +#include "gl/renderer.hpp" +#include +#include -/// Initializes the palette textures. -void paletteInit(); -/// Binds the discrete version of the current palette texture. -void paletteUseDiscrete(); -/// Binds the smooth version of the current palette texture. -void paletteUseSmooth(); -/// Sets the palette texture to bind. -void paletteSet(int num); -/// Gets the palette color array. -double * paletteGet(); -/// Rebind the color and alpha textures to their texture units. -void paletteRebind(); +class PaletteState +{ +public: + PaletteState(); + /// Initializes the palette textures. + void Init(); + /// Binds the discrete version of the current palette texture. + void UseDiscrete() { use_smooth = 0; } + /// Binds the smooth version of the current palette texture. + void UseSmooth() { use_smooth = 1; } + /// Gets whether the smooth texture is being used (1 = true) + int GetSmoothSetting() { return use_smooth; } + /// Sets the palette texture to bind. + void SetPalette(int num) { curr_palette = num; } + int GetPalette() const { return curr_palette; } + void NextPalette(); + void PrevPalette(); + int ChoosePalette(); + int SelectNewRGBPalette(); + /// Gets the data in the palette color array. + const double* GetData() const; + /// Gets the total number of colors in the current palette color array. + int GetSize(int pal = -1) const; + /// Gets the number of colors used in the current palette color array. + int GetNumColors(int pal = -1) const + { return PaletteNumColors ? PaletteNumColors : GetSize(pal); } + /// Sets the number of colors to use in the current palette color array. + void SetNumColors(int numColors) { PaletteNumColors = numColors; } + int GetRepeatTimes() const { return RepeatPaletteTimes; } + void SetRepeatTimes(int rpt) { RepeatPaletteTimes = rpt; } -int paletteGetSize(int pal = -1); + GLuint GetColorTexture() const + { return palette_tex[curr_palette][use_smooth]; } + GLuint GetAlphaTexture() const { return alpha_tex; } + void GenerateAlphaTexture(float matAlpha, float matAlphaCenter); +private: + void ToTextureDiscrete(double * palette, size_t plt_size, GLuint tex); + void ToTextureSmooth(double * palette, size_t plt_size, GLuint tex); + using TexHandle = gl3::GLDevice::TextureHandle; -void GenerateAlphaTexture(float matAlpha, float matAlphaCenter); + std::vector> palette_tex; + TexHandle alpha_tex; -void Next_RGB_Palette(); -void Prev_RGB_Palette(); -int Choose_Palette(); -int Select_New_RGB_Palette(); + int curr_palette = 2; + int use_smooth = 0; + int RepeatPaletteTimes = 1; + int PaletteNumColors = 0; + + bool first_init; + int MaxTextureSize; + GLenum alpha_channel; + GLenum rgba_internal; +}; #endif diff --git a/lib/sdl.cpp b/lib/sdl.cpp index e5e354c0..33fc699e 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -652,6 +652,7 @@ void SdlWindow::mainIter() { if (glvis_command->Execute() < 0) { + cout << "GlvisCommand signalled exit" << endl; running = false; } } @@ -663,7 +664,11 @@ void SdlWindow::mainIter() if (glvis_command && visualize == 1 && (status = glvis_command->Execute()) != 1) { - if (status < 0) { running = false; } + if (status < 0) + { + cout << "GlvisCommand signalled exit" << endl; + running = false; + } } else { diff --git a/lib/threads.cpp b/lib/threads.cpp index f2e3cada..0b01147e 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -684,7 +684,7 @@ int GLVisCommand::Execute() case PALETTE: { cout << "Command: palette: " << palette << endl; - paletteSet(palette-1); + (*vs)->GetPalette().SetPalette(palette-1); if (!GetUseTexture()) { (*vs)->EventUpdateColors(); @@ -696,8 +696,8 @@ int GLVisCommand::Execute() case PALETTE_REPEAT: { cout << "Command: palette_repeat: " << palette_repeat << endl; - RepeatPaletteTimes = palette_repeat; - paletteInit(); + (*vs)->GetPalette().SetRepeatTimes(palette_repeat); + (*vs)->GetPalette().Init(); if (!GetUseTexture()) { diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 1f819302..e375c24d 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -559,14 +559,14 @@ void KeypPressed(GLenum state) } else { - Next_RGB_Palette(); + locscene->GetPalette().NextPalette(); SendExposeEvent(); } } void KeyPPressed() { - Prev_RGB_Palette(); + locscene->GetPalette().PrevPalette(); SendExposeEvent(); } @@ -590,6 +590,7 @@ static void KeyF5Pressed() void KeyF6Pressed() { + int RepeatPaletteTimes = vsdata->GetPalette().GetRepeatTimes(); cout << "Palette is repeated " << RepeatPaletteTimes << " times.\n" << "(Negative value means the palette is flipped.)\n" << "Enter new value: " << flush; @@ -600,23 +601,24 @@ void KeyF6Pressed() } cout << "Palette will be repeated " << RepeatPaletteTimes << " times now.\n\n"; + vsdata->GetPalette().SetRepeatTimes(RepeatPaletteTimes); - int pal = Choose_Palette(); + int pal = vsdata->GetPalette().ChoosePalette(); - int colors_used = PaletteNumColors ? PaletteNumColors : paletteGetSize(pal); + int colors_used = vsdata->GetPalette().GetNumColors(pal); + int palette_size = vsdata->GetPalette().GetSize(pal); cout << "\nPalette is using " << colors_used << " colors.\n" - << "Enter new value (0 = use original " << paletteGetSize(pal) + << "Enter new value (0 = use original " << palette_size << " colors): " << flush; - cin >> PaletteNumColors; - if (PaletteNumColors == 1) - { - PaletteNumColors = 0; - } - colors_used = PaletteNumColors ? PaletteNumColors : paletteGetSize(); - cout << "Palette will be using " << colors_used << " colors now.\n"; + cin >> colors_used; + if (colors_used == 1) { colors_used = 0; } + vsdata->GetPalette().SetNumColors(colors_used); - paletteInit(); - paletteSet(pal); + vsdata->GetPalette().Init(); + vsdata->GetPalette().SetPalette(pal); + + colors_used = vsdata->GetPalette().GetNumColors(); + cout << "Palette will be using " << colors_used << " colors now.\n"; vsdata->EventUpdateColors(); SendExposeEvent(); @@ -718,23 +720,23 @@ void KeyF2Pressed() void KeykPressed() { - MatAlpha -= 0.05; - if (MatAlpha < 0.0) + locscene->matAlpha -= 0.05; + if (locscene->matAlpha < 0.0) { - MatAlpha = 0.0; + locscene->matAlpha = 0.0; } - GenerateAlphaTexture(MatAlpha, MatAlphaCenter); + locscene->GenerateAlphaTexture(); SendExposeEvent(); } void KeyKPressed() { - MatAlpha += 0.05; - if (MatAlpha > 1.0) + locscene->matAlpha += 0.05; + if (locscene->matAlpha > 1.0) { - MatAlpha = 1.0; + locscene->matAlpha = 1.0; } - GenerateAlphaTexture(MatAlpha, MatAlphaCenter); + locscene->GenerateAlphaTexture(); SendExposeEvent(); } @@ -752,23 +754,23 @@ void KeyAPressed() void KeyCommaPressed() { - MatAlphaCenter -= 0.25; + locscene->matAlphaCenter -= 0.25; //vsdata -> EventUpdateColors(); - GenerateAlphaTexture(MatAlpha, MatAlphaCenter); + locscene->GenerateAlphaTexture(); SendExposeEvent(); #ifdef GLVIS_DEBUG - cout << "MatAlphaCenter = " << MatAlphaCenter << endl; + cout << "MatAlphaCenter = " << locscene->matAlphaCenter << endl; #endif } void KeyLessPressed() { - MatAlphaCenter += 0.25; + locscene->matAlphaCenter += 0.25; //vsdata -> EventUpdateColors(); - GenerateAlphaTexture(MatAlpha, MatAlphaCenter); + locscene->GenerateAlphaTexture(); SendExposeEvent(); #ifdef GLVIS_DEBUG - cout << "MatAlphaCenter = " << MatAlphaCenter << endl; + cout << "MatAlphaCenter = " << locscene->matAlphaCenter << endl; #endif } @@ -1045,10 +1047,17 @@ gl3::SceneInfo VisualizationSceneScalarData::GetSceneObjs() void VisualizationSceneScalarData::ToggleTexture() { - SetUseTexture((GetUseTexture()+1)%2); - - static const char *texture_type[2] = {"discrete", "smooth"}; - cout << "Texture type : " << texture_type[GetUseTexture()] << endl; + int isSmooth = palette.GetSmoothSetting(); + if (isSmooth) + { + palette.UseDiscrete(); + cout << "Texture type : discrete" << endl; + } + else + { + palette.UseSmooth(); + cout << "Texture type : smooth" << endl; + } } void VisualizationSceneScalarData::SetAutoscale(int _autoscale) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 1792c0b5..bc84968d 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -476,8 +476,7 @@ void VisualizationSceneSolution::Init() VisualizationSceneScalarData::Init(); // Calls FindNewBox() !!! - paletteSet(2); // use the 'jet-like' palette in 2D - SetUseTexture(0); + palette.SetPalette(2); // use the 'jet-like' palette in 2D double eps = 1e-6; // move the cutting plane a bit to avoid artifacts CuttingPlane = new Plane(-1.0,0.0,0.0,(0.5-eps)*x[0]+(0.5+eps)*x[1]); @@ -2318,7 +2317,7 @@ gl3::SceneInfo VisualizationSceneSolution::GetSceneObjs() params.use_clip_plane = draw_cp; double* cp_eqn = CuttingPlane->Equation(); params.clip_plane_eqn = {cp_eqn[0], cp_eqn[1], cp_eqn[2], cp_eqn[3]}; - params.contains_translucent = MatAlpha < 1.0; + params.contains_translucent = matAlpha < 1.0; if (drawelems) { // draw elements @@ -2334,7 +2333,7 @@ gl3::SceneInfo VisualizationSceneSolution::GetSceneObjs() { scene.queue.emplace_back(params, &order_buf); } - params.contains_translucent = MatAlpha < 1.0; + params.contains_translucent = matAlpha < 1.0; params.mesh_material = VisualizationScene::BLK_MAT; // everything below will be drawn in "black" params.static_color = GetLineColor(); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 18686dae..5d06145c 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -769,8 +769,7 @@ void VisualizationSceneSolution3d::Init() node_pos = new double[mesh->GetNV()]; - paletteSet(12); // use the 'vivid' palette in 3D - SetUseTexture(0); + palette.SetPalette(12); // use the 'vivid' palette in 3D double eps = 1e-6; // move the cutting plane a bit to avoid artifacts CuttingPlane = new Plane(-1.0,0.0,0.0,(0.5-eps)*x[0]+(0.5+eps)*x[1]); @@ -3596,7 +3595,7 @@ gl3::SceneInfo VisualizationSceneSolution3d::GetSceneObjs() params.use_clip_plane = cplane; double* cp_eqn = CuttingPlane->Equation(); params.clip_plane_eqn = {cp_eqn[0], cp_eqn[1], cp_eqn[2], cp_eqn[3]}; - params.contains_translucent = MatAlpha < 1.0; + params.contains_translucent = matAlpha < 1.0; if (drawlsurf) { diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 38151978..8fada363 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -974,7 +974,7 @@ gl3::SceneInfo VisualizationSceneVector::GetSceneObjs() { scene.queue.emplace_back(params, &vector_buf); } - params.contains_translucent = MatAlpha < 1.0; + params.contains_translucent = matAlpha < 1.0; if (drawelems) { scene.queue.emplace_back(params, &disp_buf); diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 010d2542..e083b86b 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -1524,7 +1524,7 @@ gl3::SceneInfo VisualizationSceneVector3d::GetSceneObjs() params.use_clip_plane = cplane; double* cp_eqn = CuttingPlane->Equation(); params.clip_plane_eqn = {cp_eqn[0], cp_eqn[1], cp_eqn[2], cp_eqn[3]}; - params.contains_translucent = MatAlpha < 1.0; + params.contains_translucent = matAlpha < 1.0; // draw vector field if (drawvector == 2 || drawvector == 3) { From 6abe3c2311763f8bcc27cedb4088eb7df76c9530 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Tue, 19 Jan 2021 12:18:26 -0800 Subject: [PATCH 02/42] Move background setting to MyExpose --- lib/aux_vis.cpp | 4 ++++ lib/openglvis.cpp | 3 --- lib/openglvis.hpp | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index d841e35f..5b5f7e7a 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -379,6 +379,10 @@ void MyExpose(GLsizei w, GLsizei h) GLuint alpha_tex = locscene->GetPalette().GetAlphaTexture(); wnd->getRenderer().setColorTexture(color_tex); wnd->getRenderer().setAlphaTexture(alpha_tex); + + std::array bgcol = locscene->GetBackgroundColor(); + wnd->getRenderer().setClearColor(bgcol[0], bgcol[1], bgcol[2], bgcol[3]); + gl3::SceneInfo frame = locscene->GetSceneObjs(); for (auto drawable_ptr : frame.needs_buffering) { diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index e4f5d318..893c45e4 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -121,7 +121,6 @@ VisualizationScene::VisualizationScene() ViewCenterY = 0.0; background = BG_WHITE; - GetAppWindow()->getRenderer().setClearColor(1.f, 1.f, 1.f, 1.f); _use_cust_l0_pos = false; light_mat_idx = 3; use_light = true; @@ -183,12 +182,10 @@ void VisualizationScene::ToggleBackground() if (background == BG_BLK) { background = BG_WHITE; - GetAppWindow()->getRenderer().setClearColor(1.f, 1.f, 1.f, 1.f); } else { background = BG_BLK; - GetAppWindow()->getRenderer().setClearColor(0.f, 0.f, 0.f, 1.f); } } diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index 46ccce8c..d1c73d6b 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -191,6 +191,17 @@ class VisualizationScene void SetLight0CustomPos(std::array pos); void ToggleBackground(); + std::array GetBackgroundColor() + { + if (background == BG_BLK) + { + return { 0.f, 0.f, 0.f, 1.f }; + } + else + { + return { 1.f, 1.f, 1.f, 1.f }; + } + } PaletteState& GetPalette() { return palette; } void GenerateAlphaTexture() From 00fbe299d021ffc2583348248b291498d9961eb9 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Tue, 19 Jan 2021 16:25:20 -0800 Subject: [PATCH 03/42] Move antialiasing to aux_vis --- lib/aux_vis.cpp | 14 ++++++++++++++ lib/aux_vis.hpp | 1 + lib/vsdata.cpp | 13 ------------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 5b5f7e7a..9797c4e4 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -108,6 +108,8 @@ int InitVisualization (const char name[], int x, int y, int w, int h) wnd->setOnMouseUp(SDL_BUTTON_RIGHT, RightButtonUp); wnd->setOnMouseMove(SDL_BUTTON_RIGHT, RightButtonLoc); + wnd->setOnKeyDown('A', ToggleAntialiasing); + // auxKeyFunc (AUX_p, KeyCtrlP); // handled in vsdata.cpp wnd->setOnKeyDown (SDLK_s, KeyS); wnd->setOnKeyDown ('S', KeyS); @@ -737,6 +739,18 @@ void RightButtonLoc (EventInfo *event) void RightButtonUp (EventInfo*) {} +void ToggleAntialiasing() +{ + bool curr_aa = wnd->getRenderer().getAntialiasing(); + wnd->getRenderer().setAntialiasing(!curr_aa); + const std::string strings_off_on[2] = { "off", "on" }; + + cout << "Multisampling/Antialiasing: " + << strings_off_on[!curr_aa ? 1 : 0] << endl; + + SendExposeEvent(); +} + #if defined(GLVIS_USE_LIBTIFF) const char *glvis_screenshot_ext = ".tif"; #elif defined(GLVIS_USE_LIBPNG) diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 21e00dcd..3a13778b 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -53,6 +53,7 @@ void RightButtonDown (EventInfo *event); void RightButtonLoc (EventInfo *event); void RightButtonUp (EventInfo *event); +void ToggleAntialiasing(); void KeyCtrlP(); void KeyS(); void KeyQPressed(); diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index e375c24d..7e5a1e35 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -740,18 +740,6 @@ void KeyKPressed() SendExposeEvent(); } -void KeyAPressed() -{ - bool curr_aa = GetAppWindow()->getRenderer().getAntialiasing(); - GetAppWindow()->getRenderer().setAntialiasing(!curr_aa); - - cout << "Multisampling/Antialiasing: " - << strings_off_on[!curr_aa ? 1 : 0] << endl; - - // vsdata -> EventUpdateColors(); - SendExposeEvent(); -} - void KeyCommaPressed() { locscene->matAlphaCenter -= 0.25; @@ -1112,7 +1100,6 @@ void VisualizationSceneScalarData::Init() // wnd->setOnKeyDown('a', KeyaPressed); wnd->setOnKeyDown('a', Key_Mod_a_Pressed); - wnd->setOnKeyDown('A', KeyAPressed); wnd->setOnKeyDown('r', KeyrPressed); wnd->setOnKeyDown('R', KeyRPressed); From c8cfa0e06c6c0990c6cb049a4aa6a3bb4ffd8ce3 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Tue, 19 Jan 2021 16:28:40 -0800 Subject: [PATCH 04/42] Create GLVisWindow class, move font handling stuff into it --- glvis.cpp | 41 ++++++++++++-------- lib/aux_vis.cpp | 83 ++++++++++++++++------------------------ lib/aux_vis.hpp | 37 ++++++++++++------ lib/font.cpp | 4 +- lib/font.hpp | 14 ++++++- lib/gl/renderer.cpp | 4 +- lib/gl/renderer.hpp | 11 ++++-- lib/gl/renderer_core.cpp | 12 +++--- lib/gl/renderer_core.hpp | 4 +- lib/gl/renderer_ff.cpp | 14 +++---- lib/gl/renderer_ff.hpp | 4 +- lib/openglvis.hpp | 4 ++ lib/sdl.cpp | 2 +- lib/sdl.hpp | 2 +- lib/vsdata.cpp | 6 +-- 15 files changed, 133 insertions(+), 109 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 8b515748..bb8a8283 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -50,8 +50,10 @@ int window_x = 0; // not a command line option int window_y = 0; // not a command line option int window_w = 400; int window_h = 350; +bool legacy_gl_ctx = false; const char *window_title = string_default; const char *c_plot_caption = string_none; +const char *font_name = string_default; string plot_caption; string extra_caption; @@ -66,6 +68,7 @@ Vector & normals = stream_state.normals; GridFunction *& grid_f = stream_state.grid_f; int & is_gf = stream_state.is_gf; std::string & keys = stream_state.keys; +GLVisWindow * mainWindow = nullptr; VisualizationSceneScalarData *vs = NULL; communication_thread *comm_thread = NULL; @@ -117,15 +120,31 @@ bool GLVisInitVis(int field_type) const char *win_title = (window_title == string_default) ? window_titles[field_type] : window_title; - if (InitVisualization(win_title, window_x, window_y, window_w, window_h)) + try { - cerr << "Initializing the visualization failed." << endl; + mainWindow = new GLVisWindow(win_title, window_x, window_y, + window_w, window_h, legacy_gl_ctx); + } + catch (std::runtime_error& ex) + { + cerr << "Initializing the visualization failed: " << endl + << ex.what() << endl; return false; } + catch(...) + { + cerr << "Initializing the visualization failed - unknown error." + << endl; + return false; + } + if (font_name != string_default) + { + mainWindow->SetFont(font_name); + } if (input_streams.Size() > 0) { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); + mainWindow->getSdl()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); glvis_command = new GLVisCommand(&vs, &mesh, &grid_f, &sol, &keep_attr, &fix_elem_orient); comm_thread = new communication_thread(input_streams); @@ -167,6 +186,8 @@ bool GLVisInitVis(int field_type) { VisualizationSceneSolution3d *vss; vs = vss = new VisualizationSceneSolution3d(*mesh, sol); + // HACK: below needs to be called before ToggleAxes + vs->SetFont(mainWindow->getFont()); if (grid_f) { vss->SetGridFunction(grid_f); @@ -243,11 +264,11 @@ bool GLVisInitVis(int field_type) } if (mesh->SpaceDimension() == 2 && field_type == 2) { - SetVisualizationScene(vs, 2, keys.c_str()); + mainWindow->SetVisualizationScene(vs, 2, keys.c_str()); } else { - SetVisualizationScene(vs, 3, keys.c_str()); + mainWindow->SetVisualizationScene(vs, 3, keys.c_str()); } } return true; @@ -912,14 +933,12 @@ int main (int argc, char *argv[]) bool mac = false; const char *stream_file = string_none; const char *script_file = string_none; - const char *font_name = string_default; int portnum = 19916; bool secure = socketstream::secure_default; int multisample = GetMultisample(); double line_width = 1.0; double ms_line_width = gl3::LINE_WIDTH_AA; int geom_ref_type = Quadrature1D::ClosedUniform; - bool legacy_gl_ctx = false; OptionsParser args(argc, argv); @@ -1035,10 +1054,6 @@ int main (int argc, char *argv[]) { keys = arg_keys; } - if (font_name != string_default) - { - SetFont(font_name); - } if (multisample != GetMultisample()) { SetMultisample(multisample); @@ -1055,10 +1070,6 @@ int main (int argc, char *argv[]) { plot_caption = c_plot_caption; } - if (legacy_gl_ctx == true) - { - SetLegacyGLOnly(legacy_gl_ctx); - } GLVisGeometryRefiner.SetType(geom_ref_type); diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 9797c4e4..5fe88060 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "mfem.hpp" using namespace mfem; @@ -45,12 +46,11 @@ static int glvis_multisample = -1; float line_w = 1.f; float line_w_aa = gl3::LINE_WIDTH_AA; -SdlWindow * wnd = nullptr; -bool wndLegacyGl = false; +[[deprecated]] SdlWindow* wnd; SdlWindow * GetAppWindow() { - return wnd; + return wnd; } VisualizationScene * GetVisualizationScene() @@ -58,38 +58,27 @@ VisualizationScene * GetVisualizationScene() return locscene; } -void SetLegacyGLOnly(bool status) -{ - wndLegacyGl = true; -} - void MyExpose(GLsizei w, GLsizei h); void MyExpose(); -int InitVisualization (const char name[], int x, int y, int w, int h) +GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly) + : locscene(nullptr) { #ifdef GLVIS_DEBUG cout << "OpenGL Visualization" << endl; #endif - if (!wnd) - { - wnd = new SdlWindow(); - if (!wnd->createWindow(name, x, y, w, h, wndLegacyGl)) - { - return 1; - } - } - else + wnd.reset(new SdlWindow()); + if (!wnd->createWindow(name, x, y, w, h, legacyGlOnly)) { - cout << "Error: visualization is already up." << endl; - return 1; + throw std::runtime_error("Could not create an SDL window."); } - + ::wnd = wnd.get(); #ifdef GLVIS_DEBUG cout << "Window should be up" << endl; #endif InitFont(); + wnd->getRenderer().setFont(&font); wnd->getRenderer().setLineWidth(line_w); wnd->getRenderer().setLineWidthMS(line_w_aa); @@ -173,15 +162,7 @@ int InitVisualization (const char name[], int x, int y, int w, int h) #ifndef __EMSCRIPTEN__ wnd->setOnKeyDown(SDLK_LEFTPAREN, ShrinkWindow); wnd->setOnKeyDown(SDLK_RIGHTPAREN, EnlargeWindow); - - if (locscene) - { - delete locscene; - } #endif - locscene = nullptr; - - return 0; } void SendKeySequence(const char *seq) @@ -293,10 +274,11 @@ void CallKeySequence(const char *seq) void InitIdleFuncs(); -void SetVisualizationScene(VisualizationScene * scene, int view, - const char *keys) +void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, + const char *keys) { - locscene = scene; + ::locscene = locscene = scene; + locscene->SetFont(&font); locscene -> view = view; if (view == 2) { @@ -327,7 +309,7 @@ void RunVisualization() #endif InitIdleFuncs(); delete locscene; - delete wnd; + //delete wnd; wnd = nullptr; } @@ -1617,23 +1599,27 @@ vector fc_font_patterns = "Helvetica:style=Regular", }; -constexpr int default_font_size = 12; -int font_size = default_font_size; +//constexpr int default_font_size = 12; +//int font_size = default_font_size; -GlVisFont glvis_font; -std::string priority_font; +//GlVisFont glvis_font; +//std::string priority_font; -void InitFont() +void GLVisWindow::InitFont() { // This function is called after the window is created. GLenum alphaChannel = gl3::GLDevice::useLegacyTextureFmts() ? GL_ALPHA : GL_RED; - glvis_font.setAlphaChannel(alphaChannel); + int ppi_w, ppi_h; + wnd->getDpi(ppi_w, ppi_h); + bool is_hidpi = wnd->isHighDpi(); + font.SetDPIParams(is_hidpi, ppi_w, ppi_h); + font.setAlphaChannel(alphaChannel); bool try_fc_patterns = true; if (!priority_font.empty()) { if (SetFont({priority_font}, font_size) || - glvis_font.LoadFont(priority_font, 0, font_size)) + font.LoadFont(priority_font, 0, font_size)) { try_fc_patterns = false; } @@ -1652,18 +1638,13 @@ void InitFont() << endl; } } - wnd->getRenderer().setFontTexture(glvis_font.getFontTex()); -} - -GlVisFont * GetFont() -{ - return &glvis_font; + wnd->getRenderer().setFontTexture(font.getFontTex()); } -bool SetFont(const vector& font_patterns, int height) +bool GLVisWindow::SetFont(const vector& font_patterns, int height) { #ifdef __EMSCRIPTEN__ - return glvis_font.LoadFont("OpenSans.ttf", 0, height); + return font.LoadFont("OpenSans.ttf", 0, height); #else if (!FcInit()) { @@ -1726,7 +1707,7 @@ bool SetFont(const vector& font_patterns, int height) FcFontSetDestroy(fs); if (font_file != std::string("")) { - if (glvis_font.LoadFont(font_file, font_index, height)) + if (font.LoadFont(font_file, font_index, height)) { break; } @@ -1740,11 +1721,11 @@ bool SetFont(const vector& font_patterns, int height) FcFini(); - return glvis_font.isFontLoaded(); + return font.isFontLoaded(); #endif } -void SetFont(const std::string& fn) +void GLVisWindow::SetFont(const std::string& fn) { priority_font = fn; size_t pos = priority_font.rfind('-'); diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 3a13778b..cbce4c67 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -19,11 +19,31 @@ #include "font.hpp" #include "openglvis.hpp" -/// Initializes the visualization and some keys. -int InitVisualization(const char name[], int x, int y, int w, int h); +class GLVisWindow +{ +public: + /// Initializes the visualization and some keys. + GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly); -void SetVisualizationScene(VisualizationScene * scene, - int view = 3, const char *keys = NULL); + void SetVisualizationScene(VisualizationScene * scene, + int view = 3, const char *keys = NULL); + void SetFont(const std::string& fn); + + GlVisFont* getFont() { return &font; } + + SdlWindow* getSdl() { return wnd.get(); } + +private: + void InitFont(); + bool SetFont(const vector& patterns, int height); + std::unique_ptr wnd; + VisualizationScene* locscene; + + int visualize; + GlVisFont font; + std::string priority_font; + int font_size = 12; +}; /// Start the infinite visualization loop. void RunVisualization(); @@ -35,11 +55,9 @@ void MyExpose(); void MainLoop(); -SdlWindow * GetAppWindow(); +[[deprecated]] SdlWindow * GetAppWindow(); VisualizationScene * GetVisualizationScene(); -void SetLegacyGLOnly(bool status); - void AddIdleFunc(void (*Func)(void)); void RemoveIdleFunc(void (*Func)(void)); @@ -125,9 +143,4 @@ float GetLineWidth(); void SetLineWidthMS(float width_ms); float GetLineWidthMS(); -void InitFont(); -GlVisFont * GetFont(); -bool SetFont(const vector& patterns, int height); -void SetFont(const std::string& fn); - #endif diff --git a/lib/font.cpp b/lib/font.cpp index a365b2f5..04ae2624 100644 --- a/lib/font.cpp +++ b/lib/font.cpp @@ -43,13 +43,11 @@ bool GlVisFont::LoadFont(const std::string& path, int font_index, int font_size) return false; } face_has_kerning = FT_HAS_KERNING(face); - int ppi_w, ppi_h; - GetAppWindow()->getDpi(ppi_w, ppi_h); const bool use_fixed_ppi_h = true; if (use_fixed_ppi_h) { double ratio = double(ppi_w)/ppi_h; - ppi_h = GetAppWindow()->isHighDpi() ? 192 : 96; + ppi_h = is_hidpi ? 192 : 96; ppi_w = ratio*ppi_h + 0.5; #ifdef GLVIS_DEBUG cout << "Fonts use fixed ppi: " << ppi_w << " x " << ppi_h << endl; diff --git a/lib/font.hpp b/lib/font.hpp index 58218a1e..02eca930 100644 --- a/lib/font.hpp +++ b/lib/font.hpp @@ -47,8 +47,18 @@ class GlVisFont FT_Library library; FT_Face face; bool face_has_kerning; + + bool is_hidpi; + int ppi_w, ppi_h; public: + void SetDPIParams(bool is_hidpi, int ppi_w, int ppi_h) + { + this->is_hidpi = is_hidpi; + this->ppi_w = ppi_w; + this->ppi_h = ppi_h; + } + bool LoadFont(const std::string& path, int font_index, int font_size); const glyph &GetTexChar(char c) const @@ -62,7 +72,9 @@ class GlVisFont GlVisFont() : init(false), font_init(false), - face_has_kerning(false) + face_has_kerning(false), + is_hidpi(false), + ppi_w(96), ppi_h(96) { if (FT_Init_FreeType(&library)) { diff --git a/lib/gl/renderer.cpp b/lib/gl/renderer.cpp index 6bec6504..647dec01 100644 --- a/lib/gl/renderer.cpp +++ b/lib/gl/renderer.cpp @@ -238,7 +238,7 @@ void MeshRenderer::render(const RenderQueue& queue) device->setNumLights(0); for (TextBuffer* buf : text_bufs) { - device->drawDeviceBuffer(*buf); + device->drawDeviceBuffer(*font, *buf); } device->enableDepthWrite(); if (feat_use_fbo_antialias || !msaa_enable) { device->disableBlend(); } @@ -391,7 +391,7 @@ void MeshRenderer::buffer(GlDrawable* buf) } } } - device->bufferToDevice(buf->text_buffer); + device->bufferToDevice(*font, buf->text_buffer); } void GLDevice::init() diff --git a/lib/gl/renderer.hpp b/lib/gl/renderer.hpp index 84c3a456..4a811e46 100644 --- a/lib/gl/renderer.hpp +++ b/lib/gl/renderer.hpp @@ -20,6 +20,7 @@ #include "platform_gl.hpp" #include "types.hpp" #include "../material.hpp" +#include "../font.hpp" namespace gl3 { @@ -237,10 +238,10 @@ class GLDevice // Load a client-side vertex buffer into a device buffer. virtual void bufferToDevice(array_layout layout, IVertexBuffer& buf) = 0; virtual void bufferToDevice(array_layout layout, IIndexedBuffer& buf) = 0; - virtual void bufferToDevice(TextBuffer& t_buf) = 0; + virtual void bufferToDevice(GlVisFont& font, TextBuffer& t_buf) = 0; // Draw the data loaded in a device buffer. virtual void drawDeviceBuffer(int hnd) = 0; - virtual void drawDeviceBuffer(const TextBuffer& t_buf) = 0; + virtual void drawDeviceBuffer(GlVisFont& font, const TextBuffer& t_buf) = 0; // === Transform feedback functions === @@ -263,6 +264,7 @@ class MeshRenderer int msaa_samples; GLuint color_tex, alpha_tex, font_tex; float line_w, line_w_aa; + GlVisFont* font; bool feat_use_fbo_antialias; void init(); @@ -271,7 +273,8 @@ class MeshRenderer : msaa_enable(false) , msaa_samples(0) , line_w(1.f) - , line_w_aa(LINE_WIDTH_AA) { init(); } + , line_w_aa(LINE_WIDTH_AA) + , font(nullptr) { init(); } template void setDevice() @@ -288,6 +291,8 @@ class MeshRenderer device.reset(new TDevice(device)); } + void setFont(GlVisFont* fnt) { this->font = fnt; } + // Sets the texture handle of the color palette. void setColorTexture(GLuint tex_h) { color_tex = tex_h; } // Sets the texture handle of the alpha texture. diff --git a/lib/gl/renderer_core.cpp b/lib/gl/renderer_core.cpp index 688efe9d..ff65a905 100644 --- a/lib/gl/renderer_core.cpp +++ b/lib/gl/renderer_core.cpp @@ -514,19 +514,19 @@ void CoreGLDevice::bufferToDevice(array_layout layout, IIndexedBuffer& buf) buf.getIndices().data(), GL_STATIC_DRAW); } -void CoreGLDevice::bufferToDevice(TextBuffer &t_buf) +void CoreGLDevice::bufferToDevice(GlVisFont& font, TextBuffer &t_buf) { std::vector buf_data; - float tex_w = GetFont()->getAtlasWidth(); - float tex_h = GetFont()->getAtlasHeight(); + float tex_w = font.getAtlasWidth(); + float tex_h = font.getAtlasHeight(); for (auto &e : t_buf) { float pen_x = e.ox, pen_y = e.oy; char prev_c = '\0'; for (char c : e.text) { - const GlVisFont::glyph &g = GetFont()->GetTexChar(c); - pen_x += GetFont()->GetKerning(prev_c, c); + const GlVisFont::glyph &g = font.GetTexChar(c); + pen_x += font.GetKerning(prev_c, c); // note: subtract 1 to account for the padding in the texture glyphs float cur_x = pen_x + g.bear_x - 1; float cur_y = -pen_y - g.bear_y - 1; @@ -626,7 +626,7 @@ void CoreGLDevice::drawDeviceBuffer(int hnd) cerr << "WARNING: Unhandled vertex layout " << vbos[hnd].layout << endl; } } -void CoreGLDevice::drawDeviceBuffer(const TextBuffer& t_buf) +void CoreGLDevice::drawDeviceBuffer(GlVisFont&, const TextBuffer& t_buf) { if (t_buf.getHandle() == 0) { return; } if (t_buf.count() == 0) { return; } diff --git a/lib/gl/renderer_core.hpp b/lib/gl/renderer_core.hpp index fb221528..992c23ae 100644 --- a/lib/gl/renderer_core.hpp +++ b/lib/gl/renderer_core.hpp @@ -97,9 +97,9 @@ class CoreGLDevice : public GLDevice void bufferToDevice(array_layout layout, IVertexBuffer& buf) override; void bufferToDevice(array_layout layout, IIndexedBuffer& buf) override; - void bufferToDevice(TextBuffer& t_buf) override; + void bufferToDevice(GlVisFont& font, TextBuffer& t_buf) override; void drawDeviceBuffer(int hnd) override; - void drawDeviceBuffer(const TextBuffer& t_buf) override; + void drawDeviceBuffer(GlVisFont& font, const TextBuffer& t_buf) override; void initXfbMode() override { diff --git a/lib/gl/renderer_ff.cpp b/lib/gl/renderer_ff.cpp index f4089065..a776f3e8 100644 --- a/lib/gl/renderer_ff.cpp +++ b/lib/gl/renderer_ff.cpp @@ -236,9 +236,9 @@ void FFGLDevice::bufferToDevice(array_layout layout, IIndexedBuffer& buf) } } -void FFGLDevice::bufferToDevice(TextBuffer&) +void FFGLDevice::bufferToDevice(GlVisFont&, TextBuffer&) { - // we can't really do anything here can only compute offset matrix at draw + // we can't really do anything here - can only compute offset matrix at draw } void FFGLDevice::drawDeviceBuffer(int hnd) @@ -266,13 +266,13 @@ void FFGLDevice::drawDeviceBuffer(int hnd) // glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f); } -void FFGLDevice::drawDeviceBuffer(const TextBuffer& buf) +void FFGLDevice::drawDeviceBuffer(GlVisFont& font, const TextBuffer& buf) { glColor4fv(static_color.data()); glNormal3f(0.f, 0.f, 1.f); glMultiTexCoord2f(GL_TEXTURE0, 0.f, 0.f); - float tex_w = GetFont()->getAtlasWidth(); - float tex_h = GetFont()->getAtlasHeight(); + float tex_w = font.getAtlasWidth(); + float tex_h = font.getAtlasHeight(); // Model-view transform: // - scale bounding boxes to relative clip-space/NDC coords // - add z-offset of -0.005 to reduce text hiding by mesh @@ -298,8 +298,8 @@ void FFGLDevice::drawDeviceBuffer(const TextBuffer& buf) char prev_c = '\0'; for (char c : e.text) { - const GlVisFont::glyph &g = GetFont()->GetTexChar(c); - pen_x += GetFont()->GetKerning(prev_c, c); + const GlVisFont::glyph &g = font.GetTexChar(c); + pen_x += font.GetKerning(prev_c, c); // note: subtract 1 to account for the padding in the texture glyphs float cur_x = pen_x + g.bear_x - 1; float cur_y = -pen_y - g.bear_y - 1; diff --git a/lib/gl/renderer_ff.hpp b/lib/gl/renderer_ff.hpp index 5501d78f..0a1e8d62 100644 --- a/lib/gl/renderer_ff.hpp +++ b/lib/gl/renderer_ff.hpp @@ -54,9 +54,9 @@ class FFGLDevice : public GLDevice void bufferToDevice(array_layout layout, IVertexBuffer& buf) override; void bufferToDevice(array_layout layout, IIndexedBuffer& buf) override; - void bufferToDevice(TextBuffer& t_buf) override; + void bufferToDevice(GlVisFont& font, TextBuffer& t_buf) override; void drawDeviceBuffer(int hnd) override; - void drawDeviceBuffer(const TextBuffer& t_buf) override; + void drawDeviceBuffer(GlVisFont& font, const TextBuffer& t_buf) override; void captureXfbBuffer(CaptureBuffer& cbuf, int hnd) override; }; diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index d1c73d6b..f689f402 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -14,6 +14,7 @@ #include #include "sdl.hpp" +#include "font.hpp" #include "gl/types.hpp" #include "material.hpp" #include "palettes.hpp" @@ -134,6 +135,7 @@ class VisualizationScene bool use_light; PaletteState palette; + GlVisFont* font = nullptr; gl3::RenderParams GetMeshDrawParams(); glm::mat4 GetModelViewMtx(); @@ -203,6 +205,8 @@ class VisualizationScene } } + void SetFont(GlVisFont* fnt) { this->font = fnt; }; + PaletteState& GetPalette() { return palette; } void GenerateAlphaTexture() { palette.GenerateAlphaTexture(matAlpha, matAlphaCenter); } diff --git a/lib/sdl.cpp b/lib/sdl.cpp index 33fc699e..114e568e 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -214,7 +214,7 @@ void SdlWindow::probeGLContextSupport(bool legacyGlOnly) #endif } -bool SdlWindow::createWindow(const char * title, int x, int y, int w, int h, +bool SdlWindow::createWindow(const std::string& title, int x, int y, int w, int h, bool legacyGlOnly) { if (!SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) diff --git a/lib/sdl.hpp b/lib/sdl.hpp index 6ae4a21a..31fab675 100644 --- a/lib/sdl.hpp +++ b/lib/sdl.hpp @@ -103,7 +103,7 @@ class SdlWindow /// Creates a new OpenGL window. Returns false if SDL or OpenGL initialization /// fails. - bool createWindow(const char * title, int x, int y, int w, int h, + bool createWindow(const std::string& title, int x, int y, int w, int h, bool legacyGlOnly); /// Runs the window loop. void mainLoop(); diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 7e5a1e35..69a6c8be 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -460,7 +460,7 @@ void VisualizationSceneScalarData::PrepareCaption() caption_buf.clear(); caption_buf.addText(0, 0, 0, caption); updated_bufs.emplace_back(&caption_buf); - GetFont()->getObjectSize(caption, caption_w, caption_h); + font->getObjectSize(caption, caption_w, caption_h); } VisualizationSceneScalarData * vsdata; @@ -996,7 +996,7 @@ gl3::SceneInfo VisualizationSceneScalarData::GetSceneObjs() wnd->getGLDrawSize(gl_w, gl_h); // add caption to draw list double v_pos = 2.; - double line_h = GetFont()->getFontLineSpacing(); + double line_h = font->getFontLineSpacing(); params.model_view.translate(-(double)caption_w / gl_w, 1.0 - 2 * v_pos * line_h / gl_h, 0.0); scene.queue.emplace_back(params, &caption_buf); @@ -1314,7 +1314,7 @@ void VisualizationSceneScalarData::PrepareAxes() if (drawaxes == 1) { - int desc = GetFont()->getFontDescender(); + int desc = font->getFontDescender(); int ox = -desc/2; int oy = -3*desc/2; ostringstream buf; From aa2444c8cffad4acf28490e99bd8b1118d034562 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 27 Jan 2021 15:30:44 -0800 Subject: [PATCH 05/42] Moving more methods to GLVisWindow class --- glvis.cpp | 2 +- lib/aux_vis.cpp | 42 +++++++++++++++++++++++++++++++++--------- lib/aux_vis.hpp | 29 ++++++++++++++++++++++++++--- lib/sdl.hpp | 2 +- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index bb8a8283..f703b618 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -276,7 +276,7 @@ bool GLVisInitVis(int field_type) void GLVisStartVis() { - RunVisualization(); // deletes vs + mainWindow->RunVisualization(); // deletes vs vs = NULL; if (input_streams.Size() > 0) { diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 5fe88060..670e796f 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -47,12 +47,18 @@ float line_w = 1.f; float line_w_aa = gl3::LINE_WIDTH_AA; [[deprecated]] SdlWindow* wnd; +[[deprecated]] GLVisWindow * glvis_wnd = nullptr; SdlWindow * GetAppWindow() { return wnd; } +GLVisWindow * GetGlvisWindow() +{ + return glvis_wnd; +} + VisualizationScene * GetVisualizationScene() { return locscene; @@ -68,6 +74,7 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega #ifdef GLVIS_DEBUG cout << "OpenGL Visualization" << endl; #endif + ::glvis_wnd = this; wnd.reset(new SdlWindow()); if (!wnd->createWindow(name, x, y, w, h, legacyGlOnly)) { @@ -84,8 +91,7 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega // auxReshapeFunc (MyReshape); // not needed, MyExpose calls it // auxReshapeFunc (NULL); - void (*exposeFunc)(void) = MyExpose; - wnd->setOnExpose(exposeFunc); + wnd->setOnExpose([this]() { MyExpose(); }); wnd->setOnMouseDown(SDL_BUTTON_LEFT, LeftButtonDown); wnd->setOnMouseUp(SDL_BUTTON_LEFT, LeftButtonUp); @@ -166,6 +172,16 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega } void SendKeySequence(const char *seq) +{ + glvis_wnd->SendKeySequence(seq); +} + +void CallKeySequence(const char *seq) +{ + glvis_wnd->CallKeySequence(seq); +} + +void GLVisWindow::SendKeySequence(const char *seq) { for (const char* key = seq; *key != '\0'; key++) { @@ -218,9 +234,7 @@ void SendKeySequence(const char *seq) } -static bool disableSendExposeEvent = false; - -void CallKeySequence(const char *seq) +void GLVisWindow::CallKeySequence(const char *seq) { const char *key = seq; @@ -302,7 +316,7 @@ void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, } } -void RunVisualization() +void GLVisWindow::RunVisualization() { #ifndef __EMSCRIPTEN__ wnd->mainLoop(); @@ -314,12 +328,22 @@ void RunVisualization() } void SendExposeEvent() +{ + glvis_wnd->SendExposeEvent(); +} + +void MyExpose() +{ + glvis_wnd->MyExpose(); +} + +void GLVisWindow::SendExposeEvent() { if (disableSendExposeEvent) { return; } wnd->signalExpose(); } -void MyReshape(GLsizei w, GLsizei h) +void GLVisWindow::MyReshape(GLsizei w, GLsizei h) { wnd->getRenderer().setViewport(w, h); @@ -356,7 +380,7 @@ void MyReshape(GLsizei w, GLsizei h) locscene->SetProjectionMtx(projmtx.mtx); } -void MyExpose(GLsizei w, GLsizei h) +void GLVisWindow::MyExpose(GLsizei w, GLsizei h) { MyReshape (w, h); GLuint color_tex = locscene->GetPalette().GetColorTexture(); @@ -375,7 +399,7 @@ void MyExpose(GLsizei w, GLsizei h) wnd->getRenderer().render(frame.queue); } -void MyExpose() +void GLVisWindow::MyExpose() { int w, h; wnd->getGLDrawSize(w, h); diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index cbce4c67..cb9fbbeb 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -33,21 +33,43 @@ class GLVisWindow SdlWindow* getSdl() { return wnd.get(); } + /// Start the infinite visualization loop. + void RunVisualization(); + + /// Send expose event. In our case MyReshape is executed and Draw after it. + void SendExposeEvent(); + + void MyExpose(); + + /// Send a sequence of keystrokes to the visualization window + void SendKeySequence(const char *seq); + + // Directly call the functions assigned to the given keys. Unlike the above + // function, SendKeySequence(), this function does not send X events and + // actually disables the function SendExposeEvent() used by many of the + // functions assigned to keys. Call MyExpose() after calling this function to + // update the visualization window. + void CallKeySequence(const char *seq); private: void InitFont(); bool SetFont(const vector& patterns, int height); + + void MyReshape(GLsizei w, GLsizei h); + void MyExpose(GLsizei w, GLsizei h); std::unique_ptr wnd; VisualizationScene* locscene; + std::vector> idle_funcs; + int visualize; + + bool disableSendExposeEvent = false; + GlVisFont font; std::string priority_font; int font_size = 12; }; -/// Start the infinite visualization loop. -void RunVisualization(); - /// Send expose event. In our case MyReshape is executed and Draw after it. void SendExposeEvent(); @@ -56,6 +78,7 @@ void MyExpose(); void MainLoop(); [[deprecated]] SdlWindow * GetAppWindow(); +[[deprecated]] GLVisWindow * GetGLVisWindow(); VisualizationScene * GetVisualizationScene(); void AddIdleFunc(void (*Func)(void)); diff --git a/lib/sdl.hpp b/lib/sdl.hpp index 31fab675..16680326 100644 --- a/lib/sdl.hpp +++ b/lib/sdl.hpp @@ -29,7 +29,7 @@ struct EventInfo typedef void (*MouseDelegate)(EventInfo*); typedef std::function KeyDelegate; typedef void (*WindowDelegate)(int, int); -typedef void (*Delegate)(); +typedef std::function Delegate; class SdlWindow { From a5f331a4acc9e6de1cba7efe6a0886a247499b20 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 27 Jan 2021 15:58:45 -0800 Subject: [PATCH 06/42] Move idle func handling into GLVisWindow --- glvis.cpp | 6 ++--- lib/aux_vis.cpp | 57 ++++++++++++++++++---------------------------- lib/aux_vis.hpp | 19 ++++++++++++---- lib/vsdata.cpp | 4 ++-- lib/vsvector3d.cpp | 4 ++-- 5 files changed, 43 insertions(+), 47 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index f703b618..509b8029 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -821,7 +821,7 @@ void ExecuteScriptCommand() void ScriptControl(); -void ScriptIdleFunc() +void ScriptIdleFunc(GLVisWindow* wnd) { ExecuteScriptCommand(); if (scr_level == 0) @@ -835,12 +835,12 @@ void ScriptControl() if (scr_running) { scr_running = 0; - RemoveIdleFunc(ScriptIdleFunc); + mainWindow->RemoveIdleFunc(ScriptIdleFunc); } else { scr_running = 1; - AddIdleFunc(ScriptIdleFunc); + mainWindow->AddIdleFunc(ScriptIdleFunc); } } diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 670e796f..3dacaa7a 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -54,7 +54,7 @@ SdlWindow * GetAppWindow() return wnd; } -GLVisWindow * GetGlvisWindow() +GLVisWindow * GetGLVisWindow() { return glvis_wnd; } @@ -69,6 +69,7 @@ void MyExpose(); GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly) : locscene(nullptr) + , idle_funcs(0) { #ifdef GLVIS_DEBUG @@ -286,8 +287,6 @@ void GLVisWindow::CallKeySequence(const char *seq) disableSendExposeEvent = false; } -void InitIdleFuncs(); - void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, const char *keys) { @@ -303,7 +302,6 @@ void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, scene -> CenterObject(); } - InitIdleFuncs(); if (scene -> spinning) { AddIdleFunc(MainLoop); @@ -321,7 +319,6 @@ void GLVisWindow::RunVisualization() #ifndef __EMSCRIPTEN__ wnd->mainLoop(); #endif - InitIdleFuncs(); delete locscene; //delete wnd; wnd = nullptr; @@ -407,38 +404,27 @@ void GLVisWindow::MyExpose() wnd->signalSwap(); } - -Array IdleFuncs; -int LastIdleFunc; - -void InitIdleFuncs() -{ - IdleFuncs.SetSize(0); - LastIdleFunc = 0; - wnd->setOnIdle(NULL); -} - -void MainIdleFunc() +void GLVisWindow::MainIdleFunc() { - LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); - if (IdleFuncs[LastIdleFunc]) + last_idle_func = (last_idle_func + 1) % idle_funcs.Size(); + if (idle_funcs[last_idle_func]) { - (*IdleFuncs[LastIdleFunc])(); + (*idle_funcs[last_idle_func])(this); } } -void AddIdleFunc(void (*Func)(void)) +void GLVisWindow::AddIdleFunc(GLVisWindow::IdleFPtr Func) { - IdleFuncs.Union(Func); - wnd->setOnIdle(MainIdleFunc); + idle_funcs.Union(Func); + wnd->setOnIdle([this](){MainIdleFunc();}); } -void RemoveIdleFunc(void (*Func)(void)) +void GLVisWindow::RemoveIdleFunc(GLVisWindow::IdleFPtr Func) { - IdleFuncs.DeleteFirst(Func); - if (IdleFuncs.Size() == 0) + idle_funcs.DeleteFirst(Func); + if (idle_funcs.Size() == 0) { - wnd->setOnIdle(NULL); + wnd->setOnIdle(nullptr); } } @@ -451,8 +437,9 @@ static GLint oldx, oldy, startx, starty; int constrained_spinning = 0; -void MainLoop() +void MainLoop(GLVisWindow* wnd) { + VisualizationScene* locscene = wnd->getScene(); static int p = 1; struct timespec req; if (locscene->spinning) @@ -475,7 +462,7 @@ void MainLoop() { char fname[20]; snprintf(fname, 20, "GLVis_m%04d", p++); - wnd->screenshot(fname); + wnd->getSdl()->screenshot(fname); } } @@ -512,7 +499,7 @@ inline void ComputeSphereAngles(int &newx, int &newy, void LeftButtonDown (EventInfo *event) { locscene -> spinning = 0; - RemoveIdleFunc(MainLoop); + glvis_wnd->RemoveIdleFunc(MainLoop); oldx = event->mouse_x; oldy = event->mouse_y; @@ -596,7 +583,7 @@ void LeftButtonUp (EventInfo *event) if ( (event->keymod & KMOD_SHIFT) && (xang != 0.0 || yang != 0.0) ) { locscene -> spinning = 1; - AddIdleFunc(MainLoop); + glvis_wnd->AddIdleFunc(MainLoop); if (xang > 20) { xang = 20; } if (xang < -20) { xang = -20; } if (yang > 20) { yang = 20; } if (yang < -20) { yang = -20; } @@ -1205,12 +1192,12 @@ void CheckSpin() if (xang != 0. || yang != 0.) { locscene->spinning = 1; - AddIdleFunc(MainLoop); + glvis_wnd->AddIdleFunc(MainLoop); } else { locscene->spinning = 0; - RemoveIdleFunc(MainLoop); + glvis_wnd->RemoveIdleFunc(MainLoop); } cout << "Spin angle: " << xang << " degrees / frame" << endl; } @@ -1233,14 +1220,14 @@ void KeyDeletePressed() { xang = yang = 0.; locscene -> spinning = 0; - RemoveIdleFunc(MainLoop); + glvis_wnd->RemoveIdleFunc(MainLoop); constrained_spinning = 1; } else { xang = xang_step; locscene -> spinning = 1; - AddIdleFunc(MainLoop); + glvis_wnd->AddIdleFunc(MainLoop); constrained_spinning = 1; } } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index cb9fbbeb..a29898a7 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -12,6 +12,8 @@ #ifndef GLVIS_AUX_VIS_HPP #define GLVIS_AUX_VIS_HPP +#include "mfem/mfem.hpp" + #include "gl/platform_gl.hpp" #include "gl/types.hpp" @@ -22,6 +24,8 @@ class GLVisWindow { public: + using IdleFPtr = void(*)(GLVisWindow* wnd); + /// Initializes the visualization and some keys. GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly); @@ -29,6 +33,8 @@ class GLVisWindow int view = 3, const char *keys = NULL); void SetFont(const std::string& fn); + VisualizationScene* getScene() { return locscene; } + GlVisFont* getFont() { return &font; } SdlWindow* getSdl() { return wnd.get(); } @@ -50,16 +56,22 @@ class GLVisWindow // functions assigned to keys. Call MyExpose() after calling this function to // update the visualization window. void CallKeySequence(const char *seq); + + void AddIdleFunc(IdleFPtr func); + void RemoveIdleFunc(IdleFPtr func); private: void InitFont(); bool SetFont(const vector& patterns, int height); + void MainIdleFunc(); + void MyReshape(GLsizei w, GLsizei h); void MyExpose(GLsizei w, GLsizei h); std::unique_ptr wnd; VisualizationScene* locscene; - std::vector> idle_funcs; + mfem::Array idle_funcs{}; + int last_idle_func = 0; int visualize; @@ -75,15 +87,12 @@ void SendExposeEvent(); void MyExpose(); -void MainLoop(); +void MainLoop(GLVisWindow* wnd); [[deprecated]] SdlWindow * GetAppWindow(); [[deprecated]] GLVisWindow * GetGLVisWindow(); VisualizationScene * GetVisualizationScene(); -void AddIdleFunc(void (*Func)(void)); -void RemoveIdleFunc(void (*Func)(void)); - void LeftButtonDown (EventInfo *event); void LeftButtonLoc (EventInfo *event); void LeftButtonUp (EventInfo *event); diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 69a6c8be..5b778d88 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -531,7 +531,7 @@ void KeyLPressed() void KeyrPressed() { locscene -> spinning = 0; - RemoveIdleFunc(MainLoop); + GetGLVisWindow()->RemoveIdleFunc(MainLoop); vsdata -> CenterObject(); locscene -> ViewAngle = 45.0; @@ -546,7 +546,7 @@ void KeyrPressed() void KeyRPressed() { locscene->spinning = 0; - RemoveIdleFunc(MainLoop); + GetGLVisWindow()->RemoveIdleFunc(MainLoop); vsdata->Toggle2DView(); SendExposeEvent(); } diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index e083b86b..5dd4688a 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -137,7 +137,7 @@ static void KeyBPressed() static void KeyrPressed() { locscene -> spinning = 0; - RemoveIdleFunc(MainLoop); + GetGLVisWindow()->RemoveIdleFunc(MainLoop); vsvector3d -> CenterObject(); locscene -> ViewAngle = 45.0; locscene -> ViewScale = 1.0; @@ -154,7 +154,7 @@ static void KeyrPressed() static void KeyRPressed() { locscene->spinning = 0; - RemoveIdleFunc(MainLoop); + GetGLVisWindow()->RemoveIdleFunc(MainLoop); vsvector3d -> ianim = vsvector3d -> ianimd = 0; vsvector3d -> Prepare(); vsvector3d -> PrepareLines(); From da8381d468f25e21d2c9d1fb41f8982ab628e096 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 11:39:33 -0800 Subject: [PATCH 07/42] Add mouse events, model spinning stuff to GLVisWindow --- lib/aux_vis.cpp | 212 ++++++++++++++++++++++++++++++------------------ lib/aux_vis.hpp | 21 ++--- lib/sdl.hpp | 4 +- 3 files changed, 141 insertions(+), 96 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 3dacaa7a..5fb2d1e8 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -67,14 +67,54 @@ VisualizationScene * GetVisualizationScene() void MyExpose(GLsizei w, GLsizei h); void MyExpose(); +struct GLVisWindow::RotationControl +{ + GLVisWindow* wnd; + double xang = 0., yang = 0.; + gl3::GlMatrix srot; + double sph_t, sph_u; + GLint oldx, oldy, startx, starty; + + bool constrained_spinning = 0; + + void LeftButtonDown (EventInfo *event); + void LeftButtonLoc (EventInfo *event); + void LeftButtonUp (EventInfo *event); + void MiddleButtonDown(EventInfo *event); + void MiddleButtonLoc (EventInfo *event); + void MiddleButtonUp (EventInfo *event); + void RightButtonDown (EventInfo *event); + void RightButtonLoc (EventInfo *event); + void RightButtonUp (EventInfo *event); + + void CheckSpin(); + void Key0Pressed(); + void KeyDeletePressed(); + void KeyEnterPressed(); + MouseDelegate CreateMouseEvent(void (GLVisWindow::RotationControl::*func)(EventInfo*)) + { + return [this, func](EventInfo* ei) { (this->*func)(ei); }; + } + +}; + +template +KeyDelegate CreateKeyEvent(T* inst, void (T::*func)()) +{ + return [inst, func](GLenum) { (inst->*func)(); }; +} + + GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly) : locscene(nullptr) , idle_funcs(0) + , rot_data(new RotationControl) { #ifdef GLVIS_DEBUG cout << "OpenGL Visualization" << endl; #endif + rot_data->wnd = this; ::glvis_wnd = this; wnd.reset(new SdlWindow()); if (!wnd->createWindow(name, x, y, w, h, legacyGlOnly)) @@ -93,6 +133,19 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega // auxReshapeFunc (MyReshape); // not needed, MyExpose calls it // auxReshapeFunc (NULL); wnd->setOnExpose([this]() { MyExpose(); }); + auto LeftButtonDown = rot_data->CreateMouseEvent(&RotationControl::LeftButtonDown); + auto LeftButtonUp = rot_data->CreateMouseEvent(&RotationControl::LeftButtonUp); + auto LeftButtonLoc = rot_data->CreateMouseEvent(&RotationControl::LeftButtonLoc); + auto MiddleButtonDown = rot_data->CreateMouseEvent(&RotationControl::MiddleButtonDown); + auto MiddleButtonUp = rot_data->CreateMouseEvent(&RotationControl::MiddleButtonUp); + auto MiddleButtonLoc = rot_data->CreateMouseEvent(&RotationControl::MiddleButtonLoc); + auto RightButtonDown = rot_data->CreateMouseEvent(&RotationControl::RightButtonDown); + auto RightButtonUp = rot_data->CreateMouseEvent(&RotationControl::RightButtonUp); + auto RightButtonLoc = rot_data->CreateMouseEvent(&RotationControl::RightButtonLoc); + + auto Key0Pressed = CreateKeyEvent(rot_data.get(), &RotationControl::Key0Pressed); + auto KeyEnterPressed = CreateKeyEvent(rot_data.get(), &RotationControl::KeyEnterPressed); + auto KeyDeletePressed = CreateKeyEvent(rot_data.get(), &RotationControl::KeyDeletePressed); wnd->setOnMouseDown(SDL_BUTTON_LEFT, LeftButtonDown); wnd->setOnMouseUp(SDL_BUTTON_LEFT, LeftButtonUp); @@ -304,7 +357,7 @@ void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, if (scene -> spinning) { - AddIdleFunc(MainLoop); + AddIdleFunc(::MainLoop); } if (keys) @@ -428,23 +481,20 @@ void GLVisWindow::RemoveIdleFunc(GLVisWindow::IdleFPtr Func) } } - -double xang = 0., yang = 0.; -gl3::GlMatrix srot; -double sph_t, sph_u; -static GLint oldx, oldy, startx, starty; - -int constrained_spinning = 0; - - void MainLoop(GLVisWindow* wnd) { - VisualizationScene* locscene = wnd->getScene(); + wnd->MainLoop(); +} + +void GLVisWindow::MainLoop() +{ static int p = 1; struct timespec req; + double xang = rot_data->xang; + double yang = rot_data->yang; if (locscene->spinning) { - if (!constrained_spinning) + if (!rot_data->constrained_spinning) { locscene->Rotate(xang, yang); SendExposeEvent(); @@ -462,7 +512,7 @@ void MainLoop(GLVisWindow* wnd) { char fname[20]; snprintf(fname, 20, "GLVis_m%04d", p++); - wnd->getSdl()->screenshot(fname); + wnd->screenshot(fname); } } @@ -473,14 +523,14 @@ inline double sqr(double t) return t*t; } -inline void ComputeSphereAngles(int &newx, int &newy, +inline void ComputeSphereAngles(int viewport_w, int viewport_h, + int &newx, int &newy, double &new_sph_u, double &new_sph_t) { - GLint viewport[4] = { 0, 0, 0, 0 }; + GLint viewport[4] = { 0, 0, viewport_w, viewport_h }; double r, x, y, rr; const double maxr = 0.996194698091745532295; - wnd->getGLDrawSize(viewport[2], viewport[3]); r = sqrt(sqr(viewport[2])+sqr(viewport[3]))*M_SQRT1_2; x = double(newx-viewport[0]-viewport[2]/2) / r; @@ -496,41 +546,46 @@ inline void ComputeSphereAngles(int &newx, int &newy, new_sph_t = atan2(y, x); } -void LeftButtonDown (EventInfo *event) +void GLVisWindow::RotationControl::LeftButtonDown (EventInfo *event) { - locscene -> spinning = 0; - glvis_wnd->RemoveIdleFunc(MainLoop); + wnd->locscene -> spinning = 0; + wnd->RemoveIdleFunc(::MainLoop); oldx = event->mouse_x; oldy = event->mouse_y; - ComputeSphereAngles(oldx, oldy, sph_u, sph_t); + int vp_w, vp_h; + wnd->wnd->getGLDrawSize(vp_w, vp_h); + + ComputeSphereAngles(vp_w, vp_h, oldx, oldy, sph_u, sph_t); srot.identity(); - srot.mult(locscene->cam.RotMatrix()); - srot.mult(locscene->rotmat); + srot.mult(wnd->locscene->cam.RotMatrix()); + srot.mult(wnd->locscene->rotmat); startx = oldx; starty = oldy; } -void LeftButtonLoc (EventInfo *event) +void GLVisWindow::RotationControl::LeftButtonLoc (EventInfo *event) { GLint newx = event->mouse_x; GLint newy = event->mouse_y; - int sendexpose = 1; if (event->keymod & KMOD_CTRL) { if (event->keymod & KMOD_SHIFT) { - locscene->PreRotate(double(newx-oldx)/2, 0.0, 0.0, 1.0); + wnd->locscene->PreRotate(double(newx-oldx)/2, 0.0, 0.0, 1.0); } else { double new_sph_u, new_sph_t; - ComputeSphereAngles(newx, newy, new_sph_u, new_sph_t); + int vp_w, vp_h; + wnd->wnd->getGLDrawSize(vp_w, vp_h); + + ComputeSphereAngles(vp_w, vp_h, newx, newy, new_sph_u, new_sph_t); gl3::GlMatrix newrot; newrot.identity(); @@ -543,36 +598,33 @@ void LeftButtonLoc (EventInfo *event) inprod = InnerProd(scoord, ncoord); CrossProd(scoord, ncoord, cross); - newrot.mult(locscene->cam.TransposeRotMatrix()); + newrot.mult(wnd->locscene->cam.TransposeRotMatrix()); newrot.rotate(acos(inprod)*(180.0/M_PI), cross[0], cross[1], cross[2]); newrot.mult(srot.mtx); - locscene->rotmat = newrot.mtx; + wnd->locscene->rotmat = newrot.mtx; } } else if (event->keymod & KMOD_ALT) { - locscene->Rotate(double(newx-oldx)/2, 0.0, 0.0, 1.0); + wnd->locscene->Rotate(double(newx-oldx)/2, 0.0, 0.0, 1.0); } else if (event->keymod & KMOD_SHIFT) { - locscene->Rotate(double(newx-oldx)/2, double(newy-oldy)/2); + wnd->locscene->Rotate(double(newx-oldx)/2, double(newy-oldy)/2); } else { - locscene->Rotate(double(newy-oldy)/2, 1.0, 0.0, 0.0); - locscene->PreRotate(double(newx-oldx)/2, 0.0, 0.0, 1.0); + wnd->locscene->Rotate(double(newy-oldy)/2, 1.0, 0.0, 0.0); + wnd->locscene->PreRotate(double(newx-oldx)/2, 0.0, 0.0, 1.0); } oldx = newx; oldy = newy; - if (sendexpose) - { - SendExposeEvent(); - } + wnd->SendExposeEvent(); } -void LeftButtonUp (EventInfo *event) +void GLVisWindow::RotationControl::LeftButtonUp (EventInfo *event) { GLint newx = event->mouse_x; GLint newy = event->mouse_y; @@ -582,8 +634,8 @@ void LeftButtonUp (EventInfo *event) if ( (event->keymod & KMOD_SHIFT) && (xang != 0.0 || yang != 0.0) ) { - locscene -> spinning = 1; - glvis_wnd->AddIdleFunc(MainLoop); + wnd->locscene -> spinning = 1; + wnd->AddIdleFunc(::MainLoop); if (xang > 20) { xang = 20; } if (xang < -20) { xang = -20; } if (yang > 20) { yang = 20; } if (yang < -20) { yang = -20; } @@ -598,13 +650,13 @@ void LeftButtonUp (EventInfo *event) } } -void MiddleButtonDown (EventInfo *event) +void GLVisWindow::RotationControl::MiddleButtonDown (EventInfo *event) { startx = oldx = event->mouse_x; starty = oldy = event->mouse_y; } -void MiddleButtonLoc (EventInfo *event) +void GLVisWindow::RotationControl::MiddleButtonLoc (EventInfo *event) { GLint newx = event->mouse_x; GLint newy = event->mouse_y; @@ -614,15 +666,15 @@ void MiddleButtonLoc (EventInfo *event) int w, h; double TrX, TrY, scale; - if (locscene->OrthogonalProjection) + if (wnd->locscene->OrthogonalProjection) { - scale = locscene->ViewScale; + scale = wnd->locscene->ViewScale; } else { - scale = 0.4142135623730950488/tan(locscene->ViewAngle*(M_PI/360)); + scale = 0.4142135623730950488/tan(wnd->locscene->ViewAngle*(M_PI/360)); } - wnd->getGLDrawSize(w, h); + wnd->wnd->getGLDrawSize(w, h); if (w < h) { scale *= w; @@ -633,12 +685,12 @@ void MiddleButtonLoc (EventInfo *event) } TrX = 2.0*double(oldx-newx)/scale; TrY = 2.0*double(newy-oldy)/scale; - locscene->ViewCenterX += TrX; - locscene->ViewCenterY += TrY; + wnd->locscene->ViewCenterX += TrX; + wnd->locscene->ViewCenterY += TrY; } else { - // locscene->Translate((double)(newx-oldx)/200,(double)(newy-oldy)/200); + // wnd->locscene->Translate((double)(newx-oldx)/200,(double)(newy-oldy)/200); double dx = double(newx-oldx)/400; double dy = double(oldy-newy)/400; @@ -648,40 +700,40 @@ void MiddleButtonLoc (EventInfo *event) double sx = double(newx-startx)/400; double sy = double(starty-newy)/400; - locscene->cam.TurnLeftRight(dx-sx); - locscene->cam.TurnUpDown(sy-dy); + wnd->locscene->cam.TurnLeftRight(dx-sx); + wnd->locscene->cam.TurnUpDown(sy-dy); - locscene->cam.TurnUpDown(-sy); - locscene->cam.TurnLeftRight(sx); + wnd->locscene->cam.TurnUpDown(-sy); + wnd->locscene->cam.TurnLeftRight(sx); } else if (event->keymod & KMOD_ALT) // ctrl + alt { - locscene->cam.MoveForwardBackward(dy); - locscene->cam.TiltLeftRight(-dx); + wnd->locscene->cam.MoveForwardBackward(dy); + wnd->locscene->cam.TiltLeftRight(-dx); } else // ctrl { - locscene->cam.MoveLeftRight(dx); - locscene->cam.MoveUpDown(-dy); + wnd->locscene->cam.MoveLeftRight(dx); + wnd->locscene->cam.MoveUpDown(-dy); } } - SendExposeEvent(); + wnd->SendExposeEvent(); oldx = newx; oldy = newy; } -void MiddleButtonUp (EventInfo*) +void GLVisWindow::RotationControl::MiddleButtonUp (EventInfo*) {} -void RightButtonDown (EventInfo *event) +void GLVisWindow::RotationControl::RightButtonDown (EventInfo *event) { startx = oldx = event->mouse_x; starty = oldy = event->mouse_y; } -void RightButtonLoc (EventInfo *event) +void GLVisWindow::RotationControl::RightButtonLoc (EventInfo *event) { GLint newx = event->mouse_x; GLint newy = event->mouse_y; @@ -712,24 +764,24 @@ void RightButtonLoc (EventInfo *event) x = 0.; y = 0.; z = -1.; } cout << "(x,y,z) = (" << x << ',' << y << ',' << z << ')' << endl; - locscene->SetLight0CustomPos({(float)x, (float)y, (float)z, 0.f}); + wnd->locscene->SetLight0CustomPos({(float)x, (float)y, (float)z, 0.f}); } else if ( !( event->keymod & KMOD_CTRL ) ) { - locscene -> Zoom (exp ( double (oldy-newy) / 100 )); + wnd->locscene -> Zoom (exp ( double (oldy-newy) / 100 )); } else { - locscene -> Scale ( exp ( double (oldy-newy) / 50 ) ); + wnd->locscene -> Scale ( exp ( double (oldy-newy) / 50 ) ); } - SendExposeEvent(); + wnd->SendExposeEvent(); oldx = newx; oldy = newy; } -void RightButtonUp (EventInfo*) +void GLVisWindow::RotationControl::RightButtonUp (EventInfo*) {} void ToggleAntialiasing() @@ -1183,7 +1235,7 @@ void ThreadsRun() } } -void CheckSpin() +void GLVisWindow::RotationControl::CheckSpin() { if (fabs(xang) < 1.e-2) { @@ -1191,22 +1243,22 @@ void CheckSpin() } if (xang != 0. || yang != 0.) { - locscene->spinning = 1; - glvis_wnd->AddIdleFunc(MainLoop); + wnd->locscene->spinning = 1; + wnd->AddIdleFunc(::MainLoop); } else { - locscene->spinning = 0; - glvis_wnd->RemoveIdleFunc(MainLoop); + wnd->locscene->spinning = 0; + wnd->RemoveIdleFunc(::MainLoop); } cout << "Spin angle: " << xang << " degrees / frame" << endl; } const double xang_step = 0.2; // angle in degrees -void Key0Pressed() +void GLVisWindow::RotationControl::Key0Pressed() { - if (!locscene -> spinning) + if (!wnd->locscene -> spinning) { xang = 0; } @@ -1214,27 +1266,27 @@ void Key0Pressed() CheckSpin(); } -void KeyDeletePressed() +void GLVisWindow::RotationControl::KeyDeletePressed() { - if (locscene -> spinning) + if (wnd->locscene -> spinning) { xang = yang = 0.; - locscene -> spinning = 0; - glvis_wnd->RemoveIdleFunc(MainLoop); + wnd->locscene -> spinning = 0; + wnd->RemoveIdleFunc(::MainLoop); constrained_spinning = 1; } else { xang = xang_step; - locscene -> spinning = 1; - glvis_wnd->AddIdleFunc(MainLoop); + wnd->locscene -> spinning = 1; + wnd->AddIdleFunc(::MainLoop); constrained_spinning = 1; } } -void KeyEnterPressed() +void GLVisWindow::RotationControl::KeyEnterPressed() { - if (!locscene -> spinning) + if (!wnd->locscene -> spinning) { xang = 0; } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index a29898a7..42fd914c 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -25,6 +25,7 @@ class GLVisWindow { public: using IdleFPtr = void(*)(GLVisWindow* wnd); + using KeyEvent = void(*)(GLVisWindow* wnd, int keystate); /// Initializes the visualization and some keys. GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly); @@ -59,6 +60,8 @@ class GLVisWindow void AddIdleFunc(IdleFPtr func); void RemoveIdleFunc(IdleFPtr func); + + void MainLoop(); private: void InitFont(); bool SetFont(const vector& patterns, int height); @@ -80,6 +83,10 @@ class GLVisWindow GlVisFont font; std::string priority_font; int font_size = 12; + + struct RotationControl; + std::unique_ptr rot_data; + }; /// Send expose event. In our case MyReshape is executed and Draw after it. @@ -93,16 +100,6 @@ void MainLoop(GLVisWindow* wnd); [[deprecated]] GLVisWindow * GetGLVisWindow(); VisualizationScene * GetVisualizationScene(); -void LeftButtonDown (EventInfo *event); -void LeftButtonLoc (EventInfo *event); -void LeftButtonUp (EventInfo *event); -void MiddleButtonDown(EventInfo *event); -void MiddleButtonLoc (EventInfo *event); -void MiddleButtonUp (EventInfo *event); -void RightButtonDown (EventInfo *event); -void RightButtonLoc (EventInfo *event); -void RightButtonUp (EventInfo *event); - void ToggleAntialiasing(); void KeyCtrlP(); void KeyS(); @@ -122,10 +119,6 @@ void Key7Pressed(); void Key8Pressed(); void Key9Pressed(); -void Key0Pressed(); -void KeyDeletePressed(); -void KeyEnterPressed(); - void KeyLeftPressed(GLenum); void KeyRightPressed(GLenum); void KeyUpPressed(GLenum); diff --git a/lib/sdl.hpp b/lib/sdl.hpp index 16680326..db60ae77 100644 --- a/lib/sdl.hpp +++ b/lib/sdl.hpp @@ -26,9 +26,9 @@ struct EventInfo SDL_Keymod keymod; }; -typedef void (*MouseDelegate)(EventInfo*); +typedef std::function MouseDelegate; typedef std::function KeyDelegate; -typedef void (*WindowDelegate)(int, int); +typedef std::function WindowDelegate; typedef std::function Delegate; class SdlWindow From f439f2b69b4431a1d4988cf8044156b5642dbe2c Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 12:19:55 -0800 Subject: [PATCH 08/42] Move MSAA, screenshot controls into GLVisWindow, add wrapper for member function events --- lib/aux_vis.cpp | 18 ++++++++++++------ lib/aux_vis.hpp | 9 ++++++--- lib/vsdata.cpp | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 5fb2d1e8..6cc752c1 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -157,11 +157,11 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega wnd->setOnMouseUp(SDL_BUTTON_RIGHT, RightButtonUp); wnd->setOnMouseMove(SDL_BUTTON_RIGHT, RightButtonLoc); - wnd->setOnKeyDown('A', ToggleAntialiasing); + SetKeyEventHandler('A', &GLVisWindow::ToggleAntialiasing); // auxKeyFunc (AUX_p, KeyCtrlP); // handled in vsdata.cpp - wnd->setOnKeyDown (SDLK_s, KeyS); - wnd->setOnKeyDown ('S', KeyS); + SetKeyEventHandler (SDLK_s, &GLVisWindow::Screenshot); + SetKeyEventHandler ('S', &GLVisWindow::Screenshot); wnd->setOnKeyDown (SDLK_q, KeyQPressed); // wnd->setOnKeyDown (SDLK_Q, KeyQPressed); @@ -225,6 +225,12 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega #endif } +void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)()) +{ + auto handlerWrapper = [this, handler]() { (this->*handler)(); }; + wnd->setOnKeyDown(key, handlerWrapper); +} + void SendKeySequence(const char *seq) { glvis_wnd->SendKeySequence(seq); @@ -784,7 +790,7 @@ void GLVisWindow::RotationControl::RightButtonLoc (EventInfo *event) void GLVisWindow::RotationControl::RightButtonUp (EventInfo*) {} -void ToggleAntialiasing() +void GLVisWindow::ToggleAntialiasing() { bool curr_aa = wnd->getRenderer().getAntialiasing(); wnd->getRenderer().setAntialiasing(!curr_aa); @@ -1080,7 +1086,7 @@ int Screenshot(const char *fname, bool convert) #endif } -void KeyS() +void GLVisWindow::Screenshot() { static int p = 1; @@ -1150,7 +1156,7 @@ void PrintCaptureBuffer(gl3::CaptureBuffer& cbuf) } } -void KeyCtrlP() +void GLVisWindow::PrintToPDF() { #ifdef __EMSCRIPTEN__ cerr << "Printing in WebGL is not supported at this time." << endl; diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 42fd914c..1619e12e 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -62,10 +62,16 @@ class GLVisWindow void RemoveIdleFunc(IdleFPtr func); void MainLoop(); + + void ToggleAntialiasing(); + void Screenshot(); + void PrintToPDF(); private: void InitFont(); bool SetFont(const vector& patterns, int height); + void SetKeyEventHandler(int key, void (GLVisWindow::*handler)()); + void MainIdleFunc(); void MyReshape(GLsizei w, GLsizei h); @@ -100,9 +106,6 @@ void MainLoop(GLVisWindow* wnd); [[deprecated]] GLVisWindow * GetGLVisWindow(); VisualizationScene * GetVisualizationScene(); -void ToggleAntialiasing(); -void KeyCtrlP(); -void KeyS(); void KeyQPressed(); void ToggleThreads(); void ThreadsPauseFunc(GLenum); diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 5b778d88..e5a3cbf5 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -555,7 +555,7 @@ void KeypPressed(GLenum state) { if (state & KMOD_CTRL) { - KeyCtrlP(); + GetGLVisWindow()->PrintToPDF(); } else { From 24f7e4fbc602621ecaade48956adad430a55ed09 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 13:40:33 -0800 Subject: [PATCH 09/42] Move screenshot implementation to new file --- glvis.cpp | 13 +- lib/CMakeLists.txt | 1 + lib/aux_vis.cpp | 299 ++-------------------------------------- lib/aux_vis.hpp | 5 +- lib/sdl.cpp | 2 +- lib/sdl.hpp | 2 + lib/sdl_screenshot.cpp | 305 +++++++++++++++++++++++++++++++++++++++++ lib/threads.cpp | 10 +- makefile | 5 +- 9 files changed, 333 insertions(+), 309 deletions(-) create mode 100644 lib/sdl_screenshot.cpp diff --git a/glvis.cpp b/glvis.cpp index 509b8029..c33beb30 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -425,7 +425,7 @@ int ScriptReadDisplMesh(istream &scr, Mesh **mp, GridFunction **sp) return 0; } -void ExecuteScriptCommand() +void ExecuteScriptCommand(GLVisWindow* wnd) { if (!script) { @@ -553,12 +553,9 @@ void ExecuteScriptCommand() cout << "Script: screenshot: " << flush; - if (Screenshot(word.c_str(), true)) - { - cout << "Screenshot(" << word << ") failed." << endl; - done_one_command = 1; - continue; - } + + + wnd->Screenshot(word.c_str()); cout << "-> " << word << endl; if (scr_min_val > vs->GetMinV()) @@ -823,7 +820,7 @@ void ScriptControl(); void ScriptIdleFunc(GLVisWindow* wnd) { - ExecuteScriptCommand(); + ExecuteScriptCommand(wnd); if (scr_level == 0) { ScriptControl(); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9858ec6d..7deeb67c 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -19,6 +19,7 @@ list(APPEND SOURCES openglvis.cpp palettes.cpp sdl.cpp + sdl_screenshot.cpp stream_reader.cpp vsdata.cpp vssolution.cpp diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 6cc752c1..94dc2e71 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -802,291 +802,7 @@ void GLVisWindow::ToggleAntialiasing() SendExposeEvent(); } -#if defined(GLVIS_USE_LIBTIFF) -const char *glvis_screenshot_ext = ".tif"; -#elif defined(GLVIS_USE_LIBPNG) -const char *glvis_screenshot_ext = ".png"; -#else -const char *glvis_screenshot_ext = ".bmp"; -#endif - -// https://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom -#if SDL_BYTEORDER == SDL_BIG_ENDIAN -Uint32 rmask = 0xff000000; -Uint32 gmask = 0x00ff0000; -Uint32 bmask = 0x0000ff00: - Uint32 amask = 0x000000ff; -#else // little endian, like x86 -Uint32 rmask = 0x000000ff; -Uint32 gmask = 0x0000ff00; -Uint32 bmask = 0x00ff0000; -Uint32 amask = 0xff000000; -#endif - -// https://halfgeek.org/wiki/Vertically_invert_a_surface_in_SDL -#define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0) -#define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); } - -int InvertSurfaceVertical(SDL_Surface *surface) -{ - Uint8 *t, *a, *b, *last; - Uint16 pitch; - - if ( SDL_LOCKIFMUST(surface) < 0 ) - { - return -2; - } - - /* do nothing unless at least two lines */ - if (surface->h < 2) - { - SDL_UNLOCKIFMUST(surface); - return 0; - } - - /* get a place to store a line */ - pitch = surface->pitch; - t = (Uint8*)malloc(pitch); - - if (t == NULL) - { - SDL_UNLOCKIFMUST(surface); - return -2; - } - - /* get first line; it's about to be trampled */ - memcpy(t,surface->pixels,pitch); - - /* now, shuffle the rest so it's almost correct */ - a = (Uint8*)surface->pixels; - last = a + pitch * (surface->h - 1); - b = last; - - while (a < b) - { - memcpy(a,b,pitch); - a += pitch; - memcpy(b,a,pitch); - b -= pitch; - } - - /* in this shuffled state, the bottom slice is too far down */ - memmove( b, b+pitch, last-b ); - - /* now we can put back that first row--in the last place */ - memcpy(last,t,pitch); - - /* everything is in the right place; close up. */ - free(t); - SDL_UNLOCKIFMUST(surface); - - return 0; -} - -int Screenshot(const char *fname, bool convert) -{ -#ifdef GLVIS_DEBUG - cout << "Screenshot: glFinish() ... " << flush; -#endif - glFinish(); -#ifdef GLVIS_DEBUG - cout << "done." << endl; -#endif -#ifndef __EMSCRIPTEN__ - if (wnd->isExposePending()) - { - MFEM_WARNING("Expose pending, some events may not have been handled." << endl); - } - string filename = fname; - string convert_name = fname; - bool call_convert = false; - if (convert) - { - // check the extension of 'fname' to see if convert is needed - size_t ext_size = strlen(glvis_screenshot_ext); - if (filename.size() < ext_size || - filename.compare(filename.size() - ext_size, - ext_size, glvis_screenshot_ext) != 0) - { - call_convert = true; - filename += glvis_screenshot_ext; - } - } - else // do not call convert - { - filename += glvis_screenshot_ext; - } - - int w, h; - wnd->getGLDrawSize(w, h); - if (wnd->isSwapPending()) - { -#if GLVIS_DEBUG - cerr << "Screenshot: reading image data from back buffer..." << endl; -#endif - glReadBuffer(GL_BACK); - } - else - { -#if GLVIS_DEBUG - cerr << "Screenshot: reading image data from front buffer..." << endl; -#endif - glReadBuffer(GL_FRONT); - } -#if defined(GLVIS_USE_LIBTIFF) - // Save a TIFF image. This requires the libtiff library, see www.libtiff.org - TIFF* image; - - // MyExpose(w,h); - - unsigned char *pixels = new unsigned char[3*w]; - if (!pixels) - { - return 1; - } - - image = TIFFOpen(filename.c_str(), "w"); - if (!image) - { - delete [] pixels; - return 2; - } - - TIFFSetField(image, TIFFTAG_IMAGEWIDTH, w); - TIFFSetField(image, TIFFTAG_IMAGELENGTH, h); - TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8); - TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); - TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); - TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 3); - TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1); - TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); - TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - for (int i = 0; i < h; i++) - { - glReadPixels(0, h-i-1, w, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels); - if (TIFFWriteScanline(image, pixels, i, 0) < 0) - { - TIFFClose(image); - delete [] pixels; - return 3; - } - } - - TIFFFlushData(image); - TIFFClose(image); - delete [] pixels; - -#elif defined(GLVIS_USE_LIBPNG) - // Save as png image. Requires libpng. - - png_byte *pixels = new png_byte[3*w]; - if (!pixels) - { - return 1; - } - - png_structp png_ptr = - png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - { - delete [] pixels; - return 1; - } - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - delete [] pixels; - return 1; - } - - FILE *fp = fopen(filename.c_str(), "wb"); - if (!fp) - { - png_destroy_write_struct(&png_ptr, &info_ptr); - delete [] pixels; - return 2; - } - - if (setjmp(png_jmpbuf(png_ptr))) - { - fclose(fp); - png_destroy_write_struct(&png_ptr, &info_ptr); - delete [] pixels; - return 3; - } - - png_uint_32 ppi = wnd->isHighDpi() ? 144 : 72; // pixels/inch - png_uint_32 ppm = ppi/0.0254 + 0.5; // pixels/meter - png_set_pHYs(png_ptr, info_ptr, ppm, ppm, PNG_RESOLUTION_METER); - - png_init_io(png_ptr, fp); - png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - png_write_info(png_ptr, info_ptr); - for (int i = 0; i < h; i++) - { - glReadPixels(0, h-1-i, w, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels); - png_write_row(png_ptr, pixels); - } - png_write_end(png_ptr, info_ptr); - - fclose(fp); - png_destroy_write_struct(&png_ptr, &info_ptr); - delete [] pixels; - -#else - // use SDL for screenshots - - // https://stackoverflow.com/questions/20233469/how-do-i-take-and-save-a-bmp-screenshot-in-sdl-2 - unsigned char * pixels = new unsigned char[w*h*4]; // 4 bytes for RGBA - glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, w, h, 8*4, w*4, rmask, - gmask, bmask, amask); - if (surf == nullptr) - { - std::cerr << "unable to take screenshot: " << SDL_GetError() << std::endl; - } - else - { - if (InvertSurfaceVertical(surf)) - { - std::cerr << "failed to invert surface, your screenshot may be upside down" << - std::endl; - } - SDL_SaveBMP(surf, filename.c_str()); - SDL_FreeSurface(surf); - // automatically convert to png if not being used - if (!call_convert) - { - call_convert = true; - convert_name += ".png"; - } - } - delete [] pixels; -#endif - - if (call_convert) - { - ostringstream cmd; - cmd << "convert " << filename << ' ' << convert_name; - if (system(cmd.str().c_str())) - { - return 1; - } - remove(filename.c_str()); - } - return 0; -#else - cout << "Screenshots not yet implemented for JS" << endl; - return 1; -#endif -} - -void GLVisWindow::Screenshot() +void GLVisWindow::Screenshot(std::string filename) { static int p = 1; @@ -1106,9 +822,16 @@ void GLVisWindow::Screenshot() else { cout << "Taking snapshot number " << p << "... "; - char fname[20]; - snprintf(fname, 20, "GLVis_s%02d", p++); - wnd->screenshot(fname); + if (filename == "") + { + char fname[20]; + snprintf(fname, 20, "GLVis_s%02d", p++); + wnd->screenshot(fname); + } + else + { + wnd->screenshot(filename); + } cout << "done" << endl; } } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 1619e12e..87ab67e0 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -64,7 +64,8 @@ class GLVisWindow void MainLoop(); void ToggleAntialiasing(); - void Screenshot(); + void Screenshot() { Screenshot(""); } + void Screenshot(std::string filename); void PrintToPDF(); private: void InitFont(); @@ -142,7 +143,7 @@ void ResizeWindow(int w, int h); void SetWindowTitle(const char *title); /// Take a screenshot using libtiff, libpng or sdl2 -int Screenshot(const char *fname, bool convert = false); +//int Screenshot(const char *fname, bool convert = false); /// Send a sequence of keystrokes to the visualization window void SendKeySequence(const char *seq); diff --git a/lib/sdl.cpp b/lib/sdl.cpp index 114e568e..63452998 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -724,7 +724,7 @@ void SdlWindow::mainLoop() } if (takeScreenshot) { - Screenshot(screenshot_file.c_str()); + screenshotHelper(); takeScreenshot = false; } } diff --git a/lib/sdl.hpp b/lib/sdl.hpp index db60ae77..e2740843 100644 --- a/lib/sdl.hpp +++ b/lib/sdl.hpp @@ -96,6 +96,8 @@ class SdlWindow void keyEvent(SDL_Keysym& ks); void keyEvent(char c); + int screenshotHelper(bool convert = false); + std::string saved_keys; public: SdlWindow(); diff --git a/lib/sdl_screenshot.cpp b/lib/sdl_screenshot.cpp new file mode 100644 index 00000000..8a262fec --- /dev/null +++ b/lib/sdl_screenshot.cpp @@ -0,0 +1,305 @@ +// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-443271. +// +// This file is part of the GLVis visualization tool and library. For more +// information and source code availability see https://glvis.org. +// +// GLVis is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#include "sdl.hpp" +#include "mfem.hpp" + +#if defined(GLVIS_USE_LIBTIFF) +#include "tiffio.h" +#elif defined(GLVIS_USE_LIBPNG) +#include +#endif + +#if defined(GLVIS_USE_LIBTIFF) +const char *glvis_screenshot_ext = ".tif"; +#elif defined(GLVIS_USE_LIBPNG) +const char *glvis_screenshot_ext = ".png"; +#else +const char *glvis_screenshot_ext = ".bmp"; +#endif + +// https://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +Uint32 rmask = 0xff000000; +Uint32 gmask = 0x00ff0000; +Uint32 bmask = 0x0000ff00: + Uint32 amask = 0x000000ff; +#else // little endian, like x86 +Uint32 rmask = 0x000000ff; +Uint32 gmask = 0x0000ff00; +Uint32 bmask = 0x00ff0000; +Uint32 amask = 0xff000000; +#endif + +// https://halfgeek.org/wiki/Vertically_invert_a_surface_in_SDL +#define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0) +#define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); } + +using namespace std; + +int InvertSurfaceVertical(SDL_Surface *surface) +{ + Uint8 *t, *a, *b, *last; + Uint16 pitch; + + if ( SDL_LOCKIFMUST(surface) < 0 ) + { + return -2; + } + + /* do nothing unless at least two lines */ + if (surface->h < 2) + { + SDL_UNLOCKIFMUST(surface); + return 0; + } + + /* get a place to store a line */ + pitch = surface->pitch; + t = (Uint8*)malloc(pitch); + + if (t == NULL) + { + SDL_UNLOCKIFMUST(surface); + return -2; + } + + /* get first line; it's about to be trampled */ + memcpy(t,surface->pixels,pitch); + + /* now, shuffle the rest so it's almost correct */ + a = (Uint8*)surface->pixels; + last = a + pitch * (surface->h - 1); + b = last; + + while (a < b) + { + memcpy(a,b,pitch); + a += pitch; + memcpy(b,a,pitch); + b -= pitch; + } + + /* in this shuffled state, the bottom slice is too far down */ + memmove( b, b+pitch, last-b ); + + /* now we can put back that first row--in the last place */ + memcpy(last,t,pitch); + + /* everything is in the right place; close up. */ + free(t); + SDL_UNLOCKIFMUST(surface); + + return 0; +} + +int SdlWindow::screenshotHelper(bool convert) +{ +#ifdef GLVIS_DEBUG + cout << "Screenshot: glFinish() ... " << flush; +#endif + glFinish(); +#ifdef GLVIS_DEBUG + cout << "done." << endl; +#endif +#ifndef __EMSCRIPTEN__ + if (isExposePending()) + { + MFEM_WARNING("Expose pending, some events may not have been handled." << endl); + } + string filename = screenshot_file.c_str(); + string convert_name = screenshot_file.c_str(); + bool call_convert = false; + if (convert) + { + // check the extension of 'fname' to see if convert is needed + size_t ext_size = strlen(glvis_screenshot_ext); + if (filename.size() < ext_size || + filename.compare(filename.size() - ext_size, + ext_size, glvis_screenshot_ext) != 0) + { + call_convert = true; + filename += glvis_screenshot_ext; + } + } + else // do not call convert + { + filename += glvis_screenshot_ext; + } + + int w, h; + getGLDrawSize(w, h); + if (isSwapPending()) + { +#if GLVIS_DEBUG + cerr << "Screenshot: reading image data from back buffer..." << endl; +#endif + glReadBuffer(GL_BACK); + } + else + { +#if GLVIS_DEBUG + cerr << "Screenshot: reading image data from front buffer..." << endl; +#endif + glReadBuffer(GL_FRONT); + } +#if defined(GLVIS_USE_LIBTIFF) + // Save a TIFF image. This requires the libtiff library, see www.libtiff.org + TIFF* image; + + // MyExpose(w,h); + + unsigned char *pixels = new unsigned char[3*w]; + if (!pixels) + { + return 1; + } + + image = TIFFOpen(filename.c_str(), "w"); + if (!image) + { + delete [] pixels; + return 2; + } + + TIFFSetField(image, TIFFTAG_IMAGEWIDTH, w); + TIFFSetField(image, TIFFTAG_IMAGELENGTH, h); + TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); + TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 3); + TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1); + TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + for (int i = 0; i < h; i++) + { + glReadPixels(0, h-i-1, w, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels); + if (TIFFWriteScanline(image, pixels, i, 0) < 0) + { + TIFFClose(image); + delete [] pixels; + return 3; + } + } + + TIFFFlushData(image); + TIFFClose(image); + delete [] pixels; + +#elif defined(GLVIS_USE_LIBPNG) + // Save as png image. Requires libpng. + + png_byte *pixels = new png_byte[3*w]; + if (!pixels) + { + return 1; + } + + png_structp png_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + delete [] pixels; + return 1; + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + delete [] pixels; + return 1; + } + + FILE *fp = fopen(filename.c_str(), "wb"); + if (!fp) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + delete [] pixels; + return 2; + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + delete [] pixels; + return 3; + } + + png_uint_32 ppi = isHighDpi() ? 144 : 72; // pixels/inch + png_uint_32 ppm = ppi/0.0254 + 0.5; // pixels/meter + png_set_pHYs(png_ptr, info_ptr, ppm, ppm, PNG_RESOLUTION_METER); + + png_init_io(png_ptr, fp); + png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png_ptr, info_ptr); + for (int i = 0; i < h; i++) + { + glReadPixels(0, h-1-i, w, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels); + png_write_row(png_ptr, pixels); + } + png_write_end(png_ptr, info_ptr); + + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + delete [] pixels; + +#else + // use SDL for screenshots + + // https://stackoverflow.com/questions/20233469/how-do-i-take-and-save-a-bmp-screenshot-in-sdl-2 + unsigned char * pixels = new unsigned char[w*h*4]; // 4 bytes for RGBA + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, w, h, 8*4, w*4, rmask, + gmask, bmask, amask); + if (surf == nullptr) + { + std::cerr << "unable to take screenshot: " << SDL_GetError() << std::endl; + } + else + { + if (InvertSurfaceVertical(surf)) + { + std::cerr << "failed to invert surface, your screenshot may be upside down" << + std::endl; + } + SDL_SaveBMP(surf, filename.c_str()); + SDL_FreeSurface(surf); + // automatically convert to png if not being used + if (!call_convert) + { + call_convert = true; + convert_name += ".png"; + } + } + delete [] pixels; +#endif + + if (call_convert) + { + ostringstream cmd; + cmd << "convert " << filename << ' ' << convert_name; + if (system(cmd.str().c_str())) + { + return 1; + } + remove(filename.c_str()); + } + return 0; +#else + cout << "Screenshots not yet implemented for JS" << endl; + return 1; +#endif +} diff --git a/lib/threads.cpp b/lib/threads.cpp index 0b01147e..d3d75757 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -511,14 +511,8 @@ int GLVisCommand::Execute() case SCREENSHOT: { cout << "Command: screenshot: " << flush; - if (::Screenshot(screenshot_filename.c_str(), true)) - { - cout << "Screenshot(" << screenshot_filename << ") failed." << endl; - } - else - { - cout << "-> " << screenshot_filename << endl; - } + GetGLVisWindow()->Screenshot(screenshot_filename.c_str()); + cout << "-> " << screenshot_filename << endl; break; } diff --git a/makefile b/makefile index a35d3ded..95c296cd 100644 --- a/makefile +++ b/makefile @@ -214,8 +214,9 @@ Ccc = $(strip $(CC) $(CFLAGS) $(GL_OPTS)) ALL_SOURCE_FILES = \ lib/gl/renderer.cpp lib/gl/renderer_core.cpp lib/gl/renderer_ff.cpp \ lib/gl/types.cpp lib/aux_js.cpp lib/aux_vis.cpp lib/font.cpp lib/gl2ps.c \ - lib/material.cpp lib/openglvis.cpp lib/palettes.cpp lib/sdl.cpp lib/stream_reader.cpp \ - lib/threads.cpp lib/vsdata.cpp lib/vssolution.cpp lib/vssolution3d.cpp \ + lib/material.cpp lib/openglvis.cpp lib/palettes.cpp lib/sdl.cpp \ + lib/sdl_screenshot.cpp lib/stream_reader.cpp lib/threads.cpp \ + lib/vsdata.cpp lib/vssolution.cpp lib/vssolution3d.cpp \ lib/vsvector.cpp lib/vsvector3d.cpp OBJC_SOURCE_FILES = $(if $(NOTMAC),,lib/sdl_mac.mm) DESKTOP_ONLY_SOURCE_FILES = lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c From 6fb5ecdf71869e7b7bce7b3889221f68e4b5fd7b Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 13:50:31 -0800 Subject: [PATCH 10/42] Move some window control functions to GLVisWindow --- glvis.cpp | 2 +- lib/aux_vis.cpp | 42 +++++++++++++++++++++--------------------- lib/aux_vis.hpp | 23 +++++++++++++---------- lib/threads.cpp | 8 ++++---- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index c33beb30..7fc9b136 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -705,7 +705,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr >> window_x >> window_y >> window_w >> window_h; cout << "Script: window: " << window_x << ' ' << window_y << ' ' << window_w << ' ' << window_h << endl; - MoveResizeWindow(window_x, window_y, window_w, window_h); + wnd->MoveResizeWindow(window_x, window_y, window_w, window_h); MyExpose(); } else if (word == "keys") diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 94dc2e71..b07dd2f4 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -163,7 +163,7 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega SetKeyEventHandler (SDLK_s, &GLVisWindow::Screenshot); SetKeyEventHandler ('S', &GLVisWindow::Screenshot); - wnd->setOnKeyDown (SDLK_q, KeyQPressed); + SetKeyEventHandler (SDLK_q, &GLVisWindow::Quit); // wnd->setOnKeyDown (SDLK_Q, KeyQPressed); wnd->setOnKeyDown (SDLK_LEFT, KeyLeftPressed); @@ -209,19 +209,19 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega wnd->setOnKeyDown (SDLK_j, KeyJPressed); // wnd->setOnKeyDown (AUX_J, KeyJPressed); - wnd->setOnKeyDown (SDLK_KP_MULTIPLY, ZoomIn); - wnd->setOnKeyDown (SDLK_KP_DIVIDE, ZoomOut); + SetKeyEventHandler (SDLK_KP_MULTIPLY, &GLVisWindow::ZoomIn); + SetKeyEventHandler (SDLK_KP_DIVIDE, &GLVisWindow::ZoomOut); - wnd->setOnKeyDown (SDLK_ASTERISK, ZoomIn); - wnd->setOnKeyDown (SDLK_SLASH, ZoomOut); + SetKeyEventHandler (SDLK_ASTERISK, &GLVisWindow::ZoomIn); + SetKeyEventHandler (SDLK_SLASH, &GLVisWindow::ZoomOut); - wnd->setOnKeyDown (SDLK_LEFTBRACKET, ScaleDown); - wnd->setOnKeyDown (SDLK_RIGHTBRACKET, ScaleUp); - wnd->setOnKeyDown (SDLK_AT, LookAt); + SetKeyEventHandler (SDLK_LEFTBRACKET, &GLVisWindow::ScaleDown); + SetKeyEventHandler (SDLK_RIGHTBRACKET, &GLVisWindow::ScaleUp); + SetKeyEventHandler (SDLK_AT, &GLVisWindow::LookAt); #ifndef __EMSCRIPTEN__ - wnd->setOnKeyDown(SDLK_LEFTPAREN, ShrinkWindow); - wnd->setOnKeyDown(SDLK_RIGHTPAREN, EnlargeWindow); + SetKeyEventHandler(SDLK_LEFTPAREN, &GLVisWindow::ShrinkWindow); + SetKeyEventHandler(SDLK_RIGHTPAREN, &GLVisWindow::EnlargeWindow); #endif } @@ -920,7 +920,7 @@ void GLVisWindow::PrintToPDF() #endif } -void KeyQPressed() +void GLVisWindow::Quit() { wnd->signalQuit(); visualize = 0; @@ -1169,31 +1169,31 @@ void KeyPlusPressed() SendExposeEvent(); } -void ZoomIn() +void GLVisWindow::ZoomIn() { locscene->Zoom(exp (0.05)); SendExposeEvent(); } -void ZoomOut() +void GLVisWindow::ZoomOut() { locscene->Zoom(exp (-0.05)); SendExposeEvent(); } -void ScaleUp() +void GLVisWindow::ScaleUp() { locscene->Scale(1.025); SendExposeEvent(); } -void ScaleDown() +void GLVisWindow::ScaleDown() { locscene->Scale(1.0/1.025); SendExposeEvent(); } -void LookAt() +void GLVisWindow::LookAt() { cout << "ViewCenter = (" << locscene->ViewCenterX << ',' << locscene->ViewCenterY << ")\nNew x = " << flush; @@ -1205,7 +1205,7 @@ void LookAt() const double window_scale_factor = 1.1; -void ShrinkWindow() +void GLVisWindow::ShrinkWindow() { int w, h; wnd->getWindowSize(w, h); @@ -1217,7 +1217,7 @@ void ShrinkWindow() ResizeWindow(w, h); } -void EnlargeWindow() +void GLVisWindow::EnlargeWindow() { int w, h; wnd->getWindowSize(w, h); @@ -1229,18 +1229,18 @@ void EnlargeWindow() ResizeWindow(w, h); } -void MoveResizeWindow(int x, int y, int w, int h) +void GLVisWindow::MoveResizeWindow(int x, int y, int w, int h) { wnd->setWindowSize(w, h); wnd->setWindowPos(x, y); } -void ResizeWindow(int w, int h) +void GLVisWindow::ResizeWindow(int w, int h) { wnd->setWindowSize(w, h); } -void SetWindowTitle(const char *title) +void GLVisWindow::SetWindowTitle(const char *title) { wnd->setWindowTitle(title); } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 87ab67e0..175fd7a8 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -63,10 +63,23 @@ class GLVisWindow void MainLoop(); + void Quit(); + void ToggleAntialiasing(); void Screenshot() { Screenshot(""); } void Screenshot(std::string filename); void PrintToPDF(); + + void ZoomIn(); + void ZoomOut(); + void ScaleUp(); + void ScaleDown(); + void LookAt(); + void ShrinkWindow(); + void EnlargeWindow(); + void MoveResizeWindow(int x, int y, int w, int h); + void ResizeWindow(int w, int h); + void SetWindowTitle(const char *title); private: void InitFont(); bool SetFont(const vector& patterns, int height); @@ -131,16 +144,6 @@ void KeyJPressed(); void KeyMinusPressed(); void KeyPlusPressed(); -void ZoomIn(); -void ZoomOut(); -void ScaleUp(); -void ScaleDown(); -void LookAt(); -void ShrinkWindow(); -void EnlargeWindow(); -void MoveResizeWindow(int x, int y, int w, int h); -void ResizeWindow(int w, int h); -void SetWindowTitle(const char *title); /// Take a screenshot using libtiff, libpng or sdl2 //int Screenshot(const char *fname, bool convert = false); diff --git a/lib/threads.cpp b/lib/threads.cpp index d3d75757..544078f5 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -520,7 +520,7 @@ int GLVisCommand::Execute() { cout << "Command: keys: '" << key_commands << "'" << endl; // SendKeySequence(key_commands.c_str()); - CallKeySequence(key_commands.c_str()); + GetGLVisWindow()->CallKeySequence(key_commands.c_str()); MyExpose(); break; } @@ -528,7 +528,7 @@ int GLVisCommand::Execute() case WINDOW_SIZE: { cout << "Command: window_size: " << window_w << " x " << window_h << endl; - ResizeWindow(window_w, window_h); + GetGLVisWindow()->ResizeWindow(window_w, window_h); break; } @@ -537,14 +537,14 @@ int GLVisCommand::Execute() cout << "Command: window_geometry: " << "@(" << window_x << "," << window_y << ") " << window_w << " x " << window_h << endl; - MoveResizeWindow(window_x, window_y, window_w, window_h); + GetGLVisWindow()->MoveResizeWindow(window_x, window_y, window_w, window_h); break; } case WINDOW_TITLE: { cout << "Command: window_title: " << window_title << endl; - SetWindowTitle(window_title.c_str()); + GetGLVisWindow()->SetWindowTitle(window_title.c_str()); break; } From da7e90a95c4b0d0fe61affb8300f74fa6e3295bb Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 14:22:38 -0800 Subject: [PATCH 11/42] Move more scene transformation methods into GLVisWindow --- lib/aux_vis.cpp | 115 ++++++++++++++++++++++++---------------------- lib/aux_vis.hpp | 41 +++++++++-------- lib/openglvis.hpp | 4 ++ 3 files changed, 85 insertions(+), 75 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index b07dd2f4..c2164aca 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -64,9 +64,6 @@ VisualizationScene * GetVisualizationScene() return locscene; } -void MyExpose(GLsizei w, GLsizei h); -void MyExpose(); - struct GLVisWindow::RotationControl { GLVisWindow* wnd; @@ -166,24 +163,24 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega SetKeyEventHandler (SDLK_q, &GLVisWindow::Quit); // wnd->setOnKeyDown (SDLK_Q, KeyQPressed); - wnd->setOnKeyDown (SDLK_LEFT, KeyLeftPressed); - wnd->setOnKeyDown (SDLK_RIGHT, KeyRightPressed); - wnd->setOnKeyDown (SDLK_UP, KeyUpPressed); - wnd->setOnKeyDown (SDLK_DOWN, KeyDownPressed); + SetKeyEventHandler (SDLK_LEFT, &GLVisWindow::KeyLeftPressed); + SetKeyEventHandler (SDLK_RIGHT, &GLVisWindow::KeyRightPressed); + SetKeyEventHandler (SDLK_UP, &GLVisWindow::KeyUpPressed); + SetKeyEventHandler (SDLK_DOWN, &GLVisWindow::KeyDownPressed); wnd->setOnKeyDown (SDLK_KP_0, Key0Pressed); - wnd->setOnKeyDown (SDLK_KP_1, Key1Pressed); - wnd->setOnKeyDown (SDLK_KP_2, Key2Pressed); - wnd->setOnKeyDown (SDLK_KP_3, Key3Pressed); - wnd->setOnKeyDown (SDLK_KP_4, Key4Pressed); - wnd->setOnKeyDown (SDLK_KP_5, Key5Pressed); - wnd->setOnKeyDown (SDLK_KP_6, Key6Pressed); - wnd->setOnKeyDown (SDLK_KP_7, Key7Pressed); - wnd->setOnKeyDown (SDLK_KP_8, Key8Pressed); - wnd->setOnKeyDown (SDLK_KP_9, Key9Pressed); - - wnd->setOnKeyDown (SDLK_KP_MEMSUBTRACT, KeyMinusPressed); - wnd->setOnKeyDown (SDLK_KP_MEMADD, KeyPlusPressed); + SetKeyEventHandler (SDLK_KP_1, &GLVisWindow::Key1Pressed); + SetKeyEventHandler (SDLK_KP_2, &GLVisWindow::Key2Pressed); + SetKeyEventHandler (SDLK_KP_3, &GLVisWindow::Key3Pressed); + SetKeyEventHandler (SDLK_KP_4, &GLVisWindow::Key4Pressed); + SetKeyEventHandler (SDLK_KP_5, &GLVisWindow::Key5Pressed); + SetKeyEventHandler (SDLK_KP_6, &GLVisWindow::Key6Pressed); + SetKeyEventHandler (SDLK_KP_7, &GLVisWindow::Key7Pressed); + SetKeyEventHandler (SDLK_KP_8, &GLVisWindow::Key8Pressed); + SetKeyEventHandler (SDLK_KP_9, &GLVisWindow::Key9Pressed); + + SetKeyEventHandler (SDLK_KP_MEMSUBTRACT, &GLVisWindow::KeyMinusPressed); + SetKeyEventHandler (SDLK_KP_MEMADD, &GLVisWindow::KeyPlusPressed); wnd->setOnKeyDown (SDLK_KP_DECIMAL, KeyDeletePressed); wnd->setOnKeyDown (SDLK_KP_ENTER, KeyEnterPressed); @@ -192,21 +189,21 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega wnd->setOnKeyDown (SDLK_RETURN, KeyEnterPressed); wnd->setOnKeyDown (SDLK_0, Key0Pressed); - wnd->setOnKeyDown (SDLK_1, Key1Pressed); - wnd->setOnKeyDown (SDLK_2, Key2Pressed); - wnd->setOnKeyDown (SDLK_3, Key3Pressed); - wnd->setOnKeyDown (SDLK_4, Key4Pressed); - wnd->setOnKeyDown (SDLK_5, Key5Pressed); - wnd->setOnKeyDown (SDLK_6, Key6Pressed); - wnd->setOnKeyDown (SDLK_7, Key7Pressed); - wnd->setOnKeyDown (SDLK_8, Key8Pressed); - wnd->setOnKeyDown (SDLK_9, Key9Pressed); - - wnd->setOnKeyDown (SDLK_MINUS, KeyMinusPressed); - wnd->setOnKeyDown (SDLK_PLUS, KeyPlusPressed); - wnd->setOnKeyDown (SDLK_EQUALS, KeyPlusPressed); - - wnd->setOnKeyDown (SDLK_j, KeyJPressed); + SetKeyEventHandler (SDLK_1, &GLVisWindow::Key1Pressed); + SetKeyEventHandler (SDLK_2, &GLVisWindow::Key2Pressed); + SetKeyEventHandler (SDLK_3, &GLVisWindow::Key3Pressed); + SetKeyEventHandler (SDLK_4, &GLVisWindow::Key4Pressed); + SetKeyEventHandler (SDLK_5, &GLVisWindow::Key5Pressed); + SetKeyEventHandler (SDLK_6, &GLVisWindow::Key6Pressed); + SetKeyEventHandler (SDLK_7, &GLVisWindow::Key7Pressed); + SetKeyEventHandler (SDLK_8, &GLVisWindow::Key8Pressed); + SetKeyEventHandler (SDLK_9, &GLVisWindow::Key9Pressed); + + SetKeyEventHandler (SDLK_MINUS, &GLVisWindow::KeyMinusPressed); + SetKeyEventHandler (SDLK_PLUS, &GLVisWindow::KeyPlusPressed); + SetKeyEventHandler (SDLK_EQUALS, &GLVisWindow::KeyPlusPressed); + + SetKeyEventHandler (SDLK_j, &GLVisWindow::KeyJPressed); // wnd->setOnKeyDown (AUX_J, KeyJPressed); SetKeyEventHandler (SDLK_KP_MULTIPLY, &GLVisWindow::ZoomIn); @@ -231,6 +228,12 @@ void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)()) wnd->setOnKeyDown(key, handlerWrapper); } +void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)(GLenum)) +{ + auto handlerWrapper = [this, handler](GLenum mod) { (this->*handler)(mod); }; + wnd->setOnKeyDown(key, handlerWrapper); +} + void SendKeySequence(const char *seq) { glvis_wnd->SendKeySequence(seq); @@ -1023,31 +1026,31 @@ void GLVisWindow::RotationControl::KeyEnterPressed() CheckSpin(); } -void Key7Pressed() +void GLVisWindow::Key7Pressed() { locscene->PreRotate(1.0, 0.0, -1.0, 0.0); SendExposeEvent(); } -void Key8Pressed() +void GLVisWindow::Key8Pressed() { locscene->Rotate(0.0, -1.0); SendExposeEvent(); } -void Key9Pressed() +void GLVisWindow::Key9Pressed() { locscene->PreRotate(-1.0, 1.0, 0.0, 0.0); SendExposeEvent(); } -void Key4Pressed() +void GLVisWindow::Key4Pressed() { locscene->PreRotate(-1.0, 0.0, 0.0, 1.0); SendExposeEvent(); } -void Key5Pressed() +void GLVisWindow::Key5Pressed() { if (locscene->view == 2) { @@ -1060,31 +1063,31 @@ void Key5Pressed() SendExposeEvent(); } -void Key6Pressed() +void GLVisWindow::Key6Pressed() { locscene->PreRotate(1.0, 0.0, 0.0, 1.0); SendExposeEvent(); } -void Key1Pressed() +void GLVisWindow::Key1Pressed() { locscene->PreRotate(1.0, 1.0, 0.0, 0.0); SendExposeEvent(); } -void Key2Pressed() +void GLVisWindow::Key2Pressed() { locscene->Rotate(1.0, 1.0, 0.0, 0.0); SendExposeEvent(); } -void Key3Pressed() +void GLVisWindow::Key3Pressed() { locscene->PreRotate(1.0, 0.0, 1.0, 0.0); SendExposeEvent(); } -void ShiftView(double dx, double dy) +void ShiftView(VisualizationScene* locscene, double dx, double dy) { double scale; if (locscene->OrthogonalProjection) @@ -1099,11 +1102,11 @@ void ShiftView(double dx, double dy) locscene->ViewCenterY += dy/scale; } -void KeyLeftPressed(GLenum state) +void GLVisWindow::KeyLeftPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(0.05, 0.); + ShiftView(locscene, 0.05, 0.); } else { @@ -1112,11 +1115,11 @@ void KeyLeftPressed(GLenum state) SendExposeEvent(); } -void KeyRightPressed(GLenum state) +void GLVisWindow::KeyRightPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(-0.05, 0.); + ShiftView(locscene, -0.05, 0.); } else { @@ -1125,11 +1128,11 @@ void KeyRightPressed(GLenum state) SendExposeEvent(); } -void KeyUpPressed(GLenum state) +void GLVisWindow::KeyUpPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(0., -0.05); + ShiftView(locscene, 0., -0.05); } else { @@ -1138,11 +1141,11 @@ void KeyUpPressed(GLenum state) SendExposeEvent(); } -void KeyDownPressed(GLenum state) +void GLVisWindow::KeyDownPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(0., 0.05); + ShiftView(locscene, 0., 0.05); } else { @@ -1151,19 +1154,19 @@ void KeyDownPressed(GLenum state) SendExposeEvent(); } -void KeyJPressed() +void GLVisWindow::KeyJPressed() { - locscene->OrthogonalProjection = !(locscene->OrthogonalProjection); + locscene->ToggleProjectionMode(); SendExposeEvent(); } -void KeyMinusPressed() +void GLVisWindow::KeyMinusPressed() { locscene -> Scale(1., 1., 1./1.1); SendExposeEvent(); } -void KeyPlusPressed() +void GLVisWindow::KeyPlusPressed() { locscene -> Scale(1., 1., 1.1); SendExposeEvent(); diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 175fd7a8..af6615f3 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -85,11 +85,33 @@ class GLVisWindow bool SetFont(const vector& patterns, int height); void SetKeyEventHandler(int key, void (GLVisWindow::*handler)()); + void SetKeyEventHandler(int key, void (GLVisWindow::*handler)(GLenum)); void MainIdleFunc(); void MyReshape(GLsizei w, GLsizei h); void MyExpose(GLsizei w, GLsizei h); + + // Internal event handlers for small scene rotations + void Key1Pressed(); + void Key2Pressed(); + void Key3Pressed(); + void Key4Pressed(); + void Key5Pressed(); + void Key6Pressed(); + void Key7Pressed(); + void Key8Pressed(); + void Key9Pressed(); + + // Internal event handlers for other scene rotations, transformations + void KeyLeftPressed(GLenum); + void KeyRightPressed(GLenum); + void KeyUpPressed(GLenum); + void KeyDownPressed(GLenum); + void KeyJPressed(); + void KeyMinusPressed(); + void KeyPlusPressed(); + std::unique_ptr wnd; VisualizationScene* locscene; @@ -120,30 +142,11 @@ void MainLoop(GLVisWindow* wnd); [[deprecated]] GLVisWindow * GetGLVisWindow(); VisualizationScene * GetVisualizationScene(); -void KeyQPressed(); void ToggleThreads(); void ThreadsPauseFunc(GLenum); void ThreadsStop(); void ThreadsRun(); -void Key1Pressed(); -void Key2Pressed(); -void Key3Pressed(); -void Key4Pressed(); -void Key5Pressed(); -void Key6Pressed(); -void Key7Pressed(); -void Key8Pressed(); -void Key9Pressed(); - -void KeyLeftPressed(GLenum); -void KeyRightPressed(GLenum); -void KeyUpPressed(GLenum); -void KeyDownPressed(GLenum); -void KeyJPressed(); -void KeyMinusPressed(); -void KeyPlusPressed(); - /// Take a screenshot using libtiff, libpng or sdl2 //int Screenshot(const char *fname, bool convert = false); diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index f689f402..b3f19f37 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -187,6 +187,10 @@ class VisualizationScene void CenterObject(); void CenterObject2D(); + // Toggles between orthogonal and perspective projections. + void ToggleProjectionMode() + { OrthogonalProjection = !OrthogonalProjection; } + void SetProjectionMtx(glm::mat4 projection) { proj_mtx = projection; } void SetLightMatIdx(unsigned i); int GetLightMatIdx() { return light_mat_idx; } From 58f1aaf728efd31de2c575737a9356877a2ca7fb Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 15:06:17 -0800 Subject: [PATCH 12/42] Move geometry functions into an isolated header --- lib/CMakeLists.txt | 1 + lib/geom_utils.hpp | 147 +++++++++++++++++++++++++++++++++++++++++++ lib/openglvis.hpp | 49 +-------------- lib/vssolution3d.cpp | 86 ------------------------- lib/vssolution3d.hpp | 8 --- makefile | 2 +- 6 files changed, 150 insertions(+), 143 deletions(-) create mode 100644 lib/geom_utils.hpp diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 7deeb67c..e9a3507e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -35,6 +35,7 @@ list(APPEND HEADERS gl/types.hpp aux_vis.hpp font.hpp + geom_utils.hpp logo.hpp material.hpp openglvis.hpp diff --git a/lib/geom_utils.hpp b/lib/geom_utils.hpp new file mode 100644 index 00000000..6438e70d --- /dev/null +++ b/lib/geom_utils.hpp @@ -0,0 +1,147 @@ +// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced +// at the Lawrence Livermore National Laboratory. All Rights reserved. See files +// LICENSE and NOTICE for details. LLNL-CODE-443271. +// +// This file is part of the GLVis visualization tool and library. For more +// information and source code availability see https://glvis.org. +// +// GLVis is free software; you can redistribute it and/or modify it under the +// terms of the BSD-3 license. We welcome feedback and contributions, see file +// CONTRIBUTING.md for details. + +#ifndef GLVIS_GEOM_UTILS_HPP +#define GLVIS_GEOM_UTILS_HPP +#include "mfem.hpp" + +// Some inline functions + +inline void LinearCombination(const double a, const double x[], + const double b, const double y[], double z[]) +{ + z[0] = a*x[0] + b*y[0]; + z[1] = a*x[1] + b*y[1]; + z[2] = a*x[2] + b*y[2]; +} + +inline double InnerProd(const double a[], const double b[]) +{ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +inline void CrossProd(const double a[], const double b[], double cp[]) +{ + cp[0] = a[1] * b[2] - a[2] * b[1]; + cp[1] = a[2] * b[0] - a[0] * b[2]; + cp[2] = a[0] * b[1] - a[1] * b[0]; +} + +inline int Normalize(double v[]) +{ + double len = sqrt(InnerProd(v, v)); + if (len > 0.0) + { + len = 1.0 / len; + } + else + { + return 1; + } + for (int i = 0; i < 3; i++) + { + v[i] *= len; + } + return 0; +} + +inline int Normalize(mfem::DenseMatrix &normals) +{ + int err = 0; + for (int i = 0; i < normals.Width(); i++) + { + err += Normalize(&normals(0, i)); + } + return err; +} +// 'v' must define three vectors that add up to the zero vector +// that is v[0], v[1], and v[2] are the sides of a triangle +inline int UnitCrossProd(double v[][3], double nor[]) +{ + // normalize the three vectors + for (int i = 0; i < 3; i++) + if (Normalize(v[i])) + { + return 1; + } + + // find the pair that forms an angle closest to pi/2, i.e. having + // the longest cross product: + double cp[3][3], max_a = 0.; + int k = 0; + for (int i = 0; i < 3; i++) + { + CrossProd(v[(i+1)%3], v[(i+2)%3], cp[i]); + double a = sqrt(InnerProd(cp[i], cp[i])); + if (max_a < a) + { + max_a = a, k = i; + } + } + if (max_a == 0.) + { + return 1; + } + for (int i = 0; i < 3; i++) + { + nor[i] = cp[k][i] / max_a; + } + + return 0; +} + +inline int Compute3DUnitNormal(const double p1[], const double p2[], + const double p3[], double nor[]) +{ + double v[3][3]; + + for (int i = 0; i < 3; i++) + { + v[0][i] = p2[i] - p1[i]; + v[1][i] = p3[i] - p2[i]; + v[2][i] = p1[i] - p3[i]; + } + + return UnitCrossProd(v, nor); +} + +inline int Compute3DUnitNormal (const double p1[], const double p2[], + const double p3[], const double p4[], double nor[]) +{ + double v[3][3]; + + for (int i = 0; i < 3; i++) + { + // cross product of the two diagonals: + /* + v[0][i] = p3[i] - p1[i]; + v[1][i] = p4[i] - p2[i]; + v[2][i] = (p1[i] + p2[i]) - (p3[i] + p4[i]); + */ + + // cross product of the two vectors connecting the midpoints of the + // two pairs of opposing sides; this gives the normal vector in the + // midpoint of the quad: + v[0][i] = 0.5 * ((p2[i] + p3[i]) - (p1[i] + p4[i])); + v[1][i] = 0.5 * ((p4[i] + p3[i]) - (p1[i] + p2[i])); + v[2][i] = p1[i] - p3[i]; + } + + return UnitCrossProd(v, nor); +} + +inline int ProjectVector(double v[], const double n[]) +{ + // project 'v' on the plane with normal given by 'n' and then normalize 'v' + LinearCombination(InnerProd(n, n), v, -InnerProd(v, n), n, v); + return Normalize(v); +} +#endif // GLVIS_GEOM_UTILS_HPP diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index b3f19f37..b1a5a3b4 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -18,57 +18,10 @@ #include "gl/types.hpp" #include "material.hpp" #include "palettes.hpp" +#include "geom_utils.hpp" // Visualization header file -// Some inline functions - -inline void LinearCombination(const double a, const double x[], - const double b, const double y[], double z[]) -{ - z[0] = a*x[0] + b*y[0]; - z[1] = a*x[1] + b*y[1]; - z[2] = a*x[2] + b*y[2]; -} - -inline double InnerProd(const double a[], const double b[]) -{ - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; -} - -inline void CrossProd(const double a[], const double b[], double cp[]) -{ - cp[0] = a[1] * b[2] - a[2] * b[1]; - cp[1] = a[2] * b[0] - a[0] * b[2]; - cp[2] = a[0] * b[1] - a[1] * b[0]; -} - -inline int Normalize(double v[]) -{ - double len = sqrt(InnerProd(v, v)); - if (len > 0.0) - { - len = 1.0 / len; - } - else - { - return 1; - } - for (int i = 0; i < 3; i++) - { - v[i] *= len; - } - return 0; -} - -inline int ProjectVector(double v[], const double n[]) -{ - // project 'v' on the plane with normal given by 'n' and then normalize 'v' - LinearCombination(InnerProd(n, n), v, -InnerProd(v, n), n, v); - return Normalize(v); -} - - class Camera { private: diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 5d06145c..606d9be8 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -632,82 +632,6 @@ static void KeyF10Pressed() SendExposeEvent(); } -// 'v' must define three vectors that add up to the zero vector -// that is v[0], v[1], and v[2] are the sides of a triangle -int UnitCrossProd(double v[][3], double nor[]) -{ - // normalize the three vectors - for (int i = 0; i < 3; i++) - if (Normalize(v[i])) - { - return 1; - } - - // find the pair that forms an angle closest to pi/2, i.e. having - // the longest cross product: - double cp[3][3], max_a = 0.; - int k = 0; - for (int i = 0; i < 3; i++) - { - CrossProd(v[(i+1)%3], v[(i+2)%3], cp[i]); - double a = sqrt(InnerProd(cp[i], cp[i])); - if (max_a < a) - { - max_a = a, k = i; - } - } - if (max_a == 0.) - { - return 1; - } - for (int i = 0; i < 3; i++) - { - nor[i] = cp[k][i] / max_a; - } - - return 0; -} - -int Compute3DUnitNormal(const double p1[], const double p2[], - const double p3[], double nor[]) -{ - double v[3][3]; - - for (int i = 0; i < 3; i++) - { - v[0][i] = p2[i] - p1[i]; - v[1][i] = p3[i] - p2[i]; - v[2][i] = p1[i] - p3[i]; - } - - return UnitCrossProd(v, nor); -} - -int Compute3DUnitNormal (const double p1[], const double p2[], - const double p3[], const double p4[], double nor[]) -{ - double v[3][3]; - - for (int i = 0; i < 3; i++) - { - // cross product of the two diagonals: - /* - v[0][i] = p3[i] - p1[i]; - v[1][i] = p4[i] - p2[i]; - v[2][i] = (p1[i] + p2[i]) - (p3[i] + p4[i]); - */ - - // cross product of the two vectors connecting the midpoints of the - // two pairs of opposing sides; this gives the normal vector in the - // midpoint of the quad: - v[0][i] = 0.5 * ((p2[i] + p3[i]) - (p1[i] + p4[i])); - v[1][i] = 0.5 * ((p4[i] + p3[i]) - (p1[i] + p2[i])); - v[2][i] = p1[i] - p3[i]; - } - - return UnitCrossProd(v, nor); -} - VisualizationSceneSolution3d::VisualizationSceneSolution3d() {} @@ -1184,16 +1108,6 @@ void VisualizationSceneSolution3d::NumberOfLevelSurf(int c) PrepareLevelSurf(); } -int Normalize(DenseMatrix &normals) -{ - int err = 0; - for (int i = 0; i < normals.Width(); i++) - { - err += Normalize(&normals(0, i)); - } - return err; -} - void VisualizationSceneSolution3d::GetFaceNormals( const int FaceNo, const int side, const IntegrationRule &ir, DenseMatrix &normals) diff --git a/lib/vssolution3d.hpp b/lib/vssolution3d.hpp index 2b9e5699..3640d82f 100644 --- a/lib/vssolution3d.hpp +++ b/lib/vssolution3d.hpp @@ -183,12 +183,4 @@ class VisualizationSceneSolution3d : public VisualizationSceneScalarData virtual int GetDrawMesh() { return drawmesh; } }; -int Normalize(DenseMatrix &normals); - -int Compute3DUnitNormal(const double p1[], const double p2[], - const double p3[], double nor[]); - -int Compute3DUnitNormal (const double p1[], const double p2[], - const double p3[], const double p4[], double nor[]); - #endif diff --git a/makefile b/makefile index 95c296cd..b1ec271d 100644 --- a/makefile +++ b/makefile @@ -230,7 +230,7 @@ COMMON_SOURCE_FILES = $(filter-out \ HEADER_FILES = \ lib/gl/attr_traits.hpp lib/gl/platform_gl.hpp lib/gl/renderer.hpp \ lib/gl/renderer_core.hpp lib/gl/renderer_ff.hpp lib/gl/types.hpp \ - lib/aux_vis.hpp lib/font.hpp lib/gl2ps.h lib/logo.hpp lib/material.hpp \ + lib/aux_vis.hpp lib/font.hpp lib/geom_utils.hpp lib/gl2ps.h lib/logo.hpp lib/material.hpp \ lib/openglvis.hpp lib/palettes.hpp lib/sdl.hpp lib/sdl_helper.hpp \ lib/sdl_mac.hpp lib/sdl_x11.hpp lib/stream_reader.hpp lib/threads.hpp lib/visual.hpp \ lib/vsdata.hpp lib/vssolution.hpp lib/vssolution3d.hpp lib/vsvector.hpp \ From 7d81b6635c88c9a6ed436c9942174b0b30d45544 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 15:36:20 -0800 Subject: [PATCH 13/42] Move some more color functions into PaletteState --- lib/aux_vis.cpp | 37 --------- lib/aux_vis.hpp | 4 - lib/openglvis.cpp | 174 +++++++++++++++++++++++++++++++++++++++++++ lib/openglvis.hpp | 28 +++++++ lib/palettes.cpp | 24 ++++++ lib/palettes.hpp | 6 ++ lib/vsdata.cpp | 3 +- lib/vssolution.cpp | 174 +------------------------------------------ lib/vssolution.hpp | 14 ---- lib/vssolution3d.cpp | 2 +- lib/vsvector.cpp | 2 +- 11 files changed, 238 insertions(+), 230 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index c2164aca..b5ec1d50 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -1248,30 +1248,6 @@ void GLVisWindow::SetWindowTitle(const char *title) wnd->setWindowTitle(title); } -int MySetColorLogscale = 0; - -double GetColorCoord(double val, double min, double max) -{ - // static double eps = 1e-24; - static const double eps = 0.0; - if (MySetColorLogscale) - { - if (val < min) - { - val = min; - } - if (val > max) - { - val = max; - } - return log(fabs(val/(min+eps))) / (log(fabs(max/(min+eps)))+eps); - } - else - { - return ((val-min)/(max-min)); - } -} - void GetColorFromVal(double val, float * rgba) { int palSize = locscene->GetPalette().GetSize(); @@ -1298,19 +1274,6 @@ void GetColorFromVal(double val, float * rgba) rgba[3] = 1.f; } -void MySetColor (gl3::GlBuilder& builder, double val, double min, double max) -{ - MySetColor(builder, GetColorCoord(val, min, max)); -} - -void MySetColor (gl3::GlBuilder& builder, double val) -{ - if (val < 0.0) { val = 0.0; } - if (val > 1.0) { val = 1.0; } - - builder.glTexCoord2f(val, 1.0); -} - int GetUseTexture() { return locscene->GetPalette().GetSmoothSetting(); diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index af6615f3..18b95ef9 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -161,11 +161,7 @@ void SendKeySequence(const char *seq); // update the visualization window. void CallKeySequence(const char *seq); -extern int MySetColorLogscale; -double GetColorCoord(double val, double min, double max); void GetColorFromVal(double val, float * rgba); -void MySetColor(gl3::GlBuilder& builder, double val); -void MySetColor(gl3::GlBuilder& builder, double val, double min, double max); void SetUseTexture(int ut); int GetUseTexture(); diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 893c45e4..bedcefb9 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -14,6 +14,8 @@ #include "material.hpp" #include "aux_vis.hpp" +using namespace mfem; + const int NUM_MATERIALS = 5; extern Material materials[5]; extern Light lights[]; @@ -130,6 +132,178 @@ VisualizationScene::VisualizationScene() VisualizationScene::~VisualizationScene() {} +void VisualizationScene + ::DrawTriangle(gl3::GlDrawable& buff, + const double (&pts)[4][3], const double (&cv)[4], + const double minv, const double maxv) +{ + double nor[3]; + if (Compute3DUnitNormal(pts[0], pts[1], pts[2], nor)) + { + return; + } + + std::array texcoord[3]; + std::array fpts[3]; + std::array fnorm = {(float) nor[0], (float) nor[1], (float) nor[2]}; + + for (int i = 0; i < 3; i++) + { + float pal_coord = palette.GetColorCoord(cv[i], minv, maxv); + texcoord[i] = { pal_coord, 1.0 }; + fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; + } + buff.addTriangle( + {fpts[0], fnorm, texcoord[0]}, + {fpts[1], fnorm, texcoord[1]}, + {fpts[2], fnorm, texcoord[2]}); +} + +void VisualizationScene + ::DrawQuad(gl3::GlDrawable& buff, + const double (&pts)[4][3], const double (&cv)[4], + const double minv, const double maxv) +{ + double nor[3]; + if (Compute3DUnitNormal(pts[0], pts[1], pts[2], nor)) + { + return; + } + + std::array texcoord[4]; + std::array fpts[4]; + std::array fnorm = {(float) nor[0], (float) nor[1], (float) nor[2]}; + + for (int i = 0; i < 4; i++) + { + float pal_coord = palette.GetColorCoord(cv[i], minv, maxv); + texcoord[i] = { pal_coord, 1.0 }; + fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; + } + buff.addQuad( + {fpts[0], fnorm, texcoord[0]}, + {fpts[1], fnorm, texcoord[1]}, + {fpts[2], fnorm, texcoord[2]}, + {fpts[3], fnorm, texcoord[3]}); +} + +void VisualizationScene + ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, + DenseMatrix &normals, + const int n, const Array &ind, const double minv, + const double maxv, const int normals_opt) +{ + gl3::GlBuilder poly = drawable.createBuilder(); + double na[3]; + + if (normals_opt == 1 || normals_opt == -2) + { + normals.SetSize(3, pts.Width()); + normals = 0.; + for (int i = 0; i < ind.Size(); i += n) + { + int j; + if (n == 3) + j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), + &pts(0, ind[i+2]), na); + else + j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), + &pts(0, ind[i+2]), &pts(0, ind[i+3]), na); + if (j == 0) + for ( ; j < n; j++) + for (int k = 0; k < 3; k++) + { + normals(k, ind[i+j]) += na[k]; + } + } + } + + if (normals_opt != 0 && normals_opt != -1) + { + std::vector vertices; + std::vector indices; + vertices.reserve(pts.Size()); + indices.reserve(ind.Size()); + for (int i = 0; i < pts.Width(); i++) + { + vertices.emplace_back( + gl3::VertexNormTex + { + {(float) pts(0, i), (float) pts(1, i), (float) pts(2, i)}, + {(float) normals(0, i), (float) normals(1, i), (float) normals(2, i)}, + {(float) palette.GetColorCoord(vals(i), minv, maxv), 1.0 } + }); + } + if (normals_opt > 0) + { + for (int i = 0; i < ind.Size(); i++) + { + indices.emplace_back(ind[i]); + } + } + else + { + for (int i = ind.Size()-1; i >= 0; i--) + { + indices.emplace_back(ind[i]); + } + } + if (n == 3) + { + drawable.addTriangleIndexed(vertices, indices); + } + else + { + drawable.addQuadIndexed(vertices, indices); + } + } + else + { + if (n == 3) + { + poly.glBegin(GL_TRIANGLES); + } + else + { + poly.glBegin(GL_QUADS); + } + for (int i = 0; i < ind.Size(); i += n) + { + int j; + if (n == 3) + j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), + &pts(0, ind[i+2]), na); + else + j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), + &pts(0, ind[i+2]), &pts(0, ind[i+3]), na); + if (j == 0) + { + if (normals_opt == 0) + { + poly.glNormal3dv(na); + for ( ; j < n; j++) + { + MySetColor(poly, vals(ind[i+j]), minv, maxv); + poly.glVertex3dv(&pts(0, ind[i+j])); + } + } + else + { + poly.glNormal3d(-na[0], -na[1], -na[2]); + for (j = n-1; j >= 0; j--) + { + MySetColor(poly, vals(ind[i+j]), minv, maxv); + poly.glVertex3dv(&pts(0, ind[i+j])); + } + } + } + } + poly.glEnd(); + } +} + + + gl3::RenderParams VisualizationScene::GetMeshDrawParams() { gl3::RenderParams params = {}; diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index b1a5a3b4..71c67a49 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -18,6 +18,7 @@ #include "gl/types.hpp" #include "material.hpp" #include "palettes.hpp" +#include "mfem.hpp" #include "geom_utils.hpp" // Visualization header file @@ -105,6 +106,33 @@ class VisualizationScene } } + void MySetColor (gl3::GlBuilder& builder, double val, double min, double max) + { + MySetColor(builder, palette.GetColorCoord(val, min, max)); + } + + void MySetColor (gl3::GlBuilder& builder, double val) + { + if (val < 0.0) { val = 0.0; } + if (val > 1.0) { val = 1.0; } + + builder.glTexCoord2f(val, 1.0); + } + + // We only need 3 points, but the array is 4x3 + void DrawTriangle(gl3::GlDrawable& buff, + const double (&pts)[4][3], const double (&cv)[4], + const double minv, const double maxv); + + void DrawQuad(gl3::GlDrawable& buff, + const double (&pts)[4][3], const double (&cv)[4], + const double minv, const double maxv); + + void DrawPatch(gl3::GlDrawable& buff, const mfem::DenseMatrix &pts, + mfem::Vector &vals, mfem::DenseMatrix &normals, + const int n, const mfem::Array &ind, const double minv, + const double maxv, const int normals_opt = 0); + public: VisualizationScene(); virtual ~VisualizationScene(); diff --git a/lib/palettes.cpp b/lib/palettes.cpp index e2a8f9c4..de3282a5 100644 --- a/lib/palettes.cpp +++ b/lib/palettes.cpp @@ -7756,6 +7756,30 @@ void PaletteState::Init() } } + + +double PaletteState::GetColorCoord(double val, double min, double max) +{ + // static double eps = 1e-24; + static const double eps = 0.0; + if (use_logscale) + { + if (val < min) + { + val = min; + } + if (val > max) + { + val = max; + } + return log(fabs(val/(min+eps))) / (log(fabs(max/(min+eps)))+eps); + } + else + { + return ((val-min)/(max-min)); + } +} + const double * PaletteState::GetData() const { return RGB_Palettes[curr_palette]; diff --git a/lib/palettes.hpp b/lib/palettes.hpp index 547a05e2..b8742aba 100644 --- a/lib/palettes.hpp +++ b/lib/palettes.hpp @@ -46,6 +46,10 @@ class PaletteState int GetRepeatTimes() const { return RepeatPaletteTimes; } void SetRepeatTimes(int rpt) { RepeatPaletteTimes = rpt; } + void SetUseLogscale(bool logscale) { use_logscale = logscale; } + bool GetUseLogscale() { return use_logscale; } + double GetColorCoord(double val, double min, double max); + GLuint GetColorTexture() const { return palette_tex[curr_palette][use_smooth]; } GLuint GetAlphaTexture() const { return alpha_tex; } @@ -63,6 +67,8 @@ class PaletteState int RepeatPaletteTimes = 1; int PaletteNumColors = 0; + bool use_logscale = false; + bool first_init; int MaxTextureSize; GLenum alpha_channel; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index e5a3cbf5..71776311 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -796,7 +796,7 @@ void VisualizationSceneScalarData::ToggleLogscale(bool print) if (logscale || LogscaleRange()) { logscale = !logscale; - MySetColorLogscale = logscale; + palette.SetUseLogscale(logscale); SetLogA(); SetLevelLines(minv, maxv, nl); UpdateLevelLines(); @@ -1080,7 +1080,6 @@ void VisualizationSceneScalarData::Init() minv = 0.0; maxv = 1.0; logscale = false; - MySetColorLogscale = 0; SetLogA(); PrepareCaption(); // turn on or off the caption diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index bc84968d..02fd6812 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -990,9 +990,9 @@ void VisualizationSceneSolution::ToggleLogscale(bool print) { if (logscale || LogscaleRange()) { - // we do not change 'MySetColorLogscale' here. It is set to 0 in + // we do not change the palette logscale setting here. It is set to 0 in // Prepare() since we apply logarithmic scaling to the values. - // In PrepareVectorField() we set 'MySetColorLogscale' to 'logscale'. + // In PrepareVectorField() we call 'palette.SetUseLogscale(logscale)'. logscale = !logscale; SetLogA(); SetLevelLines(minv, maxv, nl); @@ -1038,58 +1038,6 @@ void DrawNumberedMarker(gl3::GlDrawable& buff, const double x[3], double dx, buff.addText(x[0], x[1], x[2], std::to_string(n)); } -void DrawTriangle(gl3::GlDrawable& buff, - const double (&pts)[4][3], const double (&cv)[4], - const double minv, const double maxv) -{ - double nor[3]; - if (Compute3DUnitNormal(pts[0], pts[1], pts[2], nor)) - { - return; - } - - std::array texcoord[3]; - std::array fpts[3]; - std::array fnorm = {(float) nor[0], (float) nor[1], (float) nor[2]}; - - for (int i = 0; i < 3; i++) - { - - texcoord[i] = { static_cast(GetColorCoord(cv[i], minv, maxv)), 1.0 }; - fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; - } - buff.addTriangle( - {fpts[0], fnorm, texcoord[0]}, - {fpts[1], fnorm, texcoord[1]}, - {fpts[2], fnorm, texcoord[2]}); -} - -void DrawQuad(gl3::GlDrawable& buff, - const double (&pts)[4][3], const double (&cv)[4], - const double minv, const double maxv) -{ - double nor[3]; - if (Compute3DUnitNormal(pts[0], pts[1], pts[2], nor)) - { - return; - } - - std::array texcoord[4]; - std::array fpts[4]; - std::array fnorm = {(float) nor[0], (float) nor[1], (float) nor[2]}; - - for (int i = 0; i < 4; i++) - { - texcoord[i] = { static_cast(GetColorCoord(cv[i], minv, maxv)), 1.0 }; - fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; - } - buff.addQuad( - {fpts[0], fnorm, texcoord[0]}, - {fpts[1], fnorm, texcoord[1]}, - {fpts[2], fnorm, texcoord[2]}, - {fpts[3], fnorm, texcoord[3]}); -} - void RemoveFPErrors(const DenseMatrix &pts, Vector &vals, DenseMatrix &normals, const int n, const Array &ind, Array &f_ind) { @@ -1119,122 +1067,6 @@ void RemoveFPErrors(const DenseMatrix &pts, Vector &vals, DenseMatrix &normals, f_ind.SetSize(o); } -void DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, - DenseMatrix &normals, - const int n, const Array &ind, const double minv, - const double maxv, const int normals_opt) -{ - gl3::GlBuilder poly = drawable.createBuilder(); - double na[3]; - - if (normals_opt == 1 || normals_opt == -2) - { - normals.SetSize(3, pts.Width()); - normals = 0.; - for (int i = 0; i < ind.Size(); i += n) - { - int j; - if (n == 3) - j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), - &pts(0, ind[i+2]), na); - else - j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), - &pts(0, ind[i+2]), &pts(0, ind[i+3]), na); - if (j == 0) - for ( ; j < n; j++) - for (int k = 0; k < 3; k++) - { - normals(k, ind[i+j]) += na[k]; - } - } - } - - if (normals_opt != 0 && normals_opt != -1) - { - std::vector vertices; - std::vector indices; - vertices.reserve(pts.Size()); - indices.reserve(ind.Size()); - for (int i = 0; i < pts.Width(); i++) - { - vertices.emplace_back( - gl3::VertexNormTex - { - {(float) pts(0, i), (float) pts(1, i), (float) pts(2, i)}, - {(float) normals(0, i), (float) normals(1, i), (float) normals(2, i)}, - {(float) GetColorCoord(vals(i), minv, maxv), 1.0 } - }); - } - if (normals_opt > 0) - { - for (int i = 0; i < ind.Size(); i++) - { - indices.emplace_back(ind[i]); - } - } - else - { - for (int i = ind.Size()-1; i >= 0; i--) - { - indices.emplace_back(ind[i]); - } - } - if (n == 3) - { - drawable.addTriangleIndexed(vertices, indices); - } - else - { - drawable.addQuadIndexed(vertices, indices); - } - } - else - { - if (n == 3) - { - poly.glBegin(GL_TRIANGLES); - } - else - { - poly.glBegin(GL_QUADS); - } - for (int i = 0; i < ind.Size(); i += n) - { - int j; - if (n == 3) - j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), - &pts(0, ind[i+2]), na); - else - j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), - &pts(0, ind[i+2]), &pts(0, ind[i+3]), na); - if (j == 0) - { - if (normals_opt == 0) - { - poly.glNormal3dv(na); - for ( ; j < n; j++) - { - MySetColor(poly, vals(ind[i+j]), minv, maxv); - poly.glVertex3dv(&pts(0, ind[i+j])); - } - } - else - { - poly.glNormal3d(-na[0], -na[1], -na[2]); - for (j = n-1; j >= 0; j--) - { - MySetColor(poly, vals(ind[i+j]), minv, maxv); - poly.glVertex3dv(&pts(0, ind[i+j])); - } - } - } - } - poly.glEnd(); - } -} - - - void VisualizationSceneSolution::PrepareWithNormals() { disp_buf.clear(); @@ -1425,7 +1257,7 @@ void VisualizationSceneSolution::PrepareFlat2() void VisualizationSceneSolution::Prepare() { - MySetColorLogscale = 0; + palette.SetUseLogscale(0); switch (shading) { diff --git a/lib/vssolution.hpp b/lib/vssolution.hpp index d52458cf..a49e83e8 100644 --- a/lib/vssolution.hpp +++ b/lib/vssolution.hpp @@ -165,18 +165,4 @@ class VisualizationSceneSolution : public VisualizationSceneScalarData void DrawNumberedMarker(gl3::GlDrawable& buff, const double x[3], double dx, int n); -// We only need 3 points, but the array is 4x3 -void DrawTriangle(gl3::GlDrawable& buff, - const double (&pts)[4][3], const double (&cv)[4], - const double minv, const double maxv); - -void DrawQuad(gl3::GlDrawable& buff, - const double (&pts)[4][3], const double (&cv)[4], - const double minv, const double maxv); - -void DrawPatch(gl3::GlDrawable& buff, const DenseMatrix &pts, Vector &vals, - DenseMatrix &normals, - const int n, const Array &ind, const double minv, - const double maxv, const int normals_opt = 0); - #endif diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 606d9be8..ad3cb85d 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1010,7 +1010,7 @@ void VisualizationSceneSolution3d::EventUpdateColors() void VisualizationSceneSolution3d::UpdateValueRange(bool prepare) { logscale = logscale && LogscaleRange(); - MySetColorLogscale = logscale; + palette.SetUseLogscale(logscale); SetLogA(); SetLevelLines(minv, maxv, nl); if (prepare) diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 8fada363..a5851b57 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -895,7 +895,7 @@ void VisualizationSceneVector::PrepareVectorField() { int i; - MySetColorLogscale = logscale; + palette.SetUseLogscale(logscale); if (drawvector == 3) { new_maxlen = 0.0; From 303f4a173088d11fad1be341a8eefdd94957f268 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 15:45:45 -0800 Subject: [PATCH 14/42] Fix a segfault with font ptr in VisualizationScene --- glvis.cpp | 2 -- lib/aux_vis.cpp | 2 +- lib/openglvis.cpp | 1 + lib/openglvis.hpp | 2 -- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 7fc9b136..38d9c171 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -186,8 +186,6 @@ bool GLVisInitVis(int field_type) { VisualizationSceneSolution3d *vss; vs = vss = new VisualizationSceneSolution3d(*mesh, sol); - // HACK: below needs to be called before ToggleAxes - vs->SetFont(mainWindow->getFont()); if (grid_f) { vss->SetGridFunction(grid_f); diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index b5ec1d50..e4213dc3 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -353,7 +353,7 @@ void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, const char *keys) { ::locscene = locscene = scene; - locscene->SetFont(&font); + //locscene->SetFont(&font); locscene -> view = view; if (view == 2) { diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index bedcefb9..09210ada 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -128,6 +128,7 @@ VisualizationScene::VisualizationScene() use_light = true; palette.Init(); + font = GetGLVisWindow()->getFont(); } VisualizationScene::~VisualizationScene() {} diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index 71c67a49..8e86f568 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -190,8 +190,6 @@ class VisualizationScene } } - void SetFont(GlVisFont* fnt) { this->font = fnt; }; - PaletteState& GetPalette() { return palette; } void GenerateAlphaTexture() { palette.GenerateAlphaTexture(matAlpha, matAlphaCenter); } From ae0c01caa7e0e56c97b29a23e5b8e9289ff3293d Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 16:15:06 -0800 Subject: [PATCH 15/42] Remove GetUseTexture/SetUseTexture functions, move into aux_js --- lib/aux_js.cpp | 58 +++++++++++++++++++++++++++++++++++++++---------- lib/aux_vis.cpp | 17 --------------- lib/aux_vis.hpp | 8 +++---- lib/threads.cpp | 8 ------- 4 files changed, 50 insertions(+), 41 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 6008809e..0ad48b5e 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -21,6 +21,7 @@ std::string extra_caption; // used in extern context mfem::GeometryRefiner GLVisGeometryRefiner; // used in extern context static VisualizationSceneScalarData * vs = nullptr; +GLVisWindow * mainWindow = nullptr; namespace js { @@ -80,8 +81,20 @@ bool startVisualization(const std::string input, const std::string data_type, return false; } - if (InitVisualization("glvis", 0, 0, w, h)) + try { + mainWindow = new GLVisWindow("glvis", 0, 0, w, h, false); + } + catch (std::runtime_error& ex) + { + cerr << "Initializing the visualization failed: " << endl + << ex.what() << endl; + return false; + } + catch(...) + { + cerr << "Initializing the visualization failed - unknown error." + << endl; return false; } @@ -118,7 +131,7 @@ bool startVisualization(const std::string input, const std::string data_type, vs->Zoom(1.8); // Use the 'bone' palette when visualizing a 2D mesh only (otherwise // the 'jet-like' palette is used in 2D, see vssolution.cpp). - paletteSet(4); + vs->GetPalette().SetPalette(4); } } else if (stream_state.mesh->SpaceDimension() == 3) @@ -136,14 +149,14 @@ bool startVisualization(const std::string input, const std::string data_type, { // Use the 'white' palette when visualizing a 3D volume mesh only // paletteSet(4); - paletteSet(11); + vss->GetPalette().SetPalette(11); vss->SetLightMatIdx(4); } else { // Use the 'bone' palette when visualizing a surface mesh only // (the same as when visualizing a 2D mesh only) - paletteSet(4); + vss->GetPalette().SetPalette(4); } // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp @@ -207,17 +220,17 @@ bool startVisualization(const std::string input, const std::string data_type, } if (stream_state.mesh->SpaceDimension() == 2 && field_type == 2) { - SetVisualizationScene(vs, 2); + mainWindow->SetVisualizationScene(vs, 2); } else { - SetVisualizationScene(vs, 3); + mainWindow->SetVisualizationScene(vs, 3); } } - CallKeySequence(stream_state.keys.c_str()); + mainWindow->CallKeySequence(stream_state.keys.c_str()); - SendExposeEvent(); + mainWindow->SendExposeEvent(); return true; } @@ -347,6 +360,29 @@ std::string getHelpString() = dynamic_cast(GetVisualizationScene()); return vss->GetHelpString(); } + +void ResizeWindow(int w, int h) +{ + mainWindow->ResizeWindow(w, h); +} + +int GetUseTexture() +{ + return vs->GetPalette().GetSmoothSetting(); +} + +void SetUseTexture(int ut) +{ + if (ut == 0) + { + vs->GetPalette().UseDiscrete(); + } + else + { + vs->GetPalette().UseSmooth(); + } +} + } // namespace js namespace em = emscripten; @@ -360,9 +396,9 @@ EMSCRIPTEN_BINDINGS(js_funcs) em::function("enableKeyHandling", &js::enableKeyHandling); em::function("setKeyboardListeningElementId", js::setKeyboardListeningElementId); - em::function("getTextureMode", &GetUseTexture); - em::function("setTextureMode", &SetUseTexture); - em::function("resizeWindow", &ResizeWindow); + em::function("getTextureMode", &js::GetUseTexture); + em::function("setTextureMode", &js::SetUseTexture); + em::function("resizeWindow", &js::ResizeWindow); em::function("setCanvasId", &js::setCanvasId); em::function("setupResizeEventCallback", &js::setupResizeEventCallback); em::function("getHelpString", &js::getHelpString); diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index e4213dc3..75be3adb 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -1274,23 +1274,6 @@ void GetColorFromVal(double val, float * rgba) rgba[3] = 1.f; } -int GetUseTexture() -{ - return locscene->GetPalette().GetSmoothSetting(); -} - -void SetUseTexture(int ut) -{ - if (ut == 0) - { - locscene->GetPalette().UseDiscrete(); - } - else - { - locscene->GetPalette().UseSmooth(); - } -} - int GetMultisample() { return glvis_multisample; diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 18b95ef9..93f3e7dc 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -12,7 +12,7 @@ #ifndef GLVIS_AUX_VIS_HPP #define GLVIS_AUX_VIS_HPP -#include "mfem/mfem.hpp" +#include "mfem.hpp" #include "gl/platform_gl.hpp" #include "gl/types.hpp" @@ -115,10 +115,11 @@ class GLVisWindow std::unique_ptr wnd; VisualizationScene* locscene; + // Idle function callbacks mfem::Array idle_funcs{}; int last_idle_func = 0; - int visualize; + int visualize = 0; bool disableSendExposeEvent = false; @@ -163,9 +164,6 @@ void CallKeySequence(const char *seq); void GetColorFromVal(double val, float * rgba); -void SetUseTexture(int ut); -int GetUseTexture(); -void Set_Texture_Image(); int GetMultisample(); void SetMultisample(int m); diff --git a/lib/threads.cpp b/lib/threads.cpp index 544078f5..12571255 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -679,10 +679,6 @@ int GLVisCommand::Execute() { cout << "Command: palette: " << palette << endl; (*vs)->GetPalette().SetPalette(palette-1); - if (!GetUseTexture()) - { - (*vs)->EventUpdateColors(); - } MyExpose(); break; } @@ -693,10 +689,6 @@ int GLVisCommand::Execute() (*vs)->GetPalette().SetRepeatTimes(palette_repeat); (*vs)->GetPalette().Init(); - if (!GetUseTexture()) - { - (*vs)->EventUpdateColors(); - } MyExpose(); break; } From 159252d5240ddec77362d9831507ca271426579f Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 28 Jan 2021 16:36:19 -0800 Subject: [PATCH 16/42] Move thread control functions into GLVisWindow --- glvis.cpp | 1 - lib/aux_vis.cpp | 27 +++++++++++++++++---------- lib/aux_vis.hpp | 15 +++++++++------ lib/threads.cpp | 12 ++++++------ 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 38d9c171..65a2bff4 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -144,7 +144,6 @@ bool GLVisInitVis(int field_type) if (input_streams.Size() > 0) { - mainWindow->getSdl()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); glvis_command = new GLVisCommand(&vs, &mesh, &grid_f, &sol, &keep_attr, &fix_elem_orient); comm_thread = new communication_thread(input_streams); diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 75be3adb..36a6f4d0 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -216,6 +216,8 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega SetKeyEventHandler (SDLK_RIGHTBRACKET, &GLVisWindow::ScaleUp); SetKeyEventHandler (SDLK_AT, &GLVisWindow::LookAt); + SetKeyEventHandler (SDLK_SPACE, &GLVisWindow::ThreadsPauseFunc); + #ifndef __EMSCRIPTEN__ SetKeyEventHandler(SDLK_LEFTPAREN, &GLVisWindow::ShrinkWindow); SetKeyEventHandler(SDLK_RIGHTPAREN, &GLVisWindow::EnlargeWindow); @@ -929,7 +931,7 @@ void GLVisWindow::Quit() visualize = 0; } -void ToggleThreads() +void GLVisWindow::ToggleThreads() { static const char *state[] = { "running", "stopped" }; if (visualize > 0 && visualize < 3) @@ -939,19 +941,24 @@ void ToggleThreads() } } -void ThreadsPauseFunc(GLenum state) +void GLVisWindow::ThreadsPauseFunc(GLenum state) { - if (state & KMOD_CTRL) - { - glvis_command->ToggleAutopause(); - } - else +#ifndef __EMSCRIPTEN__ + if (glvis_command) { - ToggleThreads(); + if (state & KMOD_CTRL) + { + glvis_command->ToggleAutopause(); + } + else + { + ToggleThreads(); + } } +#endif } -void ThreadsStop() +void GLVisWindow::ThreadsStop() { if (visualize == 1) { @@ -959,7 +966,7 @@ void ThreadsStop() } } -void ThreadsRun() +void GLVisWindow::ThreadsRun() { if (visualize == 2) { diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 93f3e7dc..67ba568c 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -61,6 +61,10 @@ class GLVisWindow void AddIdleFunc(IdleFPtr func); void RemoveIdleFunc(IdleFPtr func); + void ThreadsStop(); + void ThreadsRun(); + void ToggleThreads(); + void MainLoop(); void Quit(); @@ -112,6 +116,9 @@ class GLVisWindow void KeyMinusPressed(); void KeyPlusPressed(); + // Internal event handler for toggling state of threads + void ThreadsPauseFunc(GLenum); + std::unique_ptr wnd; VisualizationScene* locscene; @@ -133,9 +140,9 @@ class GLVisWindow }; /// Send expose event. In our case MyReshape is executed and Draw after it. -void SendExposeEvent(); +[[deprecated]] void SendExposeEvent(); -void MyExpose(); +[[deprecated]] void MyExpose(); void MainLoop(GLVisWindow* wnd); @@ -143,10 +150,6 @@ void MainLoop(GLVisWindow* wnd); [[deprecated]] GLVisWindow * GetGLVisWindow(); VisualizationScene * GetVisualizationScene(); -void ToggleThreads(); -void ThreadsPauseFunc(GLenum); -void ThreadsStop(); -void ThreadsRun(); /// Take a screenshot using libtiff, libpng or sdl2 diff --git a/lib/threads.cpp b/lib/threads.cpp index 12571255..46d90fa7 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -503,7 +503,7 @@ int GLVisCommand::Execute() if (autopause) { cout << "Autopause ..." << endl; - ThreadsStop(); + GetGLVisWindow()->ThreadsStop(); } break; } @@ -570,7 +570,7 @@ int GLVisCommand::Execute() case PAUSE: { cout << "Command: pause: "; - ToggleThreads(); + GetGLVisWindow()->ToggleThreads(); break; } @@ -719,11 +719,11 @@ int GLVisCommand::Execute() cout << "Command: autopause: " << strings_off_on[autopause] << endl; if (autopause) { - ThreadsStop(); + GetGLVisWindow()->ThreadsStop(); } else { - ThreadsRun(); // probably not needed + GetGLVisWindow()->ThreadsRun(); // probably not needed } break; } @@ -768,11 +768,11 @@ void GLVisCommand::ToggleAutopause() cout << "Autopause: " << strings_off_on[autopause] << endl; if (autopause) { - ThreadsStop(); + GetGLVisWindow()->ThreadsStop(); } else { - ThreadsRun(); + GetGLVisWindow()->ThreadsRun(); } } From 019b0ab0f5b3f555a46e11053439237798ed3616 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 3 Feb 2021 14:17:45 -0800 Subject: [PATCH 17/42] Modularize stream reader methods --- glvis.cpp | 133 +++++++++++++++++++-------------------- lib/stream_reader.cpp | 143 ++++++++++++++++++------------------------ lib/stream_reader.hpp | 23 ++++--- lib/threads.cpp | 76 +++++++++++----------- lib/threads.hpp | 23 +++---- 5 files changed, 182 insertions(+), 216 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 65a2bff4..c7f94101 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -59,13 +59,13 @@ string extra_caption; // Global variables int input = 1; -Mesh *&mesh = stream_state.mesh; +std::unique_ptr& mesh = stream_state.mesh; Vector & sol = stream_state.sol; Vector & solu = stream_state.solu; Vector & solv = stream_state.solv; Vector & solw = stream_state.solw; Vector & normals = stream_state.normals; -GridFunction *& grid_f = stream_state.grid_f; +std::unique_ptr& grid_f = stream_state.grid_f; int & is_gf = stream_state.is_gf; std::string & keys = stream_state.keys; GLVisWindow * mainWindow = nullptr; @@ -99,8 +99,8 @@ void SetGridFunction(); void ReadParallel(); int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, - const char *sol_prefix, Mesh **mesh_p, - GridFunction **sol_p, int keep_attr); + const char *sol_prefix, StreamState& state, + int keep_attr); int ReadInputStreams(); @@ -144,8 +144,7 @@ bool GLVisInitVis(int field_type) if (input_streams.Size() > 0) { - glvis_command = new GLVisCommand(&vs, &mesh, &grid_f, &sol, &keep_attr, - &fix_elem_orient); + glvis_command = new GLVisCommand(&vs, stream_state, &keep_attr); comm_thread = new communication_thread(input_streams); } @@ -187,7 +186,7 @@ bool GLVisInitVis(int field_type) vs = vss = new VisualizationSceneSolution3d(*mesh, sol); if (grid_f) { - vss->SetGridFunction(grid_f); + vss->SetGridFunction(grid_f.get()); } if (field_type == 2) { @@ -236,8 +235,9 @@ bool GLVisInitVis(int field_type) { if (grid_f) { - grid_f = ProjectVectorFEGridFunction(grid_f); - vs = new VisualizationSceneVector3d(*grid_f); + GridFunction* proj_grid_f = ProjectVectorFEGridFunction(grid_f.get()); + grid_f.reset(proj_grid_f); + vs = new VisualizationSceneVector3d(*proj_grid_f); } else { @@ -282,12 +282,10 @@ void GLVisStartVis() delete glvis_command; glvis_command = NULL; } - delete grid_f; grid_f = NULL; - delete mesh; mesh = NULL; cout << "GLVis window closed." << endl; } -int ScriptReadSolution(istream &scr, Mesh **mp, GridFunction **sp) +int ScriptReadSolution(istream &scr, StreamState& state) { string mword,sword; @@ -301,14 +299,14 @@ int ScriptReadSolution(istream &scr, Mesh **mp, GridFunction **sp) cout << "Can not open mesh file: " << mword << endl; return 1; } - *mp = new Mesh(imesh, 1, 0, fix_elem_orient); + state.mesh.reset(new Mesh(imesh, 1, 0, fix_elem_orient)); // read the solution (GridFunction) scr >> ws >> sword; if (sword == mword) // mesh and solution in the same file { cout << "solution: " << mword << endl; - *sp = new GridFunction(*mp, imesh); + state.grid_f.reset(new GridFunction(state.mesh.get(), imesh)); } else { @@ -317,18 +315,18 @@ int ScriptReadSolution(istream &scr, Mesh **mp, GridFunction **sp) if (!isol) { cout << "Can not open solution file: " << sword << endl; - delete *mp; *mp = NULL; + state.mesh.release(); return 2; } - *sp = new GridFunction(*mp, isol); + state.grid_f.reset(new GridFunction(state.mesh.get(), isol)); } - Extrude1DMeshAndSolution(mp, sp, NULL); + state.Extrude1DMeshAndSolution(); return 0; } -int ScriptReadParSolution(istream &scr, Mesh **mp, GridFunction **sp) +int ScriptReadParSolution(istream &scr, StreamState& state) { int np, keep_attr, err; string mesh_prefix, sol_prefix; @@ -354,17 +352,17 @@ int ScriptReadParSolution(istream &scr, Mesh **mp, GridFunction **sp) cout << "solution prefix: " << sol_prefix << endl; err = ReadParMeshAndGridFunction(np, mesh_prefix.c_str(), - sol_prefix.c_str(), mp, sp, keep_attr); + sol_prefix.c_str(), state, keep_attr); if (!err) { - Extrude1DMeshAndSolution(mp, sp, NULL); + state.Extrude1DMeshAndSolution(); } return err; } -int ScriptReadDisplMesh(istream &scr, Mesh **mp, GridFunction **sp) +int ScriptReadDisplMesh(istream &scr, StreamState& state) { - Mesh *m; + StreamState meshstate; string word; cout << "Script: mesh: " << flush; @@ -377,22 +375,21 @@ int ScriptReadDisplMesh(istream &scr, Mesh **mp, GridFunction **sp) return 1; } cout << word << endl; - m = new Mesh(imesh, 1, 0, fix_elem_orient); + meshstate.mesh.reset(new Mesh(imesh, 1, 0, fix_elem_orient)); } - Extrude1DMeshAndSolution(&m, NULL, NULL); + meshstate.Extrude1DMeshAndSolution(); + Mesh* const m = meshstate.mesh.get(); if (init_nodes == NULL) { init_nodes = new Vector; - m->GetNodes(*init_nodes); - delete m; - *mp = NULL; - *sp = NULL; + meshstate.mesh->GetNodes(*init_nodes); + state.mesh = NULL; + state.grid_f = NULL; } else { FiniteElementCollection *vfec = NULL; FiniteElementSpace *vfes; - GridFunction *g; vfes = (FiniteElementSpace *)m->GetNodalFESpace(); if (vfes == NULL) { @@ -400,7 +397,8 @@ int ScriptReadDisplMesh(istream &scr, Mesh **mp, GridFunction **sp) vfes = new FiniteElementSpace(m, vfec, m->SpaceDimension()); } - g = new GridFunction(vfes); + meshstate.grid_f.reset(new GridFunction(vfes)); + GridFunction * const g = meshstate.grid_f.get(); if (vfec) { g->MakeOwner(vfec); @@ -415,8 +413,9 @@ int ScriptReadDisplMesh(istream &scr, Mesh **mp, GridFunction **sp) cout << "Script: incompatible meshes!" << endl; *g = 0.0; } - *mp = m; - *sp = g; + + state.mesh = std::move(meshstate.mesh); + state.grid_f = std::move(meshstate.grid_f); } return 0; @@ -467,7 +466,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) if (word == "solution") { - if (ScriptReadSolution(scr, &new_m, &new_g)) + if (ScriptReadSolution(scr, stream_state)) { done_one_command = 1; continue; @@ -475,7 +474,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } else if (word == "mesh") { - if (ScriptReadDisplMesh(scr, &new_m, &new_g)) + if (ScriptReadDisplMesh(scr, stream_state)) { done_one_command = 1; continue; @@ -489,7 +488,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } else if (word == "psolution") { - if (ScriptReadParSolution(scr, &new_m, &new_g)) + if (ScriptReadParSolution(scr, stream_state)) { done_one_command = 1; continue; @@ -532,8 +531,8 @@ void ExecuteScriptCommand(GLVisWindow* wnd) vss->NewMeshAndSolution(new_m, new_g); } } - delete grid_f; grid_f = new_g; - delete mesh; mesh = new_m; + stream_state.grid_f.reset(new_g); + stream_state.mesh.reset(new_m); MyExpose(); } @@ -866,7 +865,7 @@ void PlayScript(istream &scr) } else if (word == "solution") { - if (ScriptReadSolution(scr, &mesh, &grid_f)) + if (ScriptReadSolution(scr, stream_state)) { return; } @@ -876,7 +875,7 @@ void PlayScript(istream &scr) } else if (word == "psolution") { - if (ScriptReadParSolution(scr, &mesh, &grid_f)) + if (ScriptReadParSolution(scr, stream_state)) { return; } @@ -886,7 +885,7 @@ void PlayScript(istream &scr) } else if (word == "mesh") { - if (ScriptReadDisplMesh(scr, &mesh, &grid_f)) + if (ScriptReadDisplMesh(scr, stream_state)) { return; } @@ -1079,7 +1078,7 @@ int main (int argc, char *argv[]) return 1; } ifs >> data_type >> ws; - int ft = ReadStream(ifs, data_type); + int ft = stream_state.ReadStream(ifs, data_type); input_streams.Append(&ifs); if (GLVisInitVis(ft)) { @@ -1299,8 +1298,6 @@ int main (int argc, char *argv[]) ofs << "solution\n"; mesh->Print(ofs); grid_f->Save(ofs); - delete grid_f; grid_f = NULL; - delete mesh; mesh = NULL; } ofs.close(); cout << "Data saved in " << tmp_file << endl; @@ -1336,7 +1333,7 @@ int main (int argc, char *argv[]) int ft; if (!par_data) { - ft = ReadStream(*isock, data_type); + ft = stream_state.ReadStream(*isock, data_type); input_streams.Append(isock); } else @@ -1426,7 +1423,7 @@ void ReadSerial() exit(1); } - mesh = new Mesh(meshin, 1, 0, fix_elem_orient); + stream_state.mesh.reset(new Mesh(meshin, 1, 0, fix_elem_orient)); if (is_gf || (input & 4) || (input & 8)) { @@ -1450,7 +1447,7 @@ void ReadSerial() if (is_gf) { - grid_f = new GridFunction(mesh, *solin); + stream_state.grid_f.reset(new GridFunction(mesh.get(), *solin)); SetGridFunction(); } else if (input & 4) @@ -1476,10 +1473,10 @@ void ReadSerial() } else { - SetMeshSolution(mesh, grid_f, save_coloring); + stream_state.SetMeshSolution(save_coloring); } - Extrude1DMeshAndSolution(&mesh, &grid_f, &sol); + stream_state.Extrude1DMeshAndSolution(); } @@ -1495,15 +1492,14 @@ void SetGridFunction() FiniteElementSpace *ofes = grid_f->FESpace(); FiniteElementCollection *fec = FiniteElementCollection::New(ofes->FEColl()->Name()); - FiniteElementSpace *fes = new FiniteElementSpace(mesh, fec); + FiniteElementSpace *fes = new FiniteElementSpace(mesh.get(), fec); GridFunction *new_gf = new GridFunction(fes); new_gf->MakeOwner(fec); for (int i = 0; i < new_gf->Size(); i++) { (*new_gf)(i) = (*grid_f)(ofes->DofToVDof(i, gf_component)); } - delete grid_f; - grid_f = new_gf; + stream_state.grid_f.reset(new_gf); } if (grid_f->VectorDim() == 1) { @@ -1524,7 +1520,7 @@ void ReadParallel() if (is_gf) { err = ReadParMeshAndGridFunction(np, mesh_file, sol_file, - &mesh, &grid_f, keep_attr); + stream_state, keep_attr); if (!err) { SetGridFunction(); @@ -1533,10 +1529,10 @@ void ReadParallel() else { err = ReadParMeshAndGridFunction(np, mesh_file, NULL, - &mesh, NULL, keep_attr); + stream_state, keep_attr); if (!err) { - SetMeshSolution(mesh, grid_f, save_coloring); + stream_state.SetMeshSolution(save_coloring); } } @@ -1545,21 +1541,21 @@ void ReadParallel() exit(1); } - Extrude1DMeshAndSolution(&mesh, &grid_f, &sol); + stream_state.Extrude1DMeshAndSolution(); } int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, - const char *sol_prefix, Mesh **mesh_p, - GridFunction **sol_p, int keep_attr) + const char *sol_prefix, + StreamState& state, int keep_attr) { - *mesh_p = NULL; + state.mesh = NULL; // are the solutions bundled together with the mesh files? bool same_file = false; - if (sol_prefix && sol_p) + if (sol_prefix) { same_file = !strcmp(sol_prefix, mesh_prefix); - *sol_p = NULL; + state.grid_f = NULL; } Array mesh_array(np); @@ -1596,7 +1592,7 @@ int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, } // read the solution - if (sol_prefix && sol_p) + if (sol_prefix) { if (!same_file) { @@ -1623,10 +1619,10 @@ int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, if (!err) { // create the combined mesh and gf - *mesh_p = new Mesh(mesh_array, np); - if (sol_prefix && sol_p) + state.mesh.reset(new Mesh(mesh_array, np)); + if (sol_prefix) { - *sol_p = new GridFunction(*mesh_p, gf_array, np); + state.grid_f.reset(new GridFunction(state.mesh.get(), gf_array, np)); } } @@ -1689,15 +1685,15 @@ int ReadInputStreams() mfem_error("Input streams contain a mixture of data types!"); } - mesh = new Mesh(mesh_array, nproc); + stream_state.mesh.reset(new Mesh(mesh_array, nproc)); if (gf_count == 0) { - SetMeshSolution(mesh, grid_f, save_coloring); + stream_state.SetMeshSolution(save_coloring); field_type = 2; } else { - grid_f = new GridFunction(mesh, gf_array, nproc); + stream_state.grid_f.reset(new GridFunction(mesh.get(), gf_array, nproc)); field_type = (grid_f->VectorDim() == 1) ? 0 : 1; } @@ -1707,7 +1703,7 @@ int ReadInputStreams() delete gf_array[nproc-1-p]; } - Extrude1DMeshAndSolution(&mesh, &grid_f, NULL); + stream_state.Extrude1DMeshAndSolution(); return field_type; } @@ -1743,7 +1739,6 @@ GridFunction *ProjectVectorFEGridFunction(GridFunction *gf) GridFunction *d_gf = new GridFunction(d_fespace); d_gf->MakeOwner(d_fec); gf->ProjectVectorFieldOn(*d_gf); - delete gf; return d_gf; } return gf; diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index f94db7a5..dac18673 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -16,11 +16,8 @@ using namespace mfem; StreamState stream_state; -void Extrude1DMeshAndSolution(Mesh **mesh_p, GridFunction **grid_f_p, - Vector *sol) +void StreamState::Extrude1DMeshAndSolution() { - Mesh *mesh = *mesh_p; - if (mesh->Dimension() != 1 || mesh->SpaceDimension() != 1) { return; @@ -42,35 +39,31 @@ void Extrude1DMeshAndSolution(Mesh **mesh_p, GridFunction **grid_f_p, } } - Mesh *mesh2d = Extrude1D(mesh, 1, 0.1*(xmax - xmin)); + Mesh *mesh2d = Extrude1D(mesh.get(), 1, 0.1*(xmax - xmin)); - if (grid_f_p && *grid_f_p) + if (grid_f) { GridFunction *grid_f_2d = - Extrude1DGridFunction(mesh, mesh2d, *grid_f_p, 1); + Extrude1DGridFunction(mesh.get(), mesh2d, grid_f.get(), 1); - delete *grid_f_p; - *grid_f_p = grid_f_2d; + grid_f.reset(grid_f_2d); } - if (sol && sol->Size() == mesh->GetNV()) + else if (sol.Size() == mesh->GetNV()) { Vector sol2d(mesh2d->GetNV()); for (int i = 0; i < mesh->GetNV(); i++) { - sol2d(2*i+0) = sol2d(2*i+1) = (*sol)(i); + sol2d(2*i+0) = sol2d(2*i+1) = sol(i); } - *sol = sol2d; + sol = sol2d; } - delete mesh; - *mesh_p = mesh2d; + mesh.reset(mesh2d); } -void SetMeshSolution(Mesh *mesh, GridFunction *&grid_f, bool save_coloring) +void StreamState::SetMeshSolution(bool save_coloring) { - auto & state = stream_state; - if (1) // checkerboard solution { FiniteElementCollection *cfec; @@ -86,8 +79,8 @@ void SetMeshSolution(Mesh *mesh, GridFunction *&grid_f, bool save_coloring) { cfec = new Const3DFECollection; } - FiniteElementSpace *cfes = new FiniteElementSpace(mesh, cfec); - grid_f = new GridFunction(cfes); + FiniteElementSpace *cfes = new FiniteElementSpace(mesh.get(), cfec); + grid_f.reset(new GridFunction(cfes)); grid_f->MakeOwner(cfec); { Array coloring; @@ -103,8 +96,8 @@ void SetMeshSolution(Mesh *mesh, GridFunction *&grid_f, bool save_coloring) } cout << "Number of colors: " << grid_f->Max() + 1 << endl; } - grid_f->GetNodalValues(state.sol); - state.is_gf = 1; + grid_f->GetNodalValues(sol); + is_gf = 1; if (save_coloring) { const char col_fname[] = "GLVis_coloring.gf"; @@ -116,104 +109,99 @@ void SetMeshSolution(Mesh *mesh, GridFunction *&grid_f, bool save_coloring) } else // zero solution { - state.sol.SetSize (mesh -> GetNV()); - state.sol = 0.0; + sol.SetSize (mesh -> GetNV()); + sol = 0.0; } } // Read the content of an input stream (e.g. from socket/file) -int ReadStream(istream &is, const string &data_type) +int StreamState::ReadStream(istream &is, const string &data_type) { - auto & state = stream_state; - // 0 - scalar data, 1 - vector data, 2 - mesh only, (-1) - unknown int field_type = 0; - - delete state.mesh; state.mesh = NULL; - delete state.grid_f; state.grid_f = NULL; - state.keys.clear(); + keys.clear(); if (data_type == "fem2d_data") { - state.mesh = new Mesh(is, 0, 0, state.fix_elem_orient); - state.sol.Load(is, state.mesh->GetNV()); + mesh.reset(new Mesh(is, 0, 0, fix_elem_orient)); + sol.Load(is, mesh->GetNV()); } else if (data_type == "vfem2d_data" || data_type == "vfem2d_data_keys") { field_type = 1; - state.mesh = new Mesh(is, 0, 0, state.fix_elem_orient); - state.solu.Load(is, state.mesh->GetNV()); - state.solv.Load(is, state.mesh->GetNV()); + mesh.reset(new Mesh(is, 0, 0, fix_elem_orient)); + solu.Load(is, mesh->GetNV()); + solv.Load(is, mesh->GetNV()); if (data_type == "vfem2d_data_keys") { - is >> state.keys; + is >> keys; } } else if (data_type == "fem3d_data") { - state.mesh = new Mesh(is, 0, 0, state.fix_elem_orient); - state.sol.Load(is, state.mesh->GetNV()); + mesh.reset(new Mesh(is, 0, 0, fix_elem_orient)); + sol.Load(is, mesh->GetNV()); } else if (data_type == "vfem3d_data" || data_type == "vfem3d_data_keys") { field_type = 1; - state.mesh = new Mesh(is, 0, 0, state.fix_elem_orient); - state.solu.Load(is, state.mesh->GetNV()); - state.solv.Load(is, state.mesh->GetNV()); - state.solw.Load(is, state.mesh->GetNV()); + mesh.reset(new Mesh(is, 0, 0, fix_elem_orient)); + solu.Load(is, mesh->GetNV()); + solv.Load(is, mesh->GetNV()); + solw.Load(is, mesh->GetNV()); if (data_type == "vfem3d_data_keys") { - is >> state.keys; + is >> keys; } } else if (data_type == "fem2d_gf_data" || data_type == "fem2d_gf_data_keys") { - state.mesh = new Mesh(is, 1, 0, state.fix_elem_orient); - state.grid_f = new GridFunction(state.mesh, is); + mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); + grid_f.reset(new GridFunction(mesh.get(), is)); if (data_type == "fem2d_gf_data_keys") { - is >> state.keys; + is >> keys; } } else if (data_type == "vfem2d_gf_data" || data_type == "vfem2d_gf_data_keys") { field_type = 1; - state.mesh = new Mesh(is, 1, 0, state.fix_elem_orient); - state.grid_f = new GridFunction(state.mesh, is); + mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); + grid_f.reset(new GridFunction(mesh.get(), is)); if (data_type == "vfem2d_gf_data_keys") { - is >> state.keys; + is >> keys; } } else if (data_type == "fem3d_gf_data" || data_type == "fem3d_gf_data_keys") { - state.mesh = new Mesh(is, 1, 0, state.fix_elem_orient); - state.grid_f = new GridFunction(state.mesh, is); + mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); + grid_f.reset(new GridFunction(mesh.get(), is)); if (data_type == "fem3d_gf_data_keys") { - is >> state.keys; + is >> keys; } } else if (data_type == "vfem3d_gf_data" || data_type == "vfem3d_gf_data_keys") { field_type = 1; - state.mesh = new Mesh(is, 1, 0, state.fix_elem_orient); - state.grid_f = new GridFunction(state.mesh, is); + mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); + grid_f.reset(new GridFunction(mesh.get(), is)); if (data_type == "vfem3d_gf_data_keys") { - is >> state.keys; + is >> keys; } } else if (data_type == "solution") { - state.mesh = new Mesh(is, 1, 0, state.fix_elem_orient); - state.grid_f = new GridFunction(state.mesh, is); - field_type = (state.grid_f->VectorDim() == 1) ? 0 : 1; + mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); + grid_f.reset(new GridFunction(mesh.get(), is)); + field_type = (grid_f->VectorDim() == 1) ? 0 : 1; } else if (data_type == "mesh") { - state.mesh = new Mesh(is, 1, 0, state.fix_elem_orient); - SetMeshSolution(state.mesh, state.grid_f, state.save_coloring); + mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); + SetMeshSolution(save_coloring); field_type = 2; } else if (data_type == "raw_scalar_2d") @@ -271,9 +259,9 @@ int ReadStream(istream &is, const string &data_type) tot_num_elem += num_elem; } - state.mesh = new Mesh(2, tot_num_vert, tot_num_elem, 0); - state.sol.SetSize(tot_num_vert); - state.normals.SetSize(3*tot_num_vert); + mesh.reset(new Mesh(2, tot_num_vert, tot_num_elem, 0)); + sol.SetSize(tot_num_vert); + normals.SetSize(3*tot_num_vert); int v_off = 0; for (int i = 0; i < num_patches; i++) @@ -282,11 +270,11 @@ int ReadStream(istream &is, const string &data_type) num_vert = verts.Size()/6; for (int j = 0; j < num_vert; j++) { - state.mesh->AddVertex(&verts[6*j]); - state.sol(v_off) = verts[6*j+2]; - state.normals(3*v_off+0) = verts[6*j+3]; - state.normals(3*v_off+1) = verts[6*j+4]; - state.normals(3*v_off+2) = verts[6*j+5]; + mesh->AddVertex(&verts[6*j]); + sol(v_off) = verts[6*j+2]; + normals(3*v_off+0) = verts[6*j+3]; + normals(3*v_off+1) = verts[6*j+4]; + normals(3*v_off+2) = verts[6*j+5]; v_off++; } @@ -298,29 +286,29 @@ int ReadStream(istream &is, const string &data_type) if (n == 3) for (int j = 0; j < num_elem; j++) { - state.mesh->AddTriangle(&elems[3*j], attr); + mesh->AddTriangle(&elems[3*j], attr); } else for (int j = 0; j < num_elem; j++) { - state.mesh->AddQuad(&elems[4*j], attr); + mesh->AddQuad(&elems[4*j], attr); } } if (mesh_type == 1) { - state.mesh->FinalizeTriMesh(1, 0, state.fix_elem_orient); + mesh->FinalizeTriMesh(1, 0, fix_elem_orient); } else if (mesh_type == 2) { - state.mesh->FinalizeQuadMesh(1, 0, state.fix_elem_orient); + mesh->FinalizeQuadMesh(1, 0, fix_elem_orient); } else { mfem_error("Input data contains mixture of triangles and quads!"); } - state.mesh->GenerateBoundaryElements(); + mesh->GenerateBoundaryElements(); for (int i = num_patches; i > 0; ) { @@ -340,14 +328,7 @@ int ReadStream(istream &is, const string &data_type) if (field_type >= 0 && field_type <= 2) { - if (state.grid_f) - { - Extrude1DMeshAndSolution(&state.mesh, &state.grid_f, NULL); - } - else - { - Extrude1DMeshAndSolution(&state.mesh, NULL, &state.sol); - } + Extrude1DMeshAndSolution(); } return field_type; diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 3ae90529..7fe6d349 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -13,31 +13,30 @@ #define GLVIS_STREAM_READER_HPP #include +#include #include "mfem.hpp" struct StreamState { mfem::Vector sol, solu, solv, solw, normals; std::string keys; - mfem::Mesh *mesh{nullptr}; - mfem::GridFunction *grid_f{nullptr}; + std::unique_ptr mesh; + std::unique_ptr grid_f; int is_gf{0}; bool fix_elem_orient{false}; bool save_coloring{false}; + + /// Helper function for visualizing 1D data + void Extrude1DMeshAndSolution(); + + /// Set a (checkerboard) solution when only the mesh is given + void SetMeshSolution(bool save_coloring); + + int ReadStream(std::istream &is, const std::string &data_type); }; /// Singleton holding the current stream content (defined in steam_reader.cpp) extern StreamState stream_state; -/// Helper function for visualizing 1D data -void Extrude1DMeshAndSolution(mfem::Mesh **mesh_p, - mfem::GridFunction **grid_f_p, - mfem::Vector *sol); - -/// Set a (checkerboard) solution when only the mesh is given -void SetMeshSolution(mfem::Mesh *mesh, mfem::GridFunction *&grid_f, - bool save_coloring); - -int ReadStream(std::istream &is, const std::string &data_type); #endif // GLVIS_STREAM_READER_HPP diff --git a/lib/threads.cpp b/lib/threads.cpp index 46d90fa7..41172a83 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -19,21 +19,16 @@ using namespace std; -void SetMeshSolution(Mesh *mesh, GridFunction *&grid_f, bool save_coloring); extern const char *strings_off_on[]; // defined in vsdata.cpp GLVisCommand *glvis_command = NULL; GLVisCommand::GLVisCommand( - VisualizationSceneScalarData **_vs, Mesh **_mesh, GridFunction **_grid_f, - Vector *_sol, bool *_keep_attr, bool *_fix_elem_orient) + VisualizationSceneScalarData **_vs, StreamState& state, bool *_keep_attr) + : curr_state(state) { vs = _vs; - mesh = _mesh; - grid_f = _grid_f; - sol = _sol; keep_attr = _keep_attr; - fix_elem_orient = _fix_elem_orient; pthread_mutex_init(&glvis_mutex, NULL); pthread_cond_init(&glvis_cond, NULL); @@ -105,15 +100,16 @@ void GLVisCommand::unlock() pthread_mutex_unlock(&glvis_mutex); } -int GLVisCommand::NewMeshAndSolution(Mesh *_new_m, GridFunction *_new_g) +int GLVisCommand::NewMeshAndSolution(std::unique_ptr _new_m, + std::unique_ptr _new_g) { if (lock() < 0) { return -1; } command = NEW_MESH_AND_SOLUTION; - new_m = _new_m; - new_g = _new_g; + new_state.mesh = std::move(_new_m); + new_state.grid_f = std::move(_new_g); if (signal() < 0) { return -2; @@ -442,13 +438,15 @@ int GLVisCommand::Execute() case NEW_MESH_AND_SOLUTION: { double mesh_range = -1.0; - if (new_g == NULL) + if (!new_state.grid_f) { - SetMeshSolution(new_m, new_g, false); - mesh_range = new_g->Max() + 1.0; + new_state.SetMeshSolution(false); + mesh_range = new_state.grid_f->Max() + 1.0; } - if (new_m->SpaceDimension() == (*mesh)->SpaceDimension() && - new_g->VectorDim() == (*grid_f)->VectorDim()) + Mesh* const new_m = new_state.mesh.get(); + GridFunction* const new_g = new_state.grid_f.get(); + if (new_m->SpaceDimension() == curr_state.mesh->SpaceDimension() && + new_g->VectorDim() == curr_state.grid_f->VectorDim()) { if (new_m->SpaceDimension() == 2) { @@ -456,8 +454,8 @@ int GLVisCommand::Execute() { VisualizationSceneSolution *vss = dynamic_cast(*vs); - new_g->GetNodalValues(*sol); - vss->NewMeshAndSolution(new_m, sol, new_g); + new_g->GetNodalValues(curr_state.sol); + vss->NewMeshAndSolution(new_m, &curr_state.sol, new_g); } else { @@ -472,25 +470,25 @@ int GLVisCommand::Execute() { VisualizationSceneSolution3d *vss = dynamic_cast(*vs); - new_g->GetNodalValues(*sol); - vss->NewMeshAndSolution(new_m, sol, new_g); + new_g->GetNodalValues(curr_state.sol); + vss->NewMeshAndSolution(new_m, &curr_state.sol, new_g); } else { - new_g = ProjectVectorFEGridFunction(new_g); + GridFunction* proj_new_g = ProjectVectorFEGridFunction(new_g); + new_state.grid_f.reset(proj_new_g); + VisualizationSceneVector3d *vss = dynamic_cast(*vs); - vss->NewMeshAndSolution(new_m, new_g); + vss->NewMeshAndSolution(new_m, proj_new_g); } } if (mesh_range > 0.0) { (*vs)->SetValueRange(-mesh_range, mesh_range); } - delete (*grid_f); - *grid_f = new_g; - delete (*mesh); - *mesh = new_m; + curr_state.grid_f = std::move(new_state.grid_f); + curr_state.mesh = std::move(new_state.mesh); MyExpose(); } @@ -748,8 +746,8 @@ void GLVisCommand::Terminate() switch (command) { case NEW_MESH_AND_SOLUTION: - delete new_g; - delete new_m; + stream_state.mesh.release(); + stream_state.grid_f.release(); break; } unlock(); @@ -808,9 +806,6 @@ communication_thread::~communication_thread() pthread_cancel(tid); pthread_join(tid, NULL); } - - delete new_g; - delete new_m; } // defined in glvis.cpp @@ -836,23 +831,24 @@ void *communication_thread::execute(void *p) _this->ident == "parallel") { bool fix_elem_orient = glvis_command->FixElementOrientations(); + StreamState tmp; if (_this->ident == "mesh") { - _this->new_m = new Mesh(*_this->is[0], 1, 0, fix_elem_orient); + tmp.mesh.reset(new Mesh(*_this->is[0], 1, 0, fix_elem_orient)); if (!(*_this->is[0])) { break; } - _this->new_g = NULL; + tmp.grid_f = NULL; } else if (_this->ident == "solution") { - _this->new_m = new Mesh(*_this->is[0], 1, 0, fix_elem_orient); + tmp.mesh.reset(new Mesh(*_this->is[0], 1, 0, fix_elem_orient)); if (!(*_this->is[0])) { break; } - _this->new_g = new GridFunction(_this->new_m, *_this->is[0]); + tmp.grid_f.reset(new GridFunction(tmp.mesh.get(), *_this->is[0])); if (!(*_this->is[0])) { break; @@ -897,8 +893,8 @@ void *communication_thread::execute(void *p) *_this->is[np] >> _this->ident >> ws; // "parallel" } while (1); - _this->new_m = new Mesh(mesh_array, nproc); - _this->new_g = new GridFunction(_this->new_m, gf_array, nproc); + tmp.mesh.reset(new Mesh(mesh_array, nproc)); + tmp.grid_f.reset(new GridFunction(tmp.mesh.get(), gf_array, nproc)); for (int p = 0; p < nproc; p++) { @@ -911,15 +907,13 @@ void *communication_thread::execute(void *p) // cout << "Stream: new solution" << endl; - Extrude1DMeshAndSolution(&_this->new_m, &_this->new_g, NULL); + tmp.Extrude1DMeshAndSolution(); - if (glvis_command->NewMeshAndSolution(_this->new_m, _this->new_g)) + if (glvis_command->NewMeshAndSolution(std::move(tmp.mesh), + std::move(tmp.grid_f))) { goto comm_terminate; } - - _this->new_m = NULL; - _this->new_g = NULL; } else if (_this->ident == "screenshot") { diff --git a/lib/threads.hpp b/lib/threads.hpp index c87f6190..7f46cd78 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -13,6 +13,7 @@ #define GLVIS_THREADS_HPP #include "vsdata.hpp" +#include "stream_reader.hpp" #include #include @@ -21,11 +22,8 @@ class GLVisCommand private: // Pointers to global GLVis data VisualizationSceneScalarData **vs; - mfem::Mesh **mesh; - mfem::GridFunction **grid_f; - mfem::Vector *sol; + StreamState& curr_state; bool *keep_attr; - bool *fix_elem_orient; pthread_mutex_t glvis_mutex; pthread_cond_t glvis_cond; @@ -62,8 +60,7 @@ class GLVisCommand int command; // command arguments - Mesh *new_m; - GridFunction *new_g; + StreamState new_state; std::string screenshot_filename; std::string key_commands; int window_x, window_y; @@ -93,19 +90,19 @@ class GLVisCommand public: // called by the main execution thread - GLVisCommand(VisualizationSceneScalarData **_vs, Mesh **_mesh, - GridFunction **_grid_f, Vector *_sol, bool *_keep_attr, - bool *_fix_elem_orient); + GLVisCommand(VisualizationSceneScalarData **_vs, + StreamState& thread_state, bool *_keep_attr); // to be used by the main execution (visualization) thread int ReadFD() { return pfd[0]; } // to be used by worker threads bool KeepAttrib() { return *keep_attr; } // may need to sync this - bool FixElementOrientations() { return *fix_elem_orient; } + bool FixElementOrientations() { return curr_state.fix_elem_orient; } // called by worker threads - int NewMeshAndSolution(Mesh *_new_m, GridFunction *_new_g); + int NewMeshAndSolution(std::unique_ptr _new_m, + std::unique_ptr _new_g); int Screenshot(const char *filename); int KeyCommands(const char *keys); int WindowSize(int w, int h); @@ -147,8 +144,8 @@ class communication_thread Array &is; // data that may be dynamically allocated by the thread - Mesh *new_m; - GridFunction *new_g; + std::unique_ptr new_m; + std::unique_ptr new_g; std::string ident; // thread id From a5a8ca2596f3dab6ce241f47fca433810653dd70 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 3 Feb 2021 15:01:22 -0800 Subject: [PATCH 18/42] Deduplicate mesh/solution update code --- glvis.cpp | 54 +++++++------------------------------------ lib/stream_reader.cpp | 48 ++++++++++++++++++++++++++++++++++++++ lib/stream_reader.hpp | 4 ++++ lib/threads.cpp | 49 ++++----------------------------------- 4 files changed, 64 insertions(+), 91 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index c7f94101..4b1ebb93 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -461,12 +461,11 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } else if (word == "solution" || word == "mesh" || word == "psolution") { - Mesh *new_m = NULL; - GridFunction *new_g; + StreamState new_state; if (word == "solution") { - if (ScriptReadSolution(scr, stream_state)) + if (ScriptReadSolution(scr, new_state)) { done_one_command = 1; continue; @@ -474,12 +473,12 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } else if (word == "mesh") { - if (ScriptReadDisplMesh(scr, stream_state)) + if (ScriptReadDisplMesh(scr, new_state)) { done_one_command = 1; continue; } - if (new_m == NULL) + if (new_state.mesh == NULL) { cout << "Script: unexpected 'mesh' command!" << endl; done_one_command = 1; @@ -488,59 +487,22 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } else if (word == "psolution") { - if (ScriptReadParSolution(scr, stream_state)) + if (ScriptReadParSolution(scr, new_state)) { done_one_command = 1; continue; } } - if (new_m->SpaceDimension() == mesh->SpaceDimension() && - new_g->VectorDim() == grid_f->VectorDim()) + if (new_state.mesh->SpaceDimension() == mesh->SpaceDimension() && + new_state.grid_f->VectorDim() == grid_f->VectorDim()) { - if (new_m->SpaceDimension() == 2) - { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution *vss = - dynamic_cast(vs); - new_g->GetNodalValues(sol); - vss->NewMeshAndSolution(new_m, &sol, new_g); - } - else - { - VisualizationSceneVector *vsv = - dynamic_cast(vs); - vsv->NewMeshAndSolution(*new_g); - } - } - else - { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution3d *vss = - dynamic_cast(vs); - new_g->GetNodalValues(sol); - vss->NewMeshAndSolution(new_m, &sol, new_g); - } - else - { - new_g = ProjectVectorFEGridFunction(new_g); - VisualizationSceneVector3d *vss = - dynamic_cast(vs); - vss->NewMeshAndSolution(new_m, new_g); - } - } - stream_state.grid_f.reset(new_g); - stream_state.mesh.reset(new_m); - + stream_state.SetNewMeshAndSolution(std::move(new_state), vs); MyExpose(); } else { cout << "Different type of mesh / solution." << endl; - delete new_g; - delete new_m; } } else if (word == "screenshot") diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index dac18673..5a825270 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -10,6 +10,7 @@ // CONTRIBUTING.md for details. #include "stream_reader.hpp" +#include "visual.hpp" using namespace std; using namespace mfem; @@ -333,3 +334,50 @@ int StreamState::ReadStream(istream &is, const string &data_type) return field_type; } + +GridFunction *ProjectVectorFEGridFunction(GridFunction*); + +void StreamState::SetNewMeshAndSolution(StreamState new_state, + VisualizationScene* vs) +{ + std::unique_ptr new_m = std::move(new_state.mesh); + std::unique_ptr new_g = std::move(new_state.grid_f); + if (new_m->SpaceDimension() == 2) + { + if (new_g->VectorDim() == 1) + { + VisualizationSceneSolution *vss = + dynamic_cast(vs); + new_g->GetNodalValues(sol); + vss->NewMeshAndSolution(new_m.get(), &sol, new_g.get()); + } + else + { + VisualizationSceneVector *vsv = + dynamic_cast(vs); + vsv->NewMeshAndSolution(*new_g); + } + } + else + { + if (new_g->VectorDim() == 1) + { + VisualizationSceneSolution3d *vss = + dynamic_cast(vs); + new_g->GetNodalValues(sol); + vss->NewMeshAndSolution(new_m.get(), &sol, new_g.get()); + } + else + { + GridFunction* proj_new_g = ProjectVectorFEGridFunction(new_g.get()); + new_g.reset(proj_new_g); + + VisualizationSceneVector3d *vss = + dynamic_cast(vs); + vss->NewMeshAndSolution(new_m.get(), proj_new_g); + } + } + grid_f = std::move(new_g); + mesh = std::move(new_m); +} + diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 7fe6d349..0b73fc09 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -15,6 +15,7 @@ #include #include #include "mfem.hpp" +#include "openglvis.hpp" struct StreamState { @@ -33,6 +34,9 @@ struct StreamState void SetMeshSolution(bool save_coloring); int ReadStream(std::istream &is, const std::string &data_type); + + void SetNewMeshAndSolution(StreamState new_state, + VisualizationScene* vs); }; /// Singleton holding the current stream content (defined in steam_reader.cpp) diff --git a/lib/threads.cpp b/lib/threads.cpp index 41172a83..ded6f372 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -443,60 +443,19 @@ int GLVisCommand::Execute() new_state.SetMeshSolution(false); mesh_range = new_state.grid_f->Max() + 1.0; } - Mesh* const new_m = new_state.mesh.get(); - GridFunction* const new_g = new_state.grid_f.get(); - if (new_m->SpaceDimension() == curr_state.mesh->SpaceDimension() && - new_g->VectorDim() == curr_state.grid_f->VectorDim()) + if (new_state.mesh->SpaceDimension() == curr_state.mesh->SpaceDimension() && + new_state.grid_f->VectorDim() == curr_state.grid_f->VectorDim()) { - if (new_m->SpaceDimension() == 2) - { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution *vss = - dynamic_cast(*vs); - new_g->GetNodalValues(curr_state.sol); - vss->NewMeshAndSolution(new_m, &curr_state.sol, new_g); - } - else - { - VisualizationSceneVector *vsv = - dynamic_cast(*vs); - vsv->NewMeshAndSolution(*new_g); - } - } - else - { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution3d *vss = - dynamic_cast(*vs); - new_g->GetNodalValues(curr_state.sol); - vss->NewMeshAndSolution(new_m, &curr_state.sol, new_g); - } - else - { - GridFunction* proj_new_g = ProjectVectorFEGridFunction(new_g); - new_state.grid_f.reset(proj_new_g); - - VisualizationSceneVector3d *vss = - dynamic_cast(*vs); - vss->NewMeshAndSolution(new_m, proj_new_g); - } - } + curr_state.SetNewMeshAndSolution(std::move(new_state), *vs); if (mesh_range > 0.0) { - (*vs)->SetValueRange(-mesh_range, mesh_range); + (*vs)->SetValueRange(-mesh_range, mesh_range); } - curr_state.grid_f = std::move(new_state.grid_f); - curr_state.mesh = std::move(new_state.mesh); - MyExpose(); } else { cout << "Stream: field type does not match!" << endl; - delete new_g; - delete new_m; } if (autopause) { From 33ee05795d48381a07b562541cdc008b58b4ad96 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 3 Feb 2021 15:13:50 -0800 Subject: [PATCH 19/42] Remove some global dependencies from glvis.cpp --- glvis.cpp | 50 ++++++++++++++++++++++++------------------------- lib/aux_vis.hpp | 10 ++++++++++ 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 4b1ebb93..c25abfcc 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -498,7 +498,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) new_state.grid_f->VectorDim() == grid_f->VectorDim()) { stream_state.SetNewMeshAndSolution(std::move(new_state), vs); - MyExpose(); + wnd->MyExpose(); } else { @@ -530,7 +530,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr >> vs->ViewCenterX >> vs->ViewCenterY; cout << "Script: viewcenter: " << vs->ViewCenterX << ' ' << vs->ViewCenterY << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "perspective") { @@ -549,7 +549,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << '?'; } cout << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "light") { @@ -568,7 +568,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << '?'; } cout << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "view") { @@ -576,7 +576,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr >> theta >> phi; cout << "Script: view: " << theta << ' ' << phi << endl; vs->SetView(theta, phi); - MyExpose(); + wnd->MyExpose(); } else if (word == "zoom") { @@ -584,7 +584,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr >> factor; cout << "Script: zoom: " << factor << endl; vs->Zoom(factor); - MyExpose(); + wnd->MyExpose(); } else if (word == "shading") { @@ -607,7 +607,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) { vs->SetShading(s, false); cout << word << endl; - MyExpose(); + wnd->MyExpose(); } else { @@ -621,7 +621,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << "Script: subdivisions: " << flush; vs->SetRefineFactors(t, b); cout << t << ' ' << b << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "valuerange") { @@ -630,7 +630,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << "Script: valuerange: " << flush; vs->SetValueRange(min, max); cout << min << ' ' << max << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "autoscale") { @@ -664,7 +664,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << "Script: window: " << window_x << ' ' << window_y << ' ' << window_w << ' ' << window_h << endl; wnd->MoveResizeWindow(window_x, window_y, window_w, window_h); - MyExpose(); + wnd->MyExpose(); } else if (word == "keys") { @@ -672,7 +672,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << "Script: keys: '" << keys << "'" << endl; // SendKeySequence(keys.c_str()); CallKeySequence(keys.c_str()); - MyExpose(); + wnd->MyExpose(); } else if (word == "palette") { @@ -680,7 +680,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr >> pal; cout << "Script: palette: " << pal << endl; vs->GetPalette().SetPalette(pal); - MyExpose(); + wnd->MyExpose(); } else if (word == "palette_repeat") { @@ -689,7 +689,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << "Script: palette_repeat: " << rpt_times << endl; vs->GetPalette().SetRepeatTimes(rpt_times); vs->GetPalette().Init(); - MyExpose(); + wnd->MyExpose(); } else if (word == "toggle_attributes") { @@ -711,7 +711,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr.get(); // read the end symbol: ';' cout << endl; vs->ToggleAttributes(attr_list); - MyExpose(); + wnd->MyExpose(); } else if (word == "rotmat") { @@ -722,7 +722,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << ' ' << vs->rotmat[i/4][i%4]; } cout << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "camera") { @@ -735,7 +735,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } cout << endl; vs->cam.Set(cam); - MyExpose(); + wnd->MyExpose(); } else if (word == "scale") { @@ -745,7 +745,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << ' ' << scale; cout << endl; vs->Scale(scale); - MyExpose(); + wnd->MyExpose(); } else if (word == "translate") { @@ -755,7 +755,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) cout << ' ' << x << ' ' << y << ' ' << z; cout << endl; vs->Translate(x, y, z); - MyExpose(); + wnd->MyExpose(); } else if (word == "plot_caption") { @@ -763,7 +763,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) scr >> ws >> delim; getline(scr, plot_caption, delim); vs->PrepareCaption(); // turn on or off the caption - MyExpose(); + wnd->MyExpose(); } else { @@ -774,28 +774,28 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } } -void ScriptControl(); +void ScriptControl(GLVisWindow* wnd); void ScriptIdleFunc(GLVisWindow* wnd) { ExecuteScriptCommand(wnd); if (scr_level == 0) { - ScriptControl(); + ScriptControl(wnd); } } -void ScriptControl() +void ScriptControl(GLVisWindow* wnd) { if (scr_running) { scr_running = 0; - mainWindow->RemoveIdleFunc(ScriptIdleFunc); + wnd->RemoveIdleFunc(ScriptIdleFunc); } else { scr_running = 1; - mainWindow->AddIdleFunc(ScriptIdleFunc); + wnd->AddIdleFunc(ScriptIdleFunc); } } @@ -868,7 +868,7 @@ void PlayScript(istream &scr) if (GLVisInitVis((grid_f->VectorDim() == 1) ? 0 : 1)) { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); + mainWindow->AddWindowEvent(SDLK_SPACE, ScriptControl, false); GLVisStartVis(); } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 67ba568c..a175ecba 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -84,6 +84,16 @@ class GLVisWindow void MoveResizeWindow(int x, int y, int w, int h); void ResizeWindow(int w, int h); void SetWindowTitle(const char *title); + + void AddWindowEvent(int key, void (*eh)(GLVisWindow*), bool exposeAfter = true) + { + auto wrapped_eh = [this, eh, exposeAfter](GLenum e) + { + (*eh)(this); + if (exposeAfter) { SendExposeEvent(); } + }; + wnd->setOnKeyDown(key, wrapped_eh); + } private: void InitFont(); bool SetFont(const vector& patterns, int height); From f9f8d69425887b91b4a1ca96955eb0c9eec758c7 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 4 Feb 2021 10:41:47 -0800 Subject: [PATCH 20/42] Remove references to global glvis_command instance --- glvis.cpp | 6 +++-- lib/aux_vis.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++----- lib/aux_vis.hpp | 13 ++++++++++- lib/sdl.cpp | 57 +++++++++++++---------------------------------- lib/sdl.hpp | 5 +++-- lib/threads.cpp | 53 ++++++++++++++++++++++---------------------- lib/threads.hpp | 12 +++++----- 7 files changed, 119 insertions(+), 86 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index c25abfcc..50f8cc8c 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -70,6 +70,7 @@ int & is_gf = stream_state.is_gf; std::string & keys = stream_state.keys; GLVisWindow * mainWindow = nullptr; VisualizationSceneScalarData *vs = NULL; +GLVisCommand *glvis_command = nullptr; communication_thread *comm_thread = NULL; GeometryRefiner GLVisGeometryRefiner; @@ -144,8 +145,9 @@ bool GLVisInitVis(int field_type) if (input_streams.Size() > 0) { - glvis_command = new GLVisCommand(&vs, stream_state, &keep_attr); - comm_thread = new communication_thread(input_streams); + glvis_command = new GLVisCommand(&vs, stream_state, keep_attr); + comm_thread = new communication_thread(glvis_command, input_streams); + mainWindow->SetGLVisCommand(glvis_command, comm_thread); } double mesh_range = -1.0; diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 36a6f4d0..8d0f2b8b 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -378,8 +378,18 @@ void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, } } +void GLVisWindow::SetGLVisCommand(GLVisCommand* cmd, + communication_thread* cthread) +{ + glvis_command = cmd; + comm_thread = cthread; + use_idle = false; +} + void GLVisWindow::RunVisualization() { + visualize = 1; + wnd->setOnIdle([this](){return MainIdleFunc();}); #ifndef __EMSCRIPTEN__ wnd->mainLoop(); #endif @@ -468,19 +478,55 @@ void GLVisWindow::MyExpose() wnd->signalSwap(); } -void GLVisWindow::MainIdleFunc() +bool GLVisWindow::CommunicationIdleFunc() +{ + int status = glvis_command->Execute(); + if (status < 0) + { + cout << "GLVisCommand signalled exit" << endl; + wnd->signalQuit(); + } + else if (status == 1) + { + // no commands right now - main loop should sleep + return true; + } + return false; +} + +bool GLVisWindow::MainIdleFunc() { - last_idle_func = (last_idle_func + 1) % idle_funcs.Size(); - if (idle_funcs[last_idle_func]) + bool sleep = true; + if (glvis_command && visualize == 1 + && !(idle_funcs.Size() > 0 && use_idle)) { - (*idle_funcs[last_idle_func])(this); + // Execute the next event from the communication thread if: + // - a valid GLVisCommand has been set + // - the communication thread is not stopped + // - The idle function flag is not set, or no idle functions have been + // registered + sleep = CommunicationIdleFunc(); + if (idle_funcs.Size() > 0) { sleep = false; } + } + else if (idle_funcs.Size() > 0) + { + last_idle_func = (last_idle_func + 1) % idle_funcs.Size(); + if (idle_funcs[last_idle_func]) + { + (*idle_funcs[last_idle_func])(this); + } + // Continue executing idle functions + sleep = false; } + use_idle = !use_idle; + return sleep; } void GLVisWindow::AddIdleFunc(GLVisWindow::IdleFPtr Func) { idle_funcs.Union(Func); - wnd->setOnIdle([this](){MainIdleFunc();}); + use_idle = false; + wnd->setOnIdle([this](){return MainIdleFunc();}); } void GLVisWindow::RemoveIdleFunc(GLVisWindow::IdleFPtr Func) @@ -488,7 +534,8 @@ void GLVisWindow::RemoveIdleFunc(GLVisWindow::IdleFPtr Func) idle_funcs.DeleteFirst(Func); if (idle_funcs.Size() == 0) { - wnd->setOnIdle(nullptr); + use_idle = false; + if (!glvis_command) { wnd->setOnIdle(nullptr); } } } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index a175ecba..e2865d15 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -20,6 +20,10 @@ #include "sdl.hpp" #include "font.hpp" #include "openglvis.hpp" +#include "stream_reader.hpp" + +class GLVisCommand; +class communication_thread; class GLVisWindow { @@ -32,6 +36,9 @@ class GLVisWindow void SetVisualizationScene(VisualizationScene * scene, int view = 3, const char *keys = NULL); + + void SetGLVisCommand(GLVisCommand* cmd, communication_thread* cthread); + void SetFont(const std::string& fn); VisualizationScene* getScene() { return locscene; } @@ -101,7 +108,8 @@ class GLVisWindow void SetKeyEventHandler(int key, void (GLVisWindow::*handler)()); void SetKeyEventHandler(int key, void (GLVisWindow::*handler)(GLenum)); - void MainIdleFunc(); + bool MainIdleFunc(); + bool CommunicationIdleFunc(); void MyReshape(GLsizei w, GLsizei h); void MyExpose(GLsizei w, GLsizei h); @@ -131,6 +139,9 @@ class GLVisWindow std::unique_ptr wnd; VisualizationScene* locscene; + GLVisCommand* glvis_command = nullptr; + communication_thread* comm_thread = nullptr; + bool use_idle = false; // Idle function callbacks mfem::Array idle_funcs{}; diff --git a/lib/sdl.cpp b/lib/sdl.cpp index 63452998..b015ee49 100644 --- a/lib/sdl.cpp +++ b/lib/sdl.cpp @@ -46,7 +46,6 @@ using std::endl; #endif extern int GetMultisample(); -extern int visualize; struct SdlWindow::Handle { @@ -644,47 +643,22 @@ void SdlWindow::mainIter() #ifndef __EMSCRIPTEN__ else if (onIdle) { - if (glvis_command == NULL || visualize == 2 || useIdle) + bool sleep = onIdle(); + if (sleep) { - onIdle(); - } - else - { - if (glvis_command->Execute() < 0) - { - cout << "GlvisCommand signalled exit" << endl; - running = false; - } - } - useIdle = !useIdle; - } - else - { - int status; - if (glvis_command && visualize == 1 && - (status = glvis_command->Execute()) != 1) - { - if (status < 0) - { - cout << "GlvisCommand signalled exit" << endl; - running = false; - } - } - else - { - // Wait for the next event (without consuming CPU cycles, if possible) - // See also: SdlWindow::signalLoop() - if (platform) - { - platform->WaitEvent(); - } - else - { - if (!SDL_PollEvent(nullptr)) - { - std::this_thread::sleep_for(std::chrono::milliseconds(8)); - } - } + // Wait for the next event (without consuming CPU cycles, if possible) + // See also: SdlWindow::signalLoop() + if (platform) + { + platform->WaitEvent(); + } + else + { + if (!SDL_PollEvent(nullptr)) + { + std::this_thread::sleep_for(std::chrono::milliseconds(8)); + } + } } } #else @@ -713,7 +687,6 @@ void SdlWindow::mainLoop() ((SdlWindow*) arg)->mainIter(); }, this, 0, true); #else - visualize = 1; while (running) { mainIter(); diff --git a/lib/sdl.hpp b/lib/sdl.hpp index e2740843..313421e3 100644 --- a/lib/sdl.hpp +++ b/lib/sdl.hpp @@ -30,6 +30,7 @@ typedef std::function MouseDelegate; typedef std::function KeyDelegate; typedef std::function WindowDelegate; typedef std::function Delegate; +typedef std::function IdleDelegate; class SdlWindow { @@ -57,7 +58,7 @@ class SdlWindow bool running; - Delegate onIdle; + IdleDelegate onIdle; Delegate onExpose; WindowDelegate onReshape; std::map onKeyDown; @@ -114,7 +115,7 @@ class SdlWindow // Called by worker threads in GLVisCommand::signal() void signalLoop(); - void setOnIdle(Delegate func) { onIdle = func; } + void setOnIdle(IdleDelegate func) { onIdle = func; } void setOnExpose(Delegate func) { onExpose = func; } void setOnReshape(WindowDelegate func) { onReshape = func; } diff --git a/lib/threads.cpp b/lib/threads.cpp index ded6f372..dea32e01 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -21,10 +21,8 @@ using namespace std; extern const char *strings_off_on[]; // defined in vsdata.cpp -GLVisCommand *glvis_command = NULL; - GLVisCommand::GLVisCommand( - VisualizationSceneScalarData **_vs, StreamState& state, bool *_keep_attr) + VisualizationSceneScalarData **_vs, StreamState& state, bool _keep_attr) : curr_state(state) { vs = _vs; @@ -746,8 +744,9 @@ GLVisCommand::~GLVisCommand() pthread_mutex_destroy(&glvis_mutex); } -communication_thread::communication_thread(Array &_is) - : is(_is) +communication_thread::communication_thread(GLVisCommand* parent_cmd, + Array &_is) + : is(_is), glvis_command(parent_cmd) { new_m = NULL; new_g = NULL; @@ -789,7 +788,7 @@ void *communication_thread::execute(void *p) if (_this->ident == "mesh" || _this->ident == "solution" || _this->ident == "parallel") { - bool fix_elem_orient = glvis_command->FixElementOrientations(); + bool fix_elem_orient = _this->glvis_command->FixElementOrientations(); StreamState tmp; if (_this->ident == "mesh") { @@ -818,7 +817,7 @@ void *communication_thread::execute(void *p) Array mesh_array; Array gf_array; int proc, nproc, np = 0; - bool keep_attr = glvis_command->KeepAttrib(); + bool keep_attr = _this->glvis_command->KeepAttrib(); do { istream &isock = *_this->is[np]; @@ -868,7 +867,7 @@ void *communication_thread::execute(void *p) tmp.Extrude1DMeshAndSolution(); - if (glvis_command->NewMeshAndSolution(std::move(tmp.mesh), + if (_this->glvis_command->NewMeshAndSolution(std::move(tmp.mesh), std::move(tmp.grid_f))) { goto comm_terminate; @@ -887,7 +886,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> ws >> _this->ident; // filename } - if (glvis_command->Screenshot(filename.c_str())) + if (_this->glvis_command->Screenshot(filename.c_str())) { goto comm_terminate; } @@ -905,7 +904,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> ws >> _this->ident; // keys } - if (glvis_command->KeyCommands(keys.c_str())) + if (_this->glvis_command->KeyCommands(keys.c_str())) { goto comm_terminate; } @@ -923,7 +922,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> t >> t; } - if (glvis_command->WindowSize(w, h)) + if (_this->glvis_command->WindowSize(w, h)) { goto comm_terminate; } @@ -941,7 +940,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> t >> t >> t >> t; } - if (glvis_command->WindowGeometry(x, y, w, h)) + if (_this->glvis_command->WindowGeometry(x, y, w, h)) { goto comm_terminate; } @@ -963,7 +962,7 @@ void *communication_thread::execute(void *p) getline(*_this->is[i], _this->ident, c); } - if (glvis_command->WindowTitle(title.c_str())) + if (_this->glvis_command->WindowTitle(title.c_str())) { goto comm_terminate; } @@ -985,7 +984,7 @@ void *communication_thread::execute(void *p) getline(*_this->is[i], _this->ident, c); } - if (glvis_command->PlotCaption(caption.c_str())) + if (_this->glvis_command->PlotCaption(caption.c_str())) { goto comm_terminate; } @@ -1015,7 +1014,7 @@ void *communication_thread::execute(void *p) getline(*_this->is[i], _this->ident, c); } - if (glvis_command->AxisLabels(label_x.c_str(), + if (_this->glvis_command->AxisLabels(label_x.c_str(), label_y.c_str(), label_z.c_str())) { @@ -1030,7 +1029,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> ws >> _this->ident; // 'pause' } - if (glvis_command->Pause()) + if (_this->glvis_command->Pause()) { goto comm_terminate; } @@ -1048,7 +1047,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a >> a; } - if (glvis_command->ViewAngles(theta, phi)) + if (_this->glvis_command->ViewAngles(theta, phi)) { goto comm_terminate; } @@ -1066,7 +1065,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a; } - if (glvis_command->Zoom(factor)) + if (_this->glvis_command->Zoom(factor)) { goto comm_terminate; } @@ -1084,7 +1083,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a >> a; } - if (glvis_command->Subdivisions(tot, bdr)) + if (_this->glvis_command->Subdivisions(tot, bdr)) { goto comm_terminate; } @@ -1102,7 +1101,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a >> a; } - if (glvis_command->ValueRange(minv, maxv)) + if (_this->glvis_command->ValueRange(minv, maxv)) { goto comm_terminate; } @@ -1120,7 +1119,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> ws >> _this->ident; } - if (glvis_command->SetShading(shd.c_str())) + if (_this->glvis_command->SetShading(shd.c_str())) { goto comm_terminate; } @@ -1138,7 +1137,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a >> a; } - if (glvis_command->ViewCenter(x, y)) + if (_this->glvis_command->ViewCenter(x, y)) { goto comm_terminate; } @@ -1156,7 +1155,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> ws >> _this->ident; } - if (glvis_command->Autoscale(mode.c_str())) + if (_this->glvis_command->Autoscale(mode.c_str())) { goto comm_terminate; } @@ -1174,7 +1173,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a; } - if (glvis_command->Palette(pal)) + if (_this->glvis_command->Palette(pal)) { goto comm_terminate; } @@ -1192,7 +1191,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> a; } - if (glvis_command->PaletteRepeat(n)) + if (_this->glvis_command->PaletteRepeat(n)) { goto comm_terminate; } @@ -1216,7 +1215,7 @@ void *communication_thread::execute(void *p) } } - if (glvis_command->Camera(cam)) + if (_this->glvis_command->Camera(cam)) { goto comm_terminate; } @@ -1234,7 +1233,7 @@ void *communication_thread::execute(void *p) *_this->is[i] >> ws >> _this->ident; } - if (glvis_command->Autopause(mode.c_str())) + if (_this->glvis_command->Autopause(mode.c_str())) { goto comm_terminate; } diff --git a/lib/threads.hpp b/lib/threads.hpp index 7f46cd78..e809df6f 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -23,7 +23,7 @@ class GLVisCommand // Pointers to global GLVis data VisualizationSceneScalarData **vs; StreamState& curr_state; - bool *keep_attr; + bool keep_attr; pthread_mutex_t glvis_mutex; pthread_cond_t glvis_cond; @@ -91,13 +91,13 @@ class GLVisCommand public: // called by the main execution thread GLVisCommand(VisualizationSceneScalarData **_vs, - StreamState& thread_state, bool *_keep_attr); + StreamState& thread_state, bool _keep_attr); // to be used by the main execution (visualization) thread int ReadFD() { return pfd[0]; } // to be used by worker threads - bool KeepAttrib() { return *keep_attr; } // may need to sync this + bool KeepAttrib() { return keep_attr; } // may need to sync this bool FixElementOrientations() { return curr_state.fix_elem_orient; } // called by worker threads @@ -135,14 +135,14 @@ class GLVisCommand ~GLVisCommand(); }; -extern GLVisCommand *glvis_command; - class communication_thread { private: // streams to read data from Array &is; + GLVisCommand* glvis_command; + // data that may be dynamically allocated by the thread std::unique_ptr new_m; std::unique_ptr new_g; @@ -164,7 +164,7 @@ class communication_thread static void *execute(void *); public: - communication_thread(Array &_is); + communication_thread(GLVisCommand* parent_cmd, Array &_is); ~communication_thread(); }; From ccf25c77a588d3198294ddd4dd46eff4e90b251c Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 4 Feb 2021 11:47:34 -0800 Subject: [PATCH 21/42] Move command, vis scene construction into GLVisWindow; pass local GLVisWindow into GLVisCommand --- glvis.cpp | 137 ++---------------------------------------- lib/aux_vis.cpp | 84 +++++++++++++------------- lib/aux_vis.hpp | 16 ++--- lib/stream_reader.cpp | 121 +++++++++++++++++++++++++++++++++++++ lib/stream_reader.hpp | 2 + lib/threads.cpp | 98 +++++++++++++++--------------- lib/threads.hpp | 10 +-- 7 files changed, 235 insertions(+), 233 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 50f8cc8c..02772703 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -143,147 +143,20 @@ bool GLVisInitVis(int field_type) mainWindow->SetFont(font_name); } - if (input_streams.Size() > 0) + mainWindow->InitVisualization(field_type, std::move(stream_state), + input_streams, keep_attr); + if (keys != "") { - glvis_command = new GLVisCommand(&vs, stream_state, keep_attr); - comm_thread = new communication_thread(glvis_command, input_streams); - mainWindow->SetGLVisCommand(glvis_command, comm_thread); + mainWindow->CallKeySequence(keys.c_str()); } - double mesh_range = -1.0; - if (field_type == 0 || field_type == 2) - { - if (grid_f) - { - grid_f->GetNodalValues(sol); - } - if (mesh->SpaceDimension() == 2) - { - VisualizationSceneSolution *vss; - if (normals.Size() > 0) - { - vs = vss = new VisualizationSceneSolution(*mesh, sol, &normals); - } - else - { - vs = vss = new VisualizationSceneSolution(*mesh, sol); - } - if (grid_f) - { - vss->SetGridFunction(*grid_f); - } - if (field_type == 2) - { - vs->OrthogonalProjection = 1; - vs->SetLight(false); - vs->Zoom(1.8); - // Use the 'bone' palette when visualizing a 2D mesh only (otherwise - // the 'jet-like' palette is used in 2D, see vssolution.cpp). - vs->GetPalette().SetPalette(4); - } - } - else if (mesh->SpaceDimension() == 3) - { - VisualizationSceneSolution3d *vss; - vs = vss = new VisualizationSceneSolution3d(*mesh, sol); - if (grid_f) - { - vss->SetGridFunction(grid_f.get()); - } - if (field_type == 2) - { - if (mesh->Dimension() == 3) - { - // Use the 'white' palette when visualizing a 3D volume mesh only - vss->GetPalette().SetPalette(11); - vss->SetLightMatIdx(4); - } - else - { - // Use the 'bone' palette when visualizing a surface mesh only - vss->GetPalette().SetPalette(4); - } - // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp - vss->ToggleDrawAxes(); - vss->ToggleDrawMesh(); - } - } - if (field_type == 2) - { - if (grid_f) - { - mesh_range = grid_f->Max() + 1.0; - } - else - { - mesh_range = sol.Max() + 1.0; - } - } - } - else if (field_type == 1) - { - if (mesh->SpaceDimension() == 2) - { - if (grid_f) - { - vs = new VisualizationSceneVector(*grid_f); - } - else - { - vs = new VisualizationSceneVector(*mesh, solu, solv); - } - } - else if (mesh->SpaceDimension() == 3) - { - if (grid_f) - { - GridFunction* proj_grid_f = ProjectVectorFEGridFunction(grid_f.get()); - grid_f.reset(proj_grid_f); - vs = new VisualizationSceneVector3d(*proj_grid_f); - } - else - { - vs = new VisualizationSceneVector3d(*mesh, solu, solv, solw); - } - } - } - - if (vs) - { - // increase the refinement factors if visualizing a GridFunction - if (grid_f) - { - vs->AutoRefine(); - vs->SetShading(2, true); - } - if (mesh_range > 0.0) - { - vs->SetValueRange(-mesh_range, mesh_range); - vs->SetAutoscale(0); - } - if (mesh->SpaceDimension() == 2 && field_type == 2) - { - mainWindow->SetVisualizationScene(vs, 2, keys.c_str()); - } - else - { - mainWindow->SetVisualizationScene(vs, 3, keys.c_str()); - } - } return true; } void GLVisStartVis() { mainWindow->RunVisualization(); // deletes vs - vs = NULL; - if (input_streams.Size() > 0) - { - glvis_command->Terminate(); - delete comm_thread; - delete glvis_command; - glvis_command = NULL; - } + delete mainWindow; cout << "GLVis window closed." << endl; } diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 8d0f2b8b..76aeb0f4 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -224,6 +224,44 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega #endif } +GLVisWindow::~GLVisWindow() +{ + if (glvis_command) + { + glvis_command->Terminate(); + } +} + +void GLVisWindow::InitVisualization(int field_type, StreamState state, + const mfem::Array& input_streams, + bool keep_attr) +{ + prob_state = std::move(state); + if (input_streams.Size() > 0) + { + glvis_command.reset(new GLVisCommand(this, prob_state, keep_attr)); + comm_thread.reset(new communication_thread(glvis_command.get(), input_streams)); + } + + locscene = prob_state.CreateVisualizationScene(field_type); + + if (prob_state.mesh->SpaceDimension() == 2 && field_type == 2) + { + locscene->view = 2; + locscene->CenterObject2D(); + } + else + { + locscene->view = 3; + locscene->CenterObject(); + } + + if (locscene->spinning) + { + AddIdleFunc(::MainLoop); + } +} + void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)()) { auto handlerWrapper = [this, handler]() { (this->*handler)(); }; @@ -351,41 +389,6 @@ void GLVisWindow::CallKeySequence(const char *seq) disableSendExposeEvent = false; } -void GLVisWindow::SetVisualizationScene(VisualizationScene * scene, int view, - const char *keys) -{ - ::locscene = locscene = scene; - //locscene->SetFont(&font); - locscene -> view = view; - if (view == 2) - { - scene -> CenterObject2D(); - } - else - { - scene -> CenterObject(); - } - - if (scene -> spinning) - { - AddIdleFunc(::MainLoop); - } - - if (keys) - { - // SendKeySequence(keys); - CallKeySequence(keys); - } -} - -void GLVisWindow::SetGLVisCommand(GLVisCommand* cmd, - communication_thread* cthread) -{ - glvis_command = cmd; - comm_thread = cthread; - use_idle = false; -} - void GLVisWindow::RunVisualization() { visualize = 1; @@ -393,9 +396,6 @@ void GLVisWindow::RunVisualization() #ifndef __EMSCRIPTEN__ wnd->mainLoop(); #endif - delete locscene; - //delete wnd; - wnd = nullptr; } void SendExposeEvent() @@ -1160,7 +1160,7 @@ void GLVisWindow::KeyLeftPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(locscene, 0.05, 0.); + ShiftView(locscene.get(), 0.05, 0.); } else { @@ -1173,7 +1173,7 @@ void GLVisWindow::KeyRightPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(locscene, -0.05, 0.); + ShiftView(locscene.get(), -0.05, 0.); } else { @@ -1186,7 +1186,7 @@ void GLVisWindow::KeyUpPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(locscene, 0., -0.05); + ShiftView(locscene.get(), 0., -0.05); } else { @@ -1199,7 +1199,7 @@ void GLVisWindow::KeyDownPressed(GLenum state) { if (state & KMOD_CTRL) { - ShiftView(locscene, 0., 0.05); + ShiftView(locscene.get(), 0., 0.05); } else { diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index e2865d15..9fcc79ba 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -34,14 +34,15 @@ class GLVisWindow /// Initializes the visualization and some keys. GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly); - void SetVisualizationScene(VisualizationScene * scene, - int view = 3, const char *keys = NULL); + ~GLVisWindow(); - void SetGLVisCommand(GLVisCommand* cmd, communication_thread* cthread); + void InitVisualization(int field_type, StreamState state, + const mfem::Array& input_streams, + bool keep_attr); void SetFont(const std::string& fn); - VisualizationScene* getScene() { return locscene; } + VisualizationScene* getScene() { return locscene.get(); } GlVisFont* getFont() { return &font; } @@ -138,9 +139,10 @@ class GLVisWindow void ThreadsPauseFunc(GLenum); std::unique_ptr wnd; - VisualizationScene* locscene; - GLVisCommand* glvis_command = nullptr; - communication_thread* comm_thread = nullptr; + std::unique_ptr locscene; + std::unique_ptr glvis_command; + std::unique_ptr comm_thread; + StreamState prob_state; bool use_idle = false; // Idle function callbacks diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 5a825270..2886b3ca 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -337,6 +337,127 @@ int StreamState::ReadStream(istream &is, const string &data_type) GridFunction *ProjectVectorFEGridFunction(GridFunction*); +std::unique_ptr +StreamState::CreateVisualizationScene(int field_type) +{ + std::unique_ptr vs; + double mesh_range = -1.0; + if (field_type == 0 || field_type == 2) + { + if (grid_f) + { + grid_f->GetNodalValues(sol); + } + if (mesh->SpaceDimension() == 2) + { + VisualizationSceneSolution *vss; + if (normals.Size() > 0) + { + vss = new VisualizationSceneSolution(*mesh, sol, &normals); + } + else + { + vss = new VisualizationSceneSolution(*mesh, sol); + } + vs.reset(vss); + if (grid_f) + { + vss->SetGridFunction(*grid_f); + } + if (field_type == 2) + { + vss->OrthogonalProjection = 1; + vss->SetLight(false); + vss->Zoom(1.8); + // Use the 'bone' palette when visualizing a 2D mesh only (otherwise + // the 'jet-like' palette is used in 2D, see vssolution.cpp). + vss->GetPalette().SetPalette(4); + } + } + else if (mesh->SpaceDimension() == 3) + { + VisualizationSceneSolution3d *vss = new VisualizationSceneSolution3d(*mesh, sol); + vs.reset(vss); + if (grid_f) + { + vss->SetGridFunction(grid_f.get()); + } + if (field_type == 2) + { + if (mesh->Dimension() == 3) + { + // Use the 'white' palette when visualizing a 3D volume mesh only + vss->GetPalette().SetPalette(11); + vss->SetLightMatIdx(4); + } + else + { + // Use the 'bone' palette when visualizing a surface mesh only + vss->GetPalette().SetPalette(4); + } + // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp + vss->ToggleDrawAxes(); + vss->ToggleDrawMesh(); + } + } + if (field_type == 2) + { + if (grid_f) + { + mesh_range = grid_f->Max() + 1.0; + } + else + { + mesh_range = sol.Max() + 1.0; + } + } + } + else if (field_type == 1) + { + if (mesh->SpaceDimension() == 2) + { + if (grid_f) + { + vs.reset(new VisualizationSceneVector(*grid_f)); + } + else + { + vs.reset(new VisualizationSceneVector(*mesh, solu, solv)); + } + } + else if (mesh->SpaceDimension() == 3) + { + if (grid_f) + { + GridFunction* proj_grid_f = ProjectVectorFEGridFunction(grid_f.get()); + grid_f.reset(proj_grid_f); + vs.reset(new VisualizationSceneVector3d(*proj_grid_f)); + } + else + { + vs.reset(new VisualizationSceneVector3d(*mesh, solu, solv, solw)); + } + } + } + + if (vs) + { + // increase the refinement factors if visualizing a GridFunction + if (grid_f) + { + vs->AutoRefine(); + vs->SetShading(2, true); + } + if (mesh_range > 0.0) + { + vs->SetValueRange(-mesh_range, mesh_range); + vs->SetAutoscale(0); + } + } + return vs; +} + + void StreamState::SetNewMeshAndSolution(StreamState new_state, VisualizationScene* vs) { diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 0b73fc09..8f8377c9 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -35,6 +35,8 @@ struct StreamState int ReadStream(std::istream &is, const std::string &data_type); + std::unique_ptr CreateVisualizationScene(int field_type); + void SetNewMeshAndSolution(StreamState new_state, VisualizationScene* vs); }; diff --git a/lib/threads.cpp b/lib/threads.cpp index dea32e01..85dfd063 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -22,10 +22,9 @@ using namespace std; extern const char *strings_off_on[]; // defined in vsdata.cpp GLVisCommand::GLVisCommand( - VisualizationSceneScalarData **_vs, StreamState& state, bool _keep_attr) - : curr_state(state) + GLVisWindow* wnd, StreamState& state, bool _keep_attr) + : window(wnd), curr_state(state) { - vs = _vs; keep_attr = _keep_attr; pthread_mutex_init(&glvis_mutex, NULL); @@ -78,7 +77,7 @@ int GLVisCommand::signal() return -1; } - SdlWindow *sdl_window = GetAppWindow(); + SdlWindow *sdl_window = window->getSdl(); if (sdl_window) { sdl_window->signalLoop(); @@ -428,6 +427,9 @@ int GLVisCommand::Execute() return -1; } + VisualizationSceneScalarData* vs + = dynamic_cast(window->getScene()); + switch (command) { case NO_COMMAND: @@ -444,12 +446,12 @@ int GLVisCommand::Execute() if (new_state.mesh->SpaceDimension() == curr_state.mesh->SpaceDimension() && new_state.grid_f->VectorDim() == curr_state.grid_f->VectorDim()) { - curr_state.SetNewMeshAndSolution(std::move(new_state), *vs); + curr_state.SetNewMeshAndSolution(std::move(new_state), vs); if (mesh_range > 0.0) { - (*vs)->SetValueRange(-mesh_range, mesh_range); + vs->SetValueRange(-mesh_range, mesh_range); } - MyExpose(); + window->MyExpose(); } else { @@ -458,7 +460,7 @@ int GLVisCommand::Execute() if (autopause) { cout << "Autopause ..." << endl; - GetGLVisWindow()->ThreadsStop(); + window->ThreadsStop(); } break; } @@ -466,7 +468,7 @@ int GLVisCommand::Execute() case SCREENSHOT: { cout << "Command: screenshot: " << flush; - GetGLVisWindow()->Screenshot(screenshot_filename.c_str()); + window->Screenshot(screenshot_filename.c_str()); cout << "-> " << screenshot_filename << endl; break; } @@ -475,15 +477,15 @@ int GLVisCommand::Execute() { cout << "Command: keys: '" << key_commands << "'" << endl; // SendKeySequence(key_commands.c_str()); - GetGLVisWindow()->CallKeySequence(key_commands.c_str()); - MyExpose(); + window->CallKeySequence(key_commands.c_str()); + window->MyExpose(); break; } case WINDOW_SIZE: { cout << "Command: window_size: " << window_w << " x " << window_h << endl; - GetGLVisWindow()->ResizeWindow(window_w, window_h); + window->ResizeWindow(window_w, window_h); break; } @@ -492,14 +494,14 @@ int GLVisCommand::Execute() cout << "Command: window_geometry: " << "@(" << window_x << "," << window_y << ") " << window_w << " x " << window_h << endl; - GetGLVisWindow()->MoveResizeWindow(window_x, window_y, window_w, window_h); + window->MoveResizeWindow(window_x, window_y, window_w, window_h); break; } case WINDOW_TITLE: { cout << "Command: window_title: " << window_title << endl; - GetGLVisWindow()->SetWindowTitle(window_title.c_str()); + window->SetWindowTitle(window_title.c_str()); break; } @@ -507,8 +509,8 @@ int GLVisCommand::Execute() { cout << "Command: plot_caption: " << plot_caption << endl; ::plot_caption = plot_caption; - (*vs)->PrepareCaption(); // turn on or off the caption - MyExpose(); + vs->PrepareCaption(); // turn on or off the caption + window->MyExpose(); break; } @@ -516,16 +518,16 @@ int GLVisCommand::Execute() { cout << "Command: axis_labels: '" << axis_label_x << "' '" << axis_label_y << "' '" << axis_label_z << "'" << endl; - (*vs)->SetAxisLabels(axis_label_x.c_str(), axis_label_y.c_str(), + vs->SetAxisLabels(axis_label_x.c_str(), axis_label_y.c_str(), axis_label_z.c_str()); - MyExpose(); + window->MyExpose(); break; } case PAUSE: { cout << "Command: pause: "; - GetGLVisWindow()->ToggleThreads(); + window->ToggleThreads(); break; } @@ -533,34 +535,34 @@ int GLVisCommand::Execute() { cout << "Command: view: " << view_ang_theta << ' ' << view_ang_phi << endl; - (*vs)->SetView(view_ang_theta, view_ang_phi); - MyExpose(); + vs->SetView(view_ang_theta, view_ang_phi); + window->MyExpose(); break; } case ZOOM: { cout << "Command: zoom: " << zoom_factor << endl; - (*vs)->Zoom(zoom_factor); - MyExpose(); + vs->Zoom(zoom_factor); + window->MyExpose(); break; } case SUBDIVISIONS: { cout << "Command: subdivisions: " << flush; - (*vs)->SetRefineFactors(subdiv_tot, subdiv_bdr); + vs->SetRefineFactors(subdiv_tot, subdiv_bdr); cout << subdiv_tot << ' ' << subdiv_bdr << endl; - MyExpose(); + window->MyExpose(); break; } case VALUE_RANGE: { cout << "Command: valuerange: " << flush; - (*vs)->SetValueRange(val_min, val_max); + vs->SetValueRange(val_min, val_max); cout << val_min << ' ' << val_max << endl; - MyExpose(); + window->MyExpose(); break; } @@ -582,9 +584,9 @@ int GLVisCommand::Execute() } if (s != -1) { - (*vs)->SetShading(s, false); + vs->SetShading(s, false); cout << shading << endl; - MyExpose(); + window->MyExpose(); } else { @@ -597,9 +599,9 @@ int GLVisCommand::Execute() { cout << "Command: viewcenter: " << view_center_x << ' ' << view_center_y << endl; - (*vs)->ViewCenterX = view_center_x; - (*vs)->ViewCenterY = view_center_y; - MyExpose(); + vs->ViewCenterX = view_center_x; + vs->ViewCenterY = view_center_y; + window->MyExpose(); break; } @@ -608,19 +610,19 @@ int GLVisCommand::Execute() cout << "Command: autoscale: " << autoscale_mode; if (autoscale_mode == "off") { - (*vs)->SetAutoscale(0); + vs->SetAutoscale(0); } else if (autoscale_mode == "on") { - (*vs)->SetAutoscale(1); + vs->SetAutoscale(1); } else if (autoscale_mode == "value") { - (*vs)->SetAutoscale(2); + vs->SetAutoscale(2); } else if (autoscale_mode == "mesh") { - (*vs)->SetAutoscale(3); + vs->SetAutoscale(3); } else { @@ -633,18 +635,18 @@ int GLVisCommand::Execute() case PALETTE: { cout << "Command: palette: " << palette << endl; - (*vs)->GetPalette().SetPalette(palette-1); - MyExpose(); + vs->GetPalette().SetPalette(palette-1); + window->MyExpose(); break; } case PALETTE_REPEAT: { cout << "Command: palette_repeat: " << palette_repeat << endl; - (*vs)->GetPalette().SetRepeatTimes(palette_repeat); - (*vs)->GetPalette().Init(); + vs->GetPalette().SetRepeatTimes(palette_repeat); + vs->GetPalette().Init(); - MyExpose(); + window->MyExpose(); break; } @@ -656,8 +658,8 @@ int GLVisCommand::Execute() cout << ' ' << camera[i]; } cout << endl; - (*vs)->cam.Set(camera); - MyExpose(); + vs->cam.Set(camera); + window->MyExpose(); break; } @@ -674,11 +676,11 @@ int GLVisCommand::Execute() cout << "Command: autopause: " << strings_off_on[autopause] << endl; if (autopause) { - GetGLVisWindow()->ThreadsStop(); + window->ThreadsStop(); } else { - GetGLVisWindow()->ThreadsRun(); // probably not needed + window->ThreadsRun(); // probably not needed } break; } @@ -723,11 +725,11 @@ void GLVisCommand::ToggleAutopause() cout << "Autopause: " << strings_off_on[autopause] << endl; if (autopause) { - GetGLVisWindow()->ThreadsStop(); + window->ThreadsStop(); } else { - GetGLVisWindow()->ThreadsRun(); + window->ThreadsRun(); } } @@ -745,7 +747,7 @@ GLVisCommand::~GLVisCommand() } communication_thread::communication_thread(GLVisCommand* parent_cmd, - Array &_is) + const Array &_is) : is(_is), glvis_command(parent_cmd) { new_m = NULL; diff --git a/lib/threads.hpp b/lib/threads.hpp index e809df6f..67d0bd78 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -17,11 +17,13 @@ #include #include +class GLVisWindow; + class GLVisCommand { private: // Pointers to global GLVis data - VisualizationSceneScalarData **vs; + GLVisWindow* window; StreamState& curr_state; bool keep_attr; @@ -90,7 +92,7 @@ class GLVisCommand public: // called by the main execution thread - GLVisCommand(VisualizationSceneScalarData **_vs, + GLVisCommand(GLVisWindow* parent, StreamState& thread_state, bool _keep_attr); // to be used by the main execution (visualization) thread @@ -139,7 +141,7 @@ class communication_thread { private: // streams to read data from - Array &is; + Array is; GLVisCommand* glvis_command; @@ -164,7 +166,7 @@ class communication_thread static void *execute(void *); public: - communication_thread(GLVisCommand* parent_cmd, Array &_is); + communication_thread(GLVisCommand* parent_cmd, const Array &_is); ~communication_thread(); }; From d0822194817ba609af4629bdc6ed8ab4068bb8e5 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 4 Feb 2021 12:22:21 -0800 Subject: [PATCH 22/42] JS-related build fixes --- glvis.cpp | 24 ------ lib/aux_js.cpp | 183 ++---------------------------------------- lib/aux_vis.cpp | 22 +++++ lib/aux_vis.hpp | 4 +- lib/stream_reader.cpp | 91 ++++++++++++++------- lib/stream_reader.hpp | 9 ++- lib/threads.cpp | 4 +- 7 files changed, 101 insertions(+), 236 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 02772703..59c3f29e 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -107,8 +107,6 @@ int ReadInputStreams(); void CloseInputStreams(bool); -GridFunction *ProjectVectorFEGridFunction(GridFunction*); - // Visualize the data in the global variables mesh, sol/grid_f, etc // 0 - scalar data, 1 - vector data, 2 - mesh only, (-1) - unknown bool GLVisInitVis(int field_type) @@ -1558,25 +1556,3 @@ void CloseInputStreams(bool parent) } input_streams.DeleteAll(); } - -// Replace a given VectorFiniteElement-based grid function (e.g. from a Nedelec -// or Raviart-Thomas space) with a discontinuous piece-wise polynomial Cartesian -// product vector grid function of the same order. -GridFunction *ProjectVectorFEGridFunction(GridFunction *gf) -{ - if ((gf->VectorDim() == 3) && (gf->FESpace()->GetVDim() == 1)) - { - int p = gf->FESpace()->GetOrder(0); - cout << "Switching to order " << p - << " discontinuous vector grid function..." << endl; - int dim = gf->FESpace()->GetMesh()->Dimension(); - FiniteElementCollection *d_fec = new L2_FECollection(p, dim, 1); - FiniteElementSpace *d_fespace = - new FiniteElementSpace(gf->FESpace()->GetMesh(), d_fec, 3); - GridFunction *d_gf = new GridFunction(d_fespace); - d_gf->MakeOwner(d_fec); - gf->ProjectVectorFieldOn(*d_gf); - return d_gf; - } - return gf; -} diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 19422def..a57fe9b4 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -57,10 +57,7 @@ bool startVisualization(const std::string input, const std::string data_type, std::stringstream ss(input); // 0 - scalar data, 1 - vector data, 2 - mesh only, (-1) - unknown - const int field_type = ReadStream(ss, data_type); - - // reset antialiasing - GetAppWindow()->getRenderer().setAntialiasing(0); + const int field_type = stream_state.ReadStream(ss, data_type); std::string line; double minv = 0.0, maxv = 0.0; @@ -108,133 +105,7 @@ bool startVisualization(const std::string input, const std::string data_type, vs = nullptr; double mesh_range = -1.0; - if (field_type == 0 || field_type == 2) - { - if (stream_state.grid_f) - { - stream_state.grid_f->GetNodalValues(stream_state.sol); - } - if (stream_state.mesh->SpaceDimension() == 2) - { - VisualizationSceneSolution * vss; - if (stream_state.normals.Size() > 0) - { - vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, - &stream_state.normals); - } - else - { - vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol); - } - if (stream_state.grid_f) - { - vss->SetGridFunction(*stream_state.grid_f); - } - if (field_type == 2) - { - vs->OrthogonalProjection = 1; - vs->SetLight(0); - vs->Zoom(1.8); - // Use the 'bone' palette when visualizing a 2D mesh only (otherwise - // the 'jet-like' palette is used in 2D, see vssolution.cpp). - vs->GetPalette().SetPalette(4); - } - } - else if (stream_state.mesh->SpaceDimension() == 3) - { - VisualizationSceneSolution3d * vss; - vs = vss = new VisualizationSceneSolution3d(*stream_state.mesh, - stream_state.sol); - if (stream_state.grid_f) - { - vss->SetGridFunction(stream_state.grid_f); - } - if (field_type == 2) - { - if (stream_state.mesh->Dimension() == 3) - { - // Use the 'white' palette when visualizing a 3D volume mesh only - // paletteSet(4); - vss->GetPalette().SetPalette(11); - vss->SetLightMatIdx(4); - } - else - { - // Use the 'bone' palette when visualizing a surface mesh only - // (the same as when visualizing a 2D mesh only) - vss->GetPalette().SetPalette(4); - } - // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp - - vss->ToggleDrawAxes(); - vss->ToggleDrawMesh(); - } - } - if (field_type == 2) - { - if (stream_state.grid_f) - { - mesh_range = stream_state.grid_f->Max() + 1.0; - } - else - { - mesh_range = stream_state.sol.Max() + 1.0; - } - } - } - else if (field_type == 1) - { - if (stream_state.mesh->SpaceDimension() == 2) - { - if (stream_state.grid_f) - { - vs = new VisualizationSceneVector(*stream_state.grid_f); - } - else - { - vs = new VisualizationSceneVector(*stream_state.mesh, stream_state.solu, - stream_state.solv); - } - } - else if (stream_state.mesh->SpaceDimension() == 3) - { - if (stream_state.grid_f) - { - stream_state.grid_f = ProjectVectorFEGridFunction(stream_state.grid_f); - vs = new VisualizationSceneVector3d(*stream_state.grid_f); - } - else - { - vs = new VisualizationSceneVector3d(*stream_state.mesh, stream_state.solu, - stream_state.solv, stream_state.solw); - } - } - } - - if (vs) - { - // increase the refinement factors if visualizing a GridFunction - if (stream_state.grid_f) - { - vs->AutoRefine(); - vs->SetShading(2, true); - } - if (mesh_range > 0.0) - { - vs->SetValueRange(-mesh_range, mesh_range); - vs->SetAutoscale(0); - } - if (stream_state.mesh->SpaceDimension() == 2 && field_type == 2) - { - mainWindow->SetVisualizationScene(vs, 2); - } - else - { - mainWindow->SetVisualizationScene(vs, 3); - } - } - - mainWindow->CallKeySequence(stream_state.keys.c_str()); + mainWindow->InitVisualization(field_type, std::move(stream_state)); if (minv || maxv) { @@ -256,64 +127,26 @@ int updateVisualization(std::string data_type, std::string stream) return 1; } + StreamState new_state; + new_state.ReadStream(ss, data_type); + + auto * new_m = new Mesh(ss, 1, 0, stream_state.fix_elem_orient); auto * new_g = new GridFunction(new_m, ss); double mesh_range = -1.0; - if (new_m->SpaceDimension() == stream_state.mesh->SpaceDimension() && - new_g->VectorDim() == stream_state.grid_f->VectorDim()) + if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) { - if (new_m->SpaceDimension() == 2) - { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution *vss = - dynamic_cast(vs); - new_g->GetNodalValues(stream_state.sol); - vss->NewMeshAndSolution(new_m, &stream_state.sol, new_g); - } - else - { - VisualizationSceneVector *vsv = - dynamic_cast(vs); - vsv->NewMeshAndSolution(*new_g); - } - } - else - { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution3d *vss = - dynamic_cast(vs); - new_g->GetNodalValues(stream_state.sol); - vss->NewMeshAndSolution(new_m, &stream_state.sol, new_g); - } - else - { - new_g = ProjectVectorFEGridFunction(new_g); - VisualizationSceneVector3d *vss = - dynamic_cast(vs); - vss->NewMeshAndSolution(new_m, new_g); - } - } if (mesh_range > 0.0) { vs->SetValueRange(-mesh_range, mesh_range); } - - delete stream_state.grid_f; - stream_state.grid_f = new_g; - delete stream_state.mesh; - stream_state.mesh = new_m; - - SendExposeEvent(); + mainWindow->SendExposeEvent(); return 0; } else { cout << "Stream: field type does not match!" << endl; - delete new_g; - delete new_m; return 1; } } diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 76aeb0f4..be62d0e4 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -226,10 +226,12 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega GLVisWindow::~GLVisWindow() { +#ifndef __EMSCRIPTEN__ if (glvis_command) { glvis_command->Terminate(); } +#endif } void GLVisWindow::InitVisualization(int field_type, StreamState state, @@ -237,11 +239,13 @@ void GLVisWindow::InitVisualization(int field_type, StreamState state, bool keep_attr) { prob_state = std::move(state); +#ifndef __EMSCRIPTEN__ if (input_streams.Size() > 0) { glvis_command.reset(new GLVisCommand(this, prob_state, keep_attr)); comm_thread.reset(new communication_thread(glvis_command.get(), input_streams)); } +#endif locscene = prob_state.CreateVisualizationScene(field_type); @@ -260,6 +264,11 @@ void GLVisWindow::InitVisualization(int field_type, StreamState state, { AddIdleFunc(::MainLoop); } + + if (state.keys == "") + { + CallKeySequence(state.keys.c_str()); + } } void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)()) @@ -497,6 +506,7 @@ bool GLVisWindow::CommunicationIdleFunc() bool GLVisWindow::MainIdleFunc() { bool sleep = true; +#ifndef __EMSCRIPTEN__ if (glvis_command && visualize == 1 && !(idle_funcs.Size() > 0 && use_idle)) { @@ -519,6 +529,18 @@ bool GLVisWindow::MainIdleFunc() sleep = false; } use_idle = !use_idle; +#else + if (idle_funcs.Size() > 0) + { + last_idle_func = (last_idle_func + 1) % idle_funcs.Size(); + if (idle_funcs[last_idle_func]) + { + (*idle_funcs[last_idle_func])(this); + } + // Continue executing idle functions + sleep = false; + } +#endif return sleep; } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 9fcc79ba..d7c1c7e1 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -37,8 +37,8 @@ class GLVisWindow ~GLVisWindow(); void InitVisualization(int field_type, StreamState state, - const mfem::Array& input_streams, - bool keep_attr); + const mfem::Array& input_streams = {}, + bool keep_attr = false); void SetFont(const std::string& fn); diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 2886b3ca..4bd9e676 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -335,7 +335,27 @@ int StreamState::ReadStream(istream &is, const string &data_type) return field_type; } -GridFunction *ProjectVectorFEGridFunction(GridFunction*); +// Replace a given VectorFiniteElement-based grid function (e.g. from a Nedelec +// or Raviart-Thomas space) with a discontinuous piece-wise polynomial Cartesian +// product vector grid function of the same order. +GridFunction *ProjectVectorFEGridFunction(GridFunction *gf) +{ + if ((gf->VectorDim() == 3) && (gf->FESpace()->GetVDim() == 1)) + { + int p = gf->FESpace()->GetOrder(0); + cout << "Switching to order " << p + << " discontinuous vector grid function..." << endl; + int dim = gf->FESpace()->GetMesh()->Dimension(); + FiniteElementCollection *d_fec = new L2_FECollection(p, dim, 1); + FiniteElementSpace *d_fespace = + new FiniteElementSpace(gf->FESpace()->GetMesh(), d_fec, 3); + GridFunction *d_gf = new GridFunction(d_fespace); + d_gf->MakeOwner(d_fec); + gf->ProjectVectorFieldOn(*d_gf); + return d_gf; + } + return gf; +} std::unique_ptr StreamState::CreateVisualizationScene(int field_type) @@ -458,47 +478,56 @@ StreamState::CreateVisualizationScene(int field_type) } -void StreamState::SetNewMeshAndSolution(StreamState new_state, +bool StreamState::SetNewMeshAndSolution(StreamState new_state, VisualizationScene* vs) { - std::unique_ptr new_m = std::move(new_state.mesh); - std::unique_ptr new_g = std::move(new_state.grid_f); - if (new_m->SpaceDimension() == 2) + if (new_state.mesh->SpaceDimension() == mesh->SpaceDimension() && + new_state.grid_f->VectorDim() == grid_f->VectorDim()) { - if (new_g->VectorDim() == 1) + std::unique_ptr new_m = std::move(new_state.mesh); + std::unique_ptr new_g = std::move(new_state.grid_f); + if (new_m->SpaceDimension() == 2) { - VisualizationSceneSolution *vss = - dynamic_cast(vs); - new_g->GetNodalValues(sol); - vss->NewMeshAndSolution(new_m.get(), &sol, new_g.get()); + if (new_g->VectorDim() == 1) + { + VisualizationSceneSolution *vss = + dynamic_cast(vs); + new_g->GetNodalValues(sol); + vss->NewMeshAndSolution(new_m.get(), &sol, new_g.get()); + } + else + { + VisualizationSceneVector *vsv = + dynamic_cast(vs); + vsv->NewMeshAndSolution(*new_g); + } } else { - VisualizationSceneVector *vsv = - dynamic_cast(vs); - vsv->NewMeshAndSolution(*new_g); + if (new_g->VectorDim() == 1) + { + VisualizationSceneSolution3d *vss = + dynamic_cast(vs); + new_g->GetNodalValues(sol); + vss->NewMeshAndSolution(new_m.get(), &sol, new_g.get()); + } + else + { + GridFunction* proj_new_g = ProjectVectorFEGridFunction(new_g.get()); + new_g.reset(proj_new_g); + + VisualizationSceneVector3d *vss = + dynamic_cast(vs); + vss->NewMeshAndSolution(new_m.get(), proj_new_g); + } } + grid_f = std::move(new_g); + mesh = std::move(new_m); + return true; } else { - if (new_g->VectorDim() == 1) - { - VisualizationSceneSolution3d *vss = - dynamic_cast(vs); - new_g->GetNodalValues(sol); - vss->NewMeshAndSolution(new_m.get(), &sol, new_g.get()); - } - else - { - GridFunction* proj_new_g = ProjectVectorFEGridFunction(new_g.get()); - new_g.reset(proj_new_g); - - VisualizationSceneVector3d *vss = - dynamic_cast(vs); - vss->NewMeshAndSolution(new_m.get(), proj_new_g); - } + return false; } - grid_f = std::move(new_g); - mesh = std::move(new_m); } diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 8f8377c9..41648b57 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -37,7 +37,14 @@ struct StreamState std::unique_ptr CreateVisualizationScene(int field_type); - void SetNewMeshAndSolution(StreamState new_state, + /// Sets a new mesh and solution from another StreamState object, and + /// updates the given VisualizationScene pointer with the new data. + /// + /// Mesh space and grid function dimensions must both match the original + /// dimensions of the current StreamState. If there is a mismatch in either + /// value, the function will return false, and the mesh/solution will not be + /// updated. + bool SetNewMeshAndSolution(StreamState new_state, VisualizationScene* vs); }; diff --git a/lib/threads.cpp b/lib/threads.cpp index 85dfd063..2a96f538 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -443,10 +443,8 @@ int GLVisCommand::Execute() new_state.SetMeshSolution(false); mesh_range = new_state.grid_f->Max() + 1.0; } - if (new_state.mesh->SpaceDimension() == curr_state.mesh->SpaceDimension() && - new_state.grid_f->VectorDim() == curr_state.grid_f->VectorDim()) + if (curr_state.SetNewMeshAndSolution(std::move(new_state), vs)) { - curr_state.SetNewMeshAndSolution(std::move(new_state), vs); if (mesh_range > 0.0) { vs->SetValueRange(-mesh_range, mesh_range); From b069e32b09257633857145b486bb54e0884b3e21 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 4 Feb 2021 15:15:30 -0800 Subject: [PATCH 23/42] Replace pthreads code with c++ standard library threads --- lib/threads.cpp | 51 ++++++++++++++++++++----------------------------- lib/threads.hpp | 24 +++++++++-------------- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/lib/threads.cpp b/lib/threads.cpp index 2a96f538..eaa04d02 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -27,8 +27,6 @@ GLVisCommand::GLVisCommand( { keep_attr = _keep_attr; - pthread_mutex_init(&glvis_mutex, NULL); - pthread_cond_init(&glvis_cond, NULL); num_waiting = 0; terminating = false; if (pipe(pfd) == -1) @@ -47,25 +45,22 @@ GLVisCommand::GLVisCommand( int GLVisCommand::lock() { int my_id; - pthread_mutex_lock(&glvis_mutex); + unique_lock scope_lock(glvis_mutex); if (terminating) { - pthread_mutex_unlock(&glvis_mutex); return -1; } my_id = num_waiting++; while (my_id > 0) { - pthread_cond_wait(&glvis_cond, &glvis_mutex); + glvis_cond.wait(scope_lock); if (terminating) { num_waiting--; - pthread_mutex_unlock(&glvis_mutex); return -1; } my_id--; } - pthread_mutex_unlock(&glvis_mutex); return 0; } @@ -88,13 +83,12 @@ int GLVisCommand::signal() void GLVisCommand::unlock() { - pthread_mutex_lock(&glvis_mutex); + lock_guard scope_lock(glvis_mutex); num_waiting--; if (num_waiting > 0) { - pthread_cond_broadcast(&glvis_cond); + glvis_cond.notify_all(); } - pthread_mutex_unlock(&glvis_mutex); } int GLVisCommand::NewMeshAndSolution(std::unique_ptr _new_m, @@ -695,26 +689,28 @@ void GLVisCommand::Terminate() char c; int n = read(pfd[0], &c, 1); - pthread_mutex_lock(&glvis_mutex); - terminating = true; - pthread_mutex_unlock(&glvis_mutex); + { + lock_guard scope_lock(glvis_mutex); + terminating = true; + } if (n == 1 && c == 's') { switch (command) { case NEW_MESH_AND_SOLUTION: - stream_state.mesh.release(); - stream_state.grid_f.release(); + new_state.mesh.release(); + new_state.grid_f.release(); break; } unlock(); } - pthread_mutex_lock(&glvis_mutex); - if (num_waiting > 0) { - pthread_cond_broadcast(&glvis_cond); + lock_guard scope_lock(glvis_mutex); + if (num_waiting > 0) + { + glvis_cond.notify_all(); + } } - pthread_mutex_unlock(&glvis_mutex); } void GLVisCommand::ToggleAutopause() @@ -740,8 +736,6 @@ GLVisCommand::~GLVisCommand() } close(pfd[0]); close(pfd[1]); - pthread_cond_destroy(&glvis_cond); - pthread_mutex_destroy(&glvis_mutex); } communication_thread::communication_thread(GLVisCommand* parent_cmd, @@ -753,7 +747,7 @@ communication_thread::communication_thread(GLVisCommand* parent_cmd, if (is.Size() > 0) { - pthread_create(&tid, NULL, communication_thread::execute, this); + tid = std::thread(&communication_thread::execute, this); } } @@ -761,8 +755,8 @@ communication_thread::~communication_thread() { if (is.Size() > 0) { - pthread_cancel(tid); - pthread_join(tid, NULL); + terminate_thread = true; + tid.join(); } } @@ -775,9 +769,9 @@ void *communication_thread::execute(void *p) while (1) { - *_this->is[0] >> ws; // thread cancellation point - - _this->cancel_off(); + *_this->is[0] >> ws; + // thread cancellation point + if (_this->terminate_thread) { break; } *_this->is[0] >> _this->ident; if (!(*_this->is[0])) @@ -1242,8 +1236,6 @@ void *communication_thread::execute(void *p) { cout << "Stream: unknown command: " << _this->ident << endl; } - - _this->cancel_on(); } cout << "Stream: end of input." << endl; @@ -1257,7 +1249,6 @@ void *communication_thread::execute(void *p) isock->close(); } } - _this->cancel_on(); return p; } diff --git a/lib/threads.hpp b/lib/threads.hpp index 67d0bd78..1f60c84f 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -15,7 +15,8 @@ #include "vsdata.hpp" #include "stream_reader.hpp" #include -#include +#include +#include class GLVisWindow; @@ -27,8 +28,9 @@ class GLVisCommand StreamState& curr_state; bool keep_attr; - pthread_mutex_t glvis_mutex; - pthread_cond_t glvis_cond; + std::mutex glvis_mutex; + std::condition_variable glvis_cond; + int num_waiting; bool terminating; int pfd[2]; // pfd[0] -- reading, pfd[1] -- writing @@ -150,18 +152,10 @@ class communication_thread std::unique_ptr new_g; std::string ident; - // thread id - pthread_t tid; - - static void cancel_off() - { - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - } - - static void cancel_on() - { - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - } + // thread object + std::thread tid; + // signal for thread cancellation + std::atomic terminate_thread {false}; static void *execute(void *); From 84ea36e59f84a25523fba76fe66a246665bc6f4e Mon Sep 17 00:00:00 2001 From: Max Yang Date: Fri, 5 Feb 2021 10:08:33 -0800 Subject: [PATCH 24/42] Remove some more global references to stream_state --- glvis.cpp | 146 +++++++++++++++++++----------------------- lib/aux_js.cpp | 1 + lib/aux_vis.hpp | 2 + lib/stream_reader.cpp | 6 +- lib/stream_reader.hpp | 5 +- lib/threads.cpp | 3 +- 6 files changed, 74 insertions(+), 89 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 59c3f29e..0eb39a8a 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -43,8 +43,6 @@ const char *arg_keys = string_none; int np = 0; int pad_digits = 6; int gf_component = -1; -bool & fix_elem_orient = stream_state.fix_elem_orient; -bool & save_coloring = stream_state.save_coloring; bool keep_attr = false; int window_x = 0; // not a command line option int window_y = 0; // not a command line option @@ -59,19 +57,8 @@ string extra_caption; // Global variables int input = 1; -std::unique_ptr& mesh = stream_state.mesh; -Vector & sol = stream_state.sol; -Vector & solu = stream_state.solu; -Vector & solv = stream_state.solv; -Vector & solw = stream_state.solw; -Vector & normals = stream_state.normals; -std::unique_ptr& grid_f = stream_state.grid_f; -int & is_gf = stream_state.is_gf; -std::string & keys = stream_state.keys; +StreamState stream_state; GLVisWindow * mainWindow = nullptr; -VisualizationSceneScalarData *vs = NULL; -GLVisCommand *glvis_command = nullptr; -communication_thread *comm_thread = NULL; GeometryRefiner GLVisGeometryRefiner; @@ -91,19 +78,19 @@ extern char **environ; void PrintSampleUsage(ostream &out); // read the mesh and the solution from a file -void ReadSerial(); +void ReadSerial(StreamState& state); // choose grid function component and set the input flag -void SetGridFunction(); +void SetGridFunction(StreamState& state); // read the mesh and the solution from multiple files -void ReadParallel(); +void ReadParallel(StreamState& state); int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, const char *sol_prefix, StreamState& state, int keep_attr); -int ReadInputStreams(); +int ReadInputStreams(StreamState& state); void CloseInputStreams(bool); @@ -143,10 +130,6 @@ bool GLVisInitVis(int field_type) mainWindow->InitVisualization(field_type, std::move(stream_state), input_streams, keep_attr); - if (keys != "") - { - mainWindow->CallKeySequence(keys.c_str()); - } return true; } @@ -172,7 +155,7 @@ int ScriptReadSolution(istream &scr, StreamState& state) cout << "Can not open mesh file: " << mword << endl; return 1; } - state.mesh.reset(new Mesh(imesh, 1, 0, fix_elem_orient)); + state.mesh.reset(new Mesh(imesh, 1, 0, state.fix_elem_orient)); // read the solution (GridFunction) scr >> ws >> sword; @@ -248,7 +231,7 @@ int ScriptReadDisplMesh(istream &scr, StreamState& state) return 1; } cout << word << endl; - meshstate.mesh.reset(new Mesh(imesh, 1, 0, fix_elem_orient)); + meshstate.mesh.reset(new Mesh(imesh, 1, 0, state.fix_elem_orient)); } meshstate.Extrude1DMeshAndSolution(); Mesh* const m = meshstate.mesh.get(); @@ -302,6 +285,11 @@ void ExecuteScriptCommand(GLVisWindow* wnd) return; } + VisualizationSceneScalarData* vs + = static_cast(wnd->getScene()); + + StreamState& state = wnd->getStreamState(); + istream &scr = *script; string word; int done_one_command = 0; @@ -367,10 +355,8 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } } - if (new_state.mesh->SpaceDimension() == mesh->SpaceDimension() && - new_state.grid_f->VectorDim() == grid_f->VectorDim()) + if (state.SetNewMeshAndSolution(std::move(new_state), vs)) { - stream_state.SetNewMeshAndSolution(std::move(new_state), vs); wnd->MyExpose(); } else @@ -541,10 +527,10 @@ void ExecuteScriptCommand(GLVisWindow* wnd) } else if (word == "keys") { - scr >> keys; - cout << "Script: keys: '" << keys << "'" << endl; + scr >> state.keys; + cout << "Script: keys: '" << state.keys << "'" << endl; // SendKeySequence(keys.c_str()); - CallKeySequence(keys.c_str()); + wnd->CallKeySequence(state.keys.c_str()); wnd->MyExpose(); } else if (word == "palette") @@ -724,7 +710,7 @@ void PlayScript(istream &scr) { return; } - if (mesh) + if (stream_state.mesh) { break; } @@ -737,9 +723,9 @@ void PlayScript(istream &scr) scr_level = scr_running = 0; script = &scr; - keys.clear(); + stream_state.keys.clear(); - if (GLVisInitVis((grid_f->VectorDim() == 1) ? 0 : 1)) + if (GLVisInitVis((stream_state.grid_f->VectorDim() == 1) ? 0 : 1)) { mainWindow->AddWindowEvent(SDLK_SPACE, ScriptControl, false); GLVisStartVis(); @@ -789,7 +775,7 @@ int main (int argc, char *argv[]) "Run a GLVis script file."); args.AddOption(&arg_keys, "-k", "--keys", "Execute key shortcut commands in the GLVis window."); - args.AddOption(&fix_elem_orient, "-fo", "--fix-orientations", + args.AddOption(&stream_state.fix_elem_orient, "-fo", "--fix-orientations", "-no-fo", "--dont-fix-orientations", "Attempt to fix the orientations of inverted elements."); args.AddOption(&keep_attr, "-a", "--real-attributes", @@ -799,7 +785,7 @@ int main (int argc, char *argv[]) args.AddOption(&geom_ref_type, "-grt", "--geometry-refiner-type", "Set of points to use when refining geometry:" " 3 = uniform, 1 = Gauss-Lobatto, (see mfem::Quadrature1D)."); - args.AddOption(&save_coloring, "-sc", "--save-coloring", + args.AddOption(&stream_state.save_coloring, "-sc", "--save-coloring", "-no-sc", "--dont-save-coloring", "Save the mesh coloring generated when opening only a mesh."); args.AddOption(&portnum, "-p", "--listen-port", @@ -872,7 +858,7 @@ int main (int argc, char *argv[]) if (gfunc_file != string_none) { sol_file = gfunc_file; - is_gf = 255; + stream_state.is_gf = 255; } if (np > 0) { @@ -880,7 +866,7 @@ int main (int argc, char *argv[]) } if (arg_keys != string_none) { - keys = arg_keys; + stream_state.keys = arg_keys; } if (multisample != GetMultisample()) { @@ -937,7 +923,7 @@ int main (int argc, char *argv[]) // print help for wrong input if (!(input == 1 || input == 3 || input == 7 || input == 11 || input == 259 || - (is_gf && (input == 3 || input == 259)))) + (stream_state.is_gf && (input == 3 || input == 259)))) { cout << "Invalid combination of mesh/solution options!\n\n"; PrintSampleUsage(cout); @@ -1127,12 +1113,12 @@ int main (int argc, char *argv[]) } else { - ReadInputStreams(); + ReadInputStreams(stream_state); CloseInputStreams(false); ofs.precision(8); ofs << "solution\n"; - mesh->Print(ofs); - grid_f->Save(ofs); + stream_state.mesh->Print(ofs); + stream_state.grid_f->Save(ofs); } ofs.close(); cout << "Data saved in " << tmp_file << endl; @@ -1174,7 +1160,7 @@ int main (int argc, char *argv[]) else { delete isock; - ft = ReadInputStreams(); + ft = ReadInputStreams(stream_state); } if (GLVisInitVis(ft)) { @@ -1203,11 +1189,11 @@ int main (int argc, char *argv[]) { if (input & 256) { - ReadParallel(); + ReadParallel(stream_state); } else { - ReadSerial(); + ReadSerial(stream_state); } bool use_vector_soln = (input & 8); @@ -1248,7 +1234,7 @@ void PrintSampleUsage(ostream &out) } -void ReadSerial() +void ReadSerial(StreamState& state) { // get the mesh from a file named_ifgzstream meshin(mesh_file); @@ -1258,9 +1244,9 @@ void ReadSerial() exit(1); } - stream_state.mesh.reset(new Mesh(meshin, 1, 0, fix_elem_orient)); + state.mesh.reset(new Mesh(meshin, 1, 0, state.fix_elem_orient)); - if (is_gf || (input & 4) || (input & 8)) + if (state.is_gf || (input & 4) || (input & 8)) { // get the solution from file bool freesolin = false; @@ -1280,25 +1266,25 @@ void ReadSerial() } } - if (is_gf) + if (state.is_gf) { - stream_state.grid_f.reset(new GridFunction(mesh.get(), *solin)); - SetGridFunction(); + state.grid_f.reset(new GridFunction(state.mesh.get(), *solin)); + SetGridFunction(state); } else if (input & 4) { // get rid of NetGen's info line char buff[128]; solin->getline(buff,128); - sol.Load(*solin, mesh->GetNV()); + state.sol.Load(*solin, state.mesh->GetNV()); } else if (input & 8) { - solu.Load(*solin, mesh->GetNV()); - solv.Load(*solin, mesh->GetNV()); - if (mesh->SpaceDimension() == 3) + state.solu.Load(*solin, state.mesh->GetNV()); + state.solv.Load(*solin, state.mesh->GetNV()); + if (state.mesh->SpaceDimension() == 3) { - solw.Load(*solin, mesh->GetNV()); + state.solw.Load(*solin, state.mesh->GetNV()); } } if (freesolin) @@ -1308,37 +1294,37 @@ void ReadSerial() } else { - stream_state.SetMeshSolution(save_coloring); + state.SetMeshSolution(); } - stream_state.Extrude1DMeshAndSolution(); + state.Extrude1DMeshAndSolution(); } -void SetGridFunction() +void SetGridFunction(StreamState& state) { if (gf_component != -1) { - if (gf_component < 0 || gf_component >= grid_f->VectorDim()) + if (gf_component < 0 || gf_component >= state.grid_f->VectorDim()) { cerr << "Invalid component " << gf_component << '.' << endl; exit(1); } - FiniteElementSpace *ofes = grid_f->FESpace(); + FiniteElementSpace *ofes = state.grid_f->FESpace(); FiniteElementCollection *fec = FiniteElementCollection::New(ofes->FEColl()->Name()); - FiniteElementSpace *fes = new FiniteElementSpace(mesh.get(), fec); + FiniteElementSpace *fes = new FiniteElementSpace(state.mesh.get(), fec); GridFunction *new_gf = new GridFunction(fes); new_gf->MakeOwner(fec); for (int i = 0; i < new_gf->Size(); i++) { - (*new_gf)(i) = (*grid_f)(ofes->DofToVDof(i, gf_component)); + (*new_gf)(i) = (*state.grid_f)(ofes->DofToVDof(i, gf_component)); } - stream_state.grid_f.reset(new_gf); + state.grid_f.reset(new_gf); } - if (grid_f->VectorDim() == 1) + if (state.grid_f->VectorDim() == 1) { - grid_f->GetNodalValues(sol); + state.grid_f->GetNodalValues(state.sol); input |= 4; } else @@ -1348,26 +1334,26 @@ void SetGridFunction() } -void ReadParallel() +void ReadParallel(StreamState& state) { int err; - if (is_gf) + if (state.is_gf) { err = ReadParMeshAndGridFunction(np, mesh_file, sol_file, - stream_state, keep_attr); + state, keep_attr); if (!err) { - SetGridFunction(); + SetGridFunction(state); } } else { err = ReadParMeshAndGridFunction(np, mesh_file, NULL, - stream_state, keep_attr); + state, keep_attr); if (!err) { - stream_state.SetMeshSolution(save_coloring); + state.SetMeshSolution(); } } @@ -1376,7 +1362,7 @@ void ReadParallel() exit(1); } - stream_state.Extrude1DMeshAndSolution(); + state.Extrude1DMeshAndSolution(); } int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, @@ -1411,7 +1397,7 @@ int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, break; } - mesh_array[p] = new Mesh(meshfile, 1, 0, fix_elem_orient); + mesh_array[p] = new Mesh(meshfile, 1, 0, state.fix_elem_orient); if (!keep_attr) { @@ -1470,7 +1456,7 @@ int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, return err; } -int ReadInputStreams() +int ReadInputStreams(StreamState& state) { int nproc = input_streams.Size(); Array mesh_array(nproc); @@ -1491,7 +1477,7 @@ int ReadInputStreams() #ifdef GLVIS_DEBUG cout << " type " << data_type << " ... " << flush; #endif - mesh_array[p] = new Mesh(isock, 1, 0, fix_elem_orient); + mesh_array[p] = new Mesh(isock, 1, 0, state.fix_elem_orient); if (!keep_attr) { // set element and boundary attributes to proc+1 @@ -1520,16 +1506,16 @@ int ReadInputStreams() mfem_error("Input streams contain a mixture of data types!"); } - stream_state.mesh.reset(new Mesh(mesh_array, nproc)); + state.mesh.reset(new Mesh(mesh_array, nproc)); if (gf_count == 0) { - stream_state.SetMeshSolution(save_coloring); + state.SetMeshSolution(); field_type = 2; } else { - stream_state.grid_f.reset(new GridFunction(mesh.get(), gf_array, nproc)); - field_type = (grid_f->VectorDim() == 1) ? 0 : 1; + state.grid_f.reset(new GridFunction(state.mesh.get(), gf_array, nproc)); + field_type = (state.grid_f->VectorDim() == 1) ? 0 : 1; } for (int p = 0; p < nproc; p++) @@ -1538,7 +1524,7 @@ int ReadInputStreams() delete gf_array[nproc-1-p]; } - stream_state.Extrude1DMeshAndSolution(); + state.Extrude1DMeshAndSolution(); return field_type; } diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index a57fe9b4..c4656748 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -21,6 +21,7 @@ std::string extra_caption; // used in extern context mfem::GeometryRefiner GLVisGeometryRefiner; // used in extern context static VisualizationSceneScalarData * vs = nullptr; +StreamState stream_state; GLVisWindow * mainWindow = nullptr; namespace js diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index d7c1c7e1..8970e6a9 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -48,6 +48,8 @@ class GLVisWindow SdlWindow* getSdl() { return wnd.get(); } + StreamState& getStreamState() { return prob_state; } + /// Start the infinite visualization loop. void RunVisualization(); diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index 4bd9e676..de83c767 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -15,8 +15,6 @@ using namespace std; using namespace mfem; -StreamState stream_state; - void StreamState::Extrude1DMeshAndSolution() { if (mesh->Dimension() != 1 || mesh->SpaceDimension() != 1) @@ -63,7 +61,7 @@ void StreamState::Extrude1DMeshAndSolution() } -void StreamState::SetMeshSolution(bool save_coloring) +void StreamState::SetMeshSolution() { if (1) // checkerboard solution { @@ -202,7 +200,7 @@ int StreamState::ReadStream(istream &is, const string &data_type) else if (data_type == "mesh") { mesh.reset(new Mesh(is, 1, 0, fix_elem_orient)); - SetMeshSolution(save_coloring); + SetMeshSolution(); field_type = 2; } else if (data_type == "raw_scalar_2d") diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 41648b57..9c54eab3 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -31,7 +31,7 @@ struct StreamState void Extrude1DMeshAndSolution(); /// Set a (checkerboard) solution when only the mesh is given - void SetMeshSolution(bool save_coloring); + void SetMeshSolution(); int ReadStream(std::istream &is, const std::string &data_type); @@ -48,8 +48,5 @@ struct StreamState VisualizationScene* vs); }; -/// Singleton holding the current stream content (defined in steam_reader.cpp) -extern StreamState stream_state; - #endif // GLVIS_STREAM_READER_HPP diff --git a/lib/threads.cpp b/lib/threads.cpp index eaa04d02..0b87c7f2 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -434,7 +434,8 @@ int GLVisCommand::Execute() double mesh_range = -1.0; if (!new_state.grid_f) { - new_state.SetMeshSolution(false); + new_state.save_coloring = false; + new_state.SetMeshSolution(); mesh_range = new_state.grid_f->Max() + 1.0; } if (curr_state.SetNewMeshAndSolution(std::move(new_state), vs)) From cdbcaf1aff1898ff9cb2246a30ca9021e28ba46e Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 10 Feb 2021 10:32:27 -0800 Subject: [PATCH 25/42] Remove global vsdata dependence from Plane class --- lib/vsdata.cpp | 9 +++++---- lib/vsdata.hpp | 3 ++- lib/vssolution.cpp | 3 ++- lib/vssolution3d.cpp | 3 ++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 71776311..c2c47074 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -1577,7 +1577,8 @@ void VisualizationSceneScalarData::ComputeElemAttrCenter() } -Plane::Plane(double A,double B,double C,double D) +Plane::Plane(double A,double B,double C,double D, + double (&bbx)[2], double (&bby)[2], double (&bbz)[2]) { eqn[0] = A; eqn[1] = B; @@ -1586,9 +1587,9 @@ Plane::Plane(double A,double B,double C,double D) CartesianToSpherical(); - double x[2] = {vsdata -> x[0], vsdata -> x[1]}; - double y[2] = {vsdata -> y[0], vsdata -> y[1]}; - double z[2] = {vsdata -> z[0], vsdata -> z[1]}; + double x[2] = {bbx[0], bbx[1]}; + double y[2] = {bby[0], bby[1]}; + double z[2] = {bbz[0], bbz[1]}; bbox_diam = sqrt ( (x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0]) + (z[1]-z[0])*(z[1]-z[0]) ); diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index 26a93bd8..775c33fc 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -36,7 +36,8 @@ class Plane double phi_step, theta_step, rho_step; public: - Plane(double A,double B,double C,double D); + Plane(double A,double B,double C,double D, + double (&bbx)[2], double (&bby)[2], double (&bbz)[2]); inline double * Equation() { return eqn; } inline double Transform(double x, double y, double z) { return eqn[0]*x+eqn[1]*y+eqn[2]*z+eqn[3]; } diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 02fd6812..369952f4 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -479,7 +479,8 @@ void VisualizationSceneSolution::Init() palette.SetPalette(2); // use the 'jet-like' palette in 2D double eps = 1e-6; // move the cutting plane a bit to avoid artifacts - CuttingPlane = new Plane(-1.0,0.0,0.0,(0.5-eps)*x[0]+(0.5+eps)*x[1]); + CuttingPlane = new Plane(-1.0,0.0,0.0,(0.5-eps)*x[0]+(0.5+eps)*x[1], + x, y, z); draw_cp = 0; // static int init = 0; diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index ad3cb85d..1cc290a2 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -696,7 +696,8 @@ void VisualizationSceneSolution3d::Init() palette.SetPalette(12); // use the 'vivid' palette in 3D double eps = 1e-6; // move the cutting plane a bit to avoid artifacts - CuttingPlane = new Plane(-1.0,0.0,0.0,(0.5-eps)*x[0]+(0.5+eps)*x[1]); + CuttingPlane = new Plane(-1.0,0.0,0.0,(0.5-eps)*x[0]+(0.5+eps)*x[1], + x, y, z); nlevels = 1; From 5ee2857dd5ac0a3ca60f09afd13d0d74816a8cca Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 10 Feb 2021 12:05:13 -0800 Subject: [PATCH 26/42] Only init freetype once --- lib/font.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++---- lib/font.hpp | 24 +++++++++++------------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/lib/font.cpp b/lib/font.cpp index 04ae2624..97b1470c 100644 --- a/lib/font.cpp +++ b/lib/font.cpp @@ -23,14 +23,52 @@ struct vert_tex2d : x(x), y(y), u(u), v(v) { } }; +struct FTLibraryInit +{ + FT_Library instance; + bool init = false; + + FTLibraryInit() + { + if (!init) + { + if (FT_Init_FreeType(&instance)) + { + cout << "GLVis: Cannot initialize FreeType library!" << endl; + return; + } + init = true; + } + } + + ~FTLibraryInit() + { + if (init) + { + FT_Done_FreeType(instance); + } + } +}; + +static FTLibraryInit ft_; + +bool GetFTLibrary(FT_Library& lib) +{ + if (ft_.init) + { + lib = ft_.instance; + return true; + } + return false; +} + const int font_scale = 64; bool GlVisFont::LoadFont(const std::string& path, int font_index, int font_size) { - if (!init) - { - return false; - } + FT_Library library; + if (!GetFTLibrary(library)) { return false; } + if (font_init) { glDeleteTextures(1, &font_tex); diff --git a/lib/font.hpp b/lib/font.hpp index 02eca930..41eeb8d3 100644 --- a/lib/font.hpp +++ b/lib/font.hpp @@ -34,7 +34,6 @@ class GlVisFont float tex_x; }; private: - bool init; bool font_init; GLenum alpha_channel; @@ -44,7 +43,6 @@ class GlVisFont float tex_h; uint32_t font_tex; - FT_Library library; FT_Face face; bool face_has_kerning; @@ -52,6 +50,8 @@ class GlVisFont int ppi_w, ppi_h; public: + + void SetDPIParams(bool is_hidpi, int ppi_w, int ppi_h) { this->is_hidpi = is_hidpi; @@ -70,25 +70,23 @@ class GlVisFont void getObjectSize(const std::string& text, int& w, int& h); GlVisFont() - : init(false), - font_init(false), + : font_init(false), face_has_kerning(false), is_hidpi(false), ppi_w(96), ppi_h(96) { - if (FT_Init_FreeType(&library)) - { - cout << "GLVis: Can not initialize FreeType library!" << endl; - } - init = true; + //if (FT_Init_FreeType(&library)) + //{ + // cout << "GLVis: Can not initialize FreeType library!" << endl; + //} } ~GlVisFont() { - if (init) - { - FT_Done_FreeType(library); - } + //if (init) + //{ + // FT_Done_FreeType(library); + //} } float GetKerning(char cprev, char c) From 4332822be2a5cfeb3f9a0654ce1d0bbc16df2e94 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 10 Feb 2021 14:38:55 -0800 Subject: [PATCH 27/42] Start moving over some key events to member functions --- glvis.cpp | 2 +- lib/aux_vis.hpp | 30 +++++++- lib/openglvis.cpp | 38 ++++++++++ lib/openglvis.hpp | 5 ++ lib/vsdata.cpp | 177 +++++++++++-------------------------------- lib/vssolution.cpp | 88 +++++++-------------- lib/vssolution3d.cpp | 104 ++++++++----------------- lib/vsvector.cpp | 63 ++++++--------- lib/vsvector.hpp | 9 ++- lib/vsvector3d.cpp | 108 ++++++++++---------------- lib/vsvector3d.hpp | 9 ++- 11 files changed, 254 insertions(+), 379 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 0eb39a8a..ea53e051 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -727,7 +727,7 @@ void PlayScript(istream &scr) if (GLVisInitVis((stream_state.grid_f->VectorDim() == 1) ? 0 : 1)) { - mainWindow->AddWindowEvent(SDLK_SPACE, ScriptControl, false); + mainWindow->AddKeyEvent(SDLK_SPACE, ScriptControl, false); GLVisStartVis(); } diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 8970e6a9..4c5c6ade 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -95,7 +95,25 @@ class GLVisWindow void ResizeWindow(int w, int h); void SetWindowTitle(const char *title); - void AddWindowEvent(int key, void (*eh)(GLVisWindow*), bool exposeAfter = true) + template + void AddKeyEvent(int key, void(*eh)(Args...)) + { + wnd->setOnKeyDown(key, eh); + } + + template + void AddKeyEvent(int key, void (TScene::*eh)(), bool exposeAfter = true) + { + auto wrapped_eh = [this, eh, exposeAfter](GLenum e) + { + TScene* pScene = dynamic_cast(locscene.get()); + (pScene->*eh)(); + if (exposeAfter) { SendExposeEvent(); } + }; + wnd->setOnKeyDown(key, wrapped_eh); + } + + void AddKeyEvent(int key, void (*eh)(GLVisWindow*), bool exposeAfter = true) { auto wrapped_eh = [this, eh, exposeAfter](GLenum e) { @@ -104,6 +122,16 @@ class GLVisWindow }; wnd->setOnKeyDown(key, wrapped_eh); } + + void AddKeyEvent(int key, void (*eh)(GLVisWindow*, GLenum), bool exposeAfter = true) + { + auto wrapped_eh = [this, eh, exposeAfter](GLenum e) + { + (*eh)(this, e); + if (exposeAfter) { SendExposeEvent(); } + }; + wnd->setOnKeyDown(key, wrapped_eh); + } private: void InitFont(); bool SetFont(const vector& patterns, int height); diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 09210ada..f4205c6d 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -465,3 +465,41 @@ glm::mat4 VisualizationScene::GetModelViewMtx() return modelView.mtx; } +void VisualizationScene::DecrementAlpha() +{ + matAlpha -= 0.05; + if (matAlpha < 0.0) + { + matAlpha = 0.0; + } + GenerateAlphaTexture(); +} + +void VisualizationScene::IncrementAlpha() +{ + matAlpha += 0.05; + if (matAlpha > 1.0) + { + matAlpha = 1.0; + } + GenerateAlphaTexture(); +} + +void VisualizationScene::DecrementAlphaCenter() +{ + matAlphaCenter -= 0.25; + GenerateAlphaTexture(); +#ifdef GLVIS_DEBUG + cout << "MatAlphaCenter = " << matAlphaCenter << endl; +#endif +} + +void VisualizationScene::IncrementAlphaCenter() +{ + matAlphaCenter += 0.25; + GenerateAlphaTexture(); +#ifdef GLVIS_DEBUG + cout << "MatAlphaCenter = " << matAlphaCenter << endl; +#endif +} + diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index 8e86f568..a181ad9e 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -194,6 +194,11 @@ class VisualizationScene void GenerateAlphaTexture() { palette.GenerateAlphaTexture(matAlpha, matAlphaCenter); } + void DecrementAlpha(); + void IncrementAlpha(); + void DecrementAlphaCenter(); + void IncrementAlphaCenter(); + /// This is set by SetVisualizationScene int view; }; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index c2c47074..700d45ba 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -464,13 +464,6 @@ void VisualizationSceneScalarData::PrepareCaption() } VisualizationSceneScalarData * vsdata; -extern VisualizationScene * locscene; - -void KeycPressed() -{ - vsdata->ToggleDrawColorbar(); - SendExposeEvent(); -} void KeyCPressed() { @@ -480,20 +473,10 @@ void KeyCPressed() SendExposeEvent(); } -void KeySPressed() -{ - vsdata -> ToggleScaling(); - SendExposeEvent(); -} - -void KeyaPressed() -{ - vsdata -> ToggleDrawAxes(); - SendExposeEvent(); -} - -void Key_Mod_a_Pressed(GLenum state) +void Key_Mod_a_Pressed(GLVisWindow* wnd, GLenum state) { + VisualizationSceneScalarData * vsdata + = dynamic_cast(wnd->getScene()); if (state & KMOD_CTRL) { static const char *autoscale_modes[] = { "off", "on", "value", "mesh" }; @@ -516,12 +499,6 @@ void KeyHPressed() cout << vsdata->GetHelpString() << flush; } -void KeylPressed() -{ - vsdata -> ToggleLight(); - SendExposeEvent(); -} - void KeyLPressed() { vsdata->ToggleLogscale(true); @@ -530,22 +507,22 @@ void KeyLPressed() void KeyrPressed() { - locscene -> spinning = 0; + vsdata -> spinning = 0; GetGLVisWindow()->RemoveIdleFunc(MainLoop); vsdata -> CenterObject(); - locscene -> ViewAngle = 45.0; - locscene -> ViewScale = 1.0; - locscene -> ViewCenterX = 0.0; - locscene -> ViewCenterY = 0.0; - locscene->cam.Reset(); + vsdata -> ViewAngle = 45.0; + vsdata -> ViewScale = 1.0; + vsdata -> ViewCenterX = 0.0; + vsdata -> ViewCenterY = 0.0; + vsdata->cam.Reset(); vsdata -> key_r_state = 0; SendExposeEvent(); } void KeyRPressed() { - locscene->spinning = 0; + vsdata->spinning = 0; GetGLVisWindow()->RemoveIdleFunc(MainLoop); vsdata->Toggle2DView(); SendExposeEvent(); @@ -559,14 +536,14 @@ void KeypPressed(GLenum state) } else { - locscene->GetPalette().NextPalette(); + vsdata->GetPalette().NextPalette(); SendExposeEvent(); } } void KeyPPressed() { - locscene->GetPalette().PrevPalette(); + vsdata->GetPalette().PrevPalette(); SendExposeEvent(); } @@ -705,11 +682,6 @@ void KeyGPressed() SendExposeEvent(); } -void KeyF1Pressed() -{ - vsdata->PrintState(); -} - void KeyF2Pressed() { vsdata -> EventUpdateColors(); @@ -718,68 +690,6 @@ void KeyF2Pressed() SendExposeEvent(); } -void KeykPressed() -{ - locscene->matAlpha -= 0.05; - if (locscene->matAlpha < 0.0) - { - locscene->matAlpha = 0.0; - } - locscene->GenerateAlphaTexture(); - SendExposeEvent(); -} - -void KeyKPressed() -{ - locscene->matAlpha += 0.05; - if (locscene->matAlpha > 1.0) - { - locscene->matAlpha = 1.0; - } - locscene->GenerateAlphaTexture(); - SendExposeEvent(); -} - -void KeyCommaPressed() -{ - locscene->matAlphaCenter -= 0.25; - //vsdata -> EventUpdateColors(); - locscene->GenerateAlphaTexture(); - SendExposeEvent(); -#ifdef GLVIS_DEBUG - cout << "MatAlphaCenter = " << locscene->matAlphaCenter << endl; -#endif -} - -void KeyLessPressed() -{ - locscene->matAlphaCenter += 0.25; - //vsdata -> EventUpdateColors(); - locscene->GenerateAlphaTexture(); - SendExposeEvent(); -#ifdef GLVIS_DEBUG - cout << "MatAlphaCenter = " << locscene->matAlphaCenter << endl; -#endif -} - -void KeyGravePressed() -{ - vsdata->ToggleRuler(); - SendExposeEvent(); -} - -void KeyTildePressed() -{ - vsdata->RulerPosition(); - SendExposeEvent(); -} - -void KeyToggleTexture() -{ - vsdata->ToggleTexture(); - SendExposeEvent(); -} - void VisualizationSceneScalarData::PrintLogscale(bool warn) { if (warn) @@ -1091,50 +1001,53 @@ void VisualizationSceneScalarData::Init() // if (!init) { // init = 1; + GLVisWindow* wnd = GetGLVisWindow(); + + using SceneType = VisualizationSceneScalarData; - wnd->setOnKeyDown('l', KeylPressed); - wnd->setOnKeyDown('L', KeyLPressed); + wnd->AddKeyEvent('l', &SceneType::ToggleLight); + wnd->AddKeyEvent('L', KeyLPressed); - wnd->setOnKeyDown('s', KeySPressed); + wnd->AddKeyEvent('s', &SceneType::ToggleScaling); - // wnd->setOnKeyDown('a', KeyaPressed); - wnd->setOnKeyDown('a', Key_Mod_a_Pressed); + // wnd->AddKeyEvent('a', KeyaPressed); + wnd->AddKeyEvent('a', Key_Mod_a_Pressed); - wnd->setOnKeyDown('r', KeyrPressed); - wnd->setOnKeyDown('R', KeyRPressed); + wnd->AddKeyEvent('r', KeyrPressed); + wnd->AddKeyEvent('R', KeyRPressed); - wnd->setOnKeyDown('p', KeypPressed); - wnd->setOnKeyDown('P', KeyPPressed); + wnd->AddKeyEvent('p', KeypPressed); + wnd->AddKeyEvent('P', KeyPPressed); - wnd->setOnKeyDown('h', KeyHPressed); - wnd->setOnKeyDown('H', KeyHPressed); + wnd->AddKeyEvent('h', KeyHPressed); + wnd->AddKeyEvent('H', KeyHPressed); - wnd->setOnKeyDown(SDLK_F5, KeyF5Pressed); - wnd->setOnKeyDown(SDLK_F6, KeyF6Pressed); - wnd->setOnKeyDown(SDLK_F7, KeyF7Pressed); + wnd->AddKeyEvent(SDLK_F5, KeyF5Pressed); + wnd->AddKeyEvent(SDLK_F6, KeyF6Pressed); + wnd->AddKeyEvent(SDLK_F7, KeyF7Pressed); - wnd->setOnKeyDown(SDLK_BACKSLASH, KeyBackslashPressed); - wnd->setOnKeyDown('t', KeyTPressed); - wnd->setOnKeyDown('T', KeyTPressed); + wnd->AddKeyEvent(SDLK_BACKSLASH, KeyBackslashPressed); + wnd->AddKeyEvent('t', KeyTPressed); + wnd->AddKeyEvent('T', KeyTPressed); - wnd->setOnKeyDown('g', KeyGPressed); - wnd->setOnKeyDown('G', KeyGPressed); + wnd->AddKeyEvent('g', KeyGPressed); + wnd->AddKeyEvent('G', KeyGPressed); - wnd->setOnKeyDown('c', KeycPressed); - wnd->setOnKeyDown('C', KeyCPressed); + wnd->AddKeyEvent('c', &SceneType::ToggleDrawColorbar); + wnd->AddKeyEvent('C', KeyCPressed); - wnd->setOnKeyDown('k', KeykPressed); - wnd->setOnKeyDown('K', KeyKPressed); + wnd->AddKeyEvent('k', &SceneType::DecrementAlpha); + wnd->AddKeyEvent('K', &SceneType::IncrementAlpha); - wnd->setOnKeyDown(SDLK_F1, KeyF1Pressed); - wnd->setOnKeyDown(SDLK_F2, KeyF2Pressed); + wnd->AddKeyEvent(SDLK_F1, &SceneType::PrintState, false); + wnd->AddKeyEvent(SDLK_F2, KeyF2Pressed); - wnd->setOnKeyDown(SDLK_COMMA, KeyCommaPressed); - wnd->setOnKeyDown(SDLK_LESS, KeyLessPressed); - wnd->setOnKeyDown('~', KeyTildePressed); - wnd->setOnKeyDown('`', KeyGravePressed); + wnd->AddKeyEvent(SDLK_COMMA, &SceneType::DecrementAlphaCenter); + wnd->AddKeyEvent(SDLK_LESS, &SceneType::IncrementAlphaCenter); + wnd->AddKeyEvent('~', &SceneType::RulerPosition); + wnd->AddKeyEvent('`', &SceneType::ToggleRuler); - wnd->setOnKeyDown(SDLK_EXCLAIM, KeyToggleTexture); + wnd->AddKeyEvent(SDLK_EXCLAIM, &SceneType::ToggleTexture); } //Set_Light(); diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 369952f4..7148f6d9 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -219,24 +219,6 @@ static void KeyF10Pressed(GLenum state) } } -static void KeyBPressed() -{ - vssol -> ToggleDrawBdr(); - SendExposeEvent(); -} - -static void KeyMPressed() -{ - vssol -> ToggleDrawMesh(); - SendExposeEvent(); -} - -static void KeyNPressed() -{ - vssol -> ToggleDrawNumberings(); - SendExposeEvent(); -} - int refine_func = 0; static void KeyoPressed(GLenum state) @@ -319,24 +301,6 @@ static void KeyOPressed(GLenum state) } } -static void KeyEPressed() -{ - vssol -> ToggleDrawElems(); - SendExposeEvent(); -} - -static void KeyFPressed() -{ - vssol -> ToggleShading(); - SendExposeEvent(); -} - -void KeyiPressed() -{ - vssol->ToggleDrawCP(); - SendExposeEvent(); -} - void KeyIPressed() { // no-op, available @@ -487,40 +451,42 @@ void VisualizationSceneSolution::Init() // if (!init) { // init = 1; + GLVisWindow* wnd = GetGLVisWindow(); + using SceneType = VisualizationSceneSolution; - wnd->setOnKeyDown('b', KeyBPressed); - wnd->setOnKeyDown('B', KeyBPressed); + wnd->AddKeyEvent('b', &SceneType::ToggleDrawBdr); + wnd->AddKeyEvent('B', &SceneType::ToggleDrawBdr); - wnd->setOnKeyDown('m', KeyMPressed); - wnd->setOnKeyDown('M', KeyMPressed); + wnd->AddKeyEvent('m', &SceneType::ToggleDrawMesh); + wnd->AddKeyEvent('M', &SceneType::ToggleDrawMesh); - wnd->setOnKeyDown('n', KeyNPressed); - wnd->setOnKeyDown('N', KeyNPressed); + wnd->AddKeyEvent('n', &SceneType::ToggleDrawNumberings); + wnd->AddKeyEvent('N', &SceneType::ToggleDrawNumberings); - wnd->setOnKeyDown('o', KeyoPressed); - wnd->setOnKeyDown('O', KeyOPressed); + wnd->AddKeyEvent('o', KeyoPressed); + wnd->AddKeyEvent('O', KeyOPressed); - wnd->setOnKeyDown('e', KeyEPressed); - wnd->setOnKeyDown('E', KeyEPressed); + wnd->AddKeyEvent('e', &SceneType::ToggleDrawElems); + wnd->AddKeyEvent('E', &SceneType::ToggleDrawElems); - wnd->setOnKeyDown('f', KeyFPressed); - wnd->setOnKeyDown('F', KeyFPressed); + wnd->AddKeyEvent('f', &SceneType::ToggleShading); + wnd->AddKeyEvent('F', &SceneType::ToggleShading); - wnd->setOnKeyDown('i', KeyiPressed); - wnd->setOnKeyDown('I', KeyIPressed); + wnd->AddKeyEvent('i', &SceneType::ToggleDrawCP); + //wnd->AddKeyEvent('I', KeyIPressed); - wnd->setOnKeyDown('y', KeyyPressed); - wnd->setOnKeyDown('Y', KeyYPressed); - wnd->setOnKeyDown('z', KeyzPressed); - wnd->setOnKeyDown('Z', KeyZPressed); + wnd->AddKeyEvent('y', KeyyPressed); + wnd->AddKeyEvent('Y', KeyYPressed); + wnd->AddKeyEvent('z', KeyzPressed); + wnd->AddKeyEvent('Z', KeyZPressed); - wnd->setOnKeyDown(SDLK_F3, KeyF3Pressed); - wnd->setOnKeyDown(SDLK_F4, KeyF4Pressed); - wnd->setOnKeyDown(SDLK_F8, KeyF8Pressed); - wnd->setOnKeyDown(SDLK_F9, KeyF9Pressed); - wnd->setOnKeyDown(SDLK_F10, KeyF10Pressed); - wnd->setOnKeyDown(SDLK_F11, KeyF11Pressed); - wnd->setOnKeyDown(SDLK_F12, KeyF12Pressed); + wnd->AddKeyEvent(SDLK_F3, KeyF3Pressed); + wnd->AddKeyEvent(SDLK_F4, KeyF4Pressed); + wnd->AddKeyEvent(SDLK_F8, KeyF8Pressed); + wnd->AddKeyEvent(SDLK_F9, KeyF9Pressed); + wnd->AddKeyEvent(SDLK_F10, KeyF10Pressed); + wnd->AddKeyEvent(SDLK_F11, KeyF11Pressed); + wnd->AddKeyEvent(SDLK_F12, KeyF12Pressed); } Prepare(); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 1cc290a2..b059db2a 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -105,18 +105,6 @@ std::string VisualizationSceneSolution3d::GetHelpString() const return os.str(); } -static void KeyiPressed() -{ - vssol3d -> ToggleCuttingPlane(); - SendExposeEvent(); -} - -static void KeyIPressed() -{ - vssol3d -> ToggleCPAlgorithm(); - SendExposeEvent(); -} - void VisualizationSceneSolution3d::PrepareOrderingCurve() { bool color = draworder < 3; @@ -296,36 +284,6 @@ static void KeyZPressed() SendExposeEvent(); } -static void KeymPressed() -{ - vssol3d -> ToggleDrawMesh(); - SendExposeEvent(); -} - -static void KeyePressed() -{ - vssol3d -> ToggleDrawElems(); - SendExposeEvent(); -} - -static void KeyMPressed() -{ - vssol3d -> ToggleCPDrawMesh(); - SendExposeEvent(); -} - -static void KeyEPressed() -{ - vssol3d -> ToggleCPDrawElems(); - SendExposeEvent(); -} - -static void KeyFPressed() -{ - vssol3d -> ToggleShading(); - SendExposeEvent(); -} - static void KeyoPressed(GLenum state) { if (state & KMOD_CTRL) @@ -707,50 +665,52 @@ void VisualizationSceneSolution3d::Init() // if (!init) { // init = 1; + GLVisWindow* wnd = GetGLVisWindow(); + using SceneType = VisualizationSceneSolution3d; - wnd->setOnKeyDown('m', KeymPressed); - wnd->setOnKeyDown('M', KeyMPressed); + wnd->AddKeyEvent('m', &SceneType::ToggleDrawMesh); + wnd->AddKeyEvent('M', &SceneType::ToggleCPDrawMesh); - wnd->setOnKeyDown('e', KeyePressed); - wnd->setOnKeyDown('E', KeyEPressed); + wnd->AddKeyEvent('e', &SceneType::ToggleDrawElems); + wnd->AddKeyEvent('E', &SceneType::ToggleCPDrawElems); - wnd->setOnKeyDown('f', KeyFPressed); - // wnd->setOnKeyDown('F', KeyFPressed); + wnd->AddKeyEvent('f', &SceneType::ToggleShading); + // wnd->AddKeyEvent('F', KeyFPressed); - wnd->setOnKeyDown('i', KeyiPressed); - wnd->setOnKeyDown('I', KeyIPressed); + wnd->AddKeyEvent('i', &SceneType::ToggleCuttingPlane); + wnd->AddKeyEvent('I', &SceneType::ToggleCPAlgorithm); - wnd->setOnKeyDown('o', KeyoPressed); - wnd->setOnKeyDown('O', KeyOPressed); + wnd->AddKeyEvent('o', KeyoPressed); + wnd->AddKeyEvent('O', KeyOPressed); - wnd->setOnKeyDown('w', KeywPressed); - wnd->setOnKeyDown('W', KeyWPressed); + wnd->AddKeyEvent('w', KeywPressed); + wnd->AddKeyEvent('W', KeyWPressed); - wnd->setOnKeyDown('x', KeyxPressed); - wnd->setOnKeyDown('X', KeyXPressed); + wnd->AddKeyEvent('x', KeyxPressed); + wnd->AddKeyEvent('X', KeyXPressed); - wnd->setOnKeyDown('y', KeyyPressed); - wnd->setOnKeyDown('Y', KeyYPressed); + wnd->AddKeyEvent('y', KeyyPressed); + wnd->AddKeyEvent('Y', KeyYPressed); - wnd->setOnKeyDown('z', KeyzPressed); - wnd->setOnKeyDown('Z', KeyZPressed); + wnd->AddKeyEvent('z', KeyzPressed); + wnd->AddKeyEvent('Z', KeyZPressed); - wnd->setOnKeyDown('u', KeyuPressed); - wnd->setOnKeyDown('U', KeyUPressed); + wnd->AddKeyEvent('u', KeyuPressed); + wnd->AddKeyEvent('U', KeyUPressed); - wnd->setOnKeyDown('v', KeyvPressed); - wnd->setOnKeyDown('V', KeyVPressed); + wnd->AddKeyEvent('v', KeyvPressed); + wnd->AddKeyEvent('V', KeyVPressed); - wnd->setOnKeyDown(SDLK_F3, KeyF3Pressed); - wnd->setOnKeyDown(SDLK_F4, KeyF4Pressed); - wnd->setOnKeyDown(SDLK_NUMLOCKCLEAR, ToggleMagicKey); + wnd->AddKeyEvent(SDLK_F3, KeyF3Pressed); + wnd->AddKeyEvent(SDLK_F4, KeyF4Pressed); + wnd->AddKeyEvent(SDLK_NUMLOCKCLEAR, ToggleMagicKey); - wnd->setOnKeyDown(SDLK_F8, KeyF8Pressed); - wnd->setOnKeyDown(SDLK_F9, KeyF9Pressed); - wnd->setOnKeyDown(SDLK_F10, KeyF10Pressed); + wnd->AddKeyEvent(SDLK_F8, KeyF8Pressed); + wnd->AddKeyEvent(SDLK_F9, KeyF9Pressed); + wnd->AddKeyEvent(SDLK_F10, KeyF10Pressed); - wnd->setOnKeyDown(SDLK_F11, KeyF11Pressed); - wnd->setOnKeyDown(SDLK_F12, KeyF12Pressed); + wnd->AddKeyEvent(SDLK_F11, KeyF11Pressed); + wnd->AddKeyEvent(SDLK_F12, KeyF12Pressed); } Prepare(); PrepareLines(); diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index a5851b57..3a4a501c 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -104,53 +104,34 @@ extern VisualizationScene * locscene; extern VisualizationSceneSolution * vssol; extern GeometryRefiner GLVisGeometryRefiner; -static int ianim = 0; -static int ianimmax = 10; - -void KeyDPressed() -{ - vsvector -> ToggleDisplacements(); - SendExposeEvent(); -} - -void KeyNPressed() +void VisualizationSceneVector::NextDisplacement() { ianim = (ianim + 1) % (ianimmax + 1); - vsvector -> NPressed(); + if (drawdisp == 0) + { + drawdisp = 1; + ianim = 0; + } + PrepareDisplacedMesh(); } -void KeyBPressed() +void VisualizationSceneVector::PrevDisplacement() { ianim = (ianim + ianimmax) % (ianimmax + 1); - vsvector -> NPressed(); -} - -void VisualizationSceneVector::NPressed() -{ if (drawdisp == 0) { drawdisp = 1; ianim = 0; } - PrepareDisplacedMesh(); - - SendExposeEvent(); } -void KeyvPressed() -{ - vsvector -> ToggleVectorField(); - SendExposeEvent(); -} - -void KeyVPressed() +void VisualizationSceneVector::QueryArrowScaling() { cout << "New arrow scale: " << flush; - cin >> vsvector -> ArrowScale; - cout << "New arrow scale = " << vsvector -> ArrowScale << endl; - vsvector -> PrepareVectorField(); - SendExposeEvent(); + cin >> ArrowScale; + cout << "New arrow scale = " << ArrowScale << endl; + PrepareVectorField(); } int key_u_func = 0; @@ -500,15 +481,17 @@ void VisualizationSceneVector::Init() // if (!init) { // init = 1; - - wnd->setOnKeyDown('d', KeyDPressed); - wnd->setOnKeyDown('D', KeyDPressed); - wnd->setOnKeyDown('n', KeyNPressed); - wnd->setOnKeyDown('b', KeyBPressed); - wnd->setOnKeyDown('v', KeyvPressed); - wnd->setOnKeyDown('V', KeyVPressed); - wnd->setOnKeyDown('u', KeyuPressed); - wnd->setOnKeyDown('U', KeyUPressed); + GLVisWindow* wnd = GetGLVisWindow(); + using SceneType = VisualizationSceneVector; + + wnd->AddKeyEvent('d', &SceneType::ToggleDisplacements); + wnd->AddKeyEvent('D', &SceneType::ToggleDisplacements); + wnd->AddKeyEvent('n', &SceneType::NextDisplacement); + wnd->AddKeyEvent('b', &SceneType::PrevDisplacement); + wnd->AddKeyEvent('v', &SceneType::ToggleVectorField); + wnd->AddKeyEvent('V', &SceneType::QueryArrowScaling); + wnd->AddKeyEvent('u', KeyuPressed); + wnd->AddKeyEvent('U', KeyUPressed); } // Vec2Scalar is VecLength diff --git a/lib/vsvector.hpp b/lib/vsvector.hpp index f8e836d1..8d5fdd7a 100644 --- a/lib/vsvector.hpp +++ b/lib/vsvector.hpp @@ -44,6 +44,14 @@ class VisualizationSceneVector : public VisualizationSceneSolution Vector vc0; IsoparametricTransformation T0; + int ianim = 0; + const int ianimmax = 10; + + void NextDisplacement(); + void PrevDisplacement(); + + void QueryArrowScaling(); + public: VisualizationSceneVector(Mesh &m, Vector &sx, Vector &sy); VisualizationSceneVector(GridFunction &vgf); @@ -54,7 +62,6 @@ class VisualizationSceneVector : public VisualizationSceneSolution virtual std::string GetHelpString() const; - void NPressed(); void PrepareDisplacedMesh(); virtual void PrepareLines() { VisualizationSceneSolution::PrepareLines(); PrepareDisplacedMesh(); } diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 5dd4688a..0215290a 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -104,34 +104,22 @@ VisualizationSceneVector3d *vsvector3d; extern VisualizationScene *locscene; extern GeometryRefiner GLVisGeometryRefiner; -static void KeyDPressed() +void VisualizationSceneVector3d::NextDisplacement() { - vsvector3d -> ToggleDisplacements(); - SendExposeEvent(); -} - -static void KeyNPressed() -{ - if (vsvector3d -> drawdisp) - vsvector3d -> ianimd =( (vsvector3d ->ianimd + 1) % - (vsvector3d -> ianimmax + 1) ); + if (drawdisp) + ianimd =( (ianimd + 1) % (ianimmax + 1) ); else - vsvector3d -> ianim =( (vsvector3d ->ianim + 1) % - (vsvector3d -> ianimmax + 1) ); - vsvector3d -> NPressed(); + ianim =( (ianim + 1) % (ianimmax + 1) ); + NPressed(); } -static void KeyBPressed() +void VisualizationSceneVector3d::PrevDisplacement() { - if (vsvector3d -> drawdisp) - vsvector3d ->ianimd = ((vsvector3d ->ianimd + - vsvector3d ->ianimmax) % - (vsvector3d ->ianimmax + 1)); + if (drawdisp) + ianimd = ((ianimd + ianimmax) % (ianimmax + 1)); else - vsvector3d ->ianim = ((vsvector3d ->ianim + - vsvector3d ->ianimmax) % - (vsvector3d ->ianimmax + 1)); - vsvector3d -> NPressed(); + ianim = ((ianim + ianimmax) % (ianimmax + 1)); + NPressed(); } static void KeyrPressed() @@ -178,16 +166,14 @@ void VisualizationSceneVector3d::NPressed() SendExposeEvent(); } -static void KeyuPressed() +void VisualizationSceneVector3d::NextVectorFieldLevel() { - vsvector3d -> ToggleVectorFieldLevel(+1); - SendExposeEvent(); + ToggleVectorFieldLevel(+1); } -static void KeyUPressed() +void VisualizationSceneVector3d::PrevVectorFieldLevel() { - vsvector3d -> ToggleVectorFieldLevel(-1); - SendExposeEvent(); + ToggleVectorFieldLevel(-1); } void VisualizationSceneVector3d::ToggleVectorFieldLevel(int v) @@ -206,19 +192,7 @@ void VisualizationSceneVector3d::ToggleVectorFieldLevel(int v) { dvflevel[i] = level[vflevel[i]]; } - vsvector3d -> PrepareVectorField(); -} - -static void KeywPressed() -{ - vsvector3d -> AddVectorFieldLevel(); - SendExposeEvent(); -} - -static void KeyWPressed() -{ - vsvector3d -> RemoveVectorFieldLevel(); - SendExposeEvent(); + PrepareVectorField(); } void VisualizationSceneVector3d::AddVectorFieldLevel() @@ -227,32 +201,24 @@ void VisualizationSceneVector3d::AddVectorFieldLevel() next = (next + 1) % (nl+1); vflevel.Append(next); dvflevel.Append(level[next]); - vsvector3d -> PrepareVectorField(); + PrepareVectorField(); } void VisualizationSceneVector3d::RemoveVectorFieldLevel() { vflevel.DeleteLast(); dvflevel.DeleteLast(); - vsvector3d -> PrepareVectorField(); -} - -static void KeyvPressed() -{ - vsvector3d -> ToggleVectorField(1); - SendExposeEvent(); + PrepareVectorField(); } -static void KeyVPressed() +void VisualizationSceneVector3d::NextVectorField() { - vsvector3d -> ToggleVectorField(-1); - SendExposeEvent(); + ToggleVectorField(1); } -static void VectorKeyFPressed() +void VisualizationSceneVector3d::PrevVectorField() { - vsvector3d->ToggleScalarFunction(); - SendExposeEvent(); + ToggleVectorField(-1); } void VisualizationSceneVector3d::ToggleVectorField(int i) @@ -399,29 +365,31 @@ void VisualizationSceneVector3d::Init() // if (!init) { // init = 1; + GLVisWindow* wnd = GetGLVisWindow(); + using SceneType = VisualizationSceneVector3d; - wnd->setOnKeyDown('d', KeyDPressed); - wnd->setOnKeyDown('D', KeyDPressed); + wnd->AddKeyEvent('d', &SceneType::ToggleDisplacements); + wnd->AddKeyEvent('D', &SceneType::ToggleDisplacements); - wnd->setOnKeyDown('n', KeyNPressed); - wnd->setOnKeyDown('N', KeyNPressed); + wnd->AddKeyEvent('n', &SceneType::NextDisplacement); + wnd->AddKeyEvent('N', &SceneType::NextDisplacement); - wnd->setOnKeyDown('b', KeyBPressed); - wnd->setOnKeyDown('B', KeyBPressed); + wnd->AddKeyEvent('b', &SceneType::PrevDisplacement); + wnd->AddKeyEvent('B', &SceneType::PrevDisplacement); - wnd->setOnKeyDown('r', KeyrPressed); // adds another function to 'r' and 'R' - wnd->setOnKeyDown('R', KeyRPressed); // the other function is in vsdata.cpp + wnd->AddKeyEvent('r', KeyrPressed); // adds another function to 'r' and 'R' + wnd->AddKeyEvent('R', KeyRPressed); // the other function is in vsdata.cpp - wnd->setOnKeyDown('u', KeyuPressed); // Keys u, U are also used in - wnd->setOnKeyDown('U', KeyUPressed); // VisualizationSceneSolution3d + wnd->AddKeyEvent('u', &SceneType::NextVectorFieldLevel); // Keys u, U are also used in + wnd->AddKeyEvent('U', &SceneType::PrevVectorFieldLevel); // VisualizationSceneSolution3d - wnd->setOnKeyDown('w', KeywPressed); // Keys w, W are also used in - wnd->setOnKeyDown('W', KeyWPressed); // VisualizationSceneSolution3d + wnd->AddKeyEvent('w', &SceneType::AddVectorFieldLevel); // Keys w, W are also used in + wnd->AddKeyEvent('W', &SceneType::RemoveVectorFieldLevel); // VisualizationSceneSolution3d - wnd->setOnKeyDown('v', KeyvPressed); // Keys v, V are also used in - wnd->setOnKeyDown('V', KeyVPressed); // VisualizationSceneSolution3d + wnd->AddKeyEvent('v', &SceneType::NextVectorField); // Keys v, V are also used in + wnd->AddKeyEvent('V', &SceneType::PrevVectorField); // VisualizationSceneSolution3d - wnd->setOnKeyDown('F', VectorKeyFPressed); + wnd->AddKeyEvent('F', &SceneType::ToggleScalarFunction); } } diff --git a/lib/vsvector3d.hpp b/lib/vsvector3d.hpp index a4034538..77649195 100644 --- a/lib/vsvector3d.hpp +++ b/lib/vsvector3d.hpp @@ -33,6 +33,14 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d Array vflevel; Array dvflevel; + void NextDisplacement(); + void PrevDisplacement(); + void NPressed(); + + void NextVectorField(); + void PrevVectorField(); + void NextVectorFieldLevel(); + void PrevVectorFieldLevel(); public: int ianim, ianimd, ianimmax, drawdisp; @@ -45,7 +53,6 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d virtual std::string GetHelpString() const; - void NPressed(); virtual void PrepareFlat(); virtual void Prepare(); virtual void PrepareLines(); From 0ce134048d1c4085d0119f9937018d4543b9bc28 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Wed, 10 Feb 2021 17:37:01 -0800 Subject: [PATCH 28/42] Add support for stackable events, improve handling of scene view resets --- lib/aux_vis.cpp | 46 +++++++++++++++++++++++++++++++++---------- lib/aux_vis.hpp | 18 ++++++++++++++--- lib/vsdata.cpp | 45 ++++++++++++++---------------------------- lib/vsdata.hpp | 3 ++- lib/vsvector3d.cpp | 49 ++++++++++++++++------------------------------ lib/vsvector3d.hpp | 4 ++++ 6 files changed, 89 insertions(+), 76 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index be62d0e4..90c761f6 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -101,6 +101,13 @@ KeyDelegate CreateKeyEvent(T* inst, void (T::*func)()) return [inst, func](GLenum) { (inst->*func)(); }; } +bool KeyPrint(GLVisWindow* wnd, GLenum mod) +{ + if (mod & KMOD_CTRL) + { + wnd->PrintToPDF(); + } +} GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool legacyGlOnly) : locscene(nullptr) @@ -156,7 +163,9 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega SetKeyEventHandler('A', &GLVisWindow::ToggleAntialiasing); - // auxKeyFunc (AUX_p, KeyCtrlP); // handled in vsdata.cpp + SetKeyEventHandler ('p', &GLVisWindow::PrintToPDF); + SetKeyEventHandler ('r', &GLVisWindow::StopSpinning); + SetKeyEventHandler ('R', &GLVisWindow::StopSpinning); SetKeyEventHandler (SDLK_s, &GLVisWindow::Screenshot); SetKeyEventHandler ('S', &GLVisWindow::Screenshot); @@ -271,16 +280,30 @@ void GLVisWindow::InitVisualization(int field_type, StreamState state, } } +void GLVisWindow::SetupHandledKey(int key) +{ + wnd->setOnKeyDown(key, + [this, key](GLenum e) + { + if (internal_keyevents.find(key) != internal_keyevents.end()) + { internal_keyevents[key](e); } + if (keyevents.find(key) != keyevents.end()) + { keyevents[key](e); } + }); +} + void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)()) { - auto handlerWrapper = [this, handler]() { (this->*handler)(); }; - wnd->setOnKeyDown(key, handlerWrapper); + auto handlerWrapper = [this, handler](GLenum) { (this->*handler)(); }; + internal_keyevents[key] = handlerWrapper; + SetupHandledKey(key); } void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)(GLenum)) { auto handlerWrapper = [this, handler](GLenum mod) { (this->*handler)(mod); }; - wnd->setOnKeyDown(key, handlerWrapper); + internal_keyevents[key] = handlerWrapper; + SetupHandledKey(key); } void SendKeySequence(const char *seq) @@ -628,8 +651,7 @@ inline void ComputeSphereAngles(int viewport_w, int viewport_h, void GLVisWindow::RotationControl::LeftButtonDown (EventInfo *event) { - wnd->locscene -> spinning = 0; - wnd->RemoveIdleFunc(::MainLoop); + wnd->StopSpinning(); oldx = event->mouse_x; oldy = event->mouse_y; @@ -1056,8 +1078,7 @@ void GLVisWindow::RotationControl::CheckSpin() } else { - wnd->locscene->spinning = 0; - wnd->RemoveIdleFunc(::MainLoop); + wnd->StopSpinning(); } cout << "Spin angle: " << xang << " degrees / frame" << endl; } @@ -1079,8 +1100,7 @@ void GLVisWindow::RotationControl::KeyDeletePressed() if (wnd->locscene -> spinning) { xang = yang = 0.; - wnd->locscene -> spinning = 0; - wnd->RemoveIdleFunc(::MainLoop); + wnd->StopSpinning(); constrained_spinning = 1; } else @@ -1248,6 +1268,12 @@ void GLVisWindow::KeyPlusPressed() SendExposeEvent(); } +void GLVisWindow::StopSpinning() +{ + locscene -> spinning = 0; + RemoveIdleFunc(::MainLoop); +} + void GLVisWindow::ZoomIn() { locscene->Zoom(exp (0.05)); diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 4c5c6ade..1b50e160 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -110,7 +110,8 @@ class GLVisWindow (pScene->*eh)(); if (exposeAfter) { SendExposeEvent(); } }; - wnd->setOnKeyDown(key, wrapped_eh); + keyevents[key] = wrapped_eh; + SetupHandledKey(key); } void AddKeyEvent(int key, void (*eh)(GLVisWindow*), bool exposeAfter = true) @@ -120,7 +121,8 @@ class GLVisWindow (*eh)(this); if (exposeAfter) { SendExposeEvent(); } }; - wnd->setOnKeyDown(key, wrapped_eh); + keyevents[key] = wrapped_eh; + SetupHandledKey(key); } void AddKeyEvent(int key, void (*eh)(GLVisWindow*, GLenum), bool exposeAfter = true) @@ -130,12 +132,15 @@ class GLVisWindow (*eh)(this, e); if (exposeAfter) { SendExposeEvent(); } }; - wnd->setOnKeyDown(key, wrapped_eh); + keyevents[key] = wrapped_eh; + SetupHandledKey(key); } private: void InitFont(); bool SetFont(const vector& patterns, int height); + void SetupHandledKey(int key); + void SetKeyEventHandler(int key, void (GLVisWindow::*handler)()); void SetKeyEventHandler(int key, void (GLVisWindow::*handler)(GLenum)); @@ -165,6 +170,8 @@ class GLVisWindow void KeyMinusPressed(); void KeyPlusPressed(); + void StopSpinning(); + // Internal event handler for toggling state of threads void ThreadsPauseFunc(GLenum); @@ -179,6 +186,11 @@ class GLVisWindow mfem::Array idle_funcs{}; int last_idle_func = 0; + // internal_keyevents keeps internal event handlers, which will be called + // before an event handler in keyevents + std::unordered_map internal_keyevents; + std::unordered_map keyevents; + int visualize = 0; bool disableSendExposeEvent = false; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 700d45ba..fa2afa42 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -485,12 +485,10 @@ void Key_Mod_a_Pressed(GLVisWindow* wnd, GLenum state) cout << "Autoscale: " << flush; vsdata->SetAutoscale(autoscale); cout << autoscale_modes[autoscale] << endl; - SendExposeEvent(); } else { vsdata->ToggleDrawAxes(); - SendExposeEvent(); } } @@ -505,39 +503,26 @@ void KeyLPressed() SendExposeEvent(); } -void KeyrPressed() +void VisualizationSceneScalarData::Reset3DView() { - vsdata -> spinning = 0; - GetGLVisWindow()->RemoveIdleFunc(MainLoop); - vsdata -> CenterObject(); - - vsdata -> ViewAngle = 45.0; - vsdata -> ViewScale = 1.0; - vsdata -> ViewCenterX = 0.0; - vsdata -> ViewCenterY = 0.0; - vsdata->cam.Reset(); - vsdata -> key_r_state = 0; - SendExposeEvent(); -} + CenterObject(); -void KeyRPressed() -{ - vsdata->spinning = 0; - GetGLVisWindow()->RemoveIdleFunc(MainLoop); - vsdata->Toggle2DView(); - SendExposeEvent(); + ViewAngle = 45.0; + ViewScale = 1.0; + ViewCenterX = 0.0; + ViewCenterY = 0.0; + cam.Reset(); + key_r_state = 0; } -void KeypPressed(GLenum state) +void KeypPressed(GLVisWindow* wnd, GLenum state) { - if (state & KMOD_CTRL) - { - GetGLVisWindow()->PrintToPDF(); - } - else + VisualizationSceneScalarData * vsdata + = dynamic_cast(wnd->getScene()); + // KMOD_CTRL handled by KeyPrintPDF in aux_vis.cpp + if (!(state & KMOD_CTRL)) { vsdata->GetPalette().NextPalette(); - SendExposeEvent(); } } @@ -1013,8 +998,8 @@ void VisualizationSceneScalarData::Init() // wnd->AddKeyEvent('a', KeyaPressed); wnd->AddKeyEvent('a', Key_Mod_a_Pressed); - wnd->AddKeyEvent('r', KeyrPressed); - wnd->AddKeyEvent('R', KeyRPressed); + wnd->AddKeyEvent('r', &SceneType::Reset3DView); + wnd->AddKeyEvent('R', &SceneType::Toggle2DView); wnd->AddKeyEvent('p', KeypPressed); wnd->AddKeyEvent('P', KeyPPressed); diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index 775c33fc..d3448b5e 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -264,7 +264,8 @@ class VisualizationSceneScalarData : public VisualizationScene void ToggleTexture(); - void Toggle2DView(); + virtual void Reset3DView(); + virtual void Toggle2DView(); void SetAutoscale(int _autoscale); int GetAutoscale() const { return autoscale; } diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 0215290a..268d21d7 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -100,8 +100,6 @@ std::string VisualizationSceneVector3d::GetHelpString() const return os.str(); } -VisualizationSceneVector3d *vsvector3d; -extern VisualizationScene *locscene; extern GeometryRefiner GLVisGeometryRefiner; void VisualizationSceneVector3d::NextDisplacement() @@ -122,33 +120,27 @@ void VisualizationSceneVector3d::PrevDisplacement() NPressed(); } -static void KeyrPressed() +void VisualizationSceneVector3d::Reset3DView() { - locscene -> spinning = 0; - GetGLVisWindow()->RemoveIdleFunc(MainLoop); - vsvector3d -> CenterObject(); - locscene -> ViewAngle = 45.0; - locscene -> ViewScale = 1.0; - locscene -> ViewCenterX = 0.0; - locscene -> ViewCenterY = 0.0; - vsvector3d -> ianim = vsvector3d -> ianimd = 0; - vsvector3d -> Prepare(); - vsvector3d -> PrepareLines(); - vsvector3d -> PrepareDisplacedMesh(); - vsvector3d -> key_r_state = 0; - SendExposeEvent(); + CenterObject(); + ViewAngle = 45.0; + ViewScale = 1.0; + ViewCenterX = 0.0; + ViewCenterY = 0.0; + ianim = ianimd = 0; + Prepare(); + PrepareLines(); + PrepareDisplacedMesh(); + key_r_state = 0; } -static void KeyRPressed() +void VisualizationSceneVector3d::Toggle2DView() { - locscene->spinning = 0; - GetGLVisWindow()->RemoveIdleFunc(MainLoop); - vsvector3d -> ianim = vsvector3d -> ianimd = 0; - vsvector3d -> Prepare(); - vsvector3d -> PrepareLines(); - vsvector3d -> PrepareDisplacedMesh(); - vsvector3d->Toggle2DView(); - SendExposeEvent(); + ianim = ianimd = 0; + Prepare(); + PrepareLines(); + PrepareDisplacedMesh(); + VisualizationSceneScalarData::Toggle2DView(); } void VisualizationSceneVector3d::NPressed() @@ -162,8 +154,6 @@ void VisualizationSceneVector3d::NPressed() Prepare(); PrepareLines(); } - - SendExposeEvent(); } void VisualizationSceneVector3d::NextVectorFieldLevel() @@ -359,8 +349,6 @@ void VisualizationSceneVector3d::Init() vflevel.Append(0); dvflevel.Append(level[0]); - vsvector3d = this; - // static int init = 0; // if (!init) { @@ -377,9 +365,6 @@ void VisualizationSceneVector3d::Init() wnd->AddKeyEvent('b', &SceneType::PrevDisplacement); wnd->AddKeyEvent('B', &SceneType::PrevDisplacement); - wnd->AddKeyEvent('r', KeyrPressed); // adds another function to 'r' and 'R' - wnd->AddKeyEvent('R', KeyRPressed); // the other function is in vsdata.cpp - wnd->AddKeyEvent('u', &SceneType::NextVectorFieldLevel); // Keys u, U are also used in wnd->AddKeyEvent('U', &SceneType::PrevVectorFieldLevel); // VisualizationSceneSolution3d diff --git a/lib/vsvector3d.hpp b/lib/vsvector3d.hpp index 77649195..60c0a25a 100644 --- a/lib/vsvector3d.hpp +++ b/lib/vsvector3d.hpp @@ -60,6 +60,10 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d void PrepareFlat2(); void PrepareLines2(); + // Overrides original event handlers defined in vsdata.cpp + virtual void Reset3DView(); + virtual void Toggle2DView(); + void DrawVector (gl3::GlBuilder& builder, int type, double v0, double v1, double v2, double sx, double sy, double sz, double s); From 85688cf0392de3af16680a2f9d342245db92e835 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 10:53:47 -0800 Subject: [PATCH 29/42] Add support for conditionally-updatable event handlers --- lib/aux_vis.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 1b50e160..2f44b77e 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -101,6 +101,20 @@ class GLVisWindow wnd->setOnKeyDown(key, eh); } + /// Adds a conditionally-updatable scene event. + template + void AddKeyEvent(int key, bool (TScene::*eh)()) + { + auto wrapped_eh = [this, eh](GLenum e) + { + TScene* pScene = dynamic_cast(locscene.get()); + bool exposeAfter = (pScene->*eh)(); + if (exposeAfter) { SendExposeEvent(); } + }; + keyevents[key] = wrapped_eh; + SetupHandledKey(key); + } + template void AddKeyEvent(int key, void (TScene::*eh)(), bool exposeAfter = true) { From ba785363ca44a9b45c788a260e9100cc580f6669 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 10:54:12 -0800 Subject: [PATCH 30/42] Make all vssolution3d event handlers member functions --- lib/aux_vis.hpp | 6 - lib/vssolution3d.cpp | 305 +++++++++++++++++++++---------------------- lib/vssolution3d.hpp | 25 ++++ 3 files changed, 173 insertions(+), 163 deletions(-) diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 2f44b77e..b13466c0 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -95,12 +95,6 @@ class GLVisWindow void ResizeWindow(int w, int h); void SetWindowTitle(const char *title); - template - void AddKeyEvent(int key, void(*eh)(Args...)) - { - wnd->setOnKeyDown(key, eh); - } - /// Adds a conditionally-updatable scene event. template void AddKeyEvent(int key, bool (TScene::*eh)()) diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index b059db2a..f5c0e46c 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -21,7 +21,6 @@ using namespace mfem; using namespace std; -VisualizationSceneSolution3d *vssol3d; extern GeometryRefiner GLVisGeometryRefiner; // Definitions of some more keys @@ -236,61 +235,57 @@ void VisualizationSceneSolution3d::CPMoved() } } -static void KeyxPressed() +void VisualizationSceneSolution3d::RotateCPPhi() { - vssol3d -> CuttingPlane -> IncreasePhi(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> IncreasePhi(); + FindNodePos(); + CPMoved(); } -static void KeyXPressed() +void VisualizationSceneSolution3d::RotateCPPhiBack() { - vssol3d -> CuttingPlane -> DecreasePhi(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> DecreasePhi(); + FindNodePos(); + CPMoved(); } -static void KeyyPressed() +void VisualizationSceneSolution3d::RotateCPTheta() { - vssol3d -> CuttingPlane -> IncreaseTheta(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> IncreaseTheta(); + FindNodePos(); + CPMoved(); } -static void KeyYPressed() +void VisualizationSceneSolution3d::RotateCPThetaBack() { - vssol3d -> CuttingPlane -> DecreaseTheta(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> DecreaseTheta(); + FindNodePos(); + CPMoved(); } -static void KeyzPressed() +void VisualizationSceneSolution3d::TranslateCP() { - vssol3d -> CuttingPlane -> IncreaseDistance(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> IncreaseDistance(); + FindNodePos(); + CPMoved(); } -static void KeyZPressed() +void VisualizationSceneSolution3d::TranslateCPBack() { - vssol3d -> CuttingPlane -> DecreaseDistance(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> DecreaseDistance(); + FindNodePos(); + CPMoved(); } -static void KeyoPressed(GLenum state) +void KeyoPressed(GLVisWindow* wnd, GLenum state) { + VisualizationSceneSolution3d* vssol3d + = dynamic_cast(wnd->getScene()); if (state & KMOD_CTRL) { vssol3d -> ToggleDrawOrdering(); vssol3d -> PrepareOrderingCurve(); - SendExposeEvent(); + wnd -> SendExposeEvent(); } else { @@ -304,14 +299,16 @@ static void KeyoPressed(GLenum state) vssol3d -> PrepareLines(); vssol3d -> CPPrepare(); vssol3d -> PrepareLevelSurf(); - SendExposeEvent(); + wnd -> SendExposeEvent(); } } } } -static void KeyOPressed() +static void KeyOPressed(GLVisWindow* wnd) { + VisualizationSceneSolution3d* vssol3d + = dynamic_cast(wnd->getScene()); if (vssol3d -> TimesToRefine > 1) { cout << "Subdivision factor = " << --vssol3d->TimesToRefine << endl; @@ -322,166 +319,167 @@ static void KeyOPressed() vssol3d -> PrepareLines(); vssol3d -> CPPrepare(); vssol3d -> PrepareLevelSurf(); - SendExposeEvent(); + wnd -> SendExposeEvent(); } } } -static void KeywPressed() +bool VisualizationSceneSolution3d::MoveUpBdrElems() { - if (vssol3d -> GetShading() == 2) + if (GetShading() == 2) { - if ( fabs(vssol3d -> FaceShiftScale += 0.01) < 0.001 ) + if ( fabs(FaceShiftScale += 0.01) < 0.001 ) { - vssol3d -> FaceShiftScale = 0.0; + FaceShiftScale = 0.0; } - cout << "New Shift Scale: " << vssol3d -> FaceShiftScale + cout << "New Shift Scale: " << FaceShiftScale << endl; - vssol3d -> Prepare(); - vssol3d -> PrepareLines(); - vssol3d -> CPPrepare(); - SendExposeEvent(); + Prepare(); + PrepareLines(); + CPPrepare(); + return true; } + return false; } -static void KeyWPressed() +bool VisualizationSceneSolution3d::MoveDownBdrElems() { - if (vssol3d -> GetShading() == 2) + if (GetShading() == 2) { - if ( fabs(vssol3d -> FaceShiftScale -= 0.01) < 0.001 ) + if ( fabs(FaceShiftScale -= 0.01) < 0.001 ) { - vssol3d -> FaceShiftScale = 0.0; + FaceShiftScale = 0.0; } - cout << "New Shift Scale: " << vssol3d -> FaceShiftScale + cout << "New Shift Scale: " << FaceShiftScale << endl; - vssol3d -> Prepare(); - vssol3d -> PrepareLines(); - vssol3d -> CPPrepare(); - SendExposeEvent(); + Prepare(); + PrepareLines(); + CPPrepare(); + return true; } + return false; } -static void KeyuPressed() +void VisualizationSceneSolution3d::MoveUpLevelSurf() { - vssol3d -> MoveLevelSurf(+1); - SendExposeEvent(); + MoveLevelSurf(+1); } -static void KeyUPressed() +void VisualizationSceneSolution3d::MoveDownLevelSurf() { - vssol3d -> MoveLevelSurf(-1); - SendExposeEvent(); + MoveLevelSurf(-1); } -static void KeyvPressed() +void VisualizationSceneSolution3d::AddLevelSurf() { - vssol3d -> NumberOfLevelSurf(+1); - SendExposeEvent(); + NumberOfLevelSurf(+1); } -static void KeyVPressed() +void VisualizationSceneSolution3d::RemoveLevelSurf() { - vssol3d -> NumberOfLevelSurf(-1); - SendExposeEvent(); + NumberOfLevelSurf(-1); } static int magic_key_pressed = 0; -void ToggleMagicKey() +void ToggleMagicKey(GLVisWindow* wnd) { magic_key_pressed = 1-magic_key_pressed; } -static void KeyF3Pressed() +bool VisualizationSceneSolution3d::ShrinkBoundaryElems() { - if (vssol3d->GetShading() == 2) + if (GetShading() == 2) { - if (vssol3d->GetMesh()->Dimension() == 3 && vssol3d->bdrc.Width() == 0) + if (GetMesh()->Dimension() == 3 && bdrc.Width() == 0) { - vssol3d->ComputeBdrAttrCenter(); + ComputeBdrAttrCenter(); } - if (vssol3d->GetMesh()->Dimension() == 2 && vssol3d->matc.Width() == 0) + if (GetMesh()->Dimension() == 2 && matc.Width() == 0) { - vssol3d->ComputeElemAttrCenter(); + ComputeElemAttrCenter(); } - vssol3d->shrink *= 0.9; + shrink *= 0.9; if (magic_key_pressed) { - vssol3d -> Scale(1.11111111111111111111111); + Scale(1.11111111111111111111111); } - vssol3d->Prepare(); - vssol3d->PrepareLines(); - SendExposeEvent(); + Prepare(); + PrepareLines(); + return true; } + return false; } -static void KeyF4Pressed() +bool VisualizationSceneSolution3d::ZoomBoundaryElems() { - if (vssol3d->GetShading() == 2) + if (GetShading() == 2) { - if (vssol3d->GetMesh()->Dimension() == 3 && vssol3d->bdrc.Width() == 0) + if (GetMesh()->Dimension() == 3 && bdrc.Width() == 0) { - vssol3d->ComputeBdrAttrCenter(); + ComputeBdrAttrCenter(); } - if (vssol3d->GetMesh()->Dimension() == 2 && vssol3d->matc.Width() == 0) + if (GetMesh()->Dimension() == 2 && matc.Width() == 0) { - vssol3d->ComputeElemAttrCenter(); + ComputeElemAttrCenter(); } - vssol3d->shrink *= 1.11111111111111111111111; + shrink *= 1.11111111111111111111111; if (magic_key_pressed) { - vssol3d -> Scale(0.9); + Scale(0.9); } - vssol3d->Prepare(); - vssol3d->PrepareLines(); - SendExposeEvent(); + Prepare(); + PrepareLines(); + return true; } + return false; } -static void KeyF11Pressed() +bool VisualizationSceneSolution3d::ShrinkMatSubdomains() { - if (vssol3d->GetShading() == 2) + if (GetShading() == 2) { - if (vssol3d->matc.Width() == 0) + if (matc.Width() == 0) { - vssol3d->ComputeElemAttrCenter(); + ComputeElemAttrCenter(); } - vssol3d->shrinkmat *= 0.9; + shrinkmat *= 0.9; if (magic_key_pressed) { - vssol3d -> Scale(1.11111111111111111111111); + Scale(1.11111111111111111111111); } - vssol3d->Prepare(); - vssol3d->PrepareLines(); - SendExposeEvent(); + Prepare(); + PrepareLines(); + return true; } + return false; } -static void KeyF12Pressed() +bool VisualizationSceneSolution3d::ZoomMatSubdomains() { - if (vssol3d->GetShading() == 2) + if (GetShading() == 2) { - if (vssol3d->matc.Width() == 0) + if (matc.Width() == 0) { - vssol3d->ComputeElemAttrCenter(); + ComputeElemAttrCenter(); } - vssol3d->shrinkmat *= 1.11111111111111111111111; + shrinkmat *= 1.11111111111111111111111; if (magic_key_pressed) { - vssol3d -> Scale(0.9); + Scale(0.9); } - vssol3d->Prepare(); - vssol3d->PrepareLines(); - SendExposeEvent(); + Prepare(); + PrepareLines(); + return true; } + return false; } -static void KeyF8Pressed() +void VisualizationSceneSolution3d::QueryToggleSubdomains() { - Mesh &mesh = *vssol3d->GetMesh(); - int dim = mesh.Dimension(); - const Array &all_attr = ((dim == 3) ? mesh.bdr_attributes : - mesh.attributes); - Array &attr_marker = vssol3d->bdr_attr_to_show; + int dim = mesh->Dimension(); + const Array &all_attr = ((dim == 3) ? mesh->bdr_attributes : + mesh->attributes); + Array &attr_marker = bdr_attr_to_show; int attr; Array attr_list(&attr, 1); @@ -495,17 +493,15 @@ static void KeyF8Pressed() cout << ((dim == 3) ? "Bdr a" : "A") << "ttribute to toggle : " << flush; cin >> attr; - vssol3d->ToggleAttributes(attr_list); - SendExposeEvent(); + ToggleAttributes(attr_list); } -static void KeyF9Pressed() +void VisualizationSceneSolution3d::WalkNextSubdomain() { - Mesh &mesh = *vssol3d->GetMesh(); - int dim = mesh.Dimension(); - const Array &attr_list = ((dim == 3) ? mesh.bdr_attributes : - mesh.attributes); - Array &attr_marker = vssol3d->bdr_attr_to_show; + int dim = mesh->Dimension(); + const Array &attr_list = ((dim == 3) ? mesh->bdr_attributes : + mesh->attributes); + Array &attr_marker = bdr_attr_to_show; int attr, n, j, i; if (attr_list.Size() == 0) @@ -539,18 +535,16 @@ static void KeyF9Pressed() cout << "Showing " << ((dim == 3) ? "bdr " : "") << "attribute " << attr << endl; } - vssol3d -> PrepareLines(); - vssol3d -> Prepare(); - SendExposeEvent(); + PrepareLines(); + Prepare(); } -static void KeyF10Pressed() +void VisualizationSceneSolution3d::WalkPrevSubdomain() { - Mesh &mesh = *vssol3d->GetMesh(); - int dim = mesh.Dimension(); - const Array &attr_list = ((dim == 3) ? mesh.bdr_attributes : - mesh.attributes); - Array &attr_marker = vssol3d->bdr_attr_to_show; + int dim = mesh->Dimension(); + const Array &attr_list = ((dim == 3) ? mesh->bdr_attributes : + mesh->attributes); + Array &attr_marker = bdr_attr_to_show; int attr, n, j, i; if (attr_list.Size() == 0) @@ -585,9 +579,8 @@ static void KeyF10Pressed() cout << "Showing " << ((dim == 3) ? "bdr " : "") << "attribute " << attr << endl; } - vssol3d -> PrepareLines(); - vssol3d -> Prepare(); - SendExposeEvent(); + PrepareLines(); + Prepare(); } VisualizationSceneSolution3d::VisualizationSceneSolution3d() @@ -605,8 +598,6 @@ VisualizationSceneSolution3d::VisualizationSceneSolution3d(Mesh &m, Vector &s) void VisualizationSceneSolution3d::Init() { - vssol3d = this; - cplane = 0; cp_drawmesh = 0; cp_drawelems = 1; drawlsurf = 0; @@ -680,37 +671,37 @@ void VisualizationSceneSolution3d::Init() wnd->AddKeyEvent('i', &SceneType::ToggleCuttingPlane); wnd->AddKeyEvent('I', &SceneType::ToggleCPAlgorithm); - wnd->AddKeyEvent('o', KeyoPressed); - wnd->AddKeyEvent('O', KeyOPressed); + wnd->AddKeyEvent('o', KeyoPressed, false); + wnd->AddKeyEvent('O', KeyOPressed, false); - wnd->AddKeyEvent('w', KeywPressed); - wnd->AddKeyEvent('W', KeyWPressed); + wnd->AddKeyEvent('w', &SceneType::MoveUpBdrElems); + wnd->AddKeyEvent('W', &SceneType::MoveDownBdrElems); - wnd->AddKeyEvent('x', KeyxPressed); - wnd->AddKeyEvent('X', KeyXPressed); + wnd->AddKeyEvent('x', &SceneType::RotateCPPhi); + wnd->AddKeyEvent('X', &SceneType::RotateCPPhiBack); - wnd->AddKeyEvent('y', KeyyPressed); - wnd->AddKeyEvent('Y', KeyYPressed); + wnd->AddKeyEvent('y', &SceneType::RotateCPTheta); + wnd->AddKeyEvent('Y', &SceneType::RotateCPThetaBack); - wnd->AddKeyEvent('z', KeyzPressed); - wnd->AddKeyEvent('Z', KeyZPressed); + wnd->AddKeyEvent('z', &SceneType::TranslateCP); + wnd->AddKeyEvent('Z', &SceneType::TranslateCPBack); - wnd->AddKeyEvent('u', KeyuPressed); - wnd->AddKeyEvent('U', KeyUPressed); + wnd->AddKeyEvent('u', &SceneType::MoveUpLevelSurf); + wnd->AddKeyEvent('U', &SceneType::MoveDownLevelSurf); - wnd->AddKeyEvent('v', KeyvPressed); - wnd->AddKeyEvent('V', KeyVPressed); + wnd->AddKeyEvent('v', &SceneType::AddLevelSurf); + wnd->AddKeyEvent('V', &SceneType::RemoveLevelSurf); - wnd->AddKeyEvent(SDLK_F3, KeyF3Pressed); - wnd->AddKeyEvent(SDLK_F4, KeyF4Pressed); - wnd->AddKeyEvent(SDLK_NUMLOCKCLEAR, ToggleMagicKey); + wnd->AddKeyEvent(SDLK_F3, &SceneType::ShrinkBoundaryElems); + wnd->AddKeyEvent(SDLK_F4, &SceneType::ZoomBoundaryElems); + wnd->AddKeyEvent(SDLK_NUMLOCKCLEAR, ToggleMagicKey, false); - wnd->AddKeyEvent(SDLK_F8, KeyF8Pressed); - wnd->AddKeyEvent(SDLK_F9, KeyF9Pressed); - wnd->AddKeyEvent(SDLK_F10, KeyF10Pressed); + wnd->AddKeyEvent(SDLK_F8, &SceneType::QueryToggleSubdomains); + wnd->AddKeyEvent(SDLK_F9, &SceneType::WalkNextSubdomain); + wnd->AddKeyEvent(SDLK_F10, &SceneType::WalkPrevSubdomain); - wnd->AddKeyEvent(SDLK_F11, KeyF11Pressed); - wnd->AddKeyEvent(SDLK_F12, KeyF12Pressed); + wnd->AddKeyEvent(SDLK_F11, &SceneType::ShrinkMatSubdomains); + wnd->AddKeyEvent(SDLK_F12, &SceneType::ZoomMatSubdomains); } Prepare(); PrepareLines(); diff --git a/lib/vssolution3d.hpp b/lib/vssolution3d.hpp index 3640d82f..9da197ac 100644 --- a/lib/vssolution3d.hpp +++ b/lib/vssolution3d.hpp @@ -93,6 +93,31 @@ class VisualizationSceneSolution3d : public VisualizationSceneScalarData return (n < vertices.Size()); } + void RotateCPPhi(); + void RotateCPPhiBack(); + void RotateCPTheta(); + void RotateCPThetaBack(); + void TranslateCP(); + void TranslateCPBack(); + + bool MoveUpBdrElems(); + bool MoveDownBdrElems(); + + void MoveUpLevelSurf(); + void MoveDownLevelSurf(); + void AddLevelSurf(); + void RemoveLevelSurf(); + + void QueryToggleSubdomains(); + void WalkNextSubdomain(); + void WalkPrevSubdomain(); + + bool ShrinkBoundaryElems(); + bool ZoomBoundaryElems(); + bool ShrinkMatSubdomains(); + bool ZoomMatSubdomains(); + + public: int TimesToRefine; double FaceShiftScale; From 7408d75ada3465946c416dbfb68c295fad676c05 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 11:16:52 -0800 Subject: [PATCH 31/42] Make vssolution event handlers member functions --- lib/vssolution.cpp | 274 +++++++++++++++++++++++---------------------- lib/vssolution.hpp | 18 +++ 2 files changed, 159 insertions(+), 133 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 7148f6d9..66530e7d 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -24,8 +24,6 @@ using namespace mfem; using namespace std; -VisualizationSceneSolution *vssol; -extern VisualizationScene *locscene; extern GeometryRefiner GLVisGeometryRefiner; #ifdef GLVIS_ISFINITE @@ -122,15 +120,15 @@ std::string VisualizationSceneSolution::GetHelpString() const return os.str(); } -static void KeyF8Pressed() +void VisualizationSceneSolution::QueryToggleSubdomains() { int attr; Array attr_list(&attr, 1); - const Array &all_attr = vssol->GetMesh()->attributes; + const Array &all_attr = GetMesh()->attributes; cout << "El attributes ON: "; for (int i = 0; i < all_attr.Size(); i++) - if (vssol->el_attr_to_show[all_attr[i]-1]) + if (el_attr_to_show[all_attr[i]-1]) { cout << " " << all_attr[i]; } @@ -138,11 +136,11 @@ static void KeyF8Pressed() cout << "El attribute to toggle : " << flush; cin >> attr; - vssol->ToggleAttributes(attr_list); - SendExposeEvent(); + ToggleAttributes(attr_list); } -static void SwitchAttribute(int increment, int &attribute, +static void SwitchAttribute(VisualizationSceneSolution* vssol, + int increment, int &attribute, Array &attribute_marker, bool bdr) { @@ -190,97 +188,108 @@ static void SwitchAttribute(int increment, int &attribute, vssol->PrepareLines(); vssol->Prepare(); } - SendExposeEvent(); } -static void KeyF9Pressed(GLenum state) +static void KeyF9Pressed(GLVisWindow* wnd, GLenum state) { + VisualizationSceneSolution* vssol + = dynamic_cast(wnd->getScene()); if (!(state & KMOD_SHIFT)) { - SwitchAttribute(+1, vssol->attr_to_show, vssol->el_attr_to_show, false); + SwitchAttribute(vssol, +1, vssol->attr_to_show, vssol->el_attr_to_show, false); } else { - SwitchAttribute(+1, vssol->bdr_attr_to_show, vssol->bdr_el_attr_to_show, + SwitchAttribute(vssol, +1, vssol->bdr_attr_to_show, vssol->bdr_el_attr_to_show, true); } } -static void KeyF10Pressed(GLenum state) +static void KeyF10Pressed(GLVisWindow* wnd, GLenum state) { + VisualizationSceneSolution* vssol + = dynamic_cast(wnd->getScene()); if (!(state & KMOD_SHIFT)) { - SwitchAttribute(-1, vssol->attr_to_show, vssol->el_attr_to_show, false); + SwitchAttribute(vssol, -1, vssol->attr_to_show, vssol->el_attr_to_show, false); } else { - SwitchAttribute(-1, vssol->bdr_attr_to_show, vssol->bdr_el_attr_to_show, + SwitchAttribute(vssol, -1, vssol->bdr_attr_to_show, vssol->bdr_el_attr_to_show, true); } } -int refine_func = 0; - -static void KeyoPressed(GLenum state) +static void KeyoPressed(GLVisWindow* wnd, GLenum state) { + VisualizationSceneSolution* vssol + = dynamic_cast(wnd->getScene()); if (state & KMOD_CTRL) { vssol -> ToggleDrawOrdering(); vssol -> PrepareOrderingCurve(); - SendExposeEvent(); + wnd->SendExposeEvent(); } else { - int update = 1; - switch (refine_func) - { - case 0: - vssol -> TimesToRefine += vssol -> EdgeRefineFactor; - break; - case 1: - if (vssol -> TimesToRefine > vssol -> EdgeRefineFactor) - { - vssol -> TimesToRefine -= vssol -> EdgeRefineFactor; - } - else - { - update = 0; - } - break; - case 2: - vssol -> TimesToRefine /= vssol -> EdgeRefineFactor; - vssol -> EdgeRefineFactor ++; - vssol -> TimesToRefine *= vssol -> EdgeRefineFactor; - break; - case 3: - if (vssol -> EdgeRefineFactor > 1) - { - vssol -> TimesToRefine /= vssol -> EdgeRefineFactor; - vssol -> EdgeRefineFactor --; - vssol -> TimesToRefine *= vssol -> EdgeRefineFactor; - } - else - { - update = 0; - } - break; - } - if (update && vssol -> shading == 2) - { - vssol -> DoAutoscale(false); - vssol -> PrepareLines(); - vssol -> PrepareBoundary(); - vssol -> Prepare(); - vssol -> PrepareLevelCurves(); - vssol -> PrepareCP(); - SendExposeEvent(); - } - cout << "Subdivision factors = " << vssol -> TimesToRefine - << ", " << vssol -> EdgeRefineFactor << endl; + vssol -> DoRefineFunc(); + wnd->SendExposeEvent(); } } -static void KeyOPressed(GLenum state) +bool VisualizationSceneSolution::DoRefineFunc() +{ + int update = 1; + switch (refine_func) + { + case 0: + TimesToRefine += EdgeRefineFactor; + break; + case 1: + if (TimesToRefine > EdgeRefineFactor) + { + TimesToRefine -= EdgeRefineFactor; + } + else + { + update = 0; + } + break; + case 2: + TimesToRefine /= EdgeRefineFactor; + EdgeRefineFactor ++; + TimesToRefine *= EdgeRefineFactor; + break; + case 3: + if (EdgeRefineFactor > 1) + { + TimesToRefine /= EdgeRefineFactor; + EdgeRefineFactor --; + TimesToRefine *= EdgeRefineFactor; + } + else + { + update = 0; + } + break; + } + cout << "Subdivision factors = " << TimesToRefine + << ", " << EdgeRefineFactor << endl; + if (update && shading == 2) + { + DoAutoscale(false); + PrepareLines(); + PrepareBoundary(); + Prepare(); + PrepareLevelCurves(); + PrepareCP(); + return true; + } + return false; +} + +//static void KeyOPressed(GLenum state) +void VisualizationSceneSolution::ToggleRefineFunc() { refine_func = (refine_func+1)%4; cout << "Key 'o' will: "; @@ -306,95 +315,95 @@ void KeyIPressed() // no-op, available } -static void KeyyPressed() +void VisualizationSceneSolution::RotateCP() { - vssol->CuttingPlane->IncreaseTheta(); - vssol->PrepareCP(); - SendExposeEvent(); + CuttingPlane->IncreaseTheta(); + PrepareCP(); } -static void KeyYPressed() +void VisualizationSceneSolution::RotateCPBack() { - vssol->CuttingPlane->DecreaseTheta(); - vssol->PrepareCP(); - SendExposeEvent(); + CuttingPlane->DecreaseTheta(); + PrepareCP(); } -static void KeyzPressed() +void VisualizationSceneSolution::TranslateCP() { - vssol->CuttingPlane->IncreaseDistance(); - vssol->PrepareCP(); - SendExposeEvent(); + CuttingPlane->IncreaseDistance(); + PrepareCP(); } -static void KeyZPressed() +void VisualizationSceneSolution::TranslateCPBack() { - vssol->CuttingPlane->DecreaseDistance(); - vssol->PrepareCP(); - SendExposeEvent(); + CuttingPlane->DecreaseDistance(); + PrepareCP(); } -static void KeyF3Pressed() +bool VisualizationSceneSolution::ShrinkElements() { - if (vssol->shading == 2) + if (shading == 2) { - vssol->shrink *= 0.9; - vssol->Prepare(); - vssol->PrepareLines(); - vssol->PrepareLevelCurves(); - vssol->PrepareNumbering(); - vssol->PrepareOrderingCurve(); - SendExposeEvent(); + shrink *= 0.9; + Prepare(); + PrepareLines(); + PrepareLevelCurves(); + PrepareNumbering(); + PrepareOrderingCurve(); + return true; } + return false; } -static void KeyF4Pressed() +bool VisualizationSceneSolution::ZoomElements() { - if (vssol->shading == 2) + if (shading == 2) { - vssol->shrink *= 1.11111111111111111111111; - vssol->Prepare(); - vssol->PrepareLines(); - vssol->PrepareLevelCurves(); - vssol->PrepareNumbering(); - SendExposeEvent(); + shrink *= 1.11111111111111111111111; + Prepare(); + PrepareLines(); + PrepareLevelCurves(); + PrepareNumbering(); + return true; } + return false; } -static void KeyF11Pressed() +bool VisualizationSceneSolution::ShrinkMatSubdomains() { - if (vssol->shading == 2) + if (shading == 2) { - if (vssol->matc.Width() == 0) + if (matc.Width() == 0) { - vssol->ComputeElemAttrCenter(); + ComputeElemAttrCenter(); } - vssol->shrinkmat *= 0.9; - vssol->Prepare(); - vssol->PrepareLines(); - vssol->PrepareBoundary(); - vssol->PrepareLevelCurves(); - vssol->PrepareNumbering(); - SendExposeEvent(); + shrinkmat *= 0.9; + Prepare(); + PrepareLines(); + PrepareBoundary(); + PrepareLevelCurves(); + PrepareNumbering(); + return true; } + return false; } -static void KeyF12Pressed() +bool VisualizationSceneSolution::ZoomMatSubdomains() { - if (vssol->shading == 2) + if (shading == 2) { - if (vssol->matc.Width() == 0) + if (matc.Width() == 0) { - vssol->ComputeElemAttrCenter(); + ComputeElemAttrCenter(); } - vssol->shrinkmat *= 1.11111111111111111111111; - vssol->Prepare(); - vssol->PrepareLines(); - vssol->PrepareBoundary(); - vssol->PrepareLevelCurves(); - vssol->PrepareNumbering(); - SendExposeEvent(); + shrinkmat *= 1.11111111111111111111111; + Prepare(); + PrepareLines(); + PrepareBoundary(); + PrepareLevelCurves(); + PrepareNumbering(); + return true; } + return false; } VisualizationSceneSolution::VisualizationSceneSolution() @@ -415,7 +424,6 @@ VisualizationSceneSolution::VisualizationSceneSolution( void VisualizationSceneSolution::Init() { rsol = NULL; - vssol = this; drawelems = shading = 1; drawmesh = 0; @@ -463,8 +471,8 @@ void VisualizationSceneSolution::Init() wnd->AddKeyEvent('n', &SceneType::ToggleDrawNumberings); wnd->AddKeyEvent('N', &SceneType::ToggleDrawNumberings); - wnd->AddKeyEvent('o', KeyoPressed); - wnd->AddKeyEvent('O', KeyOPressed); + wnd->AddKeyEvent('o', KeyoPressed, false); // expose handled in function + wnd->AddKeyEvent('O', &SceneType::ToggleRefineFunc); wnd->AddKeyEvent('e', &SceneType::ToggleDrawElems); wnd->AddKeyEvent('E', &SceneType::ToggleDrawElems); @@ -475,18 +483,18 @@ void VisualizationSceneSolution::Init() wnd->AddKeyEvent('i', &SceneType::ToggleDrawCP); //wnd->AddKeyEvent('I', KeyIPressed); - wnd->AddKeyEvent('y', KeyyPressed); - wnd->AddKeyEvent('Y', KeyYPressed); - wnd->AddKeyEvent('z', KeyzPressed); - wnd->AddKeyEvent('Z', KeyZPressed); + wnd->AddKeyEvent('y', &SceneType::RotateCP); + wnd->AddKeyEvent('Y', &SceneType::RotateCPBack); + wnd->AddKeyEvent('z', &SceneType::TranslateCP); + wnd->AddKeyEvent('Z', &SceneType::TranslateCPBack); - wnd->AddKeyEvent(SDLK_F3, KeyF3Pressed); - wnd->AddKeyEvent(SDLK_F4, KeyF4Pressed); - wnd->AddKeyEvent(SDLK_F8, KeyF8Pressed); + wnd->AddKeyEvent(SDLK_F3, &SceneType::ShrinkElements); + wnd->AddKeyEvent(SDLK_F4, &SceneType::ZoomElements); + wnd->AddKeyEvent(SDLK_F8, &SceneType::QueryToggleSubdomains); wnd->AddKeyEvent(SDLK_F9, KeyF9Pressed); wnd->AddKeyEvent(SDLK_F10, KeyF10Pressed); - wnd->AddKeyEvent(SDLK_F11, KeyF11Pressed); - wnd->AddKeyEvent(SDLK_F12, KeyF12Pressed); + wnd->AddKeyEvent(SDLK_F11, &SceneType::ShrinkMatSubdomains); + wnd->AddKeyEvent(SDLK_F12, &SceneType::ZoomMatSubdomains); } Prepare(); diff --git a/lib/vssolution.hpp b/lib/vssolution.hpp index a49e83e8..adcd73aa 100644 --- a/lib/vssolution.hpp +++ b/lib/vssolution.hpp @@ -74,6 +74,22 @@ class VisualizationSceneSolution : public VisualizationSceneScalarData // slow. Turn it off above some entity count. static const int MAX_RENDER_NUMBERING = 1000; + void RotateCP(); + void RotateCPBack(); + void TranslateCP(); + void TranslateCPBack(); + + bool ShrinkElements(); + bool ZoomElements(); + + void QueryToggleSubdomains(); + + bool ShrinkMatSubdomains(); + bool ZoomMatSubdomains(); + + int refine_func = 0; + + public: int shading, TimesToRefine, EdgeRefineFactor; @@ -153,6 +169,8 @@ class VisualizationSceneSolution : public VisualizationSceneScalarData void ToggleDrawCP() { draw_cp = !draw_cp; PrepareCP(); } + void ToggleRefineFunc(); + bool DoRefineFunc(); virtual void SetRefineFactors(int, int); virtual void AutoRefine(); virtual void ToggleAttributes(Array &attr_list); From 83a228844ef40939a8a9066ff94585ea8f18bf16 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 11:22:31 -0800 Subject: [PATCH 32/42] Make vsvector event handlers member functions --- lib/vsvector.cpp | 33 +++++++++++---------------------- lib/vsvector.hpp | 4 ++++ 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 3a4a501c..33b93b3c 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -99,9 +99,6 @@ std::string VisualizationSceneVector::GetHelpString() const return os.str(); } -VisualizationSceneVector * vsvector; -extern VisualizationScene * locscene; -extern VisualizationSceneSolution * vssol; extern GeometryRefiner GLVisGeometryRefiner; void VisualizationSceneVector::NextDisplacement() @@ -134,22 +131,19 @@ void VisualizationSceneVector::QueryArrowScaling() PrepareVectorField(); } -int key_u_func = 0; - -void KeyuPressed() +void VisualizationSceneVector::DoKeyU() { int update = 1; - switch (key_u_func) { case 0: - vsvector->RefineFactor++; + RefineFactor++; break; case 1: - if (vsvector->RefineFactor > 1) + if (RefineFactor > 1) { - vsvector->RefineFactor--; + RefineFactor--; } else { @@ -158,8 +152,7 @@ void KeyuPressed() break; case 2: - vsvector->CycleVec2Scalar(1); - SendExposeEvent(); + CycleVec2Scalar(1); break; } @@ -167,13 +160,11 @@ void KeyuPressed() { case 0: case 1: - if (update && vsvector->shading == 2) + if (update && shading == 2) { - vsvector->PrepareVectorField(); - SendExposeEvent(); + PrepareVectorField(); } - cout << "Vector subdivision factor = " - << vsvector->RefineFactor << endl; + cout << "Vector subdivision factor = " << RefineFactor << endl; break; case 2: @@ -181,7 +172,7 @@ void KeyuPressed() } } -void KeyUPressed() +void VisualizationSceneVector::ToggleKeyUFunc() { key_u_func = (key_u_func+1)%3; cout << "Key 'u' will: "; @@ -475,8 +466,6 @@ void VisualizationSceneVector::Init() PrepareVectorField(); // PrepareDisplacedMesh(); // called by PrepareLines() - vsvector = this; - // static int init = 0; // if (!init) { @@ -490,8 +479,8 @@ void VisualizationSceneVector::Init() wnd->AddKeyEvent('b', &SceneType::PrevDisplacement); wnd->AddKeyEvent('v', &SceneType::ToggleVectorField); wnd->AddKeyEvent('V', &SceneType::QueryArrowScaling); - wnd->AddKeyEvent('u', KeyuPressed); - wnd->AddKeyEvent('U', KeyUPressed); + wnd->AddKeyEvent('u', &SceneType::DoKeyU); + wnd->AddKeyEvent('U', &SceneType::ToggleKeyUFunc); } // Vec2Scalar is VecLength diff --git a/lib/vsvector.hpp b/lib/vsvector.hpp index 8d5fdd7a..76a58ff6 100644 --- a/lib/vsvector.hpp +++ b/lib/vsvector.hpp @@ -52,6 +52,10 @@ class VisualizationSceneVector : public VisualizationSceneSolution void QueryArrowScaling(); + int key_u_func = 0; + void ToggleKeyUFunc(); + void DoKeyU(); + public: VisualizationSceneVector(Mesh &m, Vector &sx, Vector &sy); VisualizationSceneVector(GridFunction &vgf); From bdd2aa2c190f4374d453d7ccc7b764e79c8f8eb4 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 11:41:31 -0800 Subject: [PATCH 33/42] Convert last of vsdata event handlers --- glvis.cpp | 1 + lib/threads.cpp | 2 +- lib/vsdata.cpp | 121 +++++++++++++++++++++++------------------------- lib/vsdata.hpp | 16 +++++-- 4 files changed, 73 insertions(+), 67 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index ea53e051..337c370a 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -621,6 +621,7 @@ void ExecuteScriptCommand(GLVisWindow* wnd) char delim; scr >> ws >> delim; getline(scr, plot_caption, delim); + vs->SetCaption(plot_caption); vs->PrepareCaption(); // turn on or off the caption wnd->MyExpose(); } diff --git a/lib/threads.cpp b/lib/threads.cpp index 0b87c7f2..0850f843 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -501,7 +501,7 @@ int GLVisCommand::Execute() case PLOT_CAPTION: { cout << "Command: plot_caption: " << plot_caption << endl; - ::plot_caption = plot_caption; + vs->SetCaption(plot_caption); vs->PrepareCaption(); // turn on or off the caption window->MyExpose(); break; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index fa2afa42..4eeccdc2 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -463,14 +463,12 @@ void VisualizationSceneScalarData::PrepareCaption() font->getObjectSize(caption, caption_w, caption_h); } -VisualizationSceneScalarData * vsdata; - -void KeyCPressed() +//void KeyCPressed() +void VisualizationSceneScalarData::QueryCaption() { cout << "Enter new caption: " << flush; std::getline(cin, plot_caption); - vsdata->PrepareCaption(); // turn on or off the caption - SendExposeEvent(); + PrepareCaption(); // turn on or off the caption } void Key_Mod_a_Pressed(GLVisWindow* wnd, GLenum state) @@ -492,15 +490,15 @@ void Key_Mod_a_Pressed(GLVisWindow* wnd, GLenum state) } } -void KeyHPressed() +//void KeyHPressed() +void VisualizationSceneScalarData::PrintHelpString() { - cout << vsdata->GetHelpString() << flush; + cout << GetHelpString() << flush; } -void KeyLPressed() +void VisualizationSceneScalarData::ToggleLogscale() { - vsdata->ToggleLogscale(true); - SendExposeEvent(); + ToggleLogscale(true); } void VisualizationSceneScalarData::Reset3DView() @@ -526,13 +524,15 @@ void KeypPressed(GLVisWindow* wnd, GLenum state) } } -void KeyPPressed() +void KeyPPressed(GLVisWindow* wnd) { + VisualizationSceneScalarData * vsdata + = dynamic_cast(wnd->getScene()); vsdata->GetPalette().PrevPalette(); - SendExposeEvent(); } -static void KeyF5Pressed() +//static void KeyF5Pressed() +void VisualizationSceneScalarData::QueryLevelLines() { int n; double min, max; @@ -544,15 +544,15 @@ static void KeyF5Pressed() cout << "Enter n : " << flush; cin >> n; - vsdata -> SetLevelLines (min, max, n, 0); + SetLevelLines (min, max, n, 0); - vsdata -> UpdateLevelLines(); - SendExposeEvent(); + UpdateLevelLines(); } -void KeyF6Pressed() +//void KeyF6Pressed() +void VisualizationSceneScalarData::QueryPaletteSettings() { - int RepeatPaletteTimes = vsdata->GetPalette().GetRepeatTimes(); + int RepeatPaletteTimes = GetPalette().GetRepeatTimes(); cout << "Palette is repeated " << RepeatPaletteTimes << " times.\n" << "(Negative value means the palette is flipped.)\n" << "Enter new value: " << flush; @@ -563,31 +563,32 @@ void KeyF6Pressed() } cout << "Palette will be repeated " << RepeatPaletteTimes << " times now.\n\n"; - vsdata->GetPalette().SetRepeatTimes(RepeatPaletteTimes); + GetPalette().SetRepeatTimes(RepeatPaletteTimes); - int pal = vsdata->GetPalette().ChoosePalette(); + int pal = GetPalette().ChoosePalette(); - int colors_used = vsdata->GetPalette().GetNumColors(pal); - int palette_size = vsdata->GetPalette().GetSize(pal); + int colors_used = GetPalette().GetNumColors(pal); + int palette_size = GetPalette().GetSize(pal); cout << "\nPalette is using " << colors_used << " colors.\n" << "Enter new value (0 = use original " << palette_size << " colors): " << flush; cin >> colors_used; if (colors_used == 1) { colors_used = 0; } - vsdata->GetPalette().SetNumColors(colors_used); + GetPalette().SetNumColors(colors_used); - vsdata->GetPalette().Init(); - vsdata->GetPalette().SetPalette(pal); + GetPalette().Init(); + GetPalette().SetPalette(pal); - colors_used = vsdata->GetPalette().GetNumColors(); + colors_used = GetPalette().GetNumColors(); cout << "Palette will be using " << colors_used << " colors now.\n"; - vsdata->EventUpdateColors(); - SendExposeEvent(); + EventUpdateColors(); } -void KeyF7Pressed(GLenum state) +void KeyF7Pressed(GLVisWindow* wnd, GLenum state) { + VisualizationSceneScalarData * vsdata + = dynamic_cast(wnd->getScene()); if (state & KMOD_SHIFT) { cout << "Current bounding box:\n" @@ -614,7 +615,6 @@ void KeyF7Pressed(GLenum state) << " max: (" << vsdata->x[1] << ',' << vsdata->y[1] << ',' << vsdata->z[1] << ")\n" << flush; vsdata->UpdateBoundingBox(); - SendExposeEvent(); } else { @@ -625,11 +625,11 @@ void KeyF7Pressed(GLenum state) cout << "New value for maxv: " << flush; cin >> vsdata->GetMaxV(); vsdata->UpdateValueRange(true); - SendExposeEvent(); } } -void KeyBackslashPressed() +//void KeyBackslashPressed() +void VisualizationSceneScalarData::QueryLightPosition() { float x, y, z, w; @@ -645,34 +645,32 @@ void KeyBackslashPressed() cout << "w = " << flush; cin >> w; - vsdata->SetLight0CustomPos({x, y, z, w}); - SendExposeEvent(); + SetLight0CustomPos({x, y, z, w}); } -void KeyTPressed() +//void KeyTPressed() +void VisualizationSceneScalarData::NextLightMatSetting() { int ml; - ml = (vsdata->GetLightMatIdx() + 1) % 5; - vsdata->SetLightMatIdx(ml); - SendExposeEvent(); + ml = (GetLightMatIdx() + 1) % 5; + SetLightMatIdx(ml); cout << "New material/light : " << ml << endl; } -void KeyGPressed() +void VisualizationSceneScalarData::ToggleBackground() { - vsdata->ToggleBackground(); - vsdata->PrepareAxes(); - vsdata->EventUpdateBackground(); - SendExposeEvent(); + VisualizationScene::ToggleBackground(); + PrepareAxes(); + EventUpdateBackground(); } -void KeyF2Pressed() +//void KeyF2Pressed() +void VisualizationSceneScalarData::RedrawColors() { - vsdata -> EventUpdateColors(); - vsdata -> PrepareLines(); - // vsdata->CPPrepare(); - SendExposeEvent(); + EventUpdateColors(); + PrepareLines(); + // CPPrepare(); } void VisualizationSceneScalarData::PrintLogscale(bool warn) @@ -964,9 +962,6 @@ VisualizationSceneScalarData::VisualizationSceneScalarData( void VisualizationSceneScalarData::Init() { - vsdata = this; - wnd = GetAppWindow(); - arrow_type = arrow_scaling_type = 0; scaling = 0; drawaxes = colorbar = 0; @@ -991,7 +986,7 @@ void VisualizationSceneScalarData::Init() using SceneType = VisualizationSceneScalarData; wnd->AddKeyEvent('l', &SceneType::ToggleLight); - wnd->AddKeyEvent('L', KeyLPressed); + wnd->AddKeyEvent('L', &SceneType::ToggleLogscale); wnd->AddKeyEvent('s', &SceneType::ToggleScaling); @@ -1004,28 +999,28 @@ void VisualizationSceneScalarData::Init() wnd->AddKeyEvent('p', KeypPressed); wnd->AddKeyEvent('P', KeyPPressed); - wnd->AddKeyEvent('h', KeyHPressed); - wnd->AddKeyEvent('H', KeyHPressed); + wnd->AddKeyEvent('h', &SceneType::PrintHelpString); + wnd->AddKeyEvent('H', &SceneType::PrintHelpString); - wnd->AddKeyEvent(SDLK_F5, KeyF5Pressed); - wnd->AddKeyEvent(SDLK_F6, KeyF6Pressed); + wnd->AddKeyEvent(SDLK_F5, &SceneType::QueryLevelLines); + wnd->AddKeyEvent(SDLK_F6, &SceneType::QueryPaletteSettings); wnd->AddKeyEvent(SDLK_F7, KeyF7Pressed); - wnd->AddKeyEvent(SDLK_BACKSLASH, KeyBackslashPressed); - wnd->AddKeyEvent('t', KeyTPressed); - wnd->AddKeyEvent('T', KeyTPressed); + wnd->AddKeyEvent(SDLK_BACKSLASH, &SceneType::QueryLightPosition); + wnd->AddKeyEvent('t', &SceneType::NextLightMatSetting); + wnd->AddKeyEvent('T', &SceneType::NextLightMatSetting); - wnd->AddKeyEvent('g', KeyGPressed); - wnd->AddKeyEvent('G', KeyGPressed); + wnd->AddKeyEvent('g', &SceneType::ToggleBackground); + wnd->AddKeyEvent('G', &SceneType::ToggleBackground); wnd->AddKeyEvent('c', &SceneType::ToggleDrawColorbar); - wnd->AddKeyEvent('C', KeyCPressed); + wnd->AddKeyEvent('C', &SceneType::QueryCaption); wnd->AddKeyEvent('k', &SceneType::DecrementAlpha); wnd->AddKeyEvent('K', &SceneType::IncrementAlpha); wnd->AddKeyEvent(SDLK_F1, &SceneType::PrintState, false); - wnd->AddKeyEvent(SDLK_F2, KeyF2Pressed); + wnd->AddKeyEvent(SDLK_F2, &SceneType::RedrawColors); wnd->AddKeyEvent(SDLK_COMMA, &SceneType::DecrementAlphaCenter); wnd->AddKeyEvent(SDLK_LESS, &SceneType::IncrementAlphaCenter); diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index d3448b5e..5d92ddd4 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -19,9 +19,6 @@ using namespace mfem; -extern std::string plot_caption; // defined in glvis.cpp -extern std::string extra_caption; // defined in glvis.cpp - class Plane { private: @@ -61,6 +58,8 @@ class VisualizationSceneScalarData : public VisualizationScene double minv, maxv; + std::string plot_caption = ""; + std::string extra_caption = ""; std::string a_label_x, a_label_y, a_label_z; int scaling, colorbar, drawaxes; @@ -127,6 +126,16 @@ class VisualizationSceneScalarData : public VisualizationScene void Cone(gl3::GlBuilder& builder, glm::mat4 transform); + void PrintHelpString(); + void QueryCaption(); + void QueryLevelLines(); + void QueryPaletteSettings(); + void QueryLightPosition(); + void NextLightMatSetting(); + void RedrawColors(); + void ToggleBackground(); + void ToggleLogscale(); + public: Plane *CuttingPlane; int key_r_state; @@ -240,6 +249,7 @@ class VisualizationSceneScalarData : public VisualizationScene Array * level = NULL, Array * levels = NULL); + void SetCaption(std::string caption) { plot_caption = caption; } void SetAxisLabels(const char * a_x, const char * a_y, const char * a_z); void PrepareAxes(); From a97d4446c4e7d975f1605322695aef330435747d Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 12:20:06 -0800 Subject: [PATCH 34/42] Move resource types into gl/types.hpp --- lib/gl/renderer.cpp | 14 ++++----- lib/gl/renderer.hpp | 69 ++------------------------------------------ lib/gl/types.hpp | 70 +++++++++++++++++++++++++++++++++++++++++++++ lib/palettes.hpp | 4 +-- 4 files changed, 81 insertions(+), 76 deletions(-) diff --git a/lib/gl/renderer.cpp b/lib/gl/renderer.cpp index 647dec01..d8622e18 100644 --- a/lib/gl/renderer.cpp +++ b/lib/gl/renderer.cpp @@ -115,15 +115,15 @@ void MeshRenderer::render(const RenderQueue& queue) { return !renderPair.first.contains_translucent; }); - GLDevice::RenderBufHandle renderBufs[2]; - GLDevice::FBOHandle msaaFb; + RenderBufHandle renderBufs[2]; + FBOHandle msaaFb; if (feat_use_fbo_antialias && msaa_enable) { GLuint colorBuf, depthBuf; glGenRenderbuffers(1, &colorBuf); glGenRenderbuffers(1, &depthBuf); - renderBufs[0] = GLDevice::RenderBufHandle(colorBuf); - renderBufs[1] = GLDevice::RenderBufHandle(depthBuf); + renderBufs[0] = RenderBufHandle(colorBuf); + renderBufs[1] = RenderBufHandle(depthBuf); GLuint fbo; glGenFramebuffers(1, &fbo); @@ -154,7 +154,7 @@ void MeshRenderer::render(const RenderQueue& queue) } else { - msaaFb = GLDevice::FBOHandle(fbo); + msaaFb = FBOHandle(fbo); } #ifndef __EMSCRIPTEN__ glEnable(GL_MULTISAMPLE); @@ -252,11 +252,11 @@ void MeshRenderer::render(const RenderQueue& queue) int height = vp[3]; GLuint colorBufId; glGenRenderbuffers(1, &colorBufId); - GLDevice::RenderBufHandle colorBuf(colorBufId); + RenderBufHandle colorBuf(colorBufId); GLuint fboId; glGenFramebuffers(1, &fboId); - GLDevice::FBOHandle resolveFb(fboId); + FBOHandle resolveFb(fboId); glBindRenderbuffer(GL_RENDERBUFFER, colorBuf); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); diff --git a/lib/gl/renderer.hpp b/lib/gl/renderer.hpp index 4a811e46..b11ee9d5 100644 --- a/lib/gl/renderer.hpp +++ b/lib/gl/renderer.hpp @@ -25,6 +25,8 @@ namespace gl3 { +using namespace resource; + const int LIGHTS_MAX = 3; #ifdef GLVIS_MS_LINEWIDTH const float LINE_WIDTH_AA = GLVIS_MS_LINEWIDTH; @@ -102,73 +104,6 @@ class GLDevice std::array static_color; - // RAII scope guard for OpenGL handles. - template - class Handle - { - GLuint hnd; - public: - Handle() : hnd{0} {} - Handle(GLuint h) : hnd{h} {} - ~Handle() { if (hnd) { GLFinalizer(hnd); } } - Handle(Handle&& other) - : hnd{other.hnd} { other.hnd = 0; } - Handle& operator = (Handle&& other) noexcept - { - if (this != &other) - { - hnd = other.hnd; - other.hnd = 0; - } - return *this; - } - operator GLuint() const { return hnd; } - }; - - static void boCleanup(GLuint vbo_hnd) - { - glDeleteBuffers(1, &vbo_hnd); - } - - static void dspListCleanup(GLuint dlist) - { - glDeleteLists(dlist, 1); - } - - static void prgmCleanup(GLuint prgm) - { - glDeleteProgram(prgm); - } - - static void vaoCleanup(GLuint vao) - { - glDeleteVertexArrays(1, &vao); - } - - static void texCleanup(GLuint tex) - { - glDeleteTextures(1, &tex); - } - - static void fboCleanup(GLuint fbo) - { - glDeleteFramebuffers(1, &fbo); - } - - static void rboCleanup(GLuint rbo) - { - glDeleteRenderbuffers(1, &rbo); - } -public: - - using BufObjHandle = Handle; - using DispListHandle = Handle; - using VtxArrayHandle = Handle; - using ShaderPrgmHandle = Handle; - using TextureHandle = Handle; - using FBOHandle = Handle; - using RenderBufHandle = Handle; - protected: TextureHandle passthrough_texture; diff --git a/lib/gl/types.hpp b/lib/gl/types.hpp index eda252f9..37e050e7 100644 --- a/lib/gl/types.hpp +++ b/lib/gl/types.hpp @@ -38,6 +38,76 @@ using namespace std; namespace gl3 { +namespace resource +{ +// RAII scope guard for OpenGL handles. +template +class Handle +{ + GLuint hnd; +public: + Handle() : hnd{0} {} + Handle(GLuint h) : hnd{h} {} + ~Handle() { if (hnd) { GLFinalizer(hnd); } } + Handle(Handle&& other) + : hnd{other.hnd} { other.hnd = 0; } + Handle& operator = (Handle&& other) noexcept + { + if (this != &other) + { + hnd = other.hnd; + other.hnd = 0; + } + return *this; + } + operator GLuint() const { return hnd; } +}; + +static void boCleanup(GLuint vbo_hnd) +{ + glDeleteBuffers(1, &vbo_hnd); +} + +static void dspListCleanup(GLuint dlist) +{ + glDeleteLists(dlist, 1); +} + +static void prgmCleanup(GLuint prgm) +{ + glDeleteProgram(prgm); +} + +static void vaoCleanup(GLuint vao) +{ + glDeleteVertexArrays(1, &vao); +} + +static void texCleanup(GLuint tex) +{ + glDeleteTextures(1, &tex); +} + +static void fboCleanup(GLuint fbo) +{ + glDeleteFramebuffers(1, &fbo); +} + +static void rboCleanup(GLuint rbo) +{ + glDeleteRenderbuffers(1, &rbo); +} + +using BufObjHandle = Handle; +using DispListHandle = Handle; +using VtxArrayHandle = Handle; +using ShaderPrgmHandle = Handle; +using TextureHandle = Handle; +using FBOHandle = Handle; +using RenderBufHandle = Handle; + +} // end namespace resource + struct GlMatrix { glm::mat4 mtx; diff --git a/lib/palettes.hpp b/lib/palettes.hpp index b8742aba..9dfa04f2 100644 --- a/lib/palettes.hpp +++ b/lib/palettes.hpp @@ -11,7 +11,7 @@ #ifndef GLVIS_PALETTES_HPP #define GLVIS_PALETTES_HPP -#include "gl/renderer.hpp" +#include "gl/types.hpp" #include #include @@ -57,7 +57,7 @@ class PaletteState private: void ToTextureDiscrete(double * palette, size_t plt_size, GLuint tex); void ToTextureSmooth(double * palette, size_t plt_size, GLuint tex); - using TexHandle = gl3::GLDevice::TextureHandle; + using TexHandle = gl3::resource::TextureHandle; std::vector> palette_tex; TexHandle alpha_tex; From 28b64a727844d174f1981d79eddc1c57f1dd3aa5 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 12:21:57 -0800 Subject: [PATCH 35/42] Remove SdlWindow reference from vsdata --- lib/aux_vis.cpp | 3 +++ lib/openglvis.hpp | 4 ++-- lib/vsdata.cpp | 10 +++------- lib/vsdata.hpp | 8 ++++++++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 90c761f6..122f043e 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -494,6 +494,9 @@ void GLVisWindow::MyExpose(GLsizei w, GLsizei h) std::array bgcol = locscene->GetBackgroundColor(); wnd->getRenderer().setClearColor(bgcol[0], bgcol[1], bgcol[2], bgcol[3]); + int wnd_w, wnd_h; + wnd->getWindowSize(wnd_w, wnd_h); + locscene->UpdateWindowSize(wnd_w, wnd_h, w, h); gl3::SceneInfo frame = locscene->GetSceneObjs(); for (auto drawable_ptr : frame.needs_buffering) { diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index a181ad9e..5457e9b1 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -65,8 +65,6 @@ class VisualizationScene // How to scale the visualized object(s) double xscale, yscale, zscale; - SdlWindow * wnd; - glm::mat4 proj_mtx; enum @@ -152,6 +150,8 @@ class VisualizationScene float matAlpha = 1.0; float matAlphaCenter = 0.5; + /// Needs to be called before GetSceneObjs() + virtual void UpdateWindowSize(int w, int h, int gl_w, int gl_h) = 0; virtual gl3::SceneInfo GetSceneObjs() = 0; void SetView(double theta, double phi); diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index 4eeccdc2..e3dbabe1 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -859,8 +859,6 @@ void VisualizationSceneScalarData::Toggle2DView() gl3::SceneInfo VisualizationSceneScalarData::GetSceneObjs() { - int w, h; - wnd->getWindowSize(w, h); gl3::SceneInfo scene {}; scene.needs_buffering = std::move(updated_bufs); updated_bufs.clear(); @@ -885,13 +883,11 @@ gl3::SceneInfo VisualizationSceneScalarData::GetSceneObjs() { // caption size is in screen pixels and needs to be centered with // GL pixel size - int gl_w, gl_h; - wnd->getGLDrawSize(gl_w, gl_h); // add caption to draw list double v_pos = 2.; double line_h = font->getFontLineSpacing(); - params.model_view.translate(-(double)caption_w / gl_w, - 1.0 - 2 * v_pos * line_h / gl_h, 0.0); + params.model_view.translate(-(double)caption_w / draw_w, + 1.0 - 2 * v_pos * line_h / draw_h, 0.0); scene.queue.emplace_back(params, &caption_buf); } params.contains_translucent = true; @@ -901,7 +897,7 @@ gl3::SceneInfo VisualizationSceneScalarData::GetSceneObjs() params.projection.ortho(-1.,1.,-1.,1.,-2.,2.); params.model_view.identity(); params.model_view.translate(-1, -1, 0.0); - params.model_view.scale(40.0 / w, 40.0 / h, 1); + params.model_view.scale(40.0 / window_w, 40.0 / window_h, 1); params.model_view.translate(2.0, 2.0, 0.0); params.model_view.mult(cam.RotMatrix()); params.model_view.mult(rotmat); diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index 5d92ddd4..bb7a653a 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -58,6 +58,9 @@ class VisualizationSceneScalarData : public VisualizationScene double minv, maxv; + int window_w, window_h; + int draw_w, draw_h; + std::string plot_caption = ""; std::string extra_caption = ""; std::string a_label_x, a_label_y, a_label_z; @@ -206,6 +209,11 @@ class VisualizationSceneScalarData : public VisualizationScene Mesh *GetMesh() { return mesh; } + void UpdateWindowSize(int w, int h, int gl_w, int gl_h) + { + window_w = w; window_h = h; + draw_w = gl_w; draw_h = gl_h; + } virtual gl3::SceneInfo GetSceneObjs(); double &GetMinV() { return minv; } From 7806bd67f0c7108d4900775bdd2a47b0872d5f97 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 12:42:24 -0800 Subject: [PATCH 36/42] Fix for printing --- lib/aux_vis.cpp | 6 +++--- lib/aux_vis.hpp | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 122f043e..961aa2db 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -101,11 +101,11 @@ KeyDelegate CreateKeyEvent(T* inst, void (T::*func)()) return [inst, func](GLenum) { (inst->*func)(); }; } -bool KeyPrint(GLVisWindow* wnd, GLenum mod) +void GLVisWindow::KeyPrint(GLenum mod) { if (mod & KMOD_CTRL) { - wnd->PrintToPDF(); + PrintToPDF(); } } @@ -163,7 +163,7 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega SetKeyEventHandler('A', &GLVisWindow::ToggleAntialiasing); - SetKeyEventHandler ('p', &GLVisWindow::PrintToPDF); + SetKeyEventHandler ('p', &GLVisWindow::KeyPrint); SetKeyEventHandler ('r', &GLVisWindow::StopSpinning); SetKeyEventHandler ('R', &GLVisWindow::StopSpinning); SetKeyEventHandler (SDLK_s, &GLVisWindow::Screenshot); diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index b13466c0..82f0c2bd 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -183,6 +183,8 @@ class GLVisWindow // Internal event handler for toggling state of threads void ThreadsPauseFunc(GLenum); + void KeyPrint(GLenum); + std::unique_ptr wnd; std::unique_ptr locscene; std::unique_ptr glvis_command; From 89ff3e58e1c2cf74b18de2965d597355837ae6b3 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 12:44:44 -0800 Subject: [PATCH 37/42] Make GetColorFromVal a member function of PaletteState --- lib/aux_vis.cpp | 28 ++-------------------------- lib/aux_vis.hpp | 2 -- lib/gl/renderer.cpp | 4 ++-- lib/gl/renderer.hpp | 5 ++++- lib/gl/renderer_core.cpp | 2 +- lib/gl/renderer_core.hpp | 2 +- lib/gl/renderer_ff.cpp | 12 ++++++------ lib/gl/renderer_ff.hpp | 2 +- lib/palettes.cpp | 25 +++++++++++++++++++++++++ lib/palettes.hpp | 1 + 10 files changed, 43 insertions(+), 40 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 961aa2db..df21dbcb 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -258,6 +258,8 @@ void GLVisWindow::InitVisualization(int field_type, StreamState state, locscene = prob_state.CreateVisualizationScene(field_type); + wnd->getRenderer().setPalette(&locscene->GetPalette()); + if (prob_state.mesh->SpaceDimension() == 2 && field_type == 2) { locscene->view = 2; @@ -1353,32 +1355,6 @@ void GLVisWindow::SetWindowTitle(const char *title) wnd->setWindowTitle(title); } -void GetColorFromVal(double val, float * rgba) -{ - int palSize = locscene->GetPalette().GetSize(); - int RepeatPaletteTimes = locscene->GetPalette().GetRepeatTimes(); - const double* palData = locscene->GetPalette().GetData(); - val *= 0.999999999 * ( palSize - 1 ) * abs(RepeatPaletteTimes); - int i = (int) floor( val ); - double t = val - i; - - const double* pal; - if (((i / (palSize-1)) % 2 == 0 && RepeatPaletteTimes > 0) || - ((i / (palSize-1)) % 2 == 1 && RepeatPaletteTimes < 0)) - { - pal = palData + 3 * ( i % (palSize-1) ); - } - else - { - pal = palData + 3 * ( (palSize-2) - i % (palSize-1) ); - t = 1.0 - t; - } - rgba[0] = (1.0 - t) * pal[0] + t * pal[3]; - rgba[1] = (1.0 - t) * pal[1] + t * pal[4]; - rgba[2] = (1.0 - t) * pal[2] + t * pal[5]; - rgba[3] = 1.f; -} - int GetMultisample() { return glvis_multisample; diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 82f0c2bd..8c258265 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -240,8 +240,6 @@ void SendKeySequence(const char *seq); // update the visualization window. void CallKeySequence(const char *seq); -void GetColorFromVal(double val, float * rgba); - int GetMultisample(); void SetMultisample(int m); diff --git a/lib/gl/renderer.cpp b/lib/gl/renderer.cpp index d8622e18..b9470ea3 100644 --- a/lib/gl/renderer.cpp +++ b/lib/gl/renderer.cpp @@ -351,13 +351,13 @@ CaptureBuffer MeshRenderer::capture(const RenderQueue& queue) device->attachTexture(GLDevice::SAMPLER_ALPHA, alpha_tex); for (auto buf : tex_bufs) { - device->captureXfbBuffer(cbuf, buf); + device->captureXfbBuffer(*pal, cbuf, buf); } device->detachTexture(GLDevice::SAMPLER_COLOR); device->detachTexture(GLDevice::SAMPLER_ALPHA); for (auto buf : no_tex_bufs) { - device->captureXfbBuffer(cbuf, buf); + device->captureXfbBuffer(*pal, cbuf, buf); } if (!params.contains_translucent) { diff --git a/lib/gl/renderer.hpp b/lib/gl/renderer.hpp index b11ee9d5..24369f7f 100644 --- a/lib/gl/renderer.hpp +++ b/lib/gl/renderer.hpp @@ -20,6 +20,7 @@ #include "platform_gl.hpp" #include "types.hpp" #include "../material.hpp" +#include "../palettes.hpp" #include "../font.hpp" namespace gl3 @@ -186,7 +187,7 @@ class GLDevice virtual void exitXfbMode() {} // Capture the next drawn vertex buffer to a feedback buffer instead of // drawing to screen. - virtual void captureXfbBuffer(CaptureBuffer& capture, int hnd) = 0; + virtual void captureXfbBuffer(PaletteState& pal, CaptureBuffer& capture, int hnd) = 0; // Capture the next text buffer instead of drawing to screen. void captureXfbBuffer(CaptureBuffer& capture, const TextBuffer& t_buf); @@ -200,6 +201,7 @@ class MeshRenderer GLuint color_tex, alpha_tex, font_tex; float line_w, line_w_aa; GlVisFont* font; + PaletteState* pal; bool feat_use_fbo_antialias; void init(); @@ -227,6 +229,7 @@ class MeshRenderer } void setFont(GlVisFont* fnt) { this->font = fnt; } + void setPalette(PaletteState* pal) { this->pal = pal; } // Sets the texture handle of the color palette. void setColorTexture(GLuint tex_h) { color_tex = tex_h; } diff --git a/lib/gl/renderer_core.cpp b/lib/gl/renderer_core.cpp index ff65a905..fe864c2a 100644 --- a/lib/gl/renderer_core.cpp +++ b/lib/gl/renderer_core.cpp @@ -817,7 +817,7 @@ void CoreGLDevice::processLineXfbBuffer(CaptureBuffer& cbuf, void CoreGLDevice::captureXfbBuffer( - CaptureBuffer& cbuf, int hnd) + PaletteState& pal, CaptureBuffer& cbuf, int hnd) { if (hnd == 0) { return; } if (vbos[hnd].count == 0) { return; } diff --git a/lib/gl/renderer_core.hpp b/lib/gl/renderer_core.hpp index 992c23ae..ec899f65 100644 --- a/lib/gl/renderer_core.hpp +++ b/lib/gl/renderer_core.hpp @@ -113,7 +113,7 @@ class CoreGLDevice : public GLDevice initializeShaderState(RenderMode::Default); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); } - void captureXfbBuffer(CaptureBuffer& cbuf, int hnd) override; + void captureXfbBuffer(PaletteState& pal, CaptureBuffer& cbuf, int hnd) override; }; } diff --git a/lib/gl/renderer_ff.cpp b/lib/gl/renderer_ff.cpp index a776f3e8..d8f65c47 100644 --- a/lib/gl/renderer_ff.cpp +++ b/lib/gl/renderer_ff.cpp @@ -326,7 +326,7 @@ void FFGLDevice::drawDeviceBuffer(GlVisFont& font, const TextBuffer& buf) glPopMatrix(); } -void FFGLDevice::captureXfbBuffer(CaptureBuffer& cbuf, int hnd) +void FFGLDevice::captureXfbBuffer(PaletteState& pal, CaptureBuffer& cbuf, int hnd) { if (hnd == 0) { return; } if (disp_lists[hnd].count == 0) { return; } @@ -401,8 +401,8 @@ void FFGLDevice::captureXfbBuffer(CaptureBuffer& cbuf, int hnd) if (fbStride == 11) { // get texture - GetColorFromVal(xfb_buf[tok_idx + 7], glm::value_ptr(color0)); - GetColorFromVal(xfb_buf[tok_idx + 7 + fbStride], glm::value_ptr(color1)); + pal.GetColorFromVal(xfb_buf[tok_idx + 7], glm::value_ptr(color0)); + pal.GetColorFromVal(xfb_buf[tok_idx + 7 + fbStride], glm::value_ptr(color1)); } cbuf.lines.emplace_back(coord0, color0); cbuf.lines.emplace_back(coord1, color1); @@ -421,8 +421,8 @@ void FFGLDevice::captureXfbBuffer(CaptureBuffer& cbuf, int hnd) if (fbStride == 11) { // get texture - GetColorFromVal(xfb_buf[tok_idx + 7], glm::value_ptr(color0)); - GetColorFromVal(xfb_buf[tok_idx + 7 + fbStride], glm::value_ptr(color1)); + pal.GetColorFromVal(xfb_buf[tok_idx + 7], glm::value_ptr(color0)); + pal.GetColorFromVal(xfb_buf[tok_idx + 7 + fbStride], glm::value_ptr(color1)); } // decompose polygon into n-2 triangles [0 1 2] [0 2 3] ... for (int i = 0; i < n-2; i++) @@ -433,7 +433,7 @@ void FFGLDevice::captureXfbBuffer(CaptureBuffer& cbuf, int hnd) glm::vec4 color2 = glm::make_vec4(&xfb_buf[tok_idx + 3 + vtxStart]); if (fbStride == 11) { - GetColorFromVal(xfb_buf[tok_idx + 7 + vtxStart], glm::value_ptr(color2)); + pal.GetColorFromVal(xfb_buf[tok_idx + 7 + vtxStart], glm::value_ptr(color2)); } cbuf.triangles.emplace_back(coord0, color0); cbuf.triangles.emplace_back(coord1, color1); diff --git a/lib/gl/renderer_ff.hpp b/lib/gl/renderer_ff.hpp index 0a1e8d62..56805d8e 100644 --- a/lib/gl/renderer_ff.hpp +++ b/lib/gl/renderer_ff.hpp @@ -57,7 +57,7 @@ class FFGLDevice : public GLDevice void bufferToDevice(GlVisFont& font, TextBuffer& t_buf) override; void drawDeviceBuffer(int hnd) override; void drawDeviceBuffer(GlVisFont& font, const TextBuffer& t_buf) override; - void captureXfbBuffer(CaptureBuffer& cbuf, int hnd) override; + void captureXfbBuffer(PaletteState& pal, CaptureBuffer& cbuf, int hnd) override; }; } diff --git a/lib/palettes.cpp b/lib/palettes.cpp index de3282a5..3aee8154 100644 --- a/lib/palettes.cpp +++ b/lib/palettes.cpp @@ -7780,6 +7780,31 @@ double PaletteState::GetColorCoord(double val, double min, double max) } } +void PaletteState::GetColorFromVal(double val, float * rgba) +{ + int palSize = RGB_Palettes_Sizes[curr_palette]; + const double* palData = RGB_Palettes[curr_palette]; + val *= 0.999999999 * ( palSize - 1 ) * abs(RepeatPaletteTimes); + int i = (int) floor( val ); + double t = val - i; + + const double* pal; + if (((i / (palSize-1)) % 2 == 0 && RepeatPaletteTimes > 0) || + ((i / (palSize-1)) % 2 == 1 && RepeatPaletteTimes < 0)) + { + pal = palData + 3 * ( i % (palSize-1) ); + } + else + { + pal = palData + 3 * ( (palSize-2) - i % (palSize-1) ); + t = 1.0 - t; + } + rgba[0] = (1.0 - t) * pal[0] + t * pal[3]; + rgba[1] = (1.0 - t) * pal[1] + t * pal[4]; + rgba[2] = (1.0 - t) * pal[2] + t * pal[5]; + rgba[3] = 1.f; +} + const double * PaletteState::GetData() const { return RGB_Palettes[curr_palette]; diff --git a/lib/palettes.hpp b/lib/palettes.hpp index 9dfa04f2..47362e2e 100644 --- a/lib/palettes.hpp +++ b/lib/palettes.hpp @@ -49,6 +49,7 @@ class PaletteState void SetUseLogscale(bool logscale) { use_logscale = logscale; } bool GetUseLogscale() { return use_logscale; } double GetColorCoord(double val, double min, double max); + void GetColorFromVal(double val, float* rgba); GLuint GetColorTexture() const { return palette_tex[curr_palette][use_smooth]; } From ca8d5ea360d7bba3e7a2fc77f26ee501e8e7e198 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 12:45:55 -0800 Subject: [PATCH 38/42] Cleanup some globals from aux_vis --- lib/aux_vis.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index df21dbcb..766e356e 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -34,9 +34,6 @@ using namespace mfem; #include #endif -int visualize = 0; -VisualizationScene * locscene; - #ifdef GLVIS_MULTISAMPLE static int glvis_multisample = GLVIS_MULTISAMPLE; #else @@ -49,6 +46,8 @@ float line_w_aa = gl3::LINE_WIDTH_AA; [[deprecated]] SdlWindow* wnd; [[deprecated]] GLVisWindow * glvis_wnd = nullptr; +void MainLoop(GLVisWindow* wnd); + SdlWindow * GetAppWindow() { return wnd; @@ -59,11 +58,6 @@ GLVisWindow * GetGLVisWindow() return glvis_wnd; } -VisualizationScene * GetVisualizationScene() -{ - return locscene; -} - struct GLVisWindow::RotationControl { GLVisWindow* wnd; From abdbdd0d5de8287b0689bfbaea7c381a6e38cda4 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Thu, 11 Feb 2021 12:46:18 -0800 Subject: [PATCH 39/42] Cleanup some more globals from aux_vis --- lib/aux_vis.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index 8c258265..f4962c17 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -214,18 +214,8 @@ class GLVisWindow }; -/// Send expose event. In our case MyReshape is executed and Draw after it. -[[deprecated]] void SendExposeEvent(); - -[[deprecated]] void MyExpose(); - -void MainLoop(GLVisWindow* wnd); - [[deprecated]] SdlWindow * GetAppWindow(); [[deprecated]] GLVisWindow * GetGLVisWindow(); -VisualizationScene * GetVisualizationScene(); - - /// Take a screenshot using libtiff, libpng or sdl2 //int Screenshot(const char *fname, bool convert = false); From 270260005d4934bfb99b1af7b404333b8f06086b Mon Sep 17 00:00:00 2001 From: Max Yang Date: Fri, 12 Feb 2021 12:13:21 -0800 Subject: [PATCH 40/42] Remove remaining references to global GLVisWindow --- lib/aux_vis.cpp | 2 +- lib/openglvis.cpp | 6 +++++- lib/openglvis.hpp | 4 ++++ lib/stream_reader.cpp | 8 +++++++- lib/stream_reader.hpp | 2 +- lib/vsdata.cpp | 15 +++++++++------ lib/vsdata.hpp | 8 ++++++-- lib/vssolution.cpp | 7 ++----- lib/vssolution.hpp | 4 ++-- lib/vssolution3d.cpp | 7 ++----- lib/vssolution3d.hpp | 4 ++-- lib/vsvector.cpp | 8 ++------ lib/vsvector.hpp | 4 ++-- lib/vsvector3d.cpp | 9 ++------- lib/vsvector3d.hpp | 4 ++-- 15 files changed, 49 insertions(+), 43 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 766e356e..900832bc 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -250,7 +250,7 @@ void GLVisWindow::InitVisualization(int field_type, StreamState state, } #endif - locscene = prob_state.CreateVisualizationScene(field_type); + locscene = prob_state.CreateVisualizationScene(this, field_type); wnd->getRenderer().setPalette(&locscene->GetPalette()); diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index f4205c6d..f9652b4f 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -128,11 +128,15 @@ VisualizationScene::VisualizationScene() use_light = true; palette.Init(); - font = GetGLVisWindow()->getFont(); } VisualizationScene::~VisualizationScene() {} +void VisualizationScene::Init(GLVisWindow* wnd) +{ + font = wnd->getFont(); +} + void VisualizationScene ::DrawTriangle(gl3::GlDrawable& buff, const double (&pts)[4][3], const double (&cv)[4], diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index 5457e9b1..7982b3b6 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -21,6 +21,8 @@ #include "mfem.hpp" #include "geom_utils.hpp" +class GLVisWindow; + // Visualization header file class Camera @@ -135,6 +137,8 @@ class VisualizationScene VisualizationScene(); virtual ~VisualizationScene(); + virtual void Init(GLVisWindow* wnd); + int spinning, OrthogonalProjection, print, movie; double ViewAngle, ViewScale; double ViewCenterX, ViewCenterY; diff --git a/lib/stream_reader.cpp b/lib/stream_reader.cpp index de83c767..995a4361 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -356,7 +356,7 @@ GridFunction *ProjectVectorFEGridFunction(GridFunction *gf) } std::unique_ptr -StreamState::CreateVisualizationScene(int field_type) +StreamState::CreateVisualizationScene(GLVisWindow* wnd, int field_type) { std::unique_ptr vs; double mesh_range = -1.0; @@ -377,6 +377,8 @@ StreamState::CreateVisualizationScene(int field_type) { vss = new VisualizationSceneSolution(*mesh, sol); } + // initialize events and initial scene state + vss->Init(wnd); vs.reset(vss); if (grid_f) { @@ -395,6 +397,8 @@ StreamState::CreateVisualizationScene(int field_type) else if (mesh->SpaceDimension() == 3) { VisualizationSceneSolution3d *vss = new VisualizationSceneSolution3d(*mesh, sol); + // initialize events and initial scene state + vss->Init(wnd); vs.reset(vss); if (grid_f) { @@ -456,6 +460,8 @@ StreamState::CreateVisualizationScene(int field_type) vs.reset(new VisualizationSceneVector3d(*mesh, solu, solv, solw)); } } + // initialize events and initial scene state + vs->Init(wnd); } if (vs) diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 9c54eab3..c3d6cb9c 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -35,7 +35,7 @@ struct StreamState int ReadStream(std::istream &is, const std::string &data_type); - std::unique_ptr CreateVisualizationScene(int field_type); + std::unique_ptr CreateVisualizationScene(GLVisWindow* wnd, int field_type); /// Sets a new mesh and solution from another StreamState object, and /// updates the given VisualizationScene pointer with the new data. diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index e3dbabe1..efb2a956 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -952,12 +952,13 @@ VisualizationSceneScalarData::VisualizationSceneScalarData( { mesh = &m; sol = &s; - - Init(); } -void VisualizationSceneScalarData::Init() +void VisualizationSceneScalarData::Init(GLVisWindow* wnd) { + // perform base class initialization first + VisualizationScene::Init(wnd); + arrow_type = arrow_scaling_type = 0; scaling = 0; drawaxes = colorbar = 0; @@ -977,8 +978,6 @@ void VisualizationSceneScalarData::Init() // if (!init) { // init = 1; - GLVisWindow* wnd = GetGLVisWindow(); - using SceneType = VisualizationSceneScalarData; wnd->AddKeyEvent('l', &SceneType::ToggleLight); @@ -1057,6 +1056,10 @@ void VisualizationSceneScalarData::Init() PrepareRuler(); autoscale = 1; + + saved_key_func = [wnd]() -> std::string { + return wnd->getSdl()->getSavedKeys(); + }; } VisualizationSceneScalarData::~VisualizationSceneScalarData() @@ -1321,7 +1324,7 @@ void VisualizationSceneScalarData::SetLevelLines ( void VisualizationSceneScalarData::PrintState() { - cout << "\nkeys: " << GetAppWindow()->getSavedKeys() << "\n" + cout << "\nkeys: " << saved_key_func() << "\n" << "\nlight " << strings_off_on[use_light ? 1 : 0] << "\nperspective " << strings_off_on[OrthogonalProjection ? 0 : 1] << "\nviewcenter " << ViewCenterX << ' ' << ViewCenterY diff --git a/lib/vsdata.hpp b/lib/vsdata.hpp index bb7a653a..9f0a9a29 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -13,6 +13,7 @@ #define GLVIS_VSDATA_HPP #include +#include #include "openglvis.hpp" #include "mfem.hpp" @@ -76,8 +77,6 @@ class VisualizationSceneScalarData : public VisualizationScene gl3::GlDrawable caption_buf; int caption_w, caption_h; - void Init(); - int arrow_type, arrow_scaling_type; int nl; @@ -129,6 +128,9 @@ class VisualizationSceneScalarData : public VisualizationScene void Cone(gl3::GlBuilder& builder, glm::mat4 transform); + // stored function that gets saved keys from SdlWindow + std::function saved_key_func; + void PrintHelpString(); void QueryCaption(); void QueryLevelLines(); @@ -154,6 +156,8 @@ class VisualizationSceneScalarData : public VisualizationScene virtual ~VisualizationSceneScalarData(); + virtual void Init(GLVisWindow* wnd); + virtual std::string GetHelpString() const { return ""; } // Determine 'xscale', 'yscale', and 'zscale' using the current bounding diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 66530e7d..b004e9de 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -417,11 +417,9 @@ VisualizationSceneSolution::VisualizationSceneSolution( mesh = &m; sol = &s; v_normals = normals; - - Init(); } -void VisualizationSceneSolution::Init() +void VisualizationSceneSolution::Init(GLVisWindow* wnd) { rsol = NULL; @@ -446,7 +444,7 @@ void VisualizationSceneSolution::Init() drawbdr = 0; - VisualizationSceneScalarData::Init(); // Calls FindNewBox() !!! + VisualizationSceneScalarData::Init(wnd); // Calls FindNewBox() !!! palette.SetPalette(2); // use the 'jet-like' palette in 2D @@ -459,7 +457,6 @@ void VisualizationSceneSolution::Init() // if (!init) { // init = 1; - GLVisWindow* wnd = GetGLVisWindow(); using SceneType = VisualizationSceneSolution; wnd->AddKeyEvent('b', &SceneType::ToggleDrawBdr); diff --git a/lib/vssolution.hpp b/lib/vssolution.hpp index adcd73aa..367d0338 100644 --- a/lib/vssolution.hpp +++ b/lib/vssolution.hpp @@ -44,8 +44,6 @@ class VisualizationSceneSolution : public VisualizationSceneScalarData gl3::GlDrawable order_buf; gl3::GlDrawable order_noarrow_buf; - void Init(); - void FindNewBox(double rx[], double ry[], double rval[]); void DrawCPLine(gl3::GlBuilder& bld, @@ -101,6 +99,8 @@ class VisualizationSceneSolution : public VisualizationSceneScalarData virtual ~VisualizationSceneSolution(); + virtual void Init(GLVisWindow* wnd); + virtual std::string GetHelpString() const; void SetGridFunction(GridFunction & u) { rsol = &u; } diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index f5c0e46c..f4408eb0 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -591,12 +591,10 @@ VisualizationSceneSolution3d::VisualizationSceneSolution3d(Mesh &m, Vector &s) mesh = &m; sol = &s; GridF = NULL; - - Init(); } -void VisualizationSceneSolution3d::Init() +void VisualizationSceneSolution3d::Init(GLVisWindow* wnd) { cplane = 0; cp_drawmesh = 0; cp_drawelems = 1; @@ -636,7 +634,7 @@ void VisualizationSceneSolution3d::Init() } bdr_attr_to_show = 1; - VisualizationSceneScalarData::Init(); // calls FindNewBox + VisualizationSceneScalarData::Init(wnd); // calls FindNewBox FindNewValueRange(false); @@ -656,7 +654,6 @@ void VisualizationSceneSolution3d::Init() // if (!init) { // init = 1; - GLVisWindow* wnd = GetGLVisWindow(); using SceneType = VisualizationSceneSolution3d; wnd->AddKeyEvent('m', &SceneType::ToggleDrawMesh); diff --git a/lib/vssolution3d.hpp b/lib/vssolution3d.hpp index 9da197ac..c75b2adf 100644 --- a/lib/vssolution3d.hpp +++ b/lib/vssolution3d.hpp @@ -44,8 +44,6 @@ class VisualizationSceneSolution3d : public VisualizationSceneScalarData GridFunction *GridF; - void Init(); - void GetFaceNormals(const int FaceNo, const int side, const IntegrationRule &ir, DenseMatrix &normals); @@ -127,6 +125,8 @@ class VisualizationSceneSolution3d : public VisualizationSceneScalarData VisualizationSceneSolution3d(); VisualizationSceneSolution3d(Mesh & m, Vector & s); + virtual void Init(GLVisWindow* wnd); + void SetGridFunction (GridFunction *gf) { GridF = gf; } void NewMeshAndSolution(Mesh *new_m, Vector *new_sol, diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index 33b93b3c..54244786 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -234,8 +234,6 @@ VisualizationSceneVector::VisualizationSceneVector(Mesh & m, sol = new Vector(mesh -> GetNV()); VecGridF = NULL; - - Init(); } VisualizationSceneVector::VisualizationSceneVector(GridFunction &vgf) @@ -261,7 +259,6 @@ VisualizationSceneVector::VisualizationSceneVector(GridFunction &vgf) // VisualizationSceneSolution::Init() sets rsol = NULL ! { - Init(); SetGridFunction(vgf); } @@ -447,7 +444,7 @@ void VisualizationSceneVector::NewMeshAndSolution(GridFunction &vgf) PrepareVectorField(); } -void VisualizationSceneVector::Init() +void VisualizationSceneVector::Init(GLVisWindow* wnd) { drawdisp = 0; drawvector = 0; @@ -461,7 +458,7 @@ void VisualizationSceneVector::Init() (*sol)(i) = Vec2Scalar((*solx)(i), (*soly)(i)); } - VisualizationSceneSolution::Init(); + VisualizationSceneSolution::Init(wnd); PrepareVectorField(); // PrepareDisplacedMesh(); // called by PrepareLines() @@ -470,7 +467,6 @@ void VisualizationSceneVector::Init() // if (!init) { // init = 1; - GLVisWindow* wnd = GetGLVisWindow(); using SceneType = VisualizationSceneVector; wnd->AddKeyEvent('d', &SceneType::ToggleDisplacements); diff --git a/lib/vsvector.hpp b/lib/vsvector.hpp index 76a58ff6..13e5990d 100644 --- a/lib/vsvector.hpp +++ b/lib/vsvector.hpp @@ -27,8 +27,6 @@ class VisualizationSceneVector : public VisualizationSceneSolution gl3::GlDrawable displine_buf; GridFunction *VecGridF; - void Init(); - virtual void GetRefinedValues(int i, const IntegrationRule &ir, Vector &vals, DenseMatrix &tr); virtual int GetRefinedValuesAndNormals(int i, const IntegrationRule &ir, @@ -64,6 +62,8 @@ class VisualizationSceneVector : public VisualizationSceneSolution virtual ~VisualizationSceneVector(); + virtual void Init(GLVisWindow* wnd); + virtual std::string GetHelpString() const; void PrepareDisplacedMesh(); diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 268d21d7..006679b7 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -295,8 +295,6 @@ VisualizationSceneVector3d::VisualizationSceneVector3d(Mesh &m, Vector &sx, sfes = NULL; VecGridF = NULL; - - Init(); } VisualizationSceneVector3d::VisualizationSceneVector3d(GridFunction &vgf) @@ -324,11 +322,9 @@ VisualizationSceneVector3d::VisualizationSceneVector3d(GridFunction &vgf) vgf.GetNodalValues(*solz, 3); sol = new Vector(mesh->GetNV()); - - Init(); } -void VisualizationSceneVector3d::Init() +void VisualizationSceneVector3d::Init(GLVisWindow* wnd) { key_r_state = 0; @@ -341,7 +337,7 @@ void VisualizationSceneVector3d::Init() SetScalarFunction(); - VisualizationSceneSolution3d::Init(); + VisualizationSceneSolution3d::Init(wnd); PrepareVectorField(); PrepareDisplacedMesh(); @@ -353,7 +349,6 @@ void VisualizationSceneVector3d::Init() // if (!init) { // init = 1; - GLVisWindow* wnd = GetGLVisWindow(); using SceneType = VisualizationSceneVector3d; wnd->AddKeyEvent('d', &SceneType::ToggleDisplacements); diff --git a/lib/vsvector3d.hpp b/lib/vsvector3d.hpp index 60c0a25a..a7ec8307 100644 --- a/lib/vsvector3d.hpp +++ b/lib/vsvector3d.hpp @@ -28,8 +28,6 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d GridFunction *VecGridF; FiniteElementSpace *sfes; - void Init(); - Array vflevel; Array dvflevel; @@ -51,6 +49,8 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d virtual ~VisualizationSceneVector3d(); + virtual void Init(GLVisWindow* wnd); + virtual std::string GetHelpString() const; virtual void PrepareFlat(); From fa40052ddd50e34c7367d2be331c85db77ec54b8 Mon Sep 17 00:00:00 2001 From: Max Yang Date: Fri, 12 Feb 2021 12:13:38 -0800 Subject: [PATCH 41/42] Remove some comments --- lib/vsdata.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index efb2a956..fe361d28 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -463,7 +463,6 @@ void VisualizationSceneScalarData::PrepareCaption() font->getObjectSize(caption, caption_w, caption_h); } -//void KeyCPressed() void VisualizationSceneScalarData::QueryCaption() { cout << "Enter new caption: " << flush; @@ -490,7 +489,6 @@ void Key_Mod_a_Pressed(GLVisWindow* wnd, GLenum state) } } -//void KeyHPressed() void VisualizationSceneScalarData::PrintHelpString() { cout << GetHelpString() << flush; @@ -531,7 +529,6 @@ void KeyPPressed(GLVisWindow* wnd) vsdata->GetPalette().PrevPalette(); } -//static void KeyF5Pressed() void VisualizationSceneScalarData::QueryLevelLines() { int n; @@ -549,7 +546,6 @@ void VisualizationSceneScalarData::QueryLevelLines() UpdateLevelLines(); } -//void KeyF6Pressed() void VisualizationSceneScalarData::QueryPaletteSettings() { int RepeatPaletteTimes = GetPalette().GetRepeatTimes(); @@ -648,7 +644,6 @@ void VisualizationSceneScalarData::QueryLightPosition() SetLight0CustomPos({x, y, z, w}); } -//void KeyTPressed() void VisualizationSceneScalarData::NextLightMatSetting() { int ml; @@ -665,7 +660,6 @@ void VisualizationSceneScalarData::ToggleBackground() EventUpdateBackground(); } -//void KeyF2Pressed() void VisualizationSceneScalarData::RedrawColors() { EventUpdateColors(); From 40d06ebc3e44d1b36e54610ba8ca9000c75f274e Mon Sep 17 00:00:00 2001 From: Max Yang Date: Fri, 12 Feb 2021 12:18:45 -0800 Subject: [PATCH 42/42] Remove last globals from aux_vis --- lib/aux_vis.cpp | 44 -------------------------------------------- lib/aux_vis.hpp | 13 ------------- 2 files changed, 57 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 900832bc..19f8a812 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -43,21 +43,8 @@ static int glvis_multisample = -1; float line_w = 1.f; float line_w_aa = gl3::LINE_WIDTH_AA; -[[deprecated]] SdlWindow* wnd; -[[deprecated]] GLVisWindow * glvis_wnd = nullptr; - void MainLoop(GLVisWindow* wnd); -SdlWindow * GetAppWindow() -{ - return wnd; -} - -GLVisWindow * GetGLVisWindow() -{ - return glvis_wnd; -} - struct GLVisWindow::RotationControl { GLVisWindow* wnd; @@ -113,13 +100,11 @@ GLVisWindow::GLVisWindow(std::string name, int x, int y, int w, int h, bool lega cout << "OpenGL Visualization" << endl; #endif rot_data->wnd = this; - ::glvis_wnd = this; wnd.reset(new SdlWindow()); if (!wnd->createWindow(name, x, y, w, h, legacyGlOnly)) { throw std::runtime_error("Could not create an SDL window."); } - ::wnd = wnd.get(); #ifdef GLVIS_DEBUG cout << "Window should be up" << endl; #endif @@ -302,16 +287,6 @@ void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)(GLenu SetupHandledKey(key); } -void SendKeySequence(const char *seq) -{ - glvis_wnd->SendKeySequence(seq); -} - -void CallKeySequence(const char *seq) -{ - glvis_wnd->CallKeySequence(seq); -} - void GLVisWindow::SendKeySequence(const char *seq) { for (const char* key = seq; *key != '\0'; key++) @@ -426,16 +401,6 @@ void GLVisWindow::RunVisualization() #endif } -void SendExposeEvent() -{ - glvis_wnd->SendExposeEvent(); -} - -void MyExpose() -{ - glvis_wnd->MyExpose(); -} - void GLVisWindow::SendExposeEvent() { if (disableSendExposeEvent) { return; } @@ -1369,20 +1334,11 @@ void SetMultisample(int m) void SetLineWidth(float width) { line_w = width; - if (wnd) - { - wnd->getRenderer().setLineWidth(line_w); - } } void SetLineWidthMS(float width_ms) { line_w_aa = width_ms; - if (wnd) - { - wnd->getRenderer().setLineWidthMS(line_w_aa); - } - } float GetLineWidth() diff --git a/lib/aux_vis.hpp b/lib/aux_vis.hpp index f4962c17..23651976 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -214,22 +214,9 @@ class GLVisWindow }; -[[deprecated]] SdlWindow * GetAppWindow(); -[[deprecated]] GLVisWindow * GetGLVisWindow(); - /// Take a screenshot using libtiff, libpng or sdl2 //int Screenshot(const char *fname, bool convert = false); -/// Send a sequence of keystrokes to the visualization window -void SendKeySequence(const char *seq); - -// Directly call the functions assigned to the given keys. Unlike the above -// function, SendKeySequence(), this function does not send X events and -// actually disables the function SendExposeEvent() used by many of the -// functions assigned to keys. Call MyExpose() after calling this function to -// update the visualization window. -void CallKeySequence(const char *seq); - int GetMultisample(); void SetMultisample(int m);