// // Copyright 2013 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef FAR_PATCH_PARAM_H #define FAR_PATCH_PARAM_H #include "../version.h" #include "../far/types.h" #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { /// \brief Local patch parameterization descriptor /// /// Coarse mesh faces are split into sets of patches in both uniform and feature /// adaptive modes. In order to maintain local patch parameterization, it is /// necessary to retain some information, such as level of subdivision, face- /// winding status... This parameterization is directly applicable to ptex textures, /// but has to be remapped to a specific layout for uv textures. /// /// Bitfield layout : /// /// Field | Bits | Content /// -----------|:----:|------------------------------------------------------ /// level | 4 | the subdivision level of the patch /// nonquad | 1 | whether the patch is the child of a non-quad face /// rotation | 2 | patch rotations necessary to match CCW face-winding /// v | 10 | log2 value of u parameter at first patch corner /// u | 10 | log2 value of v parameter at first patch corner /// reserved1 | 5 | padding /// /// Note : the bitfield is not expanded in the struct due to differences in how /// GPU & CPU compilers pack bit-fields and endian-ness. /// struct PatchParam { Index faceIndex:32; // Ptex face index struct BitField { unsigned int field:32; /// \brief Sets the values of the bit fields /// /// @param u value of the u parameter for the first corner of the face /// @param v value of the v parameter for the first corner of the face /// /// @param rots rotations required to reproduce CCW face-winding /// @param depth subdivision level of the patch /// @param nonquad true if the root face is not a quad /// void Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ); /// \brief Returns the log2 value of the u parameter at the top left corner of /// the patch unsigned short GetU() const { return (unsigned short)((field >> 17) & 0x3ff); } /// \brief Returns the log2 value of the v parameter at the top left corner of /// the patch unsigned short GetV() const { return (unsigned short)((field >> 7) & 0x3ff); } /// \brief Returns the rotation of the patch (the number of CCW parameter winding) unsigned char GetRotation() const { return (unsigned char)((field >> 5) & 0x3); } /// \brief True if the parent coarse face is a non-quad bool NonQuadRoot() const { return (field >> 4) & 0x1; } /// \brief Returns the fratcion of normalized parametric space covered by the /// sub-patch. float GetParamFraction() const; /// \brief Returns the level of subdivision of the patch unsigned char GetDepth() const { return (unsigned char)(field & 0xf); } /// The (u,v) pair is normalized to this sub-parametric space. /// /// @param u u parameter /// @param v v parameter /// void Normalize( float & u, float & v ) const; /// \brief Rotate (u,v) pair to compensate for transition pattern and boundary /// orientations. /// /// @param u u parameter /// @param v v parameter /// void Rotate( float & u, float & v ) const; /// \brief Resets the values to 0 void Clear() { field = 0; } } bitField; /// \brief Sets the values of the bit fields /// /// @param faceid ptex face index /// /// @param u value of the u parameter for the first corner of the face /// @param v value of the v parameter for the first corner of the face /// /// @param rots rotations required to reproduce CCW face-winding /// @param depth subdivision level of the patch /// @param nonquad true if the root face is not a quad /// void Set( Index faceid, short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) { faceIndex = faceid; bitField.Set(u,v,rots,depth,nonquad); } /// \brief Resets everything to 0 void Clear() { faceIndex = 0; bitField.Clear(); } }; typedef std::vector PatchParamTable; typedef Vtr::Array PatchParamArray; typedef Vtr::ConstArray ConstPatchParamArray; inline void PatchParam::BitField::Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) { field = (u << 17) | (v << 7) | (rots << 5) | ((nonquad ? 1:0) << 4) | (nonquad ? depth+1 : depth); } inline float PatchParam::BitField::GetParamFraction( ) const { if (NonQuadRoot()) { return 1.0f / float( 1 << (GetDepth()-1) ); } else { return 1.0f / float( 1 << GetDepth() ); } } inline void PatchParam::BitField::Normalize( float & u, float & v ) const { float frac = GetParamFraction(); // top left corner float pu = (float)GetU()*frac; float pv = (float)GetV()*frac; // normalize u,v coordinates u = (u - pu) / frac, v = (v - pv) / frac; } inline void PatchParam::BitField::Rotate( float & u, float & v ) const { switch( GetRotation() ) { case 0 : break; case 1 : { float tmp=v; v=1.0f-u; u=tmp; } break; case 2 : { u=1.0f-u; v=1.0f-v; } break; case 3 : { float tmp=u; u=1.0f-v; v=tmp; } break; default: assert(0); } } } // end namespace Far } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* FAR_PATCH_PARAM */