MStatus testNpassiveNode::compute(const MPlug &plug, MDataBlock &data) { MStatus stat; if ( plug == currentState ) { // get old positions and numVerts // if num verts is different, reset topo and zero velocity // if num verts is the same, compute new velocity int ii,jj; // initialize MnCloth MObject inMeshObj = data.inputValue(inputGeom).asMesh(); MFnMesh inputMesh(inMeshObj); unsigned int numVerts = 0; numVerts = inputMesh.numVertices(); unsigned int prevNumVerts; fNObject.getNumVertices(prevNumVerts); if(numVerts != prevNumVerts) { 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; MFloatPointArray vertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); 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); } else { MFloatPointArray vertexArray; MFloatPointArray prevVertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.getPositions(prevVertexArray); // you may want to get the playback rate for the dt // double dt = MAnimControl::playbackBy() \ 24.0; // or get the real dt by caching the last eval time double dt = 1.0/24.0; MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = (float)( (vertexArray[ii].x - prevVertexArray[ii].x)/dt); velocitiesArray[ii].y = (float)( (vertexArray[ii].y - prevVertexArray[ii].y)/dt); velocitiesArray[ii].z = (float)( (vertexArray[ii].x - prevVertexArray[ii].z)/dt); velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); fNObject.setPositions(vertexArray,true); } // in real life, you'd get these attribute values each frame and set them fNObject.setThickness(0.1f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setCollisionFlags(true, true, true); MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle currStateOutputHandle = data.outputValue(currentState); currStateOutputHandle.set(outputData.object()); } 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, MSpace::kWorld); 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.1f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setCollisionFlags(true, true, 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()); } else { stat = MS::kUnknownParameter; } return stat; }
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; }