Hi,
We're currently implementing a variable rate subdiv scheme for a renderer (where each coarse polygon is tessellated according to its screen appearance) using Far::PatchTable as in far_tutorial_5_1.
We've extended the tutorial for face varying data (uv texture coordinates), but this doesn't seem to generate the correct values. Specifically, the result does not seem to be smooth, and there some cracks between patches.
Is this supported in OSD, and is there something specific to do regarding face varying data?
Here is an indicative bit of code that represents what we do to handle face varying data:
unsigned channel = 0;
TopologyDescriptor::FVarChannel desc;
desc.numValues = nfvData;
desc.valueIndices = fvIndices.data ();
fvChannels.push_back (desc);
fvChannelsIndices.push_back (channel);
TopologyDescriptor descriptor = {};
descriptor.numVertices = numVertices;
descriptor.numFaces = numFaces;
descriptor.numVertsPerFace = numVertPerFace.data ();
descriptor.vertIndicesPerFace = vertIndicesPerFace.data ();
descriptor.numFVarChannels = fvChannels.size ();
descriptor.fvarChannels = fvChannels.data ();
PatchTableFactory::Options patchOptions (4);
patchOptions.SetPatchPrecision<float>();
patchOptions.generateVaryingTables = true;
patchOptions.generateVaryingLocalPoints = true;
patchOptions.generateFVarTables = true;
patchOptions.endCapType = PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
patchOptions.numFVarChannels = fvChannelsIndices.size ();
patchOptions.fvarChannelIndices = fvChannelsIndices.data ();
// This is adapted from lines 186-216 in far_tutorial_5_1.cpp
unsigned nRefinerVertices = refiner->GetNumFVarValuesTotal (channel);
unsigned nLocalPoints = patchTable->GetNumLocalPointsFaceVarying (channel);
std::vector<floatn<N>> facevar (nRefinerVertices + nLocalPoints);
std::memcpy (facevar.data (), fvData.data (), nfvData*N*sizeof (float));
Far::PrimvarRefinerReal<float> pvrefiner (*refiner);
floatn<N> *src = facevar.data ();
for (int level = 1; level < refiner->GetNumLevels (); ++level)
{
floatn<N> *dst = src+refiner->GetLevel (level-1).GetNumFVarValues (channel);
pvrefiner.InterpolateFaceVarying (level, src, dst, channel);
src = dst;
}
if (nLocalPoints > 0)
{
src = facevar.data ();
patchTable->GetLocalPointFaceVaryingStencilTable<float> ()->UpdateValues (src, src+nRefinerVertices, channel);
}
// This is adapted from lines 240-255 in far_tutorial_5_1.cpp
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
Far::ConstIndexArray cvs;
const Far::PatchTable::PatchHandle *handle = patchmap->FindPatch (patchId, u, v);
patchTable->EvaluateBasisFaceVarying (*handle, u, v, wP, wDu, wDv, wDuu, wDuv, wDvv, channel);
cvs = patchTable->GetPatchFVarValues (*handle, channel);
floatn<N> result (0);
for (int cv = 0; cv < cvs.size (); ++cv)
result.AddWithWeight (refined[cvs[cv]], wP[cv]);
I've put in bold the parts of the patch table prep and lookup that we adapted to face varying.
Sorry for the code dump, but I'm a bit lost here about what we do wrong.
Thanks,
Ben