Skip to content

Commit 13b712e

Browse files
committed
vertex/face only selection modes for meshes
1 parent d1dbf33 commit 13b712e

File tree

6 files changed

+105
-34
lines changed

6 files changed

+105
-34
lines changed

include/polyscope/persistent_value.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ extern PersistentCache<BackFacePolicy> persistentCache_BackFacePolicy;
144144
extern PersistentCache<MeshShadeStyle> persistentCache_MeshNormalType;
145145
extern PersistentCache<FilterMode> persistentCache_FilterMode;
146146
extern PersistentCache<IsolineStyle> persistentCache_IsolineStyle;
147+
extern PersistentCache<MeshSelectionMode> persistentCache_MeshSelectionMode;
147148

148149
template<> inline PersistentCache<double>& getPersistentCacheRef<double>() { return persistentCache_double; }
149150
template<> inline PersistentCache<float>& getPersistentCacheRef<float>() { return persistentCache_float; }
@@ -159,6 +160,7 @@ template<> inline PersistentCache<BackFacePolicy>& getPersistentCacheR
159160
template<> inline PersistentCache<MeshShadeStyle>& getPersistentCacheRef<MeshShadeStyle>() { return persistentCache_MeshNormalType; }
160161
template<> inline PersistentCache<FilterMode>& getPersistentCacheRef<FilterMode>() { return persistentCache_FilterMode; }
161162
template<> inline PersistentCache<IsolineStyle>& getPersistentCacheRef<IsolineStyle>() { return persistentCache_IsolineStyle; }
163+
template<> inline PersistentCache<MeshSelectionMode>& getPersistentCacheRef<MeshSelectionMode>() { return persistentCache_MeshSelectionMode; }
162164
}
163165
// clang-format on
164166

