Example #1
0
//------------------------------------------------------------------------------
static int 
checkMeshCPU( OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex>* farmesh,
              const std::vector<float>& coarseverts,
              xyzmesh * refmesh,
              const std::vector<int>& remap) {
                  
    static OpenSubdiv::OsdCpuComputeController *controller = new OpenSubdiv::OsdCpuComputeController();
    
    OpenSubdiv::OsdCpuComputeContext *context = OpenSubdiv::OsdCpuComputeContext::Create(farmesh->GetSubdivisionTables(), farmesh->GetVertexEditTables());
    
    OpenSubdiv::OsdCpuVertexBuffer * vb = OpenSubdiv::OsdCpuVertexBuffer::Create(3, farmesh->GetNumVertices());
    
    vb->UpdateData( & coarseverts[0], 0, (int)coarseverts.size()/3 );
    
    controller->Refine( context, farmesh->GetKernelBatches(), vb );
    
    return checkVertexBuffer(refmesh, vb->BindCpuBuffer(), vb->GetNumElements(), remap);
}
void
OsdMeshData::updateGeometry(const MHWRender::MVertexBuffer *points, const MHWRender::MVertexBuffer *normals)
{
    // Update coarse vertex
    if (!_positionBuffer) return;
    if (!_normalBuffer) return;

    int nCoarsePoints = _pointArray.length();

    OpenSubdiv::OsdCpuVertexBuffer *cpuPos = dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer*>(_positionBuffer);
    OpenSubdiv::OsdCpuVertexBuffer *cpuNormal = dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer*>(_normalBuffer);

    if (cpuPos) {
        // I know, this is very inefficient...
        float *d_pos = cpuPos->GetCpuBuffer();
        float *d_normal = cpuNormal->GetCpuBuffer();

        glBindBuffer(GL_ARRAY_BUFFER, *(GLuint*)points->resourceHandle());
        glGetBufferSubData(GL_ARRAY_BUFFER, 0, nCoarsePoints*3*sizeof(float), d_pos);
        glBindBuffer(GL_ARRAY_BUFFER, *(GLuint*)normals->resourceHandle());
        glGetBufferSubData(GL_ARRAY_BUFFER, 0, nCoarsePoints*3*sizeof(float), d_normal);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    } else {
        glBindBuffer(GL_COPY_READ_BUFFER, *(GLuint*)points->resourceHandle());
        glBindBuffer(GL_COPY_WRITE_BUFFER, _positionBuffer->GetGpuBuffer());
        glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, nCoarsePoints*3*sizeof(float));
        
        glBindBuffer(GL_COPY_READ_BUFFER, *(GLuint*)normals->resourceHandle());
        glBindBuffer(GL_COPY_WRITE_BUFFER, _normalBuffer->GetGpuBuffer());
        glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, nCoarsePoints*3*sizeof(float));
        
        glBindBuffer(GL_COPY_READ_BUFFER, 0);
        glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
    }

    _osdmesh->Subdivide(_positionBuffer, NULL);
    _osdmesh->Subdivide(_normalBuffer, NULL);

    _needsUpdate = false;
}
Example #3
0
//------------------------------------------------------------------------------
int checkMesh( char const * msg, char const * shape, int levels, Scheme scheme=kCatmark ) {

    int result =0;

    printf("- %s (scheme=%d)\n", msg, scheme);

    xyzmesh * refmesh = simpleHbr<xyzVV>(shape, scheme, 0);

    refine( refmesh, levels );


    std::vector<float> coarseverts;

    OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, coarseverts);

    OpenSubdiv::OsdMesh * omesh = new OpenSubdiv::OsdMesh();


    std::vector<int> remap;

    {
        omesh->Create(hmesh, levels, (int)OpenSubdiv::OsdKernelDispatcher::kCPU, /* exact= */ 0, &remap);

        OpenSubdiv::OsdCpuVertexBuffer * vb =
            dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer *>(omesh->InitializeVertexBuffer(3));

        vb->UpdateData( & coarseverts[0], (int)coarseverts.size()/3 );

        omesh->Subdivide( vb, NULL );

        omesh->Synchronize();

        checkVertexBuffer(refmesh, vb, remap);
    }

    delete hmesh;

    return result;
}
Example #4
0
// ====================================
// Compute
// ====================================
//
//  Description:
//      This method computes the value of the given output plug based
//      on the values of the input attributes.
//
//  Arguments:
//      plug - the plug to compute
//      data - object that provides access to the attributes for this node
//
MStatus OsdPolySmooth::compute( const MPlug& plug, MDataBlock& data ) {

    MStatus returnStatus;

    // Check which output attribute we have been asked to compute.  If this
    // node doesn't know how to compute it, we must return
    // MS::kUnknownParameter.
    //
    if( plug == a_output ) {
        bool createdSubdMesh = false;

        int subdivisionLevel = data.inputValue(a_subdivisionLevels).asInt();
        short stateH = data.inputValue(state).asShort();

        if ((subdivisionLevel > 0) and (stateH !=1)) {

            // == Retrieve input mesh ====================================
            // Get attr values
            MObject inMeshObj        = data.inputValue(a_inputPolymesh).asMesh();
            short vertBoundaryMethod = data.inputValue(a_vertBoundaryMethod).asShort();
            short fvarBoundaryMethod = data.inputValue(a_fvarBoundaryMethod).asShort();
            bool  fvarPropCorners    = data.inputValue(a_fvarPropagateCorners).asBool();
            bool  smoothTriangles    = data.inputValue(a_smoothTriangles).asBool();
            short creaseMethodVal    = data.inputValue(a_creaseMethod).asShort();

            // Convert attr values to OSD enums
            HMesh::InterpolateBoundaryMethod vertInterpBoundaryMethod =
                ConvertMayaBoundaryMethodShortToOsdInterpolateBoundaryMethod(vertBoundaryMethod);

            HMesh::InterpolateBoundaryMethod fvarInterpBoundaryMethod =
                ConvertMayaBoundaryMethodShortToOsdInterpolateBoundaryMethod(fvarBoundaryMethod);

            HCatmark::CreaseSubdivision creaseMethod =
                (creaseMethodVal == k_creaseMethod_chaikin) ?
                    HCatmark::k_CreaseChaikin : HCatmark::k_CreaseNormal;

            HCatmark::TriangleSubdivision triangleSubdivision =
                smoothTriangles ? HCatmark::k_New : HCatmark::k_Normal;

            // == Get Mesh Functions and Iterators ==========================
            MFnMeshData inMeshDat(inMeshObj);
            MFnMesh inMeshFn(inMeshObj, &returnStatus);
            MCHECKERR(returnStatus, "ERROR getting inMeshFn\n");
            MItMeshPolygon inMeshItPolygon(inMeshObj, &returnStatus);
            MCHECKERR(returnStatus, "ERROR getting inMeshItPolygon\n");

            // == Convert MFnMesh to OpenSubdiv =============================
            // Create the hbrMesh
            // Note: These fvar values only need to be kept alive through the life of the farMesh
            std::vector<int> fvarIndices;
            std::vector<int> fvarWidths;

            HMesh *hbrMesh = createOsdHbrFromPoly(
                inMeshFn, inMeshItPolygon, fvarIndices, fvarWidths);
            assert(hbrMesh);

            // Create the farMesh if successfully created the hbrMesh

            if (hbrMesh) {
                // Set Boundary methods and other hbr paramters
                hbrMesh->SetInterpolateBoundaryMethod( vertInterpBoundaryMethod );
                hbrMesh->SetFVarInterpolateBoundaryMethod( fvarInterpBoundaryMethod );
                hbrMesh->SetFVarPropagateCorners(fvarPropCorners);
                hbrMesh->GetSubdivision()->SetCreaseSubdivisionMethod(creaseMethod);

                // Set HBR Catmark Subdivision parameters
                HCatmark *catmarkSubdivision = dynamic_cast<HCatmark *>(hbrMesh->GetSubdivision());
                if (catmarkSubdivision) {
                    catmarkSubdivision->SetTriangleSubdivisionMethod(triangleSubdivision);
                }

                // Finalize subd calculations -- apply boundary interpolation rules and resolves singular verts, etc.
                // NOTE: This HAS to be called after all HBR parameters are set
                hbrMesh->Finish();

                int ncoarseverts = hbrMesh->GetNumVertices();

                // Create a FarMesh from the HBR mesh and pass into
                // It will be owned by the OsdMesh and deleted in the ~OsdMesh()
                FMeshFactory meshFactory(hbrMesh, subdivisionLevel, false);

                FMesh *farMesh = meshFactory.Create((hbrMesh->GetTotalFVarWidth() > 0));

                // == Setup OSD Data Structures =========================
                int numVertexElements  = 3; // only track vertex positions
                int numVaryingElements = 0; // XXX Future: Revise to include varying ColorSets
                int numVertices = inMeshFn.numVertices();

                int numFarVerts = farMesh->GetNumVertices();

                static OpenSubdiv::OsdCpuComputeController computeController = OpenSubdiv::OsdCpuComputeController();

                OpenSubdiv::OsdCpuComputeController::ComputeContext *computeContext =
                    OpenSubdiv::OsdCpuComputeController::ComputeContext::Create(farMesh);

                OpenSubdiv::OsdCpuVertexBuffer *vertexBuffer =
                    OpenSubdiv::OsdCpuVertexBuffer::Create(numVertexElements, numFarVerts );

                OpenSubdiv::OsdCpuVertexBuffer *varyingBuffer =
                    (numVaryingElements) ? OpenSubdiv::OsdCpuVertexBuffer::Create(numVaryingElements, numFarVerts) : NULL;

                // == UPDATE VERTICES (can be done after farMesh generated from topology) ==
                float const * vertex3fArray = inMeshFn.getRawPoints(&returnStatus);
                vertexBuffer->UpdateData(vertex3fArray, 0, numVertices );

                // Hbr dupes singular vertices during Mesh::Finish() - we need
                // to duplicate their positions in the vertex buffer.
                if (ncoarseverts > numVertices) {

                    MIntArray polyverts;

                    for (int i=numVertices; i<ncoarseverts; ++i) {

                        HVertex const * v = hbrMesh->GetVertex(i);

                        HFace const * f = v->GetIncidentEdge()->GetFace();

                        int vidx = -1;
                        for (int j=0; j<f->GetNumVertices(); ++j) {
                            if (f->GetVertex(j)==v) {
                                vidx = j;
                                break;
                            }
                        }
                        assert(vidx>-1);

                        inMeshFn.getPolygonVertices(f->GetID(), polyverts);

                        int vert = polyverts[vidx];

                        vertexBuffer->UpdateData(&vertex3fArray[0]+vert*numVertexElements, i, 1);
                    }
                }

                // == Delete HBR
                // Can now delete the hbrMesh as we will only be referencing the farMesh from this point on
                delete hbrMesh;
                hbrMesh = NULL;

                // == Subdivide OpenSubdiv mesh ==========================
                computeController.Refine(computeContext, farMesh->GetKernelBatches(), vertexBuffer, varyingBuffer);
                computeController.Synchronize();

                // == Convert subdivided OpenSubdiv mesh to MFnMesh Data outputMesh =============

                // Create New Mesh Data Object
                MFnMeshData newMeshData;
                MObject     newMeshDataObj = newMeshData.create(&returnStatus);
                MCHECKERR(returnStatus, "ERROR creating outputData");

                // Create out mesh
                returnStatus = convertOsdFarToMayaMeshData(farMesh, vertexBuffer, subdivisionLevel, inMeshFn, newMeshDataObj);
                MCHECKERR(returnStatus, "ERROR convertOsdFarToMayaMesh");

                // Propagate objectGroups from inMesh to outMesh (for per-facet shading, etc)
                returnStatus = createSmoothMesh_objectGroups(inMeshDat, subdivisionLevel, newMeshData );

                // Write to output plug
                MDataHandle outMeshH = data.outputValue(a_output, &returnStatus);
                MCHECKERR(returnStatus, "ERROR getting polygon data handle\n");
                outMeshH.set(newMeshDataObj);

                // == Cleanup OSD ============================================
                // REVISIT: Re-add these deletes
                delete(vertexBuffer);
                delete(varyingBuffer);
                delete(computeContext);
                delete(farMesh);

                // note that the subd mesh was created (see the section below if !createdSubdMesh)
                createdSubdMesh = true;
            }
        }

        // Pass-through inMesh to outMesh if not created the subd mesh
        if (!createdSubdMesh) {
            MDataHandle outMeshH = data.outputValue(a_output, &returnStatus);
            returnStatus = outMeshH.copy(data.outputValue(a_inputPolymesh, &returnStatus));
            MCHECKERR(returnStatus, "ERROR getting polygon data handle\n");
        }

        // Clean up Maya Plugs
        data.setClean(plug);
    }
    else {
        // Unhandled parameter in this compute function, so return MS::kUnknownParameter
        // so it is handled in a parent compute() function.
        return MS::kUnknownParameter;
    }
    return MS::kSuccess;
}