| OpenSubdiv OpenSubdiv

Loading...
Searching...
No Matches
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 familiar 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 it's
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 Level::ETag combineWithLevelETag(Level::ETag) const;
100 };
101
102 //
103 // Tag per Value:
104 // - informs both refinement and interpolation
105 // - every value spawns a child value in refinement
106 // - includes a subset of Level::VTag to be later combined with a VTag
107 //
108 struct ValueTag {
109 ValueTag() { }
110
111 void clear() { std::memset(this, 0, sizeof(ValueTag)); }
112
113 bool isMismatch() const { return _mismatch; }
114 bool isCrease() const { return _crease; }
115 bool isCorner() const { return !_crease; }
116 bool isSemiSharp() const { return _semiSharp; }
117 bool isInfSharp() const { return !_semiSharp && !_crease; }
118 bool isDepSharp() const { return _depSharp; }
119 bool hasCreaseEnds() const { return _crease || _semiSharp; }
120
121 bool hasInfSharpEdges() const { return _infSharpEdges; }
122 bool hasInfIrregularity() const { return _infIrregular; }
123
124 typedef unsigned char ValueTagSize;
125
126 // If there is no mismatch, no other members should be inspected
127 ValueTagSize _mismatch : 1; // local FVar topology does not match
128 ValueTagSize _xordinary : 1; // local FVar topology is extra-ordinary
129 ValueTagSize _nonManifold : 1; // local FVar topology is non-manifold
130 ValueTagSize _crease : 1; // value is a crease, otherwise a corner
131 ValueTagSize _semiSharp : 1; // value is a corner decaying to crease
132 ValueTagSize _depSharp : 1; // value is a corner by dependency on another
133
134 ValueTagSize _infSharpEdges : 1; // value is a corner by inf-sharp features
135 ValueTagSize _infIrregular : 1; // value span includes inf-sharp irregularity
136
137 Level::VTag combineWithLevelVTag(Level::VTag) const;
138
139 // Alternate constructor and accessor for dealing with integer bits directly:
140 explicit ValueTag(ValueTagSize bits) {
141 std::memcpy(this, &bits, sizeof(bits));
142 }
143 ValueTagSize getBits() const {
144 ValueTagSize bits;
145 std::memcpy(&bits, this, sizeof(bits));
146 return bits;
147 }
148 };
149
150 typedef Vtr::ConstArray<ValueTag> ConstValueTagArray;
151 typedef Vtr::Array<ValueTag> ValueTagArray;
152
153 //
154 // Simple struct containing the "end faces" of a crease, i.e. the faces which
155 // contain the FVar values to be used when interpolating the crease. (Prefer
156 // the struct over std::pair for its member names)
157 //
158 struct CreaseEndPair {
159 LocalIndex _startFace;
160 LocalIndex _endFace;
161 };
162
163 typedef Vtr::ConstArray<CreaseEndPair> ConstCreaseEndPairArray;
164 typedef Vtr::Array<CreaseEndPair> CreaseEndPairArray;
165
166 typedef LocalIndex Sibling;
167
168 typedef ConstLocalIndexArray ConstSiblingArray;
169 typedef LocalIndexArray SiblingArray;
170
171 public:
172 FVarLevel(Level const& level);
173 ~FVarLevel();
174
175 // Queries for the entire channel:
176 Level const& getLevel() const { return _level; }
177
178 int getNumValues() const { return _valueCount; }
179 int getNumFaceValuesTotal() const { return (int) _faceVertValues.size(); }
180
181 bool isLinear() const { return _isLinear; }
182 bool hasLinearBoundaries() const { return _hasLinearBoundaries; }
183 bool hasSmoothBoundaries() const { return ! _hasLinearBoundaries; }
184 bool hasCreaseEnds() const { return hasSmoothBoundaries(); }
185
186 Sdc::Options getOptions() const { return _options; }
187
188 // Queries per face:
189 ConstIndexArray getFaceValues(Index fIndex) const;
190 IndexArray getFaceValues(Index fIndex);
191
192 // Queries per edge:
193 ETag getEdgeTag(Index eIndex) const { return _edgeTags[eIndex]; }
194 bool edgeTopologyMatches(Index eIndex) const { return !getEdgeTag(eIndex)._mismatch; }
195
196 // Queries per vertex (and its potential sibling values):
197 int getNumVertexValues(Index v) const { return _vertSiblingCounts[v]; }
198 Index getVertexValueOffset(Index v, Sibling i = 0) const { return _vertSiblingOffsets[v] + i; }
199
200 Index getVertexValue(Index v, Sibling i = 0) const { return _vertValueIndices[getVertexValueOffset(v,i)]; }
201
202 Index findVertexValueIndex(Index vertexIndex, Index valueIndex) const;
203
204 // Methods to access/modify array properties per vertex:
205 ConstIndexArray getVertexValues(Index vIndex) const;
206 IndexArray getVertexValues(Index vIndex);
207
208 ConstValueTagArray getVertexValueTags(Index vIndex) const;
209 ValueTagArray getVertexValueTags(Index vIndex);
210
211 ConstCreaseEndPairArray getVertexValueCreaseEnds(Index vIndex) const;
212 CreaseEndPairArray getVertexValueCreaseEnds(Index vIndex);
213
214 ConstSiblingArray getVertexFaceSiblings(Index vIndex) const;
215 SiblingArray getVertexFaceSiblings(Index vIndex);
216
217 // Queries per value:
218 ValueTag getValueTag(Index valueIndex) const { return _vertValueTags[valueIndex]; }
219 bool valueTopologyMatches(Index valueIndex) const { return !getValueTag(valueIndex)._mismatch; }
220
221 CreaseEndPair getValueCreaseEndPair(Index valueIndex) const { return _vertValueCreaseEnds[valueIndex]; }
222
223 // Tag queries related to faces (use Level methods for those returning Level::VTag/ETag)
224 void getFaceValueTags(Index faceIndex, ValueTag valueTags[]) const;
225
226 ValueTag getFaceCompositeValueTag(Index faceIndex) const;
227
228 // Higher-level topological queries, i.e. values in a neighborhood:
229 void getEdgeFaceValues(Index eIndex, int fIncToEdge, Index valuesPerVert[2]) const;
230 void getVertexEdgeValues(Index vIndex, Index valuesPerEdge[]) const;
231 void getVertexCreaseEndValues(Index vIndex, Sibling sibling, Index endValues[2]) const;
232
233 // Initialization and allocation helpers:
234 void setOptions(Sdc::Options const& options);
235 void resizeVertexValues(int numVertexValues);
236 void resizeValues(int numValues);
237 void resizeComponents();
238
239 // Topological analysis methods -- tagging and face-value population:
240 void completeTopologyFromFaceValues(int regBoundaryValence);
241 void initializeFaceValuesFromFaceVertices();
242 void initializeFaceValuesFromVertexFaceSiblings();
243
244 struct ValueSpan;
245 void gatherValueSpans(Index vIndex, ValueSpan * vValueSpans) const;
246
247 // Debugging methods:
248 bool validate() const;
249 void print() const;
250 void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector<Sibling>& fvSiblings) const;
251
252 private:
253 // Just as Refinements build Levels, FVarRefinements build FVarLevels...
254 friend class FVarRefinement;
255
256 Level const & _level;
257
258 // Linear interpolation options vary between channels:
259 Sdc::Options _options;
260
261 bool _isLinear;
262 bool _hasLinearBoundaries;
263 bool _hasDependentSharpness;
264 int _valueCount;
265
266 //
267 // Vectors recording face-varying topology including tags that help propagate
268 // data through the refinement hierarchy. Vectors are not sparse but most use
269 // 8-bit values relative to the local topology.
270 //
271 // The vector of face-values is actually redundant here, but is constructed as
272 // it is most convenient for clients. It represents almost half the memory of
273 // the topology (4 32-bit integers per face) and not surprisingly, populating
274 // it takes a considerable amount of the refinement time (1/3). We can reduce
275 // both if we are willing to compute these on demand for clients.
276 //
277 // Per-face (matches face-verts of corresponding level):
278 std::vector<Index> _faceVertValues;
279
280 // Per-edge:
281 std::vector<ETag> _edgeTags;
282
283 // Per-vertex:
284 std::vector<Sibling> _vertSiblingCounts;
285 std::vector<int> _vertSiblingOffsets;
286 std::vector<Sibling> _vertFaceSiblings;
287
288 // Per-value:
289 std::vector<Index> _vertValueIndices;
290 std::vector<ValueTag> _vertValueTags;
291 std::vector<CreaseEndPair> _vertValueCreaseEnds;
292};
293
294//
295// Access/modify the values associated with each face:
296//
297 inline ConstIndexArray
298FVarLevel::getFaceValues(Index fIndex) const {
299
300 int vCount = _level.getNumFaceVertices(fIndex);
301 int vOffset = _level.getOffsetOfFaceVertices(fIndex);
302 return ConstIndexArray(&_faceVertValues[vOffset], vCount);
303}
304 inline IndexArray
305FVarLevel::getFaceValues(Index fIndex) {
306
307 int vCount = _level.getNumFaceVertices(fIndex);
308 int vOffset = _level.getOffsetOfFaceVertices(fIndex);
309 return IndexArray(&_faceVertValues[vOffset], vCount);
310}
311
312 inline FVarLevel::ConstSiblingArray
313FVarLevel::getVertexFaceSiblings(Index vIndex) const {
314
315 int vCount = _level.getNumVertexFaces(vIndex);
316 int vOffset = _level.getOffsetOfVertexFaces(vIndex);
317 return ConstSiblingArray(&_vertFaceSiblings[vOffset], vCount);
318}
319 inline FVarLevel::SiblingArray
320FVarLevel::getVertexFaceSiblings(Index vIndex) {
321
322 int vCount = _level.getNumVertexFaces(vIndex);
323 int vOffset = _level.getOffsetOfVertexFaces(vIndex);
324 return SiblingArray(&_vertFaceSiblings[vOffset], vCount);
325}
326
327 inline ConstIndexArray
328FVarLevel::getVertexValues(Index vIndex) const
329{
330 int vCount = getNumVertexValues(vIndex);
331 int vOffset = getVertexValueOffset(vIndex);
332 return ConstIndexArray(&_vertValueIndices[vOffset], vCount);
333}
334 inline IndexArray
335FVarLevel::getVertexValues(Index vIndex)
336{
337 int vCount = getNumVertexValues(vIndex);
338 int vOffset = getVertexValueOffset(vIndex);
339 return IndexArray(&_vertValueIndices[vOffset], vCount);
340}
341
342 inline FVarLevel::ConstValueTagArray
343FVarLevel::getVertexValueTags(Index vIndex) const
344{
345 int vCount = getNumVertexValues(vIndex);
346 int vOffset = getVertexValueOffset(vIndex);
347 return ConstValueTagArray(&_vertValueTags[vOffset], vCount);
348}
349 inline FVarLevel::ValueTagArray
350FVarLevel::getVertexValueTags(Index vIndex)
351{
352 int vCount = getNumVertexValues(vIndex);
353 int vOffset = getVertexValueOffset(vIndex);
354 return ValueTagArray(&_vertValueTags[vOffset], vCount);
355}
356
357 inline FVarLevel::ConstCreaseEndPairArray
358FVarLevel::getVertexValueCreaseEnds(Index vIndex) const
359{
360 int vCount = getNumVertexValues(vIndex);
361 int vOffset = getVertexValueOffset(vIndex);
362 return ConstCreaseEndPairArray(&_vertValueCreaseEnds[vOffset], vCount);
363}
364 inline FVarLevel::CreaseEndPairArray
365FVarLevel::getVertexValueCreaseEnds(Index vIndex)
366{
367 int vCount = getNumVertexValues(vIndex);
368 int vOffset = getVertexValueOffset(vIndex);
369 return CreaseEndPairArray(&_vertValueCreaseEnds[vOffset], vCount);
370}
371
372 inline Index
373FVarLevel::findVertexValueIndex(Index vertexIndex, Index valueIndex) const {
374
375 if (_level.getDepth() > 0) return valueIndex;
376
377 Index vvIndex = getVertexValueOffset(vertexIndex);
378 while (_vertValueIndices[vvIndex] != valueIndex) {
379 ++ vvIndex;
380 }
381 return vvIndex;
382}
383
384//
385// Methods related to tagging:
386//
387 inline Level::ETag
388FVarLevel::ETag::combineWithLevelETag(Level::ETag levelTag) const
389{
390 if (this->_mismatch) {
391 levelTag._boundary = true;
392 levelTag._infSharp = true;
393 }
394 return levelTag;
395}
396 inline Level::VTag
397FVarLevel::ValueTag::combineWithLevelVTag(Level::VTag levelTag) const
398{
399 if (this->_mismatch) {
400 //
401 // Semi-sharp FVar values are always tagged and treated as corners
402 // (at least three sharp edges (two boundary edges and one interior
403 // semi-sharp) and/or vertex is semi-sharp) until the sharpness has
404 // decayed, but they ultimately lie on the inf-sharp crease of the
405 // FVar boundary. Consider this when tagging inf-sharp features.
406 //
407 if (this->isCorner()) {
408 levelTag._rule = (Level::VTag::VTagSize) Sdc::Crease::RULE_CORNER;
409 } else {
410 levelTag._rule = (Level::VTag::VTagSize) Sdc::Crease::RULE_CREASE;
411 }
412 if (this->isCrease() || this->isSemiSharp()) {
413 levelTag._infSharp = false;
414 levelTag._infSharpCrease = true;
415 levelTag._corner = false;
416 } else {
417 levelTag._infSharp = true;
418 levelTag._infSharpCrease = false;
419 levelTag._corner = !this->_infIrregular && !this->_infSharpEdges;
420 }
421 levelTag._infSharpEdges = true;
422 levelTag._infIrregular = this->_infIrregular;
423
424 levelTag._boundary = true;
425 levelTag._xordinary = this->_xordinary;
426
427 levelTag._nonManifold |= this->_nonManifold;
428 }
429 return levelTag;
430}
431
432} // end namespace internal
433} // end namespace Vtr
434
435} // end namespace OPENSUBDIV_VERSION
436 using namespace OPENSUBDIV_VERSION;
437} // end namespace OpenSubdiv
438
439#endif /* OPENSUBDIV3_VTR_FVAR_LEVEL_H */
OpenSubdiv
Definition limits.h:32
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::ConstLocalIndexArray
ConstArray< LocalIndex > ConstLocalIndexArray
Definition types.h:83
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::LocalIndexArray
Array< LocalIndex > LocalIndexArray
Definition types.h:82
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::Index
int Index
Definition types.h:54
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::ConstIndexArray
ConstArray< Index > ConstIndexArray
Definition types.h:80
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::LocalIndex
unsigned short LocalIndex
Definition types.h:66
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::IndexArray
Array< Index > IndexArray
Definition types.h:79
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Crease::RULE_CORNER
@ RULE_CORNER
Definition crease.h:87
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Crease::RULE_CREASE
@ RULE_CREASE
Definition crease.h:86