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_HBRHIERARCHICALEDIT_H
26 #define OPENSUBDIV3_HBRHIERARCHICALEDIT_H
27 
28 #include "../version.h"
29 
30 namespace OpenSubdiv {
31 namespace OPENSUBDIV_VERSION {
32 
33 template <class T> class HbrHierarchicalEdit;
34 template <class T> class HbrFace;
35 template <class T> class HbrVertex;
36 
37 template <class T>
38 class HbrHierarchicalEdit {
39 
40 public:
41     typedef enum Operation {
42         Set,
43         Add,
44         Subtract
45     } Operation;
46 
47 protected:
48 
HbrHierarchicalEdit(int _faceid,int _nsubfaces,unsigned char * _subfaces)49     HbrHierarchicalEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces)
50         : faceid(_faceid), nsubfaces(_nsubfaces) {
51         subfaces = new unsigned char[_nsubfaces];
52         for (int i = 0; i < nsubfaces; ++i) {
53             subfaces[i] = _subfaces[i];
54         }
55     }
56 
HbrHierarchicalEdit(int _faceid,int _nsubfaces,int * _subfaces)57     HbrHierarchicalEdit(int _faceid, int _nsubfaces, int *_subfaces)
58         : faceid(_faceid), nsubfaces(_nsubfaces) {
59         subfaces = new unsigned char[_nsubfaces];
60         for (int i = 0; i < nsubfaces; ++i) {
61             subfaces[i] = static_cast<unsigned char>(_subfaces[i]);
62         }
63     }
64 
65 public:
~HbrHierarchicalEdit()66     virtual ~HbrHierarchicalEdit() {
67         delete[] subfaces;
68     }
69 
70     bool operator<(const HbrHierarchicalEdit& p) const {
71         if (faceid < p.faceid) return true;
72         if (faceid > p.faceid) return false;
73         int minlength = nsubfaces;
74         if (minlength > p.nsubfaces) minlength = p.nsubfaces;
75         for (int i = 0; i < minlength; ++i) {
76             if (subfaces[i] < p.subfaces[i]) return true;
77             if (subfaces[i] > p.subfaces[i]) return false;
78         }
79         return (nsubfaces < p.nsubfaces);
80     }
81 
82     // Return the face id (the first element in the path)
GetFaceID()83     int GetFaceID() const { return faceid; }
84 
85     // Return the number of subfaces in the path
GetNSubfaces()86     int GetNSubfaces() const { return nsubfaces; }
87 
88     // Return a subface element in the path
GetSubface(int index)89     unsigned char GetSubface(int index) const { return subfaces[index]; }
90 
91     // Determines whether this hierarchical edit is relevant to the
92     // face in question
93     bool IsRelevantToFace(HbrFace<T>* face) const;
94 
95     // Applys edit to face. All subclasses may override this method
ApplyEditToFace(HbrFace<T> *)96     virtual void ApplyEditToFace(HbrFace<T>* /* face */) {}
97 
98     // Applys edit to vertex. Subclasses may override this method.
ApplyEditToVertex(HbrFace<T> *,HbrVertex<T> *)99     virtual void ApplyEditToVertex(HbrFace<T>* /* face */, HbrVertex<T>* /* vertex */) {}
100 
101 #ifdef PRMAN
102     // Gets the effect of this hierarchical edit on the bounding box.
103     // Subclasses may override this method
ApplyToBound(struct bbox &,RtMatrix *)104     virtual void ApplyToBound(struct bbox& /* box */, RtMatrix * /* mx */) const {}
105 #endif
106 
107 protected:
108     // ID of the top most face in the mesh which begins the path
109     const int faceid;
110 
111     // Number of subfaces
112     const int nsubfaces;
113 
114     // IDs of the subfaces
115     unsigned char *subfaces;
116 };
117 
118 template <class T>
119 class HbrHierarchicalEditComparator {
120 public:
operator()121     bool operator() (const HbrHierarchicalEdit<T>* path1, const HbrHierarchicalEdit<T>* path2) const {
122         return (*path1 < *path2);
123     }
124 };
125 
126 } // end namespace OPENSUBDIV_VERSION
127 using namespace OPENSUBDIV_VERSION;
128 
129 } // end namespace OpenSubdiv
130 
131 #include "../hbr/face.h"
132 #include <cstring>
133 
134 namespace OpenSubdiv {
135 namespace OPENSUBDIV_VERSION {
136 
137 template <class T>
138 bool
IsRelevantToFace(HbrFace<T> * face)139 HbrHierarchicalEdit<T>::IsRelevantToFace(HbrFace<T>* face) const {
140 
141     // Key assumption: the face's first vertex edit is relevant to
142     // that face. We will then compare ourselves to that edit and if
143     // the first part of our subpath is identical to the entirety of
144     // that subpath, this edit is relevant.
145 
146     // Calling code is responsible for making sure we don't
147     // dereference a null pointer here
148     HbrHierarchicalEdit<T>* p = *face->GetHierarchicalEdits();
149     if (!p) return false;
150 
151     if (this == p) return true;
152 
153     if (faceid != p->faceid) return false;
154 
155     // If our path length is less than the face depth, it should mean
156     // that we're dealing with another face somewhere up the path, so
157     // we're not relevant
158     if (nsubfaces < face->GetDepth()) return false;
159 
160     if (memcmp(subfaces, p->subfaces, face->GetDepth() * sizeof(unsigned char)) != 0) {
161         return false;
162     }
163     return true;
164 }
165 
166 } // end namespace OPENSUBDIV_VERSION
167 using namespace OPENSUBDIV_VERSION;
168 
169 } // end namespace OpenSubdiv
170 
171 #endif /* OPENSUBDIV3_HBRHIERARCHICALEDIT_H */
172