fvarLevel.h
Go to the documentation of this file.
1 //
2 // Copyright 2014 DreamWorks Animation LLC.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef OPENSUBDIV3_VTR_FVAR_LEVEL_H
25 #define OPENSUBDIV3_VTR_FVAR_LEVEL_H
26 
27 #include "../version.h"
28 
29 #include "../sdc/types.h"
30 #include "../sdc/crease.h"
31 #include "../sdc/options.h"
32 #include "../vtr/types.h"
33 #include "../vtr/level.h"
34 
35 #include <vector>
36 #include <cassert>
37 #include <cstring>
38 
39 
40 namespace OpenSubdiv {
41 namespace OPENSUBDIV_VERSION {
42 
43 namespace Vtr {
44 namespace internal {
45 
46 //
47 // FVarLevel:
48 // A "face-varying channel" includes the topology for a set of face-varying
49 // data, relative to the topology of the Level with which it is associated.
50 //
51 // Analogous to a set of vertices and face-vertices that define the topology for
52 // the geometry, a channel requires a set of "values" and "face-values". The
53 // "values" are indices of entries in a set of face-varying data, just as vertices
54 // are indices into a set of vertex data. The face-values identify a value for
55 // each vertex of the face, and so define topology for the values that may be
56 // unique to each channel.
57 //
58 // In addition to the value size and the vector of face-values (which matches the
59 // size of the geometry's face-vertices), tags are associated with each component
60 // to identify deviations of the face-varying topology from the vertex topology.
61 // And since there may be a one-to-many mapping between vertices and face-varying
62 // values, that mapping is also allocated.
63 //
64 // It turns out that the mapping used is able to completely encode the set of
65 // face-values and is more amenable to refinement. Currently the face-values
66 // take up almost half the memory of this representation, so if memory does
67 // become a concern, we do not need to store them. The only reason we do so now
68 // is that the face-value interface for specifying base topology and inspecting
69 // subsequent levels is very familar to that of face-vertices for clients. So
70 // having them available for such access is convenient.
71 //
72 // Regarding scope and access...
73 // Unclear at this early state, but leaning towards nesting this class within
74 // Level, given the intimate dependency between the two.
75 // Everything is being declared public for now to facilitate access until its
76 // clearer how this functionality will be provided.
77 //
78 class FVarLevel {
79 public:
80  //
81  // Component tags -- trying to minimize the types needed here:
82  //
83  // Tag per Edge:
84  // - facilitates topological analysis around each vertex
85  // - required during refinement to spawn one or more edge-values
86  //
87  struct ETag {
88  ETag() { }
89 
90  void clear() { std::memset(this, 0, sizeof(ETag)); }
91 
92  typedef unsigned char ETagSize;
93 
94  ETagSize _mismatch : 1; // local FVar topology does not match
95  ETagSize _disctsV0 : 1; // discontinuous at vertex 0
96  ETagSize _disctsV1 : 1; // discontinuous at vertex 1
97  ETagSize _linear : 1; // linear boundary constraints
98  };
99 
100  //
101  // Tag per Value:
102  // - informs both refinement and interpolation
103  // - every value spawns a child value in refinement
104  // - given ordering of values (1-per-vertex first) serves as a vertex tag
105  //
106  struct ValueTag {
107  ValueTag() { }
108 
109  void clear() { std::memset(this, 0, sizeof(ValueTag)); }
110 
111  bool isMismatch() const { return _mismatch; }
112  bool isCrease() const { return _crease; }
113  bool isCorner() const { return !_crease; }
114  bool isSemiSharp() const { return _semiSharp; }
115  bool isInfSharp() const { return !_semiSharp && !_crease; }
116  bool isDepSharp() const { return _depSharp; }
117 
118  typedef unsigned char ValueTagSize;
119 
120  ValueTagSize _mismatch : 1; // local FVar topology does not match
121  ValueTagSize _crease : 1; // value is a crease, otherwise a corner
122  ValueTagSize _semiSharp : 1; // value is a corner decaying to crease
123  ValueTagSize _depSharp : 1; // value is a corner by dependency on another
124  ValueTagSize _xordinary : 1; // value is an x-ordinary crease in the limit
125  };
126 
129 
131  ConstIndexArray & faceVerts) const;
132 
134  ConstIndexArray & faceVerts,
135  Level::VTag * fvarVTags) const;
136 
138  Level::ETag * fvarETags) const;
139 
140  //
141  // Simple struct containing the "end faces" of a crease, i.e. the faces which
142  // contain the FVar values to be used when interpolating the crease. (Prefer
143  // the struct over std::pair for its member names)
144  //
145  struct CreaseEndPair {
148  };
149 
152 
154 
157 
158 public:
159  FVarLevel(Level const& level);
160  ~FVarLevel();
161 
162  // Queries for the entire channel:
163  Level const& getLevel() const { return _level; }
164 
165  int getNumValues() const { return _valueCount; }
166  int getNumFaceValuesTotal() const { return (int) _faceVertValues.size(); }
167 
168  bool isLinear() const { return _isLinear; }
169  bool hasLinearBoundaries() const { return _hasLinearBoundaries; }
170  bool hasSmoothBoundaries() const { return not _hasLinearBoundaries; }
171 
172  Sdc::Options getOptions() const { return _options; }
173 
174  // Queries per face:
175  ConstIndexArray getFaceValues(Index fIndex) const;
177 
178  // Queries per edge:
179  ETag getEdgeTag(Index eIndex) const { return _edgeTags[eIndex]; }
180  bool edgeTopologyMatches(Index eIndex) const { return !getEdgeTag(eIndex)._mismatch; }
181 
182  // Queries per vertex (and its potential sibling values):
183  int getNumVertexValues(Index v) const { return _vertSiblingCounts[v]; }
184  Index getVertexValueOffset(Index v, Sibling i = 0) const { return _vertSiblingOffsets[v] + i; }
185 
186  Index getVertexValue(Index v, Sibling i = 0) const { return _vertValueIndices[getVertexValueOffset(v,i)]; }
187 
188  Index findVertexValueIndex(Index vertexIndex, Index valueIndex) const;
189 
190  // Methods to access/modify array properties per vertex:
191  ConstIndexArray getVertexValues(Index vIndex) const;
193 
194  ConstValueTagArray getVertexValueTags(Index vIndex) const;
195  ValueTagArray getVertexValueTags(Index vIndex);
196 
197  ConstCreaseEndPairArray getVertexValueCreaseEnds(Index vIndex) const;
198  CreaseEndPairArray getVertexValueCreaseEnds(Index vIndex);
199 
200  ConstSiblingArray getVertexFaceSiblings(Index vIndex) const;
201  SiblingArray getVertexFaceSiblings(Index vIndex);
202 
203  // Queries per value:
204  ValueTag getValueTag(Index valueIndex) const { return _vertValueTags[valueIndex]; }
205  bool valueTopologyMatches(Index valueIndex) const { return !getValueTag(valueIndex)._mismatch; }
206 
207  // Higher-level topological queries, i.e. values in a neighborhood:
208  void getEdgeFaceValues(Index eIndex, int fIncToEdge, Index valuesPerVert[2]) const;
209  void getVertexEdgeValues(Index vIndex, Index valuesPerEdge[]) const;
210  void getVertexCreaseEndValues(Index vIndex, Sibling sibling, Index endValues[2]) const;
211 
212  // Initialization and allocation helpers:
213  void setOptions(Sdc::Options const& options);
214  void resizeVertexValues(int numVertexValues);
215  void resizeValues(int numValues);
216  void resizeComponents();
217 
218  // Topological analysis methods -- tagging and face-value population:
219  void completeTopologyFromFaceValues(int regBoundaryValence);
222 
223  // Information about the "span" for a value:
224  struct ValueSpan {
229  };
230  void gatherValueSpans(Index vIndex, ValueSpan * vValueSpans) const;
231 
232  // Debugging methods:
233  bool validate() const;
234  void print() const;
235  void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector<Sibling>& fvSiblings) const;
236 
237 private:
238  // Just as Refinements build Levels, FVarRefinements build FVarLevels...
239  friend class FVarRefinement;
240 
241  Level const & _level;
242 
243  // Linear interpolation options vary between channels:
244  Sdc::Options _options;
245 
246  bool _isLinear;
247  bool _hasLinearBoundaries;
248  bool _hasDependentSharpness;
249  int _valueCount;
250 
251  //
252  // Vectors recording face-varying topology including tags that help propagate
253  // data through the refinement hierarchy. Vectors are not sparse but most use
254  // 8-bit values relative to the local topology.
255  //
256  // The vector of face-values is actually redundant here, but is constructed as
257  // it is most convenient for clients. It represents almost half the memory of
258  // the topology (4 32-bit integers per face) and not surprisingly, populating
259  // it takes a considerable amount of the refinement time (1/3). We can reduce
260  // both if we are willing to compute these on demand for clients.
261  //
262  // Per-face (matches face-verts of corresponding level):
263  std::vector<Index> _faceVertValues;
264 
265  // Per-edge:
266  std::vector<ETag> _edgeTags;
267 
268  // Per-vertex:
269  std::vector<Sibling> _vertSiblingCounts;
270  std::vector<int> _vertSiblingOffsets;
271  std::vector<Sibling> _vertFaceSiblings;
272 
273  // Per-value:
274  std::vector<Index> _vertValueIndices;
275  std::vector<ValueTag> _vertValueTags;
276  std::vector<CreaseEndPair> _vertValueCreaseEnds;
277 };
278 
279 //
280 // Access/modify the values associated with each face:
281 //
282 inline ConstIndexArray
284 
285  int vCount = _level.getNumFaceVertices(fIndex);
286  int vOffset = _level.getOffsetOfFaceVertices(fIndex);
287  return ConstIndexArray(&_faceVertValues[vOffset], vCount);
288 }
289 inline IndexArray
291 
292  int vCount = _level.getNumFaceVertices(fIndex);
293  int vOffset = _level.getOffsetOfFaceVertices(fIndex);
294  return IndexArray(&_faceVertValues[vOffset], vCount);
295 }
296 
299 
300  int vCount = _level.getNumVertexFaces(vIndex);
301  int vOffset = _level.getOffsetOfVertexFaces(vIndex);
302  return ConstSiblingArray(&_vertFaceSiblings[vOffset], vCount);
303 }
306 
307  int vCount = _level.getNumVertexFaces(vIndex);
308  int vOffset = _level.getOffsetOfVertexFaces(vIndex);
309  return SiblingArray(&_vertFaceSiblings[vOffset], vCount);
310 }
311 
312 inline ConstIndexArray
314 {
315  int vCount = getNumVertexValues(vIndex);
316  int vOffset = getVertexValueOffset(vIndex);
317  return ConstIndexArray(&_vertValueIndices[vOffset], vCount);
318 }
319 inline IndexArray
321 {
322  int vCount = getNumVertexValues(vIndex);
323  int vOffset = getVertexValueOffset(vIndex);
324  return IndexArray(&_vertValueIndices[vOffset], vCount);
325 }
326 
329 {
330  int vCount = getNumVertexValues(vIndex);
331  int vOffset = getVertexValueOffset(vIndex);
332  return ConstValueTagArray(&_vertValueTags[vOffset], vCount);
333 }
336 {
337  int vCount = getNumVertexValues(vIndex);
338  int vOffset = getVertexValueOffset(vIndex);
339  return ValueTagArray(&_vertValueTags[vOffset], vCount);
340 }
341 
344 {
345  int vCount = getNumVertexValues(vIndex);
346  int vOffset = getVertexValueOffset(vIndex);
347  return ConstCreaseEndPairArray(&_vertValueCreaseEnds[vOffset], vCount);
348 }
351 {
352  int vCount = getNumVertexValues(vIndex);
353  int vOffset = getVertexValueOffset(vIndex);
354  return CreaseEndPairArray(&_vertValueCreaseEnds[vOffset], vCount);
355 }
356 
357 inline Index
358 FVarLevel::findVertexValueIndex(Index vertexIndex, Index valueIndex) const {
359 
360  if (_level.getDepth() > 0) return valueIndex;
361 
362  Index vvIndex = getVertexValueOffset(vertexIndex);
363  while (_vertValueIndices[vvIndex] != valueIndex) {
364  ++ vvIndex;
365  }
366  return vvIndex;
367 }
368 
369 } // end namespace internal
370 } // end namespace Vtr
371 
372 } // end namespace OPENSUBDIV_VERSION
373 using namespace OPENSUBDIV_VERSION;
374 } // end namespace OpenSubdiv
375 
376 #endif /* OPENSUBDIV3_VTR_FVAR_LEVEL_H */
Index findVertexValueIndex(Index vertexIndex, Index valueIndex) const
Definition: fvarLevel.h:358
Index getVertexValueOffset(Index v, Sibling i=0) const
Definition: fvarLevel.h:184
bool valueTopologyMatches(Index valueIndex) const
Definition: fvarLevel.h:205
ConstIndexArray getFaceValues(Index fIndex) const
Definition: fvarLevel.h:283
Index getVertexValue(Index v, Sibling i=0) const
Definition: fvarLevel.h:186
void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector< Sibling > &fvSiblings) const
void gatherValueSpans(Index vIndex, ValueSpan *vValueSpans) const
void getVertexCreaseEndValues(Index vIndex, Sibling sibling, Index endValues[2]) const
ConstCreaseEndPairArray getVertexValueCreaseEnds(Index vIndex) const
Definition: fvarLevel.h:343
ValueTag getValueTag(Index valueIndex) const
Definition: fvarLevel.h:204
int getNumFaceVertices(Index faceIndex) const
Definition: level.h:338
ConstIndexArray getVertexValues(Index vIndex) const
Definition: fvarLevel.h:313
void getVertexEdgeValues(Index vIndex, Index valuesPerEdge[]) const
All supported options applying to subdivision scheme.
Definition: options.h:51
int getNumVertexFaces(Index vertIndex) const
Definition: level.h:350
void completeTopologyFromFaceValues(int regBoundaryValence)
int getOffsetOfVertexFaces(Index vertIndex) const
Definition: level.h:351
Level::ETag getFaceCompositeCombinedEdgeTag(ConstIndexArray &faceEdges, Level::ETag *fvarETags) const
ConstArray< Index > ConstIndexArray
Definition: types.h:80
int getOffsetOfFaceVertices(Index faceIndex) const
Definition: level.h:339
void getEdgeFaceValues(Index eIndex, int fIncToEdge, Index valuesPerVert[2]) const
ValueTag getFaceCompositeValueTag(ConstIndexArray &faceValues, ConstIndexArray &faceVerts) const
ConstValueTagArray getVertexValueTags(Index vIndex) const
Definition: fvarLevel.h:328
ConstSiblingArray getVertexFaceSiblings(Index vIndex) const
Definition: fvarLevel.h:298
Vtr::ConstArray< CreaseEndPair > ConstCreaseEndPairArray
Definition: fvarLevel.h:150
Level::VTag getFaceCompositeValueAndVTag(ConstIndexArray &faceValues, ConstIndexArray &faceVerts, Level::VTag *fvarVTags) const