From 54a7a7b73be75f5753609c6b5c07898458ace567 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Sat, 24 Jan 2026 21:05:04 -0800 Subject: [PATCH] simplify main classes to remove excess templating --- include/polyscope/camera_view.h | 10 +- include/polyscope/color_bar.h | 4 +- include/polyscope/color_image_quantity.h | 2 +- include/polyscope/curve_network.h | 7 +- include/polyscope/curve_network_quantity.h | 6 +- include/polyscope/floating_quantity.h | 2 - .../polyscope/floating_quantity_structure.h | 2 +- include/polyscope/implicit_helpers.h | 32 +- include/polyscope/implicit_helpers.ipp | 29 +- include/polyscope/point_cloud.h | 9 +- include/polyscope/point_cloud_quantity.h | 6 +- include/polyscope/polyscope.h | 2 +- include/polyscope/quantity.h | 27 +- include/polyscope/quantity.ipp | 70 ---- include/polyscope/render/managed_buffer.h | 2 +- .../polyscope/render_image_quantity_base.h | 2 +- include/polyscope/scalar_image_quantity.h | 2 +- include/polyscope/scalar_quantity.h | 6 +- include/polyscope/simple_triangle_mesh.h | 8 +- include/polyscope/slice_plane.h | 4 +- include/polyscope/structure.h | 230 ++++++------ include/polyscope/structure.ipp | 341 ++---------------- include/polyscope/surface_mesh.h | 9 +- include/polyscope/surface_mesh_quantity.h | 6 +- include/polyscope/types.h | 2 +- include/polyscope/volume_grid.h | 7 +- include/polyscope/volume_grid_quantity.h | 6 +- include/polyscope/volume_mesh.h | 9 +- include/polyscope/volume_mesh_quantity.h | 8 +- src/CMakeLists.txt | 4 +- src/camera_view.cpp | 6 +- src/color_image_quantity.cpp | 5 +- src/curve_network.cpp | 25 +- src/floating_quantity.cpp | 2 +- src/floating_quantity_structure.cpp | 5 +- src/point_cloud.cpp | 10 +- src/quantity.cpp | 48 ++- src/render/ground_plane.cpp | 2 +- src/render/initialize_backend.cpp | 2 +- src/render/opengl/shaders/common.cpp | 4 +- src/render_image_quantity_base.cpp | 5 +- src/scalar_image_quantity.cpp | 5 +- src/simple_triangle_mesh.cpp | 4 +- src/slice_plane.cpp | 3 +- src/structure.cpp | 281 ++++++++++++++- src/surface_mesh.cpp | 28 +- src/volume_grid.cpp | 16 +- src/volume_mesh.cpp | 14 +- src/volume_mesh_scalar_quantity.cpp | 6 +- test/src/basics_test.cpp | 20 +- test/src/misc_test.cpp | 6 +- test/src/point_cloud_test.cpp | 4 +- 52 files changed, 630 insertions(+), 725 deletions(-) delete mode 100644 include/polyscope/quantity.ipp diff --git a/include/polyscope/camera_view.h b/include/polyscope/camera_view.h index 743872d2..43b6fbaf 100644 --- a/include/polyscope/camera_view.h +++ b/include/polyscope/camera_view.h @@ -17,19 +17,11 @@ namespace polyscope { // Forward declare structure class CameraView; -/* -// Forward declare quantity types (currently there are none) -template <> // Specialize the quantity type -struct QuantityTypeHelper { - typedef CameraViewQuantity type; -}; -*/ - struct CameraViewPickResult { // currently nothing, just following the same pattern as other structures }; -class CameraView : public QuantityStructure { +class CameraView : public Structure { public: // === Member functions === diff --git a/include/polyscope/color_bar.h b/include/polyscope/color_bar.h index e4e391da..6716f8bd 100644 --- a/include/polyscope/color_bar.h +++ b/include/polyscope/color_bar.h @@ -32,13 +32,13 @@ class ColorBar { Quantity& parent; std::pair colormapRange; // in DATA values, not [0,1] - void exportColorbarToSVG(const std::string& filename); + void exportColorbarToSVG(const std::string& filename); // Getters and setters void setOnscreenColorbarEnabled(bool newEnabled); bool getOnscreenColorbarEnabled(); - + // Location in screen coords. (-1,-1), means "place automatically" (default) void setOnscreenColorbarLocation(glm::vec2 newScreenCoords); glm::vec2 getOnscreenColorbarLocation(); diff --git a/include/polyscope/color_image_quantity.h b/include/polyscope/color_image_quantity.h index 0bd34c89..4761f6f1 100644 --- a/include/polyscope/color_image_quantity.h +++ b/include/polyscope/color_image_quantity.h @@ -27,7 +27,7 @@ class ColorImageQuantity : public ImageQuantity { // == Setters and getters - ColorImageQuantity* setEnabled(bool newEnabled) override; + void setEnabled(bool newEnabled) override; ColorImageQuantity* setIsPremultiplied(bool val); bool getIsPremultiplied(); diff --git a/include/polyscope/curve_network.h b/include/polyscope/curve_network.h index 3b6f2569..45fd818b 100644 --- a/include/polyscope/curve_network.h +++ b/include/polyscope/curve_network.h @@ -31,18 +31,13 @@ class CurveNetworkNodeVectorQuantity; class CurveNetworkEdgeVectorQuantity; -template <> // Specialize the quantity type -struct QuantityTypeHelper { - typedef CurveNetworkQuantity type; -}; - struct CurveNetworkPickResult { CurveNetworkElement elementType; // which kind of element did we click int64_t index; // index of the clicked element float tEdge = -1; // if the pick is an edge, the t-value in [0,1] along the edge }; -class CurveNetwork : public QuantityStructure { +class CurveNetwork : public Structure { public: // === Member functions === diff --git a/include/polyscope/curve_network_quantity.h b/include/polyscope/curve_network_quantity.h index 420d5c56..fb3b2583 100644 --- a/include/polyscope/curve_network_quantity.h +++ b/include/polyscope/curve_network_quantity.h @@ -7,15 +7,15 @@ namespace polyscope { -// Forward declare class CurveNetwork; -// Extend Quantity -class CurveNetworkQuantity : public QuantityS { +class CurveNetworkQuantity : public Quantity { public: CurveNetworkQuantity(std::string name, CurveNetwork& parentStructure, bool dominates = false); virtual ~CurveNetworkQuantity() {}; + CurveNetwork& parent; // shadows and hides the generic member in Quantity + // Build GUI info an element virtual void buildNodeInfoGUI(size_t vInd); virtual void buildEdgeInfoGUI(size_t fInd); diff --git a/include/polyscope/floating_quantity.h b/include/polyscope/floating_quantity.h index 7f10ea70..f1a9a29d 100644 --- a/include/polyscope/floating_quantity.h +++ b/include/polyscope/floating_quantity.h @@ -14,8 +14,6 @@ class FloatingQuantity : public Quantity { virtual ~FloatingQuantity() {}; virtual void buildUI() override; - - virtual FloatingQuantity* setEnabled(bool newEnabled) = 0; }; diff --git a/include/polyscope/floating_quantity_structure.h b/include/polyscope/floating_quantity_structure.h index 21aa03a0..8460d8d5 100644 --- a/include/polyscope/floating_quantity_structure.h +++ b/include/polyscope/floating_quantity_structure.h @@ -31,7 +31,7 @@ class ScalarImageQuantity; class ColorImageQuantity; -class FloatingQuantityStructure : public QuantityStructure { +class FloatingQuantityStructure : public Structure { public: // === Member functions === diff --git a/include/polyscope/implicit_helpers.h b/include/polyscope/implicit_helpers.h index 7baedfe8..ebff6e8e 100644 --- a/include/polyscope/implicit_helpers.h +++ b/include/polyscope/implicit_helpers.h @@ -79,7 +79,7 @@ struct ImplicitRenderOpts { // Populate the custom-filled entries of opts according to the policy above. template -void resolveImplicitRenderOpts(QuantityStructure* parent, ImplicitRenderOpts& opts); +void resolveImplicitRenderOpts(S* parent, ImplicitRenderOpts& opts); // === Depth/geometry/shape only render functions @@ -102,15 +102,13 @@ void resolveImplicitRenderOpts(QuantityStructure* parent, ImplicitRenderOpts& // handles more general implicit functions. See the options struct for other options. template -DepthRenderImageQuantity* renderImplicitSurface(QuantityStructure* parent, std::string name, Func&& func, - ImplicitRenderMode mode, +DepthRenderImageQuantity* renderImplicitSurface(S* parent, std::string name, Func&& func, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); template DepthRenderImageQuantity* renderImplicitSurface(std::string name, Func&& func, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); template -DepthRenderImageQuantity* renderImplicitSurfaceBatch(QuantityStructure* parent, std::string name, Func&& func, - ImplicitRenderMode mode, +DepthRenderImageQuantity* renderImplicitSurfaceBatch(S* parent, std::string name, Func&& func, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); template DepthRenderImageQuantity* renderImplicitSurfaceBatch(std::string name, Func&& func, ImplicitRenderMode mode, @@ -121,8 +119,8 @@ DepthRenderImageQuantity* renderImplicitSurfaceBatch(std::string name, Func&& fu // Like the implicit surface renderers above, but additionally take a color template -ColorRenderImageQuantity* renderImplicitSurfaceColor(QuantityStructure* parent, std::string name, Func&& func, - FuncColor&& funcColor, ImplicitRenderMode mode, +ColorRenderImageQuantity* renderImplicitSurfaceColor(S* parent, std::string name, Func&& func, FuncColor&& funcColor, + ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); template ColorRenderImageQuantity* renderImplicitSurfaceColor(std::string name, Func&& func, FuncColor&& funcColor, @@ -130,7 +128,7 @@ ColorRenderImageQuantity* renderImplicitSurfaceColor(std::string name, Func&& fu ImplicitRenderOpts opts = ImplicitRenderOpts()); template -ColorRenderImageQuantity* renderImplicitSurfaceColorBatch(QuantityStructure* parent, std::string name, Func&& func, +ColorRenderImageQuantity* renderImplicitSurfaceColorBatch(S* parent, std::string name, Func&& func, FuncColor&& funcColor, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); template @@ -143,17 +141,17 @@ ColorRenderImageQuantity* renderImplicitSurfaceColorBatch(std::string name, Func // Like the implicit surface renderers above, but additionally take a scalar and colormap it, etc template -ScalarRenderImageQuantity* renderImplicitSurfaceScalar(QuantityStructure* parent, std::string name, Func&& func, - FuncScalar&& funcScalar, ImplicitRenderMode mode, - ImplicitRenderOpts opts = ImplicitRenderOpts(), - DataType dataType = DataType::STANDARD); +ScalarRenderImageQuantity* +renderImplicitSurfaceScalar(S* parent, std::string name, Func&& func, FuncScalar&& funcScalar, ImplicitRenderMode mode, + ImplicitRenderOpts opts = ImplicitRenderOpts(), DataType dataType = DataType::STANDARD); + template ScalarRenderImageQuantity* renderImplicitSurfaceScalar(std::string name, Func&& func, FuncScalar&& funcScalar, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts(), DataType dataType = DataType::STANDARD); template -ScalarRenderImageQuantity* renderImplicitSurfaceScalarBatch(QuantityStructure* parent, std::string name, Func&& func, +ScalarRenderImageQuantity* renderImplicitSurfaceScalarBatch(S* parent, std::string name, Func&& func, FuncScalar&& funcScalar, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts(), DataType dataType = DataType::STANDARD); @@ -169,7 +167,7 @@ ScalarRenderImageQuantity* renderImplicitSurfaceScalarBatch(std::string name, Fu // Whereas the other functions shade based on normals, this one just renders surface depth and color directly. template -RawColorRenderImageQuantity* renderImplicitSurfaceRawColor(QuantityStructure* parent, std::string name, Func&& func, +RawColorRenderImageQuantity* renderImplicitSurfaceRawColor(S* parent, std::string name, Func&& func, FuncColor&& funcColor, ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); template @@ -178,9 +176,9 @@ RawColorRenderImageQuantity* renderImplicitSurfaceRawColor(std::string name, Fun ImplicitRenderOpts opts = ImplicitRenderOpts()); template -RawColorRenderImageQuantity* -renderImplicitSurfaceRawColorBatch(QuantityStructure* parent, std::string name, Func&& func, FuncColor&& funcColor, - ImplicitRenderMode mode, ImplicitRenderOpts opts = ImplicitRenderOpts()); +RawColorRenderImageQuantity* renderImplicitSurfaceRawColorBatch(S* parent, std::string name, Func&& func, + FuncColor&& funcColor, ImplicitRenderMode mode, + ImplicitRenderOpts opts = ImplicitRenderOpts()); template RawColorRenderImageQuantity* renderImplicitSurfaceRawColorBatch(std::string name, Func&& func, FuncColor&& funcColor, ImplicitRenderMode mode, diff --git a/include/polyscope/implicit_helpers.ipp b/include/polyscope/implicit_helpers.ipp index aa95ad3a..162e5c4a 100644 --- a/include/polyscope/implicit_helpers.ipp +++ b/include/polyscope/implicit_helpers.ipp @@ -15,7 +15,7 @@ namespace polyscope { template -void resolveImplicitRenderOpts(QuantityStructure* parent, ImplicitRenderOpts& opts) { +void resolveImplicitRenderOpts(S* parent, ImplicitRenderOpts& opts) { // see comment in the ImplicitRenderOpts struct for the logic that this function implements @@ -249,8 +249,8 @@ DepthRenderImageQuantity* renderImplicitSurfaceBatch(std::string name, Func&& fu } template -DepthRenderImageQuantity* renderImplicitSurface(QuantityStructure* parent, std::string name, Func&& func, - ImplicitRenderMode mode, ImplicitRenderOpts opts) { +DepthRenderImageQuantity* renderImplicitSurface(S* parent, std::string name, Func&& func, ImplicitRenderMode mode, + ImplicitRenderOpts opts) { // Bootstrap on the batch version auto batchFunc = [&](const float* pos_ptr, float* result_ptr, size_t size) { @@ -269,8 +269,8 @@ DepthRenderImageQuantity* renderImplicitSurface(QuantityStructure* parent, st template -DepthRenderImageQuantity* renderImplicitSurfaceBatch(QuantityStructure* parent, std::string name, Func&& func, - ImplicitRenderMode mode, ImplicitRenderOpts opts) { +DepthRenderImageQuantity* renderImplicitSurfaceBatch(S* parent, std::string name, Func&& func, ImplicitRenderMode mode, + ImplicitRenderOpts opts) { resolveImplicitRenderOpts(parent, opts); @@ -307,9 +307,8 @@ ColorRenderImageQuantity* renderImplicitSurfaceColorBatch(std::string name, Func template -ColorRenderImageQuantity* renderImplicitSurfaceColor(QuantityStructure* parent, std::string name, Func&& func, - FuncColor&& funcColor, ImplicitRenderMode mode, - ImplicitRenderOpts opts) { +ColorRenderImageQuantity* renderImplicitSurfaceColor(S* parent, std::string name, Func&& func, FuncColor&& funcColor, + ImplicitRenderMode mode, ImplicitRenderOpts opts) { // Bootstrap on the batch version auto batchFunc = [&](const float* pos_ptr, float* result_ptr, size_t size) { @@ -344,7 +343,7 @@ ColorRenderImageQuantity* renderImplicitSurfaceColor(QuantityStructure* paren template -ColorRenderImageQuantity* renderImplicitSurfaceColorBatch(QuantityStructure* parent, std::string name, Func&& func, +ColorRenderImageQuantity* renderImplicitSurfaceColorBatch(S* parent, std::string name, Func&& func, FuncColor&& funcColor, ImplicitRenderMode mode, ImplicitRenderOpts opts) { @@ -399,7 +398,7 @@ ScalarRenderImageQuantity* renderImplicitSurfaceScalarBatch(std::string name, Fu } template -ScalarRenderImageQuantity* renderImplicitSurfaceScalar(QuantityStructure* parent, std::string name, Func&& func, +ScalarRenderImageQuantity* renderImplicitSurfaceScalar(S* parent, std::string name, Func&& func, FuncScalar&& funcScalar, ImplicitRenderMode mode, ImplicitRenderOpts opts, DataType dataType) { @@ -430,7 +429,7 @@ ScalarRenderImageQuantity* renderImplicitSurfaceScalar(QuantityStructure* par } template -ScalarRenderImageQuantity* renderImplicitSurfaceScalarBatch(QuantityStructure* parent, std::string name, Func&& func, +ScalarRenderImageQuantity* renderImplicitSurfaceScalarBatch(S* parent, std::string name, Func&& func, FuncScalar&& funcScalar, ImplicitRenderMode mode, ImplicitRenderOpts opts, DataType dataType) { @@ -483,7 +482,7 @@ RawColorRenderImageQuantity* renderImplicitSurfaceRawColorBatch(std::string name template -RawColorRenderImageQuantity* renderImplicitSurfaceRawColor(QuantityStructure* parent, std::string name, Func&& func, +RawColorRenderImageQuantity* renderImplicitSurfaceRawColor(S* parent, std::string name, Func&& func, FuncColor&& funcColor, ImplicitRenderMode mode, ImplicitRenderOpts opts) { @@ -520,9 +519,9 @@ RawColorRenderImageQuantity* renderImplicitSurfaceRawColor(QuantityStructure* template -RawColorRenderImageQuantity* renderImplicitSurfaceRawColorBatch(QuantityStructure* parent, std::string name, - Func&& func, FuncColor&& funcColor, - ImplicitRenderMode mode, ImplicitRenderOpts opts) { +RawColorRenderImageQuantity* renderImplicitSurfaceRawColorBatch(S* parent, std::string name, Func&& func, + FuncColor&& funcColor, ImplicitRenderMode mode, + ImplicitRenderOpts opts) { resolveImplicitRenderOpts(parent, opts); diff --git a/include/polyscope/point_cloud.h b/include/polyscope/point_cloud.h index 4963cf37..40e8b6e7 100644 --- a/include/polyscope/point_cloud.h +++ b/include/polyscope/point_cloud.h @@ -6,7 +6,6 @@ #include "polyscope/color_management.h" #include "polyscope/persistent_value.h" #include "polyscope/pick.h" -#include "polyscope/point_cloud_quantity.h" #include "polyscope/polyscope.h" #include "polyscope/render/engine.h" #include "polyscope/render/managed_buffer.h" @@ -16,6 +15,7 @@ #include "polyscope/point_cloud_color_quantity.h" #include "polyscope/point_cloud_parameterization_quantity.h" +#include "polyscope/point_cloud_quantity.h" #include "polyscope/point_cloud_scalar_quantity.h" #include "polyscope/point_cloud_vector_quantity.h" @@ -33,16 +33,11 @@ class PointCloudParameterizationQuantity; class PointCloudVectorQuantity; -template <> // Specialize the quantity type -struct QuantityTypeHelper { - typedef PointCloudQuantity type; -}; - struct PointCloudPickResult { int64_t index; }; -class PointCloud : public QuantityStructure { +class PointCloud : public Structure { public: // === Member functions === diff --git a/include/polyscope/point_cloud_quantity.h b/include/polyscope/point_cloud_quantity.h index 7545b5c3..6c8a8e97 100644 --- a/include/polyscope/point_cloud_quantity.h +++ b/include/polyscope/point_cloud_quantity.h @@ -7,15 +7,15 @@ namespace polyscope { -// Forward delcare point cloud class PointCloud; -// Extend Quantity to add a few extra functions -class PointCloudQuantity : public QuantityS { +class PointCloudQuantity : public Quantity { public: PointCloudQuantity(std::string name, PointCloud& parentStructure, bool dominates = false); virtual ~PointCloudQuantity() {}; + PointCloud& parent; // shadows and hides the generic member in Quantity + // Build GUI info about a point virtual void buildInfoGUI(size_t pointInd); }; diff --git a/include/polyscope/polyscope.h b/include/polyscope/polyscope.h index b46f0ba1..92a125cf 100644 --- a/include/polyscope/polyscope.h +++ b/include/polyscope/polyscope.h @@ -110,7 +110,7 @@ extern std::function& userCallback; // == Other callback functions // invoked when files are dropped onto the window, nothing by default -extern std::function&)> filesDroppedCallback; +extern std::function&)> filesDroppedCallback; // === Implementation details diff --git a/include/polyscope/quantity.h b/include/polyscope/quantity.h index 87afeb47..2ac9fb49 100644 --- a/include/polyscope/quantity.h +++ b/include/polyscope/quantity.h @@ -23,7 +23,7 @@ class Structure; class Quantity : public render::ManagedBufferRegistry { public: - Quantity(std::string name, Structure& parentStructure); + Quantity(std::string name, Structure& parentStructure, bool dominates = false); virtual ~Quantity(); // Draw the quantity. @@ -42,7 +42,9 @@ class Quantity : public render::ManagedBufferRegistry { // Enable and disable the quantity bool isEnabled(); - // there is no setEnabled() here, only in subclasses, because subclasses have different return types + + // this function is defined by subclasses instead so they can return themselves for backward compatibility + virtual void setEnabled(bool newVal); // = Utility @@ -60,29 +62,10 @@ class Quantity : public render::ManagedBufferRegistry { // Is this quantity currently being displayed? PersistentValue enabled; // should be set by setEnabled() -}; - -// === Structure-specific Quantities - -template -class QuantityS : public Quantity { -public: - QuantityS(std::string name, S& parentStructure, bool dominates = false); - virtual ~QuantityS(); - - // Enable and disable the quantity - virtual QuantityS* setEnabled(bool newEnabled); - - virtual void buildUI() override; - - S& parent; // note: this HIDES the more general member of the same name in the parent class // Track dominating quantities bool dominates = false; }; -} // namespace polyscope - - -#include "polyscope/quantity.ipp" +} // namespace polyscope \ No newline at end of file diff --git a/include/polyscope/quantity.ipp b/include/polyscope/quantity.ipp deleted file mode 100644 index 787dc7d6..00000000 --- a/include/polyscope/quantity.ipp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run - -#include "imgui.h" - -#include "polyscope/messages.h" -#include "polyscope/structure.h" - -namespace polyscope { - -// forward declaration -void requestRedraw(); - -// === Structure-specific Quantities - -template -QuantityS::QuantityS(std::string name_, S& parentStructure_, bool dominates_) - : Quantity(name_, parentStructure_), parent(parentStructure_), dominates(dominates_) { - validateName(name); - - // Hack: if the quantity pulls enabled=true from the cache, need to make sure the logic from setEnabled(true) happens, - // so toggle it real quick - if (isEnabled()) { - setEnabled(false); - setEnabled(true); - } -} - -template -QuantityS::~QuantityS() {} - -template -QuantityS* QuantityS::setEnabled(bool newEnabled) { - if (newEnabled == enabled.get()) return this; - - enabled = newEnabled; - - // Dominating quantities need to update themselves as their parent's dominating quantity - if (dominates) { - if (newEnabled == true) { - parent.setDominantQuantity(this); - } else { - parent.clearDominantQuantity(); - } - } - - requestRedraw(); - - return this; -} - -template -void QuantityS::buildUI() { - // NOTE: duplicated here and in the FloatingQuantity version - - if (ImGui::TreeNode(niceName().c_str())) { - - // Enabled checkbox - bool enabledLocal = enabled.get(); - if (ImGui::Checkbox("Enabled", &enabledLocal)) { - setEnabled(enabledLocal); - } - - // Call custom UI - this->buildCustomUI(); - - ImGui::TreePop(); - } -} - -} // namespace polyscope diff --git a/include/polyscope/render/managed_buffer.h b/include/polyscope/render/managed_buffer.h index 594b6b3d..6930ff8c 100644 --- a/include/polyscope/render/managed_buffer.h +++ b/include/polyscope/render/managed_buffer.h @@ -180,7 +180,7 @@ class ManagedBuffer : public virtual WeakReferrable { // Get a copy of the data viewed through an index, such that view[i] = data[indices[i]]. // - // This follows the same logic as above, but rather than returning a render buffer it simply returns a host-side + // This follows the same logic as above, but rather than returning a render buffer it simply returns a host-side // copy (which is not cached). std::vector getIndexedView(ManagedBuffer& indices); diff --git a/include/polyscope/render_image_quantity_base.h b/include/polyscope/render_image_quantity_base.h index 4a2edddb..f98dd2c0 100644 --- a/include/polyscope/render_image_quantity_base.h +++ b/include/polyscope/render_image_quantity_base.h @@ -41,7 +41,7 @@ class RenderImageQuantityBase : public FloatingQuantity, public FullscreenArtist // == Setters and getters - virtual RenderImageQuantityBase* setEnabled(bool newEnabled) override; + virtual void setEnabled(bool newEnabled) override; // Material RenderImageQuantityBase* setMaterial(std::string name); diff --git a/include/polyscope/scalar_image_quantity.h b/include/polyscope/scalar_image_quantity.h index 9d2dddbc..2dced564 100644 --- a/include/polyscope/scalar_image_quantity.h +++ b/include/polyscope/scalar_image_quantity.h @@ -25,7 +25,7 @@ class ScalarImageQuantity : public ImageQuantity, public ScalarQuantity getMapRange(); QuantityT* resetMapRange(); // reset to full range std::pair getDataRange(); - + // Color bar options (it is always displayed inline in the structures panel) QuantityT* setOnscreenColorbarEnabled(bool newEnabled); bool getOnscreenColorbarEnabled(); @@ -91,7 +91,7 @@ class ScalarQuantity { std::pair dataRange; PersistentValue vizRangeMin; PersistentValue vizRangeMax; - + ColorBar colorBar; // Parameters diff --git a/include/polyscope/simple_triangle_mesh.h b/include/polyscope/simple_triangle_mesh.h index 10311b70..4b0c6041 100644 --- a/include/polyscope/simple_triangle_mesh.h +++ b/include/polyscope/simple_triangle_mesh.h @@ -19,17 +19,11 @@ class SimpleTriangleMesh; // Forward declare quantity types -// template <> // Specialize the quantity type -// struct QuantityTypeHelper { -// typedef SimpleTriangleMeshQuantity type; -// }; - - struct SimpleTriangleMeshPickResult { // this does nothing for now, just matching pattern from other structures }; -class SimpleTriangleMesh : public QuantityStructure { +class SimpleTriangleMesh : public Structure { public: // === Member functions === diff --git a/include/polyscope/slice_plane.h b/include/polyscope/slice_plane.h index 5aa719b9..65db8179 100644 --- a/include/polyscope/slice_plane.h +++ b/include/polyscope/slice_plane.h @@ -86,7 +86,7 @@ class SlicePlane { protected: // = State - PersistentValue enabled; // is it actually slicing? + PersistentValue enabled; // is it actually slicing? PersistentValue drawPlane; // do we draw the plane onscreen? PersistentValue drawWidget; // do we draw the widget onscreen? PersistentValue objectTransform; @@ -125,7 +125,7 @@ SlicePlane* addSlicePlane(std::string name); SlicePlane* addSlicePlane(); // DEPRECATED: there's on reason to offer this variant, it could be set manually -SlicePlane* addSceneSlicePlane(bool initiallyVisible=false); +SlicePlane* addSceneSlicePlane(bool initiallyVisible = false); // Get a slice plane by name SlicePlane* getSlicePlane(std::string name); diff --git a/include/polyscope/structure.h b/include/polyscope/structure.h index a79ae3ab..10d39ed5 100644 --- a/include/polyscope/structure.h +++ b/include/polyscope/structure.h @@ -9,17 +9,32 @@ #include "glm/glm.hpp" +#include "polyscope/floating_quantity.h" #include "polyscope/persistent_value.h" #include "polyscope/pick.h" +#include "polyscope/quantity.h" #include "polyscope/render/engine.h" #include "polyscope/transformation_gizmo.h" #include "polyscope/weak_handle.h" #include "polyscope/render/managed_buffer.h" - namespace polyscope { +// forward declarations +class Quantity; + +// Floating quantity things +class FloatingQuantity; +class ScalarImageQuantity; +class ColorImageQuantity; +class DepthRenderImageQuantity; +class ColorRenderImageQuantity; +class ScalarRenderImageQuantity; +class RawColorRenderImageQuantity; +class RawColorAlphaRenderImageQuantity; + + // forward declarations class Group; @@ -40,41 +55,53 @@ class Structure : public render::ManagedBufferRegistry, public virtual WeakRefer Structure(std::string name, std::string subtypeName); virtual ~Structure() = 0; - // == Render the the structure on screen + // ==================================================================== + // ==== Basic Meta-Management ========================================= + // ==================================================================== + + // = Identifying data + const std::string name; // should be unique amongst registered structures with this type + const std::string subtypeName; // specific type name, like "Point Cloud" + std::string uniquePrefix(); + std::string getName() { return name; }; // used by pybind to access the name property + virtual std::string typeName() = 0; + + // Re-perform any setup work, including refreshing all quantities + virtual void refresh(); + + // Get rid of it (invalidates the object and all pointers, etc!) + void remove(); + + // ==================================================================== + // ==== Rendering ===================================================== + // ==================================================================== + virtual void draw() = 0; virtual void drawPick() = 0; virtual void drawDelayed() = 0; // a second render pass virtual void drawPickDelayed() = 0; - // == Add rendering rules + // Helpers to add rendering rules std::vector addStructureRules(std::vector initRules); - // == Build the ImGUI ui elements + // ==================================================================== + // ==== ImGui UI elements ============================================= + // ==================================================================== + virtual void buildUI(); virtual void buildCustomUI() = 0; // overridden by childen to add custom UI data virtual void buildCustomOptionsUI(); // overridden by childen to add to the options menu virtual void buildStructureOptionsUI(); // overridden by structure quantities to add to the options menu - virtual void buildQuantitiesUI(); // build quantities, if they exist. Overridden by QuantityStructure. + virtual void buildQuantitiesUI(); // build quantities, if they exist. virtual void buildSharedStructureUI(); // Draw any UI elements shared between all instances of the structure virtual void buildPickUI(const PickResult& result) = 0; // Draw pick UI elements based on a selection result - // = Identifying data - const std::string name; // should be unique amongst registered structures with this type - const std::string subtypeName; // specific type name, like "Point Cloud" - std::string uniquePrefix(); - - std::string getName() { return name; }; // used by pybind to access the name property - // = Length and bounding box - // (returned in world coordinates, after the object transform is applied) - std::tuple boundingBox(); // get axis-aligned bounding box - float lengthScale(); // get characteristic length - virtual bool hasExtents(); // bounding box and length scale are only meaningful if true - - // = Basic state - virtual std::string typeName() = 0; + // ==================================================================== + // ==== Transform to position in the scene ============================ + // ==================================================================== - // = Scene transform + // Transform management glm::mat4 getModelView(); void centerBoundingBox(); void rescaleToUnit(); @@ -86,14 +113,15 @@ class Structure : public render::ManagedBufferRegistry, public virtual WeakRefer glm::vec3 getPosition(); TransformationGizmo& getTransformGizmo(); - void setStructureUniforms(render::ShaderProgram& p); - bool wantsCullPosition(); - - // Re-perform any setup work, including refreshing all quantities - virtual void refresh(); + // = Length and bounding box + // (returned in world coordinates, after the object transform is applied) + std::tuple boundingBox(); // get axis-aligned bounding box + float lengthScale(); // get characteristic length + virtual bool hasExtents(); // bounding box and length scale are only meaningful if true - // Get rid of it (invalidates the object and all pointers, etc!) - void remove(); + // ==================================================================== + // ==== Enabling, Selection, and Groups =============================== + // ==================================================================== // Selection tools virtual Structure* setEnabled(bool newEnabled); @@ -103,8 +131,10 @@ class Structure : public render::ManagedBufferRegistry, public virtual WeakRefer void addToGroup(std::string groupName); void addToGroup(Group& group); + // ==================================================================== + // ==== Options ======================================================= + // ==================================================================== - // Options Structure* setTransparency(float newVal); // also enables transparency if <1 and transparency is not enabled float getTransparency(); @@ -117,103 +147,43 @@ class Structure : public render::ManagedBufferRegistry, public virtual WeakRefer Structure* setTransformGizmoEnabled(bool newVal); bool getTransformGizmoEnabled(); -protected: - // = State - PersistentValue enabled; - PersistentValue objectTransform; // rigid transform - - // 0 for transparent, 1 for opaque, only has effect if engine transparency is set - PersistentValue transparency; - - // Widget that wraps the transform - TransformationGizmo transformGizmo; - PersistentValue cullWholeElements; + // ==================================================================== + // ==== Manage quantities ============================================= + // ==================================================================== - PersistentValue> ignoredSlicePlaneNames; - - // Manage the bounding box & length scale - // (this is defined _before_ the object transform is applied. To get the scale/bounding box after transforms, use the - // boundingBox() and lengthScale() member function) - // The STRUCTURE is responsible for making sure updateObjectSpaceBounds() gets called any time the geometry changes - std::tuple objectSpaceBoundingBox; - float objectSpaceLengthScale; - virtual void updateObjectSpaceBounds() = 0; -}; - - -// Register a structure with polyscope -// Structure name must be a globally unique identifier for the structure. -bool registerStructure(Structure* structure, bool replaceIfPresent = true); - -// Can also manage quantities - - -// forward declarations -class Quantity; -template -class QuantityS; - -// Floating quantity things -class FloatingQuantity; -class ScalarImageQuantity; -class ColorImageQuantity; -class DepthRenderImageQuantity; -class ColorRenderImageQuantity; -class ScalarRenderImageQuantity; -class RawColorRenderImageQuantity; -class RawColorAlphaRenderImageQuantity; - -// Helper used to define quantity types -template -struct QuantityTypeHelper { - typedef QuantityS type; // default values -}; - -template // template on the derived type -class QuantityStructure : public Structure { -public: - // Nicer name for the quantity type of this structure - typedef typename QuantityTypeHelper::type QuantityType; - - // === Member functions === - - // Base constructor which sets the name - QuantityStructure(std::string name, std::string subtypeName); - virtual ~QuantityStructure() = 0; - - virtual void buildQuantitiesUI() override; - virtual void buildStructureOptionsUI() override; - - // Re-perform any setup work, including refreshing all quantities - virtual void refresh() override; - - // = Manage quantities + // Primary storage to hold quantities + // Note that floating quantities are tracked separately throughout + std::map> quantities; + std::map> floatingQuantities; // Note: takes ownership of pointer after it is passed in - void addQuantity(QuantityType* q, bool allowReplacement = true); + void addQuantity(Quantity* q, bool allowReplacement = true); void addQuantity(FloatingQuantity* q, bool allowReplacement = true); - QuantityType* - getQuantity(std::string name); // NOTE: will _not_ return floating quantities, must use other version below - FloatingQuantity* getFloatingQuantity(std::string name); + // Get a quantity by name + Quantity* getQuantity(std::string name); // NOTE: will _not_ return floating quantities, must use other version below + template + S* getStructureQuantity(std::string name); // Cast to a structure-specific version + FloatingQuantity* getFloatingQuantity(std::string name); // Get general floating quantities + + // Meta quantity management void checkForQuantityWithNameAndDeleteOrError(std::string name, bool allowReplacement = true); void removeQuantity(std::string name, bool errorIfAbsent = false); void removeAllQuantities(); + void setAllQuantitiesEnabled(bool newEnabled); - void setDominantQuantity(QuantityS* q); + // Maintain a _dominant_ quantity + // If non-null, a special quantity of which only one can be drawn for the structure. Handles common case of a surface + // color, e.g. color of a mesh or point cloud. The dominant quantity must always be enabled. + Quantity* dominantQuantity = nullptr; + void setDominantQuantity(Quantity* q); void clearDominantQuantity(); - void setAllQuantitiesEnabled(bool newEnabled); - - // = Quantities - std::map> quantities; - QuantityS* dominantQuantity = nullptr; // If non-null, a special quantity of which only one can be drawn for - // the structure. Handles common case of a surface color, e.g. color of - // a mesh or point cloud. The dominant quantity must always be enabled. + // Helpers for quantities + void setStructureUniforms(render::ShaderProgram& p); + bool wantsCullPosition(); - // floating quantities are tracked separately from normal quantities, though names should still be unique etc - std::map> floatingQuantities; // === Floating Quantities template @@ -291,9 +261,43 @@ class QuantityStructure : public Structure { ImageOrigin imageOrigin); protected: + // = State + PersistentValue enabled; + PersistentValue objectTransform; // rigid transform + + // 0 for transparent, 1 for opaque, only has effect if engine transparency is set + PersistentValue transparency; + + // Widget that wraps the transform + TransformationGizmo transformGizmo; + + PersistentValue cullWholeElements; + + PersistentValue> ignoredSlicePlaneNames; + + // Manage the bounding box & length scale + // (this is defined _before_ the object transform is applied. To get the scale/bounding box after transforms, use the + // boundingBox() and lengthScale() member function) + // The STRUCTURE is responsible for making sure updateObjectSpaceBounds() gets called any time the geometry changes + std::tuple objectSpaceBoundingBox; + float objectSpaceLengthScale; + virtual void updateObjectSpaceBounds() = 0; }; +// Register a structure with polyscope +// Structure name must be a globally unique identifier for the structure. +bool registerStructure(Structure* structure, bool replaceIfPresent = true); + + +// A few template implementations + +template +S* Structure::getStructureQuantity(std::string name) { + Quantity* q = getQuantity(name); + return static_cast(q); +} + } // namespace polyscope -#include "polyscope/structure.ipp" +#include "polyscope/structure.ipp" \ No newline at end of file diff --git a/include/polyscope/structure.ipp b/include/polyscope/structure.ipp index ca3169de..4435e161 100644 --- a/include/polyscope/structure.ipp +++ b/include/polyscope/structure.ipp @@ -10,194 +10,18 @@ namespace polyscope { -// === Derived structure can manage quantities - -template -QuantityStructure::QuantityStructure(std::string name_, std::string subtypeName) : Structure(name_, subtypeName) {} - -template -QuantityStructure::~QuantityStructure(){}; - -template -void QuantityStructure::checkForQuantityWithNameAndDeleteOrError(std::string name, bool allowReplacement) { - - // Look for an existing quantity with this name - bool quantityExists = quantities.find(name) != quantities.end(); - bool floatingQuantityExists = floatingQuantities.find(name) != floatingQuantities.end(); - - // if it already exists and we cannot replace, throw an error - if (!allowReplacement && (quantityExists || floatingQuantityExists)) { - exception("Tried to add quantity with name: [" + name + - "], but a quantity with that name already exists on the structure [" + name + - "]. Use the allowReplacement option like addQuantity(..., true) to replace."); - } - - // Remove the old quantity - if (quantityExists || floatingQuantityExists) { - removeQuantity(name); - } -} - -template -void QuantityStructure::addQuantity(QuantityType* q, bool allowReplacement) { - - // Check if a quantity with this name exists, remove it or throw and error if so - checkForQuantityWithNameAndDeleteOrError(q->name, allowReplacement); - - // Add the new quantity - quantities[q->name] = std::unique_ptr(q); -} - -template -void QuantityStructure::addQuantity(FloatingQuantity* q, bool allowReplacement) { - - // Check if a quantity with this name exists, remove it or throw and error if so - checkForQuantityWithNameAndDeleteOrError(q->name, allowReplacement); - - // Add the new quantity - floatingQuantities[q->name] = std::unique_ptr(q); -} - -template -typename QuantityStructure::QuantityType* QuantityStructure::getQuantity(std::string name) { - if (quantities.find(name) == quantities.end()) { - return nullptr; - } - return quantities[name].get(); -} - -template -FloatingQuantity* QuantityStructure::getFloatingQuantity(std::string name) { - if (floatingQuantities.find(name) == floatingQuantities.end()) { - return nullptr; - } - return floatingQuantities[name].get(); -} - -template -void QuantityStructure::refresh() { - for (auto& qp : quantities) { - qp.second->refresh(); - } - for (auto& qp : floatingQuantities) { - qp.second->refresh(); - } - requestRedraw(); -} - -template -void QuantityStructure::removeQuantity(std::string name, bool errorIfAbsent) { - - // Look for an existing quantity with this name - bool quantityExists = quantities.find(name) != quantities.end(); - bool floatingQuantityExists = floatingQuantities.find(name) != floatingQuantities.end(); - - if (errorIfAbsent && !(quantityExists || floatingQuantityExists)) { - exception("No quantity named " + name + " added to structure " + name); - return; - } - - // delete standard quantities - if (quantityExists) { - // If this is the active quantity, clear it - QuantityType& q = *quantities[name]; - if (dominantQuantity == &q) { - clearDominantQuantity(); - } - - // Delete the quantity - quantities.erase(name); - } - - // delete floating quantities - if (floatingQuantityExists) { - floatingQuantities.erase(name); - } -} - -template -void QuantityStructure::removeAllQuantities() { - while (quantities.size() > 0) { - removeQuantity(quantities.begin()->first); - } - while (floatingQuantities.size() > 0) { - removeQuantity(floatingQuantities.begin()->first); - } -} - -template -void QuantityStructure::setDominantQuantity(QuantityS* q) { - if (!q->dominates) { - exception("tried to set dominant quantity with quantity that has dominates=false"); - return; - } - - // Dominant quantity must be enabled - q->setEnabled(true); - - // All other dominating quantities will be disabled - for (auto& qp : quantities) { - QuantityType* qOther = qp.second.get(); - if (qOther->dominates && qOther->isEnabled() && qOther != q) { - qOther->setEnabled(false); - } - } - - dominantQuantity = q; -} - -template -void QuantityStructure::clearDominantQuantity() { - dominantQuantity = nullptr; -} - -template -void QuantityStructure::setAllQuantitiesEnabled(bool newEnabled) { - for (auto& x : quantities) { - x.second->setEnabled(newEnabled); - } - for (auto& x : floatingQuantities) { - x.second->setEnabled(newEnabled); - } -} - - -template -void QuantityStructure::buildQuantitiesUI() { - // Build the quantities - for (auto& x : quantities) { - x.second->buildUI(); - } - for (auto& x : floatingQuantities) { - x.second->buildUI(); - } -} - -template -void QuantityStructure::buildStructureOptionsUI() { - if (ImGui::BeginMenu("Quantity Selection")) { - if (ImGui::MenuItem("Enable all")) setAllQuantitiesEnabled(true); - if (ImGui::MenuItem("Disable all")) setAllQuantitiesEnabled(false); - ImGui::EndMenu(); - } -} - // === Floating Quantities === -template template -ScalarImageQuantity* QuantityStructure::addScalarImageQuantity(std::string name, size_t dimX, size_t dimY, - const T& values, ImageOrigin imageOrigin, - DataType type) { +ScalarImageQuantity* Structure::addScalarImageQuantity(std::string name, size_t dimX, size_t dimY, const T& values, + ImageOrigin imageOrigin, DataType type) { validateSize(values, dimX * dimY, "floating scalar image " + name); return this->addScalarImageQuantityImpl(name, dimX, dimY, standardizeArray(values), imageOrigin, type); } - -template template -ColorImageQuantity* QuantityStructure::addColorImageQuantity(std::string name, size_t dimX, size_t dimY, - const T& values_rgb, ImageOrigin imageOrigin) { +ColorImageQuantity* Structure::addColorImageQuantity(std::string name, size_t dimX, size_t dimY, const T& values_rgb, + ImageOrigin imageOrigin) { validateSize(values_rgb, dimX * dimY, "floating color image " + name); // standardize and pad out the alpha component @@ -210,10 +34,9 @@ ColorImageQuantity* QuantityStructure::addColorImageQuantity(std::string name } -template template -ColorImageQuantity* QuantityStructure::addColorAlphaImageQuantity(std::string name, size_t dimX, size_t dimY, - const T& values_rgba, ImageOrigin imageOrigin) { +ColorImageQuantity* Structure::addColorAlphaImageQuantity(std::string name, size_t dimX, size_t dimY, + const T& values_rgba, ImageOrigin imageOrigin) { validateSize(values_rgba, dimX * dimY, "floating color alpha image " + name); // standardize @@ -222,11 +45,11 @@ ColorImageQuantity* QuantityStructure::addColorAlphaImageQuantity(std::string return this->addColorImageQuantityImpl(name, dimX, dimY, standardVals, imageOrigin); } -template + template -DepthRenderImageQuantity* QuantityStructure::addDepthRenderImageQuantity(std::string name, size_t dimX, size_t dimY, - const T1& depthData, const T2& normalData, - ImageOrigin imageOrigin) { +DepthRenderImageQuantity* Structure::addDepthRenderImageQuantity(std::string name, size_t dimX, size_t dimY, + const T1& depthData, const T2& normalData, + ImageOrigin imageOrigin) { validateSize(depthData, dimX * dimY, "depth render image depth data " + name); validateSize(normalData, {dimX * dimY, 0}, "depth render image normal data " + name); @@ -238,11 +61,11 @@ DepthRenderImageQuantity* QuantityStructure::addDepthRenderImageQuantity(std: return this->addDepthRenderImageQuantityImpl(name, dimX, dimY, standardDepth, standardNormal, imageOrigin); } -template + template -ColorRenderImageQuantity* -QuantityStructure::addColorRenderImageQuantity(std::string name, size_t dimX, size_t dimY, const T1& depthData, - const T2& normalData, const T3& colorData, ImageOrigin imageOrigin) { +ColorRenderImageQuantity* Structure::addColorRenderImageQuantity(std::string name, size_t dimX, size_t dimY, + const T1& depthData, const T2& normalData, + const T3& colorData, ImageOrigin imageOrigin) { validateSize(depthData, dimX * dimY, "depth render image depth data " + name); validateSize(normalData, {dimX * dimY, 0}, "depth render image normal data " + name); @@ -257,12 +80,12 @@ QuantityStructure::addColorRenderImageQuantity(std::string name, size_t dimX, imageOrigin); } -template + template -ScalarRenderImageQuantity* -QuantityStructure::addScalarRenderImageQuantity(std::string name, size_t dimX, size_t dimY, const T1& depthData, - const T2& normalData, const T3& scalarData, ImageOrigin imageOrigin, - DataType type) { +ScalarRenderImageQuantity* Structure::addScalarRenderImageQuantity(std::string name, size_t dimX, size_t dimY, + const T1& depthData, const T2& normalData, + const T3& scalarData, ImageOrigin imageOrigin, + DataType type) { validateSize(depthData, dimX * dimY, "depth render image depth data " + name); validateSize(normalData, {dimX * dimY, 0}, "depth render image normal data " + name); @@ -277,11 +100,11 @@ QuantityStructure::addScalarRenderImageQuantity(std::string name, size_t dimX imageOrigin, type); } -template + template -RawColorRenderImageQuantity* -QuantityStructure::addRawColorRenderImageQuantity(std::string name, size_t dimX, size_t dimY, const T1& depthData, - const T2& colorData, ImageOrigin imageOrigin) { +RawColorRenderImageQuantity* Structure::addRawColorRenderImageQuantity(std::string name, size_t dimX, size_t dimY, + const T1& depthData, const T2& colorData, + ImageOrigin imageOrigin) { validateSize(depthData, dimX * dimY, "depth render image depth data " + name); validateSize(colorData, dimX * dimY, "depth render image color data " + name); @@ -293,10 +116,11 @@ QuantityStructure::addRawColorRenderImageQuantity(std::string name, size_t di return this->addRawColorRenderImageQuantityImpl(name, dimX, dimY, standardDepth, standardColor, imageOrigin); } -template + template -RawColorAlphaRenderImageQuantity* QuantityStructure::addRawColorAlphaRenderImageQuantity( - std::string name, size_t dimX, size_t dimY, const T1& depthData, const T2& colorData, ImageOrigin imageOrigin) { +RawColorAlphaRenderImageQuantity* +Structure::addRawColorAlphaRenderImageQuantity(std::string name, size_t dimX, size_t dimY, const T1& depthData, + const T2& colorData, ImageOrigin imageOrigin) { validateSize(depthData, dimX * dimY, "depth render image depth data " + name); validateSize(colorData, dimX * dimY, "depth render image color data " + name); @@ -308,116 +132,5 @@ RawColorAlphaRenderImageQuantity* QuantityStructure::addRawColorAlphaRenderIm return this->addRawColorAlphaRenderImageQuantityImpl(name, dimX, dimY, standardDepth, standardColor, imageOrigin); } -// === Floating Quantity Impls === - -// Forward declare helper functions, which wrap the constructors for the floating quantities below. -// Otherwise, we would have to include their respective headers here, and create some really gnarly header dependency -// chains. -ScalarImageQuantity* createScalarImageQuantity(Structure& parent, std::string name, size_t dimX, size_t dimY, - const std::vector& data, ImageOrigin imageOrigin, - DataType dataType); -ColorImageQuantity* createColorImageQuantity(Structure& parent, std::string name, size_t dimX, size_t dimY, - const std::vector& data, ImageOrigin imageOrigin); -DepthRenderImageQuantity* createDepthRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, - const std::vector& depthData, - const std::vector& normalData, ImageOrigin imageOrigin); - -ColorRenderImageQuantity* createColorRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, - const std::vector& depthData, - const std::vector& normalData, - const std::vector& colorData, ImageOrigin imageOrigin); - - -RawColorRenderImageQuantity* createRawColorRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, - const std::vector& depthData, - const std::vector& colorData, - ImageOrigin imageOrigin); - -RawColorAlphaRenderImageQuantity* createRawColorAlphaRenderImage(Structure& parent, std::string name, size_t dimX, - size_t dimY, const std::vector& depthData, - const std::vector& colorData, - ImageOrigin imageOrigin); - - -ScalarRenderImageQuantity* createScalarRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, - const std::vector& depthData, - const std::vector& normalData, - const std::vector& scalarData, ImageOrigin imageOrigin, - DataType type); - -template -ScalarImageQuantity* QuantityStructure::addScalarImageQuantityImpl(std::string name, size_t dimX, size_t dimY, - const std::vector& values, - ImageOrigin imageOrigin, DataType type) { - checkForQuantityWithNameAndDeleteOrError(name); - ScalarImageQuantity* q = createScalarImageQuantity(*this, name, dimX, dimY, values, imageOrigin, type); - addQuantity(q); - return q; -} - -template -ColorImageQuantity* QuantityStructure::addColorImageQuantityImpl(std::string name, size_t dimX, size_t dimY, - const std::vector& values, - ImageOrigin imageOrigin) { - checkForQuantityWithNameAndDeleteOrError(name); - ColorImageQuantity* q = createColorImageQuantity(*this, name, dimX, dimY, values, imageOrigin); - addQuantity(q); - return q; -} - -template -DepthRenderImageQuantity* QuantityStructure::addDepthRenderImageQuantityImpl( - std::string name, size_t dimX, size_t dimY, const std::vector& depthData, - const std::vector& normalData, ImageOrigin imageOrigin) { - checkForQuantityWithNameAndDeleteOrError(name); - DepthRenderImageQuantity* q = createDepthRenderImage(*this, name, dimX, dimY, depthData, normalData, imageOrigin); - addQuantity(q); - return q; -} - -template -ColorRenderImageQuantity* QuantityStructure::addColorRenderImageQuantityImpl( - std::string name, size_t dimX, size_t dimY, const std::vector& depthData, - const std::vector& normalData, const std::vector& colorData, ImageOrigin imageOrigin) { - checkForQuantityWithNameAndDeleteOrError(name); - ColorRenderImageQuantity* q = - createColorRenderImage(*this, name, dimX, dimY, depthData, normalData, colorData, imageOrigin); - addQuantity(q); - return q; -} - -template -ScalarRenderImageQuantity* QuantityStructure::addScalarRenderImageQuantityImpl( - std::string name, size_t dimX, size_t dimY, const std::vector& depthData, - const std::vector& normalData, const std::vector& scalarData, ImageOrigin imageOrigin, - DataType type) { - checkForQuantityWithNameAndDeleteOrError(name); - ScalarRenderImageQuantity* q = - createScalarRenderImage(*this, name, dimX, dimY, depthData, normalData, scalarData, imageOrigin, type); - addQuantity(q); - return q; -} - -template -RawColorRenderImageQuantity* QuantityStructure::addRawColorRenderImageQuantityImpl( - std::string name, size_t dimX, size_t dimY, const std::vector& depthData, - const std::vector& colorData, ImageOrigin imageOrigin) { - checkForQuantityWithNameAndDeleteOrError(name); - RawColorRenderImageQuantity* q = - createRawColorRenderImage(*this, name, dimX, dimY, depthData, colorData, imageOrigin); - addQuantity(q); - return q; -} - -template -RawColorAlphaRenderImageQuantity* QuantityStructure::addRawColorAlphaRenderImageQuantityImpl( - std::string name, size_t dimX, size_t dimY, const std::vector& depthData, - const std::vector& colorData, ImageOrigin imageOrigin) { - checkForQuantityWithNameAndDeleteOrError(name); - RawColorAlphaRenderImageQuantity* q = - createRawColorAlphaRenderImage(*this, name, dimX, dimY, depthData, colorData, imageOrigin); - addQuantity(q); - return q; -} } // namespace polyscope diff --git a/include/polyscope/surface_mesh.h b/include/polyscope/surface_mesh.h index e3bb9b82..bff5ef31 100644 --- a/include/polyscope/surface_mesh.h +++ b/include/polyscope/surface_mesh.h @@ -46,11 +46,6 @@ class SurfaceFaceTangentVectorQuantity; class SurfaceOneFormTangentVectorQuantity; -template <> // Specialize the quantity type -struct QuantityTypeHelper { - typedef SurfaceMeshQuantity type; -}; - struct SurfaceMeshPickResult { MeshElement elementType; // which kind of element did we click int64_t index; // index of the clicked element @@ -59,10 +54,8 @@ struct SurfaceMeshPickResult { // === The grand surface mesh class -class SurfaceMesh : public QuantityStructure { +class SurfaceMesh : public Structure { public: - typedef SurfaceMeshQuantity QuantityType; - // == Constructors // initializes members diff --git a/include/polyscope/surface_mesh_quantity.h b/include/polyscope/surface_mesh_quantity.h index 9f546c6e..fa8de79a 100644 --- a/include/polyscope/surface_mesh_quantity.h +++ b/include/polyscope/surface_mesh_quantity.h @@ -8,15 +8,15 @@ namespace polyscope { -// Forward delcare surface mesh class SurfaceMesh; -// Extend Quantity to add a few extra functions -class SurfaceMeshQuantity : public QuantityS { +class SurfaceMeshQuantity : public Quantity { public: SurfaceMeshQuantity(std::string name, SurfaceMesh& parentStructure, bool dominates = false); ~SurfaceMeshQuantity() {}; + SurfaceMesh& parent; // shadows and hides the generic member in Quantity + public: // Build GUI info about this element virtual void buildVertexInfoGUI(size_t vInd); diff --git a/include/polyscope/types.h b/include/polyscope/types.h index db94d69a..fac79714 100644 --- a/include/polyscope/types.h +++ b/include/polyscope/types.h @@ -15,7 +15,7 @@ enum class TransparencyMode { None = 0, Simple, Pretty }; enum class GroundPlaneMode { None, Tile, TileReflection, ShadowOnly }; enum class GroundPlaneHeightMode { Automatic = 0, Manual }; enum class BackFacePolicy { Identical, Different, Custom, Cull }; -enum class LimitFPSMode { IgnoreLimits = 0, BlockToHitTarget, SkipFramesToHitTarget}; +enum class LimitFPSMode { IgnoreLimits = 0, BlockToHitTarget, SkipFramesToHitTarget }; enum class PointRenderMode { Sphere = 0, Quad }; enum class MeshElement { VERTEX = 0, FACE, EDGE, HALFEDGE, CORNER }; diff --git a/include/polyscope/volume_grid.h b/include/polyscope/volume_grid.h index 3467d9c8..8161af09 100644 --- a/include/polyscope/volume_grid.h +++ b/include/polyscope/volume_grid.h @@ -21,17 +21,12 @@ class VolumeGrid; class VolumeGridNodeScalarQuantity; class VolumeGridCellScalarQuantity; -template <> // Specialize the quantity type -struct QuantityTypeHelper { - typedef VolumeGridQuantity type; -}; - struct VolumeGridPickResult { VolumeGridElement elementType; // which kind of element did we click int64_t index; // index of the clicked element }; -class VolumeGrid : public QuantityStructure { +class VolumeGrid : public Structure { public: // Construct a new volume grid structure VolumeGrid(std::string name, glm::uvec3 gridNodeDim_, glm::vec3 boundMin_, glm::vec3 boundMax_); diff --git a/include/polyscope/volume_grid_quantity.h b/include/polyscope/volume_grid_quantity.h index 93aea94d..2c7cd68e 100644 --- a/include/polyscope/volume_grid_quantity.h +++ b/include/polyscope/volume_grid_quantity.h @@ -8,15 +8,15 @@ namespace polyscope { -// Forward declare structure class VolumeGrid; -// Extend Quantity to add a few extra functions -class VolumeGridQuantity : public QuantityS { +class VolumeGridQuantity : public Quantity { public: VolumeGridQuantity(std::string name, VolumeGrid& parentStructure, bool dominates = false); ~VolumeGridQuantity() {}; + VolumeGrid& parent; // shadows and hides the generic member in Quantity + virtual bool isDrawingGridcubes() = 0; // Build GUI info about this element diff --git a/include/polyscope/volume_mesh.h b/include/polyscope/volume_mesh.h index 51389703..e2e809e9 100644 --- a/include/polyscope/volume_mesh.h +++ b/include/polyscope/volume_mesh.h @@ -29,11 +29,6 @@ class VolumeMeshVertexVectorQuantity; class VolumeMeshCellVectorQuantity; -template <> // Specialize the quantity type -struct QuantityTypeHelper { - typedef VolumeMeshQuantity type; -}; - struct VolumeMeshPickResult { VolumeMeshElement elementType; // which kind of element did we click int64_t index; // index of the clicked element @@ -41,10 +36,8 @@ struct VolumeMeshPickResult { // === The grand volume mesh class -class VolumeMesh : public QuantityStructure { +class VolumeMesh : public Structure { public: - typedef VolumeMeshQuantity QuantityType; - // === Member functions === // Construct a new volume mesh structure diff --git a/include/polyscope/volume_mesh_quantity.h b/include/polyscope/volume_mesh_quantity.h index 967bfe3f..8e01511c 100644 --- a/include/polyscope/volume_mesh_quantity.h +++ b/include/polyscope/volume_mesh_quantity.h @@ -3,19 +3,21 @@ #pragma once #include "polyscope/quantity.h" +#include "polyscope/slice_plane.h" #include "polyscope/structure.h" namespace polyscope { -// Forward declare volume mesh class VolumeMesh; -// Extend Quantity to add a few extra functions -class VolumeMeshQuantity : public QuantityS { +class VolumeMeshQuantity : public Quantity { public: VolumeMeshQuantity(std::string name, VolumeMesh& parentStructure, bool dominates = false); ~VolumeMeshQuantity() {}; + + VolumeMesh& parent; // shadows and hides the generic member in Quantity + virtual std::shared_ptr createSliceProgram() { return nullptr; }; virtual void drawSlice(polyscope::SlicePlane* sp) {}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e063f760..4953d1bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -153,6 +153,7 @@ endif() SET(SRCS + # Core functionality polyscope.cpp @@ -310,13 +311,11 @@ SET(HEADERS ${INCLUDE_ROOT}/point_cloud.h ${INCLUDE_ROOT}/point_cloud.ipp ${INCLUDE_ROOT}/point_cloud_color_quantity.h - ${INCLUDE_ROOT}/point_cloud_quantity.h ${INCLUDE_ROOT}/point_cloud_scalar_quantity.h ${INCLUDE_ROOT}/point_cloud_parameterization_quantity.h ${INCLUDE_ROOT}/point_cloud_vector_quantity.h ${INCLUDE_ROOT}/polyscope.h ${INCLUDE_ROOT}/quantity.h - ${INCLUDE_ROOT}/quantity.ipp ${INCLUDE_ROOT}/raw_color_render_image_quantity.h ${INCLUDE_ROOT}/render/color_maps.h ${INCLUDE_ROOT}/render/engine.h @@ -336,7 +335,6 @@ SET(HEADERS ${INCLUDE_ROOT}/slice_plane.h ${INCLUDE_ROOT}/standardize_data_array.h ${INCLUDE_ROOT}/structure.h - ${INCLUDE_ROOT}/structure.ipp ${INCLUDE_ROOT}/surface_color_quantity.h ${INCLUDE_ROOT}/surface_mesh.h ${INCLUDE_ROOT}/surface_mesh.ipp diff --git a/src/camera_view.cpp b/src/camera_view.cpp index 8c499df7..3e31bf19 100644 --- a/src/camera_view.cpp +++ b/src/camera_view.cpp @@ -24,7 +24,7 @@ const std::string CameraView::structureTypeName = "Camera View"; // Constructor CameraView::CameraView(std::string name, const CameraParameters& params_) - : QuantityStructure(name, structureTypeName), params(params_), + : Structure(name, structureTypeName), params(params_), widgetFocalLength(uniquePrefix() + "#widgetFocalLength", relativeValue(0.05)), widgetThickness(uniquePrefix() + "#widgetThickness", 0.02), widgetColor(uniquePrefix() + "#widgetColor", glm::vec3{0., 0., 0.}) { @@ -340,7 +340,7 @@ void CameraView::geometryChanged() { } requestRedraw(); - QuantityStructure::refresh(); + Structure::refresh(); } CameraViewPickResult CameraView::interpretPickResult(const PickResult& rawResult) { @@ -447,7 +447,7 @@ void CameraView::refresh() { nodeProgram.reset(); edgeProgram.reset(); pickFrameProgram.reset(); - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities } void CameraView::setViewToThisCamera(bool withFlight) { diff --git a/src/color_image_quantity.cpp b/src/color_image_quantity.cpp index f1c97f5d..1046ce25 100644 --- a/src/color_image_quantity.cpp +++ b/src/color_image_quantity.cpp @@ -150,15 +150,14 @@ void ColorImageQuantity::refresh() { } -ColorImageQuantity* ColorImageQuantity::setEnabled(bool newEnabled) { - if (newEnabled == isEnabled()) return this; +void ColorImageQuantity::setEnabled(bool newEnabled) { + if (newEnabled == isEnabled()) return; if (newEnabled == true && getShowFullscreen()) { // if drawing fullscreen, disable anything else which was already drawing fullscreen disableAllFullscreenArtists(); } enabled = newEnabled; requestRedraw(); - return this; } ColorImageQuantity* ColorImageQuantity::setIsPremultiplied(bool val) { diff --git a/src/curve_network.cpp b/src/curve_network.cpp index b3bfd800..fbae2a74 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -20,7 +20,7 @@ const std::string CurveNetwork::structureTypeName = "Curve Network"; // Constructor CurveNetwork::CurveNetwork(std::string name, std::vector nodes_, std::vector> edges_) : // clang-format off - QuantityStructure(name, typeName()), + Structure(name, typeName()), nodePositions(this, uniquePrefix() + "nodePositions", nodePositionsData), edgeTailInds(this, uniquePrefix() + "edgeTailInds", edgeTailIndsData), edgeTipInds(this, uniquePrefix() + "edgeTipInds", edgeTipIndsData), @@ -221,7 +221,7 @@ void CurveNetwork::drawPickDelayed() { std::vector CurveNetwork::addCurveNetworkNodeRules(std::vector initRules) { initRules = addStructureRules(initRules); - + initRules.push_back(view::getCurrentProjectionModeRaycastRule()); if (nodeRadiusQuantityName != "" || edgeRadiusQuantityName != "") { @@ -296,10 +296,9 @@ void CurveNetwork::preparePick() { size_t pickStart = pick::requestPickBufferRange(this, totalPickElements); { // Set up node picking program - nodePickProgram = render::engine->requestShader( - "RAYCAST_SPHERE", - addCurveNetworkNodeRules({"SPHERE_PROPAGATE_COLOR"}), - render::ShaderReplacementDefaults::Pick); + nodePickProgram = + render::engine->requestShader("RAYCAST_SPHERE", addCurveNetworkNodeRules({"SPHERE_PROPAGATE_COLOR"}), + render::ShaderReplacementDefaults::Pick); // Fill color buffer with packed point indices std::vector pickColors; @@ -408,7 +407,7 @@ void CurveNetwork::refresh() { nodePickProgram.reset(); edgePickProgram.reset(); requestRedraw(); - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities } void CurveNetwork::recomputeGeometryIfPopulated() { edgeCenters.recomputeIfPopulated(); } @@ -445,7 +444,8 @@ void CurveNetwork::buildNodePickUI(const CurveNetworkPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildNodeInfoGUI(nodeInd); + CurveNetworkQuantity* q = static_cast(x.second.get()); + q->buildNodeInfoGUI(nodeInd); } ImGui::Indent(-20.); @@ -469,7 +469,8 @@ void CurveNetwork::buildEdgePickUI(const CurveNetworkPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildEdgeInfoGUI(edgeInd); + CurveNetworkQuantity* q = static_cast(x.second.get()); + q->buildEdgeInfoGUI(edgeInd); } ImGui::Indent(-20.); @@ -644,7 +645,7 @@ std::string CurveNetwork::typeName() { return structureTypeName; } // === Quantities CurveNetworkQuantity::CurveNetworkQuantity(std::string name_, CurveNetwork& curveNetwork_, bool dominates_) - : QuantityS(name_, curveNetwork_, dominates_) {} + : Quantity(name_, curveNetwork_, dominates_), parent(curveNetwork_) {} void CurveNetworkQuantity::buildNodeInfoGUI(size_t nodeInd) {} @@ -706,7 +707,7 @@ CurveNetworkEdgeVectorQuantity* CurveNetwork::addEdgeVectorQuantityImpl(std::str CurveNetworkNodeScalarQuantity& CurveNetwork::resolveNodeRadiusQuantity() { CurveNetworkNodeScalarQuantity* sizeScalarQ = nullptr; - CurveNetworkQuantity* sizeQ = getQuantity(nodeRadiusQuantityName); + CurveNetworkQuantity* sizeQ = getStructureQuantity(nodeRadiusQuantityName); if (sizeQ != nullptr) { sizeScalarQ = dynamic_cast(sizeQ); if (sizeScalarQ == nullptr) { @@ -722,7 +723,7 @@ CurveNetworkNodeScalarQuantity& CurveNetwork::resolveNodeRadiusQuantity() { CurveNetworkEdgeScalarQuantity& CurveNetwork::resolveEdgeRadiusQuantity() { CurveNetworkEdgeScalarQuantity* sizeScalarQ = nullptr; - CurveNetworkQuantity* sizeQ = getQuantity(edgeRadiusQuantityName); + CurveNetworkQuantity* sizeQ = getStructureQuantity(edgeRadiusQuantityName); if (sizeQ != nullptr) { sizeScalarQ = dynamic_cast(sizeQ); if (sizeScalarQ == nullptr) { diff --git a/src/floating_quantity.cpp b/src/floating_quantity.cpp index 5b430abe..c8a82a7e 100644 --- a/src/floating_quantity.cpp +++ b/src/floating_quantity.cpp @@ -12,7 +12,7 @@ namespace polyscope { void FloatingQuantity::buildUI() { - // NOTE: duplicated here and in the QuantityS version + // NOTE: duplicated here and in the Quantity version if (ImGui::TreeNode(niceName().c_str())) { diff --git a/src/floating_quantity_structure.cpp b/src/floating_quantity_structure.cpp index b8e47d25..d95104e6 100644 --- a/src/floating_quantity_structure.cpp +++ b/src/floating_quantity_structure.cpp @@ -17,8 +17,7 @@ namespace polyscope { const std::string FloatingQuantityStructure::structureTypeName = "Floating Quantities"; // Constructor -FloatingQuantityStructure::FloatingQuantityStructure(std::string name) - : QuantityStructure(name, structureTypeName) {} +FloatingQuantityStructure::FloatingQuantityStructure(std::string name) : Structure(name, structureTypeName) {} FloatingQuantityStructure::~FloatingQuantityStructure() {} @@ -79,7 +78,7 @@ void FloatingQuantityStructure::buildUI() { // Do any structure-specific stuff here this->buildCustomUI(); - // Build quantities list, in the common case of a QuantityStructure + // Build quantities list this->buildQuantitiesUI(); ImGui::PopID(); diff --git a/src/point_cloud.cpp b/src/point_cloud.cpp index be08eaa3..618dc2b5 100644 --- a/src/point_cloud.cpp +++ b/src/point_cloud.cpp @@ -24,7 +24,7 @@ const std::string PointCloud::structureTypeName = "Point Cloud"; // Constructor PointCloud::PointCloud(std::string name, std::vector points_) : // clang-format off - QuantityStructure(name, structureTypeName), + Structure(name, structureTypeName), points(this, uniquePrefix() + "points", pointsData), pointsData(std::move(points_)), pointRenderMode(uniquePrefix() + "pointRenderMode", "sphere"), @@ -269,7 +269,7 @@ std::vector PointCloud::addPointCloudRules(std::vector // helper PointCloudScalarQuantity& PointCloud::resolvePointRadiusQuantity() { PointCloudScalarQuantity* sizeScalarQ = nullptr; - PointCloudQuantity* sizeQ = getQuantity(pointRadiusQuantityName); + PointCloudQuantity* sizeQ = getStructureQuantity(pointRadiusQuantityName); if (sizeQ != nullptr) { sizeScalarQ = dynamic_cast(sizeQ); if (sizeScalarQ == nullptr) { @@ -409,7 +409,7 @@ std::string PointCloud::typeName() { return structureTypeName; } void PointCloud::refresh() { program.reset(); pickProgram.reset(); - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities } @@ -455,7 +455,7 @@ void PointCloud::clearTransparencyQuantity() { PointCloudScalarQuantity& PointCloud::resolveTransparencyQuantity() { PointCloudScalarQuantity* transparencyScalarQ = nullptr; - PointCloudQuantity* anyQ = getQuantity(transparencyQuantityName); + PointCloudQuantity* anyQ = getStructureQuantity(transparencyQuantityName); if (anyQ != nullptr) { transparencyScalarQ = dynamic_cast(anyQ); if (transparencyScalarQ == nullptr) { @@ -472,7 +472,7 @@ PointCloudScalarQuantity& PointCloud::resolveTransparencyQuantity() { // Quantity default methods PointCloudQuantity::PointCloudQuantity(std::string name_, PointCloud& pointCloud_, bool dominates_) - : QuantityS(name_, pointCloud_, dominates_) {} + : Quantity(name_, pointCloud_, dominates_), parent(pointCloud_) {} void PointCloudQuantity::buildInfoGUI(size_t pointInd) {} diff --git a/src/quantity.cpp b/src/quantity.cpp index cf55e257..9b83968f 100644 --- a/src/quantity.cpp +++ b/src/quantity.cpp @@ -5,6 +5,7 @@ #include "imgui.h" #include "polyscope/messages.h" +#include "polyscope/polyscope.h" #include "polyscope/structure.h" namespace polyscope { @@ -12,9 +13,16 @@ namespace polyscope { // === General Quantities // (subclasses could be a structure-specific quantity or a floating quantity) -Quantity::Quantity(std::string name_, Structure& parentStructure_) - : parent(parentStructure_), name(name_), enabled(uniquePrefix() + "enabled", false) { +Quantity::Quantity(std::string name_, Structure& parentStructure_, bool dominates_) + : parent(parentStructure_), name(name_), enabled(uniquePrefix() + "enabled", false), dominates(dominates_) { validateName(name); + + // Hack: if the quantity pulls enabled=true from the cache, need to make sure the logic from setEnabled(true) happens, + // so toggle it real quick + if (isEnabled()) { + setEnabled(false); + setEnabled(true); + } } Quantity::~Quantity() {}; @@ -27,7 +35,24 @@ void Quantity::drawPick() {} void Quantity::drawPickDelayed() {} -void Quantity::buildUI() {} +void Quantity::buildUI() { + // NOTE: duplicated here and in the FloatingQuantity version + + if (ImGui::TreeNode(niceName().c_str())) { + + // Enabled checkbox + bool enabledLocal = enabled.get(); + if (ImGui::Checkbox("Enabled", &enabledLocal)) { + setEnabled(enabledLocal); + } + + // Call custom UI + this->buildCustomUI(); + + ImGui::TreePop(); + } +} + void Quantity::buildCustomUI() {} @@ -35,6 +60,23 @@ void Quantity::buildPickUI(size_t localPickInd) {} bool Quantity::isEnabled() { return enabled.get(); } +void Quantity::setEnabled(bool newEnabled) { + if (newEnabled == enabled.get()) return; + + enabled = newEnabled; + + // Dominating quantities need to update themselves as their parent's dominating quantity + if (dominates) { + if (newEnabled == true) { + parent.setDominantQuantity(this); + } else { + parent.clearDominantQuantity(); + } + } + + requestRedraw(); +} + void Quantity::refresh() { requestRedraw(); } std::string Quantity::niceName() { return name; } diff --git a/src/render/ground_plane.cpp b/src/render/ground_plane.cpp index d77a2450..d56fdb8d 100644 --- a/src/render/ground_plane.cpp +++ b/src/render/ground_plane.cpp @@ -178,7 +178,7 @@ void GroundPlane::freeAllOwnedResources() { blurProgram.reset(); copyTexProgram.reset(); - for(int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { blurColorTextures[i].reset(); blurFrameBuffers[i].reset(); } diff --git a/src/render/initialize_backend.cpp b/src/render/initialize_backend.cpp index 9a38770a..cc15b009 100644 --- a/src/render/initialize_backend.cpp +++ b/src/render/initialize_backend.cpp @@ -32,7 +32,7 @@ void initializeRenderEngine(std::string backend) { if (backend == "") { backend = "auto"; // treat "" as "auto" } - + // Quick check to print a nice error for a bad name std::vector knownBackendNames = {"openGL3_glfw", "openGL3_egl", "openGL_mock", "auto"}; if (std::find(knownBackendNames.begin(), knownBackendNames.end(), backend) == knownBackendNames.end()) { diff --git a/src/render/opengl/shaders/common.cpp b/src/render/opengl/shaders/common.cpp index 7b38a339..578f3f98 100644 --- a/src/render/opengl/shaders/common.cpp +++ b/src/render/opengl/shaders/common.cpp @@ -240,8 +240,8 @@ bool raySphereIntersection(vec3 rayStart, vec3 rayDir, vec3 sphereCenter, float } )" -// Split the raw string literal to avoid compiler string length limits -R"( + // Split the raw string literal to avoid compiler string length limits + R"( bool rayPlaneIntersection(vec3 rayStart, vec3 rayDir, vec3 planePos, vec3 planeDir, out float tHit, out vec3 pHit, out vec3 nHit) { diff --git a/src/render_image_quantity_base.cpp b/src/render_image_quantity_base.cpp index 2e368279..356356dd 100644 --- a/src/render_image_quantity_base.cpp +++ b/src/render_image_quantity_base.cpp @@ -141,15 +141,14 @@ void RenderImageQuantityBase::disableFullscreenDrawing() { } } -RenderImageQuantityBase* RenderImageQuantityBase::setEnabled(bool newEnabled) { - if (newEnabled == isEnabled()) return this; +void RenderImageQuantityBase::setEnabled(bool newEnabled) { + if (newEnabled == isEnabled()) return; if (newEnabled == true && !allowFullscreenCompositing.get()) { // if drawing fullscreen, disable anything else which was already drawing fullscreen disableAllFullscreenArtists(); } enabled = newEnabled; requestRedraw(); - return this; } RenderImageQuantityBase* RenderImageQuantityBase::setMaterial(std::string m) { diff --git a/src/scalar_image_quantity.cpp b/src/scalar_image_quantity.cpp index c9a9f383..e7f9abf0 100644 --- a/src/scalar_image_quantity.cpp +++ b/src/scalar_image_quantity.cpp @@ -152,15 +152,14 @@ void ScalarImageQuantity::refresh() { std::string ScalarImageQuantity::niceName() { return name + " (scalar image)"; } -ScalarImageQuantity* ScalarImageQuantity::setEnabled(bool newEnabled) { - if (newEnabled == isEnabled()) return this; +void ScalarImageQuantity::setEnabled(bool newEnabled) { + if (newEnabled == isEnabled()) return; if (newEnabled == true && getShowFullscreen()) { // if drawing fullscreen, disable anything else which was already drawing fullscreen disableAllFullscreenArtists(); } enabled = newEnabled; requestRedraw(); - return this; } diff --git a/src/simple_triangle_mesh.cpp b/src/simple_triangle_mesh.cpp index 4db7bb77..549a2ce4 100644 --- a/src/simple_triangle_mesh.cpp +++ b/src/simple_triangle_mesh.cpp @@ -20,7 +20,7 @@ const std::string SimpleTriangleMesh::structureTypeName = "Simple Triangle Mesh" SimpleTriangleMesh::SimpleTriangleMesh(std::string name, std::vector vertices_, std::vector faces_) : // clang-format off - QuantityStructure(name, structureTypeName), + Structure(name, structureTypeName), vertices(this, uniquePrefix() + "vertices", verticesData), faces(this, uniquePrefix() + "faces", facesData), verticesData(std::move(vertices_)), @@ -264,7 +264,7 @@ void SimpleTriangleMesh::refresh() { program.reset(); pickProgram.reset(); requestRedraw(); - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities } void SimpleTriangleMesh::updateObjectSpaceBounds() { diff --git a/src/slice_plane.cpp b/src/slice_plane.cpp index 2ea7ff4a..204b3756 100644 --- a/src/slice_plane.cpp +++ b/src/slice_plane.cpp @@ -286,7 +286,8 @@ void SlicePlane::drawGeometry() { for (auto it = vMesh->quantities.begin(); it != vMesh->quantities.end(); it++) { if (!it->second->isEnabled()) continue; - it->second->drawSlice(this); + VolumeMeshQuantity* vq = static_cast(it->second.get()); + vq->drawSlice(this); } } } diff --git a/src/structure.cpp b/src/structure.cpp index 39ef2595..9e6c3ee2 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -2,7 +2,11 @@ #include "polyscope/structure.h" +#include "polyscope/floating_quantity.h" #include "polyscope/polyscope.h" +#include "polyscope/quantity.h" + +#include "polyscope/floating_quantities.h" #include "imgui.h" @@ -138,7 +142,7 @@ void Structure::buildUI() { // Do any structure-specific stuff here this->buildCustomUI(); - // Build quantities list, in the common case of a QuantityStructure + // Build quantities list, in the common case of a Structure this->buildQuantitiesUI(); ImGui::TreePop(); @@ -147,15 +151,38 @@ void Structure::buildUI() { } -void Structure::buildQuantitiesUI() {} +void Structure::buildQuantitiesUI() { + // Build the quantities + for (auto& x : quantities) { + x.second->buildUI(); + } + for (auto& x : floatingQuantities) { + x.second->buildUI(); + } +} + -void Structure::buildSharedStructureUI() {} +void Structure::buildStructureOptionsUI() { + if (ImGui::BeginMenu("Quantity Selection")) { + if (ImGui::MenuItem("Enable all")) setAllQuantitiesEnabled(true); + if (ImGui::MenuItem("Disable all")) setAllQuantitiesEnabled(false); + ImGui::EndMenu(); + } +} -void Structure::buildStructureOptionsUI() {} +void Structure::buildSharedStructureUI() {} void Structure::buildCustomOptionsUI() {} void Structure::refresh() { + + for (auto& qp : quantities) { + qp.second->refresh(); + } + for (auto& qp : floatingQuantities) { + qp.second->refresh(); + } + updateObjectSpaceBounds(); requestRedraw(); } @@ -350,4 +377,250 @@ bool Structure::getIgnoreSlicePlane(std::string name) { return ignoreThisPlane; } +void Structure::addQuantity(Quantity* q, bool allowReplacement) { + + // Check if a quantity with this name exists, remove it or throw and error if so + checkForQuantityWithNameAndDeleteOrError(q->name, allowReplacement); + + // Add the new quantity and take ownership + quantities[q->name] = std::unique_ptr(q); +} + + +void Structure::addQuantity(FloatingQuantity* q, bool allowReplacement) { + + // Check if a quantity with this name exists, remove it or throw and error if so + checkForQuantityWithNameAndDeleteOrError(q->name, allowReplacement); + + // Add the new quantity + floatingQuantities[q->name] = std::unique_ptr(q); +} + + +Quantity* Structure::getQuantity(std::string name) { + if (quantities.find(name) == quantities.end()) { + return nullptr; + } + return quantities[name].get(); +} + + +FloatingQuantity* Structure::getFloatingQuantity(std::string name) { + if (floatingQuantities.find(name) == floatingQuantities.end()) { + return nullptr; + } + return floatingQuantities[name].get(); +} + + +void Structure::removeQuantity(std::string name, bool errorIfAbsent) { + + // Look for an existing quantity with this name + bool quantityExists = quantities.find(name) != quantities.end(); + bool floatingQuantityExists = floatingQuantities.find(name) != floatingQuantities.end(); + + if (errorIfAbsent && !(quantityExists || floatingQuantityExists)) { + exception("No quantity named " + name + " added to structure " + name); + return; + } + + // delete standard quantities + if (quantityExists) { + // If this is the active quantity, clear it + Quantity& q = *quantities[name]; + if (dominantQuantity == &q) { + clearDominantQuantity(); + } + + // Delete the quantity + quantities.erase(name); + } + + // delete floating quantities + if (floatingQuantityExists) { + floatingQuantities.erase(name); + } +} + + +void Structure::removeAllQuantities() { + while (quantities.size() > 0) { + removeQuantity(quantities.begin()->first); + } + while (floatingQuantities.size() > 0) { + removeQuantity(floatingQuantities.begin()->first); + } +} + + +void Structure::setDominantQuantity(Quantity* q) { + if (!q->dominates) { + exception("tried to set dominant quantity with quantity that has dominates=false"); + return; + } + + // Dominant quantity must be enabled + q->setEnabled(true); + + // All other dominating quantities will be disabled + for (auto& qp : quantities) { + Quantity* qOther = qp.second.get(); + if (qOther->dominates && qOther->isEnabled() && qOther != q) { + qOther->setEnabled(false); + } + } + + dominantQuantity = q; +} + + +void Structure::clearDominantQuantity() { dominantQuantity = nullptr; } + + +void Structure::setAllQuantitiesEnabled(bool newEnabled) { + for (auto& x : quantities) { + x.second->setEnabled(newEnabled); + } + for (auto& x : floatingQuantities) { + x.second->setEnabled(newEnabled); + } +} + +void Structure::checkForQuantityWithNameAndDeleteOrError(std::string name, bool allowReplacement) { + + // Look for an existing quantity with this name + bool quantityExists = quantities.find(name) != quantities.end(); + bool floatingQuantityExists = floatingQuantities.find(name) != floatingQuantities.end(); + + // if it already exists and we cannot replace, throw an error + if (!allowReplacement && (quantityExists || floatingQuantityExists)) { + exception("Tried to add quantity with name: [" + name + + "], but a quantity with that name already exists on the structure [" + name + + "]. Use the allowReplacement option like addQuantity(..., true) to replace."); + } + + // Remove the old quantity + if (quantityExists || floatingQuantityExists) { + removeQuantity(name); + } +} + +// === Floating Quantity Impls === + +// Forward declare helper functions, which wrap the constructors for the floating quantities below. +// Otherwise, we would have to include their respective headers here, and create some really gnarly header dependency +// chains. +ScalarImageQuantity* createScalarImageQuantity(Structure& parent, std::string name, size_t dimX, size_t dimY, + const std::vector& data, ImageOrigin imageOrigin, + DataType dataType); +ColorImageQuantity* createColorImageQuantity(Structure& parent, std::string name, size_t dimX, size_t dimY, + const std::vector& data, ImageOrigin imageOrigin); +DepthRenderImageQuantity* createDepthRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& normalData, ImageOrigin imageOrigin); + +ColorRenderImageQuantity* createColorRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& normalData, + const std::vector& colorData, ImageOrigin imageOrigin); + + +RawColorRenderImageQuantity* createRawColorRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& colorData, + ImageOrigin imageOrigin); + +RawColorAlphaRenderImageQuantity* createRawColorAlphaRenderImage(Structure& parent, std::string name, size_t dimX, + size_t dimY, const std::vector& depthData, + const std::vector& colorData, + ImageOrigin imageOrigin); + + +ScalarRenderImageQuantity* createScalarRenderImage(Structure& parent, std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& normalData, + const std::vector& scalarData, ImageOrigin imageOrigin, + DataType type); + + +ScalarImageQuantity* Structure::addScalarImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& values, ImageOrigin imageOrigin, + DataType type) { + checkForQuantityWithNameAndDeleteOrError(name); + ScalarImageQuantity* q = createScalarImageQuantity(*this, name, dimX, dimY, values, imageOrigin, type); + addQuantity(q); + return q; +} + + +ColorImageQuantity* Structure::addColorImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& values, + ImageOrigin imageOrigin) { + checkForQuantityWithNameAndDeleteOrError(name); + ColorImageQuantity* q = createColorImageQuantity(*this, name, dimX, dimY, values, imageOrigin); + addQuantity(q); + return q; +} + + +DepthRenderImageQuantity* Structure::addDepthRenderImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& normalData, + ImageOrigin imageOrigin) { + checkForQuantityWithNameAndDeleteOrError(name); + DepthRenderImageQuantity* q = createDepthRenderImage(*this, name, dimX, dimY, depthData, normalData, imageOrigin); + addQuantity(q); + return q; +} + + +ColorRenderImageQuantity* Structure::addColorRenderImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& normalData, + const std::vector& colorData, + ImageOrigin imageOrigin) { + checkForQuantityWithNameAndDeleteOrError(name); + ColorRenderImageQuantity* q = + createColorRenderImage(*this, name, dimX, dimY, depthData, normalData, colorData, imageOrigin); + addQuantity(q); + return q; +} + + +ScalarRenderImageQuantity* Structure::addScalarRenderImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& normalData, + const std::vector& scalarData, + ImageOrigin imageOrigin, DataType type) { + checkForQuantityWithNameAndDeleteOrError(name); + ScalarRenderImageQuantity* q = + createScalarRenderImage(*this, name, dimX, dimY, depthData, normalData, scalarData, imageOrigin, type); + addQuantity(q); + return q; +} + + +RawColorRenderImageQuantity* Structure::addRawColorRenderImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& colorData, + ImageOrigin imageOrigin) { + checkForQuantityWithNameAndDeleteOrError(name); + RawColorRenderImageQuantity* q = + createRawColorRenderImage(*this, name, dimX, dimY, depthData, colorData, imageOrigin); + addQuantity(q); + return q; +} + + +RawColorAlphaRenderImageQuantity* +Structure::addRawColorAlphaRenderImageQuantityImpl(std::string name, size_t dimX, size_t dimY, + const std::vector& depthData, + const std::vector& colorData, ImageOrigin imageOrigin) { + checkForQuantityWithNameAndDeleteOrError(name); + RawColorAlphaRenderImageQuantity* q = + createRawColorAlphaRenderImage(*this, name, dimX, dimY, depthData, colorData, imageOrigin); + addQuantity(q); + return q; +} + } // namespace polyscope diff --git a/src/surface_mesh.cpp b/src/surface_mesh.cpp index 0d7809f7..a8fa78a1 100644 --- a/src/surface_mesh.cpp +++ b/src/surface_mesh.cpp @@ -22,7 +22,7 @@ const std::string SurfaceMesh::structureTypeName = "Surface Mesh"; SurfaceMesh::SurfaceMesh(std::string name_) - : QuantityStructure(name_, typeName()), + : Structure(name_, typeName()), // clang-format off // == managed quantities @@ -1190,7 +1190,8 @@ void SurfaceMesh::buildVertexInfoGui(const SurfaceMeshPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildVertexInfoGUI(vInd); + SurfaceMeshQuantity* q = static_cast(x.second.get()); + q->buildVertexInfoGUI(vInd); } ImGui::Indent(-20.); @@ -1216,7 +1217,8 @@ void SurfaceMesh::buildFaceInfoGui(const SurfaceMeshPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildFaceInfoGUI(fInd); + SurfaceMeshQuantity* q = static_cast(x.second.get()); + q->buildFaceInfoGUI(fInd); } ImGui::Indent(-20.); @@ -1240,7 +1242,8 @@ void SurfaceMesh::buildEdgeInfoGui(const SurfaceMeshPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildEdgeInfoGUI(eInd); + SurfaceMeshQuantity* q = static_cast(x.second.get()); + q->buildEdgeInfoGUI(eInd); } ImGui::Indent(-20.); @@ -1264,7 +1267,8 @@ void SurfaceMesh::buildHalfedgeInfoGui(const SurfaceMeshPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildHalfedgeInfoGUI(heInd); + SurfaceMeshQuantity* q = static_cast(x.second.get()); + q->buildHalfedgeInfoGUI(heInd); } ImGui::Indent(-20.); @@ -1285,7 +1289,8 @@ void SurfaceMesh::buildCornerInfoGui(const SurfaceMeshPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildCornerInfoGUI(cInd); + SurfaceMeshQuantity* q = static_cast(x.second.get()); + q->buildCornerInfoGUI(cInd); } ImGui::Indent(-20.); @@ -1470,7 +1475,7 @@ void SurfaceMesh::refresh() { program.reset(); pickProgram.reset(); requestRedraw(); - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities } void SurfaceMesh::updateObjectSpaceBounds() { @@ -1665,7 +1670,7 @@ void SurfaceMesh::clearTransparencyQuantity() { SurfaceScalarQuantity& SurfaceMesh::resolveTransparencyQuantity() { SurfaceScalarQuantity* transparencyScalarQ = nullptr; - SurfaceMeshQuantity* anyQ = getQuantity(transparencyQuantityName); + SurfaceMeshQuantity* anyQ = getStructureQuantity(transparencyQuantityName); if (anyQ != nullptr) { transparencyScalarQ = dynamic_cast(anyQ); if (transparencyScalarQ == nullptr) { @@ -1980,14 +1985,17 @@ SurfaceMesh::addOneFormTangentVectorQuantityImpl(std::string name, const std::ve } SurfaceParameterizationQuantity* SurfaceMesh::getParameterization(std::string name) { - SurfaceMeshQuantity* newQ = this->getQuantity(name); + Quantity* newQ = this->getQuantity(name); SurfaceParameterizationQuantity* param = dynamic_cast(newQ); + if (param == nullptr) { + exception("No parameterization quantity named " + name + " found on surface mesh " + this->getName()); + } return param; } SurfaceMeshQuantity::SurfaceMeshQuantity(std::string name, SurfaceMesh& parentStructure, bool dominates) - : QuantityS(name, parentStructure, dominates) {} + : Quantity(name, parentStructure, dominates), parent(parentStructure) {} void SurfaceMeshQuantity::buildVertexInfoGUI(size_t vInd) {} void SurfaceMeshQuantity::buildFaceInfoGUI(size_t fInd) {} void SurfaceMeshQuantity::buildEdgeInfoGUI(size_t eInd) {} diff --git a/src/volume_grid.cpp b/src/volume_grid.cpp index f108a767..5d3934ac 100644 --- a/src/volume_grid.cpp +++ b/src/volume_grid.cpp @@ -12,7 +12,7 @@ namespace polyscope { const std::string VolumeGrid::structureTypeName = "Volume Grid"; VolumeGrid::VolumeGrid(std::string name, glm::uvec3 gridNodeDim_, glm::vec3 boundMin_, glm::vec3 boundMax_) - : QuantityStructure(name, typeName()), + : Structure(name, typeName()), // clang-format off // == managed quantities @@ -170,7 +170,7 @@ void VolumeGrid::drawPick() { // Draw the actual grid render::engine->setBackfaceCull(true); pickProgram->draw(); - + for (auto& x : quantities) { x.second->drawPick(); } @@ -293,7 +293,7 @@ void VolumeGrid::updateObjectSpaceBounds() { std::string VolumeGrid::typeName() { return structureTypeName; } void VolumeGrid::refresh() { - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities program.reset(); pickProgram.reset(); @@ -419,8 +419,8 @@ double VolumeGrid::getCubeSizeFactor() { return cubeSizeFactor.get(); } // === Register functions -VolumeGridQuantity::VolumeGridQuantity(std::string name_, VolumeGrid& curveNetwork_, bool dominates_) - : QuantityS(name_, curveNetwork_, dominates_) {} +VolumeGridQuantity::VolumeGridQuantity(std::string name_, VolumeGrid& volumeGrid_, bool dominates_) + : Quantity(name_, volumeGrid_, dominates_), parent(volumeGrid_) {} VolumeGridNodeScalarQuantity* VolumeGrid::addNodeScalarQuantityImpl(std::string name, const std::vector& data, @@ -549,7 +549,8 @@ void VolumeGrid::buildNodeInfoGUI(const VolumeGridPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildNodeInfoGUI(nInd); + VolumeGridQuantity* q = static_cast(x.second.get()); + q->buildNodeInfoGUI(nInd); } ImGui::Indent(-20.); @@ -575,7 +576,8 @@ void VolumeGrid::buildCellInfoGUI(const VolumeGridPickResult& result) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildCellInfoGUI(cellInd); + VolumeGridQuantity* q = static_cast(x.second.get()); + q->buildCellInfoGUI(cellInd); } ImGui::Indent(-20.); diff --git a/src/volume_mesh.cpp b/src/volume_mesh.cpp index e79503aa..cb15871a 100644 --- a/src/volume_mesh.cpp +++ b/src/volume_mesh.cpp @@ -97,7 +97,7 @@ const std::vector>> VolumeMesh::stencilHex = VolumeMesh::VolumeMesh(std::string name, const std::vector& vertexPositions_, const std::vector>& cellIndices_) - : QuantityStructure(name, typeName()), + : Structure(name, typeName()), // clang-format off // == managed quantities @@ -878,7 +878,8 @@ void VolumeMesh::buildVertexInfoGui(size_t vInd) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildVertexInfoGUI(vInd); + VolumeMeshQuantity* q = static_cast(x.second.get()); + q->buildVertexInfoGUI(vInd); } ImGui::Indent(-20.); @@ -897,7 +898,8 @@ void VolumeMesh::buildCellInfoGUI(size_t cellInd) { ImGui::Columns(2); ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() / 3); for (auto& x : quantities) { - x.second->buildCellInfoGUI(cellInd); + VolumeMeshQuantity* q = static_cast(x.second.get()); + q->buildCellInfoGUI(cellInd); } ImGui::Indent(-20.); @@ -975,13 +977,13 @@ void VolumeMesh::refresh() { pickProgram.reset(); refreshVolumeMeshListeners(); requestRedraw(); - QuantityStructure::refresh(); // call base class version, which refreshes quantities + Structure::refresh(); // call base class version, which refreshes quantities } void VolumeMesh::geometryChanged() { recomputeGeometryIfPopulated(); requestRedraw(); - QuantityStructure::refresh(); // TODO fixme unneeded, right? + Structure::refresh(); // TODO fixme unneeded, right? } void VolumeMesh::recomputeGeometryIfPopulated() { @@ -1118,7 +1120,7 @@ VolumeMesh::addCellVectorQuantityImpl(std::string name, const std::vector(name, parentStructure, dominates) {} + : Quantity(name, parentStructure, dominates), parent(parentStructure) {} void VolumeMeshQuantity::buildVertexInfoGUI(size_t vInd) {} void VolumeMeshQuantity::buildFaceInfoGUI(size_t fInd) {} void VolumeMeshQuantity::buildEdgeInfoGUI(size_t eInd) {} diff --git a/src/volume_mesh_scalar_quantity.cpp b/src/volume_mesh_scalar_quantity.cpp index 127d8901..e3bf2a9c 100644 --- a/src/volume_mesh_scalar_quantity.cpp +++ b/src/volume_mesh_scalar_quantity.cpp @@ -175,7 +175,7 @@ void VolumeMeshVertexScalarQuantity::setLevelSetVisibleQuantity(std::string name if (pair == parent.quantities.end()) { return; } - VolumeMeshQuantity* vmq = pair->second.get(); + Quantity* vmq = pair->second.get(); VolumeMeshVertexScalarQuantity* q = dynamic_cast(vmq); if (q == nullptr) { return; @@ -220,10 +220,10 @@ void VolumeMeshVertexScalarQuantity::buildCustomUI() { ImGui::DragFloat("##value", &levelSetValue, 0.01f, (float)colorBar.colormapRange.first, (float)colorBar.colormapRange.second); if (ImGui::BeginMenu("Show Quantity")) { - std::map>::iterator it; + std::map>::iterator it; for (it = parent.quantities.begin(); it != parent.quantities.end(); it++) { std::string quantityName = it->first; - VolumeMeshQuantity* vmq = it->second.get(); + Quantity* vmq = it->second.get(); VolumeMeshVertexScalarQuantity* vmvsq = dynamic_cast(vmq); if (vmvsq != nullptr && ImGui::MenuItem(quantityName.c_str(), NULL, showQuantity == it->second.get())) { setLevelSetVisibleQuantity(quantityName); diff --git a/test/src/basics_test.cpp b/test/src/basics_test.cpp index 1544705c..9b8ab30e 100644 --- a/test/src/basics_test.cpp +++ b/test/src/basics_test.cpp @@ -153,9 +153,9 @@ TEST_F(PolyscopeTest, ImPlotBasic) { std::vector xvals = {0., 2., 4., 8.}; - auto showCallback = [&]() { - ImGui::Button("do something"); - if(ImPlot::BeginPlot("test plot")) { + auto showCallback = [&]() { + ImGui::Button("do something"); + if (ImPlot::BeginPlot("test plot")) { ImPlot::PlotLine("test line", &xvals.front(), xvals.size()); ImPlot::EndPlot(); } @@ -163,7 +163,7 @@ TEST_F(PolyscopeTest, ImPlotBasic) { polyscope::state::userCallback = showCallback; polyscope::show(3); - + for (int i = 0; i < 3; i++) { polyscope::frameTick(); } @@ -177,9 +177,9 @@ TEST_F(PolyscopeTest, ImPlotScreenshot) { std::vector xvals = {0., 2., 4., 8.}; - auto showCallback = [&]() { - ImGui::Button("do something"); - if(ImPlot::BeginPlot("test plot")) { + auto showCallback = [&]() { + ImGui::Button("do something"); + if (ImPlot::BeginPlot("test plot")) { ImPlot::PlotLine("test line", &xvals.front(), xvals.size()); ImPlot::EndPlot(); } @@ -187,14 +187,14 @@ TEST_F(PolyscopeTest, ImPlotScreenshot) { polyscope::state::userCallback = showCallback; polyscope::show(3); - + polyscope::ScreenshotOptions opts; opts.includeUI = true; opts.transparentBackground = false; polyscope::screenshot(opts); - + polyscope::show(3); - + polyscope::state::userCallback = nullptr; } diff --git a/test/src/misc_test.cpp b/test/src/misc_test.cpp index af1b3ec6..c7b00c1c 100644 --- a/test/src/misc_test.cpp +++ b/test/src/misc_test.cpp @@ -129,14 +129,12 @@ TEST_F(PolyscopeTest, TransformationGizmoStandaloneTest) { } TEST_F(PolyscopeTest, TransformationGizmoNestedShowTest) { - + polyscope::TransformationGizmo* gizmo1 = polyscope::addTransformationGizmo(); gizmo1->setEnabled(true); polyscope::show(3); - auto showCallback = [&]() { - polyscope::show(3); - }; + auto showCallback = [&]() { polyscope::show(3); }; polyscope::state::userCallback = showCallback; polyscope::show(3); diff --git a/test/src/point_cloud_test.cpp b/test/src/point_cloud_test.cpp index 574a9cf6..8e06aa32 100644 --- a/test/src/point_cloud_test.cpp +++ b/test/src/point_cloud_test.cpp @@ -70,7 +70,7 @@ TEST_F(PolyscopeTest, PointCloudSphereOrthographicRendering) { psPoints->setPointRenderMode(polyscope::PointRenderMode::Quad); polyscope::show(3); - + polyscope::view::setProjectionMode(polyscope::ProjectionMode::Perspective); polyscope::removeAllStructures(); @@ -85,7 +85,7 @@ TEST_F(PolyscopeTest, PointCloudPick) { psPoints->setPointRenderMode(polyscope::PointRenderMode::Quad); polyscope::pickAtBufferInds(glm::ivec2(77, 88)); - + // make sure it works in orthographic mode polyscope::view::setProjectionMode(polyscope::ProjectionMode::Orthographic); polyscope::pickAtBufferInds(glm::ivec2(77, 88));