1 // 2 // Copyright 2017 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 25 #ifndef OPENSUBDIV3_FAR_PATCH_BUILDER_H 26 #define OPENSUBDIV3_FAR_PATCH_BUILDER_H 27 28 #include "../version.h" 29 30 #include "../sdc/types.h" 31 #include "../far/types.h" 32 #include "../far/topologyRefiner.h" 33 #include "../far/patchDescriptor.h" 34 #include "../far/patchParam.h" 35 #include "../far/ptexIndices.h" 36 #include "../far/sparseMatrix.h" 37 38 39 namespace OpenSubdiv { 40 namespace OPENSUBDIV_VERSION { 41 42 namespace Far { 43 44 // 45 // SourcePatch 46 // 47 // This is a local utility class that captures the full local topology of an 48 // arbitrarily irregular patch, i.e. a patch which may have one or all corners 49 // irregular. Given the topology at each corner the entire collection of 50 // points involved is identified and oriented consistently. 51 // 52 // Note (barfowl): 53 // This was originally a class internal to PatchBuilder, but there is some 54 // redundancy between it and the Level::VSpan used more publicly to identify 55 // irregular corner topology. Replacing VSpan with SourcePatch is now under 56 // consideration, and doing so will impact its public/private interface (which 57 // was left public to give PatchBuilder access). 58 // A simpler constructor to initialize an instance given a set of Corners 59 // would also be preferable if made more public (i.e. public for use within 60 // the library, not exported to clients) -- eliminating the need for the 61 // explicit initialization and required call to the Finalize() method that 62 // the PatchBuilder currently performs internally. 63 // 64 class SourcePatch { 65 public: 66 struct Corner { CornerCorner67 Corner() { std::memset(this, 0, sizeof(Corner)); } 68 69 LocalIndex _numFaces; // valence of corner vertex 70 LocalIndex _patchFace; // location of patch within incident faces 71 72 unsigned short _boundary : 1; 73 unsigned short _sharp : 1; 74 unsigned short _dart : 1; 75 76 // For internal bookkeeping -- consider hiding or moving elsewhere 77 unsigned short _sharesWithPrev : 1; 78 unsigned short _sharesWithNext : 1; 79 unsigned short _val2Interior : 1; 80 unsigned short _val2Adjacent : 1; 81 }; 82 83 public: SourcePatch()84 SourcePatch() { std::memset(this, 0, sizeof(SourcePatch)); } ~SourcePatch()85 ~SourcePatch() { } 86 87 // To be called after all Corners have been initialized (hope to 88 // replace this with alternative constructor at some point) 89 void Finalize(int size3or4); 90 GetNumSourcePoints()91 int GetNumSourcePoints() const { return _numSourcePoints; } GetMaxValence()92 int GetMaxValence() const { return _maxValence; } GetMaxRingSize()93 int GetMaxRingSize() const { return _maxRingSize; } 94 GetCornerRingSize(int corner)95 int GetCornerRingSize(int corner) const { return _ringSizes[corner]; } 96 int GetCornerRingPoints(int corner, int points[]) const; 97 98 // public/private access needs to be reviewed when/if used more publicly 99 //private: 100 public: 101 // The SourcePatch is fully defined by its Corner members 102 Corner _corners[4]; 103 int _numCorners; 104 105 // Additional members (derived from Corners) to help assemble corner rings: 106 int _numSourcePoints; 107 int _maxValence; 108 int _maxRingSize; 109 110 int _ringSizes[4]; 111 int _localRingSizes[4]; 112 int _localRingOffsets[4]; 113 }; 114 115 116 // 117 // PatchBuilder 118 // 119 // This is the main class to assist the identification of limit surface 120 // patches from faces in a TopologyRefiner for assembly into other, larger 121 // datatypes. 122 // 123 // The PatchBuilder takes a const reference to a refiner and supports 124 // arbitrarily refined hierarchies, i.e. it is not restricted to uniform or 125 // adaptive refinement strategies and does not include any logic relating 126 // to the origin of the hierarchy. It can associate a patch with any face 127 // in the hierarchy (subject to a few minimum requirements) -- leaving the 128 // decision as to which faces/patches are appropriate to its client. 129 // 130 // PatchBuilder is an abstract base class with a subclass derived to support 131 // each subdivision scheme -- as such, construction relies on a factory 132 // method to create an instance of the appropriate subclass. Only two pure 133 // virtual methods are required (other than the required destructor): 134 // 135 // - determine the patch type for a subdivision scheme given a more 136 // general basis specification (e.g. Bezier, Gregory, Linear, etc) 137 // 138 // - convert the vertices in the subdivision hierarchy into points of a 139 // specified patch type, using computations specific to that scheme 140 // 141 // The base class handles the more general topological analysis that 142 // determines the nature of a patch associated with each face -- providing 143 // both queries to the client, along with more involved methods to extract 144 // or convert data associated with the patches. There is no concrete "Patch" 145 // class to which all clients would be required to conform. The queries and 146 // data returned are provided for clients to assemble into patches or other 147 // aggregates as they see fit. 148 // 149 // This is intended as an internal/private class for use within the library 150 // for now -- possibly to be exported for use by clients when/if its 151 // interface is appropriate and stable. 152 // 153 class PatchBuilder { 154 public: 155 // 156 // A PatchBuilder is constructed given a patch "basis" rather than a 157 // "type" to use with the subdivision scheme involved. The relevant 158 // explicit patch types will be determined from the basis and scheme: 159 // 160 enum BasisType { 161 BASIS_UNSPECIFIED, 162 BASIS_REGULAR, 163 BASIS_GREGORY, 164 BASIS_LINEAR, 165 BASIS_BEZIER // to be supported in future 166 }; 167 168 // 169 // Required Options specify a patch basis to use for both regular and 170 // irregular patches -- sparing the client the need to repeatedly 171 // specify these for each face considered. Other options are included 172 // to support legacy approximations: 173 // 174 struct Options { OptionsOptions175 Options() : regBasisType(BASIS_UNSPECIFIED), 176 irregBasisType(BASIS_UNSPECIFIED), 177 fillMissingBoundaryPoints(false), 178 approxInfSharpWithSmooth(false), 179 approxSmoothCornerWithSharp(false) { } 180 181 BasisType regBasisType; 182 BasisType irregBasisType; 183 bool fillMissingBoundaryPoints; 184 bool approxInfSharpWithSmooth; 185 bool approxSmoothCornerWithSharp; 186 }; 187 188 public: 189 // 190 // Public construction (via factory method) and destruction: 191 // 192 static PatchBuilder* Create(TopologyRefiner const& refiner, 193 Options const& options); 194 virtual ~PatchBuilder(); 195 196 // 197 // High-level queries related to the subdivision scheme of the refiner, the 198 // patch types associated with it and those chosen to represent its faces: 199 // GetRegularFaceSize()200 int GetRegularFaceSize() const { return _schemeRegFaceSize; } 201 GetRegularBasisType()202 BasisType GetRegularBasisType() const { return _options.regBasisType; } GetIrregularBasisType()203 BasisType GetIrregularBasisType() const { return _options.irregBasisType; } 204 GetRegularPatchType()205 PatchDescriptor::Type GetRegularPatchType() const { return _regPatchType; } GetIrregularPatchType()206 PatchDescriptor::Type GetIrregularPatchType() const { return _irregPatchType; } 207 GetNativePatchType()208 PatchDescriptor::Type GetNativePatchType() const { return _nativePatchType; } GetLinearPatchType()209 PatchDescriptor::Type GetLinearPatchType() const { return _linearPatchType; } 210 211 // 212 // Face-level queries to determine presence of patches: 213 // 214 bool IsFaceAPatch(int level, Index face) const; 215 bool IsFaceALeaf(int level, Index face) const; 216 217 // 218 // Patch-level topological queries: 219 // 220 bool IsPatchRegular(int level, Index face, int fvc = -1) const; 221 222 int GetRegularPatchBoundaryMask(int level, Index face, int fvc = -1) const; 223 224 void GetIrregularPatchCornerSpans(int level, Index face, 225 Vtr::internal::Level::VSpan cornerSpans[4], int fvc = -1) const; 226 DoesFaceVaryingPatchMatch(int level,Index face,int fvc)227 bool DoesFaceVaryingPatchMatch(int level, Index face, int fvc) const { 228 return _refiner.getLevel(level).doesFaceFVarTopologyMatch(face, fvc); 229 } 230 231 // 232 // Patch-level control point retrieval and methods for converting source 233 // points to a set of local points in a different basis 234 // 235 int GetRegularPatchPoints(int level, Index face, 236 int regBoundaryMask, // compute internally when < 0 237 Index patchPoints[], 238 int fvc = -1) const; 239 240 template <typename REAL> 241 int GetIrregularPatchConversionMatrix(int level, Index face, 242 Vtr::internal::Level::VSpan const cornerSpans[], 243 SparseMatrix<REAL> & matrix) const; 244 245 int GetIrregularPatchSourcePoints(int level, Index face, 246 Vtr::internal::Level::VSpan const cornerSpans[], 247 Index sourcePoints[], 248 int fvc = -1) const; 249 // 250 // Queries related to "single-crease" patches -- currently a subset of 251 // regular interior patches: 252 // 253 struct SingleCreaseInfo { 254 int creaseEdgeInFace; 255 float creaseSharpness; 256 }; 257 bool IsRegularSingleCreasePatch(int level, Index face, 258 SingleCreaseInfo & info) const; 259 260 // 261 // Computing the PatchParam -- note the regrettable dependency on 262 // PtexIndices but PatchParam is essentially tied to it indefinitely. 263 // Better to pass it in than have the PatchBuilder build its own 264 // PtexIndices. 265 // 266 // Consider creating a PatchParamFactory which can manage the PtexIndices 267 // along with this method. It will then be able to generate additional 268 // data to accelerate these computations. 269 // 270 PatchParam ComputePatchParam(int level, Index face, 271 PtexIndices const& ptexIndices, bool isRegular = true, 272 int boundaryMask = 0, bool computeTransitionMask = false) const; 273 274 protected: 275 PatchBuilder(TopologyRefiner const& refiner, Options const& options); 276 277 // Internal methods supporting topology queries: 278 int getRegularFacePoints(int level, Index face, 279 Index patchPoints[], int fvc) const; 280 281 int getQuadRegularPatchPoints(int level, Index face, 282 int regBoundaryMask, Index patchPoints[], int fvc) const; 283 284 int getTriRegularPatchPoints(int level, Index face, 285 int regBoundaryMask, Index patchPoints[], int fvc) const; 286 287 // Internal methods using the SourcePatch: 288 int assembleIrregularSourcePatch(int level, Index face, 289 Vtr::internal::Level::VSpan const cornerSpans[], 290 SourcePatch & sourcePatch) const; 291 292 int gatherIrregularSourcePoints(int level, Index face, 293 Vtr::internal::Level::VSpan const cornerSpans[], 294 SourcePatch & sourcePatch, 295 Index patchPoints[], int fvc) const; 296 297 protected: 298 // 299 // Virtual methods to be provided by subclass for each scheme: 300 // 301 virtual PatchDescriptor::Type patchTypeFromBasis(BasisType basis) const = 0; 302 303 // Note overloading of the conversion for SparseMatrix<REAL>: 304 virtual int convertToPatchType(SourcePatch const & sourcePatch, 305 PatchDescriptor::Type patchType, 306 SparseMatrix<float> & matrix) const = 0; 307 virtual int convertToPatchType(SourcePatch const & sourcePatch, 308 PatchDescriptor::Type patchType, 309 SparseMatrix<double> & matrix) const = 0; 310 311 protected: 312 TopologyRefiner const& _refiner; 313 Options const _options; 314 315 Sdc::SchemeType _schemeType; 316 int _schemeRegFaceSize; 317 bool _schemeIsLinear; 318 319 PatchDescriptor::Type _regPatchType; 320 PatchDescriptor::Type _irregPatchType; 321 PatchDescriptor::Type _nativePatchType; 322 PatchDescriptor::Type _linearPatchType; 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_BUILDER_H */ 333