diff --git a/Graphics/drawContext.cpp b/Graphics/drawContext.cpp index a2723decf36bb713d85e1546bd4a2a94aa05ccc6..e545ce86f851434ba956d9a26b37d482fab0c66b 100644 --- a/Graphics/drawContext.cpp +++ b/Graphics/drawContext.cpp @@ -295,11 +295,11 @@ void drawContext::draw3d() initRenderModel(); if(!CTX::instance()->camera) initPosition(); - drawAxes(); drawGeom(); drawBackgroundImage(true); drawMesh(); drawPost(); + drawAxes(); drawGraph2d(true); } diff --git a/contrib/mobile/drawContext.cpp b/contrib/mobile/drawContext.cpp index 1eeffe7ad2e2a22ed254f0c6dd0bbc43fba623b0..b25e6004a3db743ae464bd467e33195180b81e49 100644 --- a/contrib/mobile/drawContext.cpp +++ b/contrib/mobile/drawContext.cpp @@ -42,6 +42,7 @@ drawContext::drawContext(float fontFactor, bool retina) setQuaternion(0., 0., 0., 1.); _fontFactor = fontFactor; _retina = retina; + _pixel_equiv_x = _pixel_equiv_y = 0.; } static void checkGlError(const char* op) @@ -195,6 +196,10 @@ void drawContext::OrthofFromGModel() vymin -= yborder; vymax += yborder; + // store what one pixel represents in world coordinates + _pixel_equiv_x = (vxmax - vxmin) / (double)_width; + _pixel_equiv_y = (vymax - vymin) / (double)_height; + // set up the near and far clipping planes so that the box is large enough to // manipulate the model and zoom, but not too big (otherwise the z-buffer // resolution e.g. with Mesa can become insufficient) @@ -236,9 +241,10 @@ void drawContext::initView(int w, int h) void drawArray(VertexArray *va, GLint type, bool useColorArray, bool useNormalArray) { if(!va) return; - glEnable(GL_BLEND); glEnable(GL_RESCALE_NORMAL); - glShadeModel(GL_SMOOTH); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glShadeModel(GL_SMOOTH); glVertexPointer(3, GL_FLOAT, 0, va->getVertexArray()); glEnableClientState(GL_VERTEX_ARRAY); if(useNormalArray){ @@ -253,8 +259,8 @@ void drawArray(VertexArray *va, GLint type, bool useColorArray, bool useNormalAr glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - glDisable(GL_RESCALE_NORMAL); - glDisable(GL_BLEND); + glDisable(GL_BLEND); + glDisable(GL_RESCALE_NORMAL); } void drawVector(double x, double y, double z, double dx, double dy, double dz) @@ -539,9 +545,11 @@ void drawContext::drawScale() break; } - drawString lbl(label, 20 * _fontFactor); - lbl.draw(xmin + width / 2, ymin + 2.8 * dh, 0., - _width/(_right-_left), _height/(_top-_bottom)); + if(strlen(label)){ + drawString lbl(label, 20 * _fontFactor); + lbl.draw(xmin + width / 2, ymin + 2.8 * dh, 0., + _width/(_right-_left), _height/(_top-_bottom)); + } drawString val(data->getName().c_str(), 15 * _fontFactor); for(int i = 0; i < 3; i++) { @@ -567,6 +575,289 @@ void drawContext::drawPost() } void drawContext::drawAxes() +{ + glLineWidth(1.); + bool geometryExists = false; + for(unsigned int i = 0; i < GModel::list.size(); i++){ + if(!GModel::list[i]->empty()){ + geometryExists = true; + break; + } + } + if(!CTX::instance()->axesAutoPosition){ + drawAxes(CTX::instance()->axes, CTX::instance()->axesTics, + CTX::instance()->axesFormat, CTX::instance()->axesLabel, + CTX::instance()->axesPosition, CTX::instance()->axesMikado, + CTX::instance()->axesForceValue ? CTX::instance()->axesValue : + CTX::instance()->axesPosition); + } + else if(geometryExists){ + double bb[6] = + {CTX::instance()->min[0], CTX::instance()->max[0], CTX::instance()->min[1], + CTX::instance()->max[1], CTX::instance()->min[2], CTX::instance()->max[2]}; + drawAxes(CTX::instance()->axes, CTX::instance()->axesTics, + CTX::instance()->axesFormat, CTX::instance()->axesLabel, + bb, CTX::instance()->axesMikado, CTX::instance()->axesForceValue ? + CTX::instance()->axesValue : bb); + } +} + +static void drawAxis(float xmin, float ymin, float zmin, + float xmax, float ymax, float zmax, + int ntics, int mikado) +{ + GLfloat axes[] = { + xmin, ymin, zmin, + xmax, ymax, zmax + }; + GLfloat colors[] = { + 0, 0, 0, 1, + 0, 0, 0, 1, + }; + glVertexPointer(3, GL_FLOAT, 0, axes); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_FLOAT, 0, colors); + glEnableClientState(GL_COLOR_ARRAY); + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); +} + +static void drawGridStipple(int n1, int n2, double p1[3], double p2[3], double p3[3]) +{ + double t1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]}; + double t2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]}; + double l1 = norme(t1); + double l2 = norme(t2); + + std::vector<GLfloat> v, c; + for(int i = 1; i < n1 - 1; i++){ + double d = (double)i / (double)(n1 - 1) * l1; + v.push_back(p1[0] + t1[0] * d); + v.push_back(p1[1] + t1[1] * d); + v.push_back(p1[2] + t1[2] * d); + v.push_back(p1[0] + t1[0] * d + t2[0] * l2); + v.push_back(p1[1] + t1[1] * d + t2[1] * l2); + v.push_back(p1[2] + t1[2] * d + t2[2] * l2); + } + for(int i = 1; i < n2 - 1; i++){ + double d = (double)i/(double)(n2 - 1) * l2; + v.push_back(p1[0] + t2[0] * d); + v.push_back(p1[1] + t2[1] * d); + v.push_back(p1[2] + t2[2] * d); + v.push_back(p1[0] + t2[0] * d + t1[0] * l1); + v.push_back(p1[1] + t2[1] * d + t1[1] * l1); + v.push_back(p1[2] + t2[2] * d + t1[2] * l1); + } + for(unsigned int i = 0; i < v.size(); i++){ + c.push_back(0); + c.push_back(0); + c.push_back(0); + c.push_back(0.2); + } + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glVertexPointer(3, GL_FLOAT, 0, &v[0]); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_FLOAT, 0, &c[0]); + glEnableClientState(GL_COLOR_ARRAY); + glDrawArrays(GL_LINES, 0, v.size() / 3); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisable(GL_BLEND); +} + +int drawContext::drawTics(drawContext *ctx, int comp, double n, std::string &format, + std::string &label, double p1[3], double p2[3], + double perp[3], int mikado, double pixelfact, + double value_p1[3], double value_p2[3]) +{ + // draws n tic marks (in direction perp) and labels along the line p1->p2 + + double t[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]}; + double l = norme(t); + double value_t[3] = {value_p2[0] - value_p1[0], value_p2[1] - value_p1[1], + value_p2[2] - value_p1[2]}; + double value_l = norme(value_t); + double w = 10 * pixelfact; // tic marks are 10 pixels long + double w2 = w * 4.5; // distance to labels + + // draw label at the end of the axis + if(label.size()){ + drawString lbl(label, 15 * _fontFactor); + lbl.draw(p2[0] + t[0] * w2, p2[1] + t[1] * w2, p2[2] + t[2] * w2, + _width/(_right-_left)*_scale[0], _height/(_top-_bottom)*_scale[0]); + } + + // return number of tics in special cases + if(n < 2.) return 0; + if(format.empty()) return n; + + // select perp direction automatically if it is not provided + double lp = norme(perp); + if(!lp){ + switch(comp){ + case 0: perp[1] = -1.; break; + case 1: perp[0] = -1.; break; + case 2: perp[0] = 1.; break; + default: break; + } + } + + char tmp[256]; + + // reduce number of vertical tics if not zoomed enough + double ww = _width/(_right-_left)*_scale[0]; + double hh = _height/(_top-_bottom)*_scale[0]; + if(hh < 10 && comp == 1){ + n = 2; + } + + // draw n tics + double step = l / (double)(n - 1); + double value_step = value_l / (double)(n - 1); + + for(int i = 0; i < n; i++){ + double d = i * step; + double p[3] = {p1[0] + t[0] * d, p1[1] + t[1] * d, p1[2] + t[2] * d}; + double q[3] = {p[0] + perp[0] * w, p[1] + perp[1] * w, p[2] + perp[2] * w}; + double r[3] = {p[0] + perp[0] * w2, p[1] + perp[1] * w2, p[2] + perp[2] * w2}; + + double value_d = i * value_step; + double value_p[3] = {value_p1[0] + value_t[0] * value_d, + value_p1[1] + value_t[1] * value_d, + value_p1[2] + value_t[2] * value_d}; + + GLfloat lines[] = { + (float)p[0], (float)p[1], (float)p[2], + (float)q[0], (float)q[1], (float)q[2] + }; + GLfloat colors[] = { + 0, 0, 0, 1, + 0, 0, 0, 1, + }; + glVertexPointer(3, GL_FLOAT, 0, lines); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_FLOAT, 0, colors); + glEnableClientState(GL_COLOR_ARRAY); + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + // draw tic labels + if(comp < 0) // display the length value (ruler-mode, starting at 0) + sprintf(tmp, format.c_str(), value_d); + else // display the coordinate value + sprintf(tmp, format.c_str(), value_p[comp]); + + if(strlen(tmp)){ + drawString lbl(tmp, 15 * _fontFactor); + lbl.draw(r[0], r[1], r[2], ww, hh); + } + } + return n; +} + +void drawContext::drawAxes(int mode, double tics[3], std::string format[3], + std::string label[3], double bb[6], int mikado, + double value_bb[6]) +{ + // mode 0: nothing + // 1: axes + // 2: box + // 3: full grid + // 4: open grid + // 5: ruler + + if((mode < 1) || (bb[0] == bb[1] && bb[2] == bb[3] && bb[4] == bb[5])) + return; + + double xmin = bb[0], xmax = bb[1]; + double ymin = bb[2], ymax = bb[3]; + double zmin = bb[4], zmax = bb[5]; + double orig[3] = {xmin, ymin, zmin}; + + double value_xmin = value_bb[0], value_xmax = value_bb[1]; + double value_ymin = value_bb[2], value_ymax = value_bb[3]; + double value_zmin = value_bb[4], value_zmax = value_bb[5]; + double value_orig[3] = {value_xmin, value_ymin, value_zmin}; + + double pixelfact = _pixel_equiv_x / _scale[0]; + + if(mode == 5){ // draw ruler from xyz_min to xyz_max + double end[3] = {xmax, ymax, zmax}; + double dir[3] = {xmax - xmin, ymax - ymin, zmax - zmin}; + double perp[3]; + if((fabs(dir[0]) >= fabs(dir[1]) && fabs(dir[0]) >= fabs(dir[2])) || + (fabs(dir[1]) >= fabs(dir[0]) && fabs(dir[1]) >= fabs(dir[2]))){ + perp[0] = dir[1]; perp[1] = -dir[0]; perp[2] = 0.; + } + else{ + perp[0] = 0.; perp[1] = dir[2]; perp[2] = -dir[1]; + } + double value_end[3] = {value_xmax, value_ymax, value_zmax}; + drawTics(this, -1, tics[0], format[0], label[0], orig, end, perp, mikado, + pixelfact, value_orig, value_end); + drawAxis(xmin, ymin, zmin, xmax, ymax, zmax, tics[0], mikado); + return; + } + double xx[3] = {xmax, ymin, zmin}; + double yy[3] = {xmin, ymax, zmin}; + double zz[3] = {xmin, ymin, zmax}; + double value_xx[3] = {value_xmax, value_ymin, value_zmin}; + double value_yy[3] = {value_xmin, value_ymax, value_zmin}; + double value_zz[3] = {value_xmin, value_ymin, value_zmax}; + double dxm[3] = {0., (ymin != ymax) ? -1. : 0., (zmin != zmax) ? -1. : 0.}; + double dym[3] = {(xmin != xmax) ? -1. : 0., 0., (zmin != zmax) ? -1. : 0.}; + double dzm[3] = {(xmin != xmax) ? -1. : 0., (ymin != ymax) ? -1. : 0., 0.}; + + int nx = (xmin != xmax) ? drawTics(this, 0, tics[0], format[0], label[0], orig, xx, dxm, + mikado, pixelfact, value_orig, value_xx) : 0; + int ny = (ymin != ymax) ? drawTics(this, 1, tics[1], format[1], label[1], orig, yy, dym, + mikado, pixelfact, value_orig, value_yy) : 0; + int nz = (zmin != zmax) ? drawTics(this, 2, tics[2], format[2], label[2], orig, zz, dzm, + mikado, pixelfact, value_orig, value_zz) : 0; + + drawAxis(xmin, ymin, zmin, xmax, ymin, zmin, nx, mikado); + drawAxis(xmin, ymin, zmin, xmin, ymax, zmin, ny, mikado); + drawAxis(xmin, ymin, zmin, xmin, ymin, zmax, nz, mikado); + + // open box + if(mode > 1){ + drawAxis(xmin, ymax, zmin, xmax, ymax, zmin, nx, mikado); + drawAxis(xmax, ymin, zmin, xmax, ymax, zmin, ny, mikado); + drawAxis(xmax, ymin, zmin, xmax, ymin, zmax, nz, mikado); + drawAxis(xmin, ymin, zmax, xmax, ymin, zmax, nx, mikado); + drawAxis(xmin, ymin, zmax, xmin, ymax, zmax, ny, mikado); + drawAxis(xmin, ymax, zmin, xmin, ymax, zmax, nz, mikado); + } + + // closed box + if(mode == 2 || mode == 3){ + drawAxis(xmin, ymax, zmax, xmax, ymax, zmax, nx, mikado); + drawAxis(xmax, ymin, zmax, xmax, ymax, zmax, ny, mikado); + drawAxis(xmax, ymax, zmin, xmax, ymax, zmax, nz, mikado); + } + + if(mode > 2){ + drawGridStipple(nx, ny, orig, xx, yy); + drawGridStipple(ny, nz, orig, yy, zz); + drawGridStipple(nx, nz, orig, xx, zz); + } + + if(mode == 3){ + double orig2[3] = {xmax, ymax, zmax}; + double xy[3] = {xmax, ymax, zmin}; + double yz[3] = {xmin, ymax, zmax}; + double xz[3] = {xmax, ymin, zmax}; + if(zmin != zmax) drawGridStipple(nx, ny, orig2, yz, xz); + if(xmin != xmax) drawGridStipple(ny, nz, orig2, xz, xy); + if(ymin != ymax) drawGridStipple(nx, nz, orig2, yz, xy); + } +} + +void drawContext::drawSmallAxes() { glLineWidth(1.); glPushMatrix(); @@ -593,12 +884,12 @@ void drawContext::drawAxes() x0 + zx, y0 + zy }; GLfloat colors[] = { - 0., 0, 0, 1., - 0., 0, 0, 1., - 0, 0, 0., 1., - 0, 0, 0., 1., - 0, 0., 0, 1., - 0, 0., 0, 1., + 0, 0, 0, 1, + 0, 0, 0, 1, + 0, 0, 0, 1, + 0, 0, 0, 1, + 0, 0, 0, 1, + 0, 0, 0, 1, }; glVertexPointer(2, GL_FLOAT, 0, axes); glEnableClientState(GL_VERTEX_ARRAY); @@ -807,9 +1098,10 @@ void drawContext::drawView() drawMesh(); checkGlError("Draw mesh"); drawGeom(); checkGlError("Draw geometry"); drawPost(); checkGlError("Draw post-pro"); + drawAxes(); checkGlError("Draw axes"); glDisable(GL_DEPTH_TEST); drawScale(); checkGlError("Draw scales"); - drawAxes(); checkGlError("Draw axes"); + drawSmallAxes(); checkGlError("Draw small axes"); drawText2d(); checkGlError("Draw text2d"); drawGraph2d(); checkGlError("Draw graph2d"); } diff --git a/contrib/mobile/drawContext.h b/contrib/mobile/drawContext.h index 527b72677563924c5fd7f881dc76df1868401542..f5b60dba45f493013b41d5af2e18625cfb82cb43 100644 --- a/contrib/mobile/drawContext.h +++ b/contrib/mobile/drawContext.h @@ -63,6 +63,7 @@ private: float _left, _right, _top, _bottom, _far; // value of "border" float _fontFactor; bool _retina; // retina display + double _pixel_equiv_x, _pixel_equiv_y; void OrthofFromGModel(void); void drawPView(PView *p); @@ -83,6 +84,14 @@ public: int fix2dCoordinates(double *x, double *y); void drawView(); void drawAxes(); + void drawAxes(int mode, double tics[3], std::string format[3], + std::string label[3], double bb[6], int mikado, + double value_bb[6]); + int drawTics(drawContext *ctx, int comp, double n, std::string &format, + std::string &label, double p1[3], double p2[3], + double perp[3], int mikado, double pixelfact, + double value_p1[3], double value_p2[3]); + void drawSmallAxes(); void drawGeom(); void drawMesh(); void drawPost();