OpenSubdiv
Loading...
Searching...
No Matches
refinement.h
Go to the documentation of this file.
1//
2// Copyright 2014 DreamWorks Animation LLC.
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://opensubdiv.org/license.
6//
7#ifndef OPENSUBDIV3_VTR_REFINEMENT_H
8#define OPENSUBDIV3_VTR_REFINEMENT_H
9
10#include "../version.h"
11
12#include "../sdc/types.h"
13#include "../sdc/options.h"
14#include "../vtr/types.h"
15#include "../vtr/level.h"
16
17#include <vector>
18
19//
20// Declaration for the main refinement class (Refinement) and its pre-requisites:
21//
22namespace OpenSubdiv {
23namespace OPENSUBDIV_VERSION {
24
25namespace Vtr {
26namespace internal {
27
28class FVarRefinement;
29
30//
31// Refinement:
32// A refinement is a mapping between two levels -- relating the components in the original
33// (parent) level to the one refined (child). The refinement may be complete (uniform) or sparse
34// (adaptive or otherwise selective), so not all components in the parent level will spawn
35// components in the child level.
36//
37// Refinement is an abstract class and expects subclasses corresponding to the different types
38// of topological splits that the supported subdivision schemes collectively require, i.e. those
39// listed in Sdc::SplitType. Note the virtual requirements expected of the subclasses in the list
40// of protected methods -- they differ mainly in the topology that is created in the child Level
41// and not the propagation of tags through refinement, subdivision of sharpness values or the
42// treatment of face-varying data. The primary subclasses are QuadRefinement and TriRefinement.
43//
44// At a high level, all that is necessary in terms of interface is to construct, initialize
45// (linking the two levels), optionally select components for sparse refinement (via use of the
46// SparseSelector) and call the refine() method. This usage is expected of Far::TopologyRefiner.
47//
48// Since we really want this class to be restricted from public access eventually, all methods
49// begin with lower case (as is the convention for protected methods) and the list of friends
50// will be maintained more strictly.
51//
52class Refinement {
53
54public:
55 Refinement(Level const & parent, Level & child, Sdc::Options const& schemeOptions);
56 virtual ~Refinement();
57
58 Level const& parent() const { return *_parent; }
59 Level const& child() const { return *_child; }
60 Level& child() { return *_child; }
61
62 Sdc::Split getSplitType() const { return _splitType; }
63 int getRegularFaceSize() const { return _regFaceSize; }
64 Sdc::Options getOptions() const { return _options; }
65
66 // Face-varying:
67 int getNumFVarChannels() const { return (int) _fvarChannels.size(); }
68
69 FVarRefinement const & getFVarRefinement(int c) const { return *_fvarChannels[c]; }
70
71 //
72 // Options associated with the actual refinement operation, which may end up
73 // quite involved if we want to allow for the refinement of data that is not
74 // of interest to be suppressed. For now we have:
75 //
76 // "sparse": the alternative to uniform refinement, which requires that
77 // components be previously selected/marked to be included.
78 //
79 // "minimal topology": this is one that may get broken down into a finer
80 // set of options. It suppresses "full topology" in the child level
81 // and only generates what is minimally necessary for interpolation --
82 // which requires at least the face-vertices for faces, but also the
83 // vertex-faces for any face-varying channels present. So it will
84 // generate one or two of the six possible topological relations.
85 //
86 // These are strictly controlled right now, e.g. for sparse refinement, we
87 // currently enforce full topology at the finest level to allow for subsequent
88 // patch construction.
89 //
90 struct Options {
91 Options() : _sparse(false),
92 _faceVertsFirst(false),
93 _minimalTopology(false)
94 { }
95
96 unsigned int _sparse : 1;
97 unsigned int _faceVertsFirst : 1;
98 unsigned int _minimalTopology : 1;
99
100 // Still under consideration:
101 //unsigned int _childToParentMap : 1;
102 };
103
104 void refine(Options options = Options());
105
106 bool hasFaceVerticesFirst() const { return _faceVertsFirst; }
107
108public:
109 //
110 // Access to members -- some testing classes (involving vertex interpolation)
111 // currently make use of these:
112 //
113 int getNumChildFacesFromFaces() const { return _childFaceFromFaceCount; }
114 int getNumChildEdgesFromFaces() const { return _childEdgeFromFaceCount; }
115 int getNumChildEdgesFromEdges() const { return _childEdgeFromEdgeCount; }
116 int getNumChildVerticesFromFaces() const { return _childVertFromFaceCount; }
117 int getNumChildVerticesFromEdges() const { return _childVertFromEdgeCount; }
118 int getNumChildVerticesFromVertices() const { return _childVertFromVertCount; }
119
120 Index getFirstChildFaceFromFaces() const { return _firstChildFaceFromFace; }
121 Index getFirstChildEdgeFromFaces() const { return _firstChildEdgeFromFace; }
122 Index getFirstChildEdgeFromEdges() const { return _firstChildEdgeFromEdge; }
123 Index getFirstChildVertexFromFaces() const { return _firstChildVertFromFace; }
124 Index getFirstChildVertexFromEdges() const { return _firstChildVertFromEdge; }
125 Index getFirstChildVertexFromVertices() const { return _firstChildVertFromVert; }
126
127 Index getFaceChildVertex(Index f) const { return _faceChildVertIndex[f]; }
128 Index getEdgeChildVertex(Index e) const { return _edgeChildVertIndex[e]; }
129 Index getVertexChildVertex(Index v) const { return _vertChildVertIndex[v]; }
130
131 ConstIndexArray getFaceChildFaces(Index parentFace) const;
132 ConstIndexArray getFaceChildEdges(Index parentFace) const;
133 ConstIndexArray getEdgeChildEdges(Index parentEdge) const;
134
135 // Child-to-parent relationships
136 bool isChildVertexComplete(Index v) const { return ! _childVertexTag[v]._incomplete; }
137
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// Modifiers intended for internal/protected use:
147//
148public:
149
150 IndexArray getFaceChildFaces(Index parentFace);
151 IndexArray getFaceChildEdges(Index parentFace);
152 IndexArray getEdgeChildEdges(Index parentEdge);
153
154public:
155 //
156 // Tags have now been added per-component in Level, but there is additional need to tag
157 // components within Refinement -- we can't tag the parent level components for any
158 // refinement (in order to keep it const) and tags associated with children that are
159 // specific to the child-to-parent mapping may not be warranted in the child level.
160 //
161 // Parent tags are only required for sparse refinement. The main property to tag is
162 // whether a component was selected, and so a single SparseTag is used for all three
163 // component types. Tagging if a component is "transitional" is also useful. This may
164 // only be necessary for edges but is currently packed into a mask per-edge for faces,
165 // which could be deferred, in which case "transitional" could be a single bit.
166 //
167 // Child tags are part of the child-to-parent mapping, which consists of the parent
168 // component index for each child component, plus a tag for the child indicating more
169 // about its relationship to its parent, e.g. is it completely defined, what the parent
170 // component type is, what is the index of the child within its parent, etc.
171 //
172 struct SparseTag {
173 SparseTag() : _selected(0), _transitional(0) { }
174
175 unsigned char _selected : 1; // component specifically selected for refinement
176 unsigned char _transitional : 4; // adjacent to a refined component (4-bits for face)
177 };
178
179 struct ChildTag {
180 ChildTag() { }
181
182 unsigned char _incomplete : 1; // incomplete neighborhood to represent limit of parent
183 unsigned char _parentType : 2; // type of parent component: vertex, edge or face
184 unsigned char _indexInParent : 2; // index of child wrt parent: 0-3, or iterative if N > 4
185 };
186
187 // Methods to access and modify tags:
188 SparseTag const & getParentFaceSparseTag( Index f) const { return _parentFaceTag[f]; }
189 SparseTag const & getParentEdgeSparseTag( Index e) const { return _parentEdgeTag[e]; }
190 SparseTag const & getParentVertexSparseTag(Index v) const { return _parentVertexTag[v]; }
191
192 SparseTag & getParentFaceSparseTag( Index f) { return _parentFaceTag[f]; }
193 SparseTag & getParentEdgeSparseTag( Index e) { return _parentEdgeTag[e]; }
194 SparseTag & getParentVertexSparseTag(Index v) { return _parentVertexTag[v]; }
195
196 ChildTag const & getChildFaceTag( Index f) const { return _childFaceTag[f]; }
197 ChildTag const & getChildEdgeTag( Index e) const { return _childEdgeTag[e]; }
198 ChildTag const & getChildVertexTag(Index v) const { return _childVertexTag[v]; }
199
200 ChildTag & getChildFaceTag( Index f) { return _childFaceTag[f]; }
201 ChildTag & getChildEdgeTag( Index e) { return _childEdgeTag[e]; }
202 ChildTag & getChildVertexTag(Index v) { return _childVertexTag[v]; }
203
204// Remaining methods should really be protected -- for use by subclasses...
205public:
206 //
207 // Methods involved in constructing the parent-to-child mapping -- when the
208 // refinement is sparse, additional methods are needed to identify the selection:
209 //
210 void populateParentToChildMapping();
211 void populateParentChildIndices();
212 void printParentToChildMapping() const;
213
214 virtual void allocateParentChildIndices() = 0;
215
216 // Supporting method for sparse refinement:
217 void initializeSparseSelectionTags();
218 void markSparseChildComponentIndices();
219 void markSparseVertexChildren();
220 void markSparseEdgeChildren();
221
222 virtual void markSparseFaceChildren() = 0;
223
224 void initializeChildComponentCounts();
225
226 //
227 // Methods involved in constructing the child-to-parent mapping:
228 //
229 void populateChildToParentMapping();
230
231 void populateFaceParentVectors(ChildTag const initialChildTags[2][4]);
232 void populateFaceParentFromParentFaces(ChildTag const initialChildTags[2][4]);
233
234 void populateEdgeParentVectors(ChildTag const initialChildTags[2][4]);
235 void populateEdgeParentFromParentFaces(ChildTag const initialChildTags[2][4]);
236 void populateEdgeParentFromParentEdges(ChildTag const initialChildTags[2][4]);
237
238 void populateVertexParentVectors(ChildTag const initialChildTags[2][4]);
239 void populateVertexParentFromParentFaces(ChildTag const initialChildTags[2][4]);
240 void populateVertexParentFromParentEdges(ChildTag const initialChildTags[2][4]);
241 void populateVertexParentFromParentVertices(ChildTag const initialChildTags[2][4]);
242
243 //
244 // Methods involved in propagating component tags from parent to child:
245 //
246 void propagateComponentTags();
247
248 void populateFaceTagVectors();
249 void populateFaceTagsFromParentFaces();
250
251 void populateEdgeTagVectors();
252 void populateEdgeTagsFromParentFaces();
253 void populateEdgeTagsFromParentEdges();
254
255 void populateVertexTagVectors();
256 void populateVertexTagsFromParentFaces();
257 void populateVertexTagsFromParentEdges();
258 void populateVertexTagsFromParentVertices();
259
260 //
261 // Methods (and types) involved in subdividing the topology -- though not
262 // fully exploited, any subset of the 6 relations can be generated:
263 //
264 struct Relations {
265 unsigned int _faceVertices : 1;
266 unsigned int _faceEdges : 1;
267 unsigned int _edgeVertices : 1;
268 unsigned int _edgeFaces : 1;
269 unsigned int _vertexFaces : 1;
270 unsigned int _vertexEdges : 1;
271
272 void setAll(bool enable) {
273 _faceVertices = enable;
274 _faceEdges = enable;
275 _edgeVertices = enable;
276 _edgeFaces = enable;
277 _vertexFaces = enable;
278 _vertexEdges = enable;
279 }
280 };
281
282 void subdivideTopology(Relations const& relationsToSubdivide);
283
284 virtual void populateFaceVertexRelation() = 0;
285 virtual void populateFaceEdgeRelation() = 0;
286 virtual void populateEdgeVertexRelation() = 0;
287 virtual void populateEdgeFaceRelation() = 0;
288 virtual void populateVertexFaceRelation() = 0;
289 virtual void populateVertexEdgeRelation() = 0;
290
291 //
292 // Methods involved in subdividing and inspecting sharpness values:
293 //
294 void subdivideSharpnessValues();
295
296 void subdivideVertexSharpness();
297 void subdivideEdgeSharpness();
298 void reclassifySemisharpVertices();
299
300 //
301 // Methods involved in subdividing face-varying topology:
302 //
303 void subdivideFVarChannels();
304
305protected:
306 // A debug method of Level prints a Refinement (should really change this)
307 friend void Level::print(const Refinement *) const;
308
309 //
310 // Data members -- the logical grouping of some of these (and methods that make use
311 // of them) may lead to grouping them into a few utility classes or structs...
312 //
313
314 // Defined on construction:
315 Level const * _parent;
316 Level * _child;
317 Sdc::Options _options;
318
319 // Defined by the subclass:
320 Sdc::Split _splitType;
321 int _regFaceSize;
322
323 // Determined by the refinement options:
324 bool _uniform;
325 bool _faceVertsFirst;
326
327 //
328 // Inventory and ordering of the types of child components:
329 //
330 int _childFaceFromFaceCount; // arguably redundant (all faces originate from faces)
331 int _childEdgeFromFaceCount;
332 int _childEdgeFromEdgeCount;
333 int _childVertFromFaceCount;
334 int _childVertFromEdgeCount;
335 int _childVertFromVertCount;
336
337 int _firstChildFaceFromFace; // arguably redundant (all faces originate from faces)
338 int _firstChildEdgeFromFace;
339 int _firstChildEdgeFromEdge;
340 int _firstChildVertFromFace;
341 int _firstChildVertFromEdge;
342 int _firstChildVertFromVert;
343
344 //
345 // The parent-to-child mapping:
346 // These are vectors sized according to the number of parent components (and
347 // their topology) that contain references/indices to the child components that
348 // result from them by refinement. When refinement is sparse, parent components
349 // that have not spawned all child components will have their missing children
350 // marked as invalid.
351 //
352 // NOTE the "Array" members here. Often vectors within the Level can be shared
353 // with the Refinement, and an Array instance is used to do so. If not shared
354 // the subclass just initializes the Array members after allocating its own local
355 // vector members.
356 //
357 IndexArray _faceChildFaceCountsAndOffsets;
358 IndexArray _faceChildEdgeCountsAndOffsets;
359
360 IndexVector _faceChildFaceIndices; // *cannot* always use face-vert counts/offsets
361 IndexVector _faceChildEdgeIndices; // can use face-vert counts/offsets
362 IndexVector _faceChildVertIndex;
363
364 IndexVector _edgeChildEdgeIndices; // trivial/corresponding pair for each
365 IndexVector _edgeChildVertIndex;
366
367 IndexVector _vertChildVertIndex;
368
369 //
370 // The child-to-parent mapping:
371 //
372 IndexVector _childFaceParentIndex;
373 IndexVector _childEdgeParentIndex;
374 IndexVector _childVertexParentIndex;
375
376 std::vector<ChildTag> _childFaceTag;
377 std::vector<ChildTag> _childEdgeTag;
378 std::vector<ChildTag> _childVertexTag;
379
380 //
381 // Tags for sparse selection of components:
382 //
383 std::vector<SparseTag> _parentFaceTag;
384 std::vector<SparseTag> _parentEdgeTag;
385 std::vector<SparseTag> _parentVertexTag;
386
387 //
388 // Refinement data for face-varying channels present in the Levels being refined:
389 //
390 std::vector<FVarRefinement*> _fvarChannels;
391};
392
393inline ConstIndexArray
394Refinement::getFaceChildFaces(Index parentFace) const {
395
396 return ConstIndexArray(&_faceChildFaceIndices[_faceChildFaceCountsAndOffsets[2*parentFace+1]],
397 _faceChildFaceCountsAndOffsets[2*parentFace]);
398}
399
400inline IndexArray
401Refinement::getFaceChildFaces(Index parentFace) {
402
403 return IndexArray(&_faceChildFaceIndices[_faceChildFaceCountsAndOffsets[2*parentFace+1]],
404 _faceChildFaceCountsAndOffsets[2*parentFace]);
405}
406
407inline ConstIndexArray
408Refinement::getFaceChildEdges(Index parentFace) const {
409
410 return ConstIndexArray(&_faceChildEdgeIndices[_faceChildEdgeCountsAndOffsets[2*parentFace+1]],
411 _faceChildEdgeCountsAndOffsets[2*parentFace]);
412}
413inline IndexArray
414Refinement::getFaceChildEdges(Index parentFace) {
415
416 return IndexArray(&_faceChildEdgeIndices[_faceChildEdgeCountsAndOffsets[2*parentFace+1]],
417 _faceChildEdgeCountsAndOffsets[2*parentFace]);
418}
419
420inline ConstIndexArray
421Refinement::getEdgeChildEdges(Index parentEdge) const {
422
423 return ConstIndexArray(&_edgeChildEdgeIndices[parentEdge*2], 2);
424}
425
426inline IndexArray
427Refinement::getEdgeChildEdges(Index parentEdge) {
428
429 return IndexArray(&_edgeChildEdgeIndices[parentEdge*2], 2);
430}
431
432} // end namespace internal
433} // end namespace Vtr
434
435} // end namespace OPENSUBDIV_VERSION
436using namespace OPENSUBDIV_VERSION;
437} // end namespace OpenSubdiv
438
439#endif /* OPENSUBDIV3_VTR_REFINEMENT_H */
std::vector< Index > IndexVector
Definition types.h:60
ConstArray< Index > ConstIndexArray
Definition types.h:63
Split
Enumerated type for all face splitting schemes.
Definition types.h:30