/*virtual*/ void HdSt_Osd3Subdivision::RefineCPU(HdBufferSourceSharedPtr const &source, bool varying, void *vertexBuffer) { OpenSubdiv::Far::StencilTable const *stencilTable = varying ? _varyingStencils : _vertexStencils; if (!TF_VERIFY(stencilTable)) return; OpenSubdiv::Osd::CpuVertexBuffer *osdVertexBuffer = static_cast<OpenSubdiv::Osd::CpuVertexBuffer*>(vertexBuffer); int numElements = source->GetNumElements(); int stride = source->GetNumComponents(); // NOTE: in osd, GetNumElements() returns how many fields in a vertex // (i.e. 3 for XYZ, and 4 for RGBA) // in hydra, GetNumElements() returns how many vertices // (or faces, etc) in a buffer. We basically follow the hydra // convention in this file. TF_VERIFY(stride == osdVertexBuffer->GetNumElements()); // if the mesh has more vertices than that in use in topology (faceIndices), // we need to trim the buffer so that they won't overrun the coarse // vertex buffer which we allocated using the stencil table. // see HdSt_Osd3Subdivision::GetNumVertices() if (numElements > stencilTable->GetNumControlVertices()) { numElements = stencilTable->GetNumControlVertices(); } // filling coarse vertices osdVertexBuffer->UpdateData((const float*)source->GetData(), /*offset=*/0, numElements); // if there is no stencil (e.g. torus with adaptive refinement), // just return here if (stencilTable->GetNumStencils() == 0) return; // apply opensubdiv with CPU evaluator. OpenSubdiv::Osd::BufferDescriptor srcDesc(0, stride, stride); OpenSubdiv::Osd::BufferDescriptor dstDesc(numElements*stride, stride, stride); OpenSubdiv::Osd::CpuEvaluator::EvalStencils( osdVertexBuffer, srcDesc, osdVertexBuffer, dstDesc, stencilTable); }
HdBufferSourceSharedPtr _TriangulateFaceVarying(HdBufferSourceSharedPtr const &source, VtIntArray const &faceVertexCounts, VtIntArray const &holeFaces, bool flip, SdfPath const &id) { T const *srcPtr = reinterpret_cast<T const *>(source->GetData()); int numElements = source->GetNumElements(); // CPU face-varying triangulation bool invalidTopology = false; int numFVarValues = 0; int holeIndex = 0; int numHoleFaces = holeFaces.size(); for (int i = 0; i < faceVertexCounts.size(); ++i) { int nv = faceVertexCounts[i] - 2; if (nv < 1) { // skip degenerated face invalidTopology = true; } else if (holeIndex < numHoleFaces and holeFaces[holeIndex] == i) { // skip hole face ++holeIndex; } else { numFVarValues += 3 * nv; } } if (invalidTopology) { TF_WARN("degenerated face found [%s]", id.GetText()); invalidTopology = false; } VtArray<T> results(numFVarValues); // reset holeIndex holeIndex = 0; int dstIndex = 0; for (int i = 0, v = 0; i < faceVertexCounts.size(); ++i) { int nVerts = faceVertexCounts[i]; if (nVerts < 3) { // Skip degenerate faces. } else if (holeIndex < numHoleFaces and holeFaces[holeIndex] == i) { // Skip hole faces. ++holeIndex; } else { // triangulate. // apply same triangulation as index does for (int j=0; j < nVerts-2; ++j) { if (not _FanTriangulate(&results[dstIndex], srcPtr, v, j, numElements, flip)) { invalidTopology = true; } dstIndex += 3; } } v += nVerts; } if (invalidTopology) { TF_WARN("numVerts and verts are incosistent [%s]", id.GetText()); } return HdBufferSourceSharedPtr(new HdVtBufferSource( source->GetName(), VtValue(results))); }