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