Rewrite double-click selection in GUI

This commit is contained in:
Matthias Hochsteger 2023-03-29 20:30:21 +02:00
parent a12e9bec61
commit 832c17c834
5 changed files with 310 additions and 543 deletions

View File

@ -77,9 +77,11 @@ namespace netgen
int VisualScene :: locpi; int VisualScene :: locpi;
int VisualScene :: seledge; int VisualScene :: seledge;
int VisualScene :: selecttimestamp;
optional<Point<3>> VisualScene :: marker = nullopt; optional<Point<3>> VisualScene :: marker = nullopt;
int VisualScene :: subdivision_timestamp = -1;
int VisualScene :: subdivisions = 2;
int VisualScene :: viewport[4]; int VisualScene :: viewport[4];
VisualizationParameters :: VisualizationParameters() VisualizationParameters :: VisualizationParameters()

View File

@ -31,9 +31,10 @@ namespace netgen
static int locpi; static int locpi;
static int NGGUI_API seledge; static int NGGUI_API seledge;
static int selecttimestamp;
static optional<Point<3>> marker; static optional<Point<3>> marker;
static int subdivision_timestamp;
static int subdivisions;
public: public:
static int viewport[4]; static int viewport[4];
static GLuint coltexname; static GLuint coltexname;
@ -126,35 +127,47 @@ namespace netgen
class VisualSceneMesh : public VisualScene class VisualSceneMesh : public VisualScene
{ {
int filledlist; int filledlist = 0;
int linelist; int linelist = 0;
int edgelist; int edgelist = 0;
int pointnumberlist; int pointnumberlist = 0;
int tetlist; int tetlist = 0;
int prismlist; int prismlist = 0;
int pyramidlist; int pyramidlist = 0;
int hexlist; int hexlist = 0;
int badellist; int badellist = 0;
int identifiedlist; int identifiedlist = 0;
int domainsurflist; int domainsurflist = 0;
int vstimestamp;//, selecttimestamp; int vstimestamp = -1;
int filledtimestamp; int filledtimestamp = -1;
int linetimestamp; int linetimestamp = -1;
int edgetimestamp; int edgetimestamp = -1;
int pointnumbertimestamp; int pointnumbertimestamp = -1;
int tettimestamp; int tettimestamp = -1;
int prismtimestamp; int prismtimestamp = -1;
int pyramidtimestamp; int pyramidtimestamp = -1;
int hextimestamp; int hextimestamp = -1;
int badeltimestamp; int badeltimestamp = -1;
int identifiedtimestamp; int identifiedtimestamp = -1;
int domainsurftimestamp; 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 #ifdef PARALLELGL
NgArray<int> par_linelists; NgArray<int> par_linelists;
@ -200,7 +213,7 @@ namespace netgen
{ return selelement; } { return selelement; }
NGGUI_API int SelectedPoint () const NGGUI_API int SelectedPoint () const
{ return selpoint; } { return selpoint; }
void BuildFilledList (bool names); void BuildFilledList (bool select);
// private: // private:
void BuildLineList(); void BuildLineList();
void BuildEdgeList(); void BuildEdgeList();
@ -215,7 +228,9 @@ namespace netgen
void BuildIdentifiedList(); void BuildIdentifiedList();
void BuildDomainSurfList(); 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; NGGUI_API extern VisualSceneMesh vsmesh;

View File

@ -23,38 +23,9 @@ namespace netgen
VisualSceneMesh :: VisualSceneMesh () VisualSceneMesh :: VisualSceneMesh ()
: VisualScene() : 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; selface = -1;
selelement = -1; selelement = -1;
locpi = 1; locpi = -2;
selpoint = PointIndex::INVALID; selpoint = PointIndex::INVALID;
selpoint2 = PointIndex::INVALID; selpoint2 = PointIndex::INVALID;
seledge = -1; seledge = -1;
@ -62,7 +33,6 @@ namespace netgen
minh = 0.0; minh = 0.0;
maxh = 0.0; maxh = 0.0;
user_me_handler = NULL; user_me_handler = NULL;
} }
VisualSceneMesh :: ~VisualSceneMesh () VisualSceneMesh :: ~VisualSceneMesh ()
@ -149,12 +119,8 @@ namespace netgen
SetClippingPlane (); SetClippingPlane ();
if (vispar.drawfilledtrigs) if (vispar.drawfilledtrigs)
{
if (filledtimestamp < mesh->GetTimeStamp () ||
filledtimestamp < selecttimestamp)
{ {
BuildFilledList (false); BuildFilledList (false);
}
#ifdef PARALLELGL #ifdef PARALLELGL
@ -883,12 +849,17 @@ namespace netgen
void VisualSceneMesh :: BuildFilledList (bool names) void VisualSceneMesh :: BuildFilledList (bool build_select)
{ {
shared_ptr<Mesh> mesh = GetMesh(); shared_ptr<Mesh> mesh = GetMesh();
static int timer = NgProfiler::CreateTimer ("Mesh::BuildFilledList"); static int timer = NgProfiler::CreateTimer ("Mesh::BuildFilledList");
NgProfiler::RegionTimer reg (timer); 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 #ifdef PARALLELGL
if (id == 0 && ntasks > 1) if (id == 0 && ntasks > 1)
@ -901,18 +872,18 @@ namespace netgen
for ( int dest = 1; dest < ntasks; dest++ ) for ( int dest = 1; dest < ntasks; dest++ )
MyMPI_Recv (par_filledlists[dest], dest, MPI_TAG_VIS); MyMPI_Recv (par_filledlists[dest], dest, MPI_TAG_VIS);
if (filledlist) if (list)
glDeleteLists (filledlist, 1); glDeleteLists (list, 1);
filledlist = glGenLists (1); list = glGenLists (1);
glNewList (filledlist, GL_COMPILE); glNewList (list, GL_COMPILE);
for ( int dest = 1; dest < ntasks; dest++ ) for ( int dest = 1; dest < ntasks; dest++ )
glCallList (par_filledlists[dest]); glCallList (par_filledlists[dest]);
glEndList(); glEndList();
filledtimestamp = NextTimeStamp(); timestamp = NextTimeStamp();
return; return;
} }
@ -925,13 +896,13 @@ namespace netgen
lock -> Lock(); lock -> Lock();
} }
filledtimestamp = NextTimeStamp(); timestamp = NextTimeStamp();
if (filledlist) if (list)
glDeleteLists (filledlist, 1); glDeleteLists (list, 1);
filledlist = glGenLists (1); list = glGenLists (1);
glNewList (filledlist, GL_COMPILE); glNewList (list, GL_COMPILE);
#ifdef STLGEOM #ifdef STLGEOM
@ -967,6 +938,14 @@ namespace netgen
else else
glDisable (GL_COLOR_MATERIAL); 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 matcol[] = { 0, 1, 0, 1 };
GLfloat matcolsel[] = { 1, 0, 0, 1 }; GLfloat matcolsel[] = { 1, 0, 0, 1 };
@ -976,7 +955,7 @@ namespace netgen
CurvedElements & curv = mesh->GetCurvedElements(); CurvedElements & curv = mesh->GetCurvedElements();
int hoplotn = 1 << vispar.subdivisions; int hoplotn = 1 << subdivisions;
Array<SurfaceElementIndex> seia; Array<SurfaceElementIndex> seia;
@ -993,10 +972,13 @@ namespace netgen
for (auto i : Range(4)) for (auto i : Range(4))
matcol[i] = mesh->GetFaceDescriptor(faceindex).SurfColour()[i]; matcol[i] = mesh->GetFaceDescriptor(faceindex).SurfColour()[i];
if(!build_select)
{
if (faceindex == selface) if (faceindex == selface)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsel); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsel);
else else
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol);
}
static Point<3> xa[129]; static Point<3> xa[129];
static Vec<3> na[129]; static Vec<3> na[129];
@ -1020,8 +1002,14 @@ namespace netgen
if (!drawel) if (!drawel)
continue; continue;
if (names) if (build_select)
glLoadName (sei+1); {
GLushort r,g,b;
r = (sei+1) % (1<<16);
g = (sei+1) >> 16;
b = 0;
glColor3us(r,g,b);
}
switch (el.GetType()) switch (el.GetType())
{ {
@ -1267,7 +1255,7 @@ namespace netgen
#ifdef PARALLELGL #ifdef PARALLELGL
glFinish(); glFinish();
if (id > 0) if (id > 0)
MyMPI_Send (filledlist, 0, MPI_TAG_VIS); MyMPI_Send (list, 0, MPI_TAG_VIS);
#endif #endif
} }
@ -1335,7 +1323,7 @@ namespace netgen
glLineWidth (1.0f); glLineWidth (1.0f);
int hoplotn = 1 << vispar.subdivisions; int hoplotn = 1 << subdivisions;
// PrintMessage (3, "nse = ", mesh->GetNSE()); // PrintMessage (3, "nse = ", mesh->GetNSE());
for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++)
@ -1621,7 +1609,7 @@ namespace netgen
if (mesh->GetCurvedElements().IsHighOrder()) if (mesh->GetCurvedElements().IsHighOrder())
{ {
int hoplotn = 1 << vispar.subdivisions; int hoplotn = 1 << subdivisions;
// mesh->GetCurvedElements().GetNVisualSubsecs(); // mesh->GetCurvedElements().GetNVisualSubsecs();
Point<3> x; Point<3> x;
@ -1832,7 +1820,7 @@ namespace netgen
else else
glShadeModel (GL_SMOOTH); 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> grid[11][11];
Point<3> fpts[4]; Point<3> fpts[4];
int order = vispar.subdivisions+1; int order = subdivisions+1;
for (int trig = 0; trig < 2; trig++) 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(); // int hoplotn = curv.GetNVisualSubsecs();
const Point3d * facepoint = MeshTopology :: GetVertices (TRIG); const Point3d * facepoint = MeshTopology :: GetVertices (TRIG);
@ -2521,7 +2509,7 @@ namespace netgen
Point<3> grid[11][11]; Point<3> grid[11][11];
Point<3> fpts[4]; Point<3> fpts[4];
int order = vispar.subdivisions+1; int order = subdivisions+1;
for (int quad = 0; quad<6; quad++) for (int quad = 0; quad<6; quad++)
{ {
@ -2672,7 +2660,7 @@ namespace netgen
Point<3> grid[11][11]; Point<3> grid[11][11];
Point<3> fpts[4]; Point<3> fpts[4];
int order = vispar.subdivisions+1; int order = subdivisions+1;
for (int trig = 0; trig < 4; trig++) for (int trig = 0; trig < 4; trig++)
{ {
@ -3097,28 +3085,105 @@ namespace netgen
bool VisualSceneMesh :: SelectSurfaceElement (int px, int py, Point<3> &p, bool select_on_clipping_plane)
bool VisualSceneMesh :: Unproject (int px, int py, Point<3> &p)
{ {
selelement = -1;
marker = nullopt;
shared_ptr<Mesh> mesh = GetMesh(); shared_ptr<Mesh> 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);
}
glGenFramebuffers(1, &select.framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, select.framebuffer);
// 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]);
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]);
// 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); BuildFilledList (true);
marker = nullopt; glEnable(GL_DEPTH_TEST);
MouseDblClickSelect(px,py,clipplane,backcolor,transformationmat,center,rad, glClearColor(0, 0, 0, 1.0);
filledlist,selelement,selface,seledge,selpoint,selpoint2,locpi); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMultMatrixd (transformationmat);
GLdouble /* modelview[16], */ projection[16]; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
GLint viewport[4]; auto hy = select.viewport[3] - py;
GLdouble result[3];
glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); SetClippingPlane();
glGetIntegerv(GL_VIEWPORT, &viewport[0]); 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);
int hy = viewport[3]-py; double xi1mid = (center - p) * t1;
double xi2mid = (center - p) * t2;
GLfloat pz; 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) if(lock)
{ {
@ -3127,47 +3192,78 @@ namespace netgen
lock = NULL; 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); 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) ngcore::INT<2> VisualSceneMesh :: Project(Point<3> p)
return false; {
if(pz<=0.0) Point<3> pwin;
return false; gluProject(p[0], p[1], p[2], transformationmat, select.projmat, select.viewport,
&pwin[0], &pwin[1], &pwin[2]);
// cout << "pz = " << pz << endl; return ngcore::INT<2>(pwin[0]+0.5, select.viewport[3]-pwin[1]+0.5);
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;
} }
void VisualSceneMesh :: MouseDblClick (int px, int py) void VisualSceneMesh :: MouseDblClick (int px, int py)
{ {
Point<3> p; 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); const Element2d & sel = GetMesh()->SurfaceElement(selelement);
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 cout << "select element " << selelement
<< " on face " << sel.GetIndex() << endl; << " on face " << sel.GetIndex() << endl;
cout << "Nodes: "; cout << "Nodes: ";
for (int i = 1; i <= sel.GetNP(); i++) for (int i = 1; i <= sel.GetNP(); i++)
cout << sel.PNum(i) << " "; cout << sel.PNum(i) << " ";
cout << endl; cout << endl;
cout << "selected point " << selpoint
<< ", pos = " << GetMesh()->Point (selpoint)
<< endl;
cout << "seledge = " << seledge << 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) if(found_point)
{ {
@ -3179,353 +3275,21 @@ namespace netgen
} }
} }
selecttimestamp = NextTimeStamp();
if(lock) if(lock)
{ {
lock->UnLock(); lock->UnLock();
delete lock; delete lock;
lock = NULL; 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) void VisualSceneMesh :: SetSelectedFace (int asf)
{ {
if(selface != asf)
filledlist = 0;
selface = asf; selface = asf;
selecttimestamp = NextTimeStamp();
} }

View File

@ -4806,8 +4806,15 @@ namespace netgen
} }
}; };
// Check if clipping plane is drawn at current mouse cursor position Point<3> p;
if(dim==3 && clipsolution && vispar.clipping.enable) bool found_point = vsmesh.SelectSurfaceElement(px, py, p, showclipsolution && clipsolution);
if(!found_point)
return;
// marker = p;
// found point on clipping plane
if(selelement==0)
{ {
GLint viewport[4]; GLint viewport[4];
GLdouble projection[16]; GLdouble projection[16];
@ -4815,33 +4822,26 @@ namespace netgen
glGetIntegerv(GL_VIEWPORT, &viewport[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; Point<3> eye;
gluUnProject( (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2, gluUnProject( (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2,
0.0, transformationmat, projection, viewport, &eye[0], &eye[1], &eye[2]); 0.0, transformationmat, projection, viewport, &eye[0], &eye[1], &eye[2]);
Vec<3> n{vispar.clipping.normal}; Vec<3> n{vispar.clipping.normal};
n.Normalize(); n.Normalize();
Vec<3> view = p_clipping_plane-eye; Vec<3> view = p-eye;
// check if we look at the clipping plane from the right direction // check if we look at the clipping plane from the right direction
if(n*view > 1e-8) if(n*view > 1e-8)
{ {
double lam = vispar.clipping.dist - Vec<3>{eye}*n; double lam = vispar.clipping.dist - Vec<3>{eye}*n;
lam /= n*view; lam /= n*view;
p_clipping_plane = eye + lam*view; p = eye + lam*view;
double lami[3]; double lami[3];
if(auto el3d = mesh->GetElementOfPoint( p_clipping_plane, lami )) if(auto el3d = mesh->GetElementOfPoint( p, lami ))
{ {
cout << endl << "Selected point " << p_clipping_plane << " on clipping plane" << endl; cout << endl << "Selected point " << p << " on clipping plane" << endl;
marker = p_clipping_plane; // marker = p;
bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_volume; bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_volume;
bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_volume; bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_volume;
@ -4875,22 +4875,10 @@ namespace netgen
} }
} }
// no point on clipping plane found -> continue searching for surface element
Point<3> p;
bool found_point = vsmesh.Unproject(px, py, p);
if(!found_point)
return;
marker = p;
if(selelement<=0)
return;
double lami[3] = {0.0, 0.0, 0.0}; 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) // Check if unprojected Point is close to surface element (eps of 1e-3 due to z-Buffer accuracy)
bool found_2del = false; 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 // Found it, use coordinates of point projected to surface element
mesh->GetCurvedElements().CalcSurfaceTransformation({1.0-lami[0]-lami[1], lami[0]}, selelement-1, p); mesh->GetCurvedElements().CalcSurfaceTransformation({1.0-lami[0]-lami[1], lami[0]}, selelement-1, p);

View File

@ -94,7 +94,6 @@ class NGGUI_API VisualSceneSolution : public VisualScene
int fieldlinestimestamp, surface_vector_timestamp; int fieldlinestimestamp, surface_vector_timestamp;
int pointcurve_timestamp; int pointcurve_timestamp;
int isosurface_timestamp; int isosurface_timestamp;
int subdivision_timestamp;
int timetimestamp; int timetimestamp;
double minval, maxval; double minval, maxval;
@ -174,7 +173,6 @@ public:
int autoscale, logscale; int autoscale, logscale;
double mminval, mmaxval; double mminval, mmaxval;
int numisolines; int numisolines;
int subdivisions;
bool showclipsolution; bool showclipsolution;
bool showsurfacesolution; bool showsurfacesolution;