MStatus TCC::compute(const MPlug& plug, MDataBlock& data) { MStatus stat; if (plug == aOutputMesh) { /* Get time */ int subdivRes = data.inputValue(aRes, &stat).asInt(); int subdivRefRes = data.inputValue(aRefRes, &stat).asInt(); float lineThickness = data.inputValue(aLineThickness, &stat).asFloat(); MDataHandle inMeshHandle = data.inputValue( aInputMesh, &stat ); McheckErr(stat,"ERROR getting attribute"); MObject inMeshObj = inMeshHandle.asMesh(); MFnMesh inMeshFn(inMeshObj); MIntArray nFV, F; inMeshFn.getVertices(nFV, F); MIntArray nFVc = MFnIntArrayData( data.inputValue( anFVc ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MIntArray Fc = MFnIntArrayData( data.inputValue( aFc ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MIntArray pole = MFnIntArrayData( data.inputValue( aPole ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MIntArray corner = MFnIntArrayData( data.inputValue( aCorner ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MIntArray T = MFnIntArrayData( data.inputValue( aT ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MIntArray eqc = MFnIntArrayData( data.inputValue( aEqc ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MDoubleArray itv = MFnDoubleArrayData( data.inputValue( aItv ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); MIntArray err = MFnIntArrayData( data.inputValue( aErr ).data() ).array(&stat); McheckErr(stat,"ERROR getting attr"); TCCData tccData(nFV, F, nFVc, Fc, pole, corner, T, eqc, itv, err); /* Get output object */ MDataHandle outMeshHandle = data.outputValue(aOutputMesh, &stat); McheckErr(stat, "ERROR getting attribute\n"); if (validTopology(tccData)) { stat = createSubdividedMesh(subdivRes, subdivRefRes, inMeshFn, tccData, outMeshHandle, lineThickness, stat); } else { outMeshHandle.setMObject(inMeshObj); MFnMesh outMeshFn(outMeshHandle.asMesh()); stat = setErrorColors(outMeshFn, tccData); } data.setClean( plug ); } else return MS::kUnknownParameter; return stat; }
MStatus DDConvexHullUtils::generateMayaHull(MObject &output, const MPointArray &vertices, const DDConvexHullUtils::hullOpts &hullOptions) { // Allocate and push the vert list into the new array Mem Cleanup req. uint numInputVerts = vertices.length(); double *inputVerts = new double[numInputVerts*3]; for (uint i=0; i < numInputVerts; i++) { uint offset = i*3; inputVerts[offset] = vertices[i].x; inputVerts[offset+1] = vertices[i].y; inputVerts[offset+2] = vertices[i].z; } // Setup the flags uint hullFlags = QF_DEFAULT; if (hullOptions.forceTriangles) { hullFlags |= QF_TRIANGLES; } if (hullOptions.useSkinWidth) { hullFlags |= QF_SKIN_WIDTH; } if (hullOptions.reverseTriangleOrder) { hullFlags |= QF_REVERSE_ORDER; } // Create the description HullDesc hullDescription; hullDescription.mFlags = hullFlags; hullDescription.mMaxVertices = hullOptions.maxOutputVertices; hullDescription.mSkinWidth = hullOptions.skinWidth; hullDescription.mNormalEpsilon = hullOptions.normalEpsilon; hullDescription.mVertexStride = sizeof(double)*3; hullDescription.mVcount = numInputVerts; hullDescription.mVertices = inputVerts; // Create the hull HullLibrary hullComputer; HullResult hullResult; HullError err = hullComputer.CreateConvexHull(hullDescription, hullResult); MStatus hullStat = MStatus::kSuccess; if (err == QE_OK) { // Grab the verts MPointArray outPoints; for (uint i=0; i < hullResult.mNumOutputVertices; i++) { uint offset = i*3; MPoint curPoint(hullResult.mOutputVertices[offset], hullResult.mOutputVertices[offset+1], hullResult.mOutputVertices[offset+2]); outPoints.append(curPoint); } // Check if the results are in polygons, or triangles. Depending on // which for the result is in, the way the face indices are setup // is different. MIntArray polyCounts; MIntArray vertexConnects; if (hullResult.mPolygons) { const uint *idx = hullResult.mIndices; for (uint i=0; i < hullResult.mNumFaces; i++) { uint pCount = *idx++; polyCounts.append(pCount); for (uint j=0; j < pCount; j++) { uint val = idx[0]; vertexConnects.append(val); idx++; } } } else { polyCounts.setLength(hullResult.mNumFaces); for (uint i=0; i < hullResult.mNumFaces; i++) { polyCounts[i] = 3; uint *idx = &hullResult.mIndices[i*3]; vertexConnects.append(idx[0]); vertexConnects.append(idx[1]); vertexConnects.append(idx[2]); } } // Setup the outmesh MFnMesh outMeshFn(output); outMeshFn.create(hullResult.mNumOutputVertices, hullResult.mNumFaces, outPoints, polyCounts, vertexConnects, output, &hullStat); } else { hullStat = MStatus::kFailure; } // Mem Cleanup hullComputer.ReleaseResult(hullResult); delete[] inputVerts; return hullStat; }
MStatus TCC::createSubdividedMesh(int sdRes, int sdRefRes, MFnMesh &srcMesh, TCCData &tccData, MDataHandle outMeshHandle, float lineThickness, MStatus& stat) { HDS hds; bool shouldCreateUVs = true; size_t nV = srcMesh.numVertices(); size_t nF = srcMesh.numPolygons(); size_t nIHE = tccData.F.length(); bool consistentSizes= (tccData.pole.length()==nV) && (tccData.T.length()==nIHE) && (tccData.itv.length()==nIHE) & (tccData.corner.length()==nV); if ((nV==0)||(nF==0)||(!consistentSizes)) return MS::kFailure; MFloatArray uArray, vArray, sc_uArray, sc_vArray; MIntArray uvIdx; if (shouldCreateUVs) { createUVset(tccData, sdRes, uArray, vArray, sc_uArray, sc_vArray, uvIdx, lineThickness); } MFloatPointArray points; srcMesh.getPoints(points); store_in_hds(hds, points, tccData.nFV, tccData.F); // convert to HDS finalize_HDS(hds); size_t nHE = hds.nHE(); hds.T.setDims(1, nHE); hds.itv.setDims(1, nHE); hds.corner.setDims(1, nV); // interior halfedge tags for (size_t k=0; k<nV; k++) { hds.corner[k] = tccData.corner[k]; } // interior halfedge tags for (size_t k=0; k<nIHE; k++) { hds.T[k] = tccData.T[k]; hds.itv[k] = tccData.itv[k]; } // border halfedge tags for (size_t k=nIHE; k<nHE; k++) { hds.T[k] = false; hds.itv[k] = hds.itv[hds.twin[k]]; } TCC_MAX::subdivide(hds, sdRes); if (sdRefRes>0) { HDS hds2; copy_HDS(hds, hds2); TCC_MAX::subdivide(hds2, sdRefRes); memcpy(&hds.V[0], &hds2.V[0], hds.V.size() * sizeof(double)); } MObject outMeshObj = outMeshHandle.asMesh(); MFnMesh outMeshFn(outMeshObj); // if no topology change necessary, just update points! if ( (outMeshFn.numFaceVertices() == hds.nIHE()) && (outMeshFn.numPolygons() == hds.nF()) ) { size_t nV = hds.nV(); points.setLength(nV); for (size_t k=0; k<nV; k++) { points[k](0) = hds.V[3*k+0]; points[k](1) = hds.V[3*k+1]; points[k](2) = hds.V[3*k+2]; } stat = outMeshFn.setPoints(points); McheckErr(stat, "ERROR creating outputData"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; stat = outMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = outMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); } return MS::kSuccess; } // Have to update connectivity and geometry load_from_hds(hds, points, tccData.nFV, tccData.F); nV = points.length(); nF = tccData.nFV.length(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&stat); McheckErr(stat, "ERROR creating outputData"); MFnMesh newOutMeshFn; MObject newMesh; newMesh = newOutMeshFn.create(nV, nF, points, tccData.nFV, tccData.F, newOutputData, &stat); McheckErr(stat, "ERROR in MFnMesh.create\n"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; uvSet = newOutMeshFn.createUVSetDataMeshWithName(uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&uvSet); stat = newOutMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &uvSet); McheckErr(stat, "ERROR assigning UVs"); sc_uvSet = newOutMeshFn.createUVSetDataMeshWithName(sc_uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&sc_uvSet); stat = newOutMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &sc_uvSet); McheckErr(stat, "ERROR assigning UVs"); } if (stat == MS::kSuccess) { outMeshHandle.set(newOutputData); } return MS::kSuccess; }