Beispiel #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;
}
Beispiel #2
0
//------------------------------------------------------------------------------
static void
createOsdMesh(ShapeDesc const & shapeDesc, int level) {

    Shape * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme);

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

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

    g_orgPositions=shape->verts;
    g_positions.resize(g_orgPositions.size(), 0.0f);

    delete shape;

    float speed = g_particles ? g_particles->GetSpeed() : 0.2f;

    // save coarse topology (used for coarse mesh drawing)
    g_controlMeshDisplay.SetTopology(topologyRefiner->GetLevel(0));

    // create random varying color
    {
        int numCoarseVerts = topologyRefiner->GetLevel(0).GetNumVertices();
        g_varyingColors.resize(numCoarseVerts*3);
        createRandomColors(numCoarseVerts, 3, &g_varyingColors[0]);
    }

    Far::StencilTable const * vertexStencils = NULL;
    Far::StencilTable const * varyingStencils = NULL;
    int nverts=0;

    {
        bool adaptive = (sdctype == OpenSubdiv::Sdc::SCHEME_CATMARK);
        if (adaptive) {
            // Apply feature adaptive refinement to the mesh so that we can use the
            // limit evaluation API features.
            Far::TopologyRefiner::AdaptiveOptions options(level);
            topologyRefiner->RefineAdaptive(options);
        } else {
            Far::TopologyRefiner::UniformOptions options(level);
            topologyRefiner->RefineUniform(options);
        }

        // Generate stencil table to update the bi-cubic patches control
        // vertices after they have been re-posed (both for vertex & varying
        // interpolation)
        Far::StencilTableFactory::Options soptions;
        soptions.generateOffsets=true;
        soptions.generateIntermediateLevels=adaptive;

        vertexStencils =
            Far::StencilTableFactory::Create(*topologyRefiner, soptions);

        soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING;

        varyingStencils =
            Far::StencilTableFactory::Create(*topologyRefiner, soptions);

        // Generate bi-cubic patch table for the limit surface
        Far::PatchTableFactory::Options poptions;
        if (g_endCap == kEndCapBSplineBasis) {
            poptions.SetEndCapType(
                Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
        } else {
            poptions.SetEndCapType(
                Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
        }

        Far::PatchTable const * patchTable =
            Far::PatchTableFactory::Create(*topologyRefiner, poptions);

        // append local points stencils
        if (Far::StencilTable const *localPointStencilTable =
            patchTable->GetLocalPointStencilTable()) {
            Far::StencilTable const *table =
                Far::StencilTableFactory::AppendLocalPointStencilTable(
                    *topologyRefiner, vertexStencils, localPointStencilTable);
            delete vertexStencils;
            vertexStencils = table;
        }
        if (Far::StencilTable const *localPointVaryingStencilTable =
            patchTable->GetLocalPointVaryingStencilTable()) {
            Far::StencilTable const *table =
                Far::StencilTableFactory::AppendLocalPointStencilTable(
                    *topologyRefiner,
                    varyingStencils, localPointVaryingStencilTable);
            delete varyingStencils;
            varyingStencils = table;
        }

        // total number of vertices = coarse verts + refined verts + gregory basis verts
        nverts = vertexStencils->GetNumControlVertices() +
            vertexStencils->GetNumStencils();

        if (g_patchTable) delete g_patchTable;
        g_patchTable = patchTable;
    }

    // note that for patch eval we need coarse+refined combined buffer.
    int nCoarseVertices = topologyRefiner->GetLevel(0).GetNumVertices();

    // In following template instantiations, same type of vertex buffers are
    // used for both source and destination (first and second template
    // parameters), since we'd like to draw control mesh wireframe too in
    // this example viewer.
    // If we don't need to draw the coarse control mesh, the src buffer doesn't
    // have to be interoperable to GL (it can be CpuVertexBuffer etc).

    delete g_evalOutput;
    if (g_kernel == kCPU) {
        g_evalOutput = new EvalOutput<Osd::CpuGLVertexBuffer,
                                      Osd::CpuGLVertexBuffer,
                                      Far::StencilTable,
                                      Osd::CpuPatchTable,
                                      Osd::CpuEvaluator>
            (vertexStencils, varyingStencils,
             nCoarseVertices, nverts, g_nParticles, g_patchTable);
#ifdef OPENSUBDIV_HAS_OPENMP
    } else if (g_kernel == kOPENMP) {
        g_evalOutput = new EvalOutput<Osd::CpuGLVertexBuffer,
                                      Osd::CpuGLVertexBuffer,
                                      Far::StencilTable,
                                      Osd::CpuPatchTable,
                                      Osd::OmpEvaluator>
            (vertexStencils, varyingStencils,
            nCoarseVertices, nverts, g_nParticles, g_patchTable);
#endif
#ifdef OPENSUBDIV_HAS_TBB
    } else if (g_kernel == kTBB) {
        g_evalOutput = new EvalOutput<Osd::CpuGLVertexBuffer,
                                      Osd::CpuGLVertexBuffer,
                                      Far::StencilTable,
                                      Osd::CpuPatchTable,
                                      Osd::TbbEvaluator>
            (vertexStencils, varyingStencils,
            nCoarseVertices, nverts, g_nParticles, g_patchTable);
#endif
#ifdef OPENSUBDIV_HAS_CUDA
    } else if (g_kernel == kCUDA) {
        g_evalOutput = new EvalOutput<Osd::CudaGLVertexBuffer,
                                      Osd::CudaGLVertexBuffer,
                                      Osd::CudaStencilTable,
                                      Osd::CudaPatchTable,
                                      Osd::CudaEvaluator>
            (vertexStencils, varyingStencils,
            nCoarseVertices, nverts, g_nParticles, g_patchTable);
#endif
#ifdef OPENSUBDIV_HAS_OPENCL
    } else if (g_kernel == kCL) {
        static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
        g_evalOutput = new EvalOutput<Osd::CLGLVertexBuffer,
                                      Osd::CLGLVertexBuffer,
                                      Osd::CLStencilTable,
                                      Osd::CLPatchTable,
                                      Osd::CLEvaluator,
                                      CLDeviceContext>
            (vertexStencils, varyingStencils,
            nCoarseVertices, nverts, g_nParticles, g_patchTable,
            &clEvaluatorCache, &g_clDeviceContext);
#endif
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
    } else if (g_kernel == kGLXFB) {
        static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
        g_evalOutput = new EvalOutput<Osd::GLVertexBuffer,
                                      Osd::GLVertexBuffer,
                                      Osd::GLStencilTableTBO,
                                      Osd::GLPatchTable,
                                      Osd::GLXFBEvaluator>
            (vertexStencils, varyingStencils,
             nCoarseVertices, nverts, g_nParticles, g_patchTable,
             &glXFBEvaluatorCache);
#endif
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
    } else if (g_kernel == kGLCompute) {
        static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
        g_evalOutput = new EvalOutput<Osd::GLVertexBuffer,
                                      Osd::GLVertexBuffer,
                                      Osd::GLStencilTableSSBO,
                                      Osd::GLPatchTable,
                                      Osd::GLComputeEvaluator>
            (vertexStencils, varyingStencils,
             nCoarseVertices, nverts, g_nParticles, g_patchTable,
             &glComputeEvaluatorCache);
#endif
    }

    // Create the 'uv particles' manager - this class manages the limit
    // location samples (ptex face index, (s,t) and updates them between frames.
    // Note: the number of limit locations can be entirely arbitrary
    delete g_particles;
    g_particles = new STParticles(*topologyRefiner, g_patchTable,
                                  g_nParticles, !g_randomStart);
    g_nParticles = g_particles->GetNumParticles();
    g_particles->SetSpeed(speed);

    g_prevTime = -1;
    g_currentTime = 0;

    updateGeom();

    delete topologyRefiner;
}