Пример #1
0
//------------------------------------------------------------------------------
static void
createFarGLMesh(Shape * shape, int maxlevel) {

    Stopwatch s;
    s.Start();

    using namespace OpenSubdiv;

    // create Far mesh (topology)
    Sdc::SchemeType sdctype = GetSdcType(*shape);
    Sdc::Options    sdcoptions = GetSdcOptions(*shape);

    sdcoptions.SetFVarLinearInterpolation(g_fvarInterpolation);

    Far::TopologyRefiner * refiner =
        Far::TopologyRefinerFactory<Shape>::Create(*shape,
            Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));

    if (g_Adaptive) {
        Far::TopologyRefiner::AdaptiveOptions options(maxlevel);
        options.useSingleCreasePatch = false;
        refiner->RefineAdaptive(options);
    } else {
        Far::TopologyRefiner::UniformOptions options(maxlevel);
        options.fullTopologyInLastLevel = true;
        refiner->RefineUniform(options);
    }

    int numTotalVerts = refiner->GetNumVerticesTotal();

    //
    // Patch table
    //
    std::vector<Vertex> fvarBuffer;
    Far::PatchTable * patchTable = 0;
    bool createFVarWire = g_FarDrawFVarPatches or g_FarDrawFVarVerts;

    if (g_Adaptive) {
        Far::PatchTableFactory::Options options;
        options.generateFVarTables = createFVarWire;
        options.shareEndCapPatchPoints = false;

        patchTable =
            Far::PatchTableFactory::Create(*refiner, options);

        // increase vertex buffer for the additional local points
        if (patchTable->GetLocalPointStencilTable()) {
            numTotalVerts += patchTable->GetLocalPointStencilTable()->GetNumStencils();
        }

        g_numPatches = patchTable->GetNumPatchesTotal();
        g_maxValence = patchTable->GetMaxValence();

        if (createFVarWire) {

            // interpolate fvar values

            int channel = 0;

            // XXXX should use a (u,v) vertex class
            fvarBuffer.resize(refiner->GetNumFVarValuesTotal(channel), 0);
            Vertex * values = &fvarBuffer[0];

            int nCoarseValues = refiner->GetLevel(0).GetNumFVarValues(channel);

            for (int i=0; i<nCoarseValues; ++i) {
                float const * ptr = &shape->uvs[i*2];
                values[i].SetPosition(ptr[0],  ptr[1], 0.0f);
            }

            int lastLevel = refiner->GetMaxLevel();
            Vertex * src = values;
            for (int level = 1; level <= lastLevel; ++level) {
                Vertex * dst = src + refiner->GetLevel(level-1).GetNumFVarValues(channel);
                Far::PrimvarRefiner(*refiner).InterpolateFaceVarying(level, src, dst, channel);
                src = dst;
            }
        }
    }

    //
    // interpolate vertices
    //

    // create vertex primvar data buffer
    std::vector<Vertex> vertexBuffer(numTotalVerts);
    Vertex * verts = &vertexBuffer[0];

    // copy coarse vertices positions
    int ncoarseverts = shape->GetNumVertices();
    for (int i=0; i<ncoarseverts; ++i) {
        float * ptr = &shape->verts[i*3];
        verts[i].SetPosition(ptr[0], ptr[1], ptr[2]);
    }

    s.Start();
    if (g_useStencils) {
        //
        // Stencil interpolation
        //
        Far::StencilTable const * stencilTable = 0;
        Far::StencilTableFactory::Options options;
        options.generateOffsets=true;
        options.generateIntermediateLevels=true;
        stencilTable = Far::StencilTableFactory::Create(*refiner, options);

        // append local point stencils if needed
        if (patchTable and patchTable->GetLocalPointStencilTable()) {
            if (Far::StencilTable const * stencilTableWithLocalPoints =
                Far::StencilTableFactory::AppendLocalPointStencilTable(
                    *refiner, stencilTable,
                    patchTable->GetLocalPointStencilTable())) {
                delete stencilTable;
                stencilTable = stencilTableWithLocalPoints;
            }
        }

        //
        // apply stencils
        //
        stencilTable->UpdateValues(verts, verts + ncoarseverts);

        delete stencilTable;
    } else {
        //
        // TopologyRefiner interpolation
        //
        // populate buffer with Far interpolated vertex data
        int lastLevel = refiner->GetMaxLevel();
        Vertex * src = verts;
        for (int level = 1; level <= lastLevel; ++level) {
            Vertex * dst = src + refiner->GetLevel(level-1).GetNumVertices();
            Far::PrimvarRefiner(*refiner).Interpolate(level, src, dst);
            src = dst;
        }
        //printf("          %f ms (interpolate)\n", float(s.GetElapsed())*1000.0f);
        //printf("          %f ms (total)\n", float(s.GetTotalElapsed())*1000.0f);

        // TODO: endpatch basis conversion comes here
    }
    s.Stop();

    //
    // Misc display
    //

    //printf("Far time: %f ms (topology)\n", float(s.GetElapsed())*1000.0f);

    if (g_FarDrawVertIDs) {
        createVertNumbers(*refiner, vertexBuffer);
    }

    if (g_FarDrawFaceIDs) {
        createFaceNumbers(*refiner, vertexBuffer);
    }

    if (g_FarDrawPtexIDs and patchTable) {
        createPtexNumbers(*patchTable, vertexBuffer);
    }

    if (g_Adaptive) {
        createPatchNumbers(*patchTable, vertexBuffer);
    }

    if (g_Adaptive and g_FarDrawGregogyBasis) {
        createGregoryBasis(*patchTable, vertexBuffer);
    }

    if (g_Adaptive and createFVarWire) {
        createFVarPatches(*refiner, *patchTable, fvarBuffer);
        createFVarPatchNumbers(*patchTable, fvarBuffer);
    }

    createEdgeNumbers(*refiner, vertexBuffer, g_FarDrawEdgeIDs!=0, g_FarDrawEdgeSharpness!=0);

    GLMesh::Options options;
    options.vertColorMode=g_Adaptive ? GLMesh::VERTCOLOR_BY_LEVEL : GLMesh::VERTCOLOR_BY_SHARPNESS;
    options.edgeColorMode=g_Adaptive ? GLMesh::EDGECOLOR_BY_PATCHTYPE : GLMesh::EDGECOLOR_BY_SHARPNESS;
    options.faceColorMode=g_Adaptive ? GLMesh::FACECOLOR_BY_PATCHTYPE :GLMesh::FACECOLOR_SOLID;

    g_far_glmesh.Initialize(options, *refiner, patchTable, (float *)&verts[0]);
    if (g_Adaptive) {
        g_far_glmesh.SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f);
    } else {
        g_far_glmesh.SetDiffuseColor(0.75f, 0.9f, 1.0f, 1.0f);
    }


    //setFaceColors(*refiner);

    g_far_glmesh.InitializeDeviceBuffers();

    // save coarse topology (used for control mesh display)
    g_controlMeshDisplay.SetTopology(refiner->GetLevel(0));

    // save coarse points in a GPU buffer (used for control mesh display)
    if (not g_controlMeshDisplayVBO) {
        glGenBuffers(1, &g_controlMeshDisplayVBO);
    }
    glBindBuffer(GL_ARRAY_BUFFER, g_controlMeshDisplayVBO);
    glBufferData(GL_ARRAY_BUFFER,
                 3*sizeof(float)*vertexBuffer.size(), (GLfloat*)&vertexBuffer[0],
                 GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // compute model bounds
    float min[3] = { FLT_MAX,  FLT_MAX,  FLT_MAX};
    float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
    for (size_t i=0; i <vertexBuffer.size(); ++i) {
        for(int j=0; j<3; ++j) {
            float v = vertexBuffer[i].GetPos()[j];
            min[j] = std::min(min[j], v);
            max[j] = std::max(max[j], v);
        }
    }
    for (int j=0; j<3; ++j) {
        g_center[j] = (min[j] + max[j]) * 0.5f;
        g_size += (max[j]-min[j])*(max[j]-min[j]);
    }
    g_size = sqrtf(g_size);

    delete refiner;
    delete patchTable;
}
Пример #2
0
//------------------------------------------------------------------------------
int main(int, char **) {

    int maxlevel = 3;

    typedef Far::TopologyRefinerFactoryBase::TopologyDescriptor Descriptor;

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

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

    // Populate a topology descriptor with our raw data
    Descriptor desc;
    desc.numVertices  = g_nverts;
    desc.numFaces     = g_nfaces;
    desc.numVertsPerFace = g_vertsperface;
    desc.vertIndicesPerFace  = g_vertIndices;

    // Create a face-varying channel descriptor
    Descriptor::FVarChannel uvs;
    uvs.numValues = g_nuvs;
    uvs.valueIndices = g_uvIndices;

    // Add the channel topology to the main descriptor
    desc.numFVarChannels = 1;
    desc.fvarChannels = & uvs;

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

    // Uniformly refine the topolgy up to 'maxlevel'
    // note: fullTopologyInLastLevel must be true to work with face-varying data
    {
        Far::TopologyRefiner::UniformOptions options(maxlevel);
        options.fullTopologyInLastLevel = true;
        refiner->RefineUniform(options);
    }

    // Allocate & interpolate the 'vertex' primvar data (see tutorial 2 for
    // more details).
    std::vector<Vertex> vbuffer(refiner->GetNumVerticesTotal());
    Vertex * verts = &vbuffer[0];

    int nCoarseVerts = g_nverts;
    for (int i=0; i<nCoarseVerts; ++i) {
        verts[i].SetPosition(g_verts[i][0], g_verts[i][1], g_verts[i][2]);
    }

    refiner->Interpolate(verts, verts + nCoarseVerts);


    // Allocate & interpolate the 'face-varying' primvar data
    int channel = 0,
        nCoarseFVVerts = refiner->GetNumFVarValues(0, channel);

    std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel));
    FVarVertex * fvVerts = &fvBuffer[0];

    for (int i=0; i<g_nuvs; ++i) {
        fvVerts[i].u = g_uvs[i][0];
        fvVerts[i].v = g_uvs[i][1];
    }

    refiner->InterpolateFaceVarying(fvVerts, fvVerts + nCoarseFVVerts, channel);


    { // Output OBJ of the highest level refined -----------

        // Print vertex positions
        for (int level=0, firstVert=0; level<=maxlevel; ++level) {

            if (level==maxlevel) {
                for (int vert=0; vert<refiner->GetNumVertices(level); ++vert) {
                    float const * pos = verts[firstVert+vert].GetPosition();
                    printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
                }
            } else {
                firstVert += refiner->GetNumVertices(level);
            }
        }

        // Print uvs
        for (int level=0, firstVert=0; level<=maxlevel; ++level) {

            if (level==maxlevel) {
                for (int vert=0; vert<refiner->GetNumFVarValues(level, channel); ++vert) {
                    FVarVertex const & uv = fvVerts[firstVert+vert];
                    printf("vt %f %f\n", uv.u, uv.v);
                }
            } else {
                firstVert += refiner->GetNumFVarValues(level, channel);
            }
        }


        // Print faces
        for (int face=0; face<refiner->GetNumFaces(maxlevel); ++face) {

            Far::ConstIndexArray fverts = refiner->GetFaceVertices(maxlevel, face),
                                 fvverts = refiner->GetFVarFaceValues(maxlevel, face, channel);

            // all refined Catmark faces should be quads
            assert(fverts.size()==4 and fvverts.size()==4);

            printf("f ");
            for (int vert=0; vert<fverts.size(); ++vert) {
                // OBJ uses 1-based arrays...
                printf("%d/%d ", fverts[vert]+1, fvverts[vert]+1);
            }
            printf("\n");
        }
    }
}