From 0dde1a38568f1eb23135206f7c0caaab9ed8559e Mon Sep 17 00:00:00 2001 From: termi-official Date: Fri, 8 Oct 2021 03:45:48 +0200 Subject: [PATCH 01/21] 3D works. --- lib/vssolution3d.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 6d7ad3a7..00a6799f 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1383,6 +1383,23 @@ void VisualizationSceneSolution3d::PrepareFlat() Array vertices; double p[4][3], c[4]; + gl3::GlBuilder poly = disp_buf.createBuilder(); + + // 1D elements must be rendered a bit thicker + double ThicknessFactor = 10.0; + double MS_Thickness = 7.0; + double LineWidth; + if (GetMultisample() > 0) + { + LineWidth = GetLineWidthMS(); + SetLineWidthMS(MS_Thickness); + } + else + { + LineWidth = GetLineWidth(); + SetLineWidth(ThicknessFactor*LineWidth); + } + for (i = 0; i < ne; i++) { if (dim == 3) @@ -1431,21 +1448,49 @@ void VisualizationSceneSolution3d::PrepareFlat() { DrawTriangle(disp_buf, p, c, minv, maxv); } - else + else if (j == 4) { DrawQuad(disp_buf, p, c, minv, maxv); } + else if(j == 2) + { + poly.glBegin(GL_LINES); + for(int k=0;kGetVertex(vertices[k])); + } + poly.glEnd(); + } + } + + if (GetMultisample() > 0) + { + SetLineWidthMS(LineWidth); } + else + { + SetLineWidth(LineWidth); + } + updated_bufs.emplace_back(&disp_buf); } void VisualizationSceneSolution3d::PrepareFlat2() { + const int dim = mesh->Dimension(); + + if(dim == 1) + { + std::cout << "Not supported for 1D meshes. Falling back to PrepareFlat()." << std::endl; + PrepareFlat(); + return; + } + int i, k, fn, fo, di, have_normals; double bbox_diam, vmin, vmax; disp_buf.clear(); - int dim = mesh->Dimension(); int nbe = (dim == 3) ? mesh->GetNBE() : mesh->GetNE(); DenseMatrix pointmat, normals; Vector values, normal; @@ -1607,6 +1652,21 @@ void VisualizationSceneSolution3d::Prepare() disp_buf.clear(); gl3::GlBuilder poly = disp_buf.createBuilder(); + // 1D elements must be rendered a bit thicker + double ThicknessFactor = 10.0; + double MS_Thickness = 7.0; + double LineWidth; + if (GetMultisample() > 0) + { + LineWidth = GetLineWidthMS(); + SetLineWidthMS(MS_Thickness); + } + else + { + LineWidth = GetLineWidth(); + SetLineWidth(ThicknessFactor*LineWidth); + } + int dim = mesh->Dimension(); int ne = (dim == 3) ? mesh->GetNBE() : mesh->GetNE(); int nv = mesh -> GetNV(); @@ -1734,10 +1794,27 @@ void VisualizationSceneSolution3d::Prepare() case Element::QUADRILATERAL: elemType = GL_QUADS; break; + case Element::SEGMENT: + elemType = GL_LINES; + break; default: MFEM_ABORT("Invalid boundary element type"); break; } + + if(elemType == GL_LINES) + { + poly.glBegin(GL_LINES); + + MySetColor(poly, (*sol)(vertices[0]), minv, maxv); + poly.glVertex3dv(mesh->GetVertex(vertices[0])); + + MySetColor(poly, (*sol)(vertices[1]), minv, maxv); + poly.glVertex3dv(mesh->GetVertex(vertices[1])); + + poly.glEnd(); + continue; + } poly.glBegin(elemType); if (dim == 3) { @@ -1757,6 +1834,16 @@ void VisualizationSceneSolution3d::Prepare() poly.glEnd(); } } + + if (GetMultisample() > 0) + { + SetLineWidthMS(LineWidth); + } + else + { + SetLineWidth(LineWidth); + } + updated_bufs.emplace_back(&disp_buf); } From e5b11f614208ee1c8a1e599470c95d6e37746cec Mon Sep 17 00:00:00 2001 From: termi-official Date: Fri, 8 Oct 2021 04:14:19 +0200 Subject: [PATCH 02/21] Add first try on 1d elements in 2d. --- lib/vssolution.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 90840b3e..9806f0a5 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1122,6 +1122,8 @@ void VisualizationSceneSolution::PrepareFlat() Array vertices; double pts[4][3], col[4]; + gl3::GlBuilder poly = disp_buf.createBuilder(); + for (i = 0; i < ne; i++) { if (!el_attr_to_show[mesh->GetAttribute(i)-1]) { continue; } @@ -1139,10 +1141,21 @@ void VisualizationSceneSolution::PrepareFlat() { DrawTriangle(disp_buf, pts, col, minv, maxv); } - else + else if (j == 4) { DrawQuad(disp_buf, pts, col, minv, maxv); } + else if(j == 2) + { + poly.glBegin(GL_LINES); + for(int k=0;kGetVertex(vertices[k]); + poly.glVertex3d(v[0], v[1], 0.0); + } + poly.glEnd(); + } } updated_bufs.emplace_back(&disp_buf); } @@ -1156,8 +1169,12 @@ const int split_quads = 1; void VisualizationSceneSolution::PrepareFlat2() { + int dim = mesh->Dimension(); + Array vertices; + int i, j, k; disp_buf.clear(); + gl3::GlBuilder poly = disp_buf.createBuilder(); int ne = mesh -> GetNE(); DenseMatrix pointmat, pts3d, normals; Vector values; @@ -1168,6 +1185,27 @@ void VisualizationSceneSolution::PrepareFlat2() { if (!el_attr_to_show[mesh->GetAttribute(i)-1]) { continue; } + if (dim == 1) + { + mesh->GetElementVertices (i, vertices); + + poly.glBegin(GL_QUADS); + + auto v1 = mesh->GetVertex(vertices[0]); + MySetColor(poly, (*sol)(vertices[0]), minv, maxv); + poly.glVertex3d(v1[0], v1[1], 0.0); + poly.glVertex3d(v1[0], v1[1], LogVal((*sol)(vertices[0]))); + + auto v2 = mesh->GetVertex(vertices[1]); + MySetColor(poly, (*sol)(vertices[1]), minv, maxv); + poly.glVertex3d(v2[0], v2[1], LogVal((*sol)(vertices[1]))); + poly.glVertex3d(v2[0], v2[1], 0.0); + + poly.glEnd(); + + continue; + } + RefG = GLVisGeometryRefiner.Refine(mesh->GetElementBaseGeometry(i), TimesToRefine, EdgeRefineFactor); j = GetRefinedValuesAndNormals(i, RefG->RefPts, values, pointmat, @@ -1258,6 +1296,8 @@ void VisualizationSceneSolution::PrepareFlat2() void VisualizationSceneSolution::Prepare() { + const int dim = mesh->Dimension(); + palette.SetUseLogscale(0); switch (shading) @@ -1269,7 +1309,7 @@ void VisualizationSceneSolution::Prepare() PrepareFlat2(); return; default: - if (v_normals) + if (v_normals && dim > 1) { PrepareWithNormals(); return; @@ -1301,8 +1341,30 @@ void VisualizationSceneSolution::Prepare() nz = 0.; for (i = 0; i < ne; i++) + { if (mesh -> GetAttribute(i) == mesh -> attributes[d]) { + if (dim == 1) + { + mesh->GetElementVertices (i, vertices); + + poly.glBegin(GL_LINE_LOOP); + + auto v1 = mesh->GetVertex(vertices[0]); + MySetColor(poly, (*sol)(vertices[0]), minv, maxv); + poly.glVertex3d(v1[0], v1[1], 0.0); + poly.glVertex3d(v1[0], v1[1], LogVal((*sol)(vertices[0]))); + + auto v2 = mesh->GetVertex(vertices[1]); + MySetColor(poly, (*sol)(vertices[1]), minv, maxv); + poly.glVertex3d(v2[0], v2[1], LogVal((*sol)(vertices[1]))); + poly.glVertex3d(v2[0], v2[1], 0.0); + + poly.glEnd(); + + continue; + } + mesh->GetPointMatrix (i, pointmat); mesh->GetElementVertices (i, vertices); @@ -1330,8 +1392,9 @@ void VisualizationSceneSolution::Prepare() nz(vertices[j]) += nor[2]; } } + } - for (i = 0; i < ne; i++) + for (i = 0; i < ne && (dim > 1); i++) { if (mesh -> GetAttribute(i) == mesh -> attributes[d]) { From ad5bc2748ad68c67301b3ee41234690ae0d5548f Mon Sep 17 00:00:00 2001 From: termi-official Date: Fri, 8 Oct 2021 04:25:31 +0200 Subject: [PATCH 03/21] Fix some issues with 2D rendering. --- lib/vssolution.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 9806f0a5..cc0140bf 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1464,6 +1464,12 @@ void VisualizationSceneSolution::DrawLevelCurves( gl3::GlBuilder& builder, Array &RG, DenseMatrix &pointmat, Vector &values, int sides, Array &lvl, int flat) { + const int dim = mesh->Dimension(); + if (dim == 1) // Unimplemented. + { + return; + } + double point[4][4]; // double zc = 0.5*(z[0]+z[1]); double zc = z[1]; @@ -1983,6 +1989,12 @@ void VisualizationSceneSolution::UpdateValueRange(bool prepare) void VisualizationSceneSolution::PrepareBoundary() { + const int dim = mesh->Dimension(); + if (dim == 1) // Unimplemented. + { + return; + } + int i, j, ne = mesh->GetNBE(); Array vertices; DenseMatrix pointmat; From 493d5cb7f9bff87e389efdcc6f6e793a59ed68d8 Mon Sep 17 00:00:00 2001 From: Dennis Ogiermann Date: Sat, 23 Oct 2021 15:14:06 +0200 Subject: [PATCH 04/21] Fix crash in 2D. --- lib/vssolution.cpp | 49 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index cc0140bf..69f86437 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -544,7 +544,16 @@ void VisualizationSceneSolution::ToggleDrawElems() drawelems = (drawelems + 6) % 7; - cout << "Surface elements mode : " << modes[drawelems] << endl; + const int dim = mesh->Dimension(); + if (dim == 1) + { + cout << "Element mode : " << modes[drawelems] << endl; + } + else + { + cout << "Surface elements mode : " << modes[drawelems] << endl; + } + if (drawelems < 2) { extra_caption.clear(); @@ -600,8 +609,9 @@ void VisualizationSceneSolution::NewMeshAndSolution( void VisualizationSceneSolution::GetRefinedDetJ( int i, const IntegrationRule &ir, Vector &vals, DenseMatrix &tr) { - int geom = mesh->GetElementBaseGeometry(i); + const int geom = mesh->GetElementBaseGeometry(i); ElementTransformation *T = mesh->GetElementTransformation(i); + const int dim = T->GetDimension(); double Jd[4]; DenseMatrix J(Jd, 2, 2); @@ -618,15 +628,38 @@ void VisualizationSceneSolution::GetRefinedDetJ( } else if (drawelems >= 4) { - vals(j) = J.Det(); - // if (vals(j) >= 0.0) - // vals(j) = sqrt(vals(j)); - // else - // vals(j) = -sqrt(-vals(j)); + if (dim == 2) + { + vals(j) = J.Det(); + } + else if (dim == 1) + { + // Compute det(J J^T) + auto Jdl = J.Data(); + vals(j) = sqrt(Jdl[1]*Jdl[1] + Jdl[2]*Jdl[2]); // Orientation information lost. + } + else + { + std::cout << "unsupported dim " << dim << " in GetRefinedDetJ." << std::endl; + } } else { - vals(j) = J.CalcSingularvalue(0)/J.CalcSingularvalue(1); + if (dim == 2) + { + vals(j) = J.CalcSingularvalue(0)/J.CalcSingularvalue(1); + } + else if (dim == 1) + { + // Compute det(J J^T) + auto Jdl = J.Data(); + vals(j) = sqrt(Jdl[1]*Jdl[1] + Jdl[2]*Jdl[2]); // Orientation information lost. + } + else + { + std::cout << "unsupported dim " << dim << " in GetRefinedDetJ." << std::endl; + } + if (drawelems == 2) { vals(j) = vals(j) + 1.0/vals(j); From 96a3a46dee48b84310ab8876a769110050edcf74 Mon Sep 17 00:00:00 2001 From: Dennis Ogiermann Date: Sat, 23 Oct 2021 16:20:47 +0200 Subject: [PATCH 05/21] Fix crash in 3D. --- lib/vssolution3d.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 00a6799f..5cab0ee9 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1679,6 +1679,7 @@ void VisualizationSceneSolution3d::Prepare() Vector nz(nv); Table ba_to_be; // boundary_attribute--to--boundary_element + if (dim > 1) // Boundaries are just points in 1D { Table be_to_ba; be_to_ba.MakeI(ne); @@ -1708,7 +1709,7 @@ void VisualizationSceneSolution3d::Prepare() const Array &attributes = ((dim == 3) ? mesh->bdr_attributes : mesh->attributes); - for (int d = 0; d < attributes.Size(); d++) + for (int d = 0; d < attributes.Size() && dim > 1; d++) { const int attr = attributes[d]-1; From 228c0e488b83c83cd04d70a088baa166dcf314cf Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 20:40:48 +0200 Subject: [PATCH 06/21] Make rendering of segments in 2D more like rendering of triangles and quads. --- lib/openglvis.cpp | 86 ++++++++++++++++++++++++++--------- lib/vssolution.cpp | 111 +++++++++++++++++---------------------------- 2 files changed, 107 insertions(+), 90 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 24933c8a..9dfaf41d 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -312,6 +312,8 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, const double maxv, const int normals_opt) { gl3::GlBuilder poly = drawable.createBuilder(); + // If we draw lines, then we want to optionally fill the space between the line and the mesh plane. + // gl3::GlBuilder poly_infill = drawable.createBuilder(); double na[3]; if (normals_opt == 1 || normals_opt == -2) @@ -378,46 +380,88 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, } else { - if (n == 3) + if (n == 2) + { + poly.glBegin(GL_LINES); + } + else if (n == 3) { poly.glBegin(GL_TRIANGLES); } - else + else if(n == 4) { poly.glBegin(GL_QUADS); } + else // We should never hit this case + { + mfem_error("VisualizationScene::DrawPatch() : unknown input geometry."); + } for (int i = 0; i < ind.Size(); i += n) { - int j; - if (n == 3) - j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), - &pts(0, ind[i+2]), na); - else - j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), - &pts(0, ind[i+2]), &pts(0, ind[i+3]), na); - if (j == 0) + if (n == 2) // Lines { - if (normals_opt == 0) + const auto pt0 = pts(0, ind[i+0]); + const auto pt1 = pts(1, ind[i+1]); + const auto pt2 = pts(0, ind[i+0]); + const auto pt3 = pts(1, ind[i+1]); + + // Draw solution line + MySetColor(poly, vals(ind[i+0]), minv, maxv); + poly.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), pts(2, ind[i+0])); + MySetColor(poly, vals(ind[i+1]), minv, maxv); + poly.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), pts(2, ind[i+1])); + + // Fill space between mesh and solution line + // MySetColor(poly_infill, vals(ind[i+0]), minv, maxv); + // poly_infill.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), 0.0); + // MySetColor(poly_infill, vals(ind[i+0]), minv, maxv); + // poly_infill.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), pts(2, ind[i+0])); + // MySetColor(poly_infill, vals(ind[i+1]), minv, maxv); + // poly_infill.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), pts(2, ind[i+1])); + // MySetColor(poly_infill, vals(ind[i+1]), minv, maxv); + // poly_infill.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), 0.0); + } + else // Quads and triangles + { + int j; + if (n == 3) { - poly.glNormal3dv(na); - for ( ; j < n; j++) - { - MySetColor(poly, vals(ind[i+j]), minv, maxv); - poly.glVertex3dv(&pts(0, ind[i+j])); - } + j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), + &pts(0, ind[i+2]), na); } else { - poly.glNormal3d(-na[0], -na[1], -na[2]); - for (j = n-1; j >= 0; j--) + j = Compute3DUnitNormal(&pts(0, ind[i]), &pts(0, ind[i+1]), + &pts(0, ind[i+2]), &pts(0, ind[i+3]), na); + } + if (j == 0) + { + if (normals_opt == 0) + { + poly.glNormal3dv(na); + for ( ; j < n; j++) + { + MySetColor(poly, vals(ind[i+j]), minv, maxv); + poly.glVertex3dv(&pts(0, ind[i+j])); + } + } + else { - MySetColor(poly, vals(ind[i+j]), minv, maxv); - poly.glVertex3dv(&pts(0, ind[i+j])); + poly.glNormal3d(-na[0], -na[1], -na[2]); + for (j = n-1; j >= 0; j--) + { + MySetColor(poly, vals(ind[i+j]), minv, maxv); + poly.glVertex3dv(&pts(0, ind[i+j])); + } } } } } poly.glEnd(); + // if (n == 2) + // { + // poly_fill.glEnd(); + // } } } diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 84cc00a9..53fe6de1 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -720,17 +720,23 @@ int VisualizationSceneSolution::GetRefinedValuesAndNormals( { int have_normals = 0; + const int dim = mesh->Dimension(); + if (drawelems < 2) { - rsol->GetGradients(i, ir, tr); - normals.SetSize(3, tr.Width()); - for (int j = 0; j < tr.Width(); j++) + // In 1D we do not have well-defined normals. + if(dim > 1) { - normals(0, j) = -tr(0, j); - normals(1, j) = -tr(1, j); - normals(2, j) = 1.; + rsol->GetGradients(i, ir, tr); + normals.SetSize(3, tr.Width()); + for (int j = 0; j < tr.Width(); j++) + { + normals(0, j) = -tr(0, j); + normals(1, j) = -tr(1, j); + normals(2, j) = 1.; + } + have_normals = 1; } - have_normals = 1; rsol->GetValues(i, ir, vals, tr); } else @@ -1233,40 +1239,39 @@ void VisualizationSceneSolution::PrepareWithNormals() void VisualizationSceneSolution::PrepareFlat() { - int i, j; disp_buf.clear(); - int ne = mesh -> GetNE(); + const int ne = mesh -> GetNE(); DenseMatrix pointmat; Array vertices; double pts[4][3], col[4]; gl3::GlBuilder poly = disp_buf.createBuilder(); - for (i = 0; i < ne; i++) + for (int i = 0; i < ne; i++) { if (!el_attr_to_show[mesh->GetAttribute(i)-1]) { continue; } mesh->GetPointMatrix (i, pointmat); mesh->GetElementVertices (i, vertices); - for (j = 0; j < pointmat.Width(); j++) + for (int j = 0; j < pointmat.Width(); j++) { pts[j][0] = pointmat(0, j); pts[j][1] = pointmat(1, j); pts[j][2] = col[j] = LogVal((*sol)(vertices[j])); } - if (j == 3) + if (pointmat.Width() == 3) { DrawTriangle(disp_buf, pts, col, minv, maxv); } - else if (j == 4) + else if (pointmat.Width() == 4) { DrawQuad(disp_buf, pts, col, minv, maxv); } - else if(j == 2) + else if(pointmat.Width() == 2) { poly.glBegin(GL_LINES); - for(int k=0;kGetVertex(vertices[k]); @@ -1287,12 +1292,11 @@ const int split_quads = 1; void VisualizationSceneSolution::PrepareFlat2() { - int dim = mesh->Dimension(); + const int dim = mesh->Dimension(); Array vertices; int i, j, k; disp_buf.clear(); - gl3::GlBuilder poly = disp_buf.createBuilder(); int ne = mesh -> GetNE(); DenseMatrix pointmat, pts3d, normals; Vector values; @@ -1303,27 +1307,6 @@ void VisualizationSceneSolution::PrepareFlat2() { if (!el_attr_to_show[mesh->GetAttribute(i)-1]) { continue; } - if (dim == 1) - { - mesh->GetElementVertices (i, vertices); - - poly.glBegin(GL_QUADS); - - auto v1 = mesh->GetVertex(vertices[0]); - MySetColor(poly, (*sol)(vertices[0]), minv, maxv); - poly.glVertex3d(v1[0], v1[1], 0.0); - poly.glVertex3d(v1[0], v1[1], LogVal((*sol)(vertices[0]))); - - auto v2 = mesh->GetVertex(vertices[1]); - MySetColor(poly, (*sol)(vertices[1]), minv, maxv); - poly.glVertex3d(v2[0], v2[1], LogVal((*sol)(vertices[1]))); - poly.glVertex3d(v2[0], v2[1], 0.0); - - poly.glEnd(); - - continue; - } - RefG = GLVisGeometryRefiner.Refine(mesh->GetElementBaseGeometry(i), TimesToRefine, EdgeRefineFactor); j = GetRefinedValuesAndNormals(i, RefG->RefPts, values, pointmat, @@ -1435,8 +1418,6 @@ void VisualizationSceneSolution::Prepare() break; } - int i, j; - disp_buf.clear(); gl3::GlBuilder poly = disp_buf.createBuilder(); int ne = mesh -> GetNE(); @@ -1449,70 +1430,56 @@ void VisualizationSceneSolution::Prepare() Vector ny(nv); Vector nz(nv); + // For triangles and quads: Compute the normal. + // For segments: Fill render buffer. for (int d = 0; d < mesh -> attributes.Size(); d++) { - if (!el_attr_to_show[mesh -> attributes[d]-1]) { continue; } nx = 0.; ny = 0.; nz = 0.; - for (i = 0; i < ne; i++) + // Compute normals + for (int i = 0; i < ne && (dim > 1); i++) { if (mesh -> GetAttribute(i) == mesh -> attributes[d]) { - if (dim == 1) - { - mesh->GetElementVertices (i, vertices); - - poly.glBegin(GL_LINE_LOOP); - - auto v1 = mesh->GetVertex(vertices[0]); - MySetColor(poly, (*sol)(vertices[0]), minv, maxv); - poly.glVertex3d(v1[0], v1[1], 0.0); - poly.glVertex3d(v1[0], v1[1], LogVal((*sol)(vertices[0]))); - - auto v2 = mesh->GetVertex(vertices[1]); - MySetColor(poly, (*sol)(vertices[1]), minv, maxv); - poly.glVertex3d(v2[0], v2[1], LogVal((*sol)(vertices[1]))); - poly.glVertex3d(v2[0], v2[1], 0.0); - - poly.glEnd(); - - continue; - } - mesh->GetPointMatrix (i, pointmat); mesh->GetElementVertices (i, vertices); - for (j = 0; j < pointmat.Size(); j++) + for (int j = 0; j < pointmat.Size(); j++) { p[j][0] = pointmat(0, j); p[j][1] = pointmat(1, j); p[j][2] = LogVal((*sol)(vertices[j])); } + int normal_state; if (pointmat.Width() == 3) { - j = Compute3DUnitNormal(p[0], p[1], p[2], nor); + normal_state = Compute3DUnitNormal(p[0], p[1], p[2], nor); } else { - j = Compute3DUnitNormal(p[0], p[1], p[2], p[3], nor); + normal_state = Compute3DUnitNormal(p[0], p[1], p[2], p[3], nor); } - if (j == 0) - for (j = 0; j < pointmat.Size(); j++) + if (normal_state == 0) // Non-degenerate normal + { + for (int j = 0; j < pointmat.Size(); j++) { nx(vertices[j]) += nor[0]; ny(vertices[j]) += nor[1]; nz(vertices[j]) += nor[2]; } + } } } - for (i = 0; i < ne && (dim > 1); i++) + // Fill buffers for triangles and quads. We skip this portion for + // segments, because the buffers are already filled. + for (int i = 0; i < ne; i++) { if (mesh -> GetAttribute(i) == mesh -> attributes[d]) { @@ -1525,6 +1492,9 @@ void VisualizationSceneSolution::Prepare() case Element::QUADRILATERAL: shape = GL_QUADS; break; + case Element::SEGMENT: + shape = GL_LINES; + break; default: MFEM_ABORT("Invalid 2D element type"); break; @@ -1919,6 +1889,9 @@ void VisualizationSceneSolution::PrepareVertexNumbering2() void VisualizationSceneSolution::PrepareEdgeNumbering() { + // 1D meshes do not have edges. + if(mesh->Dimension() == 1) return; + f_nums_buf.clear(); DenseMatrix p; From 335bed6988fe3a6ff7ae243742d0b22c2ebc0071 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 20:42:31 +0200 Subject: [PATCH 07/21] Use same line width default everywhere. --- glvis.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glvis.cpp b/glvis.cpp index 1f061947..e85eccce 100644 --- a/glvis.cpp +++ b/glvis.cpp @@ -1152,8 +1152,8 @@ int main (int argc, char *argv[]) const char *font_name = string_default; int portnum = 19916; int multisample = GetMultisample(); - double line_width = 1.0; - double ms_line_width = gl3::LINE_WIDTH_AA; + double line_width = GetLineWidth(); + double ms_line_width = GetLineWidthMS(); int geom_ref_type = Quadrature1D::ClosedUniform; bool legacy_gl_ctx = false; bool enable_hidpi = true; From 57d454616bc40d84aea3eabc6111224efed14c7a Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 20:45:17 +0200 Subject: [PATCH 08/21] Fix typos. --- lib/vssolution.cpp | 2 +- lib/vssolution3d.cpp | 48 -------------------------------------------- 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 53fe6de1..1d6c8b9e 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1503,7 +1503,7 @@ void VisualizationSceneSolution::Prepare() mesh->GetPointMatrix (i, pointmat); mesh->GetElementVertices (i, vertices); - for (j = 0; j < pointmat.Size(); j++) + for (int j = 0; j < pointmat.Size(); j++) { double z = LogVal((*sol)(vertices[j])); MySetColor(poly, z, minv, maxv); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 31ce9e53..47ed8e16 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1431,21 +1431,6 @@ void VisualizationSceneSolution3d::PrepareFlat() gl3::GlBuilder poly = disp_buf.createBuilder(); - // 1D elements must be rendered a bit thicker - double ThicknessFactor = 10.0; - double MS_Thickness = 7.0; - double LineWidth; - if (GetMultisample() > 0) - { - LineWidth = GetLineWidthMS(); - SetLineWidthMS(MS_Thickness); - } - else - { - LineWidth = GetLineWidth(); - SetLineWidth(ThicknessFactor*LineWidth); - } - for (i = 0; i < ne; i++) { if (dim == 3) @@ -1524,15 +1509,6 @@ void VisualizationSceneSolution3d::PrepareFlat() } } - if (GetMultisample() > 0) - { - SetLineWidthMS(LineWidth); - } - else - { - SetLineWidth(LineWidth); - } - updated_bufs.emplace_back(&disp_buf); } @@ -1852,21 +1828,6 @@ void VisualizationSceneSolution3d::Prepare() disp_buf.clear(); gl3::GlBuilder poly = disp_buf.createBuilder(); - // 1D elements must be rendered a bit thicker - double ThicknessFactor = 10.0; - double MS_Thickness = 7.0; - double LineWidth; - if (GetMultisample() > 0) - { - LineWidth = GetLineWidthMS(); - SetLineWidthMS(MS_Thickness); - } - else - { - LineWidth = GetLineWidth(); - SetLineWidth(ThicknessFactor*LineWidth); - } - int dim = mesh->Dimension(); int ne = (dim == 3) ? mesh->GetNBE() : mesh->GetNE(); int nv = mesh -> GetNV(); @@ -2036,15 +1997,6 @@ void VisualizationSceneSolution3d::Prepare() } } - if (GetMultisample() > 0) - { - SetLineWidthMS(LineWidth); - } - else - { - SetLineWidth(LineWidth); - } - updated_bufs.emplace_back(&disp_buf); } From e342339346676ea43aab55b90f38ead3ead76ea7 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 21:16:51 +0200 Subject: [PATCH 09/21] Improve nc rendering of segments in 3D. --- lib/openglvis.cpp | 16 ---------------- lib/vssolution3d.cpp | 45 +++++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 9dfaf41d..79ab698e 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -312,8 +312,6 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, const double maxv, const int normals_opt) { gl3::GlBuilder poly = drawable.createBuilder(); - // If we draw lines, then we want to optionally fill the space between the line and the mesh plane. - // gl3::GlBuilder poly_infill = drawable.createBuilder(); double na[3]; if (normals_opt == 1 || normals_opt == -2) @@ -410,16 +408,6 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, poly.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), pts(2, ind[i+0])); MySetColor(poly, vals(ind[i+1]), minv, maxv); poly.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), pts(2, ind[i+1])); - - // Fill space between mesh and solution line - // MySetColor(poly_infill, vals(ind[i+0]), minv, maxv); - // poly_infill.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), 0.0); - // MySetColor(poly_infill, vals(ind[i+0]), minv, maxv); - // poly_infill.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), pts(2, ind[i+0])); - // MySetColor(poly_infill, vals(ind[i+1]), minv, maxv); - // poly_infill.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), pts(2, ind[i+1])); - // MySetColor(poly_infill, vals(ind[i+1]), minv, maxv); - // poly_infill.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), 0.0); } else // Quads and triangles { @@ -458,10 +446,6 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, } } poly.glEnd(); - // if (n == 2) - // { - // poly_fill.glEnd(); - // } } } diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 47ed8e16..1a4b307a 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1631,14 +1631,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() { const int dim = mesh->Dimension(); - if(dim == 1) - { - std::cout << "Not supported for 1D meshes. Falling back to PrepareFlat()." << std::endl; - PrepareFlat(); - return; - } - - int i, k, fn, fo, di, have_normals; + int i, k, fn, fo, di, have_normals = 0; double bbox_diam, vmin, vmax; disp_buf.clear(); @@ -1665,6 +1658,10 @@ void VisualizationSceneSolution3d::PrepareFlat2() case Element::TRIANGLE: sides = 3; break; + // TODO: can we improve this? It is quite a hack because sides + case Element::SEGMENT: + sides = 0; + break; case Element::QUADRILATERAL: default: @@ -1735,30 +1732,35 @@ void VisualizationSceneSolution3d::PrepareFlat2() CutReferenceElements(TimesToRefine, cut_lambda); cut_updated = true; } - const IntegrationRule &ir = (cut_lambda > 0) ? + const IntegrationRule &ir = (cut_lambda > 0 && dim > 1) ? ((sides == 3) ? cut_TriPts : cut_QuadPts) : RefG->RefPts; GridF->GetValues(i, ir, values, pointmat); - normals.SetSize(3, values.Size()); mesh->GetElementTransformation(i, &T); - for (int j = 0; j < values.Size(); j++) - { - T.SetIntPoint(&ir.IntPoint(j)); - const DenseMatrix &J = T.Jacobian(); - normals.GetColumnReference(j, normal); - CalcOrtho(J, normal); - normal /= normal.Norml2(); - } - have_normals = 1; di = 0; ShrinkPoints(pointmat, i, 0, 0); + + // Compute normals. Skip in 1D. + if(dim > 1) + { + normals.SetSize(3, values.Size()); + for (int j = 0; j < values.Size(); j++) + { + T.SetIntPoint(&ir.IntPoint(j)); + const DenseMatrix &J = T.Jacobian(); + normals.GetColumnReference(j, normal); + CalcOrtho(J, normal); + normal /= normal.Norml2(); + } + have_normals = 1; + } } vmin = fmin(vmin, values.Min()); vmax = fmax(vmax, values.Max()); // compute an average normal direction for the current face - if (sc != 0.0) + if (sc != 0.0 && dim > 1) { for (int j = 0; j < 3; j++) { @@ -1782,7 +1784,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() have_normals = 0; } - have_normals = have_normals ? 2 : 0; + have_normals = have_normals && (dim > 1) ? 2 : 0; if (di) { have_normals = -1 - have_normals; @@ -1795,6 +1797,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() ((sides == 3) ? cut_TriGeoms : cut_QuadGeoms) : RefG->RefGeoms; int psides = (cut_lambda > 0) ? 4 : sides; + if(dim == 1) psides = 2; // Hack to trigger line rendering. DrawPatch(disp_buf, pointmat, values, normals, psides, RefGeoms, minv, maxv, have_normals); } From c338a861df3d78aa2c4c7d0946e6a924483249b9 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 21:33:22 +0200 Subject: [PATCH 10/21] Fixing crash in 3D for segment rendering. --- lib/vssolution3d.cpp | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 1a4b307a..51547213 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1843,7 +1843,6 @@ void VisualizationSceneSolution3d::Prepare() Vector nz(nv); Table ba_to_be; // boundary_attribute--to--boundary_element - if (dim > 1) // Boundaries are just points in 1D { Table be_to_ba; be_to_ba.MakeI(ne); @@ -1873,7 +1872,7 @@ void VisualizationSceneSolution3d::Prepare() const Array &attributes = ((dim == 3) ? mesh->bdr_attributes : mesh->attributes); - for (int d = 0; d < attributes.Size() && dim > 1; d++) + for (int d = 0; d < attributes.Size(); d++) { const int attr = attributes[d]-1; @@ -1892,12 +1891,14 @@ void VisualizationSceneSolution3d::Prepare() { mesh->GetElementVertices(elem[i], vertices); } - for (j = 0; j < vertices.Size(); j++) + for (j = 0; j < vertices.Size() && (dim > 1); j++) { nx(vertices[j]) = ny(vertices[j]) = nz(vertices[j]) = 0.; } } - for (int i = 0; i < nelem; i++) + + // Compute normals. Skip in 1D. + for (int i = 0; i < nelem && (dim > 1); i++) { if (dim == 3) { @@ -1911,18 +1912,24 @@ void VisualizationSceneSolution3d::Prepare() } if (pointmat.Width() == 3) + { j = Compute3DUnitNormal(&pointmat(0,0), &pointmat(0,1), &pointmat(0,2), nor); + } else + { j = Compute3DUnitNormal(&pointmat(0,0), &pointmat(0,1), &pointmat(0,2), &pointmat(0,3), nor); + } if (j == 0) + { for (j = 0; j < pointmat.Size(); j++) { nx(vertices[j]) += nor[0]; ny(vertices[j]) += nor[1]; nz(vertices[j]) += nor[2]; } + } } for (int i = 0; i < nelem; i++) @@ -1967,19 +1974,6 @@ void VisualizationSceneSolution3d::Prepare() break; } - if(elemType == GL_LINES) - { - poly.glBegin(GL_LINES); - - MySetColor(poly, (*sol)(vertices[0]), minv, maxv); - poly.glVertex3dv(mesh->GetVertex(vertices[0])); - - MySetColor(poly, (*sol)(vertices[1]), minv, maxv); - poly.glVertex3dv(mesh->GetVertex(vertices[1])); - - poly.glEnd(); - continue; - } poly.glBegin(elemType); if (dim == 3) { @@ -1993,7 +1987,7 @@ void VisualizationSceneSolution3d::Prepare() for (j = 0; j < pointmat.Size(); j++) { MySetColor(poly, (*sol)(vertices[j]), minv, maxv); - poly.glNormal3d(nx(vertices[j]), ny(vertices[j]), nz(vertices[j])); + if(dim > 1) poly.glNormal3d(nx(vertices[j]), ny(vertices[j]), nz(vertices[j])); poly.glVertex3dv(&pointmat(0, j)); } poly.glEnd(); From e8096f9e3e1c28cb5481caca127f1064d74a593b Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 21:35:20 +0200 Subject: [PATCH 11/21] Fix astyle command being hardcoded. --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 37bb697c..7e636c07 100644 --- a/makefile +++ b/makefile @@ -352,7 +352,7 @@ print-%: $(info ) @true -ASTYLE_BIN = astyle +ASTYLE_BIN ?= astyle ASTYLE = $(ASTYLE_BIN) --options=$(MFEM_DIR)/config/mfem.astylerc ALL_FILES = ./glvis.cpp $(ALL_SOURCE_FILES) $(HEADER_FILES) EXT_FILES = lib/gl2ps.c lib/gl2ps.h From c5d9dee6d3ab099c1273b38eb722d791058cc012 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 21:44:05 +0200 Subject: [PATCH 12/21] Simplify segment rendering. --- lib/openglvis.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 79ab698e..63336f41 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -386,7 +386,7 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, { poly.glBegin(GL_TRIANGLES); } - else if(n == 4) + else if (n == 4) { poly.glBegin(GL_QUADS); } @@ -398,16 +398,12 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, { if (n == 2) // Lines { - const auto pt0 = pts(0, ind[i+0]); - const auto pt1 = pts(1, ind[i+1]); - const auto pt2 = pts(0, ind[i+0]); - const auto pt3 = pts(1, ind[i+1]); - // Draw solution line - MySetColor(poly, vals(ind[i+0]), minv, maxv); - poly.glVertex3d(pts(0, ind[i+0]), pts(1, ind[i+0]), pts(2, ind[i+0])); - MySetColor(poly, vals(ind[i+1]), minv, maxv); - poly.glVertex3d(pts(0, ind[i+1]), pts(1, ind[i+1]), pts(2, ind[i+1])); + for(int j=0; j<2; j++) + { + MySetColor(poly, vals(ind[i+j]), minv, maxv); + poly.glVertex3d(pts(0, ind[i+j]), pts(1, ind[i+j]), pts(2, ind[i+j])); + } } else // Quads and triangles { From 883f2ac70e9bd8d7c67105904f48b129bf06c806 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 21:52:04 +0200 Subject: [PATCH 13/21] Style+warnings. --- lib/gl/attr_traits.hpp | 6 +++--- lib/gl/types.hpp | 8 ++++---- lib/vssolution.cpp | 9 ++++----- lib/vssolution3d.cpp | 12 ++++++------ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/gl/attr_traits.hpp b/lib/gl/attr_traits.hpp index 63fc5089..e8ee4d2e 100644 --- a/lib/gl/attr_traits.hpp +++ b/lib/gl/attr_traits.hpp @@ -125,9 +125,9 @@ AttrNormal> const static GLenum FFArrayIdx = GL_NORMAL_ARRAY; static void FFSetupFunc(GLint /*size*/, GLenum type, GLsizei stride, const GLvoid* ptr) - { - glNormalPointer(type, stride, ptr); - } +{ + glNormalPointer(type, stride, ptr); +} }; template diff --git a/lib/gl/types.hpp b/lib/gl/types.hpp index fcdb9598..36423aa5 100644 --- a/lib/gl/types.hpp +++ b/lib/gl/types.hpp @@ -205,10 +205,10 @@ struct alignas(16) Vertex std::array coord; static Vertex create(double * d) - { - return Vertex {(float) d[0], (float) d[1], (float) d[2]}; - } - static const int layout = LAYOUT_VTX; +{ + return Vertex {(float) d[0], (float) d[1], (float) d[2]}; +} +static const int layout = LAYOUT_VTX; }; struct alignas(16) VertexColor diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 1d6c8b9e..6593f6c3 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -725,7 +725,7 @@ int VisualizationSceneSolution::GetRefinedValuesAndNormals( if (drawelems < 2) { // In 1D we do not have well-defined normals. - if(dim > 1) + if (dim > 1) { rsol->GetGradients(i, ir, tr); normals.SetSize(3, tr.Width()); @@ -1268,10 +1268,10 @@ void VisualizationSceneSolution::PrepareFlat() { DrawQuad(disp_buf, pts, col, minv, maxv); } - else if(pointmat.Width() == 2) + else if (pointmat.Width() == 2) { poly.glBegin(GL_LINES); - for(int k = 0; k < pointmat.Width(); k++) + for (int k = 0; k < pointmat.Width(); k++) { MySetColor(poly, col[k], minv, maxv); double* v = mesh->GetVertex(vertices[k]); @@ -1292,7 +1292,6 @@ const int split_quads = 1; void VisualizationSceneSolution::PrepareFlat2() { - const int dim = mesh->Dimension(); Array vertices; int i, j, k; @@ -1890,7 +1889,7 @@ void VisualizationSceneSolution::PrepareVertexNumbering2() void VisualizationSceneSolution::PrepareEdgeNumbering() { // 1D meshes do not have edges. - if(mesh->Dimension() == 1) return; + if (mesh->Dimension() == 1) { return; } f_nums_buf.clear(); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 51547213..243ecff4 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1497,10 +1497,10 @@ void VisualizationSceneSolution3d::PrepareFlat() DrawQuad(disp_buf, p, c, minv, maxv); } } - else if(j == 2) + else if (j == 2) { poly.glBegin(GL_LINES); - for(int k=0;kGetVertex(vertices[k])); @@ -1631,7 +1631,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() { const int dim = mesh->Dimension(); - int i, k, fn, fo, di, have_normals = 0; + int fn, fo, di, have_normals = 0; double bbox_diam, vmin, vmax; disp_buf.clear(); @@ -1741,7 +1741,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() ShrinkPoints(pointmat, i, 0, 0); // Compute normals. Skip in 1D. - if(dim > 1) + if (dim > 1) { normals.SetSize(3, values.Size()); for (int j = 0; j < values.Size(); j++) @@ -1797,7 +1797,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() ((sides == 3) ? cut_TriGeoms : cut_QuadGeoms) : RefG->RefGeoms; int psides = (cut_lambda > 0) ? 4 : sides; - if(dim == 1) psides = 2; // Hack to trigger line rendering. + if (dim == 1) { psides = 2; } // Hack to trigger line rendering. DrawPatch(disp_buf, pointmat, values, normals, psides, RefGeoms, minv, maxv, have_normals); } @@ -1987,7 +1987,7 @@ void VisualizationSceneSolution3d::Prepare() for (j = 0; j < pointmat.Size(); j++) { MySetColor(poly, (*sol)(vertices[j]), minv, maxv); - if(dim > 1) poly.glNormal3d(nx(vertices[j]), ny(vertices[j]), nz(vertices[j])); + if (dim > 1) { poly.glNormal3d(nx(vertices[j]), ny(vertices[j]), nz(vertices[j])); } poly.glVertex3dv(&pointmat(0, j)); } poly.glEnd(); From e3f729b85a9af71470f08e95d51c59f437591ca6 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 23:43:48 +0200 Subject: [PATCH 14/21] Add support for vector-valued fields on segments. --- lib/openglvis.cpp | 20 ++++++++++++++ lib/openglvis.hpp | 4 +++ lib/vsvector3d.cpp | 66 +++++++++++++++++++++++++++++++++------------- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 63336f41..79438235 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -305,6 +305,26 @@ ::DrawQuad(gl3::GlDrawable& buff, {fpts[3], fnorm, texcoord[3]}); } + +void VisualizationScene +::DrawLine(gl3::GlDrawable& buff, + const double (&pts)[4][3], const double (&cv)[4], + const double minv, const double maxv) +{ + std::array texcoord[4]; + std::array fpts[2]; + for (int i = 0; i < 2; i++) + { + float pal_coord = palette.GetColorCoord(cv[i], minv, maxv); + texcoord[i] = { pal_coord, 1.0 }; + fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; + } + buff.addLine( + {fpts[0], texcoord[0]}, + {fpts[1], texcoord[1]} + ); +} + void VisualizationScene ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, DenseMatrix &normals, diff --git a/lib/openglvis.hpp b/lib/openglvis.hpp index e4051cf0..8867ba91 100644 --- a/lib/openglvis.hpp +++ b/lib/openglvis.hpp @@ -125,6 +125,10 @@ class VisualizationScene const double (&pts)[4][3], const double (&cv)[4], const double minv, const double maxv); + void DrawLine(gl3::GlDrawable& buff, + const double (&pts)[4][3], const double (&cv)[4], + const double minv, const double maxv); + /// Draw a 3D triangle in physical space with a central triangle removed. The /// cut is controlled by value of cut_lambda. See keys Ctrl+F3/F4. Similar to /// CutReferenceTriangle in lib/vssolution3d.cpp. diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index cb779893..4df4a454 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -569,7 +569,7 @@ void VisualizationSceneVector3d::PrepareFlat() DrawTriangle(disp_buf, p, c, minv, maxv); } } - else + else if (j == 4) { if (cut_lambda > 0) { @@ -580,13 +580,21 @@ void VisualizationSceneVector3d::PrepareFlat() DrawQuad(disp_buf, p, c, minv, maxv); } } + else if (j == 2) + { + DrawLine(disp_buf, p, c, minv, maxv); + } + else + { + mfem_error("VisualizationSceneSolution3d::PrepareFlat() :Unknown geometry."); + } } updated_bufs.emplace_back(&disp_buf); } void VisualizationSceneVector3d::PrepareFlat2() { - int fn, fo, di = 0, have_normals; + int fn, fo, di = 0, have_normals = 0; double bbox_diam, vmin, vmax; int dim = mesh->Dimension(); int ne = (dim == 3) ? mesh->GetNBE() : mesh->GetNE(); @@ -616,6 +624,10 @@ void VisualizationSceneVector3d::PrepareFlat2() case Element::TRIANGLE: sides = 3; break; + // TODO: can we improve this? It is quite a hack because sides + case Element::SEGMENT: + sides = 0; + break; case Element::QUADRILATERAL: default: @@ -685,7 +697,7 @@ void VisualizationSceneVector3d::PrepareFlat2() } ShrinkPoints(pointmat, i, fn, di); } - else // dim == 2 + else // dim < 3 { RefG = GLVisGeometryRefiner.Refine(mesh->GetElementBaseGeometry(i), TimesToRefine); @@ -695,7 +707,7 @@ void VisualizationSceneVector3d::PrepareFlat2() CutReferenceElements(TimesToRefine, cut_lambda); cut_updated = true; } - IntegrationRule &RefPts = (cut_lambda > 0) ? + IntegrationRule &RefPts = (cut_lambda > 0 && dim > 1) ? ((sides == 3) ? cut_TriPts : cut_QuadPts) : RefG->RefPts; GridF->GetValues(i, RefPts, values, pointmat); @@ -707,20 +719,24 @@ void VisualizationSceneVector3d::PrepareFlat2() } else { - const IntegrationRule &ir = (cut_lambda > 0) ? - ((sides == 3) ? cut_TriPts : cut_QuadPts) : - RefG->RefPts; - normals.SetSize(3, values.Size()); - mesh->GetElementTransformation(i, &T); - for (int j = 0; j < values.Size(); j++) + // Compute normals. Skip in 1D. + if (dim > 1) { - T.SetIntPoint(&ir.IntPoint(j)); - normals.GetColumnReference(j, normal); - CalcOrtho(T.Jacobian(), normal); - normal /= normal.Norml2(); + const IntegrationRule &ir = (cut_lambda > 0 && dim > 1) ? + ((sides == 3) ? cut_TriPts : cut_QuadPts) : + RefG->RefPts; + normals.SetSize(3, values.Size()); + mesh->GetElementTransformation(i, &T); + for (int j = 0; j < values.Size(); j++) + { + T.SetIntPoint(&ir.IntPoint(j)); + normals.GetColumnReference(j, normal); + CalcOrtho(T.Jacobian(), normal); + normal /= normal.Norml2(); + } + have_normals = 1; + di = 0; } - have_normals = 1; - di = 0; } ShrinkPoints(pointmat, i, 0, 0); } @@ -752,16 +768,17 @@ void VisualizationSceneVector3d::PrepareFlat2() have_normals = 0; } - have_normals = have_normals ? 2 : 0; + have_normals = have_normals && (dim > 1) ? 2 : 0; if (di) { have_normals = -1 - have_normals; } - Array &RefGeoms = (cut_lambda > 0) ? + Array &RefGeoms = (cut_lambda > 0 && dim > 1) ? ((sides == 3) ? cut_TriGeoms : cut_QuadGeoms) : RefG->RefGeoms; int psides = (cut_lambda > 0) ? 4 : sides; + if (dim == 1) { psides = 2; } // Hack to trigger line rendering. DrawPatch(disp_buf, pointmat, values, normals, psides, RefGeoms, minv, maxv, have_normals); } @@ -835,18 +852,24 @@ void VisualizationSceneVector3d::Prepare() } if (pointmat.Width() == 3) + { j = Compute3DUnitNormal(&pointmat(0,0), &pointmat(0,1), &pointmat(0,2), nor); + } else + { j = Compute3DUnitNormal(&pointmat(0,0), &pointmat(0,1), &pointmat(0,2), &pointmat(0,3), nor); + } if (j == 0) + { for (j = 0; j < pointmat.Size(); j++) { nx(vertices[j]) += nor[0]; ny(vertices[j]) += nor[1]; nz(vertices[j]) += nor[2]; } + } } for (i = 0; i < ne; i++) @@ -862,10 +885,15 @@ void VisualizationSceneVector3d::Prepare() case Element::TRIANGLE: draw.glBegin (GL_TRIANGLES); break; - case Element::QUADRILATERAL: draw.glBegin (GL_QUADS); break; + case Element::SEGMENT: + draw.glBegin(GL_LINES); + break; + default: + MFEM_ABORT("Invalid boundary element type"); + break; } if (dim == 3) { From 34f1624ee5cc695cd15c086c46ada31c5365afe5 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 24 May 2022 23:59:45 +0200 Subject: [PATCH 15/21] Some cleanup. --- lib/vssolution.cpp | 9 +-------- lib/vssolution3d.cpp | 16 ++++++---------- lib/vsvector3d.cpp | 2 +- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 6593f6c3..685cf9ae 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1270,14 +1270,7 @@ void VisualizationSceneSolution::PrepareFlat() } else if (pointmat.Width() == 2) { - poly.glBegin(GL_LINES); - for (int k = 0; k < pointmat.Width(); k++) - { - MySetColor(poly, col[k], minv, maxv); - double* v = mesh->GetVertex(vertices[k]); - poly.glVertex3d(v[0], v[1], 0.0); - } - poly.glEnd(); + DrawLine(disp_buf, pts, col, minv, maxv); } } updated_bufs.emplace_back(&disp_buf); diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 243ecff4..22aec20c 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -1429,8 +1429,6 @@ void VisualizationSceneSolution3d::PrepareFlat() Array vertices; double p[4][3], c[4]; - gl3::GlBuilder poly = disp_buf.createBuilder(); - for (i = 0; i < ne; i++) { if (dim == 3) @@ -1499,13 +1497,11 @@ void VisualizationSceneSolution3d::PrepareFlat() } else if (j == 2) { - poly.glBegin(GL_LINES); - for (int k=0; kGetVertex(vertices[k])); - } - poly.glEnd(); + DrawLine(disp_buf, p, c, minv, maxv); + } + else + { + mfem_error("VisualizationSceneSolution3d::PrepareFlat() :Unknown geometry."); } } @@ -1760,7 +1756,7 @@ void VisualizationSceneSolution3d::PrepareFlat2() vmax = fmax(vmax, values.Max()); // compute an average normal direction for the current face - if (sc != 0.0 && dim > 1) + if (sc != 0.0 && have_normals) { for (int j = 0; j < 3; j++) { diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 4df4a454..4a23baa4 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -586,7 +586,7 @@ void VisualizationSceneVector3d::PrepareFlat() } else { - mfem_error("VisualizationSceneSolution3d::PrepareFlat() :Unknown geometry."); + mfem_error("VisualizationSceneVector3d::PrepareFlat() :Unknown geometry."); } } updated_bufs.emplace_back(&disp_buf); From 6ec3880ca0e4370a1c9ad714423fd311d6c94d4e Mon Sep 17 00:00:00 2001 From: termi-official Date: Wed, 25 May 2022 00:07:52 +0200 Subject: [PATCH 16/21] Style. --- lib/openglvis.cpp | 6 +++--- lib/vsvector3d.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 79438235..0d03a7c8 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -320,8 +320,8 @@ ::DrawLine(gl3::GlDrawable& buff, fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; } buff.addLine( - {fpts[0], texcoord[0]}, - {fpts[1], texcoord[1]} + {fpts[0], texcoord[0]}, + {fpts[1], texcoord[1]} ); } @@ -419,7 +419,7 @@ ::DrawPatch(gl3::GlDrawable& drawable, const DenseMatrix &pts, Vector &vals, if (n == 2) // Lines { // Draw solution line - for(int j=0; j<2; j++) + for (int j=0; j<2; j++) { MySetColor(poly, vals(ind[i+j]), minv, maxv); poly.glVertex3d(pts(0, ind[i+j]), pts(1, ind[i+j]), pts(2, ind[i+j])); diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 4a23baa4..9d78b194 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -723,8 +723,8 @@ void VisualizationSceneVector3d::PrepareFlat2() if (dim > 1) { const IntegrationRule &ir = (cut_lambda > 0 && dim > 1) ? - ((sides == 3) ? cut_TriPts : cut_QuadPts) : - RefG->RefPts; + ((sides == 3) ? cut_TriPts : cut_QuadPts) : + RefG->RefPts; normals.SetSize(3, values.Size()); mesh->GetElementTransformation(i, &T); for (int j = 0; j < values.Size(); j++) From 96184410bb2e24ff21b54172943729c549e9b7a4 Mon Sep 17 00:00:00 2001 From: termi-official Date: Wed, 25 May 2022 00:13:44 +0200 Subject: [PATCH 17/21] Remove obsolete variables. --- lib/vssolution.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 685cf9ae..ac2aee6a 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1245,8 +1245,6 @@ void VisualizationSceneSolution::PrepareFlat() Array vertices; double pts[4][3], col[4]; - gl3::GlBuilder poly = disp_buf.createBuilder(); - for (int i = 0; i < ne; i++) { if (!el_attr_to_show[mesh->GetAttribute(i)-1]) { continue; } From adb037e6f86944c35d1e33b0d74d0bb91fbd6501 Mon Sep 17 00:00:00 2001 From: termi-official Date: Wed, 27 Jul 2022 00:11:04 +0200 Subject: [PATCH 18/21] Tweak grid visualization for 1d meshes embedded in 2d space. --- lib/vssolution.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index ac2aee6a..401c3269 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1647,7 +1647,7 @@ void VisualizationSceneSolution::PrepareLevelCurves2() void VisualizationSceneSolution::PrepareLines() { - if (shading == 2) + if (shading == 2 && mesh->Dimension() > 1) // PrepareLines3 does not make sense for 1d meshes. { // PrepareLines2(); PrepareLines3(); @@ -1668,10 +1668,16 @@ void VisualizationSceneSolution::PrepareLines() lb.glBegin(GL_LINE_LOOP); mesh->GetPointMatrix (i, pointmat); mesh->GetElementVertices (i, vertices); - for (j = 0; j < pointmat.Size(); j++) - lb.glVertex3d(pointmat(0, j), pointmat(1, j), - LogVal((*sol)(vertices[j]))); + { + // 1D meshes get rendered flat + double z = GetMinV(); + if(mesh->Dimension() > 1) // In 1D we just put the mesh below the solution + { + z = LogVal((*sol)(vertices[j])); + } + lb.glVertex3d(pointmat(0, j), pointmat(1, j), z); + } lb.glEnd(); } @@ -2059,7 +2065,6 @@ void VisualizationSceneSolution::PrepareLines3() line_buf.clear(); gl3::GlBuilder lb = line_buf.createBuilder(); - for (i = 0; i < ne; i++) { if (!el_attr_to_show[mesh->GetAttribute(i)-1]) { continue; } From aca0fa7514a80a0f369f3c7395591cedd8bc4104 Mon Sep 17 00:00:00 2001 From: Tzanio Kolev Date: Sun, 6 Aug 2023 11:22:45 -0700 Subject: [PATCH 19/21] make style --- lib/gl/attr_traits.hpp | 6 +++--- lib/gl/types.hpp | 8 ++++---- lib/vssolution.cpp | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/gl/attr_traits.hpp b/lib/gl/attr_traits.hpp index e8ee4d2e..63fc5089 100644 --- a/lib/gl/attr_traits.hpp +++ b/lib/gl/attr_traits.hpp @@ -125,9 +125,9 @@ AttrNormal> const static GLenum FFArrayIdx = GL_NORMAL_ARRAY; static void FFSetupFunc(GLint /*size*/, GLenum type, GLsizei stride, const GLvoid* ptr) -{ - glNormalPointer(type, stride, ptr); -} + { + glNormalPointer(type, stride, ptr); + } }; template diff --git a/lib/gl/types.hpp b/lib/gl/types.hpp index 36423aa5..fcdb9598 100644 --- a/lib/gl/types.hpp +++ b/lib/gl/types.hpp @@ -205,10 +205,10 @@ struct alignas(16) Vertex std::array coord; static Vertex create(double * d) -{ - return Vertex {(float) d[0], (float) d[1], (float) d[2]}; -} -static const int layout = LAYOUT_VTX; + { + return Vertex {(float) d[0], (float) d[1], (float) d[2]}; + } + static const int layout = LAYOUT_VTX; }; struct alignas(16) VertexColor diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index 401c3269..3f89f307 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -1647,7 +1647,8 @@ void VisualizationSceneSolution::PrepareLevelCurves2() void VisualizationSceneSolution::PrepareLines() { - if (shading == 2 && mesh->Dimension() > 1) // PrepareLines3 does not make sense for 1d meshes. + if (shading == 2 && + mesh->Dimension() > 1) // PrepareLines3 does not make sense for 1d meshes. { // PrepareLines2(); PrepareLines3(); @@ -1672,7 +1673,7 @@ void VisualizationSceneSolution::PrepareLines() { // 1D meshes get rendered flat double z = GetMinV(); - if(mesh->Dimension() > 1) // In 1D we just put the mesh below the solution + if (mesh->Dimension() > 1) // In 1D we just put the mesh below the solution { z = LogVal((*sol)(vertices[j])); } From 94350f7c49f52a5a5f45f0d915badeec96e666c8 Mon Sep 17 00:00:00 2001 From: termi-official Date: Mon, 7 Aug 2023 12:33:48 +0200 Subject: [PATCH 20/21] Add changelog entry. --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 568fdb14..e42bf778 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ Version 4.2.1 (development) - Significantly improved memory usage. +- Add support to visualize solutions on 1D elements embedded in 2D and 3D. + Version 4.2 released on May 23, 2022 ==================================== From 4383f05c713d40de300d49da3e75640ee03bdd60 Mon Sep 17 00:00:00 2001 From: termi-official Date: Mon, 7 Aug 2023 18:39:16 +0200 Subject: [PATCH 21/21] Fix line renderer texture. --- lib/openglvis.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/openglvis.cpp b/lib/openglvis.cpp index 1e92a841..8a626217 100644 --- a/lib/openglvis.cpp +++ b/lib/openglvis.cpp @@ -309,12 +309,11 @@ ::DrawLine(gl3::GlDrawable& buff, const double (&pts)[4][3], const double (&cv)[4], const double minv, const double maxv) { - std::array texcoord[4]; + float texcoord[2]; std::array fpts[2]; for (int i = 0; i < 2; i++) { - float pal_coord = palette.GetColorCoord(cv[i], minv, maxv); - texcoord[i] = { pal_coord, 1.0 }; + texcoord[i] = palette.GetColorCoord(cv[i], minv, maxv); fpts[i] = {(float) pts[i][0], (float) pts[i][1], (float) pts[i][2]}; } buff.addLine(