1 //
2 //   Copyright 2015 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_FAR_TOPOLOGY_LEVEL_H
25 #define OPENSUBDIV3_FAR_TOPOLOGY_LEVEL_H
26 
27 #include "../version.h"
28 
29 #include "../vtr/level.h"
30 #include "../vtr/refinement.h"
31 #include "../far/types.h"
32 
33 #include <vector>
34 
35 namespace OpenSubdiv {
36 namespace OPENSUBDIV_VERSION {
37 
38 namespace Far {
39 
40 ///
41 /// \brief An interface for accessing data in a specific level of a refined topology hierarchy.
42 ///
43 /// TopologyLevel provides an interface to data in a specific level of a topology hierarchy.
44 /// Instances of TopologyLevel are created and owned by a TopologyRefiner,
45 /// which will return const-references to them.  Such references are only valid during the
46 /// lifetime of the TopologyRefiner that created and returned them, and only for a given refinement,
47 /// i.e. if the TopologyRefiner is re-refined, any references to TopoologyLevels are invalidated.
48 ///
49 class TopologyLevel {
50 
51 public:
52     //@{
53     /// @name Methods to inspect the overall inventory of components:
54     ///
55     /// All three main component types are indexed locally within each level.  For
56     /// some topological relationships -- notably face-vertices, which is often
57     /// the only relationship of interest -- the total number of entries is also
58     /// made available.
59     ///
60 
61     /// \brief Return the number of vertices in this level
GetNumVertices()62     int GetNumVertices() const     { return _level->getNumVertices(); }
63 
64     /// \brief Return the number of faces in this level
GetNumFaces()65     int GetNumFaces() const        { return _level->getNumFaces(); }
66 
67     /// \brief Return the number of edges in this level
GetNumEdges()68     int GetNumEdges() const        { return _level->getNumEdges(); }
69 
70     /// \brief Return the total number of face-vertices, i.e. the sum of all vertices for all faces
GetNumFaceVertices()71     int GetNumFaceVertices() const { return _level->getNumFaceVerticesTotal(); }
72     //@}
73 
74     //@{
75     /// @name Methods to inspect topological relationships for individual components:
76     ///
77     /// With three main component types (vertices, faces and edges), for each of the
78     /// three components the TopologyLevel stores the incident/adjacent components of
79     /// the other two types.  So there are six relationships available for immediate
80     /// inspection.  All are accessed by methods that return an array of fixed size
81     /// containing the indices of the incident components.
82     ///
83     /// For some of the relations, i.e. those for which the incident components are
84     /// of higher order or 'contain' the component itself (e.g. a vertex has incident
85     /// faces that contain it), an additional 'local index' is available that identifies
86     /// the component within each of its neighbors.  For example, if vertex V is the k'th
87     /// vertex in some face F, then when F occurs in the set of incident vertices of V,
88     /// the local index corresponding to F will be k.  The ordering of local indices
89     /// matches the ordering of the incident component to which it corresponds.
90     //
91 
92     /// \brief Access the vertices incident a given face
GetFaceVertices(Index f)93     ConstIndexArray GetFaceVertices(Index f) const { return _level->getFaceVertices(f); }
94 
95     /// \brief Access the edges incident a given face
GetFaceEdges(Index f)96     ConstIndexArray GetFaceEdges(Index f) const    { return _level->getFaceEdges(f); }
97 
98     /// \brief Access the vertices incident a given edge
GetEdgeVertices(Index e)99     ConstIndexArray GetEdgeVertices(Index e) const { return _level->getEdgeVertices(e); }
100 
101     /// \brief Access the faces incident a given edge
GetEdgeFaces(Index e)102     ConstIndexArray GetEdgeFaces(Index e) const    { return _level->getEdgeFaces(e); }
103 
104     /// \brief Access the faces incident a given vertex
GetVertexFaces(Index v)105     ConstIndexArray GetVertexFaces(Index v) const  { return _level->getVertexFaces(v); }
106 
107     /// \brief Access the edges incident a given vertex
GetVertexEdges(Index v)108     ConstIndexArray GetVertexEdges(Index v) const  { return _level->getVertexEdges(v); }
109 
110     /// \brief Access the local indices of a vertex with respect to its incident faces
GetVertexFaceLocalIndices(Index v)111     ConstLocalIndexArray GetVertexFaceLocalIndices(Index v) const { return _level->getVertexFaceLocalIndices(v); }
112 
113     /// \brief Access the local indices of a vertex with respect to its incident edges
GetVertexEdgeLocalIndices(Index v)114     ConstLocalIndexArray GetVertexEdgeLocalIndices(Index v) const { return _level->getVertexEdgeLocalIndices(v); }
115 
116     /// \brief Access the local indices of an edge with respect to its incident faces
GetEdgeFaceLocalIndices(Index e)117     ConstLocalIndexArray GetEdgeFaceLocalIndices(Index e) const   { return _level->getEdgeFaceLocalIndices(e); }
118 
119     /// \brief Identify the edge matching the given vertex pair
FindEdge(Index v0,Index v1)120     Index FindEdge(Index v0, Index v1) const { return _level->findEdge(v0, v1); }
121     //@}
122 
123     //@{
124     /// @name Methods to inspect other topological properties of individual components:
125     ///
126 
127     /// \brief Return if the edge is non-manifold
IsEdgeNonManifold(Index e)128     bool IsEdgeNonManifold(Index e) const   { return _level->isEdgeNonManifold(e); }
129 
130     /// \brief Return if the vertex is non-manifold
IsVertexNonManifold(Index v)131     bool IsVertexNonManifold(Index v) const { return _level->isVertexNonManifold(v); }
132 
133     /// \brief Return if the edge is a boundary
IsEdgeBoundary(Index e)134     bool IsEdgeBoundary(Index e) const   { return _level->getEdgeTag(e)._boundary; }
135 
136     /// \brief Return if the vertex is a boundary
IsVertexBoundary(Index v)137     bool IsVertexBoundary(Index v) const { return _level->getVertexTag(v)._boundary; }
138     //@}
139 
140     //@{
141     /// @name Methods to inspect feature tags for individual components:
142     ///
143     /// While only a subset of components may have been tagged with features such
144     /// as sharpness, all such features have a default value and so all components
145     /// can be inspected.
146 
147     /// \brief Return the sharpness assigned a given edge
GetEdgeSharpness(Index e)148     float GetEdgeSharpness(Index e) const   { return _level->getEdgeSharpness(e); }
149 
150     /// \brief Return the sharpness assigned a given vertex
GetVertexSharpness(Index v)151     float GetVertexSharpness(Index v) const { return _level->getVertexSharpness(v); }
152 
153     /// \brief Return if a given face has been tagged as a hole
IsFaceHole(Index f)154     bool  IsFaceHole(Index f) const         { return _level->isFaceHole(f); }
155 
156     /// \brief Return the subdivision rule assigned a given vertex specific to this level
GetVertexRule(Index v)157     Sdc::Crease::Rule GetVertexRule(Index v) const { return _level->getVertexRule(v); }
158     //@}
159 
160     //@{
161     /// @name Methods to inspect face-varying data:
162     ///
163     /// Face-varying data is organized into topologically independent channels,
164     /// each with an integer identifier.  Access to face-varying data generally
165     /// requires the specification of a channel, though with a single channel
166     /// being a common situation the first/only channel will be assumed if
167     /// unspecified.
168     ///
169     /// A face-varying channel is composed of a set of values that may be shared
170     /// by faces meeting at a common vertex.  Just as there are sets of vertices
171     /// that are associated with faces by index (ranging from 0 to
172     /// num-vertices - 1), face-varying values are also referenced by index
173     /// (ranging from 0 to num-values -1).
174     ///
175     /// The face-varying values associated with a face are accessed similarly to
176     /// the way in which vertices associated with the face are accessed -- an
177     /// array of fixed size containing the indices for each corner is provided
178     /// for inspection, iteration, etc.
179     ///
180     /// When the face-varying topology around a vertex "matches", it has the
181     /// same limit properties and so results in the same limit surface when
182     /// collections of adjacent vertices match.  Like other references to
183     /// "topology", this includes consideration of sharpness.  So it may be
184     /// that face-varying values are assigned around a vertex on a boundary in
185     /// a way that appears to match, but the face-varying interpolation option
186     /// requires sharpening of that vertex in face-varying space -- the
187     /// difference in the topology of the resulting limit surfaces leading to
188     /// the query returning false for the match.  The edge case is simpler in
189     /// that it only considers continuity across the edge, not the entire
190     /// neighborhood around each end vertex.
191 
192     /// \brief Return the number of face-varying channels (should be same for all levels)
GetNumFVarChannels()193     int GetNumFVarChannels() const { return _level->getNumFVarChannels(); }
194 
195     /// \brief Return the total number of face-varying values in a particular channel
196     /// (the upper bound of a face-varying value index)
197     int GetNumFVarValues(int channel = 0) const { return _level->getNumFVarValues(channel); }
198 
199     /// \brief Access the face-varying values associated with a particular face
200     ConstIndexArray GetFaceFVarValues(Index f, int channel = 0) const {
201         return _level->getFaceFVarValues(f, channel);
202     }
203 
204     /// \brief Return if face-varying topology around a vertex matches
205     bool DoesVertexFVarTopologyMatch(Index v, int channel = 0) const {
206         return _level->doesVertexFVarTopologyMatch(v, channel);
207     }
208 
209     /// \brief Return if face-varying topology across the edge only matches
210     bool DoesEdgeFVarTopologyMatch(Index e, int channel = 0) const {
211         return _level->doesEdgeFVarTopologyMatch(e, channel);
212     }
213 
214     /// \brief Return if face-varying topology around a face matches
215     bool DoesFaceFVarTopologyMatch(Index f, int channel = 0) const {
216         return _level->doesFaceFVarTopologyMatch(f, channel);
217     }
218 
219     //@}
220 
221     //@{
222     /// @name Methods to identify parent or child components in adjoining levels of refinement:
223 
224     /// \brief Access the child faces (in the next level) of a given face
GetFaceChildFaces(Index f)225     ConstIndexArray GetFaceChildFaces(Index f) const { return _refToChild->getFaceChildFaces(f); }
226 
227     /// \brief Access the child edges (in the next level) of a given face
GetFaceChildEdges(Index f)228     ConstIndexArray GetFaceChildEdges(Index f) const { return _refToChild->getFaceChildEdges(f); }
229 
230     /// \brief Access the child edges (in the next level) of a given edge
GetEdgeChildEdges(Index e)231     ConstIndexArray GetEdgeChildEdges(Index e) const { return _refToChild->getEdgeChildEdges(e); }
232 
233     /// \brief Return the child vertex (in the next level) of a given face
GetFaceChildVertex(Index f)234     Index GetFaceChildVertex(  Index f) const { return _refToChild->getFaceChildVertex(f); }
235 
236     /// \brief Return the child vertex (in the next level) of a given edge
GetEdgeChildVertex(Index e)237     Index GetEdgeChildVertex(  Index e) const { return _refToChild->getEdgeChildVertex(e); }
238 
239     /// \brief Return the child vertex (in the next level) of a given vertex
GetVertexChildVertex(Index v)240     Index GetVertexChildVertex(Index v) const { return _refToChild->getVertexChildVertex(v); }
241 
242     /// \brief Return the parent face (in the previous level) of a given face
GetFaceParentFace(Index f)243     Index GetFaceParentFace(Index f) const { return _refToParent->getChildFaceParentFace(f); }
244     //@}
245 
246     //@{
247     /// @name Debugging aides:
248 
ValidateTopology()249     bool ValidateTopology() const { return _level->validateTopology(); }
250     void PrintTopology(bool children = true) const { _level->print((children && _refToChild) ? _refToChild : 0); }
251     //@}
252 
253 
254 private:
255     friend class TopologyRefiner;
256 
257     Vtr::internal::Level const *      _level;
258     Vtr::internal::Refinement const * _refToParent;
259     Vtr::internal::Refinement const * _refToChild;
260 
261 public:
262     //  Not intended for public use, but required by std::vector, etc...
TopologyLevel()263     TopologyLevel() { }
~TopologyLevel()264     ~TopologyLevel() { }
265 };
266 
267 } // end namespace Far
268 
269 } // end namespace OPENSUBDIV_VERSION
270 using namespace OPENSUBDIV_VERSION;
271 } // end namespace OpenSubdiv
272 
273 #endif /* OPENSUBDIV3_FAR_TOPOLOGY_LEVEL_H */
274