Skip to content

Commit a4be2fe

Browse files
committed
clean up quantities, implement picking for SimpleTriangleMesh
1 parent cdec7f1 commit a4be2fe

14 files changed

Lines changed: 323 additions & 25 deletions

include/polyscope/pick.ipp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const uint64_t bitsForPickPacking = 22;
1313

1414
inline glm::vec3 indToVec(size_t globalInd) {
1515

16+
// NOTE: there is a duplicate version of this logic in a macro below, which must be kept in sync.
17+
1618
// Can comfortably fit a 22 bit integer exactly in a single precision float
1719
uint64_t factor = 1 << bitsForPickPacking;
1820
uint64_t mask = factor - 1;
@@ -48,5 +50,53 @@ inline uint64_t vecToInd(glm::vec3 vec) {
4850
return ind;
4951
}
5052

53+
54+
// == Weird alternate implementation of indToVec()
55+
// This is here because sometimes we want to evaluate the indToVec() bit-bashing logic in a shader, and get exactly
56+
// the same result as the C++ version above. A GLSL implementation is not too bad, but it's hard to test to ensure
57+
// it really matches.
58+
//
59+
// The solution here is a funky macro'd implementation, that compiles as C++ or GLSL. We compile it as C++ in the tests
60+
// and verify it matches the usual indToVec() implementation, then compile it as GLSL in shaders.
61+
//
62+
// All of the macro stuff you see below is just boilerplate to make that possible.
63+
64+
#define POLYSCOPE_PICK_STR_H(...) #__VA_ARGS__
65+
#define POLYSCOPE_PICK_STR(...) POLYSCOPE_PICK_STR_H(__VA_ARGS__)
66+
67+
// See note above. This is logic that is meant to be identical to indToVec().
68+
// clang-format off
69+
#define POLYSCOPE_PICK_INDEX_COLOR_BODY \
70+
POLYSCOPE_PICK_UINT idxLow = pickStartLow + primID; \
71+
POLYSCOPE_PICK_UINT carry = (idxLow < pickStartLow) ? 1u : 0u; \
72+
POLYSCOPE_PICK_UINT idxHigh = pickStartHigh + carry; \
73+
POLYSCOPE_PICK_UINT low22 = idxLow & 0x3FFFFFu; \
74+
POLYSCOPE_PICK_UINT med22 = ((idxLow >> 22u) | (idxHigh << 10u)) & 0x3FFFFFu; \
75+
POLYSCOPE_PICK_UINT high22 = (idxHigh >> 12u) & 0x3FFFFFu; \
76+
return POLYSCOPE_PICK_VEC3(float(low22), float(med22), float(high22)) / 4194304.0f;
77+
// clang-format on
78+
79+
// C++ version: compile the body with C++ types.
80+
#define POLYSCOPE_PICK_UINT uint32_t
81+
#define POLYSCOPE_PICK_VEC3 glm::vec3
82+
inline glm::vec3 pickIndexToColorImpl(uint32_t pickStartLow, uint32_t pickStartHigh, uint32_t primID) {
83+
POLYSCOPE_PICK_INDEX_COLOR_BODY
84+
}
85+
#undef POLYSCOPE_PICK_UINT
86+
#undef POLYSCOPE_PICK_VEC3
87+
88+
// Convenience wrapper for C++ callers that have a combined uint64_t pickStart.
89+
inline glm::vec3 pickIndexToColor(uint64_t pickStart, uint32_t primID) {
90+
return pickIndexToColorImpl(static_cast<uint32_t>(pickStart & 0xFFFFFFFFull), static_cast<uint32_t>(pickStart >> 32),
91+
primID);
92+
}
93+
94+
// GLSL string macro. Stringifies POLYSCOPE_PICK_INDEX_COLOR_BODY using GLSL type names.
95+
// REQUIRES: POLYSCOPE_PICK_UINT must equal "uint" and POLYSCOPE_PICK_VEC3 must equal "vec3"
96+
// at the point of expansion (see common.cpp for the usage pattern).
97+
#define POLYSCOPE_PICK_INDEX_TO_COLOR_GLSL \
98+
"vec3 pickIndexToColor(uint pickStartLow, uint pickStartHigh, uint primID) { " POLYSCOPE_PICK_STR( \
99+
POLYSCOPE_PICK_INDEX_COLOR_BODY) " }"
100+
51101
} // namespace pick
52102
} // namespace polyscope

