14#include <lagrange/Logger.h>
15#include <lagrange/SurfaceMesh.h>
16#include <lagrange/foreach_attribute.h>
17#include <lagrange/internal/attribute_string_utils.h>
20#include <lagrange/utils/warnoff.h>
21#include <polyscope/polyscope.h>
22#include <polyscope/point_cloud.h>
23#include <polyscope/surface_mesh.h>
24#include <polyscope/curve_network.h>
25#include <lagrange/utils/warnon.h>
28namespace lagrange::polyscope {
39 default:
return false;
47 default: return ::polyscope::VectorType::STANDARD;
52template <
typename ValueType>
53auto as_color_matrix(
const lagrange::Attribute<ValueType>& attr) ->
decltype(
auto)
58 .unaryExpr([&](
float x) {
return std::is_floating_point_v<ValueType> ? x : x / 255.f; })
60 .unaryExpr([](
float x) {
62 return std::pow(x, gamma);
66template <
typename PolyscopeStructure>
69 using PolyscopeType = std::decay_t<PolyscopeStructure>;
70 static constexpr bool IsMesh = std::is_same_v<PolyscopeType, ::polyscope::SurfaceMesh>;
71 static constexpr bool IsEdge = std::is_same_v<PolyscopeType, ::polyscope::CurveNetwork>;
73 using QuantityType = std::conditional_t<
75 ::polyscope::SurfaceMeshQuantity,
78 ::polyscope::CurveNetworkQuantity,
79 ::polyscope::PointCloudQuantity>>;
82template <
typename PolyscopeStructure>
83using QuantityType =
typename PolyscopeTrait<PolyscopeStructure>::QuantityType;
86template <
typename PolyscopeStructure,
typename ValueType>
87auto register_attribute(
88 PolyscopeStructure* ps_struct,
89 std::string_view name_,
93 std::string name(name_);
95 using PolyscopeType = std::decay_t<PolyscopeStructure>;
96 constexpr bool IsMesh = std::is_same_v<PolyscopeType, ::polyscope::SurfaceMesh>;
97 constexpr bool IsEdge = std::is_same_v<PolyscopeType, ::polyscope::CurveNetwork>;
99 constexpr auto scalar_data_type = std::is_integral_v<ValueType>
100 ? ::polyscope::DataType::CATEGORICAL
101 : ::polyscope::DataType::STANDARD;
103 switch (attr.get_element_type()) {
105 if (attr.get_usage() == Usage::Scalar) {
107 if constexpr (IsMesh) {
108 return ps_struct->addVertexScalarQuantity(
112 }
else if constexpr (IsEdge) {
113 return ps_struct->addNodeScalarQuantity(name,
vector_view(attr), scalar_data_type);
115 return ps_struct->addScalarQuantity(name,
vector_view(attr), scalar_data_type);
117 }
else if (attr.get_num_channels() == 3 || attr.get_num_channels() == 4) {
118 if (show_as_vector(attr.get_usage())) {
120 ::polyscope::VectorType vt = vector_type(attr.get_usage());
121 auto matrix =
matrix_view(attr).template leftCols<3>();
122 if constexpr (IsMesh) {
123 return ps_struct->addVertexVectorQuantity(name, matrix, vt);
124 }
else if constexpr (IsEdge) {
125 return ps_struct->addNodeVectorQuantity(name, matrix, vt);
127 return ps_struct->addVectorQuantity(name, matrix, vt);
129 }
else if (attr.get_usage() == Usage::Color) {
131 auto matrix = as_color_matrix(attr).template leftCols<3>();
132 if constexpr (IsMesh) {
133 return ps_struct->addVertexColorQuantity(name, matrix);
134 }
else if constexpr (IsEdge) {
135 return ps_struct->addNodeColorQuantity(name, matrix);
137 return ps_struct->addColorQuantity(name, matrix);
140 }
else if (attr.get_num_channels() == 2) {
141 if (show_as_vector(attr.get_usage())) {
142 lagrange::logger().info(
"Registering 2D vector vertex attribute: {}", name);
143 ::polyscope::VectorType vt = vector_type(attr.get_usage());
144 if constexpr (IsMesh) {
145 return ps_struct->addVertexVectorQuantity2D(name,
matrix_view(attr), vt);
146 }
else if constexpr (IsEdge) {
147 return ps_struct->addNodeVectorQuantity2D(name,
matrix_view(attr), vt);
149 return ps_struct->addVectorQuantity2D(name,
matrix_view(attr), vt);
152 }
else if (attr.get_usage() == Usage::UV && attr.get_num_channels() == 2) {
153 if constexpr (IsMesh) {
155 return ps_struct->addVertexParameterizationQuantity(name,
matrix_view(attr));
162 if (attr.get_usage() == Usage::Scalar) {
164 if constexpr (IsMesh) {
165 return ps_struct->addFaceScalarQuantity(name,
vector_view(attr), scalar_data_type);
166 }
else if constexpr (IsEdge) {
167 return ps_struct->addEdgeScalarQuantity(name,
vector_view(attr), scalar_data_type);
169 }
else if (attr.get_num_channels() == 3 || attr.get_num_channels() == 4) {
170 if (show_as_vector(attr.get_usage())) {
172 ::polyscope::VectorType vt = vector_type(attr.get_usage());
173 auto matrix =
matrix_view(attr).template leftCols<3>();
174 if constexpr (IsMesh) {
175 return ps_struct->addFaceVectorQuantity(name, matrix, vt);
176 }
else if constexpr (IsEdge) {
177 return ps_struct->addEdgeVectorQuantity(name, matrix, vt);
179 }
else if (attr.get_usage() == Usage::Color) {
181 auto matrix = as_color_matrix(attr).template leftCols<3>();
182 if constexpr (IsMesh) {
183 return ps_struct->addFaceColorQuantity(name, matrix);
184 }
else if constexpr (IsEdge) {
185 return ps_struct->addEdgeColorQuantity(name, matrix);
188 }
else if (attr.get_num_channels() == 2) {
189 if (show_as_vector(attr.get_usage())) {
191 ::polyscope::VectorType vt = vector_type(attr.get_usage());
192 if constexpr (IsMesh) {
193 return ps_struct->addFaceVectorQuantity2D(name,
matrix_view(attr), vt);
194 }
else if constexpr (IsEdge) {
195 return ps_struct->addEdgeVectorQuantity2D(name,
matrix_view(attr), vt);
201 if constexpr (IsMesh) {
202 if (attr.get_usage() == Usage::Scalar) {
204 return ps_struct->addEdgeScalarQuantity(name,
vector_view(attr), scalar_data_type);
209 if constexpr (IsMesh) {
210 if (attr.get_usage() == Usage::UV && attr.get_num_channels() == 2) {
212 return ps_struct->addParameterizationQuantity(name,
matrix_view(attr));
222template <
typename PolyscopeStructure,
typename Scalar,
typename Index>
223void register_attributes(PolyscopeStructure* ps_struct,
const SurfaceMesh<Scalar, Index>& mesh)
227 if (mesh.attr_name_is_reserved(name)) {
230 using AttributeType = std::decay_t<
decltype(attr)>;
231 if constexpr (AttributeType::IsIndexed) {
234 if (!register_attribute(ps_struct, name, attr)) {
236 "Skipping unsupported attribute: {}, element type: {}, usage: {}, num "
241 attr.get_num_channels());
Derived attribute class that stores the actual information.
Definition Attribute.h:174
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
AttributeUsage
Usage tag indicating how the attribute should behave under mesh transformations.
Definition AttributeFwd.h:54
@ Position
Mesh attribute must have exactly dim channels.
Definition AttributeFwd.h:57
@ Tangent
Mesh attribute can have dim or dim + 1 channels.
Definition AttributeFwd.h:59
@ Vector
Mesh attribute can have any number of channels (including 1 channel).
Definition AttributeFwd.h:55
@ Normal
Mesh attribute can have dim or dim + 1 channels.
Definition AttributeFwd.h:58
@ Bitangent
Mesh attribute can have dim or dim + 1 channels.
Definition AttributeFwd.h:60
@ Edge
Per-edge mesh attributes.
Definition AttributeFwd.h:34
@ Facet
Per-facet mesh attributes.
Definition AttributeFwd.h:31
@ Corner
Per-corner mesh attributes.
Definition AttributeFwd.h:37
@ Vertex
Per-vertex mesh attributes.
Definition AttributeFwd.h:28
void seq_foreach_named_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition foreach_attribute.h:208
SurfaceMesh< ToScalar, ToIndex > cast(const SurfaceMesh< FromScalar, FromIndex > &source_mesh, const AttributeFilter &convertible_attributes={}, std::vector< std::string > *converted_attributes_names=nullptr)
Cast a mesh to a mesh of different scalar and/or index type.
ConstRowMatrixView< ValueType > matrix_view(const Attribute< ValueType > &attribute)
Returns a read-only view of a given attribute in the form of an Eigen matrix.
Definition views.cpp:35
ConstVectorView< ValueType > vector_view(const Attribute< ValueType > &attribute)
Returns a read-only view of a scalar attribute in the form of an Eigen vector.
Definition views.cpp:51
LA_CORE_API std::string_view to_string(AttributeElement element)
Returns a string representation of an attribute element type.
Definition attribute_string_utils.cpp:22
Definition register_attributes.h:68