Skip to content

Commit

Permalink
Implement volume mesh inspection via slice planes (#129)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
tmcarey and nmwsharp authored Dec 1, 2021
1 parent a419ca8 commit 8e692da
Show file tree
Hide file tree
Showing 18 changed files with 1,293 additions and 60 deletions.
22 changes: 22 additions & 0 deletions include/polyscope/render/opengl/shaders/volume_mesh_shaders.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "polyscope/render/opengl/gl_shaders.h"

namespace polyscope {
namespace render {
namespace backend_openGL3_glfw {

// High level pipeline
extern const ShaderStageSpecification SLICE_TETS_VERT_SHADER;
extern const ShaderStageSpecification SLICE_TETS_GEOM_SHADER;
extern const ShaderStageSpecification SLICE_TETS_FRAG_SHADER;
extern const ShaderReplacementRule SLICE_TETS_BASECOLOR_SHADE;
extern const ShaderReplacementRule SLICE_TETS_MESH_WIREFRAME;
extern const ShaderReplacementRule SLICE_TETS_PROPAGATE_VALUE;
extern const ShaderReplacementRule SLICE_TETS_PROPAGATE_VECTOR;
extern const ShaderReplacementRule SLICE_TETS_VECTOR_COLOR;


} // namespace backend_openGL3_glfw
} // namespace render
} // namespace polyscope
33 changes: 25 additions & 8 deletions include/polyscope/slice_plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace polyscope {


class SlicePlane {

public:
Expand All @@ -23,17 +24,21 @@ class SlicePlane {

void buildGUI();
void draw();
void drawGeometry();
void resetVolumeSliceProgram();
void ensureVolumeInspectValid();

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

const std::string name;
const std::string postfix;

// Set the position and orientation of the plane
// planePosition is any 3D position which the plane touches (the center of the plane)
// planeNormal is a vector giving the normal direction of the plane, objects
// planeNormal is a vector giving the normal direction of the plane, objects
// in this negative side of the plane will be culled
void setPose(glm::vec3 planePosition, glm::vec3 planeNormal);

Expand All @@ -44,45 +49,57 @@ class SlicePlane {

bool getDrawPlane();
void setDrawPlane(bool newVal);

bool getDrawWidget();
void setDrawWidget(bool newVal);

glm::mat4 getTransform();
void setTransform(glm::mat4 newTransform);

void setColor(glm::vec3 newVal);
glm::vec3 getColor();

void setGridLineColor(glm::vec3 newVal);
glm::vec3 getGridLineColor();

void setTransparency(double newVal);
double getTransparency();

void setVolumeMeshToInspect(std::string meshName);
std::string getVolumeMeshToInspect();

protected:
// = State
PersistentValue<bool> active; // is it actually slicing?
PersistentValue<bool> drawPlane; // do we draw the plane onscreen?
PersistentValue<bool> active; // is it actually slicing?
PersistentValue<bool> drawPlane; // do we draw the plane onscreen?
PersistentValue<bool> drawWidget; // do we draw the widget onscreen?
PersistentValue<glm::mat4> objectTransform;
PersistentValue<glm::vec3> color;
PersistentValue<glm::vec3> gridLineColor;
PersistentValue<float> transparency;

// DON'T make these persistent, because it is unintitive to re-add a scene slice plane and have it immediately start
// slicing
bool shouldInspectMesh;
std::string inspectedMeshName;

std::shared_ptr<render::ShaderProgram> volumeInspectProgram;

// Widget that wraps the transform
TransformationGizmo transformGizmo;

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

// Helpers
void setSliceAttributes(render::ShaderProgram& p);
void createVolumeSliceProgram();
void prepare();
glm::vec3 getCenter();
glm::vec3 getNormal();
void updateWidgetEnabled();
};

SlicePlane* addSceneSlicePlane(bool initiallyVisible=false);
SlicePlane* addSceneSlicePlane(bool initiallyVisible = false);
void removeLastSceneSlicePlane();
void buildSlicePlaneGUI();

Expand Down
38 changes: 31 additions & 7 deletions include/polyscope/volume_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "polyscope/affine_remapper.h"
#include "polyscope/color_management.h"
#include "polyscope/polyscope.h"
#include "polyscope/render/engine.h"
#include "polyscope/standardize_data_array.h"
#include "polyscope/structure.h"
Expand Down Expand Up @@ -76,7 +75,7 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {

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

// clang-format on

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


// === Manage the mesh itself

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

// = Mesh helpers
VolumeCellType cellType(size_t i) const;
void computeCounts(); // call to populate counts and indices
void computeGeometryData(); // call to populate normals/areas/lengths
std::vector<std::string> addVolumeMeshRules(std::vector<std::string> initRules, bool withSurfaceShade = true);
std::vector<std::string> addVolumeMeshRules(std::vector<std::string> initRules, bool withSurfaceShade = true,
bool isSlice = false);
glm::vec3 cellCenter(size_t iC);

// Manage a separate tetrahedral representation used for volumetric visualizations
// (for a pure-tet mesh this will be the same as the cells array)
std::vector<std::array<int64_t, 4>> tets;
size_t nTets();
void computeTets(); // fills tet buffer
void ensureHaveTets(); // ensure the tet buffer is filled (but don't rebuild if already done)

// === Member variables ===
static const std::string structureTypeName;

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

VolumeMeshVertexScalarQuantity* getLevelSetQuantity();
void setLevelSetQuantity(VolumeMeshVertexScalarQuantity* _levelSet);

// Rendering helpers used by quantities
void setVolumeMeshUniforms(render::ShaderProgram& p);
void fillGeometryBuffers(render::ShaderProgram& p);
void fillSliceGeometryBuffers(render::ShaderProgram& p);
static const std::vector<std::vector<std::array<size_t, 3>>>& cellStencil(VolumeCellType type);

// Slice plane listeners
std::vector<polyscope::SlicePlane*> volumeSlicePlaneListeners;
void addSlicePlaneListener(polyscope::SlicePlane* sp);
void removeSlicePlaneListener(polyscope::SlicePlane* sp);
void refreshVolumeMeshListeners();


private:
// Visualization settings
PersistentValue<glm::vec3> color;
Expand All @@ -165,6 +182,11 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
PersistentValue<std::string> material;
PersistentValue<float> edgeWidth;

// Level sets
// TODO: not currently really supported
float activeLevelSetValue;
VolumeMeshVertexScalarQuantity* activeLevelSetQuantity;

// Do setup work related to drawing, including allocating openGL data
void prepare();
void preparePick();
Expand Down Expand Up @@ -200,6 +222,8 @@ class VolumeMesh : public QuantityStructure<VolumeMesh> {
// clang-format off
static const std::vector<std::vector<std::array<size_t, 3>>> stencilTet;
static const std::vector<std::vector<std::array<size_t, 3>>> stencilHex;
static const std::array<std::array<size_t, 8>, 8> rotationMap;
static const std::array<std::array<std::array<size_t, 4>, 6>, 4> diagonalMap;

// clang-format off

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

// === Helper implementations

void setVertexTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
void setFaceTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
//void setVertexTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
//void setFaceTangentBasisXImpl(const std::vector<glm::vec3>& vectors);
// clang-format on
};

Expand Down
5 changes: 5 additions & 0 deletions include/polyscope/volume_mesh_color_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class VolumeMeshColorQuantity : public VolumeMeshQuantity {
// UI internals
const std::string definedOn;
std::shared_ptr<render::ShaderProgram> program;
std::shared_ptr<render::ShaderProgram> sliceProgram;

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

virtual void createProgram() override;
virtual std::shared_ptr<render::ShaderProgram> createSliceProgram() override;
void fillSliceColorBuffers(render::ShaderProgram& p);
void fillColorBuffers(render::ShaderProgram& p);

virtual void drawSlice(polyscope::SlicePlane *sp) override;

void buildVertexInfoGUI(size_t vInd) override;

// === Members
Expand Down
3 changes: 3 additions & 0 deletions include/polyscope/volume_mesh_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class VolumeMeshQuantity : public Quantity<VolumeMesh> {
public:
VolumeMeshQuantity(std::string name, VolumeMesh& parentStructure, bool dominates = false);
~VolumeMeshQuantity() {};
// virtual std::shared_ptr<render::ShaderProgram> tryCreateSliceProgram(){ return nullptr; };
virtual std::shared_ptr<render::ShaderProgram> createSliceProgram(){ return nullptr; };
virtual void drawSlice(polyscope::SlicePlane *sp){};

public:
// Build GUI info about this element
Expand Down
22 changes: 22 additions & 0 deletions include/polyscope/volume_mesh_scalar_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class VolumeMeshScalarQuantity : public VolumeMeshQuantity, public ScalarQuantit
protected:
const std::string definedOn;
std::shared_ptr<render::ShaderProgram> program;
std::shared_ptr<render::ShaderProgram> sliceProgram;

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

virtual void createProgram() override;
virtual std::shared_ptr<render::ShaderProgram> createSliceProgram() override;
virtual void draw() override;
virtual void drawSlice(polyscope::SlicePlane *sp) override;


void setLevelSetValue(float f);
void setEnabledLevelSet(bool v);
void setLevelSetVisibleQuantity(std::string name);
void setLevelSetUniforms(render::ShaderProgram &p);
void fillLevelSetData(render::ShaderProgram &p);
std::shared_ptr<render::ShaderProgram> levelSetProgram;

void fillColorBuffers(render::ShaderProgram& p);

void fillSliceColorBuffers(render::ShaderProgram& p);

virtual void buildCustomUI() override;
void buildVertexInfoGUI(size_t vInd) override;
virtual void refresh() override;

float levelSetValue;
bool isDrawingLevelSet;
VolumeMeshVertexScalarQuantity* showQuantity;


};


Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ if("${POLYSCOPE_BACKEND_OPENGL3_GLFW}")
render/opengl/shaders/gizmo_shaders.cpp
render/opengl/shaders/histogram_shaders.cpp
render/opengl/shaders/surface_mesh_shaders.cpp
render/opengl/shaders/volume_mesh_shaders.cpp
render/opengl/shaders/vector_shaders.cpp
render/opengl/shaders/sphere_shaders.cpp
render/opengl/shaders/ribbon_shaders.cpp
Expand Down Expand Up @@ -85,6 +86,7 @@ if("${POLYSCOPE_BACKEND_OPENGL_MOCK}")
render/opengl/shaders/gizmo_shaders.cpp
render/opengl/shaders/histogram_shaders.cpp
render/opengl/shaders/surface_mesh_shaders.cpp
render/opengl/shaders/volume_mesh_shaders.cpp
render/opengl/shaders/vector_shaders.cpp
render/opengl/shaders/sphere_shaders.cpp
render/opengl/shaders/ribbon_shaders.cpp
Expand Down
9 changes: 8 additions & 1 deletion src/polyscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,13 @@ void drawStructures() {
s.second->draw();
}
}

// Also render any slice plane geometry
for (SlicePlane* s : state::slicePlanes) {
s->drawGeometry();
}
}


namespace {

float dragDistSinceLastRelease = 0.0;
Expand Down Expand Up @@ -331,6 +335,7 @@ void processInputEvents() {
}
}


void renderSlicePlanes() {
for (SlicePlane* s : state::slicePlanes) {
s->draw();
Expand Down Expand Up @@ -791,6 +796,8 @@ bool registerStructure(Structure* s, bool replaceIfPresent) {

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

if (type == "" || name == "") return nullptr;

// If there are no structures of that type it is an automatic fail
if (state::structures.find(type) == state::structures.end()) {
error("No structures of type " + type + " registered");
Expand Down
10 changes: 10 additions & 0 deletions src/render/mock_opengl/mock_gl_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "polyscope/render/opengl/shaders/surface_mesh_shaders.h"
#include "polyscope/render/opengl/shaders/texture_draw_shaders.h"
#include "polyscope/render/opengl/shaders/vector_shaders.h"
#include "polyscope/render/opengl/shaders/volume_mesh_shaders.h"


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

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

// marching tets things
registeredShaderRules.insert({"SLICE_TETS_BASECOLOR_SHADE", SLICE_TETS_BASECOLOR_SHADE});
registeredShaderRules.insert({"SLICE_TETS_PROPAGATE_VALUE", SLICE_TETS_PROPAGATE_VALUE});
registeredShaderRules.insert({"SLICE_TETS_PROPAGATE_VECTOR", SLICE_TETS_PROPAGATE_VECTOR});
registeredShaderRules.insert({"SLICE_TETS_VECTOR_COLOR", SLICE_TETS_VECTOR_COLOR});
registeredShaderRules.insert({"SLICE_TETS_MESH_WIREFRAME", SLICE_TETS_MESH_WIREFRAME});


// clang-format on
};

Expand Down
Loading

0 comments on commit 8e692da

Please sign in to comment.