1 //
2 //   Copyright 2013 Pixar
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 
25 #ifndef OPENSUBDIV3_FAR_PATCH_PARAM_H
26 #define OPENSUBDIV3_FAR_PATCH_PARAM_H
27 
28 #include "../version.h"
29 
30 #include "../far/types.h"
31 
32 namespace OpenSubdiv {
33 namespace OPENSUBDIV_VERSION {
34 
35 namespace Far {
36 
37 /// \brief Patch parameterization
38 ///
39 /// Topological refinement splits coarse mesh faces into refined faces.
40 ///
41 /// This patch parameterzation describes the relationship between one
42 /// of these refined faces and its corresponding coarse face. It is used
43 /// both for refined faces that are represented as full limit surface
44 /// parametric patches as well as for refined faces represented as simple
45 /// triangles or quads. This parameterization is needed to interpolate
46 /// primvar data across a refined face.
47 ///
48 /// The U,V and refinement level parameters describe the scale and offset
49 /// needed to map a location on the patch between levels of refinement.
50 /// The encoding of these values exploits the quad-tree organization of
51 /// the faces produced by subdivision. We encode the U,V origin of the
52 /// patch using two 10-bit integer values and the refinement level as
53 /// a 4-bit integer. This is sufficient to represent up through 10 levels
54 /// of refinement.
55 ///
56 /// Special consideration must be given to the refined faces resulting from
57 /// irregular coarse faces. We adopt a convention similar to Ptex texture
58 /// mapping and define the parameterization for these faces in terms of the
59 /// regular faces resulting from the first topological splitting of the
60 /// irregular coarse face.
61 ///
62 /// When computing the basis functions needed to evaluate the limit surface
63 /// parametric patch representing a refined face, we also need to know which
64 /// edges of the patch are interpolated boundaries. These edges are encoded
65 /// as a boundary bitmask identifying the boundary edges of the patch in
66 /// sequential order starting from the first vertex of the refined face.
67 ///
68 /// A sparse topological refinement (like feature adaptive refinement) can
69 /// produce refined faces that are adjacent to faces at the next level of
70 /// subdivision. We identify these transitional edges with a transition
71 /// bitmask using the same encoding as the boundary bitmask.
72 ///
73 /// For triangular subdivision schemes we specify the parameterization using
74 /// a similar method. Alternate triangles at a given level of refinement
75 /// are parameterized from their opposite corners and encoded as occupying
76 /// the opposite diagonal of the quad-tree hierarchy. The third barycentric
77 /// coordinate is dependent on and can be derived from the other two
78 /// coordinates. This encoding also takes inspiration from the Ptex
79 /// texture mapping specification.
80 ///
81 /// Bitfield layout :
82 ///
83 ///  Field0     | Bits | Content
84 ///  -----------|:----:|------------------------------------------------------
85 ///  faceId     | 28   | the faceId of the patch
86 ///  transition | 4    | transition edge mask encoding
87 ///
88 ///  Field1     | Bits | Content
89 ///  -----------|:----:|------------------------------------------------------
90 ///  level      | 4    | the subdivision level of the patch
91 ///  nonquad    | 1    | whether patch is refined from a non-quad face
92 ///  regular    | 1    | whether patch is regular
93 ///  unused     | 1    | unused
94 ///  boundary   | 5    | boundary edge mask encoding
95 ///  v          | 10   | log2 value of u parameter at first patch corner
96 ///  u          | 10   | log2 value of v parameter at first patch corner
97 ///
98 /// Note : the bitfield is not expanded in the struct due to differences in how
99 ///        GPU & CPU compilers pack bit-fields and endian-ness.
100 ///
101 /*!
102  \verbatim
103  Quad Patch Parameterization
104 
105  (0,1)                           (1,1)
106    +-------+-------+---------------+
107    |       |       |               |
108    |   L2  |   L2  |               |
109    |0,3    |1,3    |               |
110    +-------+-------+       L1      |
111    |       |       |               |
112    |   L2  |   L2  |               |
113    |0,2    |1,2    |1,1            |
114    +-------+-------+---------------+
115    |               |               |
116    |               |               |
117    |               |               |
118    |       L1      |       L1      |
119    |               |               |
120    |               |               |
121    |0,0            |1,0            |
122    +---------------+---------------+
123  (0,0)                           (1,0)
124  \endverbatim
125 */
126 /*!
127  \verbatim
128  Triangle Patch Parameterization
129 
130  (0,1)                           (1,1)  (0,1,0)
131    +-------+-------+---------------+       +
132    | \     | \     | \             |       | \
133    |L2 \   |L2 \   |   \           |       |   \
134    |0,3  \ |1,3  \ |     \         |       | L2  \
135    +-------+-------+       \       |       +-------+
136    | \     | \     |   L1    \     |       | \  L2 | \
137    |L2 \   |L2 \   |           \   |       |   \   |   \
138    |0,2  \ |1,2  \ |1,1          \ |       | L2  \ | L2  \
139    +-------+-------+---------------+       +-------+-------+
140    | \             | \             |       | \             | \
141    |   \           |   \           |       |   \           |   \
142    |     \         |     \         |       |     \    L1   |     \
143    |       \       |       \       |       |       \       |       \
144    |   L1    \     |   L1    \     |       |   L1    \     |   L1    \
145    |           \   |           \   |       |           \   |           \
146    |0,0          \ |1,0          \ |       |             \ |             \
147    +---------------+---------------+       +---------------+---------------+
148  (0,0)                           (1,0)  (0,0,1)                         (1,0,0)
149  \endverbatim
150 */
151 
152 struct PatchParam {
153     /// \brief Sets the values of the bit fields
154     ///
155     /// @param faceid face index
156     ///
157     /// @param u value of the u parameter for the first corner of the face
158     /// @param v value of the v parameter for the first corner of the face
159     ///
160     /// @param depth subdivision level of the patch
161     /// @param nonquad true if the root face is not a quad
162     ///
163     /// @param boundary 5-bits identifying boundary edges (and verts for tris)
164     /// @param transition 4-bits identifying transition edges
165     ///
166     /// @param regular whether the patch is regular
167     ///
168     void Set(Index faceid, short u, short v,
169              unsigned short depth, bool nonquad,
170              unsigned short boundary, unsigned short transition,
171              bool regular = false);
172 
173     /// \brief Resets everything to 0
ClearPatchParam174     void Clear() { field0 = field1 = 0; }
175 
176     /// \brief Returns the faceid
GetFaceIdPatchParam177     Index GetFaceId() const { return Index(unpack(field0,28,0)); }
178 
179     /// \brief Returns the log2 value of the u parameter at
180     /// the first corner of the patch
GetUPatchParam181     unsigned short GetU() const { return (unsigned short)unpack(field1,10,22); }
182 
183     /// \brief Returns the log2 value of the v parameter at
184     /// the first corner of the patch
GetVPatchParam185     unsigned short GetV() const { return (unsigned short)unpack(field1,10,12); }
186 
187     /// \brief Returns the transition edge encoding for the patch.
GetTransitionPatchParam188     unsigned short GetTransition() const { return (unsigned short)unpack(field0,4,28); }
189 
190     /// \brief Returns the boundary edge encoding for the patch.
GetBoundaryPatchParam191     unsigned short GetBoundary() const { return (unsigned short)unpack(field1,5,7); }
192 
193     /// \brief True if the parent base face is a non-quad
NonQuadRootPatchParam194     bool NonQuadRoot() const { return (unpack(field1,1,4) != 0); }
195 
196     /// \brief Returns the level of subdivision of the patch
GetDepthPatchParam197     unsigned short GetDepth() const { return (unsigned short)unpack(field1,4,0); }
198 
199     /// \brief Returns the fraction of unit parametric space covered by this face.
200     float GetParamFraction() const;
201 
202     /// \brief A (u,v) pair in the fraction of parametric space covered by this
203     /// face is mapped into a normalized parametric space.
204     ///
205     /// @param u  u parameter
206     /// @param v  v parameter
207     ///
208     template <typename REAL>
209     void Normalize( REAL & u, REAL & v ) const;
210     template <typename REAL>
211     void NormalizeTriangle( REAL & u, REAL & v ) const;
212 
213     /// \brief A (u,v) pair in a normalized parametric space is mapped back into the
214     /// fraction of parametric space covered by this face.
215     ///
216     /// @param u  u parameter
217     /// @param v  v parameter
218     ///
219     template <typename REAL>
220     void Unnormalize( REAL & u, REAL & v ) const;
221     template <typename REAL>
222     void UnnormalizeTriangle( REAL & u, REAL & v ) const;
223 
224     /// \brief Returns if a triangular patch is parametrically rotated 180 degrees
225     bool IsTriangleRotated() const;
226 
227     /// \brief Returns whether the patch is regular
IsRegularPatchParam228     bool IsRegular() const { return (unpack(field1,1,5) != 0); }
229 
230     unsigned int field0:32;
231     unsigned int field1:32;
232 
233 private:
packPatchParam234     unsigned int pack(unsigned int value, int width, int offset) const {
235         return (unsigned int)((value & ((1<<width)-1)) << offset);
236     }
237 
unpackPatchParam238     unsigned int unpack(unsigned int value, int width, int offset) const {
239         return (unsigned int)((value >> offset) & ((1<<width)-1));
240     }
241 };
242 
243 typedef std::vector<PatchParam> PatchParamTable;
244 
245 typedef Vtr::Array<PatchParam> PatchParamArray;
246 typedef Vtr::ConstArray<PatchParam> ConstPatchParamArray;
247 
248 inline void
Set(Index faceid,short u,short v,unsigned short depth,bool nonquad,unsigned short boundary,unsigned short transition,bool regular)249 PatchParam::Set(Index faceid, short u, short v,
250                 unsigned short depth, bool nonquad,
251                 unsigned short boundary, unsigned short transition,
252                 bool regular) {
253     field0 = pack(faceid,    28,  0) |
254              pack(transition, 4, 28);
255 
256     field1 = pack(u,         10, 22) |
257              pack(v,         10, 12) |
258              pack(boundary,   5,  7) |
259              pack(regular,    1,  5) |
260              pack(nonquad,    1,  4) |
261              pack(depth,      4,  0);
262 }
263 
264 inline float
GetParamFraction()265 PatchParam::GetParamFraction( ) const {
266     return 1.0f / (float)(1 << (GetDepth() - NonQuadRoot()));
267 }
268 
269 template <typename REAL>
270 inline void
Normalize(REAL & u,REAL & v)271 PatchParam::Normalize( REAL & u, REAL & v ) const {
272 
273     REAL fracInv = (REAL)(1.0f / GetParamFraction());
274 
275     u = u * fracInv - (REAL)GetU();
276     v = v * fracInv - (REAL)GetV();
277 }
278 
279 template <typename REAL>
280 inline void
Unnormalize(REAL & u,REAL & v)281 PatchParam::Unnormalize( REAL & u, REAL & v ) const {
282 
283     REAL frac = (REAL)GetParamFraction();
284 
285     u = (u + (REAL)GetU()) * frac;
286     v = (v + (REAL)GetV()) * frac;
287 }
288 
289 inline bool
IsTriangleRotated()290 PatchParam::IsTriangleRotated() const {
291 
292     return (GetU() + GetV()) >= (1 << GetDepth());
293 }
294 
295 template <typename REAL>
296 inline void
NormalizeTriangle(REAL & u,REAL & v)297 PatchParam::NormalizeTriangle( REAL & u, REAL & v ) const {
298 
299     if (IsTriangleRotated()) {
300         REAL fracInv = (REAL)(1.0f / GetParamFraction());
301 
302         int depthFactor = 1 << GetDepth();
303         u = (REAL)(depthFactor - GetU()) - (u * fracInv);
304         v = (REAL)(depthFactor - GetV()) - (v * fracInv);
305     } else {
306         Normalize(u, v);
307     }
308 }
309 
310 template <typename REAL>
311 inline void
UnnormalizeTriangle(REAL & u,REAL & v)312 PatchParam::UnnormalizeTriangle( REAL & u, REAL & v ) const {
313 
314     if (IsTriangleRotated()) {
315         REAL frac = GetParamFraction();
316 
317         int depthFactor = 1 << GetDepth();
318         u = ((REAL)(depthFactor - GetU()) - u) * frac;
319         v = ((REAL)(depthFactor - GetV()) - v) * frac;
320     } else {
321         Unnormalize(u, v);
322     }
323 }
324 
325 } // end namespace Far
326 
327 } // end namespace OPENSUBDIV_VERSION
328 using namespace OPENSUBDIV_VERSION;
329 
330 } // end namespace OpenSubdiv
331 
332 #endif /* OPENSUBDIV3_FAR_PATCH_PARAM */
333