Example #1
0
// ====================================
// Helper Functions
// ====================================
// Create component groups
void
createComp(MFnMeshData &dataCreator, MFn::Type compType, unsigned compId, MIntArray &compList) {

  MStatus returnStatus;

  MFnSingleIndexedComponent comp;
  MObject compObj = comp.create(compType,&returnStatus);
  MWARNERR(returnStatus, "cannot create MFnSingleIndexedComponent");

  returnStatus = comp.addElements(compList);
  MWARNERR(returnStatus, "Error in addElements() for MFnSingleIndexedComponent");

  returnStatus = dataCreator.addObjectGroup(compId);
  MWARNERR(returnStatus, "Error in addObjectGroup()");

  returnStatus = dataCreator.setObjectGroupComponent(compId, compObj);
  MWARNERR(returnStatus, "Error in setObjectGroupComponent()");
}
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
//! 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 #4
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;
}