All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
refinement.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 VTR_REFINEMENT_H
25 #define VTR_REFINEMENT_H
26 
27 #include "../version.h"
28 
29 #include "../sdc/type.h"
30 #include "../sdc/options.h"
31 #include "../vtr/types.h"
32 #include "../vtr/level.h"
33 
34 #include <vector>
35 
36 //
37 // Declaration for the main refinement class (Refinement) and its pre-requisites:
38 //
39 namespace OpenSubdiv {
40 namespace OPENSUBDIV_VERSION {
41 
42 namespace Far {
43  class TopologyRefiner;
44  class PatchTablesFactory;
45 }
46 
47 namespace Vtr {
48 
49 class SparseSelector;
50 class FVarRefinement;
51 
52 //
53 // Refinement:
54 // A refinement is a mapping between two levels -- relating the components in the original
55 // (parent) level to the one refined (child). The refinement may be complete (uniform) or sparse
56 // (adaptive or otherwise selective), so not all components in the parent level will spawn
57 // components in the child level.
58 //
59 // At a high level, all that is necessary in terms of interface is to construct, initialize
60 // (linking the two levels), optionally select components for sparse refinement (via use of the
61 // SparseSelector) and call the refine() method. This is the usage expected in FarTopologyRefiner.
62 //
63 // Since we really want this class to be restricted from public access eventually, all methods
64 // begin with lower case (as is the convention for protected methods) and the list of friends
65 // will be maintained more strictly.
66 //
67 class Refinement {
68 
69 public:
70  Refinement();
71  ~Refinement();
72 
73  void setScheme(Sdc::Type const& schemeType, Sdc::Options const& schemeOptions);
75 
76  Level const& parent() const { return *_parent; }
77 
78  Level const& child() const { return *_child; }
79  Level& child() { return *_child; }
80 
81  //
82  // Options associated with the actual refinement operation, which are going to get
83  // quite involved to ensure that the refinement of data that is not of interest can
84  // be suppressed. For now we have:
85  //
86  // "sparse": the alternative to uniform refinement, which requires that
87  // components be previously selected/marked to be included.
88  //
89  // "face topology only": this is one that may get broken down into a finer
90  // set of options. It suppresses "full topology" in the child level
91  // and only generates what is necessary to define the list of faces.
92  // This is only one of the six possible topological relations that
93  // can be generated -- we may eventually want a flag for each.
94  //
95  // "compute masks": this is intended to be temporary, along with the data
96  // members associated with it -- it will trigger the computation and
97  // storage of mask weights for all child vertices. This is naively
98  // stored at this point and exists only for reference.
99  //
100  // Its still up for debate as to how finely these should be controlled, e.g.
101  // for sparse refinement, we likely want full topology at the finest level to
102  // allow for subsequent patch construction...
103  //
104  struct Options {
105  Options() : _sparse(0),
107  { }
108 
109  unsigned int _sparse : 1;
110  unsigned int _faceTopologyOnly : 1;
111 
112  // Currently under consideration:
113  //unsigned int _childToParentMap : 1;
114  //unsigned int _computeMasks : 1;
115  };
116 
117  void refine(Options options = Options());
118 
119 public:
120  //
121  // Access to members -- some testing classes (involving vertex interpolation)
122  // currently make use of these:
123  //
124  int getNumChildVerticesFromFaces() const { return _childVertFromFaceCount; }
125  int getNumChildVerticesFromEdges() const { return _childVertFromEdgeCount; }
126  int getNumChildVerticesFromVertices() const { return _childVertFromVertCount; }
127 
128  Index getFaceChildVertex(Index f) const { return _faceChildVertIndex[f]; }
129  Index getEdgeChildVertex(Index e) const { return _edgeChildVertIndex[e]; }
130  Index getVertexChildVertex(Index v) const { return _vertChildVertIndex[v]; }
131 
132  IndexArray const getFaceChildFaces(Index parentFace) const;
133  IndexArray const getFaceChildEdges(Index parentFace) const;
134  IndexArray const getEdgeChildEdges(Index parentEdge) const;
135 
136  // Child-to-parent relationships (not yet complete -- unclear how we will define the
137  // "type" of the parent component, e.g. vertex, edge or face):
138  Index getChildFaceParentFace(Index f) const { return _childFaceParentIndex[f]; }
139  int getChildFaceInParentFace(Index f) const { return _childFaceTag[f]._indexInParent; }
140 
141  Index getChildEdgeParentIndex(Index e) const { return _childEdgeParentIndex[e]; }
142 
143  Index getChildVertexParentIndex(Index v) const { return _childVertexParentIndex[v]; }
144 
145 //
146 // Non-public methods:
147 //
148 protected:
149 
150  friend class FVarRefinement;
151  friend class SparseSelector;
152 
153  friend class Far::TopologyRefiner;
155 
156 
157  IndexArray getFaceChildFaces(Index parentFace);
158  IndexArray getFaceChildEdges(Index parentFace);
159  IndexArray getEdgeChildEdges(Index parentEdge);
160 
161 protected:
162  //
163  // Work in progress...
164  //
165  // Tags have now been added per-component in Level, but there is additional need to tag
166  // components within Refinement -- we can't tag the parent level components for any
167  // refinement (in order to keep it const) and tags associated with children that are
168  // specific to the child-to-parent mapping may not be warranted in the child level.
169  //
170  // Parent tags are only required for sparse refinement, and so a single SparseTag is used
171  // for all three component types. The main property to tag is whether a component was
172  // selected. Tagging if a component is "transitional" is also useful. This may only be
173  // necessary for edges but is currently packed into a mask per-edge for faces -- that may
174  // be deferred, in which case "transitional" can be a single bit.
175  //
176  // Child tags are to become part of the new child-to-parent mapping, which is to consist
177  // of the parent component index for each child component, plus a set of tags for the child
178  // indicating more about its relationship to its parent, e.g. is it completely defined,
179  // what the parent component type is, what is the index of the chile within its parent,
180  // etc.
181  //
182  struct SparseTag {
184 
185  unsigned char _selected : 1; // component specifically selected for refinement
186  unsigned char _transitional : 4; // adjacent to a refined component (4-bits for face)
187  };
188 
189  struct ChildTag {
190  ChildTag() { }
191 
192  unsigned char _incomplete : 1; // incomplete neighborhood to represent limit of parent
193  unsigned char _parentType : 2; // type of parent component: vertex, edge or face
194  unsigned char _indexInParent : 2; // index of child wrt parent: 0-3, or iterative if N > 4
195  };
196 
197 //
198 // Remaining methods really should remain private...
199 //
200 private:
201  //
202  // Methods involved in constructing the parent-to-child mapping -- when the
203  // refinement is sparse, additional methods are needed to identify the selection:
204  //
205  void initializeSparseSelectionTags();
206  void markSparseChildComponents();
207 
208  void allocateParentToChildMapping();
209  void populateParentToChildMapping();
210  void printParentToChildMapping() const;
211 
212  //
213  // Methods involved in constructing the child-to-parent mapping:
214  //
215  void createChildComponents();
216  void populateChildToParentTags();
217  void populateChildToParentIndices();
218  void populateChildToParentMapping();
219 
220  //
221  // Methods involved in subdividing/propagating component tags and sharpness:
222  //
223  void propagateComponentTags();
224 
225  void propagateFaceTagsFromParentFaces();
226  void propagateEdgeTagsFromParentFaces();
227  void propagateEdgeTagsFromParentEdges();
228  void propagateVertexTagsFromParentFaces();
229  void propagateVertexTagsFromParentEdges();
230  void propagateVertexTagsFromParentVertices();
231 
232  void subdivideVertexSharpness();
233  void subdivideEdgeSharpness();
234  void reclassifySemisharpVertices();
235 
236  //
237  // Methods involved in subdividing face-varying topology:
238  //
239  void subdivideFVarChannels();
240 
241  //
242  // Methods (and types) involved in subdividing the topology:
243  //
244  // Simple struct defining the types of topological relations to subdivide:
245  struct Relations {
246  unsigned int _faceVertices : 1;
247  unsigned int _faceEdges : 1;
248  unsigned int _edgeVertices : 1;
249  unsigned int _edgeFaces : 1;
250  unsigned int _vertexFaces : 1;
251  unsigned int _vertexEdges : 1;
252 
253  void setAll(bool value) {
254  _faceVertices = value;
255  _faceEdges = value;
256  _edgeVertices = value;
257  _edgeFaces = value;
258  _vertexFaces = value;
259  _vertexEdges = value;
260  }
261  };
262 
263  void subdivideTopology(Relations const& relationsToSubdivide);
264 
265  // Methods for sizing the child topology vectors (note we only need four of the
266  // expected six here as face-edge shares face-vert and edge-vert is trivial):
267  void initializeFaceVertexCountsAndOffsets();
268  void initializeEdgeFaceCountsAndOffsets();
269  void initializeVertexFaceCountsAndOffsets();
270  void initializeVertexEdgeCountsAndOffsets();
271 
272  // Methods for populating sections of child topology relations based on their origin
273  // in the parent -- 12 in all
274  //
275  // These iterate through all components -- currently iterating through the parents
276  // and updating only those children marked valid. We may want to change the iteration
277  // strategy here, particularly for sparse refinement. Plans are to factor these out
278  // to work between a specific parent and child pair and control the iteration through
279  // other means.
280  //
281  void populateFaceVerticesFromParentFaces();
282  void populateFaceEdgesFromParentFaces();
283  void populateEdgeVerticesFromParentFaces();
284  void populateEdgeVerticesFromParentEdges();
285  void populateEdgeFacesFromParentFaces();
286  void populateEdgeFacesFromParentEdges();
287  void populateVertexFacesFromParentFaces();
288  void populateVertexFacesFromParentEdges();
289  void populateVertexFacesFromParentVertices();
290  void populateVertexEdgesFromParentFaces();
291  void populateVertexEdgesFromParentEdges();
292  void populateVertexEdgesFromParentVertices();
293 
294 private:
295  friend class Level; // Access for some debugging information
296 
297  Level* _parent;
298  Level* _child;
299 
300  Sdc::Type _schemeType;
301  Sdc::Options _schemeOptions;
302 
303  bool _quadSplit; // generalize this to Sdc::Split later
304  bool _uniform;
305 
306  //
307  // Inventory of the types of child components:
308  // There are six types of child components: child faces can only originate from
309  // faces, child edges can originate from faces and edges, while child vertices can
310  // originate from all three component types.
311  //
312  // While the Refinement populates the Level containing the children, knowing the
313  // counts for the originating type, and generating them in blocks according to these
314  // types, allows us to process them more specifically.
315  //
316  int _childFaceFromFaceCount; // arguably redundant (all faces originate from faces)
317  int _childEdgeFromFaceCount;
318  int _childEdgeFromEdgeCount;
319  int _childVertFromFaceCount;
320  int _childVertFromEdgeCount;
321  int _childVertFromVertCount;
322 
323  //
324  // Members involved in the parent-to-child mapping:
325  // These are vectors sized according to the number of parent components (and
326  // their topology) that contain references/indices to the child components that
327  // result from them by refinement. When refinement is sparse, parent components
328  // that have not spawned all child components will have their missing children
329  // marked as invalid.
330  //
331  // Vectors for each of the six child component types are sized according to a
332  // topological relation of the originating parent type, i.e. for child faces and
333  // edges originating from parent faces, there will be a 1-to-1 correspondence
334  // between a parents face-verts and its child faces (not true for Loop) and
335  // similarly its child edges. Given this correspondence with the topology vectors,
336  // we use the same counts/offsets of the topology vectors when we can.
337  //
338  IndexVector _faceChildFaceIndices; // *cannot* always use face-vert counts/offsets
339  IndexVector _faceChildEdgeIndices; // can use face-vert counts/offsets
340  IndexVector _faceChildVertIndex;
341 
342  IndexVector _edgeChildEdgeIndices; // trivial/corresponding pair for each
343  IndexVector _edgeChildVertIndex;
344 
345  IndexVector _vertChildVertIndex;
346 
347  //
348  // Members involved in the child-to-parent mapping:
349  // In many cases just having the parent-to-child mapping is adequate to refine
350  // everything we need, but some analysis of the resulting refinement wants to "walk
351  // up the hierarchy" for a component to gather information about its ancestry (e.g.
352  // PTex coordinates). It is also useful when the refinement is sparse -- the more
353  // sparse, the more it makes sense to iterate through the child components and seek
354  // their parents rather than the reverse.
355  //
356  // So the reverse child-to-parent mapping definitely useful, but it is relatively
357  // costly (both space and time) to initialize and propagate though the hierarchy, so
358  // I would prefer to only enable it when needed, i.e. make it optional.
359  //
360  // The mapping itself is simply an integer index for each child component, along with
361  // a corresponding tag for each with information about its parent: is the child
362  // fully defined wrt its parent (when refinement is sparse), what is the index of the
363  // child within its parent, and what is the type of the parent. (The latter can be
364  // inferred from the index of the child and so may be redudant.)
365  //
366  //
367  IndexVector _childFaceParentIndex;
368  IndexVector _childEdgeParentIndex;
369  IndexVector _childVertexParentIndex;
370 
371  std::vector<ChildTag> _childFaceTag;
372  std::vector<ChildTag> _childEdgeTag;
373  std::vector<ChildTag> _childVertexTag;
374 
375  //
376  // Additional tags per parent component are also used when refinement is sparse.
377  //
378  std::vector<SparseTag> _parentFaceTag;
379  std::vector<SparseTag> _parentEdgeTag;
380  std::vector<SparseTag> _parentVertexTag;
381 
382  // References to components in the base level (top-most ancestor) may be useful
383  // to copy non-interpolatible properties to all descendant components.
384 
385  // Refinement data for face-varying channels:
386  std::vector<FVarRefinement*> _fvarChannels;
387 
388 public:
389  // TEMPORARY -- FOR ILLUSTRATIVE PURPOSES ONLY...
390  //
391  // Mask for the child vertices stored relative to parent topology, i.e. weights
392  // for a child face-vertex are stored relative to the parent face -- a weight for
393  // each of the parent face's vertices.
394  //
395  // Currently the full complement of weights is used and expected to be applied, e.g.
396  // for a crease in the interior, there may be no face-vert weights in the stencil
397  // and so no need to apply them, but we require all and so set these to zero for now.
398  // We will need some kind of stencil type associated with each child vertex if we
399  // are to avoid doing so in order to detect the difference.
400  //
401  // Note this is potentially extremely wasteful in terms of memory when the set of
402  // refined components in the child is small relative to the parent. All possible
403  // stencil weights (i.e. for uniform refinement) will be allocated here if the
404  // corresonding counts/offset of the parent are to be used.
405  //
406 //#define _VTR_COMPUTE_MASK_WEIGHTS_ENABLED
407 #ifdef _VTR_COMPUTE_MASK_WEIGHTS_ENABLED
408  void computeMaskWeights();
409 
410  std::vector<float> _faceVertWeights; // matches parent face vert counts and offsets
411  std::vector<float> _edgeVertWeights; // trivially 2 per parent edge
412  std::vector<float> _edgeFaceWeights; // matches parent edge face counts and offsets
413  std::vector<float> _vertVertWeights; // trivially 1 per parent vert
414  std::vector<float> _vertEdgeWeights; // matches parent vert edge counts and offsets
415  std::vector<float> _vertFaceWeights; // matches parent vert face counts and offsets
416 #endif
417 };
418 
419 inline IndexArray const
421 
422  //
423  // Note this will need to vary based on the topological split applied...
424  //
425  return IndexArray(&_faceChildFaceIndices[_parent->getOffsetOfFaceVertices(parentFace)],
426  _parent->getNumFaceVertices(parentFace));
427 }
428 inline IndexArray
430 
431  return IndexArray(&_faceChildFaceIndices[_parent->getOffsetOfFaceVertices(parentFace)],
432  _parent->getNumFaceVertices(parentFace));
433 }
434 
435 inline IndexArray const
437 
438  //
439  // Note this *may* need to vary based on the topological split applied...
440  //
441  return IndexArray(&_faceChildEdgeIndices[_parent->getOffsetOfFaceVertices(parentFace)],
442  _parent->getNumFaceVertices(parentFace));
443 }
444 inline IndexArray
446 
447  return IndexArray(&_faceChildEdgeIndices[_parent->getOffsetOfFaceVertices(parentFace)],
448  _parent->getNumFaceVertices(parentFace));
449 }
450 
451 inline IndexArray const
453 
454  return IndexArray(&_edgeChildEdgeIndices[parentEdge*2], 2);
455 }
456 
457 inline IndexArray
459 
460  return IndexArray(&_edgeChildEdgeIndices[parentEdge*2], 2);
461 }
462 
463 } // end namespace Vtr
464 
465 } // end namespace OPENSUBDIV_VERSION
466 using namespace OPENSUBDIV_VERSION;
467 } // end namespace OpenSubdiv
468 
469 #endif /* VTR_REFINEMENT_H */
470 
void setScheme(Sdc::Type const &schemeType, Sdc::Options const &schemeOptions)
int getNumFaceVertices(Index faceIndex) const
Definition: level.h:292
int getOffsetOfFaceVertices(Index faceIndex) const
Definition: level.h:293
void refine(Options options=Options())
std::vector< Index > IndexVector
Definition: types.h:70
IndexArray const getFaceChildEdges(Index parentFace) const
Definition: refinement.h:436
IndexArray const getFaceChildFaces(Index parentFace) const
Definition: refinement.h:420
IndexArray const getEdgeChildEdges(Index parentEdge) const
Definition: refinement.h:452
void initialize(Level &parent, Level &child)
Stores topology data for a specified set of refinement options.
A specialized factory for feature adaptive PatchTables.