// // 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 OPENSUBDIV3_HBRHIERARCHICALEDIT_H #define OPENSUBDIV3_HBRHIERARCHICALEDIT_H #include "../version.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { template class HbrHierarchicalEdit; template class HbrFace; template class HbrVertex; template class HbrHierarchicalEdit { public: typedef enum Operation { Set, Add, Subtract } Operation; protected: HbrHierarchicalEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces) : faceid(_faceid), nsubfaces(_nsubfaces) { subfaces = new unsigned char[_nsubfaces]; for (int i = 0; i < nsubfaces; ++i) { subfaces[i] = _subfaces[i]; } } HbrHierarchicalEdit(int _faceid, int _nsubfaces, int *_subfaces) : faceid(_faceid), nsubfaces(_nsubfaces) { subfaces = new unsigned char[_nsubfaces]; for (int i = 0; i < nsubfaces; ++i) { subfaces[i] = static_cast(_subfaces[i]); } } public: virtual ~HbrHierarchicalEdit() { delete[] subfaces; } bool operator<(const HbrHierarchicalEdit& p) const { if (faceid < p.faceid) return true; if (faceid > p.faceid) return false; int minlength = nsubfaces; if (minlength > p.nsubfaces) minlength = p.nsubfaces; for (int i = 0; i < minlength; ++i) { if (subfaces[i] < p.subfaces[i]) return true; if (subfaces[i] > p.subfaces[i]) return false; } return (nsubfaces < p.nsubfaces); } // Return the face id (the first element in the path) int GetFaceID() const { return faceid; } // Return the number of subfaces in the path int GetNSubfaces() const { return nsubfaces; } // Return a subface element in the path unsigned char GetSubface(int index) const { return subfaces[index]; } // Determines whether this hierarchical edit is relevant to the // face in question bool IsRelevantToFace(HbrFace* face) const; // Applys edit to face. All subclasses may override this method virtual void ApplyEditToFace(HbrFace* /* face */) {} // Applys edit to vertex. Subclasses may override this method. virtual void ApplyEditToVertex(HbrFace* /* face */, HbrVertex* /* vertex */) {} #ifdef PRMAN // Gets the effect of this hierarchical edit on the bounding box. // Subclasses may override this method virtual void ApplyToBound(struct bbox& /* box */, RtMatrix * /* mx */) const {} #endif protected: // ID of the top most face in the mesh which begins the path const int faceid; // Number of subfaces const int nsubfaces; // IDs of the subfaces unsigned char *subfaces; }; template class HbrHierarchicalEditComparator { public: bool operator() (const HbrHierarchicalEdit* path1, const HbrHierarchicalEdit* path2) const { return (*path1 < *path2); } }; } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #include "../hbr/face.h" #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { template bool HbrHierarchicalEdit::IsRelevantToFace(HbrFace* face) const { // Key assumption: the face's first vertex edit is relevant to // that face. We will then compare ourselves to that edit and if // the first part of our subpath is identical to the entirety of // that subpath, this edit is relevant. // Calling code is responsible for making sure we don't // dereference a null pointer here HbrHierarchicalEdit* p = *face->GetHierarchicalEdits(); if (!p) return false; if (this == p) return true; if (faceid != p->faceid) return false; // If our path length is less than the face depth, it should mean // that we're dealing with another face somewhere up the path, so // we're not relevant if (nsubfaces < face->GetDepth()) return false; if (memcmp(subfaces, p->subfaces, face->GetDepth() * sizeof(unsigned char)) != 0) { return false; } return true; } } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* OPENSUBDIV3_HBRHIERARCHICALEDIT_H */