Skip to content

Commit 8e692da

Browse files
tmcareynmwsharp
andauthored
Implement volume mesh inspection via slice planes (#129)
* basic geometry shader * Transer * Working slice planes * working handshake * Transitioning to full geometry shader * quick commit * Restructured to slice plane side and picking UI * working :) * Working level sets and slice materials * Working Geometry Slice Planes and Level Sets * Fix Compiler Warnings * Fix Ground Plane Reflections * Improved interface functions * Improve edge rendering * Added python functions and fixed edge rendering * Add space between VolumeMesh * Expose Level Set Functions * Expose more Level Set functions * Added: Support for Hex Meshes (converted to tet meshes when generating geom buffers) * Improved: Hex Mesh support * Quick Commit * Fixed: Hex to Tets for slicing * Improved UI * remove cmake files * return nullptr for empty structure * use persistent values for slice plane options * fix uint for windows builds * more windows compile fixes, lazily populate tets * refactor draw loop, fix include, more refresh checks * change inspect menu to popup * one more missing header * more uint fixes * rename slice --> inspect * hide volume mesh level sets for now * remove unused function * add simple unit test * refactor, add more defensive checks * remove unused logic Co-authored-by: Nicholas Sharp <[email protected]>
1 parent a419ca8 commit 8e692da

18 files changed

+1293
-60
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "polyscope/render/opengl/gl_shaders.h"
4+
5+
namespace polyscope {
6+
namespace render {
7+
namespace backend_openGL3_glfw {
8+
9+
// High level pipeline
10+
extern const ShaderStageSpecification SLICE_TETS_VERT_SHADER;
11+
extern const ShaderStageSpecification SLICE_TETS_GEOM_SHADER;
12+
extern const ShaderStageSpecification SLICE_TETS_FRAG_SHADER;
13+
extern const ShaderReplacementRule SLICE_TETS_BASECOLOR_SHADE;
14+
extern const ShaderReplacementRule SLICE_TETS_MESH_WIREFRAME;
15+
extern const ShaderReplacementRule SLICE_TETS_PROPAGATE_VALUE;
16+
extern const ShaderReplacementRule SLICE_TETS_PROPAGATE_VECTOR;
17+
extern const ShaderReplacementRule SLICE_TETS_VECTOR_COLOR;
18+
19+
20+
} // namespace backend_openGL3_glfw
21+
} // namespace render
22+
} // namespace polyscope

