Use a texture to store face colors

-> Much faster highlighting of selected face (just rebuild the texture)
This commit is contained in:
Matthias Hochsteger 2023-03-31 11:20:24 +02:00
parent 832c17c834
commit 5d0c61b10f
2 changed files with 75 additions and 43 deletions

View File

@ -156,6 +156,13 @@ namespace netgen
int identifiedtimestamp = -1; int identifiedtimestamp = -1;
int domainsurftimestamp = -1; int domainsurftimestamp = -1;
struct {
unsigned texture = -1;
int width = 0;
int height = 0;
int size = 0;
} colors;
struct { struct {
unsigned framebuffer = 0; unsigned framebuffer = 0;
unsigned render_buffers[2]; unsigned render_buffers[2];
@ -214,6 +221,7 @@ namespace netgen
NGGUI_API int SelectedPoint () const NGGUI_API int SelectedPoint () const
{ return selpoint; } { return selpoint; }
void BuildFilledList (bool select); void BuildFilledList (bool select);
void BuildColorTexture();
// private: // private:
void BuildLineList(); void BuildLineList();
void BuildEdgeList(); void BuildEdgeList();

View File

@ -185,8 +185,7 @@ namespace netgen
glPolygonOffset (1, 1); glPolygonOffset (1, 1);
glEnable (GL_POLYGON_OFFSET_LINE); glEnable (GL_POLYGON_OFFSET_LINE);
if (linetimestamp < mesh->GetTimeStamp ()) BuildLineList ();
BuildLineList ();
#ifdef PARALLELGL #ifdef PARALLELGL
if (ntasks > 1 && vispar.drawtetsdomain > 0 && vispar.drawtetsdomain < ntasks) if (ntasks > 1 && vispar.drawtetsdomain > 0 && vispar.drawtetsdomain < ntasks)
@ -848,6 +847,33 @@ namespace netgen
void VisualSceneMesh :: BuildColorTexture ()
{
shared_ptr<Mesh> mesh = GetMesh();
if(colors.texture == -1)
glGenTextures(1, &colors.texture);
// build color texture
glBindTexture(GL_TEXTURE_2D, colors.texture);
Array<float> data;
for(auto fdi : Range(1, mesh->GetNFD()+1))
{
auto c = mesh->GetFaceDescriptor(fdi).SurfColour();
ArrayMem<float, 4> cf{float(c[0]), float(c[1]), float(c[2]), float(c[3])};
if(fdi==selface)
cf = {1.0f, 0.0f, 0.0f, 1.0f};
data.Append(cf);
}
int n = data.Size()/4;
colors.width = min2(n, 1024);
colors.height = (n+colors.width-1)/colors.width;
for(auto i: Range(n, colors.width*colors.height))
data.Append({0.0f, 0.0f, 0.0f, 0.0f});
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, colors.width, colors.height, 0, GL_RGBA, GL_FLOAT, data.Data());
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
void VisualSceneMesh :: BuildFilledList (bool build_select) void VisualSceneMesh :: BuildFilledList (bool build_select)
{ {
@ -898,12 +924,16 @@ namespace netgen
timestamp = NextTimeStamp(); timestamp = NextTimeStamp();
if(!build_select && !vispar.colormeshsize && colors.texture==-1)
BuildColorTexture();
if (list) if (list)
glDeleteLists (list, 1); glDeleteLists (list, 1);
list = glGenLists (1); list = glGenLists (1);
glNewList (list, GL_COMPILE); glNewList (list, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, colors.texture);
#ifdef STLGEOM #ifdef STLGEOM
STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry); STLGeometry * stlgeometry = dynamic_cast<STLGeometry*> (ng_geometry);
@ -935,17 +965,21 @@ namespace netgen
maxh = 10; maxh = 10;
} }
} }
else else if (build_select)
glDisable (GL_COLOR_MATERIAL);
if(build_select)
{ {
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glDisable(GL_FOG); glDisable(GL_FOG);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glDisable (GL_COLOR_MATERIAL); glDisable (GL_COLOR_MATERIAL);
} }
else
{
glDisable(GL_TEXTURE_1D);
glEnable(GL_TEXTURE_2D);
glEnable (GL_COLOR_MATERIAL);
glBindTexture(GL_TEXTURE_2D, colors.texture);
}
GLfloat matcol[] = { 0, 1, 0, 1 }; GLfloat matcol[] = { 0, 1, 0, 1 };
GLfloat matcolsel[] = { 1, 0, 0, 1 }; GLfloat matcolsel[] = { 1, 0, 0, 1 };
@ -964,20 +998,12 @@ namespace netgen
{ {
mesh->GetSurfaceElementsOfFace (faceindex, seia); mesh->GetSurfaceElementsOfFace (faceindex, seia);
// Philippose - 06/07/2009 if(!build_select && !vispar.colormeshsize)
// Modified the colour system to integrate the face colours into
// the mesh data structure, rather than limit it to the OCC geometry
// structure... allows other geometry types to use face colours too
for (auto i : Range(4))
matcol[i] = mesh->GetFaceDescriptor(faceindex).SurfColour()[i];
if(!build_select)
{ {
if (faceindex == selface) int i = faceindex-1;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsel); float x = (0.5+i%colors.width)/colors.width;
else float y = (0.5+i/colors.width)/colors.height;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol); glTexCoord2f(x,y);
} }
static Point<3> xa[129]; static Point<3> xa[129];
@ -1249,6 +1275,7 @@ namespace netgen
glLoadName (0); glLoadName (0);
glBindTexture(GL_TEXTURE_2D, 0);
glEndList (); glEndList ();
@ -1263,6 +1290,8 @@ namespace netgen
void VisualSceneMesh :: BuildLineList() void VisualSceneMesh :: BuildLineList()
{ {
shared_ptr<Mesh> mesh = GetMesh(); shared_ptr<Mesh> mesh = GetMesh();
if (linetimestamp > max(mesh->GetTimeStamp (), subdivision_timestamp))
return;
static int timer = NgProfiler::CreateTimer ("Mesh::BuildLineList"); static int timer = NgProfiler::CreateTimer ("Mesh::BuildLineList");
NgProfiler::RegionTimer reg (timer); NgProfiler::RegionTimer reg (timer);
@ -1552,7 +1581,7 @@ namespace netgen
lock -> Lock(); lock -> Lock();
} }
if (edgetimestamp > mesh->GetTimeStamp () && vispar.drawtetsdomain == 0 if (edgetimestamp > max(mesh->GetTimeStamp(), subdivision_timestamp) && vispar.drawtetsdomain == 0
&& vispar.shrink == 1) && vispar.shrink == 1)
return; return;
@ -3220,11 +3249,11 @@ namespace netgen
{ {
Point<3> p; Point<3> p;
bool found_point = SelectSurfaceElement(px, py, p, false); bool found_point = SelectSurfaceElement(px, py, p, false);
int sel_face = 0;
if(selelement>0) if(selelement>0)
{ {
const Element2d & sel = GetMesh()->SurfaceElement(selelement); const Element2d & sel = GetMesh()->SurfaceElement(selelement);
SetSelectedFace(sel.GetIndex());
auto pi_nearest = sel[0]; auto pi_nearest = sel[0];
double min_dist = 1e99; double min_dist = 1e99;
@ -3235,45 +3264,38 @@ namespace netgen
pi_nearest = pi; pi_nearest = pi;
} }
auto p_win = Project(GetMesh()->Point(pi_nearest)); auto p_win = Project(GetMesh()->Point(pi_nearest));
cout << endl;
if(abs(p_win[0]-px) < 5 && abs(p_win[1]-py) < 5) if(abs(p_win[0]-px) < 5 && abs(p_win[1]-py) < 5)
{ {
cout << "select point " << pi_nearest << endl;
marker = GetMesh()->Point(pi_nearest); marker = GetMesh()->Point(pi_nearest);
sel_face = sel.GetIndex(); selpoint = pi_nearest;
cout << "select point " << pi_nearest << " at " << *marker << endl;
locpi = -2; locpi = -2;
} }
else else
{ {
if(locpi < 0) if(locpi < 0)
{ {
cout << "select element " << selelement cout << endl << "select element " << selelement
<< " on face " << sel.GetIndex() << endl; << " on face " << sel.GetIndex() << endl;
cout << "Nodes: "; cout << "\tpoint: " << p << endl;;
cout << "\tnodes: ";
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;
} }
else { else {
auto pi = sel[locpi%sel.GetNP()]; auto pi = sel[locpi%sel.GetNP()];
auto p = GetMesh()->Points()[pi]; marker = GetMesh()->Points()[pi];
marker = p; cout << "select point " << pi << " at " << *marker << endl;
cout << "selected point " << pi << endl;
} }
} }
} }
SetSelectedFace(sel_face); if(found_point && user_me_handler)
{
if(found_point) if (selelement != -1)
{ user_me_handler -> DblClick (selelement-1, p[0], p[1], p[2]);
cout << "point : " << p << endl; }
if (user_me_handler)
{
if (selelement != -1)
user_me_handler -> DblClick (selelement-1, p[0], p[1], p[2]);
}
}
if(lock) if(lock)
{ {
@ -3288,8 +3310,10 @@ namespace netgen
void VisualSceneMesh :: SetSelectedFace (int asf) void VisualSceneMesh :: SetSelectedFace (int asf)
{ {
if(selface != asf) if(selface != asf)
filledlist = 0; {
selface = asf; selface = asf;
BuildColorTexture();
}
} }