diff --git a/Common/VertexArray.cpp b/Common/VertexArray.cpp index bf906f66c3bb583964bc88e722b0a2aa9230964f..79338e74b27544dfcabc2b5e597baf84cc930b13 100644 --- a/Common/VertexArray.cpp +++ b/Common/VertexArray.cpp @@ -1,4 +1,4 @@ -// $Id: VertexArray.cpp,v 1.6 2005-05-21 04:55:59 geuzaine Exp $ +// $Id: VertexArray.cpp,v 1.7 2005-10-09 15:58:40 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -81,6 +81,20 @@ void VertexArray::add(float x, float y, float z, unsigned int col) List_Add(colors, &a); } +void VertexArray::global_change_color(unsigned int col) +{ + unsigned char r = UNPACK_RED(col); + unsigned char g = UNPACK_GREEN(col); + unsigned char b = UNPACK_BLUE(col); + unsigned char a = UNPACK_ALPHA(col); + for(int i = 0; i < List_Nbr(colors); i+= 4){ + List_Write(colors, i, &r); + List_Write(colors, i, &g); + List_Write(colors, i, &b); + List_Write(colors, i, &a); + } +} + static double theeye[3]; int compareTriEye(const void *a, const void *b) diff --git a/Common/VertexArray.h b/Common/VertexArray.h index 2d31f67ed3b4643caecbd96382c9bffd70f8e310..a77b7193b50fe37324c7b4c7bd159b5d66820160 100644 --- a/Common/VertexArray.h +++ b/Common/VertexArray.h @@ -32,6 +32,7 @@ class VertexArray{ float n0, float n1, float n2, unsigned int col); void add(float x, float y, float z, unsigned int col); void sort(double eye[3]); + void global_change_color(unsigned int col); }; #endif diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp index c992ea5d7b0e24bcefaa49ed032ffe21607a4ba6..d7c948368c5bfe78ada9e6ea79c1c4e8f6027f78 100644 --- a/Fltk/GUI.cpp +++ b/Fltk/GUI.cpp @@ -1,4 +1,4 @@ -// $Id: GUI.cpp,v 1.457 2005-09-21 15:03:46 remacle Exp $ +// $Id: GUI.cpp,v 1.458 2005-10-09 15:58:40 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -324,7 +324,7 @@ Context_Item menu_mesh[] = { { "1D", (Fl_Callback *)mesh_1d_cb } , { "2D", (Fl_Callback *)mesh_2d_cb } , { "3D", (Fl_Callback *)mesh_3d_cb } , - { "remesh", (Fl_Callback *)mesh_remesh } , + { "Remesh", (Fl_Callback *)mesh_remesh } , { "First order", (Fl_Callback *)mesh_degree_cb, (void*)1 } , { "Second order", (Fl_Callback *)mesh_degree_cb, (void*)2 } , #if defined(HAVE_NETGEN) @@ -832,6 +832,10 @@ GUI::GUI(int argc, char **argv) onscreen_buffer[0][0] = '\0'; onscreen_buffer[1][0] = '\0'; + // initialize selection bits + selection = ENT_NONE; + try_selection = quit_selection = end_selection = undo_selection = 0; + // set X display if(strlen(CTX.display)) Fl::display(CTX.display); diff --git a/Fltk/Opengl.cpp b/Fltk/Opengl.cpp index d665cf5a2de2e99c07bdd7cdc653f0ebd37f6029..188da306ce3e52b00d99a4490a25ae9ca688af37 100644 --- a/Fltk/Opengl.cpp +++ b/Fltk/Opengl.cpp @@ -1,4 +1,4 @@ -// $Id: Opengl.cpp,v 1.52 2005-04-19 01:09:33 geuzaine Exp $ +// $Id: Opengl.cpp,v 1.53 2005-10-09 15:58:41 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -33,10 +33,6 @@ extern GUI *WID; extern Mesh M; extern Context_T CTX; -void Process_SelectionBuffer(int x, int y, int *n, GLuint * ii, GLuint * jj); -void Filter_SelectionBuffer(int n, GLuint * typ, GLuint * ient, - Vertex ** thev, Curve ** thec, Surface ** thes, - Mesh * m); // Draw specialization void InitOpengl(void) @@ -208,8 +204,8 @@ int check_type(int type, Vertex * v, Curve * c, Surface * s) char SelectEntity(int type, Vertex ** v, Curve ** c, Surface ** s) { - int hits; - GLuint ii[SELECTION_BUFFER_SIZE], jj[SELECTION_BUFFER_SIZE]; + int numhits; + hit hits[SELECTION_BUFFER_SIZE]; WID->g_opengl_window->take_focus(); // force keyboard focus in GL window @@ -227,12 +223,12 @@ char SelectEntity(int type, Vertex ** v, Curve ** c, Surface ** s) WID->wait(); if(WID->quit_selection) { WID->quit_selection = 0; - WID->selection = 0; + WID->selection = ENT_NONE; return 'q'; } if(WID->end_selection) { WID->end_selection = 0; - WID->selection = 0; + WID->selection = ENT_NONE; return 'e'; } if(WID->undo_selection) { @@ -241,15 +237,14 @@ char SelectEntity(int type, Vertex ** v, Curve ** c, Surface ** s) } if(WID->try_selection) { WID->try_selection = 0; - if(type == ENT_NONE){ // just report the mouse click + if(WID->selection == ENT_NONE){ // just report the mouse click return 'c'; } else{ - Process_SelectionBuffer(Fl::event_x(), Fl::event_y(), &hits, ii, jj); - Filter_SelectionBuffer(hits, ii, jj, v, c, s, &M); - if(check_type(type, *v, *c, *s)) { + Process_SelectionBuffer(Fl::event_x(), Fl::event_y(), &numhits, hits); + if(Filter_SelectionBuffer(WID->selection, numhits, hits, v, c, s, &M)){ HighlightEntity(*v, *c, *s, 1); - WID->selection = 0; + WID->selection = ENT_NONE; return 'l'; } } diff --git a/Fltk/Opengl_Window.cpp b/Fltk/Opengl_Window.cpp index ffd4d90e755602955d0f70951d2946eafd42a660..d1adadcc4dd00058b7aa40593187d454ae253e62 100644 --- a/Fltk/Opengl_Window.cpp +++ b/Fltk/Opengl_Window.cpp @@ -1,4 +1,4 @@ -// $Id: Opengl_Window.cpp,v 1.48 2005-04-05 05:56:48 geuzaine Exp $ +// $Id: Opengl_Window.cpp,v 1.49 2005-10-09 15:58:41 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -35,11 +35,7 @@ extern GUI *WID; extern Mesh M; extern Context_T CTX; -void Process_SelectionBuffer(int x, int y, int *n, GLuint * ii, GLuint * jj); -void Filter_SelectionBuffer(int n, GLuint * typ, GLuint * ient, - Vertex ** thev, Curve ** thec, Surface ** thes, - Mesh * m); -int check_type(int type, Vertex * v, Curve * c, Surface * s); +int check_type(int type, Vertex *v, Curve *c, Surface *s); void Opengl_Window::draw() { @@ -140,7 +136,8 @@ void myZoom(GLdouble X1, GLdouble X2, GLdouble Y1, GLdouble Y2, int Opengl_Window::handle(int event) { - GLuint ii[SELECTION_BUFFER_SIZE], jj[SELECTION_BUFFER_SIZE]; + int numhits; + hit hits[SELECTION_BUFFER_SIZE]; switch (event) { @@ -319,14 +316,14 @@ int Opengl_Window::handle(int event) } else { WID->make_opengl_current(); - Process_SelectionBuffer(xpos, ypos, &hits, ii, jj); + Process_SelectionBuffer(xpos, ypos, &numhits, hits); ov = v; oc = c; os = s; v = NULL; c = NULL; s = NULL; - Filter_SelectionBuffer(hits, ii, jj, &v, &c, &s, &M); + Filter_SelectionBuffer(WID->selection, numhits, hits, &v, &c, &s, &M); if(ov != v || oc != c || os != s) { if(check_type(WID->selection, v, c, s)) WID->g_window->cursor(FL_CURSOR_CROSS, FL_BLACK, FL_WHITE); diff --git a/Graphics/Draw.cpp b/Graphics/Draw.cpp index edc9329fff5d7a93d5ba16c5986356d3aaa64994..73628233e1991dfc5ba3253de0a5bacab9ec732b 100644 --- a/Graphics/Draw.cpp +++ b/Graphics/Draw.cpp @@ -1,4 +1,4 @@ -// $Id: Draw.cpp,v 1.77 2005-03-20 20:45:11 geuzaine Exp $ +// $Id: Draw.cpp,v 1.78 2005-10-09 15:58:41 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -285,7 +285,7 @@ void InitPosition(void) // Entity selection -void Process_SelectionBuffer(int x, int y, int *n, GLuint * ii, GLuint * jj) +void Process_SelectionBuffer(int x, int y, int *n, hit *hits) { GLuint selectBuf[SELECTION_BUFFER_SIZE]; @@ -295,63 +295,90 @@ void Process_SelectionBuffer(int x, int y, int *n, GLuint * ii, GLuint * jj) CTX.render_mode = GMSH_SELECT; glInitNames(); - glPushName(0); + glPushName(0); // init stack with 0 (=type=point). This will be + // overwritten with the actual entity type everytime + // an entity is drawn glPushMatrix(); Orthogonalize(x, y); Draw_Mesh(&M); glPopMatrix(); - GLint hits = glRenderMode(GL_RENDER); + GLint numhits = glRenderMode(GL_RENDER); CTX.render_mode = GMSH_RENDER; - if(hits < 0) - return; // Selection Buffer Overflow + if(numhits < 0){ + // selection buffer overflow + *n = 0; + return; + } GLint *ptr = (GLint *) selectBuf; - for(int i = 0; i < hits; i++) { - GLint names = *ptr; + for(int i = 0; i < numhits; i++) { + GLint names = *ptr; // number of names in the name stack (should + // always be 2 in Gmsh: the first is the type + // of the entity, the second the entity + // number) ptr++; + GLint mindepth = *ptr; ptr++; + GLint maxdepth = *ptr; ptr++; + hits[i].depth = (mindepth+maxdepth)/2; for(int j = 0; j < names; j++) { if(j == 0) - ii[i] = *ptr; + hits[i].type = *ptr; // type of entity (0, 1, 2 for point, line, surf) else if(j == 1) - jj[i] = *ptr; + hits[i].ient = *ptr; // num of entity ptr++; } } - *n = hits; + *n = numhits; } -void Filter_SelectionBuffer(int n, GLuint * typ, GLuint * ient, - Vertex ** thev, Curve ** thec, Surface ** thes, - Mesh * m) +int fcmp_hit_depth(const void *a, const void *b) { - GLuint typmin = 4; + return ((hit*)a)->depth - ((hit*)b)->depth; +} + +int Filter_SelectionBuffer(int type, int n, hit *hits, + Vertex **thev, Curve **thec, Surface **thes, Mesh *m) +{ + // If type == ENT_NONE, return the closest entity of "lowest + // dimension" (point < line < surface < volume). Otherwise, return + // the closest entity of type "type" + + unsigned int typmin = 4; for(int i = 0; i < n; i++) { - if(typ[i] < typmin) - typmin = typ[i]; + if(hits[i].type < typmin) + typmin = hits[i].type; } + // sort hits to get closest entities first + qsort(hits, n, sizeof(hit), fcmp_hit_depth); + for(int i = 0; i < n; i++) { - if(typ[i] == typmin) { - switch (typ[i]) { + if((type == ENT_NONE && hits[i].type == typmin) || + (type == ENT_POINT && hits[i].type == 0) || + (type == ENT_LINE && hits[i].type == 1) || + (type == ENT_SURFACE && hits[i].type == 2)){ + switch (hits[i].type) { case 0: - *thev = FindPoint(ient[i], m); - break; + *thev = FindPoint(hits[i].ient, m); + return 1; case 1: - *thec = FindCurve(ient[i], m); - break; + *thec = FindCurve(hits[i].ient, m); + return 1; case 2: - *thes = FindSurface(ient[i], m); - break; + *thes = FindSurface(hits[i].ient, m); + return 1; } } } + + return 0; } // Takes a cursor position in window coordinates and returns the line diff --git a/Graphics/Draw.h b/Graphics/Draw.h index b21a6f299225ce35f22fac0d5dfc2ca97765ad72..e0486f162ad6a7ed4e7a28eb996cfe455ab4fc61 100644 --- a/Graphics/Draw.h +++ b/Graphics/Draw.h @@ -38,6 +38,14 @@ void Orthogonalize(int x, int y); void ClearOpengl(void); void SetOpenglContext(void); +typedef struct{ + unsigned int type, ient, depth; +} hit; + +void Process_SelectionBuffer(int x, int y, int *n, hit *hits); +int Filter_SelectionBuffer(int type, int n, hit *hits, + Vertex **thev, Curve **thec, Surface **thes, Mesh *m); + void unproject(double x, double y, double p[3], double d[3]); void Viewport2World(double win[3], double xyz[3]); void World2Viewport(double xyz[3], double win[3]); diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp index 01762f9077a9fe5ddfb1abb25c3ad3ca1b5833f6..4e77769268905706b5e33aa7882444082a1d87ca 100644 --- a/Graphics/Geom.cpp +++ b/Graphics/Geom.cpp @@ -1,4 +1,4 @@ -// $Id: Geom.cpp,v 1.90 2005-09-07 14:36:45 remacle Exp $ +// $Id: Geom.cpp,v 1.91 2005-10-09 15:58:41 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -683,7 +683,7 @@ void HighlightEntity(Vertex * v, Curve * c, Surface * s, int permanent) char Message[256], temp[256]; if(permanent){ - // we want to draw incrementally (in-between to "Draw()" calls): + // we want to draw incrementally (in-between to "Draw()" calls!): // we need to make sure that the opengl context is set correctly SetOpenglContext(); } @@ -702,6 +702,8 @@ void HighlightEntity(Vertex * v, Curve * c, Surface * s, int permanent) if(permanent){ c->ipar[3] = 1; Draw_Curve(&c,NULL); + CTX.mesh.changed = 1; // a bit brutal, but the simplest solution + Draw_Mesh_Curve(&c,NULL); } else{ if(c->beg && c->end) @@ -714,6 +716,8 @@ void HighlightEntity(Vertex * v, Curve * c, Surface * s, int permanent) if(permanent){ s->ipar[4] = 1; Draw_Surface(&s,NULL); + CTX.mesh.changed = 1; // a bit brutal, but the simplest solution + Draw_Mesh_Surface(&s,NULL); } else{ int nbg = List_Nbr(s->Generatrices); @@ -774,23 +778,28 @@ void HighlightEntityNum(int v, int c, int s, int permanent) void ZeroHighlightPoint(void *a, void *b) { - Vertex *v; - v = *(Vertex **) a; + Vertex *v = *(Vertex **) a; v->Frozen = 0; } void ZeroHighlightCurve(void *a, void *b) { - Curve *c; - c = *(Curve **) a; + Curve *c = *(Curve **) a; c->ipar[3] = 0; + // the curve colors might have changed (and in complicated ways, + // e.g., if we color by partition, so we cannot use the + // global_change_color trick) + CTX.mesh.changed = 1; } void ZeroHighlightSurface(void *a, void *b) { - Surface *s; - s = *(Surface **) a; + Surface *s = *(Surface **) a; s->ipar[4] = 0; + // the surface colors might have changed (and in complicated ways, + // e.g., if we color by partition, so we cannot use the + // global_change_color trick) + CTX.mesh.changed = 1; } void ZeroHighlight(Mesh * m) diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp index 9d757042858d3a7a8ad514431c7c705b471723c5..f9b3035d1d75a0cc6a2f47fa921a9768526b707d 100644 --- a/Graphics/Mesh.cpp +++ b/Graphics/Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: Mesh.cpp,v 1.137 2005-08-09 23:39:42 geuzaine Exp $ +// $Id: Mesh.cpp,v 1.138 2005-10-09 15:58:41 geuzaine Exp $ // // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle // @@ -162,11 +162,11 @@ void Draw_Mesh(Mesh * M) glDisable((GLenum)(GL_CLIP_PLANE0 + i)); } - // if we're in selection mode, we're done - - if(CTX.render_mode == GMSH_SELECT) - return; - + // We used to be able to exit here when in SELECT mode. Since we + // also allow to select mesh entities now, we cannot anymore. Not + // sure what we should do eventually + //if(CTX.render_mode == GMSH_SELECT) return; + // draw the bounding box if we asked for it and we have a geometry // or a mesh, or if we are in fast redraw mode and there is no // geometry but there is a mesh @@ -396,6 +396,11 @@ void Draw_Mesh_Surface(void *a, void *b) if(!(s->Visible & VIS_MESH)) return; + if(CTX.render_mode == GMSH_SELECT) { + glLoadName(2); + glPushName(s->Num); + } + if (CTX.mesh.surfaces_num) { int numLabels = Tree_Nbr(s->Simplexes) + Tree_Nbr(s->SimplexesBase) + Tree_Nbr(s->Quadrangles); @@ -467,6 +472,10 @@ void Draw_Mesh_Surface(void *a, void *b) Tree_Action(s->Quadrangles, Draw_Mesh_Quadrangle); } + if(CTX.render_mode == GMSH_SELECT) { + glPopName(); + } + theSurface = NULL; } @@ -488,6 +497,11 @@ void Draw_Mesh_Curve(void *a, void *b) if(!(c->Visible & VIS_MESH)) return; + if(CTX.render_mode == GMSH_SELECT) { + glLoadName(1); + glPushName(c->Num); + } + if (CTX.mesh.lines_num) { int numLabels = Tree_Nbr(c->Simplexes) + Tree_Nbr(c->SimplexesBase); numLabelsDisplayed = 0; @@ -526,6 +540,10 @@ void Draw_Mesh_Curve(void *a, void *b) Tree_Action(c->SimplexesBase, Draw_Mesh_Line); } + if(CTX.render_mode == GMSH_SELECT) { + glPopName(); + } + theCurve = NULL; } @@ -626,7 +644,9 @@ void Draw_Mesh_Line(void *a, void *b) } unsigned int col; - if(theColor.type) + if(theCurve && theCurve->ipar[3]) + col = CTX.color.geom.line_sel; + else if(theColor.type) col = theColor.mesh; else if(CTX.mesh.color_carousel == 1) col = CTX.color.mesh.carousel[abs(s->iEnt % 20)]; @@ -902,7 +922,9 @@ void Draw_Mesh_Triangle(void *a, void *b) return; unsigned int col; - if(theColor.type) + if(theSurface && theSurface->ipar[4]) + col = CTX.color.geom.surface_sel; + else if(theColor.type) col = theColor.mesh; else if(CTX.mesh.color_carousel == 1) col = CTX.color.mesh.carousel[abs(s->iEnt % 20)]; @@ -1080,7 +1102,9 @@ void Draw_Mesh_Quadrangle(void *a, void *b) return; unsigned int col; - if(theColor.type) + if(theSurface && theSurface->ipar[4]) + col = CTX.color.geom.surface_sel; + else if(theColor.type) col = theColor.mesh; else if(CTX.mesh.color_carousel == 1) col = CTX.color.mesh.carousel[abs(q->iEnt % 20)]; diff --git a/TODO b/TODO index e0cc1601d4c23c1a370af4bf7d75cf7bdcbed7c6..5836d23c43408033310ecc1f1ec4851bbdf10fab 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,17 @@ -$Id: TODO,v 1.100 2005-09-07 16:38:19 geuzaine Exp $ +$Id: TODO,v 1.101 2005-10-09 15:58:40 geuzaine Exp $ + +******************************************************************** + +Add a way to select multiple entities using a lasso + add a way to +remove entities from a selection by clicking on them + +******************************************************************** + +We should fine-grain CTX.mesh.changed so that we can keep track of +changes surface by surface, volume by volume, etc. This would speed up +mesh selection quite a bit on large models (since we would only have +to regenerate the vertex array for the surface/volume that has +changed, and not everything) ******************************************************************** diff --git a/doc/VERSIONS b/doc/VERSIONS index a2ff80d1e18d4d25e617287fbc41eca78b82625f..4ebc1a96d60a724d00daa34127d81d24bc4ef7cf 100644 --- a/doc/VERSIONS +++ b/doc/VERSIONS @@ -1,4 +1,4 @@ -$Id: VERSIONS,v 1.341 2005-09-02 15:56:24 geuzaine Exp $ +$Id: VERSIONS,v 1.342 2005-10-09 15:58:41 geuzaine Exp $ New since 1.60: added support for second order (curved) elements in post-processor; new version (1.4) of post-processing file formats; new @@ -14,8 +14,8 @@ Windows/Cygwin; removed Discrete Line and Discrete Surface commands in .msh format); fixed coloring by mesh partition; new "mesh statistics" export format; new full-quad recombine option; new Plugin(ModulusPhase); experimental Tetgen integration; hexas and -prisms are now always saved with positive volume; various small bug -fixes and improvements. +prisms are now always saved with positive volume; improved interactive +entity selection; various small bug fixes and improvements. New in 1.60: added support for discrete curves; new Window menu on Mac OS X; generalized all octree-based plugins (CutGrid, StreamLines,