Esempio n. 1
0
/*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);
}
Esempio n. 2
0
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)));
}