#include <algorithm>
#include <numeric>
#include <opensubdiv/far/stencilTable.h>
#include <vector>
#include "../vtr/types.hpp"
typedef OpenSubdiv::Far::StencilTable StencilTable;
typedef OpenSubdiv::Far::Stencil Stencil;
typedef OpenSubdiv::Vtr::Index Index;
class FloatValue
{
public:
float value;
FloatValue() : value(0.0f)
{
}
void Clear()
{
value = 0.0f;
}
void AddWithWeight(const FloatValue &src, float weight)
{
value += src.value * weight;
}
};
extern "C"
{
void StencilTable_destroy(StencilTable *st)
{
delete st;
}
int StencilTable_GetNumStencils(StencilTable *st)
{
return st->GetNumStencils();
}
int StencilTable_GetNumControlVertices(StencilTable *st)
{
return st->GetNumControlVertices();
}
Stencil StencilTable_GetStencil(StencilTable *st, Index i)
{
return st->GetStencil(i);
}
IntVectorRef StencilTable_GetSizes(StencilTable *st)
{
auto &v = st->GetSizes();
return IntVectorRef(v.data(), v.size());
}
IndexVectorRef StencilTable_GetOffsets(StencilTable *st)
{
auto &v = st->GetOffsets();
return IndexVectorRef(v.data(), v.size());
}
IndexVectorRef StencilTable_GetControlIndices(StencilTable *st)
{
auto &v = st->GetControlIndices();
return IndexVectorRef(v.data(), v.size());
}
FloatVectorRef StencilTable_GetWeights(StencilTable *st)
{
auto &v = st->GetWeights();
return FloatVectorRef(v.data(), v.size());
}
void StencilTable_UpdateValues(
StencilTable *st, const float *src, float *dst, int start, int end)
{
int numControlVerts = st->GetNumControlVertices();
int numStencils = st->GetNumStencils();
int actualNumControlVerts = numControlVerts;
if (numControlVerts == 0) {
const auto &indices = st->GetControlIndices();
if (!indices.empty()) {
actualNumControlVerts =
*std::max_element(indices.begin(), indices.end()) + 1;
}
}
std::vector<FloatValue> srcValues(actualNumControlVerts);
std::vector<FloatValue> dstValues(numStencils);
for (int i = 0; i < actualNumControlVerts; ++i) {
srcValues[i].value = src[i];
}
st->UpdateValues(srcValues.data(), dstValues.data(), start, end);
int actualStart = (start < 0) ? 0 : start;
int actualEnd = (end < 0 || end > numStencils) ? numStencils : end;
for (int i = actualStart; i < actualEnd; ++i) {
dst[i - actualStart] = dstValues[i].value;
}
}
}