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