From 9219b0fb00783dd1ab1ff9be23afa31934e90e86 Mon Sep 17 00:00:00 2001 From: barry Date: Wed, 12 Dec 2018 12:03:54 -0800 Subject: [PATCH] Fix Far::LimitStencilTableFactory issues with uniform refinement: - corrected stencil estimates according to the interpolation mode - removed the added error checking for the tables provided - use uniform vertex patches when varying interpolation specified --- opensubdiv/far/stencilTableFactory.cpp | 61 ++++++++++++++------------ 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/opensubdiv/far/stencilTableFactory.cpp b/opensubdiv/far/stencilTableFactory.cpp index b4cb88c6..04683420 100644 --- a/opensubdiv/far/stencilTableFactory.cpp +++ b/opensubdiv/far/stencilTableFactory.cpp @@ -436,16 +436,19 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, int fvarChannel = options.fvarChannel; // - // Quick sanity checks for given PatchTable and/or StencilTables -- more to - // come once a PatchTable is built and the number of local points known: + // Quick sanity checks for given PatchTable and/or StencilTables: // int nRefinedStencils = 0; if (uniform) { - nRefinedStencils = refiner.GetLevel(maxlevel).GetNumVertices(); - } else if (!interpolateFaceVarying) { - nRefinedStencils = refiner.GetNumVerticesTotal(); + // Uniform stencils must include at least the last level points: + nRefinedStencils = interpolateFaceVarying + ? refiner.GetLevel(maxlevel).GetNumFVarValues(fvarChannel) + : refiner.GetLevel(maxlevel).GetNumVertices(); } else { - nRefinedStencils = refiner.GetNumFVarValuesTotal(fvarChannel); + // Adaptive stencils must include at least all refined points: + nRefinedStencils = interpolateFaceVarying + ? refiner.GetNumFVarValuesTotal(fvarChannel) + : refiner.GetNumVerticesTotal(); } if (cvStencilsIn && (cvStencilsIn->GetNumStencils() < nRefinedStencils)) { // Too few stencils in given StencilTable @@ -474,7 +477,6 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, stencilTableOptions.fvarChannel = options.fvarChannel; cvstencils = StencilTableFactoryReal::Create(refiner, stencilTableOptions); - assert(cvstencils->GetNumStencils() == nRefinedStencils); } // If an appropriate PatchTable was given, use it, otherwise, create a new one @@ -487,9 +489,11 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, // PatchTableFactory::Options patchTableOptions; patchTableOptions.SetPatchPrecision(); + patchTableOptions.includeBaseLevelIndices = true; patchTableOptions.generateVaryingTables = interpolateVarying; patchTableOptions.generateFVarTables = interpolateFaceVarying; if (interpolateFaceVarying) { + patchTableOptions.includeFVarBaseLevelIndices = true; patchTableOptions.numFVarChannels = 1; patchTableOptions.fvarChannelIndices = &fvarChannel; patchTableOptions.generateFVarLegacyLinearPatches = uniform || @@ -523,15 +527,6 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, refiner, refinedstencils, localstencils); } if (!cvStencilsIn) delete refinedstencils; - } else if (cvStencilsIn) { - int nLocalStencils = localstencils ? localstencils->GetNumStencils() : 0; - if (cvstencils->GetNumStencils() != (nRefinedStencils + nLocalStencils)) { - // Stencil count mismatch with PatchTable and given StencilTable - // (previously undetected and subject to crashing) - - if (!patchTableIn) delete patchtable; - return 0; - } } assert(patchtable && cvstencils); @@ -542,14 +537,24 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, // // Generate limit stencils for locations // - StencilBuilder builder(!interpolateFaceVarying - ? refiner.GetLevel(0).GetNumVertices() - : refiner.GetLevel(0).GetNumFVarValues(fvarChannel), + int nControlVertices = interpolateFaceVarying + ? refiner.GetLevel(0).GetNumFVarValues(fvarChannel) + : refiner.GetLevel(0).GetNumVertices(); + + StencilBuilder builder(nControlVertices, /*genControlVerts*/ false, /*compactWeights*/ true); typename StencilBuilder::Index origin(&builder, 0); typename StencilBuilder::Index dst = origin; + // + // Generally use the patches corresponding to the interpolation mode, but Uniform + // PatchTables do not have varying patches -- use the equivalent linear vertex + // patches in this case: + // + bool useVertexPatches = interpolateVertex || (interpolateVarying && uniform); + bool useFVarPatches = interpolateFaceVarying; + REAL wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20]; for (size_t i=0; i::Create(TopologyRefiner const & refiner, patchmap.FindPatch(array.ptexIdx, s, t); if (handle) { ConstIndexArray cvs; - if (interpolateVertex) { + if (useVertexPatches) { cvs = patchtable->GetPatchVertices(*handle); - } else if (interpolateFaceVarying) { + } else if (useFVarPatches) { cvs = patchtable->GetPatchFVarValues(*handle, fvarChannel); } else { cvs = patchtable->GetPatchVaryingVertices(*handle); @@ -576,10 +581,10 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, dst = origin[numLimitStencils]; if (options.generate2ndDerivatives) { - if (interpolateVertex) { + if (useVertexPatches) { patchtable->EvaluateBasis( *handle, s, t, wP, wDs, wDt, wDss, wDst, wDtt); - } else if (interpolateFaceVarying) { + } else if (useFVarPatches) { patchtable->EvaluateBasisFaceVarying( *handle, s, t, wP, wDs, wDt, wDss, wDst, wDtt, fvarChannel); } else { @@ -592,10 +597,10 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k], wDss[k], wDst[k], wDtt[k]); } } else if (options.generate1stDerivatives) { - if (interpolateVertex) { + if (useVertexPatches) { patchtable->EvaluateBasis( *handle, s, t, wP, wDs, wDt); - } else if (interpolateFaceVarying) { + } else if (useFVarPatches) { patchtable->EvaluateBasisFaceVarying( *handle, s, t, wP, wDs, wDt, 0, 0, 0, fvarChannel); } else { @@ -608,10 +613,10 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k]); } } else { - if (interpolateVertex) { + if (useVertexPatches) { patchtable->EvaluateBasis( *handle, s, t, wP); - } else if (interpolateFaceVarying) { + } else if (useFVarPatches) { patchtable->EvaluateBasisFaceVarying( *handle, s, t, wP, 0, 0, 0, 0, 0, fvarChannel); } else { @@ -642,7 +647,7 @@ LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, // Copy the proto-stencils into the limit stencil table // LimitStencilTableReal * result = new LimitStencilTableReal( - refiner.GetLevel(0).GetNumVertices(), + nControlVertices, builder.GetStencilOffsets(), builder.GetStencilSizes(), builder.GetStencilSources(),