@@ -13,6 +13,8 @@ const uint64_t bitsForPickPacking = 22;
1313
1414inline 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
0 commit comments