MStatus PtexUVNode::compute( const MPlug &plug, MDataBlock &data ) { MStatus stat; bool hasNoEffect = false; MDataHandle inMeshHnd = data.inputValue( inMesh ); MDataHandle outMeshHnd = data.outputValue( outMesh ); MDataHandle stateHnd = data.inputValue( state ); int state = stateHnd.asInt(); if( state == 1 ) // No Effect/Pass through hasNoEffect = true; if( !hasNoEffect && plug == outMesh ) { MObject inMeshData = inMeshHnd.asMesh(); if( !hasNoEffect ) { MFnMeshData meshDataFn; MObject newMeshData = meshDataFn.create(); MFnMesh inMeshFn( inMeshData ); inMeshFn.copy( inMeshData, newMeshData ); MFnMesh meshFn( newMeshData ); MPointArray pts; meshFn.getPoints( pts ); MStringArray uvSetNames; meshFn.getUVSetNames( uvSetNames ); unsigned int defaultUvSetCount = (unsigned int)uvSetNames.length(); int num_faces = meshFn.numPolygons(); MIntArray uvCounts; uvCounts.setLength( num_faces ); for ( int i_f = 0; i_f < num_faces; i_f++ ) { int deg = meshFn.polygonVertexCount( i_f ); uvCounts[ i_f ] = deg; if ( deg != 4 ) { return MS::kFailure; } } MIntArray uvIds; uvIds.setLength( 4 * num_faces ); if ( defaultUvSetCount == 1 ) { int currentUVCount = meshFn.numUVs( uvSetNames[0] ); MFloatArray us, vs; us.setLength( 4 * num_faces ); vs.setLength( 4 * num_faces ); for ( int i_f = 0; i_f < num_faces; i_f++ ) { float f = (float)i_f; uvIds[ 4 * i_f + 0 ] = 4 * i_f + 0; uvIds[ 4 * i_f + 1 ] = 4 * i_f + 1; uvIds[ 4 * i_f + 2 ] = 4 * i_f + 2; uvIds[ 4 * i_f + 3 ] = 4 * i_f + 3; us[ 4 * i_f + 0 ] = (float)i_f; vs[ 4 * i_f + 0 ] = 0.0f; us[ 4 * i_f + 1 ] = (float)i_f + 1.0f; vs[ 4 * i_f + 1 ] = 0.0f; us[ 4 * i_f + 2 ] = (float)i_f + 1.0f; vs[ 4 * i_f + 2 ] = 1.0f; us[ 4 * i_f + 3 ] = (float)i_f; vs[ 4 * i_f + 3 ] = 1.0f; } stat = meshFn.setUVs( us, vs, &uvSetNames[0] ); stat = meshFn.assignUVs( uvCounts, uvIds, &uvSetNames[0] ); } meshFn.updateSurface(); meshFn.syncObject(); outMeshHnd.set( newMeshData ); } } else return MS::kUnknownParameter; if( hasNoEffect ) outMeshHnd.set( inMeshHnd.asMesh() ); data.setClean( plug ); return stat; }
// ==================================== // 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; }
MStatus AlembicNode::initialize() { MStatus status; MFnUnitAttribute uAttr; MFnTypedAttribute tAttr, tAttr2; MFnNumericAttribute nAttr; MFnGenericAttribute gAttr; MFnEnumAttribute eAttr; // add the input attributes: time, file, sequence time mTimeAttr = uAttr.create("time", "tm", MFnUnitAttribute::kTime, 0.0); status = uAttr.setStorable(true); status = addAttribute(mTimeAttr); // input file name MFnStringData fileFnStringData; MObject fileNameDefaultObject = fileFnStringData.create(""); mAbcFileNameAttr = tAttr.create("abc_File", "fn", MFnData::kString, fileNameDefaultObject); status = tAttr.setStorable(true); status = tAttr.setUsedAsFilename(true); status = addAttribute(mAbcFileNameAttr); // input layer file names MFnStringArrayData fileFnStringArrayData; MStringArray dummyStringArray; MObject layerFileNamesDefaultObject = fileFnStringArrayData.create(dummyStringArray); mAbcLayerFileNamesAttr = tAttr2.create("abc_layerFiles", "fns", MFnData::kStringArray, layerFileNamesDefaultObject); status = tAttr2.setStorable(true); status = tAttr2.setUsedAsFilename(true); status = tAttr2.setKeyable(false); status = tAttr2.setWritable(true); status = addAttribute(mAbcLayerFileNamesAttr); // playback speed mSpeedAttr = nAttr.create("speed", "sp", MFnNumericData::kDouble, 1.0, &status); status = nAttr.setWritable(true); status = nAttr.setStorable(true); status = nAttr.setKeyable(true); status = addAttribute(mSpeedAttr); // frame offset mOffsetAttr = nAttr.create("offset", "of", MFnNumericData::kDouble, 0, &status); status = nAttr.setWritable(true); status = nAttr.setStorable(true); status = nAttr.setKeyable(true); status = addAttribute(mOffsetAttr); // cycle type mCycleTypeAttr = eAttr.create("cycleType", "ct", 0, &status ); status = eAttr.addField("Hold", PLAYTYPE_HOLD); status = eAttr.addField("Loop", PLAYTYPE_LOOP); status = eAttr.addField("Reverse", PLAYTYPE_REVERSE); status = eAttr.addField("Bounce", PLAYTYPE_BOUNCE); status = eAttr.setWritable(true); status = eAttr.setStorable(true); status = eAttr.setKeyable(true); status = addAttribute(mCycleTypeAttr); // Regex Filter // This is a hidden variable to preserve a regexIncludefilter string // into a .ma file. mIncludeFilterAttr = tAttr.create("regexIncludeFilter", "ift", MFnData::kString); status = tAttr.setStorable(true); status = tAttr.setHidden(true); status = addAttribute(mIncludeFilterAttr); // Regex Filter // This is a hidden variable to preserve a regexExcludefilter string // into a .ma file. mExcludeFilterAttr = tAttr.create("regexExcludeFilter", "eft", MFnData::kString); status = tAttr.setStorable(true); status = tAttr.setHidden(true); status = addAttribute(mExcludeFilterAttr); // sequence min and max in frames mStartFrameAttr = nAttr.create("startFrame", "sf", MFnNumericData::kDouble, 0, &status); status = nAttr.setWritable(false); status = nAttr.setStorable(true); status = addAttribute(mStartFrameAttr); mEndFrameAttr = nAttr.create("endFrame", "ef", MFnNumericData::kDouble, 0, &status); status = nAttr.setWritable(false); status = nAttr.setStorable(true); status = addAttribute(mEndFrameAttr); // add the output attributes // sampled subD mesh MFnMeshData fnMeshData; MObject meshDefaultObject = fnMeshData.create(&status); mOutSubDArrayAttr = tAttr.create("outSubDMesh", "osubd", MFnData::kMesh, meshDefaultObject); status = tAttr.setStorable(false); status = tAttr.setWritable(false); status = tAttr.setKeyable(false); status = tAttr.setArray(true); status = tAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutSubDArrayAttr); // sampled poly mesh mOutPolyArrayAttr = tAttr.create("outPolyMesh", "opoly", MFnData::kMesh, meshDefaultObject); status = tAttr.setStorable(false); status = tAttr.setWritable(false); status = tAttr.setKeyable(false); status = tAttr.setArray(true); status = tAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutPolyArrayAttr); // sampled nurbs surface MFnNurbsSurfaceData fnNSData; MObject nsDefaultObject = fnNSData.create(&status); mOutNurbsSurfaceArrayAttr = tAttr.create("outNSurface", "ons", MFnData::kNurbsSurface, nsDefaultObject); status = tAttr.setStorable(false); status = tAttr.setWritable(false); status = tAttr.setKeyable(false); status = tAttr.setArray(true); status = tAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutNurbsSurfaceArrayAttr); // sampled nurbs curve group MFnNurbsCurveData fnNCData; MObject ncDefaultObject = fnNCData.create(&status); mOutNurbsCurveGrpArrayAttr = tAttr.create("outNCurveGrp", "onc", MFnData::kNurbsCurve, ncDefaultObject); status = tAttr.setStorable(false); status = tAttr.setWritable(false); status = tAttr.setKeyable(false); status = tAttr.setArray(true); status = tAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutNurbsCurveGrpArrayAttr); // sampled locator mOutLocatorPosScaleArrayAttr = nAttr.create("outLoc", "olo", MFnNumericData::kDouble, 0.0, &status); status = nAttr.setStorable(false); status = nAttr.setWritable(false); status = nAttr.setArray(true); status = nAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutLocatorPosScaleArrayAttr); // sampled transform operations mOutTransOpArrayAttr = nAttr.create("transOp", "to", MFnNumericData::kDouble, 0.0, &status); status = nAttr.setStorable(false); status = nAttr.setWritable(false); status = nAttr.setArray(true); status = nAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutTransOpArrayAttr); // sampled camera // assume the boolean variables cannot be keyed mOutCameraArrayAttr = nAttr.create("outCamera", "ocam", MFnNumericData::kDouble, 0.0, &status); status = nAttr.setStorable(false); status = nAttr.setWritable(false); status = nAttr.setArray(true); status = nAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutCameraArrayAttr); // sampled custom-attributes mOutPropArrayAttr = gAttr.create("prop", "pr", &status); status = gAttr.addNumericDataAccept(MFnNumericData::kBoolean); status = gAttr.addNumericDataAccept(MFnNumericData::kByte); status = gAttr.addNumericDataAccept(MFnNumericData::kShort); status = gAttr.addNumericDataAccept(MFnNumericData::k2Short); status = gAttr.addNumericDataAccept(MFnNumericData::k3Short); status = gAttr.addNumericDataAccept(MFnNumericData::kInt); status = gAttr.addNumericDataAccept(MFnNumericData::k2Int); status = gAttr.addNumericDataAccept(MFnNumericData::k3Int); status = gAttr.addNumericDataAccept(MFnNumericData::kFloat); status = gAttr.addNumericDataAccept(MFnNumericData::k2Float); status = gAttr.addNumericDataAccept(MFnNumericData::k3Float); status = gAttr.addNumericDataAccept(MFnNumericData::kDouble); status = gAttr.addNumericDataAccept(MFnNumericData::k2Double); status = gAttr.addNumericDataAccept(MFnNumericData::k3Double); status = gAttr.addNumericDataAccept(MFnNumericData::k4Double); status = gAttr.addDataAccept(MFnData::kString); status = gAttr.addDataAccept(MFnData::kIntArray); status = gAttr.addDataAccept(MFnData::kDoubleArray); status = gAttr.addDataAccept(MFnData::kVectorArray); status = gAttr.addDataAccept(MFnData::kPointArray); status = gAttr.setWritable(false); status = gAttr.setKeyable(false); status = gAttr.setArray(true); status = gAttr.setUsesArrayDataBuilder(true); status = addAttribute(mOutPropArrayAttr); // set up affection relationships status = attributeAffects(mTimeAttr, mOutSubDArrayAttr); status = attributeAffects(mTimeAttr, mOutPolyArrayAttr); status = attributeAffects(mTimeAttr, mOutNurbsSurfaceArrayAttr); status = attributeAffects(mTimeAttr, mOutNurbsCurveGrpArrayAttr); status = attributeAffects(mTimeAttr, mOutTransOpArrayAttr); status = attributeAffects(mTimeAttr, mOutCameraArrayAttr); status = attributeAffects(mTimeAttr, mOutPropArrayAttr); status = attributeAffects(mTimeAttr, mOutLocatorPosScaleArrayAttr); status = attributeAffects(mSpeedAttr, mOutSubDArrayAttr); status = attributeAffects(mSpeedAttr, mOutPolyArrayAttr); status = attributeAffects(mSpeedAttr, mOutNurbsSurfaceArrayAttr); status = attributeAffects(mSpeedAttr, mOutNurbsCurveGrpArrayAttr); status = attributeAffects(mSpeedAttr, mOutTransOpArrayAttr); status = attributeAffects(mSpeedAttr, mOutCameraArrayAttr); status = attributeAffects(mSpeedAttr, mOutPropArrayAttr); status = attributeAffects(mSpeedAttr, mOutLocatorPosScaleArrayAttr); status = attributeAffects(mOffsetAttr, mOutSubDArrayAttr); status = attributeAffects(mOffsetAttr, mOutPolyArrayAttr); status = attributeAffects(mOffsetAttr, mOutNurbsSurfaceArrayAttr); status = attributeAffects(mOffsetAttr, mOutNurbsCurveGrpArrayAttr); status = attributeAffects(mOffsetAttr, mOutTransOpArrayAttr); status = attributeAffects(mOffsetAttr, mOutCameraArrayAttr); status = attributeAffects(mOffsetAttr, mOutPropArrayAttr); status = attributeAffects(mOffsetAttr, mOutLocatorPosScaleArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutSubDArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutPolyArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutNurbsSurfaceArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutNurbsCurveGrpArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutTransOpArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutCameraArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutPropArrayAttr); status = attributeAffects(mCycleTypeAttr, mOutLocatorPosScaleArrayAttr); MGlobal::executeCommand( UITemplateMELScriptStr ); return status; }
/*! Compute function, gets the input surface, determines what type it is and calls the appropriate conversion function Encapsulates an cowpointer to the body into the naiadBodyData type and outputs it */ MStatus NBuddySurfaceToBodyNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if (plug == _outBody) { //Get the body name MDataHandle bodyNameHndl = data.inputValue( _bodyName, &status ); MString bodyName = bodyNameHndl.asString(); //Create the MFnPluginData for the naiadBody MFnPluginData dataFn; dataFn.create( MTypeId( naiadBodyData::id ), &status); NM_CheckMStatus( status, "Failed to create naiadBodyData in MFnPluginData"); //Get subdivision info from plugs so better approximations of meshes can be done int divisions = data.inputValue( _subDivide, &status ).asBool(); //Getting genericAttribute handle containing the surface and pick the correct conversion function MObject meshObj; MDataHandle inSurfaceHdl = data.inputValue( _inSurface, &status ); if (inSurfaceHdl.type() == MFnData::kNurbsSurface) { MFnNurbsSurface nurbsFn(inSurfaceHdl.asNurbsSurface()); // Create the data holder for the tesselated mesh MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); //Setup the tesselation parameters MTesselationParams tParams; tParams.setOutputType( MTesselationParams::kTriangles ); tParams.setFormatType( MTesselationParams::kGeneralFormat ); tParams.setUIsoparmType( MTesselationParams::kSpanEquiSpaced ); tParams.setVIsoparmType( MTesselationParams::kSpanEquiSpaced ); tParams.setUNumber( divisions+1 ); tParams.setVNumber( divisions+1 ); // Tesselate and get the returned mesh meshObj = nurbsFn.tesselate( tParams, newOutputData, &status ); NM_CheckMStatus( status, "NBuddySurfaceToBodyNode::compute Failed to tesselate nurbs surface to poly"); } else if (inSurfaceHdl.type() == MFnData::kMesh) { meshObj = inSurfaceHdl.asMesh(); if ( divisions > 0 ) { MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); MFnMesh meshFn(meshObj); MIntArray faceIds; for ( unsigned int i(0); i < meshFn.numPolygons(); ++i ) faceIds.append(i); meshFn.subdivideFaces( faceIds , divisions ); } } else if (inSurfaceHdl.type() == MFnData::kSubdSurface) { // Create the subd function set so we can tesselate MFnSubd subDfn(inSurfaceHdl.asSubdSurface()); // Create the data holder for the tesselated mesh MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); // Tesselate the subD surface meshObj = subDfn.tesselate(true, 1 , divisions , newOutputData, &status ); NM_CheckMStatus( status, "NBuddySurfaceToBodyNode::compute Failed to tesselate SubD surface to poly"); } else return status ; //Get the handle for the input transform MDataHandle inTransformHdl = data.inputValue( _inTransform, &status ); NM_CheckMStatus( status, "Failed to get inTransform handle"); MDataHandle useTransformHdl = data.inputValue( _useTransform, &status); NM_CheckMStatus( status, "Failed to get worldSpaceHdl "); bool useTransform = useTransformHdl.asBool(); //Get a new naiadBodyData naiadBodyData * newBodyData = (naiadBodyData*)dataFn.data( &status ); NM_CheckMStatus( status, "Failed to get naiadBodyData handle from MFnPluginData"); try { newBodyData->nBody = mayaMeshToNaiadBody( meshObj, std::string(bodyName.asChar()), useTransform, inTransformHdl.asMatrix() ); } catch(std::exception& ex) { NM_ExceptionPlugDisplayError("NBuddySurfaceToBodyNode::compute ", plug, ex ); } //Give the data to the output handle and set it clean MDataHandle bodyDataHnd = data.outputValue( _outBody, &status ); NM_CheckMStatus( status, "Failed to get outputData handle for outBody"); bodyDataHnd.set( newBodyData ); data.setClean( plug ); } return status; }
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; }
MStatus ropeGenerator::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if ( plug == outMesh ) { //Get Curve MDataHandle inCurve_Hdl = data.inputValue( inCurve, &status ); if (status != MS::kSuccess ){ MGlobal::displayError( "Node ropeGenerator needs an Input Curve" ); return MS::kSuccess; } MObject inCurveObj = inCurve_Hdl.asNurbsCurve(); MFnNurbsCurve curveFn( inCurveObj ); //Get Attributes int inDiv = data.inputValue( divisions ).asInt(); bool inCreateRope = data.inputValue( createRope ).asBool(); int inRopesCount = data.inputValue( ropesCount ).asInt(); int inPointsPerRope = data.inputValue( pointsPerRope ).asInt(); int inPointsCount = data.inputValue( pointsCount ).asInt(); float inRopesStrength = data.inputValue( ropesStrength ).asFloat(); float inRadius = data.inputValue( radius ).asFloat(); MRampAttribute inRadRamp( thisMObject(), taperRamp ); float inTwist = data.inputValue( twist ).asFloat(); MRampAttribute inTwistRamp( thisMObject(), twistRamp ); float inUvWidth = data.inputValue( uvWidth ).asFloat(); float inUvHeight = data.inputValue( uvHeight ).asFloat(); float inUvCapSize = data.inputValue( uvCapSize ).asFloat(); MFnMesh fnMesh; MFnMeshData dataCreator; MObject outMeshData; outMeshData = dataCreator.create(); MDataHandle outputHandle = data.outputValue(outMesh); //createBase MIntArray faceCounts, faceConnects, uvIds; MFloatArray uArray, vArray; MFloatPointArray points; faceCounts.clear(); faceConnects.clear(); points.clear(); if (inCreateRope) inPointsCount = ( inPointsPerRope + 2 ) * inRopesCount; int numVertices = ( inDiv + 1 ) * inPointsCount; int numFaces = ( inPointsCount * inDiv ) + 2; float param; float lengPerDiv = curveFn.length() / inDiv; PrevNormal = MVector( curveFn.normal( 0.0, MSpace::kWorld ).normal() ); float baseLeng = lengPerDiv; float baseParamForRamp = 0; float paramForRamp = 1.0 / float( inDiv ); float uDivNumber = inUvWidth / float( inPointsCount ); float vDivNumber = inUvHeight / float( inDiv ); for (int d = 0; d < inDiv + 1; d++) { if (d == 0) { param = 0; faceCounts.append( inPointsCount ); for ( int i = inPointsCount - 1; i >= 0; i-- ) { faceConnects.append( i ); } for ( int i = 0; i < inPointsCount; i++ ) { uvIds.append( i ); } MFloatArray uTmpArray, vTmpArray; if (inCreateRope) createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, 1.0 ); else createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, 1.0 ); for ( int u = uTmpArray.length() - 1; u >= 0 ; u-- ) { uArray.append( uTmpArray[u] + 1.0 ); vArray.append( vTmpArray[u] ); } for ( int i = 0; i < inPointsCount + 1; i++ ) { uArray.append( uDivNumber * float( i ) ); vArray.append( vDivNumber * float( d ) ); } }else{ param = curveFn.findParamFromLength( baseLeng ); for ( int i = 0; i < inPointsCount + 1; i++ ) { uArray.append( uDivNumber * float( i ) ); vArray.append( vDivNumber * float( d ) ); } for ( int f = 0; f < inPointsCount; f++ ) { faceCounts.append( 4 ); if( f == ( inPointsCount - 1 )) { faceConnects.append( ( f + 1 + ( d * inPointsCount ) ) - inPointsCount - inPointsCount ); faceConnects.append( ( f + 1 + ( d * inPointsCount ) - inPointsCount ) ); faceConnects.append( f + 1 + ( d * inPointsCount ) - 1 ); faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount - 1 ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f); }else{ faceConnects.append( ( f + ( d * inPointsCount ) ) - inPointsCount ); faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount ); faceConnects.append( f + 1 + ( d * inPointsCount ) ); faceConnects.append( ( f + ( d * inPointsCount )) ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f); } } if ( d == inDiv ) { faceCounts.append( inPointsCount ); for ( int i = 0; i < inPointsCount; i++ ) { faceConnects.append( ( inPointsCount * inDiv ) + i ); uvIds.append( ( inPointsCount * ( inDiv + 2)) + i + inDiv + 1 ); } MFloatArray uTmpArray, vTmpArray; if (inCreateRope) createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, -1.0 ); else createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, -1.0 ); for ( int u = 0; u < uTmpArray.length(); u++ ) { uArray.append( uTmpArray[u] + 2.0 ); vArray.append( vTmpArray[u] ); } } baseLeng += lengPerDiv; } float divTwist; inTwistRamp.getValueAtPosition( baseParamForRamp, divTwist ); float divTaper; inRadRamp.getValueAtPosition( baseParamForRamp, divTaper ); baseParamForRamp += paramForRamp; if (inCreateRope) createRopesRings( inRopesCount, getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ), points, inPointsPerRope, inRopesStrength, inRadius * divTaper); else createCriclePoints( inPointsCount, getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ), points, inRadius * divTaper ); } fnMesh.create( numVertices, numFaces, points, faceCounts, faceConnects, uArray, vArray, outMeshData ); fnMesh.assignUVs( faceCounts, uvIds ); outputHandle.set(outMeshData); outputHandle.setClean(); } return MS::kSuccess; }
MStatus MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; // 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(); // == Get Mesh Functions and Iterators ========================== MFnMeshData inMeshDat(inMeshObj); MFnMesh inMeshFn(inMeshObj, &status); MCHECKERR(status, "ERROR getting inMeshFn\n"); MItMeshPolygon inMeshItPolygon(inMeshObj, &status); MCHECKERR(status, "ERROR getting inMeshItPolygon\n"); // Convert attr values to OSD enums OpenSubdiv::Sdc::SchemeType type = OpenSubdiv::Sdc::SCHEME_CATMARK; // // Create Far topology // OpenSubdiv::Sdc::Options options; options.SetVtxBoundaryInterpolation(ConvertMayaVtxBoundary(vertBoundaryMethod)); options.SetFVarLinearInterpolation(ConvertMayaFVarBoundary(fvarBoundaryMethod, fvarPropCorners)); options.SetCreasingMethod(creaseMethodVal ? OpenSubdiv::Sdc::Options::CREASE_CHAIKIN : OpenSubdiv::Sdc::Options::CREASE_UNIFORM); options.SetTriangleSubdivision(smoothTriangles ? OpenSubdiv::Sdc::Options::TRI_SUB_SMOOTH : OpenSubdiv::Sdc::Options::TRI_SUB_CATMARK); float maxCreaseSharpness=0.0f; OpenSubdiv::Far::TopologyRefiner * refiner = gatherTopology(inMeshFn, inMeshItPolygon, type, options, &maxCreaseSharpness); assert(refiner); // Refine & Interpolate refiner->RefineUniform(OpenSubdiv::Far::TopologyRefiner::UniformOptions(subdivisionLevel)); Vertex const * controlVerts = reinterpret_cast<Vertex const *>(inMeshFn.getRawPoints(&status)); std::vector<Vertex> refinedVerts( refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices()); Vertex const * srcVerts = controlVerts; Vertex * dstVerts = &refinedVerts[0]; for (int level = 1; level <= subdivisionLevel; ++level) { OpenSubdiv::Far::PrimvarRefiner(*refiner).Interpolate(level, srcVerts, dstVerts); srcVerts = dstVerts; dstVerts += refiner->GetLevel(level).GetNumVertices(); } // == Convert subdivided OpenSubdiv mesh to MFnMesh Data outputMesh ============= // Create New Mesh Data Object MFnMeshData newMeshData; MObject newMeshDataObj = newMeshData.create(&status); MCHECKERR(status, "ERROR creating outputData"); // Create out mesh status = convertToMayaMeshData(*refiner, refinedVerts, inMeshFn, newMeshDataObj); MCHECKERR(status, "ERROR convertOsdFarToMayaMesh"); // Propagate objectGroups from inMesh to outMesh (for per-facet shading, etc) status = createSmoothMesh_objectGroups(inMeshFn, inMeshDat, newMeshData, subdivisionLevel, refiner->GetLevel(subdivisionLevel).GetNumFaces()); // Write to output plug MDataHandle outMeshH = data.outputValue(a_output, &status); MCHECKERR(status, "ERROR getting polygon data handle\n"); outMeshH.set(newMeshDataObj); int isolation = std::min(10,(int)ceil(maxCreaseSharpness)+1); data.outputValue(a_recommendedIsolation).set(isolation); // == Cleanup OSD ============================================ // REVISIT: Re-add these deletes delete refiner; // 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, &status); status = outMeshH.copy(data.outputValue(a_inputPolymesh, &status)); MCHECKERR(status, "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; }
// Propagate objectGroups from inMesh to subdivided outMesh // Note: Currently only supporting facet groups (for per-facet shading) MStatus createSmoothMesh_objectGroups( MFnMesh const & inMeshFn, MFnMeshData const & inMeshDat, MFnMeshData &newMeshDat, int level, int numSubfaces ) { MStatus status; MIntArray newCompElems; std::vector<unsigned int> offsets; // mapping of offsets for subdivided faces for(unsigned int gi=0; gi<inMeshDat.objectGroupCount(); gi++) { unsigned int compId = inMeshDat.objectGroup(gi, &status); MCHECKERR(status, "cannot get objectGroup() comp ID."); MFn::Type compType = inMeshDat.objectGroupType(compId, &status); MCHECKERR(status, "cannot get objectGroupType()."); // Only supporting kMeshPolygonComponent ObjectGroups at this time // Skip the other types if (compType == MFn::kMeshPolygonComponent) { // get elements from inMesh objectGroupComponent MIntArray compElems; MFnSingleIndexedComponent compFn(inMeshDat.objectGroupComponent(compId), &status ); MCHECKERR(status, "cannot get MFnSingleIndexedComponent for inMeshDat.objectGroupComponent()."); compFn.getElements(compElems); if (compElems.length()==0) { continue; } // over-allocation to maximum possible length newCompElems.setLength( numSubfaces ); if (offsets.empty()) { // lazy population of the subface offsets table int nfaces = inMeshFn.numPolygons(); offsets.resize(nfaces); for (int i=0, count=0; i<nfaces; ++i) { int nverts = inMeshFn.polygonVertexCount(i), nsubfaces = computeNumSubfaces(nverts, level); offsets[i] = count; count+=nsubfaces; } } unsigned int idx = 0; // convert/populate newCompElems from compElems of inMesh // (with new face indices) to outMesh for (unsigned int i=0; i < compElems.length(); i++) { int nverts = inMeshFn.polygonVertexCount(compElems[i]), nsubfaces = computeNumSubfaces(nverts, level); unsigned int subFaceOffset = offsets[compElems[i]]; for (int j=0; j<nsubfaces; ++j) { newCompElems[idx++] = subFaceOffset++; } } // resize to actual length newCompElems.setLength( idx ); // create comp createComp(newMeshDat, compType, compId, newCompElems); } } return MS::kSuccess; }
MStatus fishVizNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MObject arbitaryMesh = data.inputValue(aInMesh).asMesh(); MDoubleArray ptc_time_offset; MDoubleArray ptc_amplitude; MDoubleArray ptc_bend; MDoubleArray ptc_scale; MDoubleArray masses; MString cacheName = data.inputValue(acachename, &status).asString(); MTime currentTime = data.inputValue(atime, &status).asTime(); cacheName = cacheName+"."+250*int(currentTime.value())+".pdc"; pdcFile* fpdc = new pdcFile(); if(fpdc->load(cacheName.asChar())==1) { //MGlobal::displayInfo(MString("FishViz loaded cache file: ")+cacheName); fpdc->readPositions(ptc_positions, ptc_velocities, ptc_ups, ptc_views, ptc_time_offset, ptc_amplitude, ptc_bend, ptc_scale, masses); } else MGlobal::displayWarning(MString("FishViz cannot open cache file: ")+cacheName); if(currentTime.value()!=int(currentTime.value())) { float delta_t = currentTime.value()-int(currentTime.value()); for(int i=0; i<fpdc->getParticleCount(); i++) { ptc_positions[i] += ptc_velocities[i]*delta_t/24.0f; } } delete fpdc; double flapping = zGetDoubleAttr(data, aFlapping); double bending= zGetDoubleAttr(data, aBending); double oscillate= zGetDoubleAttr(data, aOscillate); double length = zGetDoubleAttr(data, aLength); m_fish_length = length; double frequency = zGetDoubleAttr(data, aFrequency); unsigned num_bones = zGetIntAttr(data, aNBone); unsigned int nptc = ptc_positions.length(); MPointArray vertices; MATRIX44F mat44, mat_bone; XYZ vert, front, up, side; MDataHandle outputHandle = data.outputValue(outMesh, &status); zCheckStatus(status, "ERROR getting polygon data handle\n"); if(m_num_fish != nptc || m_num_bone != num_bones) { m_num_bone = num_bones; m_num_fish = nptc; unsigned int vertex_count; unsigned int face_count; MIntArray pcounts; MIntArray pconnect; unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertex_count = inmeshnv * nptc; face_count = inmeshnp * nptc; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices.append(MPoint(vert.x, vert.y, vert.z)); } for(unsigned int j=0; j<inmeshnp; j++) { pcounts.append(count_inmesh[j]); } } int acc=0; for(unsigned int i=0; i<nptc; i++) { for(unsigned int j=0; j<connect_inmesh.length(); j++) { pconnect.append(connect_inmesh[j]+acc); } acc += inmeshnv; } MObject m_mesh = outputHandle.asMesh(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); zCheckStatusNR(status, "ERROR creating outputData"); MFnMesh meshFn; m_mesh= meshFn.create( vertex_count, // number of vertices face_count, // number of polygons vertices, // The points pcounts, // # of vertex for each poly pconnect, // Vertices index for each poly newOutputData, // Dependency graph data object &status ); zCheckStatusNR(status, "ERROE creating mesh"); // Update surface // outputHandle.set(newOutputData); } else { MObject m_mesh = outputHandle.asMesh(); MFnMesh meshFn(m_mesh); unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertices.setLength(nptc*inmeshnv); int acc=0; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices[j+acc] = MPoint(vert.x, vert.y, vert.z); } acc += inmeshnv; } meshFn.setPoints(vertices); outputHandle.set(meshFn.object()); } //delete fmat; data.setClean( plug ); return MS::kSuccess; }
MStatus meshCacheNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; MString path = data.inputValue( input ).asString(); double time = data.inputValue( frame ).asTime().value(); int minfrm = data.inputValue( aminframe ).asInt(); //int maxfrm = data.inputValue( amaxframe ).asInt(); int frmstep = data.inputValue( aframestep ).asInt(); if( time < minfrm ) time = minfrm; int frame_lo = minfrm + int(time-minfrm)/frmstep*frmstep; int frame_hi = frame_lo+frmstep; char filename[256]; sprintf( filename, "%s.%d.mcf", path.asChar(), frame_lo ); FMCFMesh mesh; if(mesh.load(filename) != 1) { sprintf( filename, "%s.mcf", path.asChar()); if(mesh.load(filename) != 1) { MGlobal::displayError( MString("Failed to open file: ") + filename ); return MS::kFailure; } } int lo_n_vertex = mesh.getNumVertex(); vertexArray.clear(); vertexFArray.clear(); uArray.clear(); vArray.clear(); polygonCounts.clear(); polygonConnects.clear(); polygonUVs.clear(); for(unsigned int i = 0; i < mesh.getNumFace(); i++ ) { polygonCounts.append( mesh.getFaceCount(i) ); } for(unsigned int i = 0; i < mesh.getNumFaceVertex(); i++) { polygonConnects.append( mesh.getVertexId(i) ); polygonUVs.append( mesh.getUVId(i) ); } XYZ tp; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { mesh.getVertex(tp, i); vertexArray.append( MPoint( tp.x, tp.y, tp.z ) ); } for(unsigned int i = 0; i < mesh.getNumUV(); i++) { uArray.append( mesh.getS(i) ); vArray.append( mesh.getT(i) ); } if( time > frame_lo ) { sprintf( filename, "%s.%d.mcf", path.asChar(), frame_hi ); if(mesh.load(filename) != 1) { MGlobal::displayError( MString("Failed to open file: ") + filename ); } else if(mesh.getNumVertex() == lo_n_vertex) { XYZ tp; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { mesh.getVertex(tp, i); vertexFArray.append( MPoint( tp.x, tp.y, tp.z ) ); } double alpha = double(time-frame_lo) / (double)frmstep; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { vertexArray[i] = vertexArray[i] + alpha * ( vertexFArray[i] - vertexArray[i] ); } } } if( plug == outMesh ) { MDataHandle meshh = data.outputValue(outMesh, &stat); MFnMeshData dataCreator; MObject outMeshData = dataCreator.create(&stat); int numVertex = vertexArray.length(); int numPolygon = polygonCounts.length(); MFnMesh meshFn; meshFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat ); if( !stat ) { char log[256]; sprintf( log, "Failed to create mesh %s", filename ); MGlobal::displayError( log ); return MS::kFailure; } if( polygonUVs.length() != 0 ) { meshFn.setUVs ( uArray, vArray ); meshFn.assignUVs ( polygonCounts, polygonUVs ); } meshh.set(outMeshData); data.setClean(plug); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus testNobjectNode::compute(const MPlug &plug, MDataBlock &data) { MStatus stat; if ( plug == outputGeom ) { MObject inMeshObj = data.inputValue(inputGeom).asMesh(); cerr<<"pull on outputGeom\n"; MFnMeshData meshDataFn; MFnMesh inputMesh(inMeshObj); MObject newMeshObj = meshDataFn.create(); MFnMesh newMeshFn; newMeshFn.copy( inMeshObj, newMeshObj ); //get the value of the currentTime so it can correctly dirty the //startState, currentState. data.inputValue(currentTime).asTime(); // pull on next state. This will cause the solver to pull on either // the startState or the currentState, depending on the time of solve. // When we return the state to the solver, it will do the solve and update // The N Object data directly. MObject nextNObj = data.inputValue(nextState).data(); MFloatPointArray pts; //At this point the N Object's internal state should have been updated //by the solver. Read it out and set the output mesh. fNObject.getPositions(pts); if(pts.length() == (unsigned int) inputMesh.numVertices()) { newMeshFn.setPoints(pts); } newMeshFn.setObject( newMeshObj ); data.outputValue(outputGeom).set(newMeshObj); data.setClean(plug); } if ( plug == currentState ) { MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle currStateOutputHandle = data.outputValue(currentState); currStateOutputHandle.set(outputData.object()); cerr<<"pull on currentState\n"; } if ( plug == startState ) { int ii,jj; // initialize MnCloth MObject inMeshObj = data.inputValue(inputGeom).asMesh(); MFnMesh inputMesh(inMeshObj); int numPolygons = inputMesh.numPolygons(); int * faceVertCounts = new int[numPolygons]; int facesArrayLength = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); faceVertCounts[ii] = verts.length(); facesArrayLength += verts.length(); } int * faces = new int[facesArrayLength]; int currIndex = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); for(jj=0;jj<(int)verts.length();jj++) { faces[currIndex++] = verts[jj]; } } int numEdges = inputMesh.numEdges(); int * edges = new int[2*numEdges]; currIndex = 0; for(ii=0;ii<numEdges;ii++) { int2 edge; inputMesh.getEdgeVertices(ii,edge); edges[currIndex++] = edge[0]; edges[currIndex++] = edge[1]; } // When you are doing the initialization, the first call must to be setTopology(). All other // calls must come after this. fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges ); delete[] faceVertCounts; delete[] faces; delete[] edges; unsigned int numVerts = 0; numVerts = inputMesh.numVertices(); MFloatPointArray vertexArray; inputMesh.getPoints(vertexArray); fNObject.setPositions(vertexArray,true); MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = 0.0f; velocitiesArray[ii].y = 0.0f; velocitiesArray[ii].z = 0.0f; velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); fNObject.setThickness(0.05f); fNObject.setInverseMass(1.0f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setDamping(0.0f); fNObject.setBendResistance(0.0f); fNObject.setMaxIterations(100); fNObject.setMaxSelfCollisionIterations(100); fNObject.setStretchAndCompressionResistance(20.0f,10.0f); fNObject.setSelfCollisionFlags(false); fNObject.setCollisionFlags(true); MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle startStateOutputHandle = data.outputValue(startState); startStateOutputHandle.set(outputData.object()); cerr<<"pull on startState\n"; } else { stat = MS::kUnknownParameter; } return stat; }