// // Copyright 2013 Pixar // // Licensed under the terms set forth in the LICENSE.txt file available at // https://opensubdiv.org/license. // #ifndef OPENSUBDIV3_HBRFVARDATA_H #define OPENSUBDIV3_HBRFVARDATA_H #include #include #include "../version.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { template class HbrFVarEdit; template class HbrFace; template class HbrVertex; // This class implements a "face varying vector item". Really it's // just a smart wrapper around face varying data (itself just a bunch // of floats) stored on each vertex. template class HbrFVarData { private: HbrFVarData() : faceid(0), initialized(0) { } ~HbrFVarData() { Uninitialize(); } HbrFVarData(const HbrFVarData &/* data */) {} public: // Sets the face id void SetFaceID(int id) { faceid = id; } // Returns the id of the face to which this data is bound int GetFaceID() const { return faceid; } // Clears the initialized flag void Uninitialize() { initialized = 0; faceid = 0; } // Returns initialized flag bool IsInitialized() const { return initialized; } // Sets initialized flag void SetInitialized() { initialized = 1; } // Return the data from the NgpFVVector float* GetData(int item) { return data + item; } // Clears the indicates value of this item void Clear(int startindex, int width) { memset(data + startindex, 0, width * sizeof(float)); } // Clears all values of this item void ClearAll(int width) { initialized = 1; memset(data, 0, width * sizeof(float)); } // Set values of the indicated item (with the indicated weighing) // on this item void SetWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) { float *dst = data + startindex; const float *src = fvvi.data + startindex; for (int i = 0; i < width; ++i) { *dst++ = weight * *src++; } } // Add values of the indicated item (with the indicated weighing) // to this item void AddWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) { float *dst = data + startindex; const float *src = fvvi.data + startindex; for (int i = 0; i < width; ++i) { *dst++ += weight * *src++; } } // Add all values of the indicated item (with the indicated // weighing) to this item void AddWithWeightAll(const HbrFVarData& fvvi, int width, float weight) { float *dst = data; const float *src = fvvi.data; for (int i = 0; i < width; ++i) { *dst++ += weight * *src++; } } // Compare all values item against a float buffer. Returns true // if all values match bool CompareAll(int width, const float *values, float tolerance=0.0f) const { if (!initialized) return false; for (int i = 0; i < width; ++i) { if (fabsf(values[i] - data[i]) > tolerance) return false; } return true; } // Initializes data void SetAllData(int width, const float *values) { initialized = 1; memcpy(data, values, width * sizeof(float)); } // Compare this item against another item with tolerance. Returns // true if it compares identical bool Compare(const HbrFVarData& fvvi, int startindex, int width, float tolerance=0.0f) const { for (int i = 0; i < width; ++i) { if (fabsf(data[startindex + i] - fvvi.data[startindex + i]) > tolerance) return false; } return true; } // Modify the data of the item with an edit void ApplyFVarEdit(const HbrFVarEdit& edit); friend class HbrVertex; private: unsigned int faceid:31; unsigned int initialized:1; float data[1]; }; } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #include "../hbr/fvarEdit.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { template void HbrFVarData::ApplyFVarEdit(const HbrFVarEdit& edit) { float *dst = data + edit.GetIndex() + edit.GetOffset(); const float *src = edit.GetEdit(); for (int i = 0; i < edit.GetWidth(); ++i) { switch(edit.GetOperation()) { case HbrVertexEdit::Set: *dst++ = *src++; break; case HbrVertexEdit::Add: *dst++ += *src++; break; case HbrVertexEdit::Subtract: *dst++ -= *src++; } } initialized = 1; } } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* OPENSUBDIV3_HBRFVARDATA_H */