From 832c17c83472497f63df0b3ac0c71c21c39c62d2 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 29 Mar 2023 20:30:21 +0200 Subject: [PATCH] Rewrite double-click selection in GUI --- libsrc/visualization/mvdraw.cpp | 4 +- libsrc/visualization/mvdraw.hpp | 67 +-- libsrc/visualization/vsmesh.cpp | 640 +++++++++------------------- libsrc/visualization/vssolution.cpp | 140 +++--- libsrc/visualization/vssolution.hpp | 2 - 5 files changed, 310 insertions(+), 543 deletions(-) diff --git a/libsrc/visualization/mvdraw.cpp b/libsrc/visualization/mvdraw.cpp index d216aa12..b6f70627 100644 --- a/libsrc/visualization/mvdraw.cpp +++ b/libsrc/visualization/mvdraw.cpp @@ -77,9 +77,11 @@ namespace netgen int VisualScene :: locpi; int VisualScene :: seledge; - int VisualScene :: selecttimestamp; optional> VisualScene :: marker = nullopt; + int VisualScene :: subdivision_timestamp = -1; + int VisualScene :: subdivisions = 2; + int VisualScene :: viewport[4]; VisualizationParameters :: VisualizationParameters() diff --git a/libsrc/visualization/mvdraw.hpp b/libsrc/visualization/mvdraw.hpp index 76d610ea..06fb5740 100644 --- a/libsrc/visualization/mvdraw.hpp +++ b/libsrc/visualization/mvdraw.hpp @@ -31,9 +31,10 @@ namespace netgen static int locpi; static int NGGUI_API seledge; - static int selecttimestamp; static optional> marker; + static int subdivision_timestamp; + static int subdivisions; public: static int viewport[4]; static GLuint coltexname; @@ -126,35 +127,47 @@ namespace netgen class VisualSceneMesh : public VisualScene { - int filledlist; - int linelist; - int edgelist; - int pointnumberlist; + int filledlist = 0; + int linelist = 0; + int edgelist = 0; + int pointnumberlist = 0; - int tetlist; - int prismlist; - int pyramidlist; - int hexlist; + int tetlist = 0; + int prismlist = 0; + int pyramidlist = 0; + int hexlist = 0; - int badellist; - int identifiedlist; - int domainsurflist; + int badellist = 0; + int identifiedlist = 0; + int domainsurflist = 0; - int vstimestamp;//, selecttimestamp; - int filledtimestamp; - int linetimestamp; - int edgetimestamp; - int pointnumbertimestamp; + int vstimestamp = -1; + int filledtimestamp = -1; + int linetimestamp = -1; + int edgetimestamp = -1; + int pointnumbertimestamp = -1; - int tettimestamp; - int prismtimestamp; - int pyramidtimestamp; - int hextimestamp; + int tettimestamp = -1; + int prismtimestamp = -1; + int pyramidtimestamp = -1; + int hextimestamp = -1; - int badeltimestamp; - int identifiedtimestamp; - int domainsurftimestamp; + int badeltimestamp = -1; + int identifiedtimestamp = -1; + int domainsurftimestamp = -1; + struct { + unsigned framebuffer = 0; + unsigned render_buffers[2]; + unsigned width = 0; + unsigned height = 0; + unsigned x = 0; + unsigned y = 0; + int list = 0; + int list_timestamp = -1; + double projmat[16]; + int viewport[4]; + } select; #ifdef PARALLELGL NgArray par_linelists; @@ -200,7 +213,7 @@ namespace netgen { return selelement; } NGGUI_API int SelectedPoint () const { return selpoint; } - void BuildFilledList (bool names); + void BuildFilledList (bool select); // private: void BuildLineList(); void BuildEdgeList(); @@ -215,7 +228,9 @@ namespace netgen void BuildIdentifiedList(); void BuildDomainSurfList(); - bool Unproject (int px, int py, Point<3> &p); + bool SelectSurfaceElement (int px, int py, Point<3> &p, bool select_on_clipping_plane); + bool Unproject(int px, int py, Point<3> &p); + ngcore::INT<2> Project(Point<3> p); }; NGGUI_API extern VisualSceneMesh vsmesh; diff --git a/libsrc/visualization/vsmesh.cpp b/libsrc/visualization/vsmesh.cpp index ceef36e2..d0705aab 100644 --- a/libsrc/visualization/vsmesh.cpp +++ b/libsrc/visualization/vsmesh.cpp @@ -23,38 +23,9 @@ namespace netgen VisualSceneMesh :: VisualSceneMesh () : VisualScene() { - filledlist = 0; - linelist = 0; - edgelist = 0; - badellist = 0; - tetlist = 0; - prismlist = 0; - hexlist = 0; - pyramidlist = 0; - identifiedlist = 0; - pointnumberlist = 0; - domainsurflist = 0; - - vstimestamp = -1; // GetTimeStamp(); - selecttimestamp = -1; // GetTimeStamp(); - filledtimestamp = -1; // GetTimeStamp(); - linetimestamp = -1; // GetTimeStamp(); - edgetimestamp = -1; // GetTimeStamp(); - pointnumbertimestamp = -1; // GetTimeStamp(); - - tettimestamp = -1; // GetTimeStamp(); - prismtimestamp = -1; // GetTimeStamp(); - hextimestamp = -1; // GetTimeStamp(); - pyramidtimestamp = -1; // GetTimeStamp(); - - badeltimestamp = -1; // GetTimeStamp(); - identifiedtimestamp = -1; // GetTimeStamp(); - domainsurftimestamp = -1; // GetTimeStamp(); - - selface = -1; selelement = -1; - locpi = 1; + locpi = -2; selpoint = PointIndex::INVALID; selpoint2 = PointIndex::INVALID; seledge = -1; @@ -62,7 +33,6 @@ namespace netgen minh = 0.0; maxh = 0.0; user_me_handler = NULL; - } VisualSceneMesh :: ~VisualSceneMesh () @@ -150,11 +120,7 @@ namespace netgen if (vispar.drawfilledtrigs) { - if (filledtimestamp < mesh->GetTimeStamp () || - filledtimestamp < selecttimestamp) - { - BuildFilledList (false); - } + BuildFilledList (false); #ifdef PARALLELGL @@ -883,12 +849,17 @@ namespace netgen - void VisualSceneMesh :: BuildFilledList (bool names) + void VisualSceneMesh :: BuildFilledList (bool build_select) { shared_ptr mesh = GetMesh(); static int timer = NgProfiler::CreateTimer ("Mesh::BuildFilledList"); NgProfiler::RegionTimer reg (timer); + auto & list = build_select ? select.list : filledlist; + auto & timestamp = build_select ? select.list_timestamp : filledtimestamp; + if (list && timestamp > max(mesh->GetTimeStamp(), subdivision_timestamp)) + return; + #ifdef PARALLELGL if (id == 0 && ntasks > 1) @@ -901,18 +872,18 @@ namespace netgen for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_filledlists[dest], dest, MPI_TAG_VIS); - if (filledlist) - glDeleteLists (filledlist, 1); + if (list) + glDeleteLists (list, 1); - filledlist = glGenLists (1); - glNewList (filledlist, GL_COMPILE); + list = glGenLists (1); + glNewList (list, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_filledlists[dest]); glEndList(); - filledtimestamp = NextTimeStamp(); + timestamp = NextTimeStamp(); return; } @@ -925,13 +896,13 @@ namespace netgen lock -> Lock(); } - filledtimestamp = NextTimeStamp(); + timestamp = NextTimeStamp(); - if (filledlist) - glDeleteLists (filledlist, 1); + if (list) + glDeleteLists (list, 1); - filledlist = glGenLists (1); - glNewList (filledlist, GL_COMPILE); + list = glGenLists (1); + glNewList (list, GL_COMPILE); #ifdef STLGEOM @@ -967,6 +938,14 @@ namespace netgen else glDisable (GL_COLOR_MATERIAL); + if(build_select) + { + glDisable(GL_TEXTURE_2D); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable (GL_COLOR_MATERIAL); + } + GLfloat matcol[] = { 0, 1, 0, 1 }; GLfloat matcolsel[] = { 1, 0, 0, 1 }; @@ -976,7 +955,7 @@ namespace netgen CurvedElements & curv = mesh->GetCurvedElements(); - int hoplotn = 1 << vispar.subdivisions; + int hoplotn = 1 << subdivisions; Array seia; @@ -993,10 +972,13 @@ namespace netgen for (auto i : Range(4)) matcol[i] = mesh->GetFaceDescriptor(faceindex).SurfColour()[i]; - if (faceindex == selface) - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsel); - else - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol); + if(!build_select) + { + if (faceindex == selface) + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsel); + else + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol); + } static Point<3> xa[129]; static Vec<3> na[129]; @@ -1020,8 +1002,14 @@ namespace netgen if (!drawel) continue; - if (names) - glLoadName (sei+1); + if (build_select) + { + GLushort r,g,b; + r = (sei+1) % (1<<16); + g = (sei+1) >> 16; + b = 0; + glColor3us(r,g,b); + } switch (el.GetType()) { @@ -1267,7 +1255,7 @@ namespace netgen #ifdef PARALLELGL glFinish(); if (id > 0) - MyMPI_Send (filledlist, 0, MPI_TAG_VIS); + MyMPI_Send (list, 0, MPI_TAG_VIS); #endif } @@ -1335,7 +1323,7 @@ namespace netgen glLineWidth (1.0f); - int hoplotn = 1 << vispar.subdivisions; + int hoplotn = 1 << subdivisions; // PrintMessage (3, "nse = ", mesh->GetNSE()); for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) @@ -1621,7 +1609,7 @@ namespace netgen if (mesh->GetCurvedElements().IsHighOrder()) { - int hoplotn = 1 << vispar.subdivisions; + int hoplotn = 1 << subdivisions; // mesh->GetCurvedElements().GetNVisualSubsecs(); Point<3> x; @@ -1832,7 +1820,7 @@ namespace netgen else glShadeModel (GL_SMOOTH); - int hoplotn = max (2, 1 << vispar.subdivisions); + int hoplotn = max (2, 1 << subdivisions); @@ -2134,7 +2122,7 @@ namespace netgen Point<3> grid[11][11]; Point<3> fpts[4]; - int order = vispar.subdivisions+1; + int order = subdivisions+1; for (int trig = 0; trig < 2; trig++) { @@ -2233,7 +2221,7 @@ namespace netgen /* - int hoplotn = 1 << vispar.subdivisions; + int hoplotn = 1 << subdivisions; // int hoplotn = curv.GetNVisualSubsecs(); const Point3d * facepoint = MeshTopology :: GetVertices (TRIG); @@ -2521,7 +2509,7 @@ namespace netgen Point<3> grid[11][11]; Point<3> fpts[4]; - int order = vispar.subdivisions+1; + int order = subdivisions+1; for (int quad = 0; quad<6; quad++) { @@ -2672,7 +2660,7 @@ namespace netgen Point<3> grid[11][11]; Point<3> fpts[4]; - int order = vispar.subdivisions+1; + int order = subdivisions+1; for (int trig = 0; trig < 4; trig++) { @@ -3097,28 +3085,105 @@ namespace netgen - - bool VisualSceneMesh :: Unproject (int px, int py, Point<3> &p) + bool VisualSceneMesh :: SelectSurfaceElement (int px, int py, Point<3> &p, bool select_on_clipping_plane) { - shared_ptr mesh = GetMesh(); - - BuildFilledList (true); - + selelement = -1; marker = nullopt; - MouseDblClickSelect(px,py,clipplane,backcolor,transformationmat,center,rad, - filledlist,selelement,selface,seledge,selpoint,selpoint2,locpi); + shared_ptr mesh = GetMesh(); + if(px != select.x || py != select.y) + { + select.x = px; + select.y = py; + locpi = -2; + } + glGetIntegerv (GL_VIEWPORT, select.viewport); + GLenum err; + if(select.framebuffer == 0 || select.viewport[2] != select.width || select.viewport[3] != select.height) + { + select.width = select.viewport[2]; + select.height = select.viewport[3]; + if(select.framebuffer != 0) + { + glDeleteRenderbuffers(2, select.render_buffers); + glDeleteFramebuffers(1, &select.framebuffer); + } - GLdouble /* modelview[16], */ projection[16]; - GLint viewport[4]; - GLdouble result[3]; + glGenFramebuffers(1, &select.framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, select.framebuffer); - glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); - glGetIntegerv(GL_VIEWPORT, &viewport[0]); + // create, reserve and attach color and depth renderbuffer + glGenRenderbuffers(2, select.render_buffers); + glBindRenderbuffer(GL_RENDERBUFFER, select.render_buffers[0]); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB16, select.width, select.height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, select.render_buffers[0]); - int hy = viewport[3]-py; + glBindRenderbuffer(GL_RENDERBUFFER, select.render_buffers[1]); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, select.width, select.height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, select.render_buffers[1]); - GLfloat pz; + // check if framebuffer status is complete + if(int fbstatus; (fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) + cerr << "no frame buffer " << fbstatus << endl; + + } + glFlush(); + + glBindFramebuffer(GL_FRAMEBUFFER, select.framebuffer); + BuildFilledList (true); + + glEnable(GL_DEPTH_TEST); + glClearColor(0, 0, 0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMultMatrixd (transformationmat); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + auto hy = select.viewport[3] - py; + + SetClippingPlane(); + if (vispar.clipping.enable) + { + Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); + double len = Abs(n); + double mu = -clipplane[3] / (len*len); + Point<3> p (mu * n); + n /= len; + Vec<3> t1 = n.GetNormal (); + Vec<3> t2 = Cross (n, t1); + + double xi1mid = (center - p) * t1; + double xi2mid = (center - p) * t2; + + if(select_on_clipping_plane) + { + glColor3us(0,0,0); + glBegin (GL_QUADS); + glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); + glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); + glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); + glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); + glEnd (); + } + } + glCallList (select.list); + glFinish(); + + glGetDoublev (GL_PROJECTION_MATRIX, select.projmat); + auto found = Unproject(px, py, p); + if(found) + { + marker = p; + GLushort numbers[3]; + glReadPixels (px, hy, 1, 1, GL_RGB, GL_UNSIGNED_SHORT, numbers); + selelement = numbers[0] + numbers[1]*(1<<16); + locpi++; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glPopMatrix(); if(lock) { @@ -3127,48 +3192,79 @@ namespace netgen lock = NULL; } - // cout << "x, y = " << px << ", " << hy << endl; + return found; + } + + bool VisualSceneMesh :: Unproject(int px, int py, Point<3> &p) + { + auto hy = select.viewport[3] - py; + float pz; glReadPixels (px, hy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pz); + if(pz<1 && pz>0) + gluUnProject(px, hy, pz, transformationmat, select.projmat, select.viewport, + &p[0], &p[1], &p[2]); + return pz<1 && pz>0; + } - if(pz>=1.0) - return false; - if(pz<=0.0) - return false; + ngcore::INT<2> VisualSceneMesh :: Project(Point<3> p) + { + Point<3> pwin; + gluProject(p[0], p[1], p[2], transformationmat, select.projmat, select.viewport, + &pwin[0], &pwin[1], &pwin[2]); - // cout << "pz = " << pz << endl; - gluUnProject(px, hy, pz, transformationmat, projection, viewport, - &result[0], &result[1], &result[2]); - - p = Point<3>{result[0], result[1], result[2]}; - marker = p; - return true; + return ngcore::INT<2>(pwin[0]+0.5, select.viewport[3]-pwin[1]+0.5); } void VisualSceneMesh :: MouseDblClick (int px, int py) { Point<3> p; - bool found_point = Unproject(px, py, p); + bool found_point = SelectSurfaceElement(px, py, p, false); + int sel_face = 0; - if(selelement!=-1) + if(selelement>0) { const Element2d & sel = GetMesh()->SurfaceElement(selelement); - cout << "select element " << selelement - << " on face " << sel.GetIndex() << endl; - cout << "Nodes: "; - for (int i = 1; i <= sel.GetNP(); i++) - cout << sel.PNum(i) << " "; - cout << endl; - - cout << "selected point " << selpoint - << ", pos = " << GetMesh()->Point (selpoint) - << endl; - - cout << "seledge = " << seledge << endl; - + auto pi_nearest = sel[0]; + double min_dist = 1e99; + for(auto pi : sel.PNums()) + if(Dist2(GetMesh()->Point(pi), p) < min_dist) + { + min_dist = Dist2(GetMesh()->Point(pi), p); + pi_nearest = pi; + } + auto p_win = Project(GetMesh()->Point(pi_nearest)); + cout << endl; + if(abs(p_win[0]-px) < 5 && abs(p_win[1]-py) < 5) + { + cout << "select point " << pi_nearest << endl; + marker = GetMesh()->Point(pi_nearest); + sel_face = sel.GetIndex(); + locpi = -2; + } + else + { + if(locpi < 0) + { + cout << "select element " << selelement + << " on face " << sel.GetIndex() << endl; + cout << "Nodes: "; + for (int i = 1; i <= sel.GetNP(); i++) + cout << sel.PNum(i) << " "; + cout << endl; + } + else { + auto pi = sel[locpi%sel.GetNP()]; + auto p = GetMesh()->Points()[pi]; + marker = p; + cout << "selected point " << pi << endl; + } + } } + SetSelectedFace(sel_face); + if(found_point) { cout << "point : " << p << endl; @@ -3179,353 +3275,21 @@ namespace netgen } } - selecttimestamp = NextTimeStamp(); - if(lock) { lock->UnLock(); delete lock; lock = NULL; } - - /* - int i, hits; - - // select surface triangle by mouse click - - GLuint selbuf[10000]; - glSelectBuffer (10000, selbuf); - - - glRenderMode (GL_SELECT); - - GLint viewport[4]; - glGetIntegerv (GL_VIEWPORT, viewport); - - - glMatrixMode (GL_PROJECTION); - glPushMatrix(); - - GLdouble projmat[16]; - glGetDoublev (GL_PROJECTION_MATRIX, projmat); - - glLoadIdentity(); - gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); - glMultMatrixd (projmat); - - - - glClearColor(backcolor, backcolor, backcolor, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode (GL_MODELVIEW); - - glPushMatrix(); - glMultMatrixf (transformationmat); - - - // SetClippingPlane(); - - glInitNames(); - glPushName (1); - - glPolygonOffset (1, 1); - glEnable (GL_POLYGON_OFFSET_FILL); - - glDisable(GL_CLIP_PLANE0); - - if (vispar.clipenable) - { - Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); - double len = Abs(n); - double mu = -clipplane[3] / (len*len); - Point<3> p (mu * n); - n /= len; - Vec<3> t1 = n.GetNormal (); - Vec<3> t2 = Cross (n, t1); - - double xi1mid = (center - p) * t1; - double xi2mid = (center - p) * t2; - - glLoadName (0); - glBegin (GL_QUADS); - glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); - glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); - glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); - glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); - glEnd (); - } - - // SetClippingPlane(); - - glCallList (filledlist); - - glDisable (GL_POLYGON_OFFSET_FILL); - - glPopName(); - - glMatrixMode (GL_PROJECTION); - glPopMatrix(); - - glMatrixMode (GL_MODELVIEW); - glPopMatrix(); - - glFlush(); - - - hits = glRenderMode (GL_RENDER); - - // cout << "hits = " << hits << endl; - - int minname = 0; - GLuint mindepth = 0; - - // find clippingplane - GLuint clipdepth = 0; // GLuint(-1); - - for (i = 0; i < hits; i++) - { - int curname = selbuf[4*i+3]; - if (!curname) clipdepth = selbuf[4*i+1]; - } - - for (i = 0; i < hits; i++) - { - int curname = selbuf[4*i+3]; - GLuint curdepth = selbuf[4*i+1]; - - if (curname && (curdepth > clipdepth) && - (curdepth < mindepth || !minname)) - { - mindepth = curdepth; - minname = curname; - } - } - - seledge = -1; - if (minname) - { - const Element2d & sel = mesh->SurfaceElement(minname); - - - cout << "select element " << minname - << " on face " << sel.GetIndex() << endl; - cout << "Nodes: "; - for (i = 1; i <= sel.GetNP(); i++) - cout << sel.PNum(i) << " "; - cout << endl; - - selelement = minname; - selface = mesh->SurfaceElement(minname).GetIndex(); - - locpi = (locpi % sel.GetNP()) + 1; - selpoint2 = selpoint; - selpoint = sel.PNum(locpi); - cout << "selected point " << selpoint - << ", pos = " << mesh->Point (selpoint) - << endl; - - for (i = 1; i <= mesh->GetNSeg(); i++) - { - const Segment & seg = mesh->LineSegment(i); - if (seg[0] == selpoint && seg[1] == selpoint2 || - seg[1] == selpoint && seg[0] == selpoint2) - { - seledge = seg.edgenr; - cout << "seledge = " << seledge << endl; - } - } - - } - else - { - selface = -1; - selelement = -1; - selpoint = -1; - selpoint2 = -1; - } - - glDisable(GL_CLIP_PLANE0); - - selecttimestamp = NextTimeStamp(); - */ - } - - - void MouseDblClickSelect (const int px, const int py, - const GLdouble * clipplane, const GLdouble backcolor, - const double * transformationmat, - const Point3d & center, - const double rad, - const int displaylist, - int & selelement, int & selface, int & seledge, PointIndex & selpoint, - PointIndex & selpoint2, int & locpi) - { - auto mesh = vsmesh.GetMesh(); - - int i, hits; - - // select surface triangle by mouse click - - GLuint selbuf[10000]; - glSelectBuffer (10000, selbuf); - - - glRenderMode (GL_SELECT); - - GLint viewport[4]; - glGetIntegerv (GL_VIEWPORT, viewport); - - - glMatrixMode (GL_PROJECTION); - glPushMatrix(); - - GLdouble projmat[16]; - glGetDoublev (GL_PROJECTION_MATRIX, projmat); - - glLoadIdentity(); - gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); - glMultMatrixd (projmat); - - - - glClearColor(backcolor, backcolor, backcolor, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode (GL_MODELVIEW); - - glPushMatrix(); - glMultMatrixd (transformationmat); - - - // SetClippingPlane(); - - glInitNames(); - glPushName (1); - - glPolygonOffset (1, 1); - glEnable (GL_POLYGON_OFFSET_FILL); - - glDisable(GL_CLIP_PLANE0); - - if (vispar.clipping.enable) - { - glEnable(GL_CLIP_PLANE0); - Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); - double len = Abs(n); - double mu = -clipplane[3] / (len*len); - Point<3> p (mu * n); - n /= len; - Vec<3> t1 = n.GetNormal (); - Vec<3> t2 = Cross (n, t1); - - double xi1mid = (center - p) * t1; - double xi2mid = (center - p) * t2; - - glLoadName (0); - glBegin (GL_QUADS); - glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); - glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); - glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); - glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); - glEnd (); - } - - // SetClippingPlane(); - glCallList (displaylist); - - glDisable (GL_POLYGON_OFFSET_FILL); - - glPopName(); - - glMatrixMode (GL_PROJECTION); - glPopMatrix(); - - glMatrixMode (GL_MODELVIEW); - glPopMatrix(); - - glFlush(); - - - hits = glRenderMode (GL_RENDER); - //cout << "hits = " << hits << endl; - - int minname = 0; - GLuint mindepth = 0; - - // find clippingplane - GLuint clipdepth = 0; // GLuint(-1); - - for (i = 0; i < hits; i++) - { - int curname = selbuf[4*i+3]; - if (!curname) clipdepth = selbuf[4*i+1]; - } - - for (i = 0; i < hits; i++) - { - int curname = selbuf[4*i+3]; - GLuint curdepth = selbuf[4*i+1]; - /* - cout << selbuf[4*i] << " " << selbuf[4*i+1] << " " - << selbuf[4*i+2] << " " << selbuf[4*i+3] << endl; - */ - if (curname && (curdepth > clipdepth) && - (curdepth < mindepth || !minname)) - { - mindepth = curdepth; - minname = curname; - } - } - - seledge = -1; - if (minname) - { - const Element2d & sel = mesh->SurfaceElement(minname); - - selelement = minname; - selface = mesh->SurfaceElement(minname).GetIndex(); - - locpi = (locpi % sel.GetNP()) + 1; - selpoint2 = selpoint; - selpoint = sel.PNum(locpi); - - for (i = 1; i <= mesh->GetNSeg(); i++) - { - const Segment & seg = mesh->LineSegment(i); - if ( (seg[0] == selpoint && seg[1] == selpoint2) || - (seg[1] == selpoint && seg[0] == selpoint2) ) - { - seledge = seg.edgenr; - } - } - } - else - { - selface = -1; - selelement = -1; - selpoint = -1; - selpoint2 = -1; - } - - glDisable(GL_CLIP_PLANE0); - - - -#ifdef PARALLELGL - vsmesh.Broadcast (); -#endif - } - - void VisualSceneMesh :: SetSelectedFace (int asf) { + if(selface != asf) + filledlist = 0; selface = asf; - selecttimestamp = NextTimeStamp(); } diff --git a/libsrc/visualization/vssolution.cpp b/libsrc/visualization/vssolution.cpp index a803b457..ef2645b6 100644 --- a/libsrc/visualization/vssolution.cpp +++ b/libsrc/visualization/vssolution.cpp @@ -4806,91 +4806,79 @@ namespace netgen } }; - // Check if clipping plane is drawn at current mouse cursor position - if(dim==3 && clipsolution && vispar.clipping.enable) - { - GLint viewport[4]; - GLdouble projection[16]; - glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); - - glGetIntegerv(GL_VIEWPORT, &viewport[0]); - - int hy = viewport[3]-py; - - // manually intersect the view vector with the clipping plane (also working if clipping vectors are shown) - Point<3> p_clipping_plane; - gluUnProject(px, hy, 1.0, transformationmat, projection, viewport, - &p_clipping_plane[0], &p_clipping_plane[1], &p_clipping_plane[2]); - - Point<3> eye; - gluUnProject( (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2, - 0.0, transformationmat, projection, viewport, &eye[0], &eye[1], &eye[2]); - - Vec<3> n{vispar.clipping.normal}; - n.Normalize(); - Vec<3> view = p_clipping_plane-eye; - - // check if we look at the clipping plane from the right direction - if(n*view > 1e-8) - { - double lam = vispar.clipping.dist - Vec<3>{eye}*n; - lam /= n*view; - p_clipping_plane = eye + lam*view; - - double lami[3]; - if(auto el3d = mesh->GetElementOfPoint( p_clipping_plane, lami )) - { - cout << endl << "Selected point " << p_clipping_plane << " on clipping plane" << endl; - marker = p_clipping_plane; - - bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_volume; - bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_volume; - - if(have_scal_func) - { - auto & sol = *soldata[scalfunction]; - double val; - double imag = 0; - int rcomponent = scalcomp; - int comp = scalcomp; - if(sol.iscomplex && rcomponent != 0) - { - rcomponent = 2 * ((rcomponent-1)/2) + 1; - GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent+1, - imag); - comp = (scalcomp-1)/2 + 1; - } - GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent, val); - printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0); - } - if(vecfunction!=-1 && soldata[vecfunction]->draw_volume) - { - auto & sol = *soldata[vecfunction]; - ArrayMem values(sol.components); - GetValues(&sol, el3d-1, lami[0], lami[1], lami[2], &values[0]); - printVecValue(sol, values); - } - return; - } - } - } - - // no point on clipping plane found -> continue searching for surface element - Point<3> p; - bool found_point = vsmesh.Unproject(px, py, p); + bool found_point = vsmesh.SelectSurfaceElement(px, py, p, showclipsolution && clipsolution); if(!found_point) return; - marker = p; + // marker = p; - if(selelement<=0) - return; + // found point on clipping plane + if(selelement==0) + { + GLint viewport[4]; + GLdouble projection[16]; + glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); + + glGetIntegerv(GL_VIEWPORT, &viewport[0]); + + Point<3> eye; + gluUnProject( (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2, + 0.0, transformationmat, projection, viewport, &eye[0], &eye[1], &eye[2]); + + Vec<3> n{vispar.clipping.normal}; + n.Normalize(); + Vec<3> view = p-eye; + + // check if we look at the clipping plane from the right direction + if(n*view > 1e-8) + { + double lam = vispar.clipping.dist - Vec<3>{eye}*n; + lam /= n*view; + p = eye + lam*view; + + double lami[3]; + if(auto el3d = mesh->GetElementOfPoint( p, lami )) + { + cout << endl << "Selected point " << p << " on clipping plane" << endl; + // marker = p; + + bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_volume; + bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_volume; + + if(have_scal_func) + { + auto & sol = *soldata[scalfunction]; + double val; + double imag = 0; + int rcomponent = scalcomp; + int comp = scalcomp; + if(sol.iscomplex && rcomponent != 0) + { + rcomponent = 2 * ((rcomponent-1)/2) + 1; + GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent+1, + imag); + comp = (scalcomp-1)/2 + 1; + } + GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent, val); + printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0); + } + if(vecfunction!=-1 && soldata[vecfunction]->draw_volume) + { + auto & sol = *soldata[vecfunction]; + ArrayMem values(sol.components); + GetValues(&sol, el3d-1, lami[0], lami[1], lami[2], &values[0]); + printVecValue(sol, values); + } + return; + } + } + } double lami[3] = {0.0, 0.0, 0.0}; // Check if unprojected Point is close to surface element (eps of 1e-3 due to z-Buffer accuracy) bool found_2del = false; - if(mesh->PointContainedIn2DElement(p, lami, selelement, false && fabs(lami[2])<1e-3)) + if(selelement>0 && mesh->PointContainedIn2DElement(p, lami, selelement, false && fabs(lami[2])<1e-3)) { // Found it, use coordinates of point projected to surface element mesh->GetCurvedElements().CalcSurfaceTransformation({1.0-lami[0]-lami[1], lami[0]}, selelement-1, p); diff --git a/libsrc/visualization/vssolution.hpp b/libsrc/visualization/vssolution.hpp index 0ec17763..66684ed4 100644 --- a/libsrc/visualization/vssolution.hpp +++ b/libsrc/visualization/vssolution.hpp @@ -94,7 +94,6 @@ class NGGUI_API VisualSceneSolution : public VisualScene int fieldlinestimestamp, surface_vector_timestamp; int pointcurve_timestamp; int isosurface_timestamp; - int subdivision_timestamp; int timetimestamp; double minval, maxval; @@ -174,7 +173,6 @@ public: int autoscale, logscale; double mminval, mmaxval; int numisolines; - int subdivisions; bool showclipsolution; bool showsurfacesolution;