include/polyscope/surface_mesh.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ class SurfaceMesh : public QuantityStructure<SurfaceMesh> {
290290
SurfaceMesh* setShadeStyle(MeshShadeStyle newStyle);
291291
MeshShadeStyle getShadeStyle();
292292

293+
// Selection mode
294+
SurfaceMesh* setSelectionMode(MeshSelectionMode newMode);
295+
MeshSelectionMode getSelectionMode();
296+
293297
// == Rendering helpers used by quantities
294298

295299
// void fillGeometryBuffers(render::ShaderProgram& p);
@@ -361,12 +365,12 @@ class SurfaceMesh : public QuantityStructure<SurfaceMesh> {
361365
PersistentValue<BackFacePolicy> backFacePolicy;
362366
PersistentValue<glm::vec3> backFaceColor;
363367
PersistentValue<MeshShadeStyle> shadeStyle;
368+
PersistentValue<MeshSelectionMode> selectionMode;
364369

365370
// Do setup work related to drawing, including allocating openGL data
366371
void prepare();
367372
void preparePick();
368373

369-
370374
/// == Compute indices & geometry data
371375
void computeTriangleCornerInds();
372376
void computeTriangleAllVertexInds();
@@ -405,6 +409,7 @@ class SurfaceMesh : public QuantityStructure<SurfaceMesh> {
405409

406410
std::shared_ptr<render::ShaderProgram> program;
407411
std::shared_ptr<render::ShaderProgram> pickProgram;
412+
bool usingSimplePick = false;
408413

409414

410415
// === Helper functions

include/polyscope/types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ enum class BackFacePolicy { Identical, Different, Custom, Cull };
1818

1919
enum class PointRenderMode { Sphere = 0, Quad };
2020
enum class MeshElement { VERTEX = 0, FACE, EDGE, HALFEDGE, CORNER };
21-
enum class CurveNetworkElement { NODE = 0, EDGE };
2221
enum class MeshShadeStyle { Smooth = 0, Flat, TriFlat };
22+
enum class MeshSelectionMode { Auto = 0, VerticesOnly, FacesOnly };
23+
enum class CurveNetworkElement { NODE = 0, EDGE };
2324
enum class VolumeMeshElement { VERTEX = 0, EDGE, FACE, CELL };
2425
enum class VolumeCellType { TET = 0, HEX };
2526
enum class VolumeGridElement { NODE = 0, CELL };

src/persistent_value.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ PersistentCache<BackFacePolicy> persistentCache_BackFacePolicy;
2222
PersistentCache<MeshShadeStyle> persistentCache_MeshNormalType;
2323
PersistentCache<FilterMode> persistentCache_FilterMode;
2424
PersistentCache<IsolineStyle> persistentCache_IsolineStyle;
25+
PersistentCache<MeshSelectionMode> persistentCache_MeshSelectionMode;
2526
// clang-format on
2627
} // namespace detail
2728
} // namespace polyscope

src/render/opengl/shaders/surface_mesh_shaders.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -703,22 +703,26 @@ const ShaderReplacementRule MESH_PROPAGATE_PICK_SIMPLE ( // this one does faces
703703
{"FRAG_DECLARATIONS", R"(
704704
flat in vec3 vertexColors[3];
705705
flat in vec3 faceColor;
706+
uniform float u_vertPickRadius;
706707
)"},
707708
{"GENERATE_SHADE_VALUE", R"(
708709
// Parameters defining the pick shape (in barycentric 0-1 units)
709-
float vertRadius = 0.2;
710710
711711
vec3 shadeColor = faceColor;
712712
713713
// Test vertices and corners
714+
float nearestRad = 1.0-u_vertPickRadius;
714715
for(int i = 0; i < 3; i++) {
715-
if(a_barycoordToFrag[i] > 1.0-vertRadius) {
716+
if(a_barycoordToFrag[i] > nearestRad) {
717+
nearestRad = a_barycoordToFrag[i];
716718
shadeColor = vertexColors[i];
717719
}
718720
}
719721
)"},
720722
},
721-
/* uniforms */ {},
723+
/* uniforms */ {
724+
{"u_vertPickRadius", RenderDataType::Float},
725+
},
722726
/* attributes */ {
723727
{"a_vertexColors", RenderDataType::Vector3Float, 3},
724728
{"a_faceColor", RenderDataType::Vector3Float},

src/surface_mesh.cpp

Lines changed: 87 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ edgeColor( uniquePrefix() + "edgeColor", glm::vec3{0., 0., 0.
6161
edgeWidth( uniquePrefix() + "edgeWidth", 0.),
6262
backFacePolicy( uniquePrefix() + "backFacePolicy", BackFacePolicy::Different),
6363
backFaceColor( uniquePrefix() + "backFaceColor", glm::vec3(1.f - surfaceColor.get().r, 1.f - surfaceColor.get().g, 1.f - surfaceColor.get().b)),
64-
shadeStyle( uniquePrefix() + "shadeStyle", MeshShadeStyle::Flat)
64+
shadeStyle( uniquePrefix() + "shadeStyle", MeshShadeStyle::Flat),
65+
selectionMode( uniquePrefix() + "selectionMode", MeshSelectionMode::Auto)
6566

6667
// clang-format on
6768
{}
@@ -734,8 +735,7 @@ void SurfaceMesh::draw() {
734735
if (program == nullptr) {
735736
prepare();
736737

737-
// do this now to reduce lag when picking later, etc
738-
// FIXME
738+
// do this now to reduce lag when picking later
739739
// preparePick();
740740
}
741741

@@ -792,6 +792,22 @@ void SurfaceMesh::drawPick() {
792792
// Set uniforms
793793
setStructureUniforms(*pickProgram);
794794

795+
if (usingSimplePick) {
796+
float radVal;
797+
switch (selectionMode.get()) {
798+
case MeshSelectionMode::Auto:
799+
radVal = 0.2;
800+
break;
801+
case MeshSelectionMode::VerticesOnly:
802+
radVal = 1.;
803+
break;
804+
case MeshSelectionMode::FacesOnly:
805+
radVal = 0.;
806+
break;
807+
}
808+
pickProgram->setUniform("u_vertPickRadius", radVal);
809+
}
810+
795811
pickProgram->draw();
796812

797813
render::engine->setBackfaceCull(); // return to default setting
@@ -813,10 +829,19 @@ void SurfaceMesh::prepare() {
813829

814830
void SurfaceMesh::preparePick() {
815831

832+
switch (selectionMode.get()) {
833+
case MeshSelectionMode::Auto:
834+
usingSimplePick = !(edgesHaveBeenUsed || halfedgesHaveBeenUsed || cornersHaveBeenUsed);
835+
break;
836+
case MeshSelectionMode::VerticesOnly:
837+
usingSimplePick = true;
838+
break;
839+
case MeshSelectionMode::FacesOnly:
840+
usingSimplePick = true;
841+
break;
842+
}
816843

817-
bool simplePick = !(edgesHaveBeenUsed || halfedgesHaveBeenUsed || cornersHaveBeenUsed);
818-
819-
if (simplePick) {
844+
if (usingSimplePick) {
820845
pickProgram =
821846
render::engine->requestShader("MESH", addSurfaceMeshRules({"MESH_PROPAGATE_PICK_SIMPLE"}, true, false),
822847
render::ShaderReplacementDefaults::Pick);
@@ -870,7 +895,6 @@ void SurfaceMesh::setMeshPickAttributes(render::ShaderProgram& p) {
870895
// CPU-side processing. Maybe the solution is to directly render ints?
871896

872897
// make sure we have the relevant indexing data
873-
bool simplePick = !(edgesHaveBeenUsed || halfedgesHaveBeenUsed || cornersHaveBeenUsed);
874898
triangleVertexInds.ensureHostBufferPopulated();
875899
triangleFaceInds.ensureHostBufferPopulated();
876900
if (edgesHaveBeenUsed) triangleAllEdgeInds.ensureHostBufferPopulated();
@@ -905,7 +929,7 @@ void SurfaceMesh::setMeshPickAttributes(render::ShaderProgram& p) {
905929
// Reserve space
906930
vertexColors.reserve(3 * nFacesTriangulation());
907931
faceColor.reserve(3 * nFacesTriangulation());
908-
if (!simplePick) {
932+
if (!usingSimplePick) {
909933
halfedgeColors.reserve(3 * nFacesTriangulation());
910934
cornerColors.reserve(3 * nFacesTriangulation());
911935
}
@@ -936,7 +960,7 @@ void SurfaceMesh::setMeshPickAttributes(render::ShaderProgram& p) {
936960
}
937961

938962
// Second half does halfedges/edges/corners, not used for simple mode
939-
if (simplePick) {
963+
if (usingSimplePick) {
940964
iFTri++;
941965
continue;
942966
}
@@ -948,42 +972,45 @@ void SurfaceMesh::setMeshPickAttributes(render::ShaderProgram& p) {
948972

949973
// == Build edge index data, if needed
950974

975+
if (!usingSimplePick) {
976+
if (edgesHaveBeenUsed || halfedgesHaveBeenUsed) {
951977

952-
if (edgesHaveBeenUsed || halfedgesHaveBeenUsed) {
953-
954-
const std::vector<uint32_t>& eDataVec =
955-
(edgesHaveBeenUsed && !halfedgesHaveBeenUsed) ? triangleAllEdgeInds.data : triangleAllHalfedgeInds.data;
956-
size_t offset =
957-
(edgesHaveBeenUsed && !halfedgesHaveBeenUsed) ? edgeGlobalPickIndStart : halfedgeGlobalPickIndStart;
978+
const std::vector<uint32_t>& eDataVec =
979+
(edgesHaveBeenUsed && !halfedgesHaveBeenUsed) ? triangleAllEdgeInds.data : triangleAllHalfedgeInds.data;
980+
size_t offset =
981+
(edgesHaveBeenUsed && !halfedgesHaveBeenUsed) ? edgeGlobalPickIndStart : halfedgeGlobalPickIndStart;
958982

959-
// clang-format off
983+
// clang-format off
960984
std::array<glm::vec3, 3> eColor = {
961985
fColor,
962986
pick::indToVec(eDataVec[9*iFTri + 1] + offset),
963987
fColor
964988
};
965-
// clang-format on
966-
if (j == 1) eColor[0] = pick::indToVec(eDataVec[9 * iFTri + 0] + offset);
967-
if (j + 2 == D) eColor[2] = pick::indToVec(eDataVec[9 * iFTri + 2] + offset);
989+
// clang-format on
990+
if (j == 1) eColor[0] = pick::indToVec(eDataVec[9 * iFTri + 0] + offset);
991+
if (j + 2 == D) eColor[2] = pick::indToVec(eDataVec[9 * iFTri + 2] + offset);
968992

969-
for (int j = 0; j < 3; j++) halfedgeColors.push_back(eColor);
970-
} else {
971-
for (int j = 0; j < 3; j++) halfedgeColors.push_back({fColor, fColor, fColor});
993+
for (int j = 0; j < 3; j++) halfedgeColors.push_back(eColor);
994+
} else {
995+
for (int j = 0; j < 3; j++) halfedgeColors.push_back({fColor, fColor, fColor});
996+
}
972997
}
973998

974999
// == Build corner index data, if needed
9751000

976-
if (cornersHaveBeenUsed) {
977-
// clang-format off
1001+
if (!usingSimplePick) {
1002+
if (cornersHaveBeenUsed) {
1003+
// clang-format off
9781004
std::array<glm::vec3, 3> cColor = {
9791005
pick::indToVec(triangleCornerInds.data[3*iFTri + 0] + cornerGlobalPickIndStart),
9801006
pick::indToVec(triangleCornerInds.data[3*iFTri + 1] + cornerGlobalPickIndStart),
9811007
pick::indToVec(triangleCornerInds.data[3*iFTri + 2] + cornerGlobalPickIndStart),
9821008
};
983-
// clang-format on
984-
for (int j = 0; j < 3; j++) cornerColors.push_back(cColor);
985-
} else {
986-
for (int j = 0; j < 3; j++) cornerColors.push_back({vColor[0], vColor[1], vColor[2]});
1009+
// clang-format on
1010+
for (int j = 0; j < 3; j++) cornerColors.push_back(cColor);
1011+
} else {
1012+
for (int j = 0; j < 3; j++) cornerColors.push_back({vColor[0], vColor[1], vColor[2]});
1013+
}
9871014
}
9881015

9891016
iFTri++;
@@ -1002,7 +1029,7 @@ void SurfaceMesh::setMeshPickAttributes(render::ShaderProgram& p) {
10021029
faceColorsBuff->setData(faceColor);
10031030
pickProgram->setAttribute("a_faceColor", faceColorsBuff);
10041031

1005-
if (!simplePick) {
1032+
if (!usingSimplePick) {
10061033

10071034
std::shared_ptr<render::AttributeBuffer> halfedgeColorsBuff =
10081035
render::engine->generateAttributeBuffer(RenderDataType::Vector3Float, 3);
@@ -1384,6 +1411,29 @@ void SurfaceMesh::buildCustomOptionsUI() {
13841411
}
13851412
}
13861413
}
1414+
ImGui::EndMenu();
1415+
}
1416+
1417+
// Selection mode
1418+
if (ImGui::BeginMenu("Selection Mode")) {
1419+
if (ImGui::MenuItem("auto", NULL, selectionMode.get() == MeshSelectionMode::Auto))
1420+
setSelectionMode(MeshSelectionMode::Auto);
1421+
if (ImGui::MenuItem("vertices only", NULL, selectionMode.get() == MeshSelectionMode::VerticesOnly))
1422+
setSelectionMode(MeshSelectionMode::VerticesOnly);
1423+
if (ImGui::MenuItem("faces only", NULL, selectionMode.get() == MeshSelectionMode::FacesOnly))
1424+
setSelectionMode(MeshSelectionMode::FacesOnly);
1425+
1426+
ImGui::Separator();
1427+
1428+
if (ImGui::MenuItem("Mark edges as used (selectable)", NULL, edgesHaveBeenUsed)) {
1429+
markEdgesAsUsed();
1430+
}
1431+
if (ImGui::MenuItem("Mark halfedges as used (selectable)", NULL, halfedgesHaveBeenUsed)) {
1432+
markHalfedgesAsUsed();
1433+
}
1434+
if (ImGui::MenuItem("Mark corners as used (selectable)", NULL, cornersHaveBeenUsed)) {
1435+
markCornersAsUsed();
1436+
}
13871437

13881438
ImGui::EndMenu();
13891439
}
@@ -1694,6 +1744,14 @@ SurfaceMesh* SurfaceMesh::setShadeStyle(MeshShadeStyle newStyle) {
16941744
}
16951745
MeshShadeStyle SurfaceMesh::getShadeStyle() { return shadeStyle.get(); }
16961746

1747+
SurfaceMesh* SurfaceMesh::setSelectionMode(MeshSelectionMode newMode) {
1748+
selectionMode = newMode;
1749+
refresh();
1750+
requestRedraw();
1751+
return this;
1752+
}
1753+
MeshSelectionMode SurfaceMesh::getSelectionMode() { return selectionMode.get(); }
1754+
16971755
// === Quantity adders
16981756

16991757

0 commit comments

Comments
 (0)