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