From b61da056ae01ac1e408e0dfc765feb344409b0cb Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Thu, 24 Aug 2006 01:14:59 +0000 Subject: [PATCH] extended selection buffer to prepare for mesh element picking and the new mesh editing interface --- Common/Makefile | 6 ++--- Common/Options.cpp | 25 ++++++++++------- Common/VertexArray.cpp | 14 +++++++--- Common/VertexArray.h | 21 ++++++++++----- Fltk/Callbacks.cpp | 7 ++++- Fltk/GUI.cpp | 13 ++++----- Geo/MRep.h | 56 +++++++++++++++++++++++++++------------ Graphics/Makefile | 6 +++-- Graphics/Mesh.cpp | 28 ++++++++++++++++---- Graphics/SelectBuffer.cpp | 51 +++++++++++++++++++++++++++-------- 10 files changed, 159 insertions(+), 68 deletions(-) diff --git a/Common/Makefile b/Common/Makefile index 0e8dad21b2..4e5cc2ae95 100644 --- a/Common/Makefile +++ b/Common/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.105 2006-08-17 21:28:34 geuzaine Exp $ +# $Id: Makefile,v 1.106 2006-08-24 01:14:55 geuzaine Exp $ # # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle # @@ -157,9 +157,7 @@ Visibility.o: Visibility.cpp Visibility.h GmshDefines.h ../Geo/GVertex.h \ # 1 "/Users/geuzaine/.gmsh/Common//" Trackball.o: Trackball.cpp Trackball.h # 1 "/Users/geuzaine/.gmsh/Common//" -VertexArray.o: VertexArray.cpp Gmsh.h Message.h ../DataStr/Malloc.h \ - ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \ - ../DataStr/List.h ../DataStr/Tree.h VertexArray.h Context.h \ +VertexArray.o: VertexArray.cpp VertexArray.h Context.h ../DataStr/List.h \ ../Numeric/Numeric.h # 1 "/Users/geuzaine/.gmsh/Common//" SmoothNormals.o: SmoothNormals.cpp Gmsh.h Message.h ../DataStr/Malloc.h \ diff --git a/Common/Options.cpp b/Common/Options.cpp index d2541538e3..dbb25cc8f7 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -1,4 +1,4 @@ -// $Id: Options.cpp,v 1.303 2006-08-23 19:53:37 geuzaine Exp $ +// $Id: Options.cpp,v 1.304 2006-08-24 01:14:55 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -2773,17 +2773,24 @@ double opt_general_mouse_selection(OPT_ARGS_NUM) CTX.enable_mouse_selection = (int)val; #if defined(HAVE_FLTK) if(WID && (action & GMSH_GUI)) { - if(CTX.enable_mouse_selection == 0){ - if(!CTX.batch) Msg(STATUS2N, "Mouse selection OFF"); - WID->g_status_butt[9]->color(FL_RED); - } - else if(CTX.enable_mouse_selection == 1){ + switch(CTX.enable_mouse_selection){ + case 1: if(!CTX.batch) Msg(STATUS2N, "Mouse selection ON"); WID->g_status_butt[9]->color(FL_BACKGROUND_COLOR); - } - else{ - if(!CTX.batch) Msg(STATUS2N, "Full mouse selection ON"); + break; + case 2: + if(!CTX.batch) Msg(STATUS2N, "Mouse selection ON (with mesh hover)"); WID->g_status_butt[9]->color(FL_GREEN); + break; + case 3: + if(!CTX.batch) Msg(STATUS2N, "Mouse selection ON (with element hover)"); + WID->g_status_butt[9]->color(FL_YELLOW); + break; + case 0: + default: + if(!CTX.batch) Msg(STATUS2N, "Mouse selection OFF"); + WID->g_status_butt[9]->color(FL_RED); + break; } WID->g_status_butt[9]->redraw(); } diff --git a/Common/VertexArray.cpp b/Common/VertexArray.cpp index 8b874065cf..733fd3ca85 100644 --- a/Common/VertexArray.cpp +++ b/Common/VertexArray.cpp @@ -1,4 +1,4 @@ -// $Id: VertexArray.cpp,v 1.14 2006-08-22 15:34:34 geuzaine Exp $ +// $Id: VertexArray.cpp,v 1.15 2006-08-24 01:14:55 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -35,8 +35,8 @@ VertexArray::VertexArray(int numNodesPerElement, int numElements) _colors.reserve(nb *4); } -void VertexArray::add(float x, float y, float z, - float n0, float n1, float n2, unsigned int col) +void VertexArray::add(float x, float y, float z, float n0, float n1, float n2, + unsigned int col, MElement *ele) { _vertices.push_back(x); _vertices.push_back(y); @@ -59,9 +59,12 @@ void VertexArray::add(float x, float y, float z, _colors.push_back(g); _colors.push_back(b); _colors.push_back(a); + + if(ele && CTX.enable_mouse_selection > 2) + _elements.push_back(ele); } -void VertexArray::add(float x, float y, float z, unsigned int col) +void VertexArray::add(float x, float y, float z, unsigned int col, MElement *ele) { _vertices.push_back(x); _vertices.push_back(y); @@ -75,6 +78,9 @@ void VertexArray::add(float x, float y, float z, unsigned int col) _colors.push_back(g); _colors.push_back(b); _colors.push_back(a); + + if(ele && CTX.enable_mouse_selection > 2) + _elements.push_back(ele); } diff --git a/Common/VertexArray.h b/Common/VertexArray.h index 01f5034889..61af100955 100644 --- a/Common/VertexArray.h +++ b/Common/VertexArray.h @@ -20,7 +20,9 @@ // // Please report all bugs and problems to <gmsh@geuz.org>. -#include "vector" +#include <vector> + +class MElement; class VertexArray{ public: @@ -30,6 +32,7 @@ class VertexArray{ std::vector<float> _vertices; std::vector<char> _normals; std::vector<unsigned char> _colors; + std::vector<MElement*> _elements; public: VertexArray(int numNodesPerElement, int numElements); ~VertexArray(){} @@ -37,16 +40,20 @@ class VertexArray{ int getNumVertices() { return _vertices.size() / 3; } // returns the type of the array int getType() { return _type; } + // returns the number of element pointers + int getNumElementPointers() { return _elements.size(); } // returns a pointer to the raw vertex array - float *getVertexArray(){ return &_vertices[0]; } + float *getVertexArray(int i=0){ return &_vertices[i]; } // returns a pointer to the raw normal array - char *getNormalArray(){ return &_normals[0]; } + char *getNormalArray(int i=0){ return &_normals[i]; } // returns a pointer to the raw color array - unsigned char *getColorArray(){ return &_colors[0]; } + unsigned char *getColorArray(int i=0){ return &_colors[i]; } + // returns a pointer to the raw element array + MElement **getElementPointerArray(int i=0){ return &_elements[i]; } // adds a vertex in the arrays - void add(float x, float y, float z, - float n0, float n1, float n2, unsigned int col); - void add(float x, float y, float z, unsigned int col); + void add(float x, float y, float z, float n0, float n1, float n2, + unsigned int col, MElement *ele=0); + void add(float x, float y, float z, unsigned int col, MElement *ele=0); // sorts the elements back to front wrt the eye position void sort(double eye[3]); }; diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index 15d1a72f56..795fd75e5e 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -1,4 +1,4 @@ -// $Id: Callbacks.cpp,v 1.448 2006-08-23 19:53:37 geuzaine Exp $ +// $Id: Callbacks.cpp,v 1.449 2006-08-24 01:14:56 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -471,6 +471,11 @@ void status_xyz1p_cb(CALLBACK_ARGS) // full mouse hover and select for geometry and mesh opt_general_mouse_selection(0, GMSH_SET | GMSH_GUI, 2); } + else if(Fl::event_state(FL_META)){ + // full hover and select, even for mesh elements + opt_general_mouse_selection(0, GMSH_SET | GMSH_GUI, 3); + CTX.mesh.changed = ENT_ALL; // need to regenerate the mesh reps + } else if(CTX.enable_mouse_selection){ // mouse does nothing opt_general_mouse_selection(0, GMSH_SET | GMSH_GUI, 0); diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp index c7bd326894..8544a36d7a 100644 --- a/Fltk/GUI.cpp +++ b/Fltk/GUI.cpp @@ -1,4 +1,4 @@ -// $Id: GUI.cpp,v 1.535 2006-08-23 19:53:37 geuzaine Exp $ +// $Id: GUI.cpp,v 1.536 2006-08-24 01:14:56 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -510,12 +510,6 @@ int GUI::global_shortcuts(int event) if(event != FL_SHORTCUT) return 0; - if(Fl::test_shortcut(FL_CTRL + FL_Escape) || - Fl::test_shortcut(FL_META + FL_Escape) || - Fl::test_shortcut(FL_ALT + FL_Escape)) { - return 1; - } - if(Fl::test_shortcut('0')) { geometry_reload_cb(0, 0); mod_geometry_cb(0, 0); @@ -579,7 +573,10 @@ int GUI::global_shortcuts(int event) return 0; // trick: do as if we didn't use it } else if(Fl::test_shortcut(FL_Escape) || - Fl::test_shortcut(FL_SHIFT + FL_Escape)) { + Fl::test_shortcut(FL_META + FL_Escape) || + Fl::test_shortcut(FL_SHIFT + FL_Escape) || + Fl::test_shortcut(FL_CTRL + FL_Escape) || + Fl::test_shortcut(FL_ALT + FL_Escape)) { if(g_opengl_window->LassoMode){ g_opengl_window->LassoMode = false; redraw_opengl(); diff --git a/Geo/MRep.h b/Geo/MRep.h index 625c8ed7c4..24bfcef29a 100644 --- a/Geo/MRep.h +++ b/Geo/MRep.h @@ -35,8 +35,7 @@ class MRep { protected: - // container for the edge representation (this is 2x faster than - // std::set<MEdge, MEdgeLessThan>) + // container for the edge representation std::map<std::pair<MVertex*, MVertex*>, MElement*> edges; // generates the edges from a bunch of elements @@ -52,29 +51,24 @@ class MRep { } } + public: + // the vertex arrays + VertexArray *va_lines, *va_triangles, *va_quads; + + // a flag telling if all the elements in the entity are visible + bool allElementsVisible; + public: MRep() : va_lines(0), va_triangles(0), va_quads(0), allElementsVisible(true) {} virtual ~MRep(){ destroy(); } - // destroy everything + // destroys everything void destroy(){ resetArrays(); edges.clear(); allElementsVisible = true; } - // generates the edge representation - virtual void generateEdgeRep() = 0; - - // acces the edge representation - typedef std::map<std::pair<MVertex*, MVertex*>, MElement*>::const_iterator eriter; - eriter firstEdgeRep() { return edges.begin(); } - eriter lastEdgeRep() { return edges.end(); } - int getNumEdgeRep() { return edges.size(); } - - // the vertex arrays - VertexArray *va_lines, *va_triangles, *va_quads; - // destroys all the vertex arrays void resetArrays(){ if(va_lines) delete va_lines; @@ -85,8 +79,36 @@ class MRep { va_quads = 0; } - // a flag telling if all the elements in the entity are visible - bool allElementsVisible; + // generates the edge representation + virtual void generateEdgeRep() = 0; + + // accesses the edge representation + typedef std::map<std::pair<MVertex*, MVertex*>, MElement*>::const_iterator eriter; + eriter firstEdgeRep() { return edges.begin(); } + eriter lastEdgeRep() { return edges.end(); } + int getNumEdgeRep() { return edges.size(); } + + // returns the element at a given position in a vertex array + // (element pointers are not always stored: returning 0 is not an + // error) + MElement *getElement(int va_type, int index) + { + switch(va_type){ + case 2: + if(va_lines && index < va_lines->getNumElementPointers()) + return *va_lines->getElementPointerArray(index); + break; + case 3: + if(va_triangles && index < va_triangles->getNumElementPointers()) + return *va_triangles->getElementPointerArray(index); + break; + case 4: + if(va_quads && index < va_quads->getNumElementPointers()) + return *va_quads->getElementPointerArray(index); + break; + } + return 0; + } }; class MRepEdge : public MRep { diff --git a/Graphics/Makefile b/Graphics/Makefile index ab1eea8d35..6cc19844cd 100644 --- a/Graphics/Makefile +++ b/Graphics/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.99 2006-08-20 14:12:40 geuzaine Exp $ +# $Id: Makefile,v 1.100 2006-08-24 01:14:58 geuzaine Exp $ # # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle # @@ -164,7 +164,9 @@ SelectBuffer.o: SelectBuffer.cpp ../Common/Gmsh.h ../Common/Message.h \ ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h \ ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \ ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h \ - ../Geo/GRegion.h ../Geo/SBoundingBox3d.h + ../Geo/GRegion.h ../Geo/SBoundingBox3d.h ../Geo/Melement.h \ + ../Geo/MRep.h ../Geo/GEdge.h ../Geo/GFace.h ../Geo/GRegion.h \ + ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MElement.h ../Common/OS.h # 1 "/Users/geuzaine/.gmsh/Graphics//" Iso.o: Iso.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \ ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \ diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp index 01c53442cc..f6814248d9 100644 --- a/Graphics/Mesh.cpp +++ b/Graphics/Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: Mesh.cpp,v 1.183 2006-08-22 15:34:34 geuzaine Exp $ +// $Id: Mesh.cpp,v 1.184 2006-08-24 01:14:59 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -372,7 +372,7 @@ static void addEdgesInArrays(GEntity *e) for(int i = 0; i < 2; i++){ if(e->dim() == 2 && CTX.mesh.smooth_normals) e->model()->normals->get(v[i]->x(), v[i]->y(), v[i]->z(), n[0], n[1], n[2]); - m->va_lines->add(v[i]->x(), v[i]->y(), v[i]->z(), n[0], n[1], n[2], color); + m->va_lines->add(v[i]->x(), v[i]->y(), v[i]->z(), n[0], n[1], n[2], color, ele); } } } @@ -405,9 +405,9 @@ static void addElementsInArrays(GEntity *e, std::vector<T*> &elements) if(e->dim() == 2 && CTX.mesh.smooth_normals) e->model()->normals->get(p[0], p[1], p[2], n[0], n[1], n[2]); if(numverts == 3) - m->va_triangles->add(p[0], p[1], p[2], n[0], n[1], n[2], color); + m->va_triangles->add(p[0], p[1], p[2], n[0], n[1], n[2], color, ele); else if(numverts == 4) - m->va_quads->add(p[0], p[1], p[2], n[0], n[1], n[2], color); + m->va_quads->add(p[0], p[1], p[2], n[0], n[1], n[2], color, ele); } } } @@ -423,7 +423,7 @@ static void addElementsInArrays(GEntity *e, std::vector<T*> &elements) for(int l = 0; l < 3; l++) p[l] = pc[l] + CTX.mesh.explode * (p[l] - pc[l]); } - m->va_lines->add(p[0], p[1], p[2], color); + m->va_lines->add(p[0], p[1], p[2], color, ele); } } } @@ -435,6 +435,24 @@ static void drawArrays(GEntity *e, VertexArray *va, GLint type, bool useNormalAr { if(!va) return; + // If we want to be enable picking of individual elements we need to + // draw each one separately + if(CTX.render_mode == GMSH_SELECT && CTX.enable_mouse_selection > 2) { + if(va->getNumElementPointers() == va->getNumVertices()){ + for(int i = 0; i < va->getNumVertices(); i += va->getType()){ + glPushName(va->getType()); + glPushName(i); + glBegin(type); + for(int j = 0; j < va->getType(); j++) + glVertex3fv(va->getVertexArray(3 * (i + j))); + glEnd(); + glPopName(); + glPopName(); + } + return; + } + } + glVertexPointer(3, GL_FLOAT, 0, va->getVertexArray()); glNormalPointer(GL_BYTE, 0, va->getNormalArray()); glColorPointer(4, GL_UNSIGNED_BYTE, 0, va->getColorArray()); diff --git a/Graphics/SelectBuffer.cpp b/Graphics/SelectBuffer.cpp index e03cf203c5..34247eab71 100644 --- a/Graphics/SelectBuffer.cpp +++ b/Graphics/SelectBuffer.cpp @@ -1,4 +1,4 @@ -// $Id: SelectBuffer.cpp,v 1.1 2006-08-20 14:12:41 geuzaine Exp $ +// $Id: SelectBuffer.cpp,v 1.2 2006-08-24 01:14:59 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -26,14 +26,17 @@ #include "Context.h" #include "SelectBuffer.h" #include "GModel.h" +#include "Melement.h" +#include "MRep.h" extern Context_T CTX; extern GModel *GMODEL; class hit{ public: - GLuint type, ient, depth; - hit(GLuint t, GLuint i, GLuint d) : type(t), ient(i), depth(d) {} + GLuint type, ient, depth, type2, ient2; + hit(GLuint t, GLuint i, GLuint d, GLuint t2=0, GLuint i2=0) + : type(t), ient(i), depth(d), type2(t2), ient2(i2) {} }; class hitDepthLessThan{ @@ -56,10 +59,10 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, faces.clear(); regions.clear(); - // In our case the selection buffer size is equal to 5 x the maximum - // number of possible hits + // In our case the selection buffer size is equal to between 5 and 7 + // times the maximum number of possible hits int size = 5 * (GMODEL->numVertex() + GMODEL->numEdge() + - GMODEL->numFace() + GMODEL->numRegion()) + 100; + GMODEL->numFace() + GMODEL->numRegion()) + 1000; GLuint *selectionBuffer = new GLuint[size]; glSelectBuffer(size, selectionBuffer); @@ -90,10 +93,16 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, std::vector<hit> hits; GLuint *ptr = selectionBuffer; for(int i = 0; i < numhits; i++) { - // in Gmsh 'names' should always be 2 or 0. If names is 2, the - // first name is the type of the entity (0 for point, 1 for line, - // etc.) and the second is the entity number; if names is 0 there - // is nothing on the stack. + // in Gmsh 'names' should always be 0, 2 or 4: + // * names == 0 means that there is nothing on the stack + // * if names == 2, the first name is the type of the entity + // (0 for point, 1 for edge, 2 for face or 3 for volume) and + // the second is the entity number; + // * if names == 4, the first name is the type of the entity, + // the second is the entity number, the third is the type + // of vertex array (2 for line, 3 for triangle, 4 for quad) + // and the fourth is the index of the element in the vertex + // array GLuint names = *ptr++; GLuint mindepth = *ptr++; *ptr++; // maxdepth @@ -103,6 +112,14 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, GLuint ient = *ptr++; hits.push_back(hit(type, ient, depth)); } + else if(names == 4){ + GLuint depth = mindepth; + GLuint type = *ptr++; + GLuint ient = *ptr++; + GLuint type2 = *ptr++; + GLuint ient2 = *ptr++; + hits.push_back(hit(type, ient, depth, type2, ient2)); + } } delete [] selectionBuffer; @@ -118,7 +135,7 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, // entity of "lowest dimension" (point < line < surface < // volume). Otherwise, return the closest entity of type // "entityType" - GLuint typmin = 4; + GLuint typmin = 10; for(unsigned int i = 0; i < hits.size(); i++) typmin = std::min(typmin, hits[i].type); @@ -148,6 +165,10 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, Msg(GERROR, "Problem in line selection processing"); return false; } + if(hits[i].type2 && e->meshRep){ + MElement *ele = e->meshRep->getElement(hits[i].type2, hits[i].ient2); + if(ele) printf("element %d\n", ele->getNum()); + } edges.push_back(e); if(!multipleSelection) return true; } @@ -159,6 +180,10 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, Msg(GERROR, "Problem in surface selection processing"); return false; } + if(hits[i].type2 && f->meshRep){ + MElement *ele = f->meshRep->getElement(hits[i].type2, hits[i].ient2); + if(ele) printf("element %d\n", ele->getNum()); + } faces.push_back(f); if(!multipleSelection) return true; } @@ -170,6 +195,10 @@ bool ProcessSelectionBuffer(int entityType, bool multipleSelection, Msg(GERROR, "Problem in volume selection processing"); return false; } + if(hits[i].type2 && r->meshRep){ + MElement *ele = r->meshRep->getElement(hits[i].type2, hits[i].ient2); + if(ele) printf("element %d\n", ele->getNum()); + } regions.push_back(r); if(!multipleSelection) return true; } -- GitLab