include/polyscope/render/opengl/shaders/surface_mesh_shaders.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern const ShaderReplacementRule MESH_PROPAGATE_PICK_SIMPLE;
3838
extern const ShaderReplacementRule MESH_PROPAGATE_TYPE_AND_BASECOLOR2_SHADE;
3939
extern const ShaderReplacementRule SIMPLE_MESH_PROPAGATE_FACE_VALUE;
4040
extern const ShaderReplacementRule SIMPLE_MESH_PROPAGATE_FACE_COLOR;
41+
extern const ShaderReplacementRule SIMPLE_MESH_PROPAGATE_FACE_PICK;
4142

4243

4344
} // namespace backend_openGL3

include/polyscope/simple_triangle_mesh.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "polyscope/scaled_value.h"
1111
#include "polyscope/standardize_data_array.h"
1212
#include "polyscope/structure.h"
13+
#include "polyscope/types.h"
1314

1415
#include "polyscope/simple_triangle_mesh_color_quantity.h"
1516
#include "polyscope/simple_triangle_mesh_quantity.h"
@@ -31,7 +32,8 @@ class SimpleTriangleMeshVertexColorQuantity;
3132
class SimpleTriangleMeshFaceColorQuantity;
3233

3334
struct SimpleTriangleMeshPickResult {
34-
// this does nothing for now, just matching pattern from other structures
35+
MeshElement elementType = MeshElement::FACE; // which kind of element was clicked
36+
int64_t index = -1; // index of the clicked element (vertex or face)
3537
};
3638

3739
class SimpleTriangleMesh : public Structure {
@@ -114,6 +116,10 @@ class SimpleTriangleMesh : public Structure {
114116
SimpleTriangleMesh* setBackFacePolicy(BackFacePolicy newPolicy);
115117
BackFacePolicy getBackFacePolicy();
116118

119+
// Selection mode (controls vertex vs face pick threshold)
120+
SimpleTriangleMesh* setSelectionMode(MeshSelectionMode newMode);
121+
MeshSelectionMode getSelectionMode();
122+
117123
// Rendering helpers used by quantities
118124
void setSimpleTriangleMeshUniforms(render::ShaderProgram& p, bool withSurfaceShade = true);
119125
void setSimpleTriangleMeshProgramGeometryAttributes(render::ShaderProgram& p);
@@ -132,6 +138,7 @@ class SimpleTriangleMesh : public Structure {
132138
PersistentValue<std::string> material;
133139
PersistentValue<BackFacePolicy> backFacePolicy;
134140
PersistentValue<glm::vec3> backFaceColor;
141+
PersistentValue<MeshSelectionMode> selectionMode;
135142

136143
// Drawing related things
137144
// if nullptr, prepare() (resp. preparePick()) needs to be called
@@ -142,7 +149,7 @@ class SimpleTriangleMesh : public Structure {
142149
// Do setup work related to drawing, including allocating openGL data
143150
void ensureRenderProgramPrepared();
144151
void ensurePickProgramPrepared();
145-
void setPickUniforms(render::ShaderProgram& p);
152+
void setPickUniforms(render::ShaderProgram& p); // sets u_pickStartLow/High for SIMPLE_MESH_PROPAGATE_FACE_PICK
146153

147154
// === Quantity adder implementations
148155
SimpleTriangleMeshVertexScalarQuantity* addVertexScalarQuantityImpl(std::string name, const std::vector<float>& data,
@@ -154,8 +161,7 @@ class SimpleTriangleMesh : public Structure {
154161
SimpleTriangleMeshFaceColorQuantity* addFaceColorQuantityImpl(std::string name, const std::vector<glm::vec3>& colors);
155162

156163
// == Picking related things
157-
size_t pickStart;
158-
glm::vec3 pickColor;
164+
size_t pickStart = 0;
159165
};
160166

161167

include/polyscope/simple_triangle_mesh_color_quantity.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class SimpleTriangleMeshColorQuantity : public SimpleTriangleMeshQuantity,
1717

1818
virtual void draw() override;
1919
virtual void buildCustomUI() override;
20+
virtual void buildColorOptionsUI() override;
2021
virtual void refresh() override;
2122
virtual std::string niceName() override;
2223

@@ -39,6 +40,7 @@ class SimpleTriangleMeshVertexColorQuantity : public SimpleTriangleMeshColorQuan
3940
SimpleTriangleMesh& mesh);
4041

4142
virtual void createProgram() override;
43+
virtual void buildVertexInfoGUI(size_t vInd) override;
4244
};
4345

4446

@@ -52,6 +54,7 @@ class SimpleTriangleMeshFaceColorQuantity : public SimpleTriangleMeshColorQuanti
5254
SimpleTriangleMesh& mesh);
5355

5456
virtual void createProgram() override;
57+
virtual void buildFaceInfoGUI(size_t fInd) override;
5558
};
5659

5760

include/polyscope/simple_triangle_mesh_quantity.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@ class SimpleTriangleMesh;
1212
class SimpleTriangleMeshQuantity : public Quantity {
1313
public:
1414
SimpleTriangleMeshQuantity(std::string name, SimpleTriangleMesh& parentStructure, bool dominates = false);
15-
virtual ~SimpleTriangleMeshQuantity(){};
15+
virtual ~SimpleTriangleMeshQuantity() {};
1616

1717
SimpleTriangleMesh& parent; // shadows and hides the generic member in Quantity
18+
19+
// Called by buildPickUI() to display this quantity's value for the selected element.
20+
// Override in vertex quantities (for vertex picks) and face quantities (for face picks).
21+
virtual void buildVertexInfoGUI(size_t vInd) {}
22+
virtual void buildFaceInfoGUI(size_t fInd) {}
1823
};
1924

2025
} // namespace polyscope

