diff --git a/Common/Context.h b/Common/Context.h index 485711d2f6ff1a6c7433b5b8b5c4ba1cd52a1e30..570e7e6daa2809e6e412ef71fea5bd3b04fa022f 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -180,7 +180,8 @@ class CTX { int bgGradient; // draw background image? std::string bgImageFileName; - double bgImagePosition[2]; + double bgImagePosition[2], bgImageSize[2]; + int bgImage3d; // fltk font size (and delta for palette windows) int fontSize, deltaFontSize; // font name, FLTK enum and size for opengl graphics diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 00ce9f219bf192245f489f6f72e871cca553afdf..749e527c27c868946fe76dfdcbd05ca0358bb605 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -329,12 +329,19 @@ StringXNumber GeneralOptions_Number[] = { { F|O, "BackgroundGradient" , opt_general_background_gradient , 1. , "Draw background gradient (0=none, 1=vertical, 2=horizontal, 3=radial)" }, - { F|O, "BackgroundImagePositionX" , opt_general_background_image_position0 , 1.e5 , - "X position (in pixels) of background image (< 0: measure from right edge; " + { F|O, "BackgroundImage3D" , opt_general_background_image_3d , 0 , + "Create background image in the 3D model (units = model units) or as " + "2D background (units = pixels)" }, + { F|O, "BackgroundImagePositionX" , opt_general_background_image_position0 , 0 , + "X position of background image (for 2D background: < 0: measure from right edge; " ">= 1e5: centered)" }, - { F|O, "BackgroundImagePositionY" , opt_general_background_image_position1 , 1.e5 , - "Y position (in pixels) of background image (< 0: measure from bottom edge; " + { F|O, "BackgroundImagePositionY" , opt_general_background_image_position1 , 0 , + "Y position of background image (for 2D background: < 0: measure from bottom edge; " ">= 1e5: centered)" }, + { F|O, "BackgroundImageWidth" , opt_general_background_image_size0 , -1. , + "Width of background image (0: actual width; -1: fullscreen)" }, + { F|O, "BackgroundImageHeight" , opt_general_background_image_size1 , -1 , + "Height of background image (0: actual width; -1: fullscreen)" }, { F|O, "Camera" , opt_general_camera_mode, 0. , "Enable camera view mode" }, diff --git a/Common/Options.cpp b/Common/Options.cpp index 3d76466f8fad88c1c47a352a57734af759f73d5b..f85aa81b6efcb940e4b7cae0f670dc673ac5a577 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -3224,6 +3224,27 @@ double opt_general_background_image_position1(OPT_ARGS_NUM) return CTX::instance()->bgImagePosition[1]; } +double opt_general_background_image_size0(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->bgImageSize[0] = val; + return CTX::instance()->bgImageSize[0]; +} + +double opt_general_background_image_size1(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->bgImageSize[1] = val; + return CTX::instance()->bgImageSize[1]; +} + +double opt_general_background_image_3d(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->bgImage3d = (int)val; + return CTX::instance()->bgImage3d; +} + double opt_general_trackball(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index 6bbb799f9fabaffdaa27706cbc340602ca151452..0dc1d9fbfd2e8d54ec267174d24d1ce191e909a1 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -187,6 +187,9 @@ double opt_general_color_scheme(OPT_ARGS_NUM); double opt_general_background_gradient(OPT_ARGS_NUM); double opt_general_background_image_position0(OPT_ARGS_NUM); double opt_general_background_image_position1(OPT_ARGS_NUM); +double opt_general_background_image_size0(OPT_ARGS_NUM); +double opt_general_background_image_size1(OPT_ARGS_NUM); +double opt_general_background_image_3d(OPT_ARGS_NUM); double opt_general_verbosity(OPT_ARGS_NUM); double opt_general_progress_meter_step(OPT_ARGS_NUM); double opt_general_nopopup(OPT_ARGS_NUM); diff --git a/Common/gmshPopplerWrapper.cpp b/Common/gmshPopplerWrapper.cpp index 6d730e125053f80520c476e4ab56d5b740a6b5ab..c681920aee60b10b32707e16a42c530a929442d4 100644 --- a/Common/gmshPopplerWrapper.cpp +++ b/Common/gmshPopplerWrapper.cpp @@ -45,11 +45,11 @@ GLuint gmshPopplerWrapper::getTextureForPage(double xres, { int iPage = _current_page; std::map<int,GLuint>::iterator it = _pages2textures.find(iPage); - if (it != _pages2textures.end())return it->second; + if (it != _pages2textures.end()) return it->second; if (!_current_doc) return 0; - poppler::page *_current_page = _current_doc->create_page (iPage); + poppler::page *_current_page = _current_doc->create_page(iPage); poppler::page_renderer pr; - poppler::image im = pr.render_page (_current_page,xres,yres,-1,-1,-1); + poppler::image im = pr.render_page(_current_page, xres, yres, -1, -1, -1); _w = im.width(); _h = im.height(); // im.save("page.png","png"); @@ -59,9 +59,8 @@ GLuint gmshPopplerWrapper::getTextureForPage(double xres, _pages2textures[iPage] = texture; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(),im.height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE,im.const_data()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(), im.height(), 0, + GL_RGBA, GL_UNSIGNED_BYTE, im.const_data()); return texture; } #endif diff --git a/Common/gmshPopplerWrapper.h b/Common/gmshPopplerWrapper.h index 0bb46dcb32ad36ebaf2235416d4f786a0fcac80d..288562094d6b964f63e06f56816425d76babae3a 100644 --- a/Common/gmshPopplerWrapper.h +++ b/Common/gmshPopplerWrapper.h @@ -27,7 +27,7 @@ private: static int _current_page; static poppler::document *_current_doc; static gmshPopplerWrapper *_instance; - static int _w,_h; + static int _w, _h; #if defined(HAVE_OPENGL) static std::map<int,GLuint> _pages2textures; // map pages to textures #endif diff --git a/Graphics/drawContext.cpp b/Graphics/drawContext.cpp index 13db4f7f0c8e7eef778dbbbba28a13c5185301e7..4bd617c4735b9332cc41576649ea48886c146d67 100644 --- a/Graphics/drawContext.cpp +++ b/Graphics/drawContext.cpp @@ -52,7 +52,7 @@ drawContext::drawContext(drawTransform *transform) vxmin = vymin = vxmax = vymax = 0.; pixel_equiv_x = pixel_equiv_y = 0.; - _bgImageSize[0] = _bgImageSize[1] = 0; + _bgImageTexture = _bgImageW = _bgImageH = 0; _quadric = 0; // cannot create it here: needs valid opengl context _displayLists = 0; @@ -283,6 +283,7 @@ void drawContext::draw3d() if(!CTX::instance()->camera) initPosition(); drawAxes(); drawGeom(); + drawBackgroundImage(true); drawMesh(); drawPost(); } @@ -355,83 +356,107 @@ void drawContext::drawBackgroundGradient() } } -void drawContext::drawBackgroundImage() +void drawContext::drawBackgroundImage(bool threeD) { - if(CTX::instance()->bgImageFileName.empty()) return; + if(CTX::instance()->bgImageFileName.empty() || + (CTX::instance()->bgImage3d && !threeD) || + (!CTX::instance()->bgImage3d && threeD)) return; - std::string name = CTX::instance()->bgImageFileName; + std::string name = FixRelativePath(GModel::current()->getFileName(), + CTX::instance()->bgImageFileName); std::string ext = SplitFileName(CTX::instance()->bgImageFileName)[2]; + double x = CTX::instance()->bgImagePosition[0]; + double y = CTX::instance()->bgImagePosition[1]; + double w = CTX::instance()->bgImageSize[0]; + double h = CTX::instance()->bgImageSize[1]; + if(ext == ".pdf" || ext == ".PDF"){ #if defined(HAVE_POPPLER) if(!gmshPopplerWrapper::instance()->hasFile()){ if(!gmshPopplerWrapper::instance()->loadFromFile(name)){ Msg::Error("Could not load PDF file '%s'", name.c_str()); CTX::instance()->bgImageFileName.clear(); + return; } } - GLuint texture = gmshPopplerWrapper::getTextureForPage(800,600); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture); - glBegin(GL_QUADS); - glColor4ubv((GLubyte *) & CTX::instance()->color.bg); - int dw = viewport[2] - viewport[0]; - int dh = viewport[3] - viewport[1]; - int dw_im = gmshPopplerWrapper::width(); - int dh_im = gmshPopplerWrapper::height(); - // conserve aspect ratio : dw / dh = dw_im / dh_im - // dw = dh * dw_im / dh_im; - dh = dw * dh_im / dw_im; - glTexCoord2f(1.0f, 1.0f); glVertex2i(viewport[2], viewport[3]-dh); - glTexCoord2f(1.0f, 0.0f); glVertex2i(viewport[2], viewport[3]); - glTexCoord2f(0.0f, 0.0f); glVertex2i(viewport[2]-dw, viewport[3]); - glTexCoord2f(0.0f, 1.0f); glVertex2i(viewport[2]-dw, viewport[3]-dh); - glEnd(); + _bgImageTexture = gmshPopplerWrapper::getTextureForPage(800, 600); + _bgImageW = gmshPopplerWrapper::width(); + _bgImageH = gmshPopplerWrapper::height(); #endif } else{ #if defined(HAVE_FLTK) - if(_bgImage.empty()){ + if(!_bgImageTexture){ Fl_RGB_Image *img = 0; if(ext == ".jpg" || ext == ".JPG" || ext == ".jpeg" || ext == ".JPEG") img = new Fl_JPEG_Image(name.c_str()); else if(ext == ".png" || ext == ".PNG") img = new Fl_PNG_Image(name.c_str()); - if(img && img->d() >= 3){ - const unsigned char *data = img->array; - for(int j = img->h() - 1; j >= 0; j--) { - for(int i = 0; i < img->w(); i++) { - int idx = j * img->w() * img->d() + i * img->d(); - _bgImage.push_back((GLfloat)data[idx] / 255.F); - _bgImage.push_back((GLfloat)data[idx + 1] / 255.F); - _bgImage.push_back((GLfloat)data[idx + 2] / 255.F); - } - } - _bgImageSize[0] = img->w(); - _bgImageSize[1] = img->h(); + if(img){ + glGenTextures(1, &_bgImageTexture); + glBindTexture(GL_TEXTURE_2D, _bgImageTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->w(), img->h(), 0, + GL_RGB, GL_UNSIGNED_BYTE, img->array); + _bgImageW = img->w(); + _bgImageH = img->h(); + delete img; } - if(img) delete img; - if(!_bgImageSize[0] || !_bgImageSize[1]){ + else{ Msg::Error("Could not load background image '%s'", name.c_str()); CTX::instance()->bgImageFileName.clear(); + return; } } - double x = CTX::instance()->bgImagePosition[0]; - double y = CTX::instance()->bgImagePosition[1]; - int c = fix2dCoordinates(&x, &y); - if(c & 1) x -= _bgImageSize[0] / 2.; - if(c & 2) y -= _bgImageSize[1] / 2.; +#endif + } + + if(!_bgImageTexture) return; + + if(w < 0 && h == 0){ + w = viewport[2] - viewport[0]; + h = w * _bgImageH / _bgImageW; + } + else if(h < 0 && w == 0){ + h = viewport[3] - viewport[1]; + w = h * _bgImageW / _bgImageH; + } + else if(h < 0 && w < 0){ + w = viewport[2] - viewport[0]; + h = viewport[3] - viewport[1]; + } + else if(h == 0 && w == 0){ + w = _bgImageW; + h = _bgImageH; + } + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, _bgImageTexture); + glBegin(GL_QUADS); + glColor4ubv((GLubyte *) & CTX::instance()->color.bg); + if(threeD){ + if(w <= 0) w = _bgImageW; + if(h <= 0) h = _bgImageH; + glTexCoord2f(1.0f, 1.0f); glVertex2d(x+w, y); + glTexCoord2f(1.0f, 0.0f); glVertex2d(x+w, y+h); + glTexCoord2f(0.0f, 0.0f); glVertex2d(x, y+h); + glTexCoord2f(0.0f, 1.0f); glVertex2d(x, y); + } + else{ + int c = fix2dCoordinates(&x, &y); // y=0 now means top + if(c & 1) x -= _bgImageW / 2.; + if(c & 2) y += _bgImageH / 2.; if(x < viewport[0]) x = viewport[0]; if(y < viewport[1]) y = viewport[1]; - glRasterPos2d(x, y); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glDrawPixels(_bgImageSize[0], _bgImageSize[1], GL_RGB, GL_FLOAT, - (void*)&_bgImage[0]); - gl2psDrawPixels(_bgImageSize[0], _bgImageSize[1], 0, 0, GL_RGB, GL_FLOAT, - (void*)&_bgImage[0]); + glTexCoord2f(1.0f, 1.0f); glVertex2d(x+w, y-h); + glTexCoord2f(1.0f, 0.0f); glVertex2d(x+w, y); + glTexCoord2f(0.0f, 0.0f); glVertex2d(x, y); + glTexCoord2f(0.0f, 1.0f); glVertex2d(x, y-h); } -#endif + glEnd(); + glDisable(GL_TEXTURE_2D); } void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick) @@ -539,7 +564,7 @@ void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick) // hack for GL2PS (to make sure that the image is in front of the // gradient) glTranslated(0., 0., 0.01 * clip_far); - drawBackgroundImage(); + drawBackgroundImage(false); glPopMatrix(); glEnable(GL_DEPTH_TEST); } diff --git a/Graphics/drawContext.h b/Graphics/drawContext.h index 5fd64428ffebafaed562e4fc07951084adc1b3c7..ffcd9d57fa108394bdc6310eaef04c01cf45e2f6 100644 --- a/Graphics/drawContext.h +++ b/Graphics/drawContext.h @@ -110,8 +110,7 @@ class drawContext { GLuint _displayLists; std::set<GModel*> _hiddenModels; std::set<PView*> _hiddenViews; - std::vector<GLfloat> _bgImage; - int _bgImageSize[2]; + GLuint _bgImageTexture, _bgImageW, _bgImageH; public: Camera camera; double r[3]; // current Euler angles (in degrees!) @@ -201,7 +200,7 @@ class drawContext { void drawMesh(); void drawPost(); void drawBackgroundGradient(); - void drawBackgroundImage(); + void drawBackgroundImage(bool moving); void drawText2d(); void drawGraph2d(); void drawAxis(double xmin, double ymin, double zmin,