24 #if defined(GLVIS_USE_LIBTIFF)
26 #elif defined(GLVIS_USE_LIBPNG)
31 #ifndef __EMSCRIPTEN__
32 #include <fontconfig/fontconfig.h>
41 #ifdef GLVIS_MULTISAMPLE
42 static int glvis_multisample = GLVIS_MULTISAMPLE;
44 static int glvis_multisample = -1;
85 cout <<
"OpenGL Visualization" << endl;
101 cout <<
"Window should be up" << endl;
109 void (*exposeFunc)(void) =
MyExpose;
184 #ifndef __EMSCRIPTEN__
200 for (
const char* key = seq; *key !=
'\0'; key++)
255 const char *key = seq;
258 for ( ; *key !=
'\0'; key++ )
314 scene -> CenterObject2D();
318 scene -> CenterObject();
322 if (scene -> spinning)
337 #ifndef __EMSCRIPTEN__
367 projmtx.
ortho(-1.0, 1.0, -
double(h)/w,
double(h)/w, -10, 10);
371 projmtx.
ortho(-
double(w)/h,
double(w)/h, -1, 1, -10, 10);
373 projmtx.
scale(scale, scale, 1.0);
380 ViewAngle = (360.0/M_PI)*atan( tan( ViewAngle*(M_PI/360.0) ) *
383 projmtx.
perspective(ViewAngle,
double(w)/h, 0.1, 5.0);
385 projmtx.
translate(-ViewCenterX, -ViewCenterY, 0.0);
434 cout <<
"GLVisCommand signalled exit" << endl;
437 else if (status == 1)
448 #ifndef __EMSCRIPTEN__
458 if (
IdleFuncs.Size() > 0) { sleep =
false; }
530 std::this_thread::sleep_for(std::chrono::milliseconds{10});
535 snprintf(fname, 20,
"GLVis_m%04d", p++);
542 inline double sqr(
double t)
548 double &new_sph_u,
double &new_sph_t)
550 GLint viewport[4] = { 0, 0, 0, 0 };
552 const double maxr = 0.996194698091745532295;
555 r = sqrt(
sqr(viewport[2])+
sqr(viewport[3]))*M_SQRT1_2;
557 x = double(newx-viewport[0]-viewport[2]/2) / r;
558 y = double(-newy+viewport[1]+viewport[3]/2) / r;
563 x *= maxr/rr, y *= maxr/rr, rr = maxr;
566 new_sph_u = 2.0 * acos(rr) - M_PI_2;
567 new_sph_t = atan2(y, x);
575 oldx =
event->mouse_x;
576 oldy =
event->mouse_y;
590 GLint newx =
event->mouse_x;
591 GLint newy =
event->mouse_y;
594 if (event->
keymod & KMOD_CTRL)
596 if (event->
keymod & KMOD_SHIFT)
602 double new_sph_u, new_sph_t;
609 double scoord[3], ncoord[3], inprod, cross[3];
610 scoord[0] = scoord[1] = cos(
sph_u); scoord[2] = sin(
sph_u);
611 ncoord[0] = ncoord[1] = cos(new_sph_u); ncoord[2] = sin(new_sph_u);
612 scoord[0] *= cos(
sph_t); scoord[1] *= sin(
sph_t);
613 ncoord[0] *= cos(new_sph_t); ncoord[1] *= sin(new_sph_t);
618 newrot.
rotate(acos(inprod)*(180.0/M_PI), cross[0], cross[1], cross[2]);
623 else if (event->
keymod & KMOD_ALT)
627 else if (event->
keymod & KMOD_SHIFT)
648 GLint newx =
event->mouse_x;
649 GLint newy =
event->mouse_y;
654 if ( (event->
keymod & KMOD_SHIFT) && (
xang != 0.0 ||
yang != 0.0) )
661 if (event->
keymod & KMOD_CTRL)
680 GLint newx =
event->mouse_x;
681 GLint newy =
event->mouse_y;
683 if ( !( event->
keymod & KMOD_CTRL ) )
686 double TrX, TrY, scale;
705 TrX = 2.0*double(
oldx-newx)/scale;
706 TrY = 2.0*double(newy-
oldy)/scale;
714 double dx = double(newx-
oldx)/400;
715 double dy = double(
oldy-newy)/400;
717 if (event->
keymod & KMOD_SHIFT)
719 double sx = double(newx-
startx)/400;
720 double sy = double(
starty-newy)/400;
728 else if (event->
keymod & KMOD_ALT)
757 GLint newx =
event->mouse_x;
758 GLint newy =
event->mouse_y;
760 if (event->
keymod & KMOD_SHIFT)
767 x = (double)newx / 300;
768 y = -(double)newy / 300;
769 l = sqrt (x*x + y*y);
779 z = -sqrt (1. - l*l);
783 x = 0.; y = 0.; z = -1.;
785 cout <<
"(x,y,z) = (" << x <<
',' << y <<
',' << z <<
')' << endl;
788 else if ( !( event->
keymod & KMOD_CTRL ) )
813 #if defined(GLVIS_USE_LIBTIFF)
815 #elif defined(GLVIS_USE_LIBPNG)
816 const char *glvis_screenshot_ext =
".png";
818 const char *glvis_screenshot_ext =
".bmp";
822 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
826 Uint32
amask = 0x000000ff;
827 #else // little endian, like x86
828 Uint32 rmask = 0x000000ff;
829 Uint32 gmask = 0x0000ff00;
830 Uint32 bmask = 0x00ff0000;
831 Uint32 amask = 0xff000000;
835 #define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0)
836 #define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); }
840 Uint8 *t, *a, *b, *last;
843 if ( SDL_LOCKIFMUST(surface) < 0 )
851 SDL_UNLOCKIFMUST(surface);
856 pitch = surface->pitch;
857 t = (Uint8*)malloc(pitch);
861 SDL_UNLOCKIFMUST(surface);
866 memcpy(t,surface->pixels,pitch);
869 a = (Uint8*)surface->pixels;
870 last = a + pitch * (surface->h - 1);
882 memmove( b, b+pitch, last-b );
885 memcpy(last,t,pitch);
889 SDL_UNLOCKIFMUST(surface);
894 #ifdef GLVIS_USE_LIBPNG
895 int SaveAsPNG(
const char *fname,
int w,
int h,
bool is_hidpi,
bool with_alpha,
896 std::function<
void(
int,
void*)> get_row)
898 png_byte *pixels =
new png_byte[(with_alpha ? 4 : 3)*w];
904 png_structp png_ptr =
905 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
911 png_infop info_ptr = png_create_info_struct(png_ptr);
914 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
919 FILE *fp = fopen(fname,
"wb");
922 png_destroy_write_struct(&png_ptr, &info_ptr);
927 if (setjmp(png_jmpbuf(png_ptr)))
930 png_destroy_write_struct(&png_ptr, &info_ptr);
935 png_uint_32 ppi = is_hidpi ? 144 : 72;
936 png_uint_32 ppm = ppi/0.0254 + 0.5;
937 png_set_pHYs(png_ptr, info_ptr, ppm, ppm, PNG_RESOLUTION_METER);
939 png_init_io(png_ptr, fp);
940 png_set_IHDR(png_ptr, info_ptr, w, h, 8,
941 with_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
942 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
943 PNG_FILTER_TYPE_DEFAULT);
946 png_write_info(png_ptr, info_ptr);
947 for (
int i = 0; i < h; i++)
951 glReadPixels(0, h-1-i, w, 1, with_alpha ? GL_RGBA : GL_RGB,
952 GL_UNSIGNED_BYTE, pixels);
958 png_write_row(png_ptr, pixels);
960 png_write_end(png_ptr, info_ptr);
963 png_destroy_write_struct(&png_ptr, &info_ptr);
968 #endif // GLVIS_USE_LIBPNG
973 cout <<
"Screenshot: glFinish() ... " << flush;
977 cout <<
"done." << endl;
979 #ifndef __EMSCRIPTEN__
982 MFEM_WARNING(
"Expose pending, some events may not have been handled." << endl);
984 string filename = fname;
985 string convert_name = fname;
986 bool call_convert =
false;
990 size_t ext_size = strlen(glvis_screenshot_ext);
991 if (filename.size() < ext_size ||
992 filename.compare(filename.size() - ext_size,
1009 cerr <<
"Screenshot: reading image data from back buffer..." << endl;
1011 glReadBuffer(GL_BACK);
1016 cerr <<
"Screenshot: reading image data from front buffer..." << endl;
1018 MFEM_WARNING(
"Screenshot: Reading from the front buffer is unreliable. "
1019 <<
" Resulting screenshots may be incorrect." << endl);
1020 glReadBuffer(GL_FRONT);
1022 #if defined(GLVIS_USE_LIBTIFF)
1028 unsigned char *pixels =
new unsigned char[3*w];
1034 image = TIFFOpen(filename.c_str(),
"w");
1041 TIFFSetField(image, TIFFTAG_IMAGEWIDTH, w);
1042 TIFFSetField(image, TIFFTAG_IMAGELENGTH, h);
1043 TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8);
1044 TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
1045 TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1046 TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 3);
1047 TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1);
1048 TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
1049 TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1050 for (
int i = 0; i < h; i++)
1052 glReadPixels(0, h-i-1, w, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels);
1053 if (TIFFWriteScanline(image, pixels, i, 0) < 0)
1061 TIFFFlushData(image);
1065 #elif defined(GLVIS_USE_LIBPNG)
1068 if (status != 0) {
return status; }
1074 unsigned char * pixels =
new unsigned char[w*h*4];
1075 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1077 SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, w, h, 8*4, w*4, rmask,
1078 gmask, bmask, amask);
1079 if (surf ==
nullptr)
1081 std::cerr <<
"unable to take screenshot: " << SDL_GetError() << std::endl;
1087 std::cerr <<
"failed to invert surface, your screenshot may be upside down" <<
1090 SDL_SaveBMP(surf, filename.c_str());
1091 SDL_FreeSurface(surf);
1095 call_convert =
true;
1096 convert_name +=
".png";
1105 cmd <<
"convert " << filename <<
' ' << convert_name;
1106 if (system(cmd.str().c_str()))
1110 remove(filename.c_str());
1114 cout <<
"Screenshots not yet implemented for JS" << endl;
1128 cout <<
"Recording a movie (series of snapshots)..." << endl;
1138 cout <<
"Taking snapshot number " << p <<
"... ";
1140 snprintf(fname, 20,
"GLVis_s%02d", p++);
1142 cout <<
"done" << endl;
1159 for (
size_t i = 0; i < cbuf.
lines.size(); i += 2)
1161 GL2PSvertex lineOut[2] =
1166 gl2psAddPolyPrimitive(GL2PS_LINE, 2, lineOut, 0, 0.f, 0.f,
1167 0xFFFF, 1, 0.2, 0, 0, 0);
1170 for (
size_t i = 0; i < cbuf.
triangles.size(); i += 3)
1172 GL2PSvertex triOut[3] =
1178 gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, triOut, 0, 0.f, 0.f,
1179 0xFFFF, 1, 1, 0, 0, 0);
1182 for (
const auto &entry : cbuf.
text)
1185 gl2psForceRasterPos(&rpos);
1186 gl2psText(entry.text.c_str(),
"Times", 12);
1192 #ifdef __EMSCRIPTEN__
1193 cerr <<
"Printing in WebGL is not supported at this time." << endl;
1195 cout <<
"Printing the figure to GLVis.pdf... " << flush;
1198 fp = fopen(
"GLVis.pdf",
"wb");
1199 GLint viewport[4] = { 0, 0, 0, 0 };
1207 gl2psBeginPage (
"GLVis.pdf",
"GLVis", viewport,
1210 GL2PS_SIMPLE_LINE_OFFSET |
1218 GL2PS_NO_OPENGL_CONTEXT,
1219 GL_RGBA, 0, NULL, 16, 16, 16, 0, fp,
"a" );
1226 cout <<
"done" << endl;
1239 static const char *state[] = {
"running",
"stopped" };
1243 cout <<
"Communication thread(s): " << state[
visualize-1] << endl;
1249 if (state & KMOD_CTRL)
1277 if (fabs(
xang) < 1.e-2)
1291 cout <<
"Spin angle: " <<
xang <<
" degrees / frame" << endl;
1412 if (state & KMOD_CTRL)
1425 if (state & KMOD_CTRL)
1438 if (state & KMOD_CTRL)
1451 if (state & KMOD_CTRL)
1509 cout <<
"New y = " << flush;
1520 w = (int)ceil(w / window_scale_factor);
1521 h = (int)ceil(h / window_scale_factor);
1523 cout <<
"New window size : " << w <<
" x " << h << endl;
1532 w = (int)ceil(w * window_scale_factor);
1533 h = (int)ceil(h * window_scale_factor);
1535 cout <<
"New window size : " << w <<
" x " << h << endl;
1575 return glvis_multisample;
1580 if (glvis_multisample > -2)
1582 glvis_multisample = m;
1586 cout <<
"Multisampling is disabled." << endl;
1626 "Ubuntu Light:style=Regular",
1627 "Ubuntu:style=Regular:weight=80",
1628 "OpenSans:style=Regular",
1629 "DejaVu Sans:style=Book:width=Normal",
1630 "DejaVu LGC Sans:style=Book:width=Normal",
1631 "Bitstream Vera Sans:style=Roman",
1632 "FreeSans:style=Medium",
1633 "Ubuntu Mono:style=Regular",
1634 "DejaVu Sans Mono:style=Book",
1635 "DejaVu LGC Sans Mono:style=Book",
1636 "Helvetica:style=Regular",
1637 "Arial:style=Regular:weight=80"
1649 GLenum alphaChannel =
1651 glvis_font.setAlphaChannel(alphaChannel);
1652 bool try_fc_patterns =
true;
1653 if (!priority_font.empty())
1656 glvis_font.LoadFont(priority_font, 0, font_size))
1658 try_fc_patterns =
false;
1662 cerr <<
"InitFont(): Font not found: " << priority_font << endl;
1665 if (try_fc_patterns)
1667 if (!
SetFont(fc_font_patterns, font_size))
1670 "InitFont(): No fonts found matching the built-in patterns.\n"
1671 "Use the -fn option or edit 'fc_font_patterns' in lib/aux_vis.cpp"
1683 bool SetFont(
const vector<std::string>& font_patterns,
int height)
1685 #ifdef __EMSCRIPTEN__
1686 return glvis_font.LoadFont(
"OpenSans.ttf", 0, height);
1693 FcObjectSet * os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FILE,
1694 FC_SCALABLE, FC_INDEX, FC_WEIGHT,
1697 for (
const string& pattern : font_patterns)
1699 string patternScale = pattern +
":scalable=True";
1700 FcPattern * pat = FcNameParse((FcChar8*)patternScale.c_str());
1706 FcFontSet * fs = FcFontList(0, pat, os);
1709 FcPatternDestroy(pat);
1715 cout <<
"Font pattern '" << pattern <<
"' matched fonts:\n";
1719 cout <<
"Font pattern '" << pattern <<
"' matched no fonts.\n";
1722 std::string font_file =
"";
1723 std::string font_name =
"";
1725 for (
int match_idx = 0; match_idx < fs->nfont; match_idx++)
1730 FcPatternGetBool(fs->fonts[match_idx], FC_SCALABLE, 0, &scalable);
1731 FcPatternGetInteger(fs->fonts[match_idx], FC_INDEX, 0, &curr_font_idx);
1732 FcResult res = FcPatternGetString(fs->fonts[match_idx], FC_FILE, 0, &s);
1733 FcChar8 * fnt = FcNameUnparse(fs->fonts[match_idx]);
1735 cout <<
" - " << fnt << endl;
1737 if (res == FcResultMatch && s && font_file == std::string(
""))
1739 font_file = (
char*) s;
1740 font_name = (
char*) fnt;
1741 font_index = curr_font_idx;
1746 FcFontSetDestroy(fs);
1747 if (font_file != std::string(
""))
1749 if (glvis_font.LoadFont(font_file, font_index, height))
1758 FcObjectSetDestroy(os);
1763 return glvis_font.isFontLoaded();
1770 size_t pos = priority_font.rfind(
'-');
1771 if (pos != string::npos)
1773 font_size = std::stoi(priority_font.substr(pos + 1));
1774 priority_font.erase(pos);
1777 cout <<
"SetFont: name = '"
1779 <<
"', height = " << font_size << endl;
void SendExposeEvent()
Send expose event. In our case MyReshape is executed and Draw after it.
void MiddleButtonUp(EventInfo *)
thread_local int LastIdleFunc
void signalKeyDown(SDL_Keycode k, SDL_Keymod m=KMOD_NONE)
void identity()
Sets the matrix to the identity matrix.
int view
This is set by SetVisualizationScene.
void translate(double x, double y, double z)
Applies a translation transform to the matrix.
thread_local double sph_u
const double window_scale_factor
void TouchPinch(SDL_MultiGestureEvent &e)
void SendKeySequence(const char *seq)
Send a sequence of keystrokes to the visualization window.
int Screenshot(const char *fname, bool convert)
Take a screenshot using libtiff, libpng or sdl2.
void getGLDrawSize(int &w, int &h)
void LeftButtonDown(EventInfo *event)
thread_local SdlWindow * wnd
void mainLoop()
Runs the window loop.
void setViewport(GLsizei w, GLsizei h)
gl3::MeshRenderer & getRenderer()
void SetLineWidthMS(float width_ms)
void setPalette(PaletteState *pal)
void setAlphaTexture(GLuint tex_h)
thread_local GlVisFont glvis_font
VisualizationScene * GetVisualizationScene()
bool SetFont(const vector< std::string > &font_patterns, int height)
void TiltLeftRight(double angle)
void render(const RenderQueue &queued)
void setWindowTitle(std::string &title)
void MyExpose(GLsizei w, GLsizei h)
void ThreadsPauseFunc(GLenum state)
void SetUseTexture(int ut)
void TurnUpDown(double angle)
void SetVisualizationScene(VisualizationScene *scene, int view, const char *keys)
void MyReshape(GLsizei w, GLsizei h)
void setWindowPos(int x, int y)
void setLineWidth(float w)
void RightButtonLoc(EventInfo *event)
void AddIdleFunc(void(*Func)(void))
thread_local GLint startx
vector< FeedbackText > text
GL2PSvertex CreatePrintVtx(gl3::FeedbackVertex v)
void SDLMainLoop(bool server_mode)
void PreRotate(double angle, double x, double y, double z)
void SetProjectionMtx(glm::mat4 projection)
CaptureBuffer capture(const RenderQueue &queued)
void MoveUpDown(double dist)
thread_local GLint starty
void screenshot(std::string filename, bool convert=false)
Queues a screenshot to be taken.
constexpr int default_font_size
void MiddleButtonDown(EventInfo *event)
void RightButtonUp(EventInfo *)
void ComputeSphereAngles(int &newx, int &newy, double &new_sph_u, double &new_sph_t)
void getWindowSize(int &w, int &h)
thread_local gl3::GlMatrix srot
bool CommunicationIdleFunc()
static bool useLegacyTextureFmts()
GLuint GetColorTexture() const
GLuint GetAlphaTexture() const
void setOnMouseDown(int btn, MouseDelegate func)
void CrossProd(const double a[], const double b[], double cp[])
void SetLight0CustomPos(std::array< float, 4 > pos)
void LeftButtonLoc(EventInfo *event)
thread_local Array< void(*)()> IdleFuncs
void setFontTexture(GLuint tex_h)
void KeyUpPressed(GLenum state)
void RemoveIdleFunc(void(*Func)(void))
void ShiftView(double dx, double dy)
void callKeyDown(SDL_Keycode k, Uint16 mod=0)
static void StartSDL(bool server_mode)
void setOnMouseMove(int btn, MouseDelegate func)
void ortho(double left, double right, double bottom, double top, double z_near, double z_far)
Sets the matrix to an orthographic projection.
thread_local int visualize
int SaveAsPNG(const char *fname, int w, int h, bool is_hidpi, bool with_alpha, std::function< void(int, void *)> get_row)
double InnerProd(const double a[], const double b[])
void LeftButtonUp(EventInfo *event)
void scale(double x, double y, double z)
Applies a scale transform to the matrix.
virtual gl3::SceneInfo GetSceneObjs()=0
void rotate(float angle, double x, double y, double z)
Applies a rotation transform to the matrix.
void buffer(GlDrawable *buf)
void setTouchPinchCallback(TouchDelegate cb)
bool isHighDpi() const
This property is set by createWindow().
void SetLineWidth(float width)
void KeyRightPressed(GLenum state)
void ResizeWindow(int w, int h)
void perspective(double fov, double aspect, double z_near, double z_far)
Sets the matrix to a perspective projection.
SdlWindow * GetAppWindow()
void MoveLeftRight(double dist)
void MoveResizeWindow(int x, int y, int w, int h)
int GetSmoothSetting()
Gets whether the smooth texture is being used (1 = true)
void SetLegacyGLOnly(bool status)
void UseSmooth()
Binds the smooth version of the current palette texture.
void KeyLeftPressed(GLenum state)
glm::mat4 TransposeRotMatrix()
void setOnExpose(Delegate func)
std::string priority_font
thread_local GLVisCommand * glvis_command
bool createWindow(const char *title, int x, int y, int w, int h, bool legacyGlOnly)
thread_local int constrained_spinning
void SetWindowTitle(const char *title)
void KeyDownPressed(GLenum state)
thread_local double sph_t
vector< string > fc_font_patterns
vector< FeedbackVertex > lines
void MoveForwardBackward(double dist)
void setLineWidthMS(float w)
void TurnLeftRight(double angle)
void setColorTexture(GLuint tex_h)
void setOnIdle(IdleDelegate func)
int InitVisualization(const char name[], int x, int y, int w, int h)
Initializes the visualization and some keys.
void RunVisualization()
Start the infinite visualization loop.
vector< GlDrawable * > needs_buffering
vector< FeedbackVertex > triangles
void SetMultisample(int m)
void setOnKeyDown(int key, Delegate func)
void MiddleButtonLoc(EventInfo *event)
const char * glvis_screenshot_ext
const float LINE_WIDTH_AA
thread_local bool use_idle
int InvertSurfaceVertical(SDL_Surface *surface)
void PrintCaptureBuffer(gl3::CaptureBuffer &cbuf)
thread_local VisualizationScene * locscene
void CallKeySequence(const char *seq)
thread_local bool disableSendExposeEvent
void UseDiscrete()
Binds the discrete version of the current palette texture.
void SetUseHiDPI(bool status)
void Rotate(double angle, double x, double y, double z)
void setOnMouseUp(int btn, MouseDelegate func)
void RightButtonDown(EventInfo *event)
void setWindowSize(int w, int h)