Skip to content

Create uniform b-spline patches with adaptive refinement #1292

@roquo

Description

@roquo

Hi there!

I am trying to create uniform b-spline patches with adaptive refinement. As an example, I took the catmark_torus an set a crease value to one of the inner circle edges.

Refiner:

  Sdc::SchemeType type = OpenSubdiv::Sdc::SCHEME_CATMARK;

  Sdc::Options options;
  options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);

  Descriptor desc;
  desc.numVertices = quadMesh.Vertices.size();
  desc.numFaces = quadMesh.Faces.size();
  desc.numVertsPerFace = quadMesh.VerticesPerFace.data();

  const auto* vec = static_cast<void*>(quadMesh.Faces.data());
  desc.vertIndicesPerFace = static_cast<const Far::Index*>(vec);
  desc.numCreases = 8;
  std::vector<int> crease_verts{1, 29, 29, 25, 25, 21, 21, 17, 17, 13, 13, 9, 9, 5, 5, 1};
  std::vector<float> crease_weights{3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f};
  desc.creaseVertexIndexPairs = crease_verts.data();
  desc.creaseWeights = crease_weights.data();

  // Instantiate a Far::TopologyRefiner from the descriptor.
  Far::TopologyRefiner* refiner = Far::TopologyRefinerFactory<Descriptor>::Create(
    desc, Far::TopologyRefinerFactory<Descriptor>::Options(type, options));

Code to create b-splines:

  int maxPatchLevel = 3;

  Far::PatchTableFactory::Options patchOptions(maxPatchLevel);
  patchOptions.SetPatchPrecision<Real>();
  patchOptions.useInfSharpPatch = true;
  patchOptions.generateVaryingTables = false;
  patchOptions.endCapType = Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS;

  // Initialize corresonding options for adaptive refinement:
  Far::TopologyRefiner::AdaptiveOptions adaptiveOptions = patchOptions.GetRefineAdaptiveOptions();

  // Apply adaptive refinement and construct the associated PatchTable to
  // evaluate the limit surface:
  refiner->RefineAdaptive(adaptiveOptions);

  Far::PatchTable const* patchTable = Far::PatchTableFactory::Create(*refiner, patchOptions);

  // Compute the total number of points we need to evaluate the PatchTable.
  // Approximations at irregular or extraordinary features require the use
  // of additional points associated with the patches that are referred to
  // as "local points" (i.e. local to the PatchTable).
  int nRefinerVertices = refiner->GetNumVerticesTotal();
  int nLocalPoints = patchTable->GetNumLocalPoints();

  // Create a buffer to hold the position of the refined verts and
  // local points, then copy the coarse positions at the beginning.
  std::vector<Vertex> verts(nRefinerVertices + nLocalPoints);
  auto index = 0;
  for(auto& vertex : quadMesh.Vertices)
  {
    verts[index].point[0] = vertex[0];
    verts[index].point[1] = vertex[1];
    verts[index].point[2] = vertex[2];
    ++index;
  }
  //std::memcpy(&verts[0], quadMesh.Vertices.data(), quadMesh.Vertices.size() * 3 * sizeof(float));

  // Adaptive refinement may result in fewer levels than the max specified.
  int nRefinedLevels = refiner->GetNumLevels();

  // Interpolate vertex primvar data : they are the control vertices
  // of the limit patches (see tutorial_1_1 for details)
  Far::PrimvarRefinerReal<Real> primvarRefiner(*refiner);

  Vertex* src = &verts[0];
  for (int level = 1; level < nRefinedLevels; ++level)
  {
    Vertex* dst = src + refiner->GetLevel(level - 1).GetNumVertices();
    primvarRefiner.Interpolate(level, src, dst);
    src = dst;
  }

  // Evaluate local points from interpolated vertex primvars.
  if (nLocalPoints)
  {
    patchTable->GetLocalPointStencilTable<Real>()->UpdateValues(&verts[0], &verts[nRefinerVertices]);
  }

  // Create a Far::PatchMap to help locating patches in the table
  Far::PatchMap patchmap(*patchTable);

  // Create a Far::PtexIndices to help find indices of ptex faces.
  Far::PtexIndices ptexIndices(*refiner);
  
  int face = 0;
  for (auto& handle : patchmap._handles)
  {
    Far::ConstIndexArray cvs = patchTable->GetPatchVertices(handle);

    // tessellate b-spline
    // done with other library
  }

Then this is my result, I did draw in the actual borders for better visibility:
first

So the inner circle of the torus has got the crease as expected and the patches are getting smaller and are adaptively refined

What I need now is that the smallest adaptive refinement is globally uniformly applied. So at one border of a b-spline patch is also only one other patch. I tried to draw what I mean from the example above:
first

Is something like that possible with OpenSubdiv?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions