From b48cc3a49f4e50dcd764a6cfb12efbf7a720f972 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Thu, 15 Aug 2024 21:57:26 -0700 Subject: [PATCH] add per-element depth for meshes and point clouds --- include/polyscope/point_cloud.h | 14 ++++ .../render/opengl/shaders/sphere_shaders.h | 1 + .../opengl/shaders/surface_mesh_shaders.h | 1 + include/polyscope/surface_mesh.h | 15 ++++ include/polyscope/surface_scalar_quantity.h | 17 +++-- src/point_cloud.cpp | 66 +++++++++++++++++- src/render/mock_opengl/mock_gl_engine.cpp | 2 + src/render/opengl/gl_engine.cpp | 2 + .../opengl/shaders/lighting_shaders.cpp | 4 +- src/render/opengl/shaders/sphere_shaders.cpp | 31 +++++++++ .../opengl/shaders/surface_mesh_shaders.cpp | 24 +++++++ src/surface_mesh.cpp | 69 +++++++++++++++++++ src/surface_scalar_quantity.cpp | 22 ++++++ test/src/point_cloud_test.cpp | 37 ++++++++++ test/src/surface_mesh_test.cpp | 40 +++++++++++ 15 files changed, 335 insertions(+), 10 deletions(-) diff --git a/include/polyscope/point_cloud.h b/include/polyscope/point_cloud.h index c58efea8..3627d460 100644 --- a/include/polyscope/point_cloud.h +++ b/include/polyscope/point_cloud.h @@ -102,6 +102,13 @@ class PointCloud : public QuantityStructure { void setPointRadiusQuantity(std::string name, bool autoScale = true); void clearPointRadiusQuantity(); + // === Set transparency alpha from a scalar quantity + // effect is multiplicative with other transparency values + // values are clamped to [0,1] + void setTransparencyQuantity(PointCloudScalarQuantity* quantity); + void setTransparencyQuantity(std::string name); + void clearTransparencyQuantity(); + // The points that make up this point cloud // Normally, the values are stored here. But if the render buffer // is being manually updated, they will live only in the render buffer @@ -174,9 +181,16 @@ class PointCloud : public QuantityStructure { // Manage varying point size // which (scalar) quantity to set point size from + // TODO make these PersistentValue<>? std::string pointRadiusQuantityName = ""; // empty string means none bool pointRadiusQuantityAutoscale = true; PointCloudScalarQuantity& resolvePointRadiusQuantity(); // helper + + // Manage per-element transparency + // which (scalar) quantity to set point size from + // TODO make these PersistentValue<>? + std::string transparencyQuantityName = ""; // empty string means none + PointCloudScalarQuantity& resolveTransparencyQuantity(); // helper }; diff --git a/include/polyscope/render/opengl/shaders/sphere_shaders.h b/include/polyscope/render/opengl/shaders/sphere_shaders.h index a447e2e6..203eafec 100644 --- a/include/polyscope/render/opengl/shaders/sphere_shaders.h +++ b/include/polyscope/render/opengl/shaders/sphere_shaders.h @@ -19,6 +19,7 @@ extern const ShaderStageSpecification FLEX_POINTQUAD_FRAG_SHADER; // Rules specific to spheres extern const ShaderReplacementRule SPHERE_PROPAGATE_VALUE; +extern const ShaderReplacementRule SPHERE_PROPAGATE_VALUEALPHA; extern const ShaderReplacementRule SPHERE_PROPAGATE_VALUE2; extern const ShaderReplacementRule SPHERE_PROPAGATE_COLOR; extern const ShaderReplacementRule SPHERE_VARIABLE_SIZE; diff --git a/include/polyscope/render/opengl/shaders/surface_mesh_shaders.h b/include/polyscope/render/opengl/shaders/surface_mesh_shaders.h index 34a87ca5..81c61ac4 100644 --- a/include/polyscope/render/opengl/shaders/surface_mesh_shaders.h +++ b/include/polyscope/render/opengl/shaders/surface_mesh_shaders.h @@ -24,6 +24,7 @@ extern const ShaderReplacementRule MESH_BACKFACE_NORMAL_FLIP; extern const ShaderReplacementRule MESH_BACKFACE_DIFFERENT; extern const ShaderReplacementRule MESH_BACKFACE_DARKEN; extern const ShaderReplacementRule MESH_PROPAGATE_VALUE; +extern const ShaderReplacementRule MESH_PROPAGATE_VALUEALPHA; extern const ShaderReplacementRule MESH_PROPAGATE_FLAT_VALUE; extern const ShaderReplacementRule MESH_PROPAGATE_INT; extern const ShaderReplacementRule MESH_PROPAGATE_VALUE2; diff --git a/include/polyscope/surface_mesh.h b/include/polyscope/surface_mesh.h index da151b70..0d752913 100644 --- a/include/polyscope/surface_mesh.h +++ b/include/polyscope/surface_mesh.h @@ -29,6 +29,7 @@ namespace polyscope { class SurfaceVertexColorQuantity; class SurfaceFaceColorQuantity; class SurfaceTextureColorQuantity; +class SurfaceScalarQuantity; class SurfaceVertexScalarQuantity; class SurfaceFaceScalarQuantity; class SurfaceEdgeScalarQuantity; @@ -176,6 +177,13 @@ class SurfaceMesh : public QuantityStructure { template void updateVertexPositions2D(const V& newPositions2D); + // === Set transparency alpha from a scalar quantity + // effect is multiplicative with other transparency values + // values are clamped to [0,1] + void setTransparencyQuantity(SurfaceScalarQuantity* quantity); + void setTransparencyQuantity(std::string name); + void clearTransparencyQuantity(); + // === Indexing conventions @@ -376,6 +384,13 @@ class SurfaceMesh : public QuantityStructure { void buildHalfedgeInfoGui(size_t heInd); void buildCornerInfoGui(size_t cInd); + // Manage per-element transparency + // which (scalar) quantity to set point size from + // TODO make these PersistentValue<>? + std::string transparencyQuantityName = ""; // empty string means none + SurfaceScalarQuantity& resolveTransparencyQuantity(); // helper + + // ==== Gui implementation details std::shared_ptr program; diff --git a/include/polyscope/surface_scalar_quantity.h b/include/polyscope/surface_scalar_quantity.h index 9cf9969f..3d73c8eb 100644 --- a/include/polyscope/surface_scalar_quantity.h +++ b/include/polyscope/surface_scalar_quantity.h @@ -28,8 +28,11 @@ class SurfaceScalarQuantity : public SurfaceMeshQuantity, public ScalarQuantity< virtual std::string niceName() override; virtual void refresh() override; -protected: + virtual std::shared_ptr getAttributeBuffer() = 0; + const std::string definedOn; + +protected: std::shared_ptr program; // Helpers @@ -47,6 +50,8 @@ class SurfaceVertexScalarQuantity : public SurfaceScalarQuantity { virtual void createProgram() override; + virtual std::shared_ptr getAttributeBuffer() override; + void buildVertexInfoGUI(size_t vInd) override; }; @@ -61,7 +66,7 @@ class SurfaceFaceScalarQuantity : public SurfaceScalarQuantity { DataType dataType_ = DataType::STANDARD); virtual void createProgram() override; - + virtual std::shared_ptr getAttributeBuffer() override; void buildFaceInfoGUI(size_t fInd) override; }; @@ -76,7 +81,7 @@ class SurfaceEdgeScalarQuantity : public SurfaceScalarQuantity { DataType dataType_ = DataType::STANDARD); virtual void createProgram() override; - + virtual std::shared_ptr getAttributeBuffer() override; void buildEdgeInfoGUI(size_t edgeInd) override; }; @@ -90,7 +95,7 @@ class SurfaceHalfedgeScalarQuantity : public SurfaceScalarQuantity { DataType dataType_ = DataType::STANDARD); virtual void createProgram() override; - + virtual std::shared_ptr getAttributeBuffer() override; void buildHalfedgeInfoGUI(size_t heInd) override; }; @@ -104,7 +109,7 @@ class SurfaceCornerScalarQuantity : public SurfaceScalarQuantity { DataType dataType_ = DataType::STANDARD); virtual void createProgram() override; - + virtual std::shared_ptr getAttributeBuffer() override; void buildCornerInfoGUI(size_t heInd) override; }; @@ -119,6 +124,8 @@ class SurfaceTextureScalarQuantity : public SurfaceScalarQuantity { DataType dataType_ = DataType::STANDARD); virtual void createProgram() override; + virtual std::shared_ptr getAttributeBuffer() override; + protected: SurfaceParameterizationQuantity& param; diff --git a/src/point_cloud.cpp b/src/point_cloud.cpp index aa9dd198..47009ee9 100644 --- a/src/point_cloud.cpp +++ b/src/point_cloud.cpp @@ -185,6 +185,10 @@ void PointCloud::setPointProgramGeometryAttributes(render::ShaderProgram& p) { PointCloudScalarQuantity& radQ = resolvePointRadiusQuantity(); p.setAttribute("a_pointRadius", radQ.values.getRenderAttributeBuffer()); } + if (transparencyQuantityName != "") { + PointCloudScalarQuantity& transparencyQ = resolveTransparencyQuantity(); + p.setAttribute("a_valueAlpha", transparencyQ.values.getRenderAttributeBuffer()); + } } std::string PointCloud::getShaderNameForRenderMode() { @@ -212,6 +216,9 @@ std::vector PointCloud::addPointCloudRules(std::vector else if (getPointRenderMode() == PointRenderMode::Quad) initRules.push_back("SPHERE_CULLPOS_FROM_CENTER_QUAD"); } + if (transparencyQuantityName != "") { + initRules.push_back("SPHERE_PROPAGATE_VALUEALPHA"); + } } return initRules; } @@ -268,6 +275,11 @@ void PointCloud::buildCustomUI() { } void PointCloud::buildCustomOptionsUI() { + if (render::buildMaterialOptionsGui(material.get())) { + material.manuallyChanged(); + setMaterial(material.get()); // trigger the other updates that happen on set() + } + if (ImGui::BeginMenu("Point Render Mode")) { for (const PointRenderMode& m : {PointRenderMode::Sphere, PointRenderMode::Quad}) { @@ -305,9 +317,21 @@ void PointCloud::buildCustomOptionsUI() { ImGui::EndMenu(); } - if (render::buildMaterialOptionsGui(material.get())) { - material.manuallyChanged(); - setMaterial(material.get()); // trigger the other updates that happen on set() + // transparency quantity + if (ImGui::BeginMenu("Per-Point Transparency")) { + + if (ImGui::MenuItem("none", nullptr, transparencyQuantityName == "")) clearTransparencyQuantity(); + ImGui::Separator(); + + for (auto& q : quantities) { + PointCloudScalarQuantity* scalarQ = dynamic_cast(q.second.get()); + if (scalarQ != nullptr) { + if (ImGui::MenuItem(scalarQ->name.c_str(), nullptr, transparencyQuantityName == scalarQ->name)) + setTransparencyQuantity(scalarQ); + } + } + + ImGui::EndMenu(); } } @@ -362,6 +386,42 @@ void PointCloud::clearPointRadiusQuantity() { refresh(); } +void PointCloud::setTransparencyQuantity(PointCloudScalarQuantity* quantity) { + setTransparencyQuantity(quantity->name); +} + +void PointCloud::setTransparencyQuantity(std::string name) { + transparencyQuantityName = name; + resolveTransparencyQuantity(); // do it once, just so we fail fast if it doesn't exist + + // if transparency is disabled, enable it + if (options::transparencyMode == TransparencyMode::None) { + options::transparencyMode = TransparencyMode::Pretty; + } + + refresh(); +} + +void PointCloud::clearTransparencyQuantity() { + transparencyQuantityName = ""; + refresh(); +} + +PointCloudScalarQuantity& PointCloud::resolveTransparencyQuantity() { + PointCloudScalarQuantity* transparencyScalarQ = nullptr; + PointCloudQuantity* anyQ = getQuantity(transparencyQuantityName); + if (anyQ != nullptr) { + transparencyScalarQ = dynamic_cast(anyQ); + if (transparencyScalarQ == nullptr) { + exception("Cannot populate per-element transparency from quantity [" + name + "], it is not a scalar quantity"); + } + } else { + exception("Cannot populate per-element transparency from quantity [" + name + "], it does not exist"); + } + + return *transparencyScalarQ; +} + // === Quantities // Quantity default methods diff --git a/src/render/mock_opengl/mock_gl_engine.cpp b/src/render/mock_opengl/mock_gl_engine.cpp index 5d362604..6b33aef2 100644 --- a/src/render/mock_opengl/mock_gl_engine.cpp +++ b/src/render/mock_opengl/mock_gl_engine.cpp @@ -1981,6 +1981,7 @@ void MockGLEngine::populateDefaultShadersAndRules() { registerShaderRule("MESH_BACKFACE_DIFFERENT", MESH_BACKFACE_DIFFERENT); registerShaderRule("MESH_BACKFACE_DARKEN", MESH_BACKFACE_DARKEN); registerShaderRule("MESH_PROPAGATE_VALUE", MESH_PROPAGATE_VALUE); + registerShaderRule("MESH_PROPAGATE_VALUEALPHA", MESH_PROPAGATE_VALUEALPHA); registerShaderRule("MESH_PROPAGATE_FLAT_VALUE", MESH_PROPAGATE_FLAT_VALUE); registerShaderRule("MESH_PROPAGATE_VALUE2", MESH_PROPAGATE_VALUE2); registerShaderRule("MESH_PROPAGATE_TCOORD", MESH_PROPAGATE_TCOORD); @@ -2000,6 +2001,7 @@ void MockGLEngine::populateDefaultShadersAndRules() { // sphere things registerShaderRule("SPHERE_PROPAGATE_VALUE", SPHERE_PROPAGATE_VALUE); + registerShaderRule("SPHERE_PROPAGATE_VALUEALPHA", SPHERE_PROPAGATE_VALUEALPHA); registerShaderRule("SPHERE_PROPAGATE_VALUE2", SPHERE_PROPAGATE_VALUE2); registerShaderRule("SPHERE_PROPAGATE_COLOR", SPHERE_PROPAGATE_COLOR); registerShaderRule("SPHERE_CULLPOS_FROM_CENTER", SPHERE_CULLPOS_FROM_CENTER); diff --git a/src/render/opengl/gl_engine.cpp b/src/render/opengl/gl_engine.cpp index f493ca19..bc5a70fa 100644 --- a/src/render/opengl/gl_engine.cpp +++ b/src/render/opengl/gl_engine.cpp @@ -2540,6 +2540,7 @@ void GLEngine::populateDefaultShadersAndRules() { registerShaderRule("MESH_BACKFACE_DIFFERENT", MESH_BACKFACE_DIFFERENT); registerShaderRule("MESH_BACKFACE_DARKEN", MESH_BACKFACE_DARKEN); registerShaderRule("MESH_PROPAGATE_VALUE", MESH_PROPAGATE_VALUE); + registerShaderRule("MESH_PROPAGATE_VALUEALPHA", MESH_PROPAGATE_VALUEALPHA); registerShaderRule("MESH_PROPAGATE_FLAT_VALUE", MESH_PROPAGATE_FLAT_VALUE); registerShaderRule("MESH_PROPAGATE_VALUE2", MESH_PROPAGATE_VALUE2); registerShaderRule("MESH_PROPAGATE_TCOORD", MESH_PROPAGATE_TCOORD); @@ -2559,6 +2560,7 @@ void GLEngine::populateDefaultShadersAndRules() { // sphere things registerShaderRule("SPHERE_PROPAGATE_VALUE", SPHERE_PROPAGATE_VALUE); + registerShaderRule("SPHERE_PROPAGATE_VALUEALPHA", SPHERE_PROPAGATE_VALUEALPHA); registerShaderRule("SPHERE_PROPAGATE_VALUE2", SPHERE_PROPAGATE_VALUE2); registerShaderRule("SPHERE_PROPAGATE_COLOR", SPHERE_PROPAGATE_COLOR); registerShaderRule("SPHERE_CULLPOS_FROM_CENTER", SPHERE_CULLPOS_FROM_CENTER); diff --git a/src/render/opengl/shaders/lighting_shaders.cpp b/src/render/opengl/shaders/lighting_shaders.cpp index b2e009ee..bfe850f4 100644 --- a/src/render/opengl/shaders/lighting_shaders.cpp +++ b/src/render/opengl/shaders/lighting_shaders.cpp @@ -238,7 +238,7 @@ const ShaderReplacementRule TRANSPARENCY_STRUCTURE ( uniform float u_transparency; )"}, {"GENERATE_ALPHA", R"( - alphaOut = u_transparency; + alphaOut *= u_transparency; )"}, }, /* uniforms */ { @@ -257,7 +257,7 @@ const ShaderReplacementRule TRANSPARENCY_PEEL_STRUCTURE ( uniform vec2 u_viewportDim; )"}, {"GENERATE_ALPHA", R"( - alphaOut = u_transparency; + alphaOut *= u_transparency; )"}, {"GLOBAL_FRAGMENT_FILTER", R"( // assumption: "float depth" must be already set diff --git a/src/render/opengl/shaders/sphere_shaders.cpp b/src/render/opengl/shaders/sphere_shaders.cpp index b140a95b..f4f1eb59 100644 --- a/src/render/opengl/shaders/sphere_shaders.cpp +++ b/src/render/opengl/shaders/sphere_shaders.cpp @@ -386,6 +386,37 @@ const ShaderReplacementRule SPHERE_PROPAGATE_VALUE ( /* textures */ {} ); +const ShaderReplacementRule SPHERE_PROPAGATE_VALUEALPHA ( + /* rule name */ "SPHERE_PROPAGATE_VALUEALPHA", + { /* replacement sources */ + {"VERT_DECLARATIONS", R"( + in float a_valueAlpha; + out float a_valueAlphaToGeom; + )"}, + {"VERT_ASSIGNMENTS", R"( + a_valueAlphaToGeom = a_valueAlpha; + )"}, + {"GEOM_DECLARATIONS", R"( + in float a_valueAlphaToGeom[]; + out float a_valueAlphaToFrag; + )"}, + {"GEOM_PER_EMIT", R"( + a_valueAlphaToFrag = a_valueAlphaToGeom[0]; + )"}, + {"FRAG_DECLARATIONS", R"( + in float a_valueAlphaToFrag; + )"}, + {"GENERATE_ALPHA", R"( + alphaOut *= clamp(a_valueAlphaToFrag, 0.f, 1.f); + )"}, + }, + /* uniforms */ {}, + /* attributes */ { + {"a_valueAlpha", RenderDataType::Float}, + }, + /* textures */ {} +); + const ShaderReplacementRule SPHERE_PROPAGATE_VALUE2 ( /* rule name */ "SPHERE_PROPAGATE_VALUE2", { /* replacement sources */ diff --git a/src/render/opengl/shaders/surface_mesh_shaders.cpp b/src/render/opengl/shaders/surface_mesh_shaders.cpp index 97643655..2b1b3ee5 100644 --- a/src/render/opengl/shaders/surface_mesh_shaders.cpp +++ b/src/render/opengl/shaders/surface_mesh_shaders.cpp @@ -256,6 +256,30 @@ const ShaderReplacementRule MESH_PROPAGATE_VALUE ( /* textures */ {} ); +const ShaderReplacementRule MESH_PROPAGATE_VALUEALPHA ( + /* rule name */ "MESH_PROPAGATE_VALUEALPHA", + { /* replacement sources */ + {"VERT_DECLARATIONS", R"( + in float a_valueAlpha; + out float a_valueAlphaToFrag; + )"}, + {"VERT_ASSIGNMENTS", R"( + a_valueAlphaToFrag = a_valueAlpha; + )"}, + {"FRAG_DECLARATIONS", R"( + in float a_valueAlphaToFrag; + )"}, + {"GENERATE_ALPHA", R"( + alphaOut *= clamp(a_valueAlphaToFrag, 0.f, 1.f); + )"}, + }, + /* uniforms */ {}, + /* attributes */ { + {"a_valueAlpha", RenderDataType::Float}, + }, + /* textures */ {} +); + const ShaderReplacementRule MESH_PROPAGATE_FLAT_VALUE ( /* rule name */ "MESH_PROPAGATE_FLAT_VALUE", { /* replacement sources */ diff --git a/src/surface_mesh.cpp b/src/surface_mesh.cpp index 577465f0..74e8dde2 100644 --- a/src/surface_mesh.cpp +++ b/src/surface_mesh.cpp @@ -826,6 +826,11 @@ void SurfaceMesh::setMeshGeometryAttributes(render::ShaderProgram& p) { if (wantsCullPosition()) { p.setAttribute("a_cullPos", faceCenters.getIndexedRenderAttributeBuffer(triangleFaceInds)); } + + if (transparencyQuantityName != "") { + SurfaceScalarQuantity& transparencyQ = resolveTransparencyQuantity(); + p.setAttribute("a_valueAlpha", transparencyQ.getAttributeBuffer()); + } } void SurfaceMesh::setMeshPickAttributes(render::ShaderProgram& p) { @@ -1023,6 +1028,10 @@ std::vector SurfaceMesh::addSurfaceMeshRules(std::vector(q.second.get()); + if (scalarQ != nullptr) { + if (scalarQ->definedOn == "vertex" || scalarQ->definedOn == "face" || scalarQ->definedOn == "corner") { + + if (ImGui::MenuItem(scalarQ->name.c_str(), nullptr, transparencyQuantityName == scalarQ->name)) + setTransparencyQuantity(scalarQ); + } + } + } + + ImGui::EndMenu(); + } } void SurfaceMesh::recomputeGeometryIfPopulated() { @@ -1412,6 +1441,46 @@ long long int SurfaceMesh::selectVertex() { return returnVertInd; } +void SurfaceMesh::setTransparencyQuantity(SurfaceScalarQuantity* quantity) { setTransparencyQuantity(quantity->name); } + +void SurfaceMesh::setTransparencyQuantity(std::string name) { + transparencyQuantityName = name; + resolveTransparencyQuantity(); // do it once, just so we fail fast if it doesn't exist + + // if transparency is disabled, enable it + if (options::transparencyMode == TransparencyMode::None) { + options::transparencyMode = TransparencyMode::Pretty; + } + + refresh(); +} + +void SurfaceMesh::clearTransparencyQuantity() { + transparencyQuantityName = ""; + refresh(); +} + +SurfaceScalarQuantity& SurfaceMesh::resolveTransparencyQuantity() { + SurfaceScalarQuantity* transparencyScalarQ = nullptr; + SurfaceMeshQuantity* anyQ = getQuantity(transparencyQuantityName); + if (anyQ != nullptr) { + transparencyScalarQ = dynamic_cast(anyQ); + if (transparencyScalarQ == nullptr) { + exception("Cannot populate per-element transparency from quantity [" + name + "], it is not a scalar quantity"); + } + + if (!(transparencyScalarQ->definedOn == "vertex" || transparencyScalarQ->definedOn == "face" || + transparencyScalarQ->definedOn == "corner")) { + exception("Cannot populate per-element transparency from quantity [" + name + + "], only vertex, face, and corner quantities are supported"); + } + + } else { + exception("Cannot populate per-element transparency from quantity [" + name + "], it does not exist"); + } + + return *transparencyScalarQ; +} void SurfaceMesh::markEdgesAsUsed() { if (edgesHaveBeenUsed) return; diff --git a/src/surface_scalar_quantity.cpp b/src/surface_scalar_quantity.cpp index d3d47681..86ace35e 100644 --- a/src/surface_scalar_quantity.cpp +++ b/src/surface_scalar_quantity.cpp @@ -89,6 +89,9 @@ void SurfaceVertexScalarQuantity::createProgram() { program->setTextureFromColormap("t_colormap", cMap.get()); } +std::shared_ptr SurfaceVertexScalarQuantity::getAttributeBuffer() { + return values.getIndexedRenderAttributeBuffer(parent.triangleVertexInds); +} void SurfaceVertexScalarQuantity::buildVertexInfoGUI(size_t vInd) { ImGui::TextUnformatted(name.c_str()); @@ -133,6 +136,10 @@ void SurfaceFaceScalarQuantity::createProgram() { } +std::shared_ptr SurfaceFaceScalarQuantity::getAttributeBuffer() { + return values.getIndexedRenderAttributeBuffer(parent.triangleFaceInds); +} + void SurfaceFaceScalarQuantity::buildFaceInfoGUI(size_t fInd) { ImGui::TextUnformatted(name.c_str()); ImGui::NextColumn(); @@ -177,6 +184,9 @@ void SurfaceEdgeScalarQuantity::createProgram() { program->setTextureFromColormap("t_colormap", cMap.get()); } +std::shared_ptr SurfaceEdgeScalarQuantity::getAttributeBuffer() { + return values.getIndexedRenderAttributeBuffer(parent.triangleAllEdgeInds); +} void SurfaceEdgeScalarQuantity::buildEdgeInfoGUI(size_t eInd) { ImGui::TextUnformatted(name.c_str()); @@ -219,6 +229,10 @@ void SurfaceHalfedgeScalarQuantity::createProgram() { program->setTextureFromColormap("t_colormap", cMap.get()); } +std::shared_ptr SurfaceHalfedgeScalarQuantity::getAttributeBuffer() { + return values.getIndexedRenderAttributeBuffer(parent.triangleAllHalfedgeInds); +} + void SurfaceHalfedgeScalarQuantity::buildHalfedgeInfoGUI(size_t heInd) { ImGui::TextUnformatted(name.c_str()); ImGui::NextColumn(); @@ -260,6 +274,10 @@ void SurfaceCornerScalarQuantity::createProgram() { program->setTextureFromColormap("t_colormap", cMap.get()); } +std::shared_ptr SurfaceCornerScalarQuantity::getAttributeBuffer() { + return values.getIndexedRenderAttributeBuffer(parent.triangleCornerInds); +} + void SurfaceCornerScalarQuantity::buildCornerInfoGUI(size_t cInd) { ImGui::TextUnformatted(name.c_str()); ImGui::NextColumn(); @@ -319,5 +337,9 @@ void SurfaceTextureScalarQuantity::createProgram() { values.getRenderTextureBuffer()->setFilterMode(FilterMode::Linear); } +std::shared_ptr SurfaceTextureScalarQuantity::getAttributeBuffer() { + exception("unsupported operation -- cannot get attribute buffer for texture scalar quantity [" + this->name + "]"); + return std::shared_ptr(nullptr); +} } // namespace polyscope diff --git a/test/src/point_cloud_test.cpp b/test/src/point_cloud_test.cpp index 250a9a61..c85edfcd 100644 --- a/test/src/point_cloud_test.cpp +++ b/test/src/point_cloud_test.cpp @@ -181,3 +181,40 @@ TEST_F(PolyscopeTest, PointCloudScalarRadius) { polyscope::removeAllStructures(); } + +TEST_F(PolyscopeTest, PointCloudScalarTransparency) { + auto psPoints = registerPointCloud(); + std::vector vScalar(psPoints->nPoints(), 7.); + std::vector vScalar2(psPoints->nPoints(), 7.); + auto q1 = psPoints->addScalarQuantity("vScalar", vScalar); + auto q2 = psPoints->addScalarQuantity("vScalar2", vScalar2); + q1->setEnabled(true); + + psPoints->setTransparencyQuantity(q1); + polyscope::show(3); + + psPoints->setPointRenderMode(polyscope::PointRenderMode::Quad); + polyscope::show(3); + + psPoints->setTransparencyQuantity("vScalar2"); + polyscope::show(3); + + // Change transparency settings + polyscope::options::transparencyMode = polyscope::TransparencyMode::Simple; + polyscope::show(3); + + q2->updateData(vScalar2); + polyscope::show(3); + + polyscope::options::transparencyMode = polyscope::TransparencyMode::None; + polyscope::show(3); + polyscope::options::transparencyMode = polyscope::TransparencyMode::Pretty; + + psPoints->clearPointRadiusQuantity(); + polyscope::show(3); + + polyscope::options::transparencyMode = polyscope::TransparencyMode::None; + polyscope::show(3); + + polyscope::removeAllStructures(); +} diff --git a/test/src/surface_mesh_test.cpp b/test/src/surface_mesh_test.cpp index d819539d..3c503197 100644 --- a/test/src/surface_mesh_test.cpp +++ b/test/src/surface_mesh_test.cpp @@ -307,6 +307,46 @@ TEST_F(PolyscopeTest, SurfaceMeshScalarTexture) { polyscope::removeAllStructures(); } +TEST_F(PolyscopeTest, SurfaceMeshScalarTransparency) { + + auto psMesh = registerTriangleMesh(); + + { // vertex quantity + std::vector vScalar(psMesh->nVertices(), 7.); + auto qVert = psMesh->addVertexScalarQuantity("vScalar", vScalar); + psMesh->setTransparencyQuantity(qVert); + polyscope::show(3); + } + + // make sure clear works + psMesh->clearTransparencyQuantity(); + polyscope::show(3); + + { // face quantity + std::vector fScalar(psMesh->nFaces(), 8.); + auto qFace = psMesh->addFaceScalarQuantity("fScalar", fScalar); + psMesh->setTransparencyQuantity(qFace); + polyscope::show(3); + } + + { // corner quantity + std::vector cornerScalar(psMesh->nCorners(), 10.); + auto qCorner = psMesh->addCornerScalarQuantity("cornerScalar", cornerScalar); + psMesh->setTransparencyQuantity(qCorner); + polyscope::show(3); + } + + // edges, halfedges, and textures are currently not supported + + // Change transparency settings + polyscope::options::transparencyMode = polyscope::TransparencyMode::Simple; + polyscope::show(3); + polyscope::options::transparencyMode = polyscope::TransparencyMode::None; + polyscope::show(3); + + polyscope::removeAllStructures(); +} + TEST_F(PolyscopeTest, SurfaceMeshDistance) { auto psMesh = registerTriangleMesh(); std::vector vScalar(psMesh->nVertices(), 7.);