Example #1
0
static MStatus
convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
    std::vector<Vertex> const & refinedVerts,
    bool hasUVs, std::vector<FVarVertexUV> const & refinedUVs,
    bool hasColors, std::vector<FVarVertexColor> const & refinedColors,
    MFnMesh & inMeshFn, MObject newMeshDataObj) {

    MStatus status;

    typedef OpenSubdiv::Far::ConstIndexArray IndexArray;

    int maxlevel = refiner.GetMaxLevel();

    OpenSubdiv::Far::TopologyLevel const & refLastLevel 
                                                = refiner.GetLevel(maxlevel);

    int nfaces = refLastLevel.GetNumFaces();

    // Init Maya Data

    // Face Counts
    MIntArray faceCounts(nfaces);
    for (int face=0; face < nfaces; ++face) {
        faceCounts[face] = 4;
    }

    // Face Connects
    MIntArray faceConnects(nfaces*4);
    for (int face=0, idx=0; face < nfaces; ++face) {
        IndexArray fverts = refLastLevel.GetFaceVertices(face);
        for (int vert=0; vert < fverts.size(); ++vert) {
            faceConnects[idx++] = fverts[vert];
        }
    }

    // Points
    int nverts = refLastLevel.GetNumVertices();
    int firstOfLastVert = refiner.GetNumVerticesTotal() 
                        - nverts 
                        - refiner.GetLevel(0).GetNumVertices();

    MFloatPointArray points(nverts);
    for (int vIt = 0; vIt < nverts; ++vIt) {
        Vertex const & v = refinedVerts[firstOfLastVert + vIt];
        points.set(vIt, v.position[0], v.position[1], v.position[2]);
    }

    // Create New Mesh from MFnMesh
    MFnMesh newMeshFn;
    MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(),
        points, faceCounts, faceConnects, newMeshDataObj, &status);
    MCHECKERR(status, "Cannot create new mesh");

    // Get face-varying set names and other info from the inMesh
    MStringArray uvSetNames;
    MStringArray colorSetNames;
    std::vector<int> colorSetChannels;
    std::vector<MFnMesh::MColorRepresentation> colorSetReps;
    int totalColorSetChannels = 0;
    status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames,
        colorSetChannels, colorSetReps, totalColorSetChannels);

    // Add new UVs back to the mesh if needed
    if (hasUVs) {

        MIntArray fvarConnects(faceConnects.length());
        int count = 0;
        for (int f = 0; f < refLastLevel.GetNumFaces(); ++f) {
            IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELUV);
            for (int index = 0 ; index < faceIndices.size() ; ++index) {
                fvarConnects[count++] = faceIndices[index];
            }
        }

        int nuvs = refLastLevel.GetNumFVarValues(CHANNELUV);
        int firstOfLastUvs = refiner.GetNumFVarValuesTotal(CHANNELUV) 
                             - nuvs
                             - refiner.GetLevel(0).GetNumFVarValues(CHANNELUV);

        MFloatArray uCoord(nuvs), vCoord(nuvs);
        for (int uvIt = 0; uvIt < nuvs; ++uvIt) {
            FVarVertexUV const & uv = refinedUVs[firstOfLastUvs + uvIt];
            uCoord[uvIt] = uv.u;
            vCoord[uvIt] = uv.v;
        }

        // Currently, the plugin only supports one UV set
        int uvSetIndex = 0;
        if (uvSetIndex > 0) {
            status = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] );
            MCHECKERR(status, "Cannot create UVSet");
        }
        static MString defaultUVName("map1");
        MString const * uvname = uvSetIndex==0 ? 
            &defaultUVName : &uvSetNames[uvSetIndex];
        status = newMeshFn.setUVs(uCoord, vCoord, uvname);                  
        MCHECKERR(status, "Cannot set UVs for set : "+*uvname);

        status = newMeshFn.assignUVs(faceCounts, fvarConnects, uvname);     
        MCHECKERR(status, "Cannot assign UVs");
    }

    // Add new colors back to the mesh if needed
    if (hasColors) {

        int count = 0;
        MIntArray fvarConnects2(faceConnects.length());
        for (int f = 0 ; f < refLastLevel.GetNumFaces(); ++f) {
            IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELCOLOR);
            for (int index = 0 ; index < faceIndices.size() ; ++index) {
                fvarConnects2[count++] = faceIndices[index];
            }
        }
  
        int ncols = refLastLevel.GetNumFVarValues(CHANNELCOLOR);
        int firstOfLastCols = refiner.GetNumFVarValuesTotal(CHANNELCOLOR) 
                              - ncols
                              - refiner.GetLevel(0).GetNumFVarValues(CHANNELCOLOR);

        MColorArray colorArray(ncols);
        for (int colIt = 0; colIt < ncols; ++colIt) {
            FVarVertexColor const & c = refinedColors[firstOfLastCols + colIt];
            colorArray.set(colIt, c.r, c.g, c.b, c.a);
        }

        // Currently, the plugin only supports one color sets
        int colorSetIndex = 0;

        // Assign color buffer and map the ids for each face-vertex
        // API Limitation: Cannot set MColorRepresentation here
        status = newMeshFn.createColorSetDataMesh(
            colorSetNames[colorSetIndex]);                                
        MCHECKERR(status, "Cannot create ColorSet");

        bool isColorClamped = inMeshFn.isColorClamped(
            colorSetNames[colorSetIndex], &status);                   
        MCHECKERR(status, "Can not get Color Clamped ");

        status = newMeshFn.setIsColorClamped(
            colorSetNames[colorSetIndex], isColorClamped);                     
        MCHECKERR(status, "Can not set Color Clamped : " + isColorClamped);

        status = newMeshFn.setColors(
            colorArray, &colorSetNames[colorSetIndex], 
            colorSetReps[colorSetIndex]);   
        MCHECKERR(status, "Can not set Colors");

        status = newMeshFn.assignColors(
            fvarConnects2, &colorSetNames[colorSetIndex]);                          
        MCHECKERR(status, "Can not assign Colors");
    }

    return MS::kSuccess;
}
Example #2
0
//! Caller is expected to delete the returned value
static OpenSubdiv::Far::TopologyRefiner *
gatherTopology( MFnMesh & inMeshFn,
                MItMeshPolygon & inMeshItPolygon,
                OpenSubdiv::Sdc::SchemeType type,
                OpenSubdiv::Sdc::Options options,
                bool * hasUVs, bool * hasColors,
                std::vector<MFloatArray> & uvSet_uCoords,
                std::vector<MFloatArray> & uvSet_vCoords,
                std::vector<MColorArray> & colorSet_colors,
                float * maxCreaseSharpness=0 ) {

    MStatus returnStatus;

    // Gather FVarData
    MStringArray uvSetNames;
    MStringArray colorSetNames;
    std::vector<int> colorSetChannels;
    std::vector<MFnMesh::MColorRepresentation> colorSetReps;
    int totalColorSetChannels = 0;
    returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, 
                        colorSetChannels, colorSetReps, totalColorSetChannels);
    MWARNERR(returnStatus, "Failed to retrieve Maya face-varying parameters");

    // Storage for UVs and ColorSets for face-vertex
    MIntArray fvArray; // face vertex array
    uvSet_uCoords.clear();  uvSet_uCoords.resize(uvSetNames.length());
    uvSet_vCoords.clear();  uvSet_vCoords.resize(uvSetNames.length());
    colorSet_colors.clear();colorSet_colors.resize(colorSetNames.length());

    // Put the data in the format needed for OSD
    Descriptor desc;
    
    int numFaceVertices = inMeshFn.numFaceVertices();

    desc.numVertices = inMeshFn.numVertices();
    desc.numFaces = inMeshItPolygon.count();

    int * vertsPerFace = new int[desc.numFaces],
        * vertIndices = new int[numFaceVertices];

    desc.numVertsPerFace = vertsPerFace;
    desc.vertIndicesPerFace = vertIndices;

    // Create Topology
    for (inMeshItPolygon.reset(); !inMeshItPolygon.isDone(); inMeshItPolygon.next()) {

        inMeshItPolygon.getVertices(fvArray);
        int nverts = fvArray.length();

        vertsPerFace[inMeshItPolygon.index()] = nverts;

        for (int i=0; i<nverts; ++i) {
            *vertIndices++ = fvArray[i];
        }
    }

    // Add Face-Varying data to the descriptor
    Descriptor::FVarChannel * channels = NULL;
    *hasUVs = uvSet_uCoords.size() > 0 && uvSet_vCoords.size() > 0;
    *hasColors = colorSet_colors.size() > 0;

    // Note : Only supports 1 channel of UVs and 1 channel of color
    if (*hasUVs || *hasColors) {

        // Create 2 face-varying channel descriptor that will hold UVs and color
        desc.numFVarChannels = 2;
        channels = new Descriptor::FVarChannel[desc.numFVarChannels];
        desc.fvarChannels = channels;

        int * uvIndices = new int[numFaceVertices];
        channels[CHANNELUV].valueIndices = uvIndices;
        channels[CHANNELUV].numValues = 0;

        int * colorIndices = new int[numFaceVertices];
        channels[CHANNELCOLOR].valueIndices = colorIndices;
        channels[CHANNELCOLOR].numValues = 0;

        // Obtain UV information
        if (*hasUVs) {
            inMeshFn.getUVs(uvSet_uCoords[0], uvSet_vCoords[0], &uvSetNames[0]);
            assert( uvSet_uCoords[0].length() == uvSet_vCoords[0].length() );

            int uvId = 0, nUVs = 0;
            for (int faceIndex = 0; faceIndex < inMeshFn.numPolygons(); ++faceIndex)
            {
                int numVertices = inMeshFn.polygonVertexCount(faceIndex);
                for (int v = 0; v < numVertices; v++)
                {
                    inMeshFn.getPolygonUVid(faceIndex, v, uvId, &uvSetNames[0]);
                    uvIndices[nUVs++] = uvId;
                }
            }

            channels[CHANNELUV].numValues = uvSet_uCoords[0].length();
        }

        // Obtain color information
        if (*hasColors) {  
            inMeshFn.getColors(colorSet_colors[0], &colorSetNames[0]);

            int colorId = 0, nColors = 0;
            bool addDefaultColor = true;
            for (int faceIndex = 0; faceIndex < inMeshFn.numPolygons(); ++faceIndex)
            {
                int numVertices = inMeshFn.polygonVertexCount(faceIndex);
                for ( int v = 0 ; v < numVertices; v++ )
                {
                    inMeshFn.getColorIndex(faceIndex, v, colorId, &colorSetNames[0]);
                    if (colorId == -1)
                    {
                        if (addDefaultColor)
                        {
                            addDefaultColor = false;
                            colorSet_colors[0].append(MColor(1.0, 1.0, 1.0, 1.0));
                        }
                        colorId = colorSet_colors[0].length() - 1;
                    }
                    colorIndices[nColors ++] = colorId;
                }
            }
            
            channels[CHANNELCOLOR].numValues = colorSet_colors[0].length();
        }
    }

    // Apply Creases
    float maxEdgeCrease = getCreaseEdges( inMeshFn, desc );
    float maxVertexCrease = getCreaseVertices( inMeshFn, desc );

    OpenSubdiv::Far::TopologyRefiner * refiner =
        OpenSubdiv::Far::TopologyRefinerFactory<Descriptor>::Create(desc,
            OpenSubdiv::Far::TopologyRefinerFactory<Descriptor>::Options(type, options));

    delete [] desc.numVertsPerFace;
    delete [] desc.vertIndicesPerFace;
    delete [] desc.creaseVertexIndexPairs;
    delete [] desc.creaseWeights;
    delete [] desc.cornerVertexIndices;
    delete [] desc.cornerWeights;

    if (*hasUVs || *hasColors) {
        for(int i = 0 ; i < desc.numFVarChannels ; i ++) {
            delete [] channels[i].valueIndices;
        }
        delete [] channels;
    }

    if (maxCreaseSharpness) {
        *maxCreaseSharpness = std::max(maxEdgeCrease, maxVertexCrease);
    }

    return refiner;
}
Example #3
0
MStatus convertOsdFarToMayaMeshData(
     FMesh const * farMesh,
     OpenSubdiv::OsdCpuVertexBuffer * vertexBuffer,
     int subdivisionLevel,
     MFnMesh const & inMeshFn,
     MObject newMeshDataObj ) {

    MStatus returnStatus;

    // Get sizing data from OSD
    const OpenSubdiv::FarPatchTables *farPatchTables = farMesh->GetPatchTables();
    int numPolygons = farPatchTables->GetNumFaces(); // use the highest level stored in the patch tables
    const unsigned int *polygonConnects_orig = farPatchTables->GetFaceVertices(); // use the highest level stored in the patch tables

    const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *farSubdivTables = farMesh->GetSubdivisionTables();
    unsigned int numVertices  = farSubdivTables->GetNumVertices(subdivisionLevel);
    unsigned int vertexOffset = farSubdivTables->GetFirstVertexOffset(subdivisionLevel);

    // Init Maya Data
    MFloatPointArray points(numVertices);
    MIntArray faceCounts(numPolygons); // number of edges for each polygon.  Assume quads (4-edges per face)
    MIntArray faceConnects(numPolygons*4); // array of vertex ids for all edges. assuming quads

    // -- Face Counts
    for (int i=0; i < numPolygons; ++i) {
        faceCounts[i] = 4;
    }

    // -- Face Connects
    for (unsigned int i=0; i < faceConnects.length(); i++) {
        faceConnects[i] = polygonConnects_orig[i] - vertexOffset; // adjust vertex indices so that v0 is at index 0
    }

    // -- Points
    // Number of floats in each vertex.  (positions, normals, etc)
    int numFloatsPerVertex = vertexBuffer->GetNumElements();
    assert(numFloatsPerVertex == 3); // assuming only xyz stored for each vertex
    const float *vertexData = vertexBuffer->BindCpuBuffer();
    float *ptrVertexData;

    for (unsigned int i=0; i < numVertices; i++) {

        // make sure to offset to the first osd vertex for that subd level
        unsigned int osdRawVertexIndex = i + vertexOffset;

        // Lookup the data in the vertexData
        ptrVertexData = (float *) vertexData + ((osdRawVertexIndex) * numFloatsPerVertex);
        points.set(i, ptrVertexData[0], ptrVertexData[1], ptrVertexData[2]);
    }

    // Create New Mesh from MFnMesh
    MFnMesh newMeshFn;
    MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(),
        points, faceCounts, faceConnects, newMeshDataObj, &returnStatus);
    MCHECKERR(returnStatus, "Cannot create new mesh");

    // Attach UVs (if present)
    // ASSUMPTION: Only tracking UVs as FVar data.  Will need to change this
    // ASSUMPTION: OSD has a unique UV for each face-vertex
    int fvarTotalWidth = farMesh->GetTotalFVarWidth();

    if (fvarTotalWidth > 0) {

        // Get face-varying set names and other info from the inMesh
        MStringArray uvSetNames;
        MStringArray colorSetNames;
        std::vector<int> colorSetChannels;
        std::vector<MFnMesh::MColorRepresentation> colorSetReps;
        int totalColorSetChannels = 0;
        returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels);

        int numUVSets = uvSetNames.length();
        int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels;
        assert(fvarTotalWidth == expectedFvarTotalWidth);

        const OpenSubdiv::FarPatchTables::FVarDataTable &fvarDataTable =  farPatchTables->GetFVarDataTable();
        assert(fvarDataTable.size() == expectedFvarTotalWidth*faceConnects.length());

        // Create an array of indices to map each face-vert to the UV and ColorSet Data
        MIntArray fvarConnects(faceConnects.length());
        for (unsigned int i=0; i < faceConnects.length(); i++) {
            fvarConnects[i] = i;
        }

        MFloatArray uCoord(faceConnects.length());
        MFloatArray vCoord(faceConnects.length());

        for (int uvSetIndex=0; uvSetIndex < numUVSets; uvSetIndex++) {

            for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) {
                int fvarItem = vertid*fvarTotalWidth + uvSetIndex*2; // stride per vertex is the fvarTotalWidth
                uCoord[vertid] = fvarDataTable[fvarItem];
                vCoord[vertid] = fvarDataTable[fvarItem+1];
            }
            // Assign UV buffer and map the uvids for each face-vertex
            if (uvSetIndex != 0) { // assume uvset index 0 is the default UVset, so do not create
                returnStatus = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] );
            }
            MCHECKERR(returnStatus, "Cannot create UVSet");
            newMeshFn.setUVs(uCoord,vCoord, &uvSetNames[uvSetIndex]);
            newMeshFn.assignUVs(faceCounts, fvarConnects, &uvSetNames[uvSetIndex]);
        }

        MColorArray colorArray(faceConnects.length());
        int colorSetRelativeStartIndex = numUVSets*2;

        for (unsigned int colorSetIndex=0; colorSetIndex < colorSetNames.length(); colorSetIndex++) {

            for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) {

                int fvarItem = vertid*fvarTotalWidth + colorSetRelativeStartIndex;
                if (colorSetChannels[colorSetIndex] == 1) {
                    colorArray[vertid].r = fvarDataTable[fvarItem];
                    colorArray[vertid].g = fvarDataTable[fvarItem];
                    colorArray[vertid].b = fvarDataTable[fvarItem];
                    colorArray[vertid].a = 1.0f;
                } else if (colorSetChannels[colorSetIndex] == 3) {
                    colorArray[vertid].r = fvarDataTable[fvarItem];
                    colorArray[vertid].g = fvarDataTable[fvarItem+1];
                    colorArray[vertid].b = fvarDataTable[fvarItem+2];
                    colorArray[vertid].a = 1.0f;
                } else {
                    colorArray[vertid].r = fvarDataTable[fvarItem];
                    colorArray[vertid].g = fvarDataTable[fvarItem+1];
                    colorArray[vertid].b = fvarDataTable[fvarItem+2];
                    colorArray[vertid].a = fvarDataTable[fvarItem+3];
                }
            }

            // Assign UV buffer and map the uvids for each face-vertex
            // API Limitation: Cannot set MColorRepresentation here
            returnStatus = newMeshFn.createColorSetDataMesh(colorSetNames[colorSetIndex]);
            MCHECKERR(returnStatus, "Cannot create ColorSet");

            bool isColorClamped = inMeshFn.isColorClamped(colorSetNames[colorSetIndex], &returnStatus);
            newMeshFn.setIsColorClamped(colorSetNames[colorSetIndex], isColorClamped);
            newMeshFn.setColors(colorArray, &colorSetNames[colorSetIndex], colorSetReps[colorSetIndex]);
            newMeshFn.assignColors(fvarConnects, &colorSetNames[colorSetIndex]);

            // Increment colorSet start location in fvar buffer
            colorSetRelativeStartIndex += colorSetChannels[colorSetIndex];
        }
    }
    return MS::kSuccess;
}
Example #4
0
//! Create OSD HBR mesh.
//! Caller is expected to delete the resulting hbrMesh returned
HMesh *
createOsdHbrFromPoly( MFnMesh const & inMeshFn,
                      MItMeshPolygon & inMeshItPolygon,
                      std::vector<int> & fvarIndices,
                      std::vector<int> & fvarWidths)
{
    MStatus returnStatus;

    // == Mesh Properties

    // Gather FVarData
    MStringArray uvSetNames;
    MStringArray colorSetNames;
    std::vector<int> colorSetChannels;
    std::vector<MFnMesh::MColorRepresentation> colorSetReps;
    int totalColorSetChannels = 0;
    returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels);
    MWARNERR(returnStatus, "Failed to retrieve Maya face-varying parameters");

    // Create face-varying data with independent float channels of dimension 1
    // Note: This FVarData needs to be kept around for the duration of the HBR mesh
    int totalFvarWidth = 2*uvSetNames.length() + totalColorSetChannels;
    fvarIndices.resize(totalFvarWidth);
    fvarWidths.resize(totalFvarWidth);
    for (int i=0; i < totalFvarWidth; ++i) {
        fvarIndices[i] = i;
        fvarWidths[i] = 1;
    }

    // temp storage for UVs and ColorSets for a face
    MIntArray fvArray; // face vertex array
    std::vector<MFloatArray> uvSet_uCoords(uvSetNames.length());
    std::vector<MFloatArray> uvSet_vCoords(uvSetNames.length());
    std::vector<MColorArray> colorSet_colors(colorSetNames.length());

    // =====================================
    // Init HBR
    // =====================================

    // Determine HBR Subdiv Method
    static HCatmark _catmark;

    // Create HBR mesh
    assert(fvarIndices.size() == fvarWidths.size());
    HMesh * hbrMesh = new HMesh( &_catmark,
                                 (int)fvarIndices.size(),
                                 (fvarIndices.size() > 0) ? &fvarIndices[0] : NULL,
                                 (fvarWidths.size()  > 0) ? &fvarWidths[0] : NULL,
                                 totalFvarWidth );

    // Create Stub HBR Vertices
    int numVerts = inMeshFn.numVertices();
    OpenSubdiv::OsdVertex v;
    for(int i=0; i<numVerts; i++ ) {
        hbrMesh->NewVertex( i, v );
    }

    // ===================================================
    // Create HBR Topology
    // ===================================================

    assert(totalFvarWidth == hbrMesh->GetTotalFVarWidth());
    unsigned int ptxidx = 0;

    for( inMeshItPolygon.reset(); !inMeshItPolygon.isDone(); inMeshItPolygon.next() ) {

        // Verts for this face
        inMeshItPolygon.getVertices(fvArray);
        unsigned int nv = fvArray.length();

        bool valid = true;

        for(unsigned int j=0;j<fvArray.length(); j++) {

            HVertex const * origin      = hbrMesh->GetVertex( fvArray[j] ),
                          * destination = hbrMesh->GetVertex( fvArray[(j+1)%nv] );
            HHalfedge const * opposite = destination->GetEdge(origin);

            if(origin==NULL || destination==NULL) {
                fprintf(stderr, "Skipping face: An edge was specified that connected a nonexistent vertex\n");
                valid = false;
                break;
            }

            if(origin == destination) {
                fprintf(stderr, "Skipping face: An edge was specified that connected a vertex to itself\n");
                valid = false;
                break;
            }

            if(opposite && opposite->GetOpposite() ) {
                fprintf(stderr, "Skipping face: A non-manifold edge incident to more than 2 faces was found\n");
                valid = false;
                break;
            }

            if(origin->GetEdge(destination)) {
                fprintf(stderr, "Skipping face: An edge connecting two vertices was specified more than once."
                       " It's likely that an incident face was flipped\n");
                valid = false;
                break;
            }
        }

        // Update faces
        const int * fvArrayPtr = &(fvArray[0]); // get the raw int* array from std::vector<int>
        OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> * face = hbrMesh->NewFace(nv, fvArrayPtr, 0);

        // Increment ptex index
        face->SetPtexIndex(ptxidx);

        // Add FaceVaryingData (UVSets, ...)
        if (totalFvarWidth > 0) {

            // Retrieve all UV and ColorSet data
            MIntArray faceCounts;
            for (unsigned int i=0; i < uvSetNames.length(); ++i) {
                returnStatus = inMeshItPolygon.getUVs(uvSet_uCoords[i], uvSet_vCoords[i], &uvSetNames[i] );
                MWARNERR(returnStatus, "Cannot get UVs");
            }
            for (unsigned int i=0; i < colorSetNames.length(); ++i) {
                returnStatus = inMeshItPolygon.getColors (colorSet_colors[i], &colorSetNames[i]);
                MWARNERR(returnStatus, "Cannot get face vertex colors");
            }

            std::vector<float> fvarItem(totalFvarWidth); // storage for all the face-varying channels for this face-vertex

            // loop over each uvSet and the uvs within
            for (unsigned int fvid=0; fvid < fvArray.length(); ++fvid) {

                int fvarItemIndex = 0;
                // Handle uvSets
                for( unsigned int uvSetIt=0; uvSetIt < uvSetNames.length(); ++uvSetIt ) {
                    fvarItem[fvarItemIndex]   = uvSet_uCoords[uvSetIt][fvid];
                    fvarItem[fvarItemIndex+1] = uvSet_vCoords[uvSetIt][fvid];
                    fvarItemIndex +=2;
                }
                // Handle colorSets
                for( unsigned int colorSetIt=0; colorSetIt < colorSetNames.length(); ++colorSetIt ) {
                    if (colorSetChannels[colorSetIt] == 1) {
                        fvarItem[fvarItemIndex]   = colorSet_colors[colorSetIt][fvid].a;
                    }
                    else if (colorSetChannels[colorSetIt] == 3) {
                        fvarItem[fvarItemIndex]   = colorSet_colors[colorSetIt][fvid].r;
                        fvarItem[fvarItemIndex+1] = colorSet_colors[colorSetIt][fvid].g;
                        fvarItem[fvarItemIndex+2] = colorSet_colors[colorSetIt][fvid].b;
                    }
                    else { // colorSetChannels[colorSetIt] == 4
                        fvarItem[fvarItemIndex]   = colorSet_colors[colorSetIt][fvid].r;
                        fvarItem[fvarItemIndex+1] = colorSet_colors[colorSetIt][fvid].g;
                        fvarItem[fvarItemIndex+2] = colorSet_colors[colorSetIt][fvid].b;
                        fvarItem[fvarItemIndex+3] = colorSet_colors[colorSetIt][fvid].a;
                    }
                    fvarItemIndex += colorSetChannels[colorSetIt];
                }
                assert((fvarItemIndex) == totalFvarWidth); // For UVs, sanity check the resulting value

                // Insert into the HBR structure for that face
                HVertex * hbrVertex = hbrMesh->GetVertex( fvArray[fvid] );
                HFvarData & fvarData = hbrVertex->GetFVarData(face);

                if (not fvarData.IsInitialized()) {
                    fvarData.SetAllData(totalFvarWidth, &fvarItem[0]);
                } else if (not fvarData.CompareAll(totalFvarWidth, &fvarItem[0])) {

                    // If data exists for this face vertex, but is different
                    // (e.g. we're on a UV seam) create another fvar datum
                    OpenSubdiv::HbrFVarData<OpenSubdiv::OsdVertex> &fvarData_new = hbrVertex->NewFVarData(face);
                    fvarData_new.SetAllData( totalFvarWidth, &fvarItem[0] );
                }
            }
        }

        // Increment ptxidx and store off ptex index values
        //   The number of ptexIds needed is 1 if a quad.  Otherwise it is the number of
        //   vertices for the face.
        int numPtexIdsForFace;
        if (valid) {
            numPtexIdsForFace = ( nv != 4 ) ? nv : 1 ;
        }
        else {
            numPtexIdsForFace = 0;
        }
        ptxidx += numPtexIdsForFace;
    }

    // Apply Creases
    applyCreaseEdges( inMeshFn, hbrMesh );
    applyCreaseVertices( inMeshFn, hbrMesh );

    // Return the resulting HBR Mesh
    // Note that boundaryMethods and hbrMesh->Finish() still need to be called
    return hbrMesh;
}
Example #5
0
static MStatus
convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
    std::vector<Vertex> const & vertexBuffer, MFnMesh const & inMeshFn,
        MObject newMeshDataObj) {

    MStatus status;

    typedef OpenSubdiv::Far::ConstIndexArray IndexArray;

    int maxlevel = refiner.GetMaxLevel();

    OpenSubdiv::Far::TopologyLevel const & refLastLevel 
                                                = refiner.GetLevel(maxlevel);

    int nfaces = refLastLevel.GetNumFaces();
        
    // Init Maya Data

    // -- Face Counts
    MIntArray faceCounts(nfaces);
    for (int face=0; face < nfaces; ++face) {
        faceCounts[face] = 4;
    }

    // -- Face Connects
    MIntArray faceConnects(nfaces*4);
    for (int face=0, idx=0; face < nfaces; ++face) {
        IndexArray fverts = refLastLevel.GetFaceVertices(face);
        for (int vert=0; vert < fverts.size(); ++vert) {
            faceConnects[idx++] = fverts[vert];
        }
    }

    // -- Points
    MFloatPointArray points(refLastLevel.GetNumVertices());
    Vertex const * v = &vertexBuffer.at(0);

    for (int level=1; level<=maxlevel; ++level) {
        int nverts = refiner.GetLevel(level).GetNumVertices();
        if (level==maxlevel) {
            for (int vert=0; vert < nverts; ++vert, ++v) {
                points.set(vert, v->position[0], v->position[1], v->position[2]);
            }
        } else {
            v += nverts;
        }
    }

    // Create New Mesh from MFnMesh
    MFnMesh newMeshFn;
    MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(),
        points, faceCounts, faceConnects, newMeshDataObj, &status);
    MCHECKERR(status, "Cannot create new mesh");

    int fvarTotalWidth = 0;

    if (fvarTotalWidth > 0) {

        // Get face-varying set names and other info from the inMesh
        MStringArray uvSetNames;
        MStringArray colorSetNames;
        std::vector<int> colorSetChannels;
        std::vector<MFnMesh::MColorRepresentation> colorSetReps;
        int totalColorSetChannels = 0;
        status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames,
            colorSetChannels, colorSetReps, totalColorSetChannels);

