HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
meshTopologyValidation.h
Go to the documentation of this file.
1 //
2 // Copyright 2020 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 
8 
9 #ifndef PXR_IMAGING_PX_OSD_MESH_TOPOLOGY_VALIDATION_H
10 #define PXR_IMAGING_PX_OSD_MESH_TOPOLOGY_VALIDATION_H
11 
13 
14 #include <array>
15 #include <memory>
16 
18 
19 class PxOsdMeshTopology;
20 
21 /// Utility to help validate an OpenSubdiv Mesh topology.
22 ///
23 /// This class is created by PxOsdMeshTopology's Validate method.
24 ///
25 /// Internally, this will avoid dynamic allocations as long as
26 /// the topology is valid (currently using std::unique_ptr but
27 /// targeting std::optional for C++17).
28 ///
29 /// This class does a set of basic validation tests on
30 /// the topology of a mesh. This set of tests isn't necessarily
31 /// complete. There are other cases like invalid primvar size
32 /// that this will not check for.
33 ///
34 /// Topology is considered valid if it passes a series of checks
35 /// enumerated by the Code class enum.
36 ///
37 /// \warn This doesn't currently validate that the topology of crease
38 /// indices match valid edges.
39 ///
40 /// \note This class is convertable to bool and converts to true if the
41 /// the topology is valid and false if any invalidations were found.
42 /// That is to say, a conversion to true implies an empty invalidation
43 /// vector and false implies a non-empty invalidation vector.
45 public:
46  friend class PxOsdMeshTopology;
47  /// Codes for various invalid states for PxOsdMeshTopology
48  enum class Code {
49  /// Encodes invalid scheme token value
51  /// Encodes invalid orientation token value
53  /// Encodes invalid triangle subdivision token value
55  /// Encodes invalid vertex interpolation rule token value
57  /// Encodes invalid face varying interpolation rule token value
59  /// Encodes invalid crease method token value
61  /// Encodes crease lengths element less than 2
63  /// Encodes crease indices size not matching the sum of the lengths
64  /// array
66  /// Encodes crease indices element is not in the face vertex indices
67  /// vector
69  /// Encodes if crease weights is the size of the number of creases or
70  /// the number of crease edges
72  /// Encodes if crease weights are negative
74  /// Encodes corner indices element is not in the face vertex indices
75  /// vector
77  /// Encodes if corner weights are negative
79  /// Encodes if corner weights is not the size of the number of corner
80  /// indices
82  /// Encodes if the hole indices are negative or greater than the maximum
83  /// face index (face count - 1)
85  /// Encodes if a vertex count is less than 3
87  /// Encodes if the element is negative
89  /// Encodes if the indices size does not match the sum of the face
90  /// vertex counts array
92  };
93  /// A tuple containing a code describing an invalidation and a descriptive
94  /// message
95  struct Invalidation {
97  std::string message;
98  };
99 private:
100  // TODO: In C++17, this class is uncessary and should be replaced with
101  // std::optional<std::vector<Invalidation>>
102  class _OptionalInvalidationVector {
103  std::unique_ptr<std::vector<Invalidation>> _value;
104 
105  public:
106  _OptionalInvalidationVector() = default;
107  _OptionalInvalidationVector(_OptionalInvalidationVector&&) = default;
108  _OptionalInvalidationVector& operator=(_OptionalInvalidationVector&&) =
109  default;
110  _OptionalInvalidationVector(_OptionalInvalidationVector const& other)
111  : _value(nullptr) {
112  if (other._value) {
113  _value.reset(new std::vector<Invalidation>(*other._value));
114  }
115  }
116  _OptionalInvalidationVector& operator=(
117  _OptionalInvalidationVector const& other) {
118  _value = nullptr;
119  if (other._value) {
120  _value.reset(new std::vector<Invalidation>(*other._value));
121  }
122  return *this;
123  }
124  void emplace() { _value.reset(new std::vector<Invalidation>); }
125  explicit operator bool() const { return _value != nullptr; }
126  std::vector<Invalidation>& value() {
127  TF_DEV_AXIOM(*this);
128  return *_value;
129  }
130  std::vector<Invalidation> const& value() const {
131  TF_DEV_AXIOM(*this);
132  return *_value;
133  }
134  };
135 
136  _OptionalInvalidationVector _invalidations;
137  template <size_t S>
138  void _ValidateToken(PxOsdMeshTopologyValidation::Code code,
139  const char* name, const TfToken& token,
140  const std::array<TfToken, S>& validTokens);
141  /// initializes the vector if necessary
142  void _AppendInvalidation(const Invalidation& invalidation) {
143  if (!_invalidations) {
144  _invalidations.emplace();
145  }
146  _invalidations.value().push_back(invalidation);
147  }
149 
150 public:
151  PxOsdMeshTopologyValidation() = default;
154  default;
156  default;
158  PxOsdMeshTopologyValidation const& other) = default;
159 
160  /// Return true if the topology is valid
161  explicit operator bool() const {
162  return !_invalidations || _invalidations.value().empty();
163  }
164 
165  using iterator = std::vector<Invalidation>::const_iterator;
166  using const_iterator = std::vector<Invalidation>::const_iterator;
167 
168  /// Returns an iterator for the beginning of the invalidation vector
169  /// if it has been initialized. Otherwise, returns an empty iterator.
171  return _invalidations ? _invalidations.value().cbegin()
172  : const_iterator();
173  }
174  /// Returns an iterator for the end of the invalidation vector
175  /// if it has been initialized. Otherwise, returns an empty iterator.
176  const_iterator end() const {
177  return _invalidations ? _invalidations.value().cend()
178  : const_iterator();
179  }
180 
181  /// Returns an iterator for the beginning of the invalidation vector
182  /// if it has been initialized. Otherwise, returns an empty iterator.
184  return _invalidations ? _invalidations.value().cbegin()
185  : const_iterator();
186  }
187  /// Returns an iterator for the end of the invalidation vector
188  /// if it has been initialized. Otherwise, returns an empty iterator.
190  return _invalidations ? _invalidations.value().cend()
191  : const_iterator();
192  }
193 private:
194  void _ValidateScheme(PxOsdMeshTopology const&);
195  void _ValidateOrientation(PxOsdMeshTopology const&);
196  void _ValidateTriangleSubdivision(PxOsdMeshTopology const&);
197  void _ValidateVertexInterpolation(PxOsdMeshTopology const&);
198  void _ValidateFaceVaryingInterpolation(PxOsdMeshTopology const&);
199  void _ValidateCreaseMethod(PxOsdMeshTopology const&);
200  void _ValidateCreasesAndCorners(PxOsdMeshTopology const&);
201  void _ValidateHoles(PxOsdMeshTopology const&);
202  void _ValidateFaceVertexCounts(PxOsdMeshTopology const&);
203  void _ValidateFaceVertexIndices(PxOsdMeshTopology const&);
204 };
205 
207 
208 #endif
Encodes invalid triangle subdivision token value.
std::vector< Invalidation >::const_iterator iterator
PxOsdMeshTopologyValidation & operator=(PxOsdMeshTopologyValidation &&)=default
GLsizei const GLfloat * value
Definition: glcorearb.h:824
const_iterator cbegin() const
Encodes invalid face varying interpolation rule token value.
OutGridT const XformOp bool bool
Encodes invalid crease method token value.
#define TF_DEV_AXIOM(cond)
Definition: token.h:70
Encodes if crease weights are negative.
Encodes invalid vertex interpolation rule token value.
Code
Codes for various invalid states for PxOsdMeshTopology.
std::vector< Invalidation >::const_iterator const_iterator
GLuint const GLchar * name
Definition: glcorearb.h:786
Encodes invalid scheme token value.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
Encodes invalid orientation token value.
Encodes if corner weights are negative.
Encodes crease lengths element less than 2.