include/polyscope/slice_plane.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace polyscope {
1010

11+
1112
class SlicePlane {
1213

1314
public:
@@ -23,17 +24,21 @@ class SlicePlane {
2324

2425
void buildGUI();
2526
void draw();
27+
void drawGeometry();
28+
void resetVolumeSliceProgram();
29+
void ensureVolumeInspectValid();
2630

2731
void setSceneObjectUniforms(render::ShaderProgram& p,
2832
bool alwaysPass = false); // if alwaysPass, fake values are given so the plane does
2933
// nothing (regardless of this plane's active setting)
34+
void setSliceGeomUniforms(render::ShaderProgram& p);
3035

3136
const std::string name;
3237
const std::string postfix;
33-
38+
3439
// Set the position and orientation of the plane
3540
// planePosition is any 3D position which the plane touches (the center of the plane)
36-
// planeNormal is a vector giving the normal direction of the plane, objects
41+
// planeNormal is a vector giving the normal direction of the plane, objects
3742
// in this negative side of the plane will be culled
3843
void setPose(glm::vec3 planePosition, glm::vec3 planeNormal);
3944

@@ -44,45 +49,57 @@ class SlicePlane {
4449

4550
bool getDrawPlane();
4651
void setDrawPlane(bool newVal);
47-
52+
4853
bool getDrawWidget();
4954
void setDrawWidget(bool newVal);
5055

5156
glm::mat4 getTransform();
5257
void setTransform(glm::mat4 newTransform);
53-
58+
5459
void setColor(glm::vec3 newVal);
5560
glm::vec3 getColor();
56-
61+
5762
void setGridLineColor(glm::vec3 newVal);
5863
glm::vec3 getGridLineColor();
5964

6065
void setTransparency(double newVal);
6166
double getTransparency();
6267

68+
void setVolumeMeshToInspect(std::string meshName);
69+
std::string getVolumeMeshToInspect();
70+
6371
protected:
6472
// = State
65-
PersistentValue<bool> active; // is it actually slicing?
66-
PersistentValue<bool> drawPlane; // do we draw the plane onscreen?
73+
PersistentValue<bool> active; // is it actually slicing?
74+
PersistentValue<bool> drawPlane; // do we draw the plane onscreen?
6775
PersistentValue<bool> drawWidget; // do we draw the widget onscreen?
6876
PersistentValue<glm::mat4> objectTransform;
6977
PersistentValue<glm::vec3> color;
7078
PersistentValue<glm::vec3> gridLineColor;
7179
PersistentValue<float> transparency;
7280

81+
// DON'T make these persistent, because it is unintitive to re-add a scene slice plane and have it immediately start
82+
// slicing
83+
bool shouldInspectMesh;
84+
std::string inspectedMeshName;
85+
86+
std::shared_ptr<render::ShaderProgram> volumeInspectProgram;
87+
7388
// Widget that wraps the transform
7489
TransformationGizmo transformGizmo;
7590

7691
std::shared_ptr<render::ShaderProgram> planeProgram;
7792

7893
// Helpers
94+
void setSliceAttributes(render::ShaderProgram& p);
95+
void createVolumeSliceProgram();
7996
void prepare();
8097
glm::vec3 getCenter();
8198
glm::vec3 getNormal();
8299
void updateWidgetEnabled();
83100
};
84101

85-
SlicePlane* addSceneSlicePlane(bool initiallyVisible=false);
102+
SlicePlane* addSceneSlicePlane(bool initiallyVisible = false);
86103
void removeLastSceneSlicePlane();
87104
void buildSlicePlaneGUI();
88105

include/polyscope/volume_mesh.h

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
#include "polyscope/affine_remapper.h"
88
#include "polyscope/color_management.h"
9-
#include "polyscope/polyscope.h"
109
#include "polyscope/render/engine.h"
1110
#include "polyscope/standardize_data_array.h"
1211
#include "polyscope/structure.h"
@@ -76,7 +75,7 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
7675

7776
// = Vectors (expect vector array, inner type must be indexable with correct dimension (3 for extrinsic, 2 for intrinsic)
7877
template <class T> VolumeMeshVertexVectorQuantity* addVertexVectorQuantity(std::string name, const T& vectors, VectorType vectorType = VectorType::STANDARD);
79-
template <class T> VolumeMeshCellVectorQuantity* addCellVectorQuantity(std::string name, const T& vectors, VectorType vectorType = VectorType::STANDARD);
78+
template <class T> VolumeMeshCellVectorQuantity* addCellVectorQuantity(std::string name, const T& vectors, VectorType vectorType = VectorType::STANDARD);
8079

8180
// clang-format on
8281

@@ -99,7 +98,6 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
9998
size_t faceDataSize;
10099
size_t cellDataSize;
101100

102-
103101
// === Manage the mesh itself
104102

105103
// Core data
@@ -117,15 +115,23 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
117115
std::vector<double> cellAreas;
118116
std::vector<double> faceAreas;
119117
std::vector<double> vertexAreas;
120-
std::vector<char> faceIsInterior; // a flat array whos order matches the iteration order of the mesh
118+
std::vector<char> faceIsInterior; // a flat array whose order matches the iteration order of the mesh
121119

122120
// = Mesh helpers
123121
VolumeCellType cellType(size_t i) const;
124122
void computeCounts(); // call to populate counts and indices
125123
void computeGeometryData(); // call to populate normals/areas/lengths
126-
std::vector<std::string> addVolumeMeshRules(std::vector<std::string> initRules, bool withSurfaceShade = true);
124+
std::vector<std::string> addVolumeMeshRules(std::vector<std::string> initRules, bool withSurfaceShade = true,
125+
bool isSlice = false);
127126
glm::vec3 cellCenter(size_t iC);
128127

128+
// Manage a separate tetrahedral representation used for volumetric visualizations
129+
// (for a pure-tet mesh this will be the same as the cells array)
130+
std::vector<std::array<int64_t, 4>> tets;
131+
size_t nTets();
132+
void computeTets(); // fills tet buffer
133+
void ensureHaveTets(); // ensure the tet buffer is filled (but don't rebuild if already done)
134+
129135
// === Member variables ===
130136
static const std::string structureTypeName;
131137

@@ -152,11 +158,22 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
152158
VolumeMesh* setEdgeWidth(double newVal);
153159
double getEdgeWidth();
154160

161+
VolumeMeshVertexScalarQuantity* getLevelSetQuantity();
162+
void setLevelSetQuantity(VolumeMeshVertexScalarQuantity* _levelSet);
163+
155164
// Rendering helpers used by quantities
156165
void setVolumeMeshUniforms(render::ShaderProgram& p);
157166
void fillGeometryBuffers(render::ShaderProgram& p);
167+
void fillSliceGeometryBuffers(render::ShaderProgram& p);
158168
static const std::vector<std::vector<std::array<size_t, 3>>>& cellStencil(VolumeCellType type);
159169

170+
// Slice plane listeners
171+
std::vector<polyscope::SlicePlane*> volumeSlicePlaneListeners;
172+
void addSlicePlaneListener(polyscope::SlicePlane* sp);
173+
void removeSlicePlaneListener(polyscope::SlicePlane* sp);
174+
void refreshVolumeMeshListeners();
175+
176+
160177
private:
161178
// Visualization settings
162179
PersistentValue<glm::vec3> color;
@@ -165,6 +182,11 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
165182
PersistentValue<std::string> material;
166183
PersistentValue<float> edgeWidth;
167184

185+
// Level sets
186+
// TODO: not currently really supported
187+
float activeLevelSetValue;
188+
VolumeMeshVertexScalarQuantity* activeLevelSetQuantity;
189+
168190
// Do setup work related to drawing, including allocating openGL data
169191
void prepare();
170192
void preparePick();
@@ -200,6 +222,8 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
200222
// clang-format off
201223
static const std::vector<std::vector<std::array<size_t, 3>>> stencilTet;
202224
static const std::vector<std::vector<std::array<size_t, 3>>> stencilHex;
225+
static const std::array<std::array<size_t, 8>, 8> rotationMap;
226+
static const std::array<std::array<std::array<size_t, 4>, 6>, 4> diagonalMap;
203227

204228
// clang-format off
205229

@@ -214,8 +238,8 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
214238

215239
// === Helper implementations
216240

217-
void setVertexTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
218-
void setFaceTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
241+
//void setVertexTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
242+
//void setFaceTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
219243
// clang-format on
220244
};
221245

include/polyscope/volume_mesh_color_quantity.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class VolumeMeshColorQuantity : public VolumeMeshQuantity {
2424
// UI internals
2525
const std::string definedOn;
2626
std::shared_ptr<render::ShaderProgram> program;
27+
std::shared_ptr<render::ShaderProgram> sliceProgram;
2728

2829
// Helpers
2930
virtual void createProgram() = 0;
@@ -38,8 +39,12 @@ class VolumeMeshVertexColorQuantity : public VolumeMeshColorQuantity {
3839
VolumeMeshVertexColorQuantity(std::string name, std::vector<glm::vec3> values_, VolumeMesh& mesh_);
3940

4041
virtual void createProgram() override;
42+
virtual std::shared_ptr<render::ShaderProgram> createSliceProgram() override;
43+
void fillSliceColorBuffers(render::ShaderProgram& p);
4144
void fillColorBuffers(render::ShaderProgram& p);
4245

46+
virtual void drawSlice(polyscope::SlicePlane *sp) override;
47+
4348
void buildVertexInfoGUI(size_t vInd) override;
4449

4550
// === Members

include/polyscope/volume_mesh_quantity.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ class VolumeMeshQuantity : public Quantity<VolumeMesh> {
1515
public:
1616
VolumeMeshQuantity(std::string name, VolumeMesh& parentStructure, bool dominates = false);
1717
~VolumeMeshQuantity() {};
18+
// virtual std::shared_ptr<render::ShaderProgram> tryCreateSliceProgram(){ return nullptr; };
19+
virtual std::shared_ptr<render::ShaderProgram> createSliceProgram(){ return nullptr; };
20+
virtual void drawSlice(polyscope::SlicePlane *sp){};
1821

1922
public:
2023
// Build GUI info about this element

include/polyscope/volume_mesh_scalar_quantity.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class VolumeMeshScalarQuantity : public VolumeMeshQuantity, public ScalarQuantit
2323
protected:
2424
const std::string definedOn;
2525
std::shared_ptr<render::ShaderProgram> program;
26+
std::shared_ptr<render::ShaderProgram> sliceProgram;
2627

2728
// Helpers
2829
virtual void createProgram() = 0;
@@ -38,10 +39,31 @@ class VolumeMeshVertexScalarQuantity : public VolumeMeshScalarQuantity {
3839
DataType dataType_ = DataType::STANDARD);
3940

4041
virtual void createProgram() override;
42+
virtual std::shared_ptr<render::ShaderProgram> createSliceProgram() override;
43+
virtual void draw() override;
44+
virtual void drawSlice(polyscope::SlicePlane *sp) override;
45+
46+
47+
void setLevelSetValue(float f);
48+
void setEnabledLevelSet(bool v);
49+
void setLevelSetVisibleQuantity(std::string name);
50+
void setLevelSetUniforms(render::ShaderProgram &p);
51+
void fillLevelSetData(render::ShaderProgram &p);
52+
std::shared_ptr<render::ShaderProgram> levelSetProgram;
4153

4254
void fillColorBuffers(render::ShaderProgram& p);
4355

56+
void fillSliceColorBuffers(render::ShaderProgram& p);
57+
58+
virtual void buildCustomUI() override;
4459
void buildVertexInfoGUI(size_t vInd) override;
60+
virtual void refresh() override;
61+
62+
float levelSetValue;
63+
bool isDrawingLevelSet;
64+
VolumeMeshVertexScalarQuantity* showQuantity;
65+
66+
4567
};
4668

4769

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ if("${POLYSCOPE_BACKEND_OPENGL3_GLFW}")
2828
render/opengl/shaders/gizmo_shaders.cpp
2929
render/opengl/shaders/histogram_shaders.cpp
3030
render/opengl/shaders/surface_mesh_shaders.cpp
31+
render/opengl/shaders/volume_mesh_shaders.cpp
3132
render/opengl/shaders/vector_shaders.cpp
3233
render/opengl/shaders/sphere_shaders.cpp
3334
render/opengl/shaders/ribbon_shaders.cpp
@@ -85,6 +86,7 @@ if("${POLYSCOPE_BACKEND_OPENGL_MOCK}")
8586
render/opengl/shaders/gizmo_shaders.cpp
8687
render/opengl/shaders/histogram_shaders.cpp
8788
render/opengl/shaders/surface_mesh_shaders.cpp
89+
render/opengl/shaders/volume_mesh_shaders.cpp
8890
render/opengl/shaders/vector_shaders.cpp
8991
render/opengl/shaders/sphere_shaders.cpp
9092
render/opengl/shaders/ribbon_shaders.cpp

src/polyscope.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,13 @@ void drawStructures() {
207207
s.second->draw();
208208
}
209209
}
210+
211+
// Also render any slice plane geometry
212+
for (SlicePlane* s : state::slicePlanes) {
213+
s->drawGeometry();
214+
}
210215
}
211216

212-
213217
namespace {
214218

215219
float dragDistSinceLastRelease = 0.0;
@@ -331,6 +335,7 @@ void processInputEvents() {
331335
}
332336
}
333337

338+
334339
void renderSlicePlanes() {
335340
for (SlicePlane* s : state::slicePlanes) {
336341
s->draw();
@@ -791,6 +796,8 @@ bool registerStructure(Structure* s, bool replaceIfPresent) {
791796

792797
Structure* getStructure(std::string type, std::string name) {
793798

799+
if (type == "" || name == "") return nullptr;
800+
794801
// If there are no structures of that type it is an automatic fail
795802
if (state::structures.find(type) == state::structures.end()) {
796803
error("No structures of type " + type + " registered");

src/render/mock_opengl/mock_gl_engine.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "polyscope/render/opengl/shaders/surface_mesh_shaders.h"
2323
#include "polyscope/render/opengl/shaders/texture_draw_shaders.h"
2424
#include "polyscope/render/opengl/shaders/vector_shaders.h"
25+
#include "polyscope/render/opengl/shaders/volume_mesh_shaders.h"
2526

2627

2728
#include "stb_image.h"
@@ -1365,6 +1366,7 @@ void MockGLEngine::populateDefaultShadersAndRules() {
13651366

13661367
// == Load general base shaders
13671368
registeredShaderPrograms.insert({"MESH", {{FLEX_MESH_VERT_SHADER, FLEX_MESH_FRAG_SHADER}, DrawMode::Triangles}});
1369+
registeredShaderPrograms.insert({"SLICE_TETS", {{SLICE_TETS_VERT_SHADER, SLICE_TETS_GEOM_SHADER, SLICE_TETS_FRAG_SHADER}, DrawMode::Triangles}});
13681370
registeredShaderPrograms.insert({"RAYCAST_SPHERE", {{FLEX_SPHERE_VERT_SHADER, FLEX_SPHERE_GEOM_SHADER, FLEX_SPHERE_FRAG_SHADER}, DrawMode::Points}});
13691371
registeredShaderPrograms.insert({"POINT_QUAD", {{FLEX_POINTQUAD_VERT_SHADER, FLEX_POINTQUAD_GEOM_SHADER, FLEX_POINTQUAD_FRAG_SHADER}, DrawMode::Points}});
13701372
registeredShaderPrograms.insert({"RAYCAST_VECTOR", {{FLEX_VECTOR_VERT_SHADER, FLEX_VECTOR_GEOM_SHADER, FLEX_VECTOR_FRAG_SHADER}, DrawMode::Points}});
@@ -1455,6 +1457,14 @@ void MockGLEngine::populateDefaultShadersAndRules() {
14551457
registeredShaderRules.insert({"CYLINDER_PROPAGATE_PICK", CYLINDER_PROPAGATE_PICK});
14561458
registeredShaderRules.insert({"CYLINDER_CULLPOS_FROM_MID", CYLINDER_CULLPOS_FROM_MID});
14571459

1460+
// marching tets things
1461+
registeredShaderRules.insert({"SLICE_TETS_BASECOLOR_SHADE", SLICE_TETS_BASECOLOR_SHADE});
1462+
registeredShaderRules.insert({"SLICE_TETS_PROPAGATE_VALUE", SLICE_TETS_PROPAGATE_VALUE});
1463+
registeredShaderRules.insert({"SLICE_TETS_PROPAGATE_VECTOR", SLICE_TETS_PROPAGATE_VECTOR});
1464+
registeredShaderRules.insert({"SLICE_TETS_VECTOR_COLOR", SLICE_TETS_VECTOR_COLOR});
1465+
registeredShaderRules.insert({"SLICE_TETS_MESH_WIREFRAME", SLICE_TETS_MESH_WIREFRAME});
1466+
1467+
14581468
// clang-format on
14591469
};
14601470

0 commit comments

Comments
 (0)