include/polyscope/simple_triangle_mesh_scalar_quantity.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class SimpleTriangleMeshVertexScalarQuantity : public SimpleTriangleMeshScalarQu
4141
DataType dataType = DataType::STANDARD);
4242

4343
virtual void createProgram() override;
44+
virtual void buildVertexInfoGUI(size_t vInd) override;
4445
};
4546

4647

@@ -54,6 +55,7 @@ class SimpleTriangleMeshFaceScalarQuantity : public SimpleTriangleMeshScalarQuan
5455
DataType dataType = DataType::STANDARD);
5556

5657
virtual void createProgram() override;
58+
virtual void buildFaceInfoGUI(size_t fInd) override;
5759
};
5860

5961

src/render/mock_opengl/mock_gl_engine.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2235,7 +2235,8 @@ void MockGLEngine::populateDefaultShadersAndRules() {
22352235
registerShaderRule("MESH_PROPAGATE_PICK_SIMPLE", MESH_PROPAGATE_PICK_SIMPLE);
22362236
registerShaderRule("SIMPLE_MESH_PROPAGATE_FACE_VALUE", SIMPLE_MESH_PROPAGATE_FACE_VALUE);
22372237
registerShaderRule("SIMPLE_MESH_PROPAGATE_FACE_COLOR", SIMPLE_MESH_PROPAGATE_FACE_COLOR);
2238-
2238+
registerShaderRule("SIMPLE_MESH_PROPAGATE_FACE_PICK", SIMPLE_MESH_PROPAGATE_FACE_PICK);
2239+
22392240
// volume gridcube things
22402241
registerShaderRule("GRIDCUBE_PROPAGATE_NODE_VALUE", GRIDCUBE_PROPAGATE_NODE_VALUE);
22412242
registerShaderRule("GRIDCUBE_PROPAGATE_CELL_VALUE", GRIDCUBE_PROPAGATE_CELL_VALUE);

src/render/opengl/gl_engine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2718,6 +2718,7 @@ void GLEngine::populateDefaultShadersAndRules() {
27182718
registerShaderRule("MESH_PROPAGATE_PICK_SIMPLE", MESH_PROPAGATE_PICK_SIMPLE);
27192719
registerShaderRule("SIMPLE_MESH_PROPAGATE_FACE_VALUE", SIMPLE_MESH_PROPAGATE_FACE_VALUE);
27202720
registerShaderRule("SIMPLE_MESH_PROPAGATE_FACE_COLOR", SIMPLE_MESH_PROPAGATE_FACE_COLOR);
2721+
registerShaderRule("SIMPLE_MESH_PROPAGATE_FACE_PICK", SIMPLE_MESH_PROPAGATE_FACE_PICK);
27212722

27222723
// volume gridcube things
27232724
registerShaderRule("GRIDCUBE_PROPAGATE_NODE_VALUE", GRIDCUBE_PROPAGATE_NODE_VALUE);

src/render/opengl/shaders/common.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "polyscope/render/opengl/shaders/common.h"
55

6+
#include "polyscope/pick.h" // for POLYSCOPE_PICK_INDEX_TO_COLOR_GLSL
7+
68
namespace polyscope {
79
namespace render {
810
namespace backend_openGL3 {
@@ -437,6 +439,15 @@ bool rayTaperedCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, ve
437439
}
438440
439441
442+
)"
443+
// Define GLSL type names so POLYSCOPE_PICK_INDEX_COLOR_BODY stringifies as GLSL (see pick.ipp).
444+
#define POLYSCOPE_PICK_UINT uint
445+
#define POLYSCOPE_PICK_VEC3 vec3
446+
POLYSCOPE_PICK_INDEX_TO_COLOR_GLSL
447+
#undef POLYSCOPE_PICK_UINT
448+
#undef POLYSCOPE_PICK_VEC3
449+
R"(
450+
440451
bool rayConeIntersection(vec3 rayStart, vec3 rayDir, vec3 coneBase, vec3 coneTip, float coneRad, out float tHit, out vec3 pHit, out vec3 nHit) {
441452
442453
rayDir = normalize(rayDir);
@@ -510,6 +521,6 @@ bool rayConeIntersection(vec3 rayStart, vec3 rayDir, vec3 coneBase, vec3 coneTip
510521
511522
)";
512523

513-
}
524+
} // namespace backend_openGL3
514525
} // namespace render
515526
} // namespace polyscope

src/render/opengl/shaders/surface_mesh_shaders.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,28 @@ const ShaderReplacementRule SIMPLE_MESH_PROPAGATE_FACE_COLOR(
765765
/* textures */ {{"t_faceColors", 1}}
766766
);
767767

768+
// Encodes the pick color for each face directly from gl_PrimitiveID + pickStart, with no texture lookup.
769+
// Delegates encoding to pickIndexToColor() in common.cpp (see there for the bit layout).
770+
const ShaderReplacementRule SIMPLE_MESH_PROPAGATE_FACE_PICK(
771+
/* rule name */ "SIMPLE_MESH_PROPAGATE_FACE_PICK",
772+
{ /* replacement sources */
773+
{"FRAG_DECLARATIONS", R"(
774+
uniform uint u_pickStartLow; // lower 32 bits of the global pick index for face 0
775+
uniform uint u_pickStartHigh; // upper 32 bits of the global pick index for face 0
776+
vec3 pickIndexToColor(uint pickStartLow, uint pickStartHigh, uint primID); // defined in common.cpp
777+
)"},
778+
{"GENERATE_SHADE_VALUE", R"(
779+
vec3 shadeColor = pickIndexToColor(u_pickStartLow, u_pickStartHigh, uint(gl_PrimitiveID));
780+
)"},
781+
},
782+
/* uniforms */ {
783+
{"u_pickStartLow", RenderDataType::UInt},
784+
{"u_pickStartHigh", RenderDataType::UInt},
785+
},
786+
/* attributes */ {},
787+
/* textures */ {}
788+
);
789+
768790
// clang-format on
769791

770792
} // namespace backend_openGL3

0 commit comments

Comments
 (0)