MObject MG_poseReader::makePlane(const MVector& p1,const MVector& p2,const MVector& p3){ MFnMesh meshFn; MPoint p1p (p1); MPoint p2p (p2); MPoint p3p (p3); MPointArray pArray; pArray.append(p1p); pArray.append(p2p); pArray.append(p3p); MIntArray polyCount; polyCount.append(3); MIntArray polyConnect; polyConnect.append(0); polyConnect.append(1); polyConnect.append(2); MFnMeshData data; MObject polyData = data.create(); MStatus stat; meshFn.create(3,1,pArray,polyCount,polyConnect,polyData,&stat); return polyData; }
MStatus MeshParameterHandler::doSetValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const { IECore::ConstObjectParameterPtr p = IECore::runTimeCast<const IECore::ObjectParameter>( parameter ); if( !p ) { return MS::kFailure; } MFnMeshData fnData; MObject data = fnData.create(); /// \todo Pull in userData from parameter to set up conversion parameters ToMayaObjectConverterPtr converter = ToMayaObjectConverter::create( p->getValue(), MFn::kMeshData ); assert(converter); bool conversionSuccess = converter->convert( data ); if ( !conversionSuccess ) { return MS::kFailure; } /// \todo It seems like this can occassionally fail, usually with an empty mesh, but sometimes not. Try to establish exactly why. plug.setValue( data ); return MS::kSuccess; }
MStatus ClothSimMayaPlugin::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == g_aOutputMesh) { MDataHandle timeData = data.inputValue(g_aTime, &returnStatus); McheckErr(returnStatus, "Error getting time data handle\n"); MTime time = timeData.asTime(); /* Get output object */ MDataHandle outputHandle = data.outputValue(g_aOutputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); createMesh(time, newOutputData, returnStatus); if (!returnStatus) { std::cerr << "ERROR creating new Cube: " << returnStatus.errorString() << std::endl; return returnStatus; } outputHandle.set(newOutputData); data.setClean(plug); } else return MS::kUnknownParameter; return MS::kSuccess; }
MStatus animCube::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { /* Get time */ MDataHandle timeData = data.inputValue( time, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MTime time = timeData.asTime(); /* Get output object */ MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); createMesh(time, newOutputData, returnStatus); McheckErr(returnStatus, "ERROR creating new Cube"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
void MayaObject::getMeshData(MPointArray& points, MFloatVectorArray& normals) { MStatus stat; MObject meshObject = this->mobject; MMeshSmoothOptions options; MFnMesh tmpMesh(this->mobject); MFnMeshData meshData; MObject dataObject; MObject smoothedObj; // create smooth mesh if needed if (tmpMesh.findPlug("displaySmoothMesh").asBool()) { stat = tmpMesh.getSmoothMeshDisplayOptions(options); if (stat) { if (!tmpMesh.findPlug("useSmoothPreviewForRender", false, &stat).asBool()) { //Logging::debug(MString("useSmoothPreviewForRender turned off")); int smoothLevel = tmpMesh.findPlug("renderSmoothLevel", false, &stat).asInt(); options.setDivisions(smoothLevel); } if (options.divisions() > 0) { dataObject = meshData.create(); smoothedObj = tmpMesh.generateSmoothMesh(dataObject, &options, &stat); if (stat) { meshObject = smoothedObj; } } } } MFnMesh meshFn(meshObject, &stat); if (!stat) { MString error = stat.errorString(); Logging::error(error); } meshFn.getPoints(points); meshFn.getNormals(normals, MSpace::kObject); }
MStatus blindDataMesh::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { // Get the given random number generator seed. We need to use a // seed, because a pseudo-random number generator will always give // the same random numbers for a constant seed. This means that the // mesh will not change when it is recalculated. // MDataHandle seedHandle = data.inputValue(seed, &returnStatus); McheckErr(returnStatus,"ERROR getting random number generator seed\n"); long seed = seedHandle.asLong(); // Get the handle to the output mesh. The creation of the output mesh // is done in two steps. First, the mesh is created. That involves // calculating the position of the vertices and their connectivity. // // Second, blind data is associated to the vertices on the mesh. // For this example, three double blind data values is associated // to each vertex: "red", "green" and "blue". // MFnMeshData dataCreator; MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); createMesh(seed, newOutputData, returnStatus); McheckErr(returnStatus, "ERROR creating new plane"); returnStatus = setMeshBlindData(newOutputData); McheckErr(returnStatus, "ERROR setting the blind Data on the plane"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
MStatus LSystemNode::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { //angle MDataHandle angleData = data.inputValue(angle,&returnStatus); McheckErr(returnStatus, "Error getting angle data handle\n"); double angle = angleData.asDouble(); //step MDataHandle stepData = data.inputValue(step,&returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); double step = stepData.asDouble(); //grammar MDataHandle grammarData = data.inputValue(grammar,&returnStatus); McheckErr(returnStatus, "Error getting grammar data handle\n"); MString grammar = grammarData.asString(); /* Get time */ MDataHandle timeData = data.inputValue( time, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MTime time = timeData.asTime(); /* Get output object */ MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); createMesh(angle, step, grammar, time, newOutputData, returnStatus); McheckErr(returnStatus, "ERROR creating new Cube"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
MObject AppleseedRenderer::checkSmoothMesh(MObject& meshObject, MFnMeshData& smoothMeshData) { MStatus stat; MObject object = MObject::kNullObj; MFnMesh mesh(meshObject, &stat); if(!stat) { logger.error(MString("checkSmoothMesh : could not get mesh: ") + stat.errorString()); return object; } bool displaySmoothMesh = false; if( getBool("displaySmoothMesh", mesh, displaySmoothMesh) ) { if( !displaySmoothMesh ) return object; }else{ logger.error(MString("generateSmoothMesh : could not get displaySmoothMesh attr ")); return object; } MObject meshDataObj = smoothMeshData.create(); MObject smoothMeshObj = mesh.generateSmoothMesh(meshDataObj, &stat); if(!stat) { logger.error(MString("generateSmoothMesh : failed")); return object; } MFnMesh smoothMeshDn(smoothMeshObj, &stat); if(!stat) { logger.error(MString("generateSmoothMesh : could not create smoothMeshDn: ") + stat.errorString()); return object; } return smoothMeshObj; }
void MayaGeoAttribute::transferValueToMaya(MPlug &plug, MDataBlock &data){ coral::Geo *coralGeo = value(); const std::vector<Imath::V3f> &coralPoints = coralGeo->points(); // transfer points MFloatPointArray mayaPoints; for(int i = 0; i < coralPoints.size(); ++i){ const Imath::V3f *coralPoint = &coralPoints[i]; mayaPoints.append(MFloatPoint(coralPoint->x, coralPoint->y, coralPoint->z)); } // transfer faces MIntArray mayaFaceCount; MIntArray mayaFaceVertices; const std::vector<std::vector<int> > coralFaces = coralGeo->rawFaces(); for(int polyId = 0; polyId < coralFaces.size(); ++polyId){ const std::vector<int> *coralFace = &coralFaces[polyId]; int faceVertexCount = coralFace->size(); mayaFaceCount.append(faceVertexCount); for(int i = 0; i < faceVertexCount; ++i){ mayaFaceVertices.append(coralFace->at(i)); } } // create maya mesh MDataHandle dataHandle = data.outputValue(plug); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(); MFnMesh newMesh; newMesh.create(mayaPoints.length(), coralFaces.size(), mayaPoints, mayaFaceCount, mayaFaceVertices, newOutputData); dataHandle.set(newOutputData); }
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); // Storage for face-varying values (UV sets, vertex colors...) std::vector<MFloatArray> uvSet_uCoords; std::vector<MFloatArray> uvSet_vCoords; std::vector<MColorArray> colorSet_colors; bool hasUVs = false, hasColors = false; float maxCreaseSharpness=0.0f; OpenSubdiv::Far::TopologyRefiner * refiner = gatherTopology( inMeshFn, inMeshItPolygon, type, options, &hasUVs, &hasColors, uvSet_uCoords, uvSet_vCoords, colorSet_colors, &maxCreaseSharpness); assert(refiner); // == Refine & Interpolate ========================== refiner->RefineUniform(OpenSubdiv::Far::TopologyRefiner::UniformOptions(subdivisionLevel)); // Prepare vertex information Vertex const * initialVerts = reinterpret_cast<Vertex const *>(inMeshFn.getRawPoints(&status)); std::vector<Vertex> refinedVerts( refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices()); Vertex const * srcVerts = &initialVerts[0]; Vertex * dstVerts = &refinedVerts[0]; // Verify the refiner has the correct number of values // needed to interpolate the different channels int numInitialUVs = refiner->GetLevel(0).GetNumFVarValues(CHANNELUV); int numInitialColors = refiner->GetLevel(0).GetNumFVarValues(CHANNELCOLOR); if (hasUVs && numInitialUVs <= 0) { hasUVs = false; MGlobal::displayError("Model with incorrect data, the UV channel will not be interpolated."); } if (hasColors && numInitialColors <= 0) { hasColors = false; MGlobal::displayError("Model with incorrect data, the color channel will not be interpolated."); } // Prepare UV information if needed std::vector<FVarVertexUV> initialUVs, refinedUVs; FVarVertexUV const * srcUV = NULL; FVarVertexUV * dstUV = NULL; if(hasUVs) { initialUVs.resize(numInitialUVs); refinedUVs.resize(refiner->GetNumFVarValuesTotal(CHANNELUV)); for (int i=0; i<numInitialUVs; ++i) { initialUVs[i].u = uvSet_uCoords[0][i]; initialUVs[i].v = uvSet_vCoords[0][i]; } srcUV = &initialUVs[0]; dstUV = &refinedUVs[0]; } // Prepare color information if needed std::vector<FVarVertexColor> initialColors, refinedColors; FVarVertexColor const * srcColor = NULL; FVarVertexColor * dstColor = NULL; if(hasColors) { initialColors.resize(numInitialColors); refinedColors.resize(refiner->GetNumFVarValuesTotal(CHANNELCOLOR)); for (int i=0; i<numInitialColors; ++i) { initialColors[i].r = colorSet_colors[0][i].r; initialColors[i].g = colorSet_colors[0][i].g; initialColors[i].b = colorSet_colors[0][i].b; initialColors[i].a = colorSet_colors[0][i].a; } srcColor = &initialColors[0]; dstColor = &refinedColors[0]; } // Interpolate the vertices and the different channels OpenSubdiv::Far::PrimvarRefiner primvarRefiner(*refiner); for (int level = 1; level <= subdivisionLevel; ++level) { // Interpolate vertices primvarRefiner.Interpolate(level, srcVerts, dstVerts); srcVerts = dstVerts; dstVerts += refiner->GetLevel(level).GetNumVertices(); // Interpolate the uv set if(hasUVs) { primvarRefiner.InterpolateFaceVarying(level, srcUV, dstUV, CHANNELUV); srcUV = dstUV; dstUV += refiner->GetLevel(level).GetNumFVarValues(CHANNELUV); } // Interpolate any color set if(hasColors) { primvarRefiner.InterpolateFaceVarying(level, srcColor, dstColor, CHANNELCOLOR); srcColor = dstColor; dstColor += refiner->GetLevel(level).GetNumFVarValues(CHANNELCOLOR); } } // == 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, hasUVs, refinedUVs, hasColors, refinedColors, 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; }
void MayaObject::getMeshData(MPointArray& points, MFloatVectorArray& normals, MFloatArray& uArray, MFloatArray& vArray, MIntArray& triPointIndices, MIntArray& triNormalIndices, MIntArray& triUvIndices, MIntArray& triMatIndices) { MStatus stat; MObject meshObject = this->mobject; MMeshSmoothOptions options; MFnMesh tmpMesh(this->mobject, &stat); MFnMeshData meshData; MObject dataObject; MObject smoothedObj; // create smooth mesh if needed if (tmpMesh.findPlug("displaySmoothMesh").asBool()) { stat = tmpMesh.getSmoothMeshDisplayOptions(options); if (stat) { if (!tmpMesh.findPlug("useSmoothPreviewForRender", false, &stat).asBool()) { //Logging::debug(MString("useSmoothPreviewForRender turned off")); int smoothLevel = tmpMesh.findPlug("renderSmoothLevel", false, &stat).asInt(); options.setDivisions(smoothLevel); } if (options.divisions() > 0) { dataObject = meshData.create(); smoothedObj = tmpMesh.generateSmoothMesh(dataObject, &options, &stat); if (stat) { meshObject = smoothedObj; } } } } MFnMesh meshFn(meshObject, &stat); CHECK_MSTATUS(stat); MItMeshPolygon faceIt(meshObject, &stat); CHECK_MSTATUS(stat); meshFn.getPoints(points); meshFn.getNormals(normals, MSpace::kObject); meshFn.getUVs(uArray, vArray); uint numVertices = points.length(); uint numNormals = normals.length(); uint numUvs = uArray.length(); //Logging::debug(MString("numVertices ") + numVertices); //Logging::debug(MString("numNormals ") + numNormals); //Logging::debug(MString("numUvs ") + numUvs); // some meshes may have no uv's // to avoid problems I add a default uv coordinate if (numUvs == 0) { Logging::warning(MString("Object has no uv's: ") + this->shortName); uArray.append(0.0); vArray.append(0.0); } for (uint nid = 0; nid < numNormals; nid++) { if (normals[nid].length() < 0.1f) Logging::warning(MString("Malformed normal in ") + this->shortName); } MPointArray triPoints; MIntArray triVtxIds; MIntArray faceVtxIds; MIntArray faceNormalIds; for (faceIt.reset(); !faceIt.isDone(); faceIt.next()) { int faceId = faceIt.index(); int numTris; faceIt.numTriangles(numTris); faceIt.getVertices(faceVtxIds); int perFaceShadingGroup = 0; if (this->perFaceAssignments.length() > 0) perFaceShadingGroup = this->perFaceAssignments[faceId]; MIntArray faceUVIndices; faceNormalIds.clear(); for (uint vtxId = 0; vtxId < faceVtxIds.length(); vtxId++) { faceNormalIds.append(faceIt.normalIndex(vtxId)); int uvIndex; if (numUvs == 0) { faceUVIndices.append(0); } else{ faceIt.getUVIndex(vtxId, uvIndex); //if (uvIndex > uArray.length()) // Logging::info(MString("-----------------> UV Problem!!! uvIndex ") + uvIndex + " > uvArray in object " + this->shortName); faceUVIndices.append(uvIndex); } } for (int triId = 0; triId < numTris; triId++) { int faceRelIds[3]; faceIt.getTriangle(triId, triPoints, triVtxIds); for (uint triVtxId = 0; triVtxId < 3; triVtxId++) { for (uint faceVtxId = 0; faceVtxId < faceVtxIds.length(); faceVtxId++) { if (faceVtxIds[faceVtxId] == triVtxIds[triVtxId]) { faceRelIds[triVtxId] = faceVtxId; } } } uint vtxId0 = faceVtxIds[faceRelIds[0]]; uint vtxId1 = faceVtxIds[faceRelIds[1]]; uint vtxId2 = faceVtxIds[faceRelIds[2]]; uint normalId0 = faceNormalIds[faceRelIds[0]]; uint normalId1 = faceNormalIds[faceRelIds[1]]; uint normalId2 = faceNormalIds[faceRelIds[2]]; uint uvId0 = faceUVIndices[faceRelIds[0]]; uint uvId1 = faceUVIndices[faceRelIds[1]]; uint uvId2 = faceUVIndices[faceRelIds[2]]; triPointIndices.append(vtxId0); triPointIndices.append(vtxId1); triPointIndices.append(vtxId2); triNormalIndices.append(normalId0); triNormalIndices.append(normalId1); triNormalIndices.append(normalId2); triUvIndices.append(uvId0); triUvIndices.append(uvId1); triUvIndices.append(uvId2); triMatIndices.append(perFaceShadingGroup); //Logging::debug(MString("vtxIds ") + vtxId0 + " " + vtxId1 + " " + vtxId2); //Logging::debug(MString("nIds ") + normalId0 + " " + normalId1 + " " + normalId2); //Logging::debug(MString("uvIds ") + uvId0 + " " + uvId1 + " " + uvId2); } } }
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 LSSolverNode::compute(const MPlug& plug, MDataBlock& data) { MStatus stat; if( plug == deformed) { MDataHandle tetWorldMatrixData = data.inputValue(tetWorldMatrix, &returnStatus); McheckErr(returnStatus, "Error getting tetWorldMatrix data handle\n"); MDataHandle restShapeData = data.inputValue(restShape, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restVerticesData = data.inputValue(restVertices, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restElementsData = data.inputValue(restElements, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedConstraintVertsData = data.inputValue(selectedConstraintVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedForceVertsData = data.inputValue(selectedForceVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle timeData = data.inputValue(time, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle outputMeshData = data.outputValue(deformed, &returnStatus); McheckErr(returnStatus, "Error getting outputMesh data handle\n"); MMatrix twmat = tetWorldMatrixData.asMatrix(); MObject rs = restShapeData.asMesh(); double t = timeData.asDouble(); MDataHandle poissonRatioData = data.inputValue(poissonRatio, &returnStatus); McheckErr(returnStatus, "Error getting poissonRatio data handle\n"); MDataHandle youngsModulusData = data.inputValue(youngsModulus, &returnStatus); McheckErr(returnStatus, "Error getting youngsmodulus data handle\n"); MDataHandle objectDensityData = data.inputValue(objectDensity, &returnStatus); McheckErr(returnStatus, "Error getting objectDensity data handle\n"); MDataHandle frictionData = data.inputValue(friction, &returnStatus); McheckErr(returnStatus, "Error getting friction data handle\n"); MDataHandle restitutionData = data.inputValue(restitution, &returnStatus); McheckErr(returnStatus, "Error getting restitution data handle\n"); MDataHandle dampingData = data.inputValue(damping, &returnStatus); McheckErr(returnStatus, "Error getting damping data handle\n"); MDataHandle userSuppliedDtData = data.inputValue(userSuppliedDt, &returnStatus); McheckErr(returnStatus, "Error getting user supplied dt data handle\n"); MDataHandle integrationTypeData = data.inputValue(integrationType, &returnStatus); McheckErr(returnStatus, "Error getting user integrationTypeData\n"); MDataHandle forceModelTypeData = data.inputValue(forceModelType, &returnStatus); McheckErr(returnStatus, "Error getting user forceModelTypeData\n"); MDataHandle forceApplicationTimeData = data.inputValue(forceApplicationTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceApplicationTime\n"); MDataHandle forceReleasedTimeData = data.inputValue(forceReleasedTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceReleasedTime\n"); MDataHandle forceIncrementTimeData = data.inputValue(forceIncrementTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceIncrementTime\n"); MDataHandle forceStartTimeData = data.inputValue(forceStartTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStartTime\n"); MDataHandle forceStopTimeData = data.inputValue(forceStopTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStopTime\n"); MDataHandle forceMagnitudeData = data.inputValue(forceMagnitude, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedForceData = data.inputValue(useSuppliedForce, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedConstraintsData = data.inputValue(useSuppliedConstraints, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle forceDirectionData = data.inputValue(forceDirection, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKsData = data.inputValue(contactKs, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKdData = data.inputValue(contactKd, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MTime currentTime, maxTime; currentTime = MAnimControl::currentTime(); maxTime = MAnimControl::maxTime(); if (currentTime == MAnimControl::minTime()) { // retrive restVertices and restElements MFnDoubleArrayData restVertArrayData(restVerticesData.data()); MDoubleArray verts = restVertArrayData.array(); int vertArrayLen = verts.length(); double *vertArray = new double[vertArrayLen]; verts.get(vertArray); for(int v=0;v<vertArrayLen;v=v+3) { MPoint mpoint = MPoint(vertArray[v],vertArray[v+1],vertArray[v+2])*twmat; vertArray[v] = mpoint.x; vertArray[v+1] = mpoint.y; vertArray[v+2] = mpoint.z; } MFnIntArrayData restEleArrayData(restElementsData.data()); MIntArray ele = restEleArrayData.array(); int eleArrayLen = ele.length(); int *eleArray = new int[eleArrayLen]; ele.get(eleArray); MFnIntArrayData selectedConstraintVertsArrayData(selectedConstraintVertsData.data()); MIntArray sv = selectedConstraintVertsArrayData.array(); // building selectedConstraintVerts vector<int> selectedConstraintVertIndices; for (int i = 0 ; i < sv.length() ; i++) { selectedConstraintVertIndices.push_back(sv[i]); } MFnIntArrayData selectedForceVertsArrayData(selectedForceVertsData.data()); MIntArray sf = selectedForceVertsArrayData.array(); vector<int> selectedForceVertIndices; for (int i = 0 ; i < sf.length() ; i++) { selectedForceVertIndices.push_back(sf[i]); } // temporarily create force direction vector double *forceDir = forceDirectionData.asDouble3(); vector<double> dir; dir.push_back(forceDir[0]); dir.push_back(forceDir[1]);dir.push_back(forceDir[2]); prevDeformed = 0; double youngsModulusDouble = youngsModulusData.asDouble(); double poissonRatioDouble = poissonRatioData.asDouble(); double objectDensityDouble = objectDensityData.asDouble(); double frictionDouble = frictionData.asDouble(); double restitutionDouble = restitutionData.asDouble(); double dampingDouble = dampingData.asDouble(); double userSuppliedDtDouble = userSuppliedDtData.asDouble(); double forceMagnitudeDouble = forceMagnitudeData.asDouble(); int fAppT = forceApplicationTimeData.asInt(); int fReleasedT = forceReleasedTimeData.asInt(); int fIncT = forceIncrementTimeData.asInt(); int fStartT = forceStartTimeData.asInt(); int fStopT = forceStopTimeData.asInt(); int integrationTypeInt = integrationTypeData.asShort(); int forceModelTypeInt = forceModelTypeData.asShort(); bool useSuppliedForceBool = useSuppliedForceData.asBool(); bool useSuppliedConstraintsBool = useSuppliedConstraintsData.asBool(); double contactKs = contactKsData.asDouble(); double contactKd = contactKdData.asDouble(); if( sm) { delete sm; } sm = new SoftBodySim(youngsModulusDouble,poissonRatioDouble,objectDensityDouble, frictionDouble,restitutionDouble,dampingDouble, eleArrayLen, eleArray, vertArrayLen, vertArray,integrationTypeInt,forceModelTypeInt); sm->setContactAttributes(contactKs,contactKd); if (useSuppliedConstraintsBool) sm->initialize("",userSuppliedDtDouble, selectedConstraintVertIndices); else { vector<int> empty; sm->initialize("",userSuppliedDtDouble, empty); } if (useSuppliedForceBool) sm->setUserForceAttributes(forceMagnitudeDouble, dir,selectedForceVertIndices,fAppT,fReleasedT,fIncT,fStartT,fStopT); } else { sm->update(); } MFnMesh surfFn(rs,&stat); McheckErr( stat, "compute - MFnMesh error" ); MFnMeshData ouputMeshDataCreator; MObject oMesh = ouputMeshDataCreator.create(&stat); buildOutputMesh(surfFn, sm->m_vertices,oMesh); outputMeshData.set(oMesh); data.setClean(plug); } else stat = MS::kUnknownParameter; return stat; }
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; }
/*! 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 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; }
// ========================================================================================================== // ========================================================================================================== virtual MStatus compute(const MPlug& plug, MDataBlock& dataBlock) { // enable this node or not if ( dataBlock.inputValue(aEnable).asBool() == false ) { return MS::kSuccess; } // check if the inpute attribute is connected // in Not, stop compute() // in order to avoid crash when disconnect input attributes on the fly //cout << "isPlugConnect: " << isPlugConnect(aVolumeObj) << endl; if ( isPlugConnect(aSourceObj) == false || isPlugConnect(aVolumeObj) == false ) { return MS::kSuccess; } // execution when output attr needs to be updated if ( plug == aOutValue || plug == aOutMesh || plug == aOutCompList ) { // test if input source object is a valid type if ( dataBlock.inputValue(aSourceObj).type() != MFnData::kMesh ) { MGlobal::displayInfo( MString("No Object Input!") ); return MS::kSuccess; } MObject sourceObj = dataBlock.inputValue(aSourceObj).asMeshTransformed(); MArrayDataHandle arrayHandle = dataBlock.inputValue(aVolumeObj); arrayHandle.jumpToArrayElement(0); MSelectionList sList; // add the vertice every ligal loop for ( int idx=0; idx < arrayHandle.elementCount(); idx++, arrayHandle.next() ) { // first, check if the sub-plug is un-connected if ( isPlugConnect( aVolumeObj, idx ) == false ) { cout << "No Data " << idx << endl; continue; } // second, check if the input object is mesh if ( arrayHandle.inputValue().type() != MFnData::kMesh ) { return MS::kSuccess; MGlobal::displayError( "input voulme objects is not mesh" ); } // input volume object as Wrold mesh MObject volumeObj = arrayHandle.inputValue().asMeshTransformed(); MFnMesh sourceMeshFn; MFnMesh volumeMeshFn; // third, test if the input obj is compatible with meshFn if ( volumeMeshFn.hasObj(sourceObj) && volumeMeshFn.hasObj(volumeObj) ) { volumeMeshFn.setObject(volumeObj); // check if object is closed if ( isClosedMesh(volumeObj) == false ) { if ( dataBlock.inputValue(aClosedObj).asBool() == true ) { //MGlobal::displayInfo( MString("The volume object is not closed!") ); continue; } } sourceMeshFn.setObject( sourceObj ); int numVtx = sourceMeshFn.numVertices(); vector<int> tmpCompArray; // an temporary int array to store component index // do hit test // to check if each source's component is inside // for ( int i=0; i < numVtx; i++ ) { // get each vertex of source object MPoint srcVtx; sourceMeshFn.getPoint( i, srcVtx, MSpace::kWorld ); // Test how much hit is for each vertex // declare parameters for allIntersection() MFloatPoint raySource; raySource.setCast(srcVtx); MFloatVector rayDirection(0, 0, 1); MFloatPointArray hitPoints; MIntArray hitFaces; bool hit = volumeMeshFn.allIntersections( raySource, rayDirection, NULL, NULL, false, MSpace::kWorld, 99999, false, NULL, true, hitPoints, NULL, &hitFaces, NULL, NULL, NULL, 1e-6 ); if (hit) { int isInside = hitFaces.length() % 2; // cout << "isInside: " << isInside << endl; // if the mod is odd, it's inside if ( isInside > 0 ) { tmpCompArray.push_back(i); } } } // declare a dynamic array to recieve All elements from tmpCompArray int* compArray = new int[tmpCompArray.size()]; // copy array data from tmpCompArray --> compArray memcpy( &compArray[0], &tmpCompArray[0], sizeof( int ) * tmpCompArray.size() ); // the below processes are to collect component data, and then select them in viewport // // first, get dagPath from the source object MDagPath dPathSrcObj = getConnectNodeDagPath(aSourceObj); // second, get the selection list storing components by feeding comopnet array MSelectionList vtxSelList = getVtxSelList( dPathSrcObj, compArray, tmpCompArray.size() ); sList.merge(vtxSelList); delete [] compArray; } } // end of loop // if so, actively select these component int compType = dataBlock.inputValue(aComponentType).asInt(); MSelectionList currCompSelList; if( dataBlock.inputValue(aKeepSel).asBool() == true ) { // clear if last-time is not keep selection if (flag==0) { addSelComponentList.clear(); flag = 1; } else { addSelComponentList.merge(sList); // merge the accumulative components currCompSelList = convertVtxSListToCompSList( addSelComponentList, compType ); MGlobal::setActiveSelectionList( currCompSelList, MGlobal::kReplaceList ); flag = 1; } } else { addSelComponentList.clear(); // celar all components addSelComponentList.merge(sList); currCompSelList = convertVtxSListToCompSList( addSelComponentList, compType ); MGlobal::setActiveSelectionList( currCompSelList, MGlobal::kReplaceList ); flag = 0; } // keep this node selecting if ( dataBlock.inputValue(aFixPanel).asBool() == true ) MGlobal::select( thisMObject(), MGlobal::kAddToList ); // **** OUTPUT ATTRIBUTE **** MObject currCompList = getCompListFromSList( currCompSelList ); MFnComponentListData compListDataFn; MObject currCompListData = compListDataFn.create(); // pointer to the component data compListDataFn.add( currCompList ); dataBlock.outputValue(aOutCompList).set( currCompListData ); // MFnMeshData outMeshDataFn; MObject outObj = outMeshDataFn.create(); MFnMesh outMeshFn( outObj ); outMeshFn.copy( sourceObj, outObj ); dataBlock.outputValue(aOutMesh).set( outObj ); } // end of if ( plug == aOutValue || plug == aOutMesh ) return MS::kSuccess; }
MStatus LSystemNode::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { /* Get time */ MDataHandle timeData = data.inputValue( time, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MTime time = timeData.asTime(); MDataHandle angleData = data.inputValue( angle, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); double angle_value = angleData.asDouble(); MDataHandle stepsData = data.inputValue( steps, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); double steps_value = stepsData.asDouble(); MDataHandle grammarData = data.inputValue( grammar, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MString grammar_value = grammarData.asString(); /* Get output object */ MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); MFnMesh myMesh; MPointArray points; MIntArray faceCounts; MIntArray faceConnects; //MString grammar = ("F\\nF->F[+F]F[-F]F"); CylinderMesh *cm; LSystem system; system.loadProgramFromString(grammar_value.asChar()); system.setDefaultAngle(angle_value); system.setDefaultStep(steps_value); std::vector<LSystem::Branch> branches; system.process(time.value(), branches); int k = branches.size(); for(int j = 0; j < branches.size(); j++) { //1. find the position for start and end point of current branch //2. generate a cylinder MPoint start(branches[j].first[0],branches[j].first[1],branches[j].first[2]); MPoint end(branches[j].second[0],branches[j].second[1],branches[j].second[2]); cm = new CylinderMesh(start, end); cm->appendToMesh(points, faceCounts, faceConnects); } MObject newMesh = myMesh.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newOutputData, &returnStatus); McheckErr(returnStatus, "ERROR creating new mesh"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
// ==================================== // 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 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; }
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 LSSolverNode::compute(const MPlug& plug, MDataBlock& data) { MStatus stat; if( plug == deformed) { MDataHandle tetWorldMatrixData = data.inputValue(tetWorldMatrix, &returnStatus); McheckErr(returnStatus, "Error getting tetWorldMatrix data handle\n"); MDataHandle restShapeData = data.inputValue(restShape, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restVerticesData = data.inputValue(restVertices, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restElementsData = data.inputValue(restElements, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedConstraintVertsData = data.inputValue(selectedConstraintVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedForceVertsData = data.inputValue(selectedForceVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle timeData = data.inputValue(time, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle outputMeshData = data.outputValue(deformed, &returnStatus); McheckErr(returnStatus, "Error getting outputMesh data handle\n"); MMatrix twmat = tetWorldMatrixData.asMatrix(); MObject rs = restShapeData.asMesh(); double t = timeData.asDouble(); MDataHandle poissonRatioData = data.inputValue(poissonRatio, &returnStatus); McheckErr(returnStatus, "Error getting poissonRatio data handle\n"); MDataHandle youngsModulusData = data.inputValue(youngsModulus, &returnStatus); McheckErr(returnStatus, "Error getting youngsmodulus data handle\n"); MDataHandle objectDensityData = data.inputValue(objectDensity, &returnStatus); McheckErr(returnStatus, "Error getting objectDensity data handle\n"); MDataHandle frictionData = data.inputValue(friction, &returnStatus); McheckErr(returnStatus, "Error getting friction data handle\n"); MDataHandle restitutionData = data.inputValue(restitution, &returnStatus); McheckErr(returnStatus, "Error getting restitution data handle\n"); MDataHandle dampingData = data.inputValue(damping, &returnStatus); McheckErr(returnStatus, "Error getting damping data handle\n"); MDataHandle userSuppliedDtData = data.inputValue(userSuppliedDt, &returnStatus); McheckErr(returnStatus, "Error getting user supplied dt data handle\n"); MDataHandle integrationTypeData = data.inputValue(integrationType, &returnStatus); McheckErr(returnStatus, "Error getting user integrationTypeData\n"); MDataHandle forceModelTypeData = data.inputValue(forceModelType, &returnStatus); McheckErr(returnStatus, "Error getting user forceModelTypeData\n"); MDataHandle forceApplicationTimeData = data.inputValue(forceApplicationTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceApplicationTime\n"); MDataHandle forceReleasedTimeData = data.inputValue(forceReleasedTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceReleasedTime\n"); MDataHandle forceIncrementTimeData = data.inputValue(forceIncrementTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceIncrementTime\n"); MDataHandle forceStartTimeData = data.inputValue(forceStartTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStartTime\n"); MDataHandle forceStopTimeData = data.inputValue(forceStopTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStopTime\n"); MDataHandle forceMagnitudeData = data.inputValue(forceMagnitude, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedForceData = data.inputValue(useSuppliedForce, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedConstraintsData = data.inputValue(useSuppliedConstraints, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle forceDirectionData = data.inputValue(forceDirection, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKsData = data.inputValue(contactKs, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKdData = data.inputValue(contactKd, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MTime currentTime, maxTime; currentTime = MAnimControl::currentTime(); maxTime = MAnimControl::maxTime(); if (currentTime == MAnimControl::minTime()) { // retrive restVertices and restElements sTime=0; MFnDoubleArrayData restVertArrayData(restVerticesData.data()); MDoubleArray verts = restVertArrayData.array(); int vertArrayLen = verts.length(); double *vertArray = new double[vertArrayLen]; verts.get(vertArray); for(int v=0;v<vertArrayLen;v=v+3) { MPoint mpoint = MPoint(vertArray[v],vertArray[v+1],vertArray[v+2])*twmat; vertArray[v] = mpoint.x; vertArray[v+1] = mpoint.y; vertArray[v+2] = mpoint.z; } MFnIntArrayData restEleArrayData(restElementsData.data()); MIntArray ele = restEleArrayData.array(); int eleArrayLen = ele.length(); int *eleArray = new int[eleArrayLen]; ele.get(eleArray); MFnIntArrayData selectedConstraintVertsArrayData(selectedConstraintVertsData.data()); MIntArray sv = selectedConstraintVertsArrayData.array(); // building selectedConstraintVerts vector<int> selectedConstraintVertIndices; for (int i = 0 ; i < sv.length() ; i++) { selectedConstraintVertIndices.push_back(sv[i]); } MGlobal::displayInfo("!!!!!"); //std::string tmp=std::to_string((long double)selectedConstraintVertIndices.size()); //MGlobal::displayInfo(MString(tmp.c_str())); //std::cout<<currentConstriant<<" up"<<std::endl; for(int i=0;i<constraintIndex[currentConstriant].size();i++){ if(domainParentIndex[currentConstriant]==-1) selectedConstraintVertIndices.push_back(constraintIndex[currentConstriant][i]); //std::cout<<constraintIndex[currentConstriant][i]<<std::endl; } //std::cout<<currentConstriant<<" up"<<std::endl; /*for(int i=0;i<10;i++){ selectedConstraintVertIndices.push_back(i+1); }*/ MFnIntArrayData selectedForceVertsArrayData(selectedForceVertsData.data()); MIntArray sf = selectedForceVertsArrayData.array(); vector<int> selectedForceVertIndices; for (int i = 0 ; i < sf.length() ; i++) { selectedForceVertIndices.push_back(sf[i]); } // temporarily create force direction vector double *forceDir = forceDirectionData.asDouble3(); vector<double> dir; dir.push_back(forceDir[0]); dir.push_back(forceDir[1]);dir.push_back(forceDir[2]); prevDeformed = 0; double youngsModulusDouble = youngsModulusData.asDouble(); double poissonRatioDouble = poissonRatioData.asDouble(); double objectDensityDouble = objectDensityData.asDouble(); double frictionDouble = frictionData.asDouble(); double restitutionDouble = restitutionData.asDouble(); double dampingDouble = dampingData.asDouble(); double userSuppliedDtDouble = userSuppliedDtData.asDouble(); double forceMagnitudeDouble = forceMagnitudeData.asDouble(); int fAppT = forceApplicationTimeData.asInt(); int fReleasedT = forceReleasedTimeData.asInt(); int fIncT = forceIncrementTimeData.asInt(); int fStartT = forceStartTimeData.asInt(); int fStopT = forceStopTimeData.asInt(); int integrationTypeInt = integrationTypeData.asShort(); int forceModelTypeInt = forceModelTypeData.asShort(); bool useSuppliedForceBool = useSuppliedForceData.asBool(); bool useSuppliedConstraintsBool = useSuppliedConstraintsData.asBool(); double contactKs = contactKsData.asDouble(); double contactKd = contactKdData.asDouble(); if( sm) { delete sm; } sm = new SoftBodySim(youngsModulusDouble,poissonRatioDouble,objectDensityDouble, frictionDouble,restitutionDouble,dampingDouble, eleArrayLen, eleArray, vertArrayLen, vertArray,integrationTypeInt,forceModelTypeInt); sm->setContactAttributes(contactKs,contactKd); if (useSuppliedConstraintsBool) sm->initialize("",userSuppliedDtDouble, selectedConstraintVertIndices); else { vector<int> empty; sm->initialize("",userSuppliedDtDouble, empty); } if (useSuppliedForceBool) sm->setUserForceAttributes(forceMagnitudeDouble, dir,selectedForceVertIndices,fAppT,fReleasedT,fIncT,fStartT,fStopT); std::vector<int> childList=fdg.GetDomainChild(currentConstriant); if(childList.size()!=0){//not the root for(int i=0;i<childList.size();i++){ int childIndex=-1; for(int j=0;j<fdomain_list.size();j++){ if(fdomain_list[j]->index==childList[i]){ childIndex=j; } }//j glm::dvec3 oldPos=glm::dvec3(0,0,0); for(int j=0;j<parentConstraintIndex[childIndex].size();j++){ int index=3*parentConstraintIndex[childIndex][j]; oldPos.x+=sm->m_vertices[index]; oldPos.y+=sm->m_vertices[index+1]; oldPos.z+=sm->m_vertices[index+2]; } oldPos=oldPos*(1.0/parentConstraintIndex[childIndex].size()); parentLastPosOld[childIndex]=oldPos; parentLastPosNew[childIndex]=oldPos; }//i } domainID=currentConstriant; currentConstriant++; if(currentConstriant==fdomain_list.size()) currentConstriant=0; } else { std::vector<int> childList=fdg.GetDomainChild(domainID); if(childList.size()!=0){//not the root for(int i=0;i<childList.size();i++){ int childIndex=-1; for(int j=0;j<fdomain_list.size();j++){ if(fdomain_list[j]->index==childList[i]){ childIndex=j; } }//j glm::dvec3 newPos=glm::dvec3(0,0,0); for(int j=0;j<parentConstraintIndex[childIndex].size();j++){ int index=3*parentConstraintIndex[childIndex][j]; newPos.x+=sm->m_vertices[index]; newPos.y+=sm->m_vertices[index+1]; newPos.z+=sm->m_vertices[index+2]; } //std::cout<<newPos.x<<","<<newPos.y<<","<<newPos.z<<std::endl; newPos=newPos*(1.0/parentConstraintIndex[childIndex].size()); parentLastPosOld[childIndex]=parentLastPosNew[childIndex]; parentLastPosNew[childIndex]=newPos; }//i } //update the parents' fixed point moving distance std::vector<float> pos; int num=0; if(domainParentIndex[domainID]!=-1){//has parent for(int i=0;i<constraintIndex[domainID].size();i++){ int index=3*constraintIndex[domainID][i]; pos.push_back(sm->m_vertices[index]); pos.push_back(sm->m_vertices[index+1]); pos.push_back(sm->m_vertices[index+2]); } } sm->update(sTime); sTime++; if(domainParentIndex[domainID]!=-1){//has parent //std::cout<<sm->numOfVertices<<std::endl; for(int i=0;i<constraintIndex[domainID].size();i++){ int index=3*constraintIndex[domainID][i]; if(index>3*sm->numOfVertices) std::cout<<index-3*sm->numOfVertices<<"big "<<currentConstriant<<std::endl; glm::dvec3 movePos=parentLastPosNew[domainID]-parentLastPosOld[domainID]; //std::cout<<sm->m_vertices[index]<<","<<sm->m_vertices[index+1]<<","<<sm->m_vertices[index+2]<<std::endl; sm->m_vertices[index]=pos[num++]+movePos.x; sm->m_vertices[index+1]=pos[num++]+movePos.y; sm->m_vertices[index+2]=pos[num++]+movePos.z; //std::cout<<sm->m_vertices[index]<<","<<sm->m_vertices[index+1]<<","<<sm->m_vertices[index+2]<<"end"<<std::endl; //std::cout<<constraintIndex[domainID][i]<<std::endl; } } } MFnMesh surfFn(rs,&stat); McheckErr( stat, "compute - MFnMesh error" ); MFnMeshData ouputMeshDataCreator; MObject oMesh = ouputMeshDataCreator.create(&stat); buildOutputMesh(surfFn, sm->m_vertices,oMesh); outputMeshData.set(oMesh); data.setClean(plug); } else stat = MS::kUnknownParameter; return stat; }
//---------------------------------------------------------------------------------------------------------------------- // This method should be overridden in user defined nodes. // Recompute the given output based on the nodes inputs. // The plug represents the data value that needs to be recomputed, and the data block holds the storage // for all of the node'_scale attributes. //---------------------------------------------------------------------------------------------------------------------- MStatus OceanNode::compute( const MPlug &_plug , MDataBlock &_data ){ MStatus status; // see if we get the output plug if( _plug == m_output){ MDataHandle dataHandle; dataHandle = _data.inputValue(m_resolution, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get data handle for resolution plug"); if (m_res != dataHandle.asInt()){ switch(dataHandle.asInt()){ case 0: m_ocean->setResolution(128); MGlobal::displayInfo("Resolution: 128"); break; case 1: m_ocean->setResolution(256); MGlobal::displayInfo("Resolution: 256"); break; case 2: m_ocean->setResolution(512); MGlobal::displayInfo("Resolution: 512"); break; case 3: m_ocean->setResolution(1024); MGlobal::displayInfo("Resolution: 1024"); break; default: break; } m_res = dataHandle.asInt(); } dataHandle = _data.inputValue( m_amplitude , &status ); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL( status , "Unable to get data handle for amplitude plug" ); // now get the value for the data handle as a double double amp = dataHandle.asDouble(); m_ocean->setAmplitude(amp); dataHandle = _data.inputValue(m_frequency, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get handle for \"frequency\" plug"); double freq = dataHandle.asDouble(); m_ocean->setFrequency(freq); dataHandle = _data.inputValue(m_windDirectionX, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get data handle for windDirectionX plug"); // now get value for data handle double wdx = dataHandle.asDouble(); dataHandle = _data.inputValue(m_windDirectionZ, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get data handle for windDirectionY plug"); // now get value for data handle double wdz = dataHandle.asDouble(); m_ocean->setWindVector(make_float2(wdx, wdz)); dataHandle = _data.inputValue(m_windSpeed, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get data handle for windSpeed plug"); // now get value for data handle double ws = dataHandle.asDouble(); m_ocean->setWindSpeed(ws); // Only create a new frequency domain if either amplitude or the wind vecotr has changed if (m_amp != amp || m_wdx != wdx || m_wdz != wdz || m_ws != ws ){ MGlobal::displayInfo("here"); m_ocean->createH0(); m_amp = amp; m_wdx = wdx; m_wdz = wdz; m_ws = ws; } dataHandle = _data.inputValue(m_choppiness, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get data handle for the choppiness plug"); double choppiness = dataHandle.asDouble(); dataHandle = _data.inputValue(m_time, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to get data handle for time plug"); MTime time = dataHandle.asTime(); MDataHandle outputData = _data.outputValue(m_output, &status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL( status , "Unable to get data handle for output plug" ); MFnMeshData mesh; MObject outputObject = mesh.create(&status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to create output mesh"); // Find the current frame number we're on and create the grid based on this MAnimControl anim; anim.setMinTime(time); createGrid((int)pow(2.0, m_res+7), anim.currentTime().value()/24, choppiness, outputObject, status); CHECK_STATUS_AND_RETURN_MSTATUS_IF_FAIL(status, "Unable to to create grid"); outputData.set(outputObject); // clean the output plug, ie unset it from dirty so that maya does not re-evaluate it _data.setClean( _plug ); return MStatus::kSuccess; } return MStatus::kUnknownParameter; }
MObject VMesh::createFeather() { MStatus stat; MFnMeshData dataCreator; MObject outMeshData = dataCreator.create(&stat); int numVertex = 0; int numPolygon = 0; MPointArray vertexArray; MFloatArray uArray, vArray; MIntArray polygonCounts, polygonConnects, polygonUVs; MFnMesh meshFn(pgrow, &stat); MItMeshVertex vertIter(pgrow, &stat); MItMeshPolygon faceIter(pgrow, &stat); MPoint S; MVector N, tang, ttang, binormal, dir, hair_up; MColor Cscale, Cerect, Crotate, Ccurl, Cwidth; float rot, lengreal; MATRIX44F hair_space; MString setScale("fb_scale"); MString setErect("fb_erect"); MString setRotate("fb_rotate"); MString setCurl("fb_curl"); MString setWidth("fb_width"); MIntArray conn_face; for( int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { if(vertIter.onBoundary()) continue; vertIter.getNormal(N, MSpace::kWorld); N.normalize(); vertIter.getColor(Cscale, &setScale); vertIter.getColor(Cerect, &setErect); vertIter.getColor(Crotate, &setRotate); vertIter.getColor(Ccurl, &setCurl); vertIter.getColor(Cwidth, &setWidth); vertIter.getConnectedFaces(conn_face); tang = MVector(0,0,0); for(int j=0; j<conn_face.length(); j++) { meshFn.getFaceVertexTangent (conn_face[j], i, ttang, MSpace::kWorld); ttang.normalize(); tang += ttang; } tang /= conn_face.length(); conn_face.clear(); tang.normalize(); tang = N^tang; tang.normalize(); binormal = N^tang; if(Crotate.r<0.5) { rot = (0.5 - Crotate.r)*2; tang = tang + (binormal-tang)*rot; tang.normalize(); binormal = N^tang; } else { rot = (Crotate.r-0.5)*2; tang = tang + (binormal*-1-tang)*rot; tang.normalize(); binormal = N^tang; } dir = tang + (N - tang)*Cerect.r; dir.normalize(); //S = S+dir*Cscale.r*m_scale; //glVertex3f(S.x, S.y, S.z); hair_up = dir^binormal; hair_space.setIdentity(); hair_space.setOrientations(XYZ(binormal.x, binormal.y, binormal.z), XYZ(hair_up.x, hair_up.y, hair_up.z), XYZ(dir.x, dir.y, dir.z)); S = vertIter.position(MSpace::kWorld); hair_space.setTranslation(XYZ(S.x, S.y, S.z)); lengreal = Cscale.r*m_scale; fb->create(lengreal, 0, lengreal*(Ccurl.r-0.5)*2); XYZ pw; MPoint pvx; MPoint pright = S + binormal*Cwidth.r*m_width*lengreal; MPoint pleft = S - binormal*Cwidth.r*m_width*lengreal; MPoint phit; int polyhit; meshFn.getClosestPoint (pright, phit, MSpace::kObject, &polyhit); MVector topright = phit - S; topright.normalize(); topright *= Cwidth.r*m_width*lengreal; meshFn.getClosestPoint (pleft, phit, MSpace::kObject, &polyhit); MVector topleft = phit - S; topleft.normalize(); topleft *= Cwidth.r*m_width*lengreal; //tws_binormal = binormal*cos(0.2) + hair_up*sin(0.2); for(int j=0; j<NUMBENDSEG+1; j++) { fb->getPoint(j, pw); hair_space.transform(pw); pvx = MPoint(pw.x, pw.y, pw.z) + topleft;//- tws_binormal*Cwidth.r*m_width*lengreal; vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z); vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z) + topright;//tws_binormal*Cwidth.r*m_width*lengreal; vertexArray.append(pvx); uArray.append(0.0); vArray.append((float)j/NUMBENDSEG); uArray.append(0.5); vArray.append((float)j/NUMBENDSEG); uArray.append(1.0); vArray.append((float)j/NUMBENDSEG); } for(int j=0; j<NUMBENDSEG; j++) { polygonConnects.append(j*3 + numVertex); polygonConnects.append(j*3+3 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+1 + numVertex); polygonCounts.append(4); polygonConnects.append(j*3+1 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+5 + numVertex); polygonConnects.append(j*3+2 + numVertex); polygonCounts.append(4); polygonUVs.append(j*3 + numVertex); polygonUVs.append(j*3+3 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+5 + numVertex); polygonUVs.append(j*3+2 + numVertex); } numVertex += (NUMBENDSEG+1)*3; numPolygon += NUMBENDSEG*2; } MIntArray connvert; int idxpre; float averg_scale, averg_erect, averg_rotate, averg_curl, averg_width; for( int i=0; !faceIter.isDone(); faceIter.next(), i++ ) { if(faceIter.onBoundary()) continue; faceIter.getNormal(N, MSpace::kWorld); N.normalize(); faceIter.getVertices(connvert); averg_scale=averg_erect=averg_rotate=averg_curl=0; for(int j=0; j<connvert.length(); j++) { vertIter.setIndex(connvert[j], idxpre); vertIter.getColor(Cscale, &setScale); vertIter.getColor(Cerect, &setErect); vertIter.getColor(Crotate, &setRotate); vertIter.getColor(Ccurl, &setCurl); vertIter.getColor(Cwidth, &setWidth); averg_scale += Cscale.r; averg_erect += Cerect.r; averg_rotate += Crotate.r; averg_curl += Ccurl.r; averg_width += Cwidth.r; } averg_scale /= connvert.length(); averg_erect /= connvert.length(); averg_rotate /= connvert.length(); averg_curl /= connvert.length(); averg_width /= connvert.length(); tang = MVector(0,0,0); for(int j=0; j<connvert.length(); j++) { meshFn.getFaceVertexTangent (i, connvert[j], ttang, MSpace::kWorld); ttang.normalize(); tang += ttang; } //tang /= conn_face.length(); connvert.clear(); tang.normalize(); tang = N^tang; tang.normalize(); binormal = N^tang; if(averg_rotate<0.5) { rot = (0.5 - averg_rotate)*2; tang = tang + (binormal-tang)*rot; tang.normalize(); binormal = N^tang; } else { rot = (averg_rotate-0.5)*2; tang = tang + (binormal*-1-tang)*rot; tang.normalize(); binormal = N^tang; } dir = tang + (N - tang)*averg_erect; dir.normalize(); //S = S+dir*Cscale.r*m_scale; //glVertex3f(S.x, S.y, S.z); hair_up = dir^binormal; hair_space.setIdentity(); hair_space.setOrientations(XYZ(binormal.x, binormal.y, binormal.z), XYZ(hair_up.x, hair_up.y, hair_up.z), XYZ(dir.x, dir.y, dir.z)); S = faceIter.center(MSpace::kWorld); hair_space.setTranslation(XYZ(S.x, S.y, S.z)); lengreal = Cscale.r*m_scale; fb->create(lengreal, 0, lengreal*(averg_curl-0.5)*2); MPoint pright = S + binormal*Cwidth.r*m_width*lengreal; MPoint pleft = S - binormal*Cwidth.r*m_width*lengreal; XYZ pw; MPoint pvx; MPoint phit; int polyhit; meshFn.getClosestPoint (pright, phit, MSpace::kObject, &polyhit); MVector topright = phit - S; topright.normalize(); topright *= Cwidth.r*m_width*lengreal; meshFn.getClosestPoint (pleft, phit, MSpace::kObject, &polyhit); MVector topleft = phit - S; topleft.normalize(); topleft *= Cwidth.r*m_width*lengreal; //tws_binormal = binormal*cos(0.2) + hair_up*sin(0.2); for(int j=0; j<NUMBENDSEG+1; j++) { fb->getPoint(j, pw); hair_space.transform(pw); pvx = MPoint(pw.x, pw.y, pw.z) + topleft;//- tws_binormal*averg_width*m_width*lengreal; vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z); vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z) + topright;//tws_binormal*averg_width*m_width*lengreal; vertexArray.append(pvx); uArray.append(0.0); vArray.append((float)j/NUMBENDSEG); uArray.append(0.5); vArray.append((float)j/NUMBENDSEG); uArray.append(1.0); vArray.append((float)j/NUMBENDSEG); } for(int j=0; j<NUMBENDSEG; j++) { polygonConnects.append(j*3 + numVertex); polygonConnects.append(j*3+3 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+1 + numVertex); polygonCounts.append(4); polygonConnects.append(j*3+1 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+5 + numVertex); polygonConnects.append(j*3+2 + numVertex); polygonCounts.append(4); polygonUVs.append(j*3 + numVertex); polygonUVs.append(j*3+3 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+5 + numVertex); polygonUVs.append(j*3+2 + numVertex); } numVertex += (NUMBENDSEG+1)*3; numPolygon += NUMBENDSEG*2; } MFnMesh meshCreateFn; meshCreateFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat ); meshCreateFn.setUVs ( uArray, vArray ); meshCreateFn.assignUVs ( polygonCounts, polygonUVs ); return outMeshData; }
MStatus AlembicNode::initialize() { MStatus status; MFnUnitAttribute uAttr; MFnTypedAttribute tAttr; 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); // 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; }
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 HesMeshNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; MPlug pnames(thisMObject(), ameshname); const unsigned numMeshes = pnames.numElements(); MString cacheName = data.inputValue( input ).asString(); std::string substitutedCacheName(cacheName.asChar()); EnvVar::replace(substitutedCacheName); MArrayDataHandle meshNameArray = data.inputArrayValue( ameshname ); MArrayDataHandle meshArry = data.outputArrayValue(outMesh, &stat); bool hesStat = false; if( plug.array() == outMesh ) { const unsigned idx = plug.logicalIndex(); if(BaseUtil::IsImporting) hesStat = true; else { if(idx == 0) AHelper::Info<std::string>(" hes mesh open file ", substitutedCacheName ); hesStat = BaseUtil::OpenHes(substitutedCacheName, HDocument::oReadOnly); } if(!hesStat) { AHelper::Info<std::string >("hes mesh cannot open file ", substitutedCacheName); return MS::kFailure; } meshNameArray.jumpToElement(idx); const MString meshName = meshNameArray.inputValue().asString(); if(!BaseUtil::HesDoc->find(meshName.asChar())) { AHelper::Info<MString>(" hes cannot find mesh ", meshName ); return MS::kFailure; } meshArry.jumpToElement(idx); MDataHandle hmesh = meshArry.outputValue(); HPolygonalMesh entryMesh(meshName.asChar() ); APolygonalMesh dataMesh; entryMesh.load(&dataMesh); entryMesh.close(); MFnMeshData dataCreator; MObject outMeshData = dataCreator.create(&stat); if( !stat ) { MGlobal::displayWarning("hes mesh cannot create " + meshName); return MS::kFailure; } AHelper::Info<MString>(" hes init mesh ", meshName); HesperisPolygonalMeshCreator::create(&dataMesh, outMeshData); hmesh.set(outMeshData); data.setClean(plug); if( (idx+1)>=numMeshes ) { if(!BaseUtil::IsImporting) { AHelper::Info<std::string>(" hes mesh close file ", substitutedCacheName ); BaseUtil::CloseHes(); } } } 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; }