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_HBRVERTEXEDIT_H
26 #define OPENSUBDIV3_HBRVERTEXEDIT_H
27 
28 #include <algorithm>
29 #include "../hbr/hierarchicalEdit.h"
30 
31 #include "../version.h"
32 
33 namespace OpenSubdiv {
34 namespace OPENSUBDIV_VERSION {
35 
36 template <class T> class HbrVertexEdit;
37 
38 template <class T>
39 std::ostream& operator<<(std::ostream& out, const HbrVertexEdit<T>& path) {
40     out << "vertex path = (" << path.faceid << ' ';
41     for (int i = 0; i < path.nsubfaces; ++i) {
42         out << static_cast<int>(path.subfaces[i]) << ' ';
43     }
44     return out << static_cast<int>(path.vertexid) << "), edit = (" << path.edit[0] << ',' << path.edit[1] << ',' << path.edit[2] << ')';
45 }
46 
47 template <class T>
48 class HbrVertexEdit : public HbrHierarchicalEdit<T> {
49 
50 public:
51 
HbrVertexEdit(int _faceid,int _nsubfaces,unsigned char * _subfaces,unsigned char _vertexid,int _index,int _width,bool _isP,typename HbrHierarchicalEdit<T>::Operation _op,float * _edit)52     HbrVertexEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
53         : HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
54         edit = new float[width];
55         memcpy(edit, _edit, width * sizeof(float));
56     }
57 
HbrVertexEdit(int _faceid,int _nsubfaces,int * _subfaces,int _vertexid,int _index,int _width,bool _isP,typename HbrHierarchicalEdit<T>::Operation _op,float * _edit)58     HbrVertexEdit(int _faceid, int _nsubfaces, int *_subfaces, int _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
59         : HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(static_cast<unsigned char>(_vertexid)), index(_index), width(_width), isP(_isP), op(_op) {
60         edit = new float[width];
61         memcpy(edit, _edit, width * sizeof(float));
62     }
63 
~HbrVertexEdit()64     virtual ~HbrVertexEdit() {
65         delete[] edit;
66     }
67 
68     // Return the vertex id (the last element in the path)
GetVertexID()69     unsigned char GetVertexID() const { return vertexid; }
70 
71     friend std::ostream& operator<< <T> (std::ostream& out, const HbrVertexEdit<T>& path);
72 
73     // Return index of variable this edit applies to
GetIndex()74     int GetIndex() const { return index; }
75 
76     // Return width of the variable
GetWidth()77     int GetWidth() const { return width; }
78 
79     // Get the numerical value of the edit
GetEdit()80     const float* GetEdit() const { return edit; }
81 
82     // Get the type of operation
GetOperation()83     typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
84 
ApplyEditToFace(HbrFace<T> * face)85     virtual void ApplyEditToFace(HbrFace<T>* face) {
86         if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
87             // Tags the vertex as being edited; it'll figure out what to
88             // when GuaranteeNeighbor is called
89             face->GetVertex(vertexid)->SetVertexEdit();
90         }
91         // In any event, mark the face as having a vertex edit (which
92         // may only be applied on subfaces)
93         face->MarkVertexEdits();
94     }
95 
ApplyEditToVertex(HbrFace<T> * face,HbrVertex<T> * vertex)96     virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
97         if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
98                 face->GetVertex(vertexid) == vertex) {
99             vertex->GetData().ApplyVertexEdit(*const_cast<const HbrVertexEdit<T>*>(this));
100         }
101     }
102 
103 #ifdef PRMAN
ApplyToBound(struct bbox & bbox,RtMatrix * mx)104     virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) const {
105         if (isP) {
106             struct xyz p = *(struct xyz*)edit;
107             if (mx)
108                 MxTransformByMatrix(&p, &p, *mx, 1);
109             if (op == HbrHierarchicalEdit<T>::Set) {
110                 bbox.min.x = std::min(bbox.min.x, p.x);
111                 bbox.min.y = std::min(bbox.min.y, p.y);
112                 bbox.min.z = std::min(bbox.min.z, p.z);
113                 bbox.max.x = std::max(bbox.max.x, p.x);
114                 bbox.max.y = std::max(bbox.max.y, p.y);
115                 bbox.max.z = std::max(bbox.max.z, p.z);
116             } else if (op == HbrHierarchicalEdit<T>::Add ||
117                        op == HbrHierarchicalEdit<T>::Subtract) {
118                 bbox.min.x -= fabsf(p.x);
119                 bbox.min.y -= fabsf(p.y);
120                 bbox.min.z -= fabsf(p.z);
121                 bbox.max.x += fabsf(p.x);
122                 bbox.max.y += fabsf(p.y);
123                 bbox.max.z += fabsf(p.z);
124             }
125         }
126     }
127 #endif
128 
129 private:
130     const unsigned char vertexid;
131     int index;
132     int width;
133     unsigned isP:1;
134     typename HbrHierarchicalEdit<T>::Operation op;
135     float* edit;
136 };
137 
138 template <class T>
139 class HbrMovingVertexEdit : public HbrHierarchicalEdit<T> {
140 
141 public:
142 
HbrMovingVertexEdit(int _faceid,int _nsubfaces,unsigned char * _subfaces,unsigned char _vertexid,int _index,int _width,bool _isP,typename HbrHierarchicalEdit<T>::Operation _op,float * _edit)143     HbrMovingVertexEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
144         : HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
145         edit = new float[width * 2];
146         memcpy(edit, _edit, 2 * width * sizeof(float));
147     }
148 
HbrMovingVertexEdit(int _faceid,int _nsubfaces,int * _subfaces,int _vertexid,int _index,int _width,bool _isP,typename HbrHierarchicalEdit<T>::Operation _op,float * _edit)149     HbrMovingVertexEdit(int _faceid, int _nsubfaces, int *_subfaces, int _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
150         : HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
151         edit = new float[width * 2];
152         memcpy(edit, _edit, 2 * width * sizeof(float));
153     }
154 
~HbrMovingVertexEdit()155     virtual ~HbrMovingVertexEdit() {
156         delete[] edit;
157     }
158 
159     // Return the vertex id (the last element in the path)
GetVertexID()160     unsigned char GetVertexID() const { return vertexid; }
161 
162     friend std::ostream& operator<< <T> (std::ostream& out, const HbrVertexEdit<T>& path);
163 
164     // Return index of variable this edit applies to
GetIndex()165     int GetIndex() const { return index; }
166 
167     // Return width of the variable
GetWidth()168     int GetWidth() const { return width; }
169 
170     // Get the numerical value of the edit
GetEdit()171     const float* GetEdit() const { return edit; }
172 
173     // Get the type of operation
GetOperation()174     typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
175 
ApplyEditToFace(HbrFace<T> * face)176     virtual void ApplyEditToFace(HbrFace<T>* face) {
177         if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
178             // Tags the vertex as being edited; it'll figure out what to
179             // when GuaranteeNeighbor is called
180             face->GetVertex(vertexid)->SetVertexEdit();
181         }
182         // In any event, mark the face as having a vertex edit (which
183         // may only be applied on subfaces)
184         face->MarkVertexEdits();
185     }
186 
ApplyEditToVertex(HbrFace<T> * face,HbrVertex<T> * vertex)187     virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
188         if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
189                 face->GetVertex(vertexid) == vertex) {
190             vertex->GetData().ApplyMovingVertexEdit(*const_cast<const HbrMovingVertexEdit<T>*>(this));
191         }
192     }
193 
194 #ifdef PRMAN
ApplyToBound(struct bbox & bbox,RtMatrix * mx)195     virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) const {
196         if (isP) {
197             struct xyz p1 = *(struct xyz*)edit;
198             struct xyz p2 = *(struct xyz*)&edit[3];
199             if (mx) {
200                 MxTransformByMatrix(&p1, &p1, *mx, 1);
201                 MxTransformByMatrix(&p2, &p2, *mx, 1);
202             }
203             if (op == HbrVertexEdit<T>::Set) {
204                 bbox.min.x = std::min(std::min(bbox.min.x, p1.x), p2.x);
205                 bbox.min.y = std::min(std::min(bbox.min.y, p1.y), p2.y);
206                 bbox.min.z = std::min(std::min(bbox.min.z, p1.z), p2.z);
207                 bbox.max.x = std::max(std::max(bbox.max.x, p1.x), p2.x);
208                 bbox.max.y = std::max(std::max(bbox.max.y, p1.y), p2.y);
209                 bbox.max.z = std::max(std::max(bbox.max.z, p1.z), p2.z);
210             } else if (op == HbrVertexEdit<T>::Add ||
211                        op == HbrVertexEdit<T>::Subtract) {
212                 float maxx = std::max(fabsf(p1.x), fabsf(p2.x));
213                 float maxy = std::max(fabsf(p1.y), fabsf(p2.y));
214                 float maxz = std::max(fabsf(p1.z), fabsf(p2.z));
215                 bbox.min.x -= maxx;
216                 bbox.min.y -= maxy;
217                 bbox.min.z -= maxz;
218                 bbox.max.x += maxx;
219                 bbox.max.y += maxy;
220                 bbox.max.z += maxz;
221             }
222         }
223     }
224 #endif
225 
226 private:
227     const unsigned char vertexid;
228     int index;
229     int width;
230     unsigned isP:1;
231     typename HbrHierarchicalEdit<T>::Operation op;
232     float* edit;
233 };
234 
235 
236 } // end namespace OPENSUBDIV_VERSION
237 using namespace OPENSUBDIV_VERSION;
238 
239 } // end namespace OpenSubdiv
240 
241 #endif /* OPENSUBDIV3_HBRVERTEXEDIT_H */
242