diff --git a/glvis.cpp b/glvis.cpp index 90f6f542..47e61e8b 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -48,16 +48,16 @@ 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; // Global variables int input = 1; -StreamState stream_state; -VisualizationSceneScalarData *vs = NULL; -communication_thread *comm_thread = NULL; +GLVisWindow * mainWindow = nullptr; GeometryRefiner GLVisGeometryRefiner; @@ -95,7 +95,7 @@ void CloseInputStreams(bool); // 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) +bool GLVisInitVis(StreamState stream_state, int field_type) { if (field_type < 0 || field_type > 2) { @@ -105,157 +105,38 @@ 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; - return false; + mainWindow = new GLVisWindow(win_title, window_x, window_y, + window_w, window_h, legacy_gl_ctx); } - - if (input_streams.Size() > 0) + catch (std::runtime_error& ex) { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); - glvis_command = new GLVisCommand(&vs, stream_state, &keep_attr); - comm_thread = new communication_thread(input_streams); + cerr << "Initializing the visualization failed: " << endl + << ex.what() << endl; + return false; } - - double mesh_range = -1.0; - if (field_type == 0 || field_type == 2) + catch (...) { - 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(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->palette.SetIndex(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.get()); - } - if (field_type == 2) - { - if (stream_state.mesh->Dimension() == 3) - { - // Use the 'white' palette when visualizing a 3D volume mesh only - vss->palette.SetIndex(11); - vss->SetLightMatIdx(4); - } - else - { - // Use the 'bone' palette when visualizing a surface mesh only - vss->palette.SetIndex(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; - } - } + cerr << "Initializing the visualization failed - unknown error." + << endl; + return false; } - else if (field_type == 1) + if (font_name != string_default) { - 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(std::move(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); - } - } + mainWindow->SetFont(font_name); } - 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) - { - SetVisualizationScene(vs, 2, stream_state.keys.c_str()); - } - else - { - SetVisualizationScene(vs, 3, stream_state.keys.c_str()); - } - } + mainWindow->InitVisualization(field_type, std::move(stream_state), + keep_attr, input_streams); + return true; } void GLVisStartVis() { - RunVisualization(); // deletes vs - vs = NULL; - if (input_streams.Size() > 0) - { - glvis_command->Terminate(); - delete comm_thread; - delete glvis_command; - glvis_command = NULL; - } + mainWindow->RunVisualization(); // deletes vs + delete mainWindow; cout << "GLVis window closed." << endl; } @@ -395,7 +276,7 @@ int ScriptReadDisplMesh(istream &scr, StreamState& state) return 0; } -void ExecuteScriptCommand() +void ExecuteScriptCommand(GLVisWindow* wnd) { if (!script) { @@ -403,6 +284,9 @@ void ExecuteScriptCommand() return; } + VisualizationSceneScalarData* vs + = static_cast(wnd->getScene()); + StreamState& stream_state = wnd->getStreamState(); istream &scr = *script; string word; int done_one_command = 0; @@ -470,7 +354,7 @@ void ExecuteScriptCommand() if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) { - MyExpose(); + wnd->MyExpose(); } else { @@ -483,12 +367,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()) @@ -505,7 +386,7 @@ void ExecuteScriptCommand() scr >> vs->ViewCenterX >> vs->ViewCenterY; cout << "Script: viewcenter: " << vs->ViewCenterX << ' ' << vs->ViewCenterY << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "perspective") { @@ -524,7 +405,7 @@ void ExecuteScriptCommand() cout << '?'; } cout << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "light") { @@ -543,7 +424,7 @@ void ExecuteScriptCommand() cout << '?'; } cout << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "view") { @@ -551,7 +432,7 @@ void ExecuteScriptCommand() scr >> theta >> phi; cout << "Script: view: " << theta << ' ' << phi << endl; vs->SetView(theta, phi); - MyExpose(); + wnd->MyExpose(); } else if (word == "zoom") { @@ -559,7 +440,7 @@ void ExecuteScriptCommand() scr >> factor; cout << "Script: zoom: " << factor << endl; vs->Zoom(factor); - MyExpose(); + wnd->MyExpose(); } else if (word == "shading") { @@ -582,7 +463,7 @@ void ExecuteScriptCommand() { vs->SetShading(s, false); cout << word << endl; - MyExpose(); + wnd->MyExpose(); } else { @@ -596,7 +477,7 @@ void ExecuteScriptCommand() cout << "Script: subdivisions: " << flush; vs->SetRefineFactors(t, b); cout << t << ' ' << b << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "valuerange") { @@ -605,7 +486,7 @@ void ExecuteScriptCommand() cout << "Script: valuerange: " << flush; vs->SetValueRange(min, max); cout << min << ' ' << max << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "autoscale") { @@ -638,16 +519,16 @@ void ExecuteScriptCommand() 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); - MyExpose(); + wnd->MoveResizeWindow(window_x, window_y, window_w, window_h); + wnd->MyExpose(); } else if (word == "keys") { scr >> stream_state.keys; cout << "Script: keys: '" << stream_state.keys << "'" << endl; // SendKeySequence(keys.c_str()); - CallKeySequence(stream_state.keys.c_str()); - MyExpose(); + wnd->CallKeySequence(stream_state.keys.c_str()); + wnd->MyExpose(); } else if (word == "palette") { @@ -655,7 +536,7 @@ void ExecuteScriptCommand() scr >> pal; cout << "Script: palette: " << pal << endl; vs->palette.SetIndex(pal-1); - MyExpose(); + wnd->MyExpose(); } else if (word == "palette_repeat") { @@ -664,7 +545,7 @@ void ExecuteScriptCommand() cout << "Script: palette_repeat: " << rpt_times << endl; vs->palette.SetRepeatTimes(rpt_times); vs->palette.Init(); - MyExpose(); + wnd->MyExpose(); } else if (word == "toggle_attributes") { @@ -686,7 +567,7 @@ void ExecuteScriptCommand() scr.get(); // read the end symbol: ';' cout << endl; vs->ToggleAttributes(attr_list); - MyExpose(); + wnd->MyExpose(); } else if (word == "rotmat") { @@ -697,7 +578,7 @@ void ExecuteScriptCommand() cout << ' ' << vs->rotmat[i/4][i%4]; } cout << endl; - MyExpose(); + wnd->MyExpose(); } else if (word == "camera") { @@ -710,7 +591,7 @@ void ExecuteScriptCommand() } cout << endl; vs->cam.Set(cam); - MyExpose(); + wnd->MyExpose(); } else if (word == "scale") { @@ -720,7 +601,7 @@ void ExecuteScriptCommand() cout << ' ' << scale; cout << endl; vs->Scale(scale); - MyExpose(); + wnd->MyExpose(); } else if (word == "translate") { @@ -730,15 +611,16 @@ void ExecuteScriptCommand() cout << ' ' << x << ' ' << y << ' ' << z; cout << endl; vs->Translate(x, y, z); - MyExpose(); + wnd->MyExpose(); } else if (word == "plot_caption") { char delim; scr >> ws >> delim; getline(scr, plot_caption, delim); + vs->SetCaption(plot_caption); vs->PrepareCaption(); // turn on or off the caption - MyExpose(); + wnd->MyExpose(); } else { @@ -749,38 +631,39 @@ void ExecuteScriptCommand() } } -void ScriptControl(); +void ScriptControl(GLVisWindow* wnd); -void ScriptIdleFunc() +void ScriptIdleFunc(GLVisWindow* wnd) { - ExecuteScriptCommand(); + ExecuteScriptCommand(wnd); if (scr_level == 0) { - ScriptControl(); + ScriptControl(wnd); } } -void ScriptControl() +void ScriptControl(GLVisWindow* wnd) { if (scr_running) { scr_running = 0; - RemoveIdleFunc(ScriptIdleFunc); + wnd->RemoveIdleFunc(ScriptIdleFunc); } else { scr_running = 1; - AddIdleFunc(ScriptIdleFunc); + wnd->AddIdleFunc(ScriptIdleFunc); } } -void PlayScript(istream &scr) +void PlayScript(istream &scr, StreamState stream_state) { string word; scr_min_val = numeric_limits::infinity(); scr_max_val = -scr_min_val; + // read initializing commands while (1) { @@ -840,10 +723,11 @@ void PlayScript(istream &scr) scr_level = scr_running = 0; script = &scr; stream_state.keys.clear(); + int ftype = (stream_state.grid_f->VectorDim() == 1) ? 0 : 1; - if (GLVisInitVis((stream_state.grid_f->VectorDim() == 1) ? 0 : 1)) + if (GLVisInitVis(std::move(stream_state), ftype)) { - GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); + mainWindow->AddKeyEvent(SDLK_SPACE, ScriptControl, false); GLVisStartVis(); } @@ -863,14 +747,14 @@ 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; + + StreamState stream_state; OptionsParser args(argc, argv); @@ -986,10 +870,6 @@ int main (int argc, char *argv[]) { stream_state.keys = arg_keys; } - if (font_name != string_default) - { - SetFont(font_name); - } if (multisample != GetMultisample()) { SetMultisample(multisample); @@ -1006,10 +886,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); @@ -1027,7 +903,7 @@ int main (int argc, char *argv[]) ifs >> data_type >> ws; int ft = stream_state.ReadStream(ifs, data_type); input_streams.Append(&ifs); - if (GLVisInitVis(ft)) + if (GLVisInitVis(std::move(stream_state), ft)) { GLVisStartVis(); } @@ -1043,7 +919,7 @@ int main (int argc, char *argv[]) cout << "Can not open script: " << script_file << endl; return 1; } - PlayScript(scr); + PlayScript(scr, std::move(stream_state)); return 0; } @@ -1288,7 +1164,7 @@ int main (int argc, char *argv[]) delete isock; ft = ReadInputStreams(stream_state); } - if (GLVisInitVis(ft)) + if (GLVisInitVis(std::move(stream_state), ft)) { GLVisStartVis(); } @@ -1333,7 +1209,7 @@ int main (int argc, char *argv[]) { field_type = (use_soln) ? 0 : 2; } - if (GLVisInitVis(field_type)) + if (GLVisInitVis(std::move(stream_state), field_type)) { GLVisStartVis(); } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a02c0b3e..461182b2 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -20,6 +20,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_js.cpp b/lib/aux_js.cpp index e4b3b6e2..75c97b25 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -20,8 +20,9 @@ std::string plot_caption; std::string extra_caption; // used in extern context mfem::GeometryRefiner GLVisGeometryRefiner; // used in extern context -static VisualizationSceneScalarData * vs = nullptr; -StreamState stream_state; +static GLVisWindow * mainWindow = nullptr; +static VisualizationSceneScalarData * vssd = nullptr; +static bool keep_attr = false; namespace js { @@ -33,12 +34,10 @@ bool startVisualization(const std::string input, const std::string data_type, { std::stringstream ss(input); + StreamState stream_state; // 0 - scalar data, 1 - vector data, 2 - mesh only, (-1) - unknown const int field_type = stream_state.ReadStream(ss, data_type); - // reset antialiasing - GetAppWindow()->getRenderer().setAntialiasing(0); - std::string line; double minv = 0.0, maxv = 0.0; while (ss >> line) @@ -64,150 +63,35 @@ bool startVisualization(const std::string input, const std::string data_type, return false; } - if (InitVisualization("glvis", 0, 0, w, h)) - { - return false; - } - - delete vs; - vs = nullptr; - - double mesh_range = -1.0; - if (field_type == 0 || field_type == 2) + if (mainWindow == nullptr) { - if (stream_state.grid_f) + try { - stream_state.grid_f->GetNodalValues(stream_state.sol); + mainWindow = new GLVisWindow("glvis", 0, 0, w, h, false); } - if (stream_state.mesh->SpaceDimension() == 2) + catch (std::runtime_error& ex) { - 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->palette.SetIndex(4); - } + cerr << "Initializing the visualization failed: " << endl + << ex.what() << endl; + return false; } - else if (stream_state.mesh->SpaceDimension() == 3) + catch (...) { - VisualizationSceneSolution3d * vss; - vs = vss = new VisualizationSceneSolution3d(*stream_state.mesh, - stream_state.sol); - if (stream_state.grid_f) - { - vss->SetGridFunction(stream_state.grid_f.get()); - } - if (field_type == 2) - { - if (stream_state.mesh->Dimension() == 3) - { - // Use the 'white' palette when visualizing a 3D volume mesh only - // vs->palette.SetIndex(4); - vs->palette.SetIndex(11); - vss->SetLightMatIdx(4); - } - else - { - // Use the 'bone' palette when visualizing a surface mesh only - // (the same as when visualizing a 2D mesh only) - vs->palette.SetIndex(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(std::move(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); - } + cerr << "Initializing the visualization failed - unknown error." + << endl; + return false; } } - 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) - { - SetVisualizationScene(vs, 2); - } - else - { - SetVisualizationScene(vs, 3); - } - } - - CallKeySequence(stream_state.keys.c_str()); + double mesh_range = -1.0; + mainWindow->InitVisualization(field_type, std::move(stream_state), keep_attr); + vssd = dynamic_cast(mainWindow->getScene()); if (minv || maxv) { - vs->SetValueRange(minv, maxv); + vssd->SetValueRange(minv, maxv); } - - SendExposeEvent(); + mainWindow->SendExposeEvent(); return true; } @@ -227,14 +111,14 @@ int updateVisualization(std::string data_type, std::string stream) new_state.ReadStream(ss, data_type); double mesh_range = -1.0; - if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) + StreamState & stream_state = mainWindow->getStreamState(); + if (stream_state.SetNewMeshAndSolution(std::move(new_state), vssd)) { if (mesh_range > 0.0) { - vs->SetValueRange(-mesh_range, mesh_range); + vssd->SetValueRange(-mesh_range, mesh_range); } - - SendExposeEvent(); + mainWindow->SendExposeEvent(); return 0; } else @@ -246,13 +130,13 @@ int updateVisualization(std::string data_type, std::string stream) void iterVisualization() { - GetAppWindow()->mainIter(); + mainWindow->getSdl()->mainIter(); } void setCanvasId(const std::string & id) { std::cout << "glvis: setting canvas id to " << id << std::endl; - GetAppWindow()->setCanvasId(id); + mainWindow->getSdl()->setCanvasId(id); } void disableKeyHandling() @@ -274,7 +158,7 @@ void setKeyboardListeningElementId(const std::string & id) void processKeys(const std::string & keys) { - CallKeySequence(keys.c_str()); + mainWindow->CallKeySequence(keys.c_str()); } void processKey(int sym, bool ctrl=false, bool shift=false, bool alt=false) @@ -283,7 +167,7 @@ void processKey(int sym, bool ctrl=false, bool shift=false, bool alt=false) mod |= ctrl ? KMOD_CTRL : 0; mod |= shift ? KMOD_SHIFT : 0; mod |= alt ? KMOD_ALT : 0; - GetAppWindow()->callKeyDown(sym, mod); + mainWindow->getSdl()->callKeyDown(sym, mod); } void setupResizeEventCallback(const std::string & id) @@ -306,10 +190,36 @@ void setupResizeEventCallback(const std::string & id) std::string getHelpString() { - VisualizationSceneScalarData* vss - = dynamic_cast(GetVisualizationScene()); - return vss->GetHelpString(); + return vssd->GetHelpString(); +} + +void ResizeWindow(int w, int h) +{ + mainWindow->ResizeWindow(w, h); +} + +int GetUseTexture() +{ + return vssd->palette.GetSmoothSetting(); } + +void SetUseTexture(int ut) +{ + if (ut == 0) + { + vssd->palette.UseDiscrete(); + } + else + { + vssd->palette.UseSmooth(); + } +} + +void SendExposeEvent() +{ + mainWindow->SendExposeEvent(); +} + } // namespace js // Info on type conversion: @@ -320,14 +230,14 @@ EMSCRIPTEN_BINDINGS(js_funcs) em::function("startVisualization", &js::startVisualization); em::function("updateVisualization", &js::updateVisualization); em::function("iterVisualization", &js::iterVisualization); - em::function("sendExposeEvent", &SendExposeEvent); + em::function("sendExposeEvent", &js::SendExposeEvent); em::function("disableKeyHanding", &js::disableKeyHandling); 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 1ec14c18..d0be1a95 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; @@ -33,9 +34,6 @@ using namespace mfem; #include #endif -int visualize = 0; -VisualizationScene * locscene; - #ifdef GLVIS_MULTISAMPLE static int glvis_multisample = GLVIS_MULTISAMPLE; #else @@ -45,57 +43,106 @@ static int glvis_multisample = -1; float line_w = 1.f; float line_w_aa = gl3::LINE_WIDTH_AA; -SdlWindow * wnd = nullptr; -bool wndLegacyGl = false; +void MainLoop(GLVisWindow* wnd); -SdlWindow * GetAppWindow() +struct GLVisWindow::RotationControl { - return wnd; -} + 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); }; + } + +}; -VisualizationScene * GetVisualizationScene() +template +KeyDelegate CreateKeyEvent(T* inst, void (T::*func)()) { - return locscene; + return [inst, func](GLenum) { (inst->*func)(); }; } -void SetLegacyGLOnly(bool status) +void GLVisWindow::KeyPrint(GLenum mod) { - wndLegacyGl = true; + if (mod & KMOD_CTRL) + { + PrintToPDF(); + } } -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) + , idle_funcs(0) + , rot_data(new RotationControl) { #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 + rot_data->wnd = this; + wnd.reset(new SdlWindow()); + if (!wnd->createWindow(name, x, y, w, h, legacyGlOnly)) { - wnd->clearEvents(); + throw std::runtime_error("Could not create an SDL window."); } - #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); // auxReshapeFunc (MyReshape); // not needed, MyExpose calls it // auxReshapeFunc (NULL); - void (*exposeFunc)(void) = MyExpose; - wnd->setOnExpose(exposeFunc); + 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); @@ -107,33 +154,39 @@ 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->setTouchPinchCallback(TouchPinch); + TouchDelegate onTouch = [this](SDL_MultiGestureEvent& e) + { this->TouchPinch(e); }; + + wnd->setTouchPinchCallback(onTouch); + SetKeyEventHandler('A', &GLVisWindow::ToggleAntialiasing); - // auxKeyFunc (AUX_p, KeyCtrlP); // handled in vsdata.cpp - wnd->setOnKeyDown (SDLK_s, KeyS); - wnd->setOnKeyDown ('S', KeyS); + SetKeyEventHandler ('p', &GLVisWindow::KeyPrint); + SetKeyEventHandler ('r', &GLVisWindow::StopSpinning); + SetKeyEventHandler ('R', &GLVisWindow::StopSpinning); + 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); - 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); @@ -142,48 +195,116 @@ int InitVisualization (const char name[], int x, int y, int w, int h) 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); - wnd->setOnKeyDown (SDLK_KP_MULTIPLY, ZoomIn); - wnd->setOnKeyDown (SDLK_KP_DIVIDE, ZoomOut); + SetKeyEventHandler (SDLK_KP_MULTIPLY, &GLVisWindow::ZoomIn); + SetKeyEventHandler (SDLK_KP_DIVIDE, &GLVisWindow::ZoomOut); + + SetKeyEventHandler (SDLK_ASTERISK, &GLVisWindow::ZoomIn); + SetKeyEventHandler (SDLK_SLASH, &GLVisWindow::ZoomOut); - wnd->setOnKeyDown (SDLK_ASTERISK, ZoomIn); - wnd->setOnKeyDown (SDLK_SLASH, ZoomOut); + SetKeyEventHandler (SDLK_LEFTBRACKET, &GLVisWindow::ScaleDown); + SetKeyEventHandler (SDLK_RIGHTBRACKET, &GLVisWindow::ScaleUp); + SetKeyEventHandler (SDLK_AT, &GLVisWindow::LookAt); - wnd->setOnKeyDown (SDLK_LEFTBRACKET, ScaleDown); - wnd->setOnKeyDown (SDLK_RIGHTBRACKET, ScaleUp); - wnd->setOnKeyDown (SDLK_AT, LookAt); + SetKeyEventHandler (SDLK_SPACE, &GLVisWindow::ThreadsPauseFunc); #ifndef __EMSCRIPTEN__ - wnd->setOnKeyDown(SDLK_LEFTPAREN, ShrinkWindow); - wnd->setOnKeyDown(SDLK_RIGHTPAREN, EnlargeWindow); + SetKeyEventHandler(SDLK_LEFTPAREN, &GLVisWindow::ShrinkWindow); + SetKeyEventHandler(SDLK_RIGHTPAREN, &GLVisWindow::EnlargeWindow); +#endif +} - if (locscene) +GLVisWindow::~GLVisWindow() +{ +#ifndef __EMSCRIPTEN__ + if (glvis_command) { - delete locscene; + glvis_command->Terminate(); } #endif - locscene = nullptr; +} + +void GLVisWindow::InitVisualization(int field_type, StreamState state, + bool& keep_attr, + const mfem::Array& input_streams) +{ + prob_state = std::move(state); +#ifndef __EMSCRIPTEN__ + if (input_streams.Size() > 0) + { + glvis_command.reset(new GLVisCommand(this, keep_attr)); + comm_thread.reset(new communication_thread(glvis_command.get(), input_streams)); + } +#endif + + locscene = prob_state.CreateVisualizationScene(this, 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); + } + + if (!prob_state.keys.empty()) + { + CallKeySequence(prob_state.keys.c_str()); + } +} + +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); } + }); +} - return 0; +void GLVisWindow::SetKeyEventHandler(int key, void (GLVisWindow::*handler)()) +{ + 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); }; + internal_keyevents[key] = handlerWrapper; + SetupHandledKey(key); } -void SendKeySequence(const char *seq) +void GLVisWindow::SendKeySequence(const char *seq) { for (const char* key = seq; *key != '\0'; key++) { @@ -236,9 +357,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; @@ -290,54 +409,22 @@ void CallKeySequence(const char *seq) disableSendExposeEvent = false; } -void InitIdleFuncs(); - -void SetVisualizationScene(VisualizationScene * scene, int view, - const char *keys) -{ - locscene = scene; - locscene -> view = view; - if (view == 2) - { - scene -> CenterObject2D(); - } - else - { - scene -> CenterObject(); - } - - InitIdleFuncs(); - if (scene -> spinning) - { - AddIdleFunc(MainLoop); - } - - if (keys) - { - // SendKeySequence(keys); - CallKeySequence(keys); - } - wnd->getRenderer().setPalette(&locscene->palette); -} - -void RunVisualization() +void GLVisWindow::RunVisualization() { + visualize = 1; + wnd->setOnIdle([this]() {return MainIdleFunc();}); #ifndef __EMSCRIPTEN__ wnd->mainLoop(); #endif - InitIdleFuncs(); - delete locscene; - delete wnd; - wnd = nullptr; } -void SendExposeEvent() +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); @@ -374,13 +461,20 @@ 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->palette.GetColorTexture(); GLuint alpha_tex = locscene->palette.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]); + + 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) { @@ -389,7 +483,7 @@ void MyExpose(GLsizei w, GLsizei h) wnd->getRenderer().render(frame.queue); } -void MyExpose() +void GLVisWindow::MyExpose() { int w, h; wnd->getGLDrawSize(w, h); @@ -397,57 +491,100 @@ void MyExpose() wnd->signalSwap(); } - -Array IdleFuncs; -int LastIdleFunc; - -void InitIdleFuncs() +#ifndef __EMSCRIPTEN__ +bool GLVisWindow::CommunicationIdleFunc() { - IdleFuncs.SetSize(0); - LastIdleFunc = 0; - wnd->setOnIdle(NULL); + 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; } +#endif -void MainIdleFunc() +bool GLVisWindow::MainIdleFunc() { - LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); - if (IdleFuncs[LastIdleFunc]) + bool sleep = true; +#ifndef __EMSCRIPTEN__ + if (glvis_command && visualize == 1 + && !(idle_funcs.Size() > 0 && use_idle)) + { + // 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) { - (*IdleFuncs[LastIdleFunc])(); + 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; +#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; } -void AddIdleFunc(void (*Func)(void)) +void GLVisWindow::AddIdleFunc(GLVisWindow::IdleFPtr Func) { - IdleFuncs.Union(Func); - wnd->setOnIdle(MainIdleFunc); + idle_funcs.Union(Func); + use_idle = false; + wnd->setOnIdle([this]() {return 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); + use_idle = false; +#ifndef __EMSCRIPTEN__ + if (!glvis_command) { wnd->setOnIdle(nullptr); } +#else + wnd->setOnIdle(nullptr); +#endif } } +void MainLoop(GLVisWindow* wnd) +{ + wnd->MainLoop(); +} -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() +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(); @@ -476,14 +613,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; @@ -499,41 +636,45 @@ 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; - RemoveIdleFunc(MainLoop); + wnd->StopSpinning(); 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(); @@ -546,36 +687,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; @@ -585,8 +723,8 @@ void LeftButtonUp (EventInfo *event) if ( (event->keymod & KMOD_SHIFT) && (xang != 0.0 || yang != 0.0) ) { - locscene -> spinning = 1; - 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; } @@ -601,13 +739,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; @@ -617,15 +755,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; @@ -636,12 +774,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; @@ -651,40 +789,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; @@ -715,318 +853,46 @@ 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 TouchPinch(SDL_MultiGestureEvent & e) +void GLVisWindow::ToggleAntialiasing() { - // Scale or Zoom? - locscene->Zoom(exp(e.dDist*10)); - 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); + bool curr_aa = wnd->getRenderer().getAntialiasing(); + wnd->getRenderer().setAntialiasing(!curr_aa); + const std::string strings_off_on[2] = { "off", "on" }; - /* now, shuffle the rest so it's almost correct */ - a = (Uint8*)surface->pixels; - last = a + pitch * (surface->h - 1); - b = last; + cout << "Multisampling/Antialiasing: " + << strings_off_on[!curr_aa ? 1 : 0] << endl; - 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; + SendExposeEvent(); } -int Screenshot(const char *fname, bool convert) +void GLVisWindow::TouchPinch(SDL_MultiGestureEvent & e) { -#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 + // Scale or Zoom? + locscene->Zoom(exp(e.dDist*10)); + SendExposeEvent(); } -void KeyS() +void GLVisWindow::Screenshot(std::string filename) { static int p = 1; @@ -1046,9 +912,16 @@ void KeyS() 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; } } @@ -1096,7 +969,7 @@ void PrintCaptureBuffer(gl3::CaptureBuffer& cbuf) } } -void KeyCtrlP() +void GLVisWindow::PrintToPDF() { #ifdef __EMSCRIPTEN__ cerr << "Printing in WebGL is not supported at this time." << endl; @@ -1137,13 +1010,13 @@ void KeyCtrlP() #endif } -void KeyQPressed() +void GLVisWindow::Quit() { wnd->signalQuit(); visualize = 0; } -void ToggleThreads() +void GLVisWindow::ToggleThreads() { static const char *state[] = { "running", "stopped" }; if (visualize > 0 && visualize < 3) @@ -1153,19 +1026,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) { @@ -1173,7 +1051,7 @@ void ThreadsStop() } } -void ThreadsRun() +void GLVisWindow::ThreadsRun() { if (visualize == 2) { @@ -1181,7 +1059,7 @@ void ThreadsRun() } } -void CheckSpin() +void GLVisWindow::RotationControl::CheckSpin() { if (fabs(xang) < 1.e-2) { @@ -1189,22 +1067,21 @@ void CheckSpin() } if (xang != 0. || yang != 0.) { - locscene->spinning = 1; - AddIdleFunc(MainLoop); + wnd->locscene->spinning = 1; + wnd->AddIdleFunc(::MainLoop); } else { - locscene->spinning = 0; - RemoveIdleFunc(MainLoop); + wnd->StopSpinning(); } 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; } @@ -1212,27 +1089,26 @@ void Key0Pressed() CheckSpin(); } -void KeyDeletePressed() +void GLVisWindow::RotationControl::KeyDeletePressed() { - if (locscene -> spinning) + if (wnd->locscene -> spinning) { xang = yang = 0.; - locscene -> spinning = 0; - RemoveIdleFunc(MainLoop); + wnd->StopSpinning(); constrained_spinning = 1; } else { xang = xang_step; - locscene -> spinning = 1; - 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; } @@ -1240,31 +1116,31 @@ void 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) { @@ -1277,31 +1153,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) @@ -1316,11 +1192,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.get(), 0.05, 0.); } else { @@ -1329,11 +1205,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.get(), -0.05, 0.); } else { @@ -1342,11 +1218,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.get(), 0., -0.05); } else { @@ -1355,11 +1231,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.get(), 0., 0.05); } else { @@ -1368,49 +1244,55 @@ 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(); } -void ZoomIn() +void GLVisWindow::StopSpinning() +{ + locscene -> spinning = 0; + RemoveIdleFunc(::MainLoop); +} + +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; @@ -1422,7 +1304,7 @@ void LookAt() const double window_scale_factor = 1.1; -void ShrinkWindow() +void GLVisWindow::ShrinkWindow() { int w, h; wnd->getWindowSize(w, h); @@ -1434,7 +1316,7 @@ void ShrinkWindow() ResizeWindow(w, h); } -void EnlargeWindow() +void GLVisWindow::EnlargeWindow() { int w, h; wnd->getWindowSize(w, h); @@ -1446,39 +1328,22 @@ 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); } -int GetUseTexture() -{ - return locscene->palette.GetSmoothSetting(); -} - -void SetUseTexture(int ut) -{ - if (ut == 0) - { - locscene->palette.UseDiscrete(); - } - else - { - locscene->palette.UseSmooth(); - } -} - int GetMultisample() { return glvis_multisample; @@ -1499,20 +1364,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() @@ -1545,23 +1401,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; } @@ -1580,18 +1440,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()) { @@ -1654,7 +1509,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; } @@ -1668,11 +1523,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 93542868..c3ef18bc 100644 --- a/lib/aux_vis.hpp +++ b/lib/aux_vis.hpp @@ -12,107 +12,223 @@ #ifndef GLVIS_AUX_VIS_HPP #define GLVIS_AUX_VIS_HPP +#include "mfem.hpp" + #include "gl/platform_gl.hpp" #include "gl/types.hpp" #include "sdl.hpp" #include "font.hpp" #include "openglvis.hpp" +#include "stream_reader.hpp" -/// Initializes the visualization and some keys. -int InitVisualization(const char name[], int x, int y, int w, int h); - -void SetVisualizationScene(VisualizationScene * scene, - int view = 3, const char *keys = NULL); - -/// Start the infinite visualization loop. -void RunVisualization(); - -/// Send expose event. In our case MyReshape is executed and Draw after it. -void SendExposeEvent(); - -void MyExpose(); - -void MainLoop(); - -SdlWindow * GetAppWindow(); -VisualizationScene * GetVisualizationScene(); - -void SetLegacyGLOnly(bool status); - -void AddIdleFunc(void (*Func)(void)); -void RemoveIdleFunc(void (*Func)(void)); - -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 TouchPinch(SDL_MultiGestureEvent & e); - -void KeyCtrlP(); -void KeyS(); -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 Key0Pressed(); -void KeyDeletePressed(); -void KeyEnterPressed(); - -void KeyLeftPressed(GLenum); -void KeyRightPressed(GLenum); -void KeyUpPressed(GLenum); -void KeyDownPressed(GLenum); -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); +#ifndef __EMSCRIPTEN__ +class GLVisCommand; +class communication_thread; +#endif -/// Take a screenshot using libtiff, libpng or sdl2 -int Screenshot(const char *fname, bool convert = false); +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); + + ~GLVisWindow(); + + void InitVisualization(int field_type, StreamState state, + bool& keep_attr, + const mfem::Array& input_streams = {}); + + void SetFont(const std::string& fn); + + StreamState& getStreamState() { return prob_state; } + + VisualizationScene* getScene() { return locscene.get(); } + + GlVisFont* getFont() { return &font; } + + 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); + + void AddIdleFunc(IdleFPtr func); + void RemoveIdleFunc(IdleFPtr func); + + void ThreadsStop(); + void ThreadsRun(); + void ToggleThreads(); + + 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); + + /// 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) + { + auto wrapped_eh = [this, eh, exposeAfter](GLenum e) + { + TScene* pScene = dynamic_cast(locscene.get()); + (pScene->*eh)(); + if (exposeAfter) { SendExposeEvent(); } + }; + keyevents[key] = wrapped_eh; + SetupHandledKey(key); + } + + void AddKeyEvent(int key, void (*eh)(GLVisWindow*), bool exposeAfter = true) + { + auto wrapped_eh = [this, eh, exposeAfter](GLenum e) + { + (*eh)(this); + if (exposeAfter) { SendExposeEvent(); } + }; + keyevents[key] = wrapped_eh; + SetupHandledKey(key); + } + + 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(); } + }; + 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)); + + bool MainIdleFunc(); +#ifndef __EMSCRIPTEN__ + bool CommunicationIdleFunc(); +#endif + + void MyReshape(GLsizei w, GLsizei h); + void MyExpose(GLsizei w, GLsizei h); + + // Internal event handler for touch screen actions + void TouchPinch(SDL_MultiGestureEvent & e); + + // 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(); + + void StopSpinning(); + + // Internal event handler for toggling state of threads + void ThreadsPauseFunc(GLenum); + + void KeyPrint(GLenum); + + std::unique_ptr wnd; + std::unique_ptr locscene; +#ifndef __EMSCRIPTEN__ + std::unique_ptr glvis_command; + std::unique_ptr comm_thread; +#endif + StreamState prob_state; + bool use_idle = false; + + // Idle function callbacks + 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; -/// Send a sequence of keystrokes to the visualization window -void SendKeySequence(const char *seq); + int visualize = 0; -// 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); + bool disableSendExposeEvent = false; + GlVisFont font; + std::string priority_font; + int font_size = 12; + + struct RotationControl; + std::unique_ptr rot_data; + +}; + + + +/// Take a screenshot using libtiff, libpng or sdl2 +//int Screenshot(const char *fname, bool convert = false); -void SetUseTexture(int ut); -int GetUseTexture(); -void Set_Texture_Image(); int GetMultisample(); void SetMultisample(int m); @@ -121,9 +237,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 ddcf4bdc..da694fbf 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 a1f3137e..7654f736 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 7d6442b4..ea1d269c 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 6144faa0..61483a37 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" #include "../palettes.hpp" namespace gl3 @@ -173,10 +174,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 === @@ -201,6 +202,7 @@ class MeshRenderer GLuint color_tex, alpha_tex, font_tex; float line_w, line_w_aa; PaletteState* pal; + GlVisFont* font; bool feat_use_fbo_antialias; void init(); @@ -209,7 +211,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() @@ -227,6 +230,8 @@ class MeshRenderer } void setPalette(PaletteState* pal) { this->pal = pal; } + 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 dc761643..50a28be1 100644 --- a/lib/gl/renderer_core.cpp +++ b/lib/gl/renderer_core.cpp @@ -290,19 +290,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; @@ -402,7 +402,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 5804c1a6..eaf3a0aa 100644 --- a/lib/gl/renderer_core.hpp +++ b/lib/gl/renderer_core.hpp @@ -92,9 +92,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 0d641335..745b4a0a 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 565ba517..74d6f786 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(PaletteState& pal, CaptureBuffer& cbuf, int hnd) override; }; diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 069a94d8..c7a60e04 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -123,7 +123,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; @@ -133,6 +132,11 @@ VisualizationScene::VisualizationScene() 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], @@ -357,12 +361,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); } } @@ -467,3 +469,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 a23bf93a..4712fe08 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -14,12 +14,15 @@ #include #include "sdl.hpp" +#include "font.hpp" #include "gl/types.hpp" #include "material.hpp" #include "palettes.hpp" #include "mfem.hpp" #include "geom_utils.hpp" +class GLVisWindow; + // Visualization header file class Camera @@ -64,8 +67,6 @@ class VisualizationScene // How to scale the visualized object(s) double xscale, yscale, zscale; - SdlWindow * wnd; - glm::mat4 proj_mtx; enum @@ -87,6 +88,7 @@ class VisualizationScene int light_mat_idx; bool use_light; + GlVisFont* font = nullptr; gl3::RenderParams GetMeshDrawParams(); glm::mat4 GetModelViewMtx(); @@ -134,6 +136,8 @@ class VisualizationScene VisualizationScene(); virtual ~VisualizationScene(); + virtual void Init(GLVisWindow* wnd); + int spinning, OrthogonalProjection, print, movie; double ViewAngle, ViewScale; double ViewCenterX, ViewCenterY; @@ -150,6 +154,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); @@ -166,16 +172,36 @@ 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; } 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 }; + } + } 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/sdl.cpp b/lib/sdl.cpp index 63b31533..79e806d1 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 { @@ -205,7 +204,8 @@ 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)) @@ -605,7 +605,6 @@ void SdlWindow::multiGestureEvent(SDL_MultiGestureEvent & e) void SdlWindow::mainIter() { SDL_Event e; - static bool useIdle = false; static bool disable_mouse = false; if (SDL_PollEvent(&e)) { @@ -666,28 +665,8 @@ void SdlWindow::mainIter() #ifndef __EMSCRIPTEN__ else if (onIdle) { - if (glvis_command == NULL || visualize == 2 || useIdle) - { - onIdle(); - } - else - { - if (glvis_command->Execute() < 0) - { - running = false; - } - } - useIdle = !useIdle; - } - else - { - int status; - if (glvis_command && visualize == 1 && - (status = glvis_command->Execute()) != 1) - { - if (status < 0) { running = false; } - } - else + bool sleep = onIdle(); + if (sleep) { // Wait for the next event (without consuming CPU cycles, if possible) // See also: SdlWindow::signalLoop() @@ -730,7 +709,6 @@ void SdlWindow::mainLoop() ((SdlWindow*) arg)->mainIter(); }, this, 0, true); #else - visualize = 1; while (running) { mainIter(); @@ -741,7 +719,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 88e16314..bbf188ea 100644 --- a/lib/sdl.hpp +++ b/lib/sdl.hpp @@ -27,11 +27,12 @@ struct EventInfo SDL_Keymod keymod; }; -typedef void (*TouchDelegate)(SDL_MultiGestureEvent&); -typedef void (*MouseDelegate)(EventInfo*); +typedef std::function TouchDelegate; +typedef std::function MouseDelegate; typedef std::function KeyDelegate; -typedef void (*WindowDelegate)(int, int); -typedef void (*Delegate)(); +typedef std::function WindowDelegate; +typedef std::function Delegate; +typedef std::function IdleDelegate; class SdlWindow { @@ -59,7 +60,7 @@ class SdlWindow bool running; - Delegate onIdle{nullptr}; + IdleDelegate onIdle{nullptr}; Delegate onExpose{nullptr}; WindowDelegate onReshape{nullptr}; std::map onKeyDown; @@ -102,6 +103,8 @@ class SdlWindow void keyEvent(char c); void multiGestureEvent(SDL_MultiGestureEvent & e); + int screenshotHelper(bool convert = false); + std::string saved_keys; public: SdlWindow(); @@ -109,7 +112,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(); @@ -118,7 +121,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/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/stream_reader.cpp b/lib/stream_reader.cpp index 24ba3d95..09e79122 100644 --- a/lib/stream_reader.cpp +++ b/lib/stream_reader.cpp @@ -356,6 +356,133 @@ ProjectVectorFEGridFunction(std::unique_ptr gf) return gf; } +std::unique_ptr +StreamState::CreateVisualizationScene(GLVisWindow* wnd, 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); + } + // initialize events and initial scene state + vss->Init(wnd); + 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->palette.SetIndex(4); + } + } + 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) + { + 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->palette.SetIndex(11); + vss->SetLightMatIdx(4); + } + else + { + // Use the 'bone' palette when visualizing a surface mesh only + vss->palette.SetIndex(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) + { + grid_f = ProjectVectorFEGridFunction(std::move(grid_f)); + vs.reset(new VisualizationSceneVector3d(*grid_f)); + } + else + { + vs.reset(new VisualizationSceneVector3d(*mesh, solu, solv, solw)); + } + } + // initialize events and initial scene state + vs->Init(wnd); + } + + 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; +} + + bool StreamState::SetNewMeshAndSolution(StreamState new_state, VisualizationScene* vs) { diff --git a/lib/stream_reader.hpp b/lib/stream_reader.hpp index 179e4c75..7c53ea78 100644 --- a/lib/stream_reader.hpp +++ b/lib/stream_reader.hpp @@ -35,6 +35,9 @@ struct StreamState int ReadStream(std::istream &is, const std::string &data_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/threads.cpp b/lib/threads.cpp index fc3d809b..f5df5fc2 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -16,15 +16,10 @@ 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) - : curr_state(state) + GLVisWindow* wnd, bool _keep_attr) + : window(wnd), keep_attr(_keep_attr) { - vs = _vs; - keep_attr = _keep_attr; - num_waiting = 0; terminating = false; command = NO_COMMAND; @@ -32,6 +27,11 @@ GLVisCommand::GLVisCommand( autopause = 0; } +bool GLVisCommand::FixElementOrientations() const +{ + return window->getStreamState().fix_elem_orient; +} + int GLVisCommand::lock() { int my_id; @@ -58,7 +58,7 @@ int GLVisCommand::signal() { command_ready = true; - SdlWindow *sdl_window = GetAppWindow(); + SdlWindow *sdl_window = window->getSdl(); if (sdl_window) { sdl_window->signalLoop(); @@ -400,6 +400,9 @@ int GLVisCommand::Execute() return 1; } + VisualizationSceneScalarData* vs + = dynamic_cast(window->getScene()); + switch (command) { case NO_COMMAND: @@ -414,13 +417,13 @@ int GLVisCommand::Execute() new_state.SetMeshSolution(); mesh_range = new_state.grid_f->Max() + 1.0; } - if (curr_state.SetNewMeshAndSolution(std::move(new_state), *vs)) + if (window->getStreamState().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 { @@ -429,7 +432,7 @@ int GLVisCommand::Execute() if (autopause) { cout << "Autopause ..." << endl; - ThreadsStop(); + window->ThreadsStop(); } break; } @@ -437,14 +440,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; - } + window->Screenshot(screenshot_filename.c_str()); + cout << "-> " << screenshot_filename << endl; break; } @@ -452,15 +449,15 @@ int GLVisCommand::Execute() { cout << "Command: keys: '" << key_commands << "'" << endl; // SendKeySequence(key_commands.c_str()); - 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; - ResizeWindow(window_w, window_h); + window->ResizeWindow(window_w, window_h); break; } @@ -469,23 +466,23 @@ 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); + window->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()); + window->SetWindowTitle(window_title.c_str()); break; } case PLOT_CAPTION: { cout << "Command: plot_caption: " << plot_caption << endl; - ::plot_caption = plot_caption; - (*vs)->PrepareCaption(); // turn on or off the caption - MyExpose(); + vs->SetCaption(plot_caption); + vs->PrepareCaption(); // turn on or off the caption + window->MyExpose(); break; } @@ -493,16 +490,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(), - axis_label_z.c_str()); - MyExpose(); + vs->SetAxisLabels(axis_label_x.c_str(), axis_label_y.c_str(), + axis_label_z.c_str()); + window->MyExpose(); break; } case PAUSE: { cout << "Command: pause: "; - ToggleThreads(); + window->ToggleThreads(); break; } @@ -510,34 +507,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; } @@ -559,9 +556,9 @@ int GLVisCommand::Execute() } if (s != -1) { - (*vs)->SetShading(s, false); + vs->SetShading(s, false); cout << shading << endl; - MyExpose(); + window->MyExpose(); } else { @@ -574,9 +571,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; } @@ -585,19 +582,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 { @@ -610,26 +607,18 @@ int GLVisCommand::Execute() case PALETTE: { cout << "Command: palette: " << palette << endl; - (*vs)->palette.SetIndex(palette-1); - if (!GetUseTexture()) - { - (*vs)->EventUpdateColors(); - } - MyExpose(); + vs->palette.SetIndex(palette-1); + window->MyExpose(); break; } case PALETTE_REPEAT: { cout << "Command: palette_repeat: " << palette_repeat << endl; - (*vs)->palette.SetRepeatTimes(palette_repeat); - (*vs)->palette.Init(); + vs->palette.SetRepeatTimes(palette_repeat); + vs->palette.Init(); - if (!GetUseTexture()) - { - (*vs)->EventUpdateColors(); - } - MyExpose(); + window->MyExpose(); break; } @@ -641,8 +630,8 @@ int GLVisCommand::Execute() cout << ' ' << camera[i]; } cout << endl; - (*vs)->cam.Set(camera); - MyExpose(); + vs->cam.Set(camera); + window->MyExpose(); break; } @@ -659,11 +648,11 @@ int GLVisCommand::Execute() cout << "Command: autopause: " << strings_off_on[autopause] << endl; if (autopause) { - ThreadsStop(); + window->ThreadsStop(); } else { - ThreadsRun(); // probably not needed + window->ThreadsRun(); // probably not needed } break; } @@ -696,11 +685,11 @@ void GLVisCommand::ToggleAutopause() cout << "Autopause: " << strings_off_on[autopause] << endl; if (autopause) { - ThreadsStop(); + window->ThreadsStop(); } else { - ThreadsRun(); + window->ThreadsRun(); } } @@ -713,8 +702,9 @@ GLVisCommand::~GLVisCommand() } } -communication_thread::communication_thread(Array &_is) - : is(_is) +communication_thread::communication_thread(GLVisCommand* parent_cmd, + const Array &_is) + : is(_is), glvis_command(parent_cmd) { new_m = NULL; new_g = NULL; diff --git a/lib/threads.hpp b/lib/threads.hpp index e270df52..87d8d8ac 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -19,13 +19,14 @@ #include #include +class GLVisWindow; + class GLVisCommand { private: // Pointers to global GLVis data - VisualizationSceneScalarData **vs; - StreamState& curr_state; - bool *keep_attr; + GLVisWindow* window; + bool keep_attr; std::mutex glvis_mutex; std::condition_variable glvis_cond; @@ -94,12 +95,11 @@ class GLVisCommand public: // called by the main execution thread - GLVisCommand(VisualizationSceneScalarData **_vs, - StreamState& thread_state, bool *_keep_attr); + GLVisCommand(GLVisWindow* parent, bool _keep_attr); // to be used by worker threads - bool KeepAttrib() { return *keep_attr; } // may need to sync this - bool FixElementOrientations() { return curr_state.fix_elem_orient; } + bool KeepAttrib() const { return keep_attr; } // may need to sync this + bool FixElementOrientations() const; // called by worker threads int NewMeshAndSolution(std::unique_ptr _new_m, @@ -136,13 +136,13 @@ class GLVisCommand ~GLVisCommand(); }; -extern GLVisCommand *glvis_command; - class communication_thread { private: // streams to read data from - Array &is; + Array is; + + GLVisCommand* glvis_command; // data that may be dynamically allocated by the thread std::unique_ptr new_m; @@ -157,7 +157,8 @@ class communication_thread void execute(); public: - communication_thread(Array &_is); + communication_thread(GLVisCommand* parent_cmd, + const Array &_is); ~communication_thread(); }; diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index aa5c5fc9..f5fc48af 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -460,40 +460,21 @@ 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; -extern VisualizationScene * locscene; - -void KeycPressed() -{ - vsdata->ToggleDrawColorbar(); - SendExposeEvent(); -} - -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(); -} - -void KeySPressed() -{ - vsdata -> ToggleScaling(); - SendExposeEvent(); -} - -void KeyaPressed() -{ - vsdata -> ToggleDrawAxes(); - SendExposeEvent(); + PrepareCaption(); // turn on or off the caption } -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" }; @@ -502,75 +483,56 @@ void Key_Mod_a_Pressed(GLenum state) cout << "Autoscale: " << flush; vsdata->SetAutoscale(autoscale); cout << autoscale_modes[autoscale] << endl; - SendExposeEvent(); } else { vsdata->ToggleDrawAxes(); - SendExposeEvent(); } } -void KeyHPressed() +//void KeyHPressed() +void VisualizationSceneScalarData::PrintHelpString() { - cout << vsdata->GetHelpString() << flush; + cout << GetHelpString() << flush; } -void KeylPressed() +void VisualizationSceneScalarData::ToggleLogscale() { - vsdata -> ToggleLight(); - SendExposeEvent(); + ToggleLogscale(true); } -void KeyLPressed() +void VisualizationSceneScalarData::Reset3DView() { - vsdata->ToggleLogscale(true); - SendExposeEvent(); -} - -void KeyrPressed() -{ - locscene -> spinning = 0; - RemoveIdleFunc(MainLoop); - vsdata -> CenterObject(); - - locscene -> ViewAngle = 45.0; - locscene -> ViewScale = 1.0; - locscene -> ViewCenterX = 0.0; - locscene -> ViewCenterY = 0.0; - locscene->cam.Reset(); - vsdata -> key_r_state = 0; - SendExposeEvent(); -} + CenterObject(); -void KeyRPressed() -{ - locscene->spinning = 0; - 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) - { - KeyCtrlP(); - } - else + VisualizationSceneScalarData * vsdata + = dynamic_cast(wnd->getScene()); + // KMOD_CTRL handled by KeyPrintPDF in aux_vis.cpp + if (!(state & KMOD_CTRL)) { - locscene->palette.NextIndex(); - SendExposeEvent(); + vsdata->palette.NextIndex(); } } -void KeyPPressed() +void KeyPPressed(GLVisWindow* wnd) { - locscene->palette.PrevIndex(); - SendExposeEvent(); + VisualizationSceneScalarData * vsdata + = dynamic_cast(wnd->getScene()); + vsdata->palette.PrevIndex(); } -static void KeyF5Pressed() +//static void KeyF5Pressed() +void VisualizationSceneScalarData::QueryLevelLines() { int n; double min, max; @@ -582,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->palette.GetRepeatTimes(); + int RepeatPaletteTimes = palette.GetRepeatTimes(); cout << "Palette is repeated " << RepeatPaletteTimes << " times.\n" << "(Negative value means the palette is flipped.)\n" << "Enter new value: " << flush; @@ -601,31 +563,32 @@ void KeyF6Pressed() } cout << "Palette will be repeated " << RepeatPaletteTimes << " times now.\n\n"; - vsdata->palette.SetRepeatTimes(RepeatPaletteTimes); + palette.SetRepeatTimes(RepeatPaletteTimes); - int pal = vsdata->palette.ChoosePalette(); + int pal = palette.ChoosePalette(); - int colors_used = vsdata->palette.GetNumColors(pal); - int palette_size = vsdata->palette.GetSize(pal); + int colors_used = palette.GetNumColors(pal); + int palette_size = palette.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->palette.SetNumColors(colors_used); + palette.SetNumColors(colors_used); - vsdata->palette.Init(); - vsdata->palette.SetIndex(pal); + palette.Init(); + palette.SetIndex(pal); - colors_used = vsdata->palette.GetNumColors(); + colors_used = palette.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" @@ -652,7 +615,6 @@ void KeyF7Pressed(GLenum state) << " max: (" << vsdata->x[1] << ',' << vsdata->y[1] << ',' << vsdata->z[1] << ")\n" << flush; vsdata->UpdateBoundingBox(); - SendExposeEvent(); } else { @@ -663,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; @@ -683,113 +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() -{ - vsdata->ToggleBackground(); - vsdata->PrepareAxes(); - vsdata->EventUpdateBackground(); - SendExposeEvent(); -} - -void KeyF1Pressed() -{ - vsdata->PrintState(); -} - -void KeyF2Pressed() -{ - vsdata -> EventUpdateColors(); - vsdata -> PrepareLines(); - // vsdata->CPPrepare(); - SendExposeEvent(); -} - -void KeykPressed() +void VisualizationSceneScalarData::ToggleBackground() { - 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 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; - //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(); + VisualizationScene::ToggleBackground(); + PrepareAxes(); + EventUpdateBackground(); } -void KeyToggleTexture() +//void KeyF2Pressed() +void VisualizationSceneScalarData::RedrawColors() { - vsdata->ToggleTexture(); - SendExposeEvent(); + EventUpdateColors(); + PrepareLines(); + // CPPrepare(); } void VisualizationSceneScalarData::PrintLogscale(bool warn) @@ -978,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(); @@ -1004,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 = GetFont()->getFontLineSpacing(); - params.model_view.translate(-(double)caption_w / gl_w, - 1.0 - 2 * v_pos * line_h / gl_h, 0.0); + double line_h = font->getFontLineSpacing(); + 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; @@ -1020,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); @@ -1075,14 +952,12 @@ VisualizationSceneScalarData::VisualizationSceneScalarData( { mesh = &m; sol = &s; - - Init(); } -void VisualizationSceneScalarData::Init() +void VisualizationSceneScalarData::Init(GLVisWindow* wnd) { - vsdata = this; - wnd = GetAppWindow(); + // perform base class initialization first + VisualizationScene::Init(wnd); arrow_type = arrow_scaling_type = 0; scaling = 0; @@ -1103,51 +978,51 @@ void VisualizationSceneScalarData::Init() // if (!init) { // init = 1; + using SceneType = VisualizationSceneScalarData; - wnd->setOnKeyDown('l', KeylPressed); - wnd->setOnKeyDown('L', KeyLPressed); + wnd->AddKeyEvent('l', &SceneType::ToggleLight); + wnd->AddKeyEvent('L', &SceneType::ToggleLogscale); - wnd->setOnKeyDown('s', KeySPressed); + wnd->AddKeyEvent('s', &SceneType::ToggleScaling); - // wnd->setOnKeyDown('a', KeyaPressed); - wnd->setOnKeyDown('a', Key_Mod_a_Pressed); - wnd->setOnKeyDown('A', KeyAPressed); + // wnd->AddKeyEvent('a', KeyaPressed); + wnd->AddKeyEvent('a', Key_Mod_a_Pressed); - wnd->setOnKeyDown('r', KeyrPressed); - wnd->setOnKeyDown('R', KeyRPressed); + wnd->AddKeyEvent('r', &SceneType::Reset3DView); + wnd->AddKeyEvent('R', &SceneType::Toggle2DView); - 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', &SceneType::PrintHelpString); + wnd->AddKeyEvent('H', &SceneType::PrintHelpString); - wnd->setOnKeyDown(SDLK_F5, KeyF5Pressed); - wnd->setOnKeyDown(SDLK_F6, KeyF6Pressed); - wnd->setOnKeyDown(SDLK_F7, KeyF7Pressed); + wnd->AddKeyEvent(SDLK_F5, &SceneType::QueryLevelLines); + wnd->AddKeyEvent(SDLK_F6, &SceneType::QueryPaletteSettings); + wnd->AddKeyEvent(SDLK_F7, KeyF7Pressed); - wnd->setOnKeyDown(SDLK_BACKSLASH, KeyBackslashPressed); - wnd->setOnKeyDown('t', KeyTPressed); - wnd->setOnKeyDown('T', KeyTPressed); + wnd->AddKeyEvent(SDLK_BACKSLASH, &SceneType::QueryLightPosition); + wnd->AddKeyEvent('t', &SceneType::NextLightMatSetting); + wnd->AddKeyEvent('T', &SceneType::NextLightMatSetting); - wnd->setOnKeyDown('g', KeyGPressed); - wnd->setOnKeyDown('G', KeyGPressed); + wnd->AddKeyEvent('g', &SceneType::ToggleBackground); + wnd->AddKeyEvent('G', &SceneType::ToggleBackground); - wnd->setOnKeyDown('c', KeycPressed); - wnd->setOnKeyDown('C', KeyCPressed); + wnd->AddKeyEvent('c', &SceneType::ToggleDrawColorbar); + wnd->AddKeyEvent('C', &SceneType::QueryCaption); - 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, &SceneType::RedrawColors); - 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(); @@ -1181,6 +1056,11 @@ void VisualizationSceneScalarData::Init() PrepareRuler(); autoscale = 1; + + saved_key_func = [wnd]() -> std::string + { + return wnd->getSdl()->getSavedKeys(); + }; } VisualizationSceneScalarData::~VisualizationSceneScalarData() @@ -1326,7 +1206,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; @@ -1445,7 +1325,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 @@ -1590,7 +1470,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; @@ -1599,9 +1480,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 c5fbd3c5..eff73422 100644 --- a/lib/vsdata.hpp +++ b/lib/vsdata.hpp @@ -13,15 +13,13 @@ #define GLVIS_VSDATA_HPP #include +#include #include "openglvis.hpp" #include "mfem.hpp" using namespace mfem; -extern std::string plot_caption; // defined in glvis.cpp -extern std::string extra_caption; // defined in glvis.cpp - class Plane { private: @@ -36,7 +34,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]; } @@ -60,6 +59,11 @@ 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; int scaling, colorbar, drawaxes; @@ -73,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; @@ -126,6 +128,19 @@ 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(); + void QueryPaletteSettings(); + void QueryLightPosition(); + void NextLightMatSetting(); + void RedrawColors(); + void ToggleBackground(); + void ToggleLogscale(); + public: Plane *CuttingPlane; int key_r_state; @@ -141,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 @@ -196,6 +213,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; } @@ -239,6 +261,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(); @@ -263,7 +286,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/vssolution.cpp b/lib/vssolution.cpp index cff12196..36e6f8b9 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,115 +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); } } -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) +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(); + } +} + +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) +//static void KeyOPressed(GLenum state) +void VisualizationSceneSolution::ToggleRefineFunc() { refine_func = (refine_func+1)%4; cout << "Key 'o' will: "; @@ -319,118 +310,100 @@ 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 } -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() @@ -444,14 +417,11 @@ VisualizationSceneSolution::VisualizationSceneSolution( mesh = &m; sol = &s; v_normals = normals; - - Init(); } -void VisualizationSceneSolution::Init() +void VisualizationSceneSolution::Init(GLVisWindow* wnd) { rsol = NULL; - vssol = this; drawelems = shading = 1; drawmesh = 0; @@ -474,52 +444,54 @@ void VisualizationSceneSolution::Init() drawbdr = 0; - VisualizationSceneScalarData::Init(); // Calls FindNewBox() !!! + VisualizationSceneScalarData::Init(wnd); // Calls FindNewBox() !!! palette.SetIndex(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; // if (!init) { // init = 1; + 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, false); // expose handled in function + wnd->AddKeyEvent('O', &SceneType::ToggleRefineFunc); - 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', &SceneType::RotateCP); + wnd->AddKeyEvent('Y', &SceneType::RotateCPBack); + wnd->AddKeyEvent('z', &SceneType::TranslateCP); + wnd->AddKeyEvent('Z', &SceneType::TranslateCPBack); - 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, &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, &SceneType::ShrinkMatSubdomains); + wnd->AddKeyEvent(SDLK_F12, &SceneType::ZoomMatSubdomains); } Prepare(); diff --git a/lib/vssolution.hpp b/lib/vssolution.hpp index 5c178c5a..1a7e9563 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, @@ -74,6 +72,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; @@ -85,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; } @@ -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); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index b3369a06..9d4d0f54 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 @@ -105,18 +104,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; @@ -248,91 +235,57 @@ void VisualizationSceneSolution3d::CPMoved() } } -static void KeyxPressed() -{ - vssol3d -> CuttingPlane -> IncreasePhi(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); -} - -static void KeyXPressed() +void VisualizationSceneSolution3d::RotateCPPhi() { - vssol3d -> CuttingPlane -> DecreasePhi(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); -} - -static void KeyyPressed() -{ - vssol3d -> CuttingPlane -> IncreaseTheta(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); -} - -static void KeyYPressed() -{ - vssol3d -> CuttingPlane -> DecreaseTheta(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); -} - -static void KeyzPressed() -{ - vssol3d -> CuttingPlane -> IncreaseDistance(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); -} - -static void KeyZPressed() -{ - vssol3d -> CuttingPlane -> DecreaseDistance(); - vssol3d -> FindNodePos(); - vssol3d -> CPMoved(); - SendExposeEvent(); + CuttingPlane -> IncreasePhi(); + FindNodePos(); + CPMoved(); } -static void KeymPressed() +void VisualizationSceneSolution3d::RotateCPPhiBack() { - vssol3d -> ToggleDrawMesh(); - SendExposeEvent(); + CuttingPlane -> DecreasePhi(); + FindNodePos(); + CPMoved(); } -static void KeyePressed() +void VisualizationSceneSolution3d::RotateCPTheta() { - vssol3d -> ToggleDrawElems(); - SendExposeEvent(); + CuttingPlane -> IncreaseTheta(); + FindNodePos(); + CPMoved(); } -static void KeyMPressed() +void VisualizationSceneSolution3d::RotateCPThetaBack() { - vssol3d -> ToggleCPDrawMesh(); - SendExposeEvent(); + CuttingPlane -> DecreaseTheta(); + FindNodePos(); + CPMoved(); } -static void KeyEPressed() +void VisualizationSceneSolution3d::TranslateCP() { - vssol3d -> ToggleCPDrawElems(); - SendExposeEvent(); + CuttingPlane -> IncreaseDistance(); + FindNodePos(); + CPMoved(); } -static void KeyFPressed() +void VisualizationSceneSolution3d::TranslateCPBack() { - vssol3d -> ToggleShading(); - 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 { @@ -346,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; @@ -364,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); @@ -537,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) @@ -581,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) @@ -627,9 +579,8 @@ static void KeyF10Pressed() cout << "Showing " << ((dim == 3) ? "bdr " : "") << "attribute " << attr << endl; } - vssol3d -> PrepareLines(); - vssol3d -> Prepare(); - SendExposeEvent(); + PrepareLines(); + Prepare(); } VisualizationSceneSolution3d::VisualizationSceneSolution3d() @@ -640,15 +591,11 @@ VisualizationSceneSolution3d::VisualizationSceneSolution3d(Mesh &m, Vector &s) mesh = &m; sol = &s; GridF = NULL; - - Init(); } -void VisualizationSceneSolution3d::Init() +void VisualizationSceneSolution3d::Init(GLVisWindow* wnd) { - vssol3d = this; - cplane = 0; cp_drawmesh = 0; cp_drawelems = 1; drawlsurf = 0; @@ -687,7 +634,7 @@ void VisualizationSceneSolution3d::Init() } bdr_attr_to_show = 1; - VisualizationSceneScalarData::Init(); // calls FindNewBox + VisualizationSceneScalarData::Init(wnd); // calls FindNewBox FindNewValueRange(false); @@ -696,7 +643,8 @@ void VisualizationSceneSolution3d::Init() palette.SetIndex(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; @@ -706,50 +654,51 @@ void VisualizationSceneSolution3d::Init() // if (!init) { // init = 1; + 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, false); + wnd->AddKeyEvent('O', KeyOPressed, false); - wnd->setOnKeyDown('w', KeywPressed); - wnd->setOnKeyDown('W', KeyWPressed); + wnd->AddKeyEvent('w', &SceneType::MoveUpBdrElems); + wnd->AddKeyEvent('W', &SceneType::MoveDownBdrElems); - wnd->setOnKeyDown('x', KeyxPressed); - wnd->setOnKeyDown('X', KeyXPressed); + wnd->AddKeyEvent('x', &SceneType::RotateCPPhi); + wnd->AddKeyEvent('X', &SceneType::RotateCPPhiBack); - wnd->setOnKeyDown('y', KeyyPressed); - wnd->setOnKeyDown('Y', KeyYPressed); + wnd->AddKeyEvent('y', &SceneType::RotateCPTheta); + wnd->AddKeyEvent('Y', &SceneType::RotateCPThetaBack); - wnd->setOnKeyDown('z', KeyzPressed); - wnd->setOnKeyDown('Z', KeyZPressed); + wnd->AddKeyEvent('z', &SceneType::TranslateCP); + wnd->AddKeyEvent('Z', &SceneType::TranslateCPBack); - wnd->setOnKeyDown('u', KeyuPressed); - wnd->setOnKeyDown('U', KeyUPressed); + wnd->AddKeyEvent('u', &SceneType::MoveUpLevelSurf); + wnd->AddKeyEvent('U', &SceneType::MoveDownLevelSurf); - wnd->setOnKeyDown('v', KeyvPressed); - wnd->setOnKeyDown('V', KeyVPressed); + wnd->AddKeyEvent('v', &SceneType::AddLevelSurf); + wnd->AddKeyEvent('V', &SceneType::RemoveLevelSurf); - wnd->setOnKeyDown(SDLK_F3, KeyF3Pressed); - wnd->setOnKeyDown(SDLK_F4, KeyF4Pressed); - wnd->setOnKeyDown(SDLK_NUMLOCKCLEAR, ToggleMagicKey); + wnd->AddKeyEvent(SDLK_F3, &SceneType::ShrinkBoundaryElems); + wnd->AddKeyEvent(SDLK_F4, &SceneType::ZoomBoundaryElems); + wnd->AddKeyEvent(SDLK_NUMLOCKCLEAR, ToggleMagicKey, false); - wnd->setOnKeyDown(SDLK_F8, KeyF8Pressed); - wnd->setOnKeyDown(SDLK_F9, KeyF9Pressed); - wnd->setOnKeyDown(SDLK_F10, KeyF10Pressed); + wnd->AddKeyEvent(SDLK_F8, &SceneType::QueryToggleSubdomains); + wnd->AddKeyEvent(SDLK_F9, &SceneType::WalkNextSubdomain); + wnd->AddKeyEvent(SDLK_F10, &SceneType::WalkPrevSubdomain); - wnd->setOnKeyDown(SDLK_F11, KeyF11Pressed); - wnd->setOnKeyDown(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 2b1d8ee3..37ad1a8b 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); @@ -93,6 +91,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; @@ -102,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 67cf1dfc..41362fb7 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -99,76 +99,51 @@ std::string VisualizationSceneVector::GetHelpString() const return os.str(); } -VisualizationSceneVector * vsvector; -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; - -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 { @@ -177,8 +152,7 @@ void KeyuPressed() break; case 2: - vsvector->CycleVec2Scalar(1); - SendExposeEvent(); + CycleVec2Scalar(1); break; } @@ -186,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: @@ -200,7 +172,7 @@ void KeyuPressed() } } -void KeyUPressed() +void VisualizationSceneVector::ToggleKeyUFunc() { key_u_func = (key_u_func+1)%3; cout << "Key 'u' will: "; @@ -262,8 +234,6 @@ VisualizationSceneVector::VisualizationSceneVector(Mesh & m, sol = new Vector(mesh -> GetNV()); VecGridF = NULL; - - Init(); } VisualizationSceneVector::VisualizationSceneVector(GridFunction &vgf) @@ -287,12 +257,6 @@ VisualizationSceneVector::VisualizationSceneVector(GridFunction &vgf) sol = new Vector(mesh -> GetNV()); - // VisualizationSceneSolution::Init() sets rsol = NULL ! - { - Init(); - SetGridFunction(vgf); - } - mesh->GetNodes(vc0); if (vc0.Size() != vgf.Size()) { @@ -475,7 +439,7 @@ void VisualizationSceneVector::NewMeshAndSolution(GridFunction &vgf) PrepareVectorField(); } -void VisualizationSceneVector::Init() +void VisualizationSceneVector::Init(GLVisWindow* wnd) { drawdisp = 0; drawvector = 0; @@ -489,26 +453,30 @@ void VisualizationSceneVector::Init() (*sol)(i) = Vec2Scalar((*solx)(i), (*soly)(i)); } - VisualizationSceneSolution::Init(); + // VisualizationSceneSolution::Init() sets rsol = null + VisualizationSceneSolution::Init(wnd); + if (VecGridF) + { + SetGridFunction(*VecGridF); + } PrepareVectorField(); // PrepareDisplacedMesh(); // called by PrepareLines() - vsvector = this; - // static int init = 0; // 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); + 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', &SceneType::DoKeyU); + wnd->AddKeyEvent('U', &SceneType::ToggleKeyUFunc); } // Vec2Scalar is VecLength diff --git a/lib/vsvector.hpp b/lib/vsvector.hpp index ee56f1c2..cfa4e8c3 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, @@ -44,6 +42,18 @@ class VisualizationSceneVector : public VisualizationSceneSolution Vector vc0; IsoparametricTransformation T0; + int ianim = 0; + const int ianimmax = 10; + + void NextDisplacement(); + void PrevDisplacement(); + + void QueryArrowScaling(); + + int key_u_func = 0; + void ToggleKeyUFunc(); + void DoKeyU(); + public: VisualizationSceneVector(Mesh &m, Vector &sx, Vector &sy); VisualizationSceneVector(GridFunction &vgf); @@ -52,9 +62,10 @@ class VisualizationSceneVector : public VisualizationSceneSolution virtual ~VisualizationSceneVector(); + virtual void Init(GLVisWindow* wnd); + 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 0820537a..b8f89429 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -100,67 +100,55 @@ std::string VisualizationSceneVector3d::GetHelpString() const return os.str(); } -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() +void VisualizationSceneVector3d::Reset3DView() { - locscene -> spinning = 0; - 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; - 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() @@ -174,20 +162,16 @@ void VisualizationSceneVector3d::NPressed() Prepare(); PrepareLines(); } - - 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 +190,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 +199,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) @@ -339,8 +303,6 @@ VisualizationSceneVector3d::VisualizationSceneVector3d(Mesh &m, Vector &sx, sfes = NULL; VecGridF = NULL; - - Init(); } VisualizationSceneVector3d::VisualizationSceneVector3d(GridFunction &vgf) @@ -368,11 +330,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; @@ -385,7 +345,7 @@ void VisualizationSceneVector3d::Init() SetScalarFunction(); - VisualizationSceneSolution3d::Init(); + VisualizationSceneSolution3d::Init(wnd); PrepareVectorField(); PrepareDisplacedMesh(); @@ -393,35 +353,37 @@ void VisualizationSceneVector3d::Init() vflevel.Append(0); dvflevel.Append(level[0]); - vsvector3d = this; - // static int init = 0; // if (!init) { // init = 1; + using SceneType = VisualizationSceneVector3d; - wnd->setOnKeyDown('d', KeyDPressed); - wnd->setOnKeyDown('D', KeyDPressed); - - wnd->setOnKeyDown('n', KeyNPressed); - wnd->setOnKeyDown('N', KeyNPressed); + wnd->AddKeyEvent('d', &SceneType::ToggleDisplacements); + wnd->AddKeyEvent('D', &SceneType::ToggleDisplacements); - wnd->setOnKeyDown('b', KeyBPressed); - wnd->setOnKeyDown('B', KeyBPressed); + wnd->AddKeyEvent('n', &SceneType::NextDisplacement); + wnd->AddKeyEvent('N', &SceneType::NextDisplacement); - wnd->setOnKeyDown('r', KeyrPressed); // adds another function to 'r' and 'R' - wnd->setOnKeyDown('R', KeyRPressed); // the other function is in vsdata.cpp + wnd->AddKeyEvent('b', &SceneType::PrevDisplacement); + wnd->AddKeyEvent('B', &SceneType::PrevDisplacement); - 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 ab1cfaab..d13b3265 100644 --- a/lib/vsvector3d.hpp +++ b/lib/vsvector3d.hpp @@ -28,11 +28,17 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d GridFunction *VecGridF; FiniteElementSpace *sfes; - void Init(); - Array vflevel; Array dvflevel; + void NextDisplacement(); + void PrevDisplacement(); + void NPressed(); + + void NextVectorField(); + void PrevVectorField(); + void NextVectorFieldLevel(); + void PrevVectorFieldLevel(); public: int ianim, ianimd, ianimmax, drawdisp; @@ -43,9 +49,10 @@ class VisualizationSceneVector3d : public VisualizationSceneSolution3d virtual ~VisualizationSceneVector3d(); + virtual void Init(GLVisWindow* wnd); + virtual std::string GetHelpString() const; - void NPressed(); virtual void PrepareFlat(); virtual void Prepare(); virtual void PrepareLines(); @@ -53,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); diff --git a/makefile b/makefile index 3c1a2a1a..50f2018f 100644 --- a/makefile +++ b/makefile @@ -215,8 +215,9 @@ ALL_SOURCE_FILES = \ lib/gl/renderer.cpp lib/gl/renderer_core.cpp lib/gl/renderer_ff.cpp \ lib/gl/shader.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/vsvector.cpp lib/vsvector3d.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 WEB_ONLY_SOURCE_FILES = lib/aux_js.cpp