#if defined(DEBUG) or defined(_DEBUG)
        int numUVSets = uvSetNames.length();
        int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels;
        assert(fvarTotalWidth == expectedFvarTotalWidth);
#endif

// XXXX fvar stuff here

    }

    return MS::kSuccess;
}
Example #6
0
//! Caller is expected to delete the returned value
static OpenSubdiv::Far::TopologyRefiner *
gatherTopology( MFnMesh const & inMeshFn,
                MItMeshPolygon & inMeshItPolygon,
                OpenSubdiv::Sdc::SchemeType type,
                OpenSubdiv::Sdc::Options options,
                float * maxCreaseSharpness=0 ) {

    MStatus returnStatus;

    // Gather FVarData
    MStringArray uvSetNames;
    MStringArray colorSetNames;
    std::vector<int> colorSetChannels;
    std::vector<MFnMesh::MColorRepresentation> colorSetReps;
    int totalColorSetChannels = 0;
    returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels);
    MWARNERR(returnStatus, "Failed to retrieve Maya face-varying parameters");

    // Create face-varying data with independent float channels of dimension 1
    // Note: This FVarData needs to be kept around for the duration of the HBR mesh
    int totalFvarWidth = 2*uvSetNames.length() + totalColorSetChannels;

    // temp storage for UVs and ColorSets for a face
    MIntArray fvArray; // face vertex array
    std::vector<MFloatArray> uvSet_uCoords(uvSetNames.length());
    std::vector<MFloatArray> uvSet_vCoords(uvSetNames.length());
    std::vector<MColorArray> colorSet_colors(colorSetNames.length());

    Descriptor desc;

    desc.numVertices = inMeshFn.numVertices();
    desc.numFaces = inMeshItPolygon.count();

    int * vertsPerFace = new int[desc.numFaces],
        * vertIndices = new int[inMeshFn.numFaceVertices()];

    desc.numVertsPerFace = vertsPerFace;
    desc.vertIndicesPerFace = vertIndices;

    // Create Topology

    for( inMeshItPolygon.reset(); !inMeshItPolygon.isDone(); inMeshItPolygon.next() ) {

        inMeshItPolygon.getVertices(fvArray);
        int nverts = fvArray.length();

        vertsPerFace[inMeshItPolygon.index()] = nverts;

        for (int i=0; i<nverts; ++i) {
            *vertIndices++ = fvArray[i];
        }

        // Add FaceVaryingData (UVSets, ...)
        if (totalFvarWidth > 0) {
// XXXX
            // Retrieve all UV and ColorSet topology
            for (unsigned int i=0; i < uvSetNames.length(); ++i) {
                inMeshItPolygon.getUVs(uvSet_uCoords[i], uvSet_vCoords[i], &uvSetNames[i] );
            }
            for (unsigned int i=0; i < colorSetNames.length(); ++i) {
                inMeshItPolygon.getColors(colorSet_colors[i], &colorSetNames[i]);
            }

            // Handle uvSets
            for (unsigned int fvid=0; fvid < fvArray.length(); ++fvid) {
            }
            // Handle colorSets
            for( unsigned int colorSetIt=0; colorSetIt < colorSetNames.length(); ++colorSetIt ) {
            }
        }
    }

    // Apply Creases
    float maxEdgeCrease = getCreaseEdges( inMeshFn, desc );

    float maxVertexCrease = getCreaseVertices( inMeshFn, desc );

    OpenSubdiv::Far::TopologyRefiner * refiner =
        OpenSubdiv::Far::TopologyRefinerFactory<Descriptor>::Create(desc,
            OpenSubdiv::Far::TopologyRefinerFactory<Descriptor>::Options(type, options));

    delete [] desc.numVertsPerFace;
    delete [] desc.vertIndicesPerFace;

    delete [] desc.creaseVertexIndexPairs;
    delete [] desc.creaseWeights;
    delete [] desc.cornerVertexIndices;
    delete [] desc.cornerWeights;

    if (maxCreaseSharpness) {
        *maxCreaseSharpness = std::max(maxEdgeCrease, maxVertexCrease);
    }

    return refiner;
}