MStatus ffdPlanar::getBoundingBox( MDataBlock& block, unsigned int multiIndex, MBoundingBox &boundingBoxOut ) { MStatus status = MS::kSuccess; MArrayDataHandle inputHandle = block.outputArrayValue( input ); inputHandle.jumpToElement( multiIndex ); MObject mesh = inputHandle.outputValue().child( inputGeom ).asMesh(); MBoundingBox boundingBox = MBoundingBox(); MFnMesh meshFn( mesh, &status ); MCheckErr( status, "Error getting mesh from mesh object\n" ); MPointArray pointArray = MPointArray(); meshFn.getPoints( pointArray, MSpace::kTransform ); for ( int i = 0; i < pointArray.length(); i++ ) { boundingBox.expand( pointArray[i] ); } boundingBoxOut = boundingBox; return status; }
void SurfaceAttach::setOutPlugs(MDataBlock dataBlock, const MFnNurbsSurface &fnSurface, const double dataOffset, const bool dataReverse, const short dataGenus, const double dataStaticLength, const MMatrix &dataParentInverse, const short dataDirection) { MTransformationMatrix tfm; MVector t; MEulerRotation r; MArrayDataHandle outputHandle = dataBlock.outputArrayValue(SurfaceAttach::out); std::int32_t count = outputHandle.elementCount(); MDataHandle o; for (unsigned int k = 0; k < count; ++k) { outputHandle.jumpToElement(k); // Get Transformations tfm = this->matrix(fnSurface, outputHandle.elementIndex(), dataOffset, dataReverse, dataGenus, dataStaticLength, dataParentInverse, dataDirection); t = tfm.translation(MSpace::Space::kWorld); r = tfm.eulerRotation(); o = outputHandle.outputValue(); o.child(SurfaceAttach::translate).set(t); o.child(SurfaceAttach::rotate).set(r.x, r.y, r.z); } // Mark Clean dataBlock.setClean(SurfaceAttach::translate); dataBlock.setClean(SurfaceAttach::rotate); dataBlock.setClean(SurfaceAttach::out); }
MStatus RippleDeformer::deform(MDataBlock& dataBlock, MItGeometry& itGeo, const MMatrix& localToWorldMatrix, unsigned int geomIndex) { MStatus status; //get attriubtes as a datahandle float env = dataBlock.inputValue(envelope).asFloat(); float amplitude = dataBlock.inputValue(aAmplitude).asFloat(); float displace = dataBlock.inputValue(aDisplace).asFloat(); //get the mesh //retrieve the handle to the input attribute MArrayDataHandle hInput = dataBlock.outputArrayValue(input, &status); CHECK_MSTATUS_AND_RETURN_IT(status); //get the input array index handle status = hInput.jumpToElement(geomIndex); //get the handle of geomIndex attribute MDataHandle hInputElement = hInput.outputValue(&status); //Get the MObject of the input geometry of geomindex MObject oInputGeom = hInputElement.child(inputGeom).asMesh(); MFnMesh fnMesh(oInputGeom, &status); CHECK_MSTATUS_AND_RETURN_IT(status); if (oInputGeom.isNull()) { return MS::kSuccess; } MFloatVectorArray normals; fnMesh.getVertexNormals(false, normals); MPoint pointPos; float weight; for (; !itGeo.isDone(); itGeo.next()) { //get current point position pointPos = itGeo.position(); weight = weightValue(dataBlock, geomIndex, itGeo.index()); pointPos.x = pointPos.x + sin(itGeo.index() + displace) * amplitude * normals[itGeo.index()].x * weight * env; pointPos.y = pointPos.y + sin(itGeo.index() + displace) * amplitude * normals[itGeo.index()].y * weight * env; pointPos.z = pointPos.z + sin(itGeo.index() + displace) * amplitude * normals[itGeo.index()].z * weight * env; //setPosition itGeo.setPosition(pointPos); } return MS::kSuccess; }
MStatus n_tentacle::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; //make sure we have the curve MObject curveObj = data.inputValue(curve).asNurbsCurve(); if(!curveObj.isNull()) { //get the data MArrayDataHandle inMatrixArrayHnd = data.inputArrayValue(matrix); int tangentAxisI = data.inputValue(tangentAxis).asInt(); if(tangentAxisI > 2) tangentAxisI = - (tangentAxisI - 2); else tangentAxisI = tangentAxisI + 1; double stretchF = data.inputValue(stretch).asDouble(); double globalScaleF = data.inputValue(globalScale).asDouble(); double iniLengthF = data.inputValue(iniLength).asDouble(); const MFnNurbsCurve curve(curveObj); MArrayDataHandle parameterArrayHnd = data.inputArrayValue(parameter); MArrayDataHandle blendRotArrayHnd = data.inputArrayValue(blendRot); MArrayDataHandle intervalArrayHnd = data.inputArrayValue(interval); MArrayDataHandle outTranslateArrayHnd = data.outputArrayValue(outTranslate); MArrayDataHandle outRotateArrayHnd = data.outputArrayValue(outRotate); int parameterNrPlugs = parameterArrayHnd.elementCount(); int blendRotNrPlugs = blendRotArrayHnd.elementCount(); int outTranslateNrPlugs = outTranslateArrayHnd.elementCount(); int outRotateNrPlugs = outRotateArrayHnd.elementCount(); //get the current curve length double currCurveLen = curve.length(); if(this->init == false) { if(outTranslateNrPlugs == parameterNrPlugs && outRotateNrPlugs == parameterNrPlugs && parameterNrPlugs == blendRotNrPlugs) { this->init = true; } } if( plug == outTranslate || plug == outRotate || plug == outRotateX || plug == outRotateY || plug == outRotateZ) { if(this->init) { MArrayDataBuilder tbuilder(outTranslate, parameterNrPlugs); MArrayDataBuilder rbuilder(outRotate, parameterNrPlugs); for(int i = 0; i < parameterNrPlugs; i++) { intervalArrayHnd.jumpToArrayElement(i); int intervalI = intervalArrayHnd.inputValue().asInt(); inMatrixArrayHnd.jumpToArrayElement(intervalI); MMatrix matrix1 = inMatrixArrayHnd.inputValue().asMatrix(); this->removeMatrixScale(matrix1); inMatrixArrayHnd.jumpToArrayElement(intervalI + 1); MMatrix matrix2 = inMatrixArrayHnd.inputValue().asMatrix(); this->removeMatrixScale(matrix2); parameterArrayHnd.jumpToArrayElement(i); double parameterF = parameterArrayHnd.inputValue().asDouble(); blendRotArrayHnd.jumpToArrayElement(i); double blendRotF = blendRotArrayHnd.inputValue().asDouble(); MVector outPos, outRot; this->computeSlerp(matrix1, matrix2, curve, parameterF, blendRotF, iniLengthF, currCurveLen, stretchF, globalScaleF, tangentAxisI, outPos, outRot); MDataHandle outTranslateHnd = tbuilder.addElement(i); outTranslateHnd.set3Double(outPos.x, outPos.y, outPos.z); MDataHandle outRotateHnd = rbuilder.addElement(i); double rotation[3]; outRotateHnd.set( outRot.x, outRot.y, outRot.z ); //this->output(outPos, outRot, i, outTranslateArrayHnd, outRotateArrayHnd); } outTranslateArrayHnd.set(tbuilder); outTranslateArrayHnd.setAllClean(); outRotateArrayHnd.set(rbuilder); outRotateArrayHnd.setAllClean(); } data.setClean(plug); } else { return MS::kUnknownParameter; } } return MS::kSuccess; }
MStatus BCIViz::compute( const MPlug& plug, MDataBlock& block ) { if( plug == outValue ) { MStatus status; MDagPath path; MDagPath::getAPathTo(thisMObject(), path); MMatrix worldInverseSpace = path.inclusiveMatrixInverse(); MDataHandle inputdata = block.inputValue(ainput, &status); if(status) { const MMatrix drvSpace = inputdata.asMatrix(); fDriverPos.x = drvSpace(3, 0); fDriverPos.y = drvSpace(3, 1); fDriverPos.z = drvSpace(3, 2); fDriverPos *= worldInverseSpace; } fTargetPositions.clear(); MArrayDataHandle htarget = block.inputArrayValue( atargets ); unsigned numTarget = htarget.elementCount(); fTargetPositions.setLength(numTarget); for(unsigned i = 0; i<numTarget; i++) { MDataHandle tgtdata = htarget.inputValue(&status); if(status) { const MMatrix tgtSpace = tgtdata.asMatrix(); MPoint tgtPos(tgtSpace(3,0), tgtSpace(3,1), tgtSpace(3,2)); tgtPos *= worldInverseSpace; MVector disp = tgtPos; disp.normalize(); tgtPos = disp; fTargetPositions[i] = tgtPos; } htarget.next(); } m_hitTriangle = 0; neighbourId[0] = 0; neighbourId[1] = 1; neighbourId[2] = 2; if(!checkTarget()) { MGlobal::displayWarning("convex hull must have no less than 4 targes."); return MS::kSuccess; } if(!checkFirstFour(fTargetPositions)) { MGlobal::displayWarning("first 4 targes cannot sit on the same plane."); return MS::kSuccess; } if(!constructHull()) { MGlobal::displayWarning("convex hull failed on construction."); return MS::kSuccess; } findNeighbours(); calculateWeight(); MArrayDataHandle outputHandle = block.outputArrayValue( outValue ); int numWeight = fTargetPositions.length(); m_resultWeights.setLength(numWeight); for(int i=0; i < numWeight; i++) m_resultWeights[i] = 0.0; m_resultWeights[neighbourId[0]] = fAlpha; m_resultWeights[neighbourId[1]] = fBeta; m_resultWeights[neighbourId[2]] = fGamma; MArrayDataBuilder builder(outValue, numWeight, &status); for(int i=0; i < numWeight; i++) { MDataHandle outWeightHandle = builder.addElement(i); outWeightHandle.set( m_resultWeights[i] ); //MGlobal::displayInfo(MString("wei ") + i + " " + weights[i]); } outputHandle.set(builder); outputHandle.setAllClean(); } return MS::kSuccess; }
MStatus dynExprField::compute(const MPlug& plug, MDataBlock& block) // // Descriptions: // compute output force. // { MStatus status; if( !(plug == mOutputForce) ) return( MS::kUnknownParameter ); // get the logical index of the element this plug refers to. // int multiIndex = plug.logicalIndex( &status ); McheckErr(status, "ERROR in plug.logicalIndex.\n"); // Get input data handle, use outputArrayValue since we do not // want to evaluate both inputs, only the one related to the // requested multiIndex. Evaluating both inputs at once would cause // a dependency graph loop. MArrayDataHandle hInputArray = block.outputArrayValue( mInputData, &status ); McheckErr(status,"ERROR in hInputArray = block.outputArrayValue().\n"); status = hInputArray.jumpToElement( multiIndex ); McheckErr(status, "ERROR: hInputArray.jumpToElement failed.\n"); // get children of aInputData. MDataHandle hCompond = hInputArray.inputValue( &status ); McheckErr(status, "ERROR in hCompond=hInputArray.inputValue\n"); MDataHandle hPosition = hCompond.child( mInputPositions ); MObject dPosition = hPosition.data(); MFnVectorArrayData fnPosition( dPosition ); MVectorArray points = fnPosition.array( &status ); McheckErr(status, "ERROR in fnPosition.array(), not find points.\n"); // Comment out the following since velocity, and mass are // not needed in this field. // // MDataHandle hVelocity = hCompond.child( mInputVelocities ); // MObject dVelocity = hVelocity.data(); // MFnVectorArrayData fnVelocity( dVelocity ); // MVectorArray velocities = fnVelocity.array( &status ); // McheckErr(status, "ERROR in fnVelocity.array(), not find velocities.\n"); // // MDataHandle hMass = hCompond.child( mInputMass ); // MObject dMass = hMass.data(); // MFnDoubleArrayData fnMass( dMass ); // MDoubleArray masses = fnMass.array( &status ); // McheckErr(status, "ERROR in fnMass.array(), not find masses.\n"); // The attribute mInputPPData contains the attribute in an array form // parpared by the particleShape if the particleShape has per particle // attribute fieldName_attrName. // // Suppose a field with the name dynExprField1 is connecting to // particleShape1, and the particleShape1 has per particle float attribute // dynExprField1_magnitude and vector attribute dynExprField1_direction, // then hInputPPArray will contains a MdoubleArray with the corresponding // name "magnitude" and a MvectorArray with the name "direction". This // is a mechanism to allow the field attributes being driven by dynamic // expression. MArrayDataHandle mhInputPPData = block.inputArrayValue( mInputPPData, &status ); McheckErr(status,"ERROR in mhInputPPData = block.inputArrayValue().\n"); status = mhInputPPData.jumpToElement( multiIndex ); McheckErr(status, "ERROR: mhInputPPArray.jumpToElement failed.\n"); MDataHandle hInputPPData = mhInputPPData.inputValue( &status ); McheckErr(status, "ERROR in hInputPPData = mhInputPPData.inputValue\n"); MObject dInputPPData = hInputPPData.data(); MFnArrayAttrsData inputPPArray( dInputPPData ); MDataHandle hOwnerPPData = block.inputValue( mOwnerPPData, &status ); McheckErr(status, "ERROR in hOwnerPPData = block.inputValue\n"); MObject dOwnerPPData = hOwnerPPData.data(); MFnArrayAttrsData ownerPPArray( dOwnerPPData ); const MString magString("magnitude"); MFnArrayAttrsData::Type doubleType(MFnArrayAttrsData::kDoubleArray); bool arrayExist; MDoubleArray magnitudeArray; arrayExist = inputPPArray.checkArrayExist(magString, doubleType, &status); // McheckErr(status, "ERROR in checkArrayExist(magnitude)\n"); if(arrayExist) { magnitudeArray = inputPPArray.getDoubleData(magString, &status); // McheckErr(status, "ERROR in inputPPArray.doubleArray(magnitude)\n"); } MDoubleArray magnitudeOwnerArray; arrayExist = ownerPPArray.checkArrayExist(magString, doubleType, &status); // McheckErr(status, "ERROR in checkArrayExist(magnitude)\n"); if(arrayExist) { magnitudeOwnerArray = ownerPPArray.getDoubleData(magString, &status); // McheckErr(status, "ERROR in ownerPPArray.doubleArray(magnitude)\n"); } const MString dirString("direction"); MFnArrayAttrsData::Type vectorType(MFnArrayAttrsData::kVectorArray); arrayExist = inputPPArray.checkArrayExist(dirString, vectorType, &status); MVectorArray directionArray; // McheckErr(status, "ERROR in checkArrayExist(direction)\n"); if(arrayExist) { directionArray = inputPPArray.getVectorData(dirString, &status); // McheckErr(status, "ERROR in inputPPArray.vectorArray(direction)\n"); } arrayExist = ownerPPArray.checkArrayExist(dirString, vectorType, &status); MVectorArray directionOwnerArray; // McheckErr(status, "ERROR in checkArrayExist(direction)\n"); if(arrayExist) { directionOwnerArray = ownerPPArray.getVectorData(dirString, &status); // McheckErr(status, "ERROR in ownerPPArray.vectorArray(direction)\n"); } // Compute the output force. // MVectorArray forceArray; apply( block, points.length(), magnitudeArray, magnitudeOwnerArray, directionArray, directionOwnerArray, forceArray ); // get output data handle // MArrayDataHandle hOutArray = block.outputArrayValue( mOutputForce, &status); McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n"); MArrayDataBuilder bOutArray = hOutArray.builder( &status ); McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n"); // get output force array from block. // MDataHandle hOut = bOutArray.addElement(multiIndex, &status); McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n"); MFnVectorArrayData fnOutputForce; MObject dOutputForce = fnOutputForce.create( forceArray, &status ); McheckErr(status, "ERROR in dOutputForce = fnOutputForce.create\n"); // update data block with new output force data. // hOut.set( dOutputForce ); block.setClean( plug ); return( MS::kSuccess ); }
MStatus PushDeformer::deform(MDataBlock& dataBlock, MItGeometry& itGeo, const MMatrix& localToWorldMatrix, unsigned int geomIndex) { MStatus status; //get attribute handles double bulgeAmount = dataBlock.inputValue(aAmount, &status).asDouble(); CHECK_MSTATUS_AND_RETURN_IT(status); m_taskData.envelope = dataBlock.inputValue(envelope, &status).asFloat(); CHECK_MSTATUS_AND_RETURN_IT(status); bool useStressV = dataBlock.inputValue(aUseStress, &status).asBool(); CHECK_MSTATUS_AND_RETURN_IT(status); int multiThreadingType = dataBlock.inputValue(aMultiThreadingType, &status).asBool(); CHECK_MSTATUS_AND_RETURN_IT(status); if (m_taskData.envelope <= 0.001) { return MS::kSuccess; } // if the use stress plug is turned on pull MDoubleArray stressV; if (useStressV == true) { //pull out the raw data as an Mobject MObject stressMap = dataBlock.inputValue(aStressMap, &status).data(); CHECK_MSTATUS_AND_RETURN_IT(status); MFnDoubleArrayData stressDataFn(stressMap); m_taskData.stressV = stressDataFn.array(); } //retrieve the handle to the output array attribute MArrayDataHandle hInput = dataBlock.outputArrayValue(input, &status); CHECK_MSTATUS_AND_RETURN_IT(status); //get the input array index handle status = hInput.jumpToElement(geomIndex); //get the handle of geomIndex attribute MDataHandle hInputElement = hInput.outputValue(&status); CHECK_MSTATUS_AND_RETURN_IT(status); //Get the MObject of the input geometry of geomindex MObject oInputGeom = hInputElement.child(inputGeom).asMesh(); MFnMesh fnMesh(oInputGeom, &status); CHECK_MSTATUS_AND_RETURN_IT(status); fnMesh.getVertexNormals(false, m_taskData.normals, MSpace::kWorld); itGeo.allPositions(m_taskData.points, MSpace::kWorld); //MGlobal::displayInfo( "test" ); /*for (int i = 0; i < itGeo.count(); i++) { MGlobal::displayInfo( MFnAttribute(weightList).isArray ); }*/ m_taskData.bulgeAmount = bulgeAmount; if(multiThreadingType == 1) { ThreadData* pThreadData = createThreadData( NUM_TASKS, &m_taskData ); MThreadPool::newParallelRegion( createTasks, (void*)pThreadData ); itGeo.setAllPositions(m_taskData.points); delete [] pThreadData; return MS::kSuccess; } else if(multiThreadingType == 2) { tbb::parallel_for(size_t(0), size_t(itGeo.count()), [this](size_t i) { //const float w = weightValue(dataBlock, geomIndex, i); const float w = 1.0; if (m_taskData.useStressV == true && (m_taskData.stressV.length() > 0)) { //deform m_taskData.points[i] += (MVector(m_taskData.normals[i]) * m_taskData.bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[i]); } else { //deform m_taskData.points[i] += m_taskData.normals[i] * m_taskData.bulgeAmount * m_taskData.envelope * w; } }); } // else if(multiThreadingType == 3) #pragma omp parallel for for (int i = 0; i < itGeo.count(); i++) { float w = weightValue(dataBlock, geomIndex, itGeo.index()); if (useStressV == true && (stressV.length() > 0)) { //deform m_taskData.points[i] += (MVector(m_taskData.normals[i]) * bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[i]); } else { //deform m_taskData.points[i] += m_taskData.normals[i] * bulgeAmount * m_taskData.envelope * w; } } else { for (; !itGeo.isDone(); itGeo.next()) { float w = weightValue(dataBlock, geomIndex, itGeo.index()); if (useStressV == true && (stressV.length() > 0)) { //deform m_taskData.points[itGeo.index()] += (MVector(m_taskData.normals[itGeo.index()]) * bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[itGeo.index()]); } else { //deform m_taskData.points[itGeo.index()] += m_taskData.normals[itGeo.index()] * bulgeAmount * m_taskData.envelope * w; } } } itGeo.setAllPositions(m_taskData.points); return MS::kSuccess; }
void TestDeformer::initVertMapping(MDataBlock& data, MItGeometry& iter, const MMatrix& localToWorldMatrix, unsigned int mIndex) { MStatus status; MArrayDataHandle vertMapOutArrayData = data.outputArrayValue( vert_map, &status ); CHECK_MSTATUS( status ); // use vertMapOutArrayBuilder to modify vertMapOutArrayData iter.reset(); int count = iter.count(); MArrayDataBuilder vertMapOutArrayBuilder( vert_map, count, &status ); CHECK_MSTATUS( status ); MPointArray allPts;// world vertex position of the driven mesh allPts.clear(); // walk through the driven mesh /// copy MItGeometry's vertex to vertMapOutArrayData int i = 0; while( !iter.isDone(&status) ) { CHECK_MSTATUS( status ); MDataHandle initIndexDataHnd = vertMapOutArrayBuilder.addElement( i, &status ); CHECK_MSTATUS( status ); int negIndex = -1; initIndexDataHnd.setInt( negIndex ); initIndexDataHnd.setClean(); // append a vertex position(world coordination) to allPts CHECK_MSTATUS(allPts.append( iter.position() * localToWorldMatrix )); i = i+1; iter.next(); } CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); /// Append more vertex from each driver mesh to vertMapOutArrayData MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status ); CHECK_MSTATUS( status ); int numMeshes = meshAttrHandle.elementCount(); __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes); CHECK_MSTATUS(meshAttrHandle.jumpToElement(0)); for( int meshIndex=0; meshIndex < numMeshes; ++meshIndex ) { __debug("%s(), meshIndex=%d", __FUNCTION__, meshIndex); MDataHandle currentMesh = meshAttrHandle.inputValue(&status); CHECK_MSTATUS(status); MObject meshMobj = currentMesh.asMesh(); __debug("%s(), meshMobj.apiTypeStr()=%s", __FUNCTION__, meshMobj.apiTypeStr()); __debugMeshInfo(__FUNCTION__, meshMobj); { _initVertMapping_on_one_mesh(meshMobj, vertMapOutArrayBuilder, allPts);// Note: vertMapOutArrayBuilder is updated in this function! //CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); } if( !meshAttrHandle.next() ) { break; } }// for (mesh CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); }
MStatus sweptEmitter::compute(const MPlug& plug, MDataBlock& block) // // Descriptions: // Call emit emit method to generate new particles. // { MStatus status; // Determine if we are requesting the output plug for this emitter node. // if( !(plug == mOutput) ) return( MS::kUnknownParameter ); // Get the logical index of the element this plug refers to, // because the node can be emitting particles into more // than one particle shape. // int multiIndex = plug.logicalIndex( &status ); McheckErr(status, "ERROR in plug.logicalIndex.\n"); // Get output data arrays (position, velocity, or parentId) // that the particle shape is holding from the previous frame. // MArrayDataHandle hOutArray = block.outputArrayValue(mOutput, &status); McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n"); // Create a builder to aid in the array construction efficiently. // MArrayDataBuilder bOutArray = hOutArray.builder( &status ); McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n"); // Get the appropriate data array that is being currently evaluated. // MDataHandle hOut = bOutArray.addElement(multiIndex, &status); McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n"); // Get the data and apply the function set. // MFnArrayAttrsData fnOutput; MObject dOutput = fnOutput.create ( &status ); McheckErr(status, "ERROR in fnOutput.create.\n"); // Check if the particle object has reached it's maximum, // hence is full. If it is full then just return with zero particles. // bool beenFull = isFullValue( multiIndex, block ); if( beenFull ) { return( MS::kSuccess ); } // Get deltaTime, currentTime and startTime. // If deltaTime <= 0.0, or currentTime <= startTime, // do not emit new pariticles and return. // MTime cT = currentTimeValue( block ); MTime sT = startTimeValue( multiIndex, block ); MTime dT = deltaTimeValue( multiIndex, block ); if( (cT <= sT) || (dT <= 0.0) ) { // We do not emit particles before the start time, // and do not emit particles when moving backwards in time. // // This code is necessary primarily the first time to // establish the new data arrays allocated, and since we have // already set the data array to length zero it does // not generate any new particles. // hOut.set( dOutput ); block.setClean( plug ); return( MS::kSuccess ); } // Get speed, direction vector, and inheritFactor attributes. // double speed = speedValue( block ); MVector dirV = directionVector( block ); double inheritFactor = inheritFactorValue( multiIndex, block ); // Get the position and velocity arrays to append new particle data. // MVectorArray fnOutPos = fnOutput.vectorArray("position", &status); MVectorArray fnOutVel = fnOutput.vectorArray("velocity", &status); // Convert deltaTime into seconds. // double dt = dT.as( MTime::kSeconds ); // Apply rotation to the direction vector MVector rotatedV = useRotation ( dirV ); // position, MVectorArray inPosAry; // velocity MVectorArray inVelAry; // emission rate MIntArray emitCountPP; // Get the swept geometry data // MObject thisObj = this->thisMObject(); MPlug sweptPlug( thisObj, mSweptGeometry ); if ( sweptPlug.isConnected() ) { MDataHandle sweptHandle = block.inputValue( mSweptGeometry ); // MObject sweptData = sweptHandle.asSweptGeometry(); MObject sweptData = sweptHandle.data(); MFnDynSweptGeometryData fnSweptData( sweptData ); // Curve emission // if (fnSweptData.lineCount() > 0) { int numLines = fnSweptData.lineCount(); for ( int i=0; i<numLines; i++ ) { inPosAry.clear(); inVelAry.clear(); emitCountPP.clear(); MDynSweptLine line = fnSweptData.sweptLine( i ); // ... process current line ... MVector p1 = line.vertex( 0 ); MVector p2 = line.vertex( 1 ); inPosAry.append( p1 ); inPosAry.append( p2 ); inVelAry.append( MVector( 0,0,0 ) ); inVelAry.append( MVector( 0,0,0 ) ); // emit Rate for two points on line emitCountPP.clear(); status = emitCountPerPoint( plug, block, 2, emitCountPP ); emit( inPosAry, inVelAry, emitCountPP, dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel ); } } // Surface emission (nurb or polygon) // if (fnSweptData.triangleCount() > 0) { int numTriangles = fnSweptData.triangleCount(); for ( int i=0; i<numTriangles; i++ ) { inPosAry.clear(); inVelAry.clear(); emitCountPP.clear(); MDynSweptTriangle tri = fnSweptData.sweptTriangle( i ); // ... process current triangle ... MVector p1 = tri.vertex( 0 ); MVector p2 = tri.vertex( 1 ); MVector p3 = tri.vertex( 2 ); MVector center = p1 + p2 + p3; center /= 3.0; inPosAry.append( center ); inVelAry.append( MVector( 0,0,0 ) ); // emit Rate for two points on line emitCountPP.clear(); status = emitCountPerPoint( plug, block, 1, emitCountPP ); emit( inPosAry, inVelAry, emitCountPP, dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel ); } } } // Update the data block with new dOutput and set plug clean. // hOut.set( dOutput ); block.setClean( plug ); return( MS::kSuccess ); }
MStatus CageDeformerNode::deform( MDataBlock& data, MItGeometry& itGeo, const MMatrix &localToWorldMatrix, unsigned int mIndex ) { /// main MStatus status; MThreadUtils::syncNumOpenMPThreads(); // for OpenMP // load cage mesh and other attributes MObject oCageMesh = data.inputValue( aCageMesh ).asMesh(); short blendMode = data.inputValue(aBlendMode).asShort(); bool rotationCosistency = data.inputValue( aRotationConsistency ).asBool(); bool frechetSum = data.inputValue( aFrechetSum ).asBool(); short newConstraintMode = data.inputValue(aConstraintMode).asShort(); double newConstraintWeight = data.inputValue( aConstraintWeight ).asDouble(); if ( oCageMesh.isNull() || blendMode == 99) return MS::kSuccess; short newCageMode = data.inputValue(aCageMode).asShort(); MFnMesh fnCageMesh( oCageMesh, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MPointArray cagePoints; fnCageMesh.getPoints( cagePoints, MSpace::kWorld ); // save initial cage state if (initCagePoints.length() != cagePoints.length()){ initCageMesh = oCageMesh; initCagePoints=cagePoints; } // when cage mode is changed if(newCageMode != cageMode || newConstraintMode != constraintMode || newConstraintWeight != constraintWeight) { cageMode = newCageMode; constraintMode = newConstraintMode; constraintWeight = newConstraintWeight; std::vector<double> tetWeight; // read target mesh data MArrayDataHandle hInput = data.outputArrayValue( input, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); status = hInput.jumpToElement( mIndex ); CHECK_MSTATUS_AND_RETURN_IT( status ); MObject oInputGeom = hInput.outputValue().child( inputGeom ).asMesh(); MFnMesh inputMesh(oInputGeom); inputMesh.getPoints( pts ); numPts=pts.length(); for(int j=0; j<numPts; j++ ) pts[j] *= localToWorldMatrix; MIntArray count; inputMesh.getTriangles( count, meshTriangles ); numTet=meshTriangles.length()/3; std::vector<Matrix4d> P(numTet); tetCenter.resize(numTet); tetMatrixC(pts, meshTriangles, P, tetCenter); PI.resize(numTet); for(int i=0;i<numTet;i++) PI[i] = P[i].inverse(); // prepare cage tetrahedra MFnMesh fnInitCageMesh( initCageMesh, &status ); if(cageMode == 10 || cageMode == 11) // face mode { if(cageMode == 10){ // triangulate faces by MAYA standard MIntArray count; fnInitCageMesh.getTriangles( count, triangles ); tetWeight.resize(triangles.length()/3, 1.0f); }else if(cageMode ==11){ // trianglate faces with more than 3 edges in a symmetric way triangles.clear(); MItMeshPolygon iter(initCageMesh); MIntArray tmp; MVector normal; tetWeight.reserve(4*iter.count()); unsigned int l; for(unsigned int i=0; ! iter.isDone(); i++){ iter.getVertices(tmp); l=tmp.length(); if(l==3){ tetWeight.push_back(1.0); triangles.append(tmp[0]); triangles.append(tmp[1]); triangles.append(tmp[2]); }else{ for(unsigned int j=0;j<l;j++){ tetWeight.push_back((l-2.0)/l); triangles.append(tmp[j]); triangles.append(tmp[(j+1) % l]); triangles.append(tmp[(j+2) % l]); } } iter.next(); } } // face mode compute init matrix numPrb=triangles.length()/3; initMatrix.resize(numPrb); tetMatrix(initCagePoints, triangles, cageMode, initMatrix); // compute weight w.resize(numTet); std::vector< std::vector<double> > idist(numTet); for(int j=0;j<numTet;j++){ idist[j].resize(numPrb); w[j].resize(numPrb); double sidist = 0.0; for(int i=0;i<numPrb;i++){ idist[j][i] = tetWeight[i]/distPtTri(tetCenter[j],initMatrix[i]); sidist += idist[j][i]; } assert(sidist>0.0f); for(int i=0;i<numPrb;i++) w[j][i] = idist[j][i] /sidist; }// face mode end }else if(cageMode == 0 || cageMode == 1){ // vertex mode triangles.clear(); std::vector<int> tetCount(initCagePoints.length()); MItMeshVertex iter(initCageMesh); for(int j=0; ! iter.isDone(); j++){ MIntArray v; iter.getConnectedVertices(v); // at each vertex, construct tetrahedra from connected edges int l=v.length(); if(l==3){ if(isDegenerate(initCagePoints[j],initCagePoints[v[0]],initCagePoints[v[1]],initCagePoints[v[2]]) != 0){ tetCount[j]++; triangles.append(j); triangles.append(v[0]); triangles.append(v[1]); triangles.append(v[2]); } }else{ for(int k=0;k<l;k++){ if(isDegenerate(initCagePoints[j],initCagePoints[v[k]],initCagePoints[v[(k+1) % l]],initCagePoints[v[(k+2) % l]]) != 0){ tetCount[j]++; triangles.append(j); triangles.append(v[k]); triangles.append(v[(k+1) % l]); triangles.append(v[(k+2) % l]); } } } iter.next(); } numPrb=triangles.length()/4; initMatrix.resize(numPrb); tetMatrix(initCagePoints, triangles, cageMode, initMatrix); // vertex mode compute weight w.resize(numTet); std::vector< std::vector<double> > idist(numTet); tetWeight.resize(numPrb); for(int i=0;i<numPrb;i++) tetWeight[i]=1.0/(double)tetCount[triangles[4*i]]; for(int j=0;j<numTet;j++){ idist[j].resize(numPrb); w[j].resize(numPrb); double sidist = 0.0; for(int i=0;i<numPrb;i++){ Vector3d c(initCagePoints[triangles[4*i]].x,initCagePoints[triangles[4*i]].y,initCagePoints[triangles[4*i]].z); idist[j][i] = tetWeight[i] / ((tetCenter[j]-c).squaredNorm()); sidist += idist[j][i]; } assert(sidist>0.0f); for(int i=0;i<numPrb;i++) w[j][i] = idist[j][i] /sidist; } }else if(cageMode == 5 || cageMode == 6 ){ // vertex averaged normal mode triangles.clear(); std::vector<int> tetCount(initCagePoints.length()); MItMeshVertex iter(initCageMesh); for(int j=0; ! iter.isDone(); j++){ MIntArray v; iter.getConnectedVertices(v); int l=v.length(); for(int k=0;k<l;k++){ tetCount[j]++; triangles.append(j); triangles.append(v[k]); triangles.append(v[(k+1) % l]); } iter.next(); } numPrb=triangles.length()/3; initMatrix.resize(numPrb); tetMatrix(initCagePoints, triangles, cageMode, initMatrix); // vertex mode compute weight w.resize(numTet); std::vector< std::vector<double> > idist(numTet); tetWeight.resize(numPrb); for(int i=0;i<numPrb;i++) tetWeight[i]=1.0/(double)tetCount[triangles[3*i]]; for(int j=0;j<numTet;j++){ idist[j].resize(numPrb); w[j].resize(numPrb); double sidist = 0.0; for(int i=0;i<numPrb;i++){ Vector3d c(initCagePoints[triangles[3*i]].x,initCagePoints[triangles[3*i]].y,initCagePoints[triangles[3*i]].z); idist[j][i] = tetWeight[i] / ((tetCenter[j]-c).squaredNorm()); sidist += idist[j][i]; } assert(sidist>0.0f); for(int i=0;i<numPrb;i++) w[j][i] = idist[j][i] /sidist; } }// end of cage setup // find constraint points if(constraintMode == 1){ numConstraint = numPrb; }else{ numConstraint = 1; // at least one constraint is necessary to determine global translation } constraintTet.resize(numConstraint); constraintVector.resize(numConstraint); // for each cage tetrahedra, constraint the point on the mesh with largest weight for(int i=0;i<numConstraint;i++){ constraintTet[i] = 0; for(int j=1;j<numTet;j++){ if(w[j][i] > w[constraintTet[i]][i]){ constraintTet[i] = j; } } constraintVector[i] << tetCenter[constraintTet[i]](0), tetCenter[constraintTet[i]](1), tetCenter[constraintTet[i]](2), 1.0; } // precompute arap solver arapHI(PI, meshTriangles); } // compute deformation if( ! rotationCosistency || numPrb != prevNs.size()){ // clear previous rotation prevThetas.clear(); prevThetas.resize(numPrb, 0.0); prevNs.clear(); prevNs.resize(numPrb, Vector3d::Zero()); } // find affine transformations for tetrahedra std::vector<Matrix4d> cageMatrix(numPrb), SE(numPrb), logSE(numPrb),logAff(numPrb),aff(numPrb); std::vector<Matrix3d> logR(numPrb),R(numPrb),logS(numPrb),logGL(numPrb); std::vector<Vector3d> L(numPrb); std::vector<Vector4d> quat(numPrb); tetMatrix(cagePoints, triangles, cageMode, cageMatrix); for(int i=0; i<numPrb; i++) aff[i]=initMatrix[i].inverse()*cageMatrix[i]; // compute parametrisation if(blendMode == 0 || blendMode == 1 || blendMode == 5) // polarexp or quaternion { for(unsigned int i=0;i<numPrb;i++){ parametriseGL(aff[i].block(0,0,3,3), logS[i] ,R[i]); L[i] = transPart(aff[i]); if(blendMode == 0){ // Rotational log logR[i]=logSOc(R[i], prevThetas[i], prevNs[i]); }else if(blendMode == 1){ // Eucledian log SE[i]=affine(R[i], L[i]); logSE[i]=logSEc(SE[i], prevThetas[i], prevNs[i]); }else if(blendMode == 5){ // quaternion Quaternion<double> Q(R[i].transpose()); quat[i] << Q.x(), Q.y(), Q.z(), Q.w(); } } }else if(blendMode == 2){ //logmatrix3 for(unsigned int i=0;i<numPrb;i++){ logGL[i] = aff[i].block(0,0,3,3).log(); L[i] = transPart(aff[i]); } }else if(blendMode == 3){ // logmatrix4 for(unsigned int i=0;i<numPrb;i++){ logAff[i] = aff[i].log(); } } // compute blended matrices #pragma omp parallel for std::vector<Matrix4d> At(numTet); for(int j=0; j<numTet; j++ ){ if(blendMode==0){ Matrix3d RR=Matrix3d::Zero(); Matrix3d SS=Matrix3d::Zero(); Vector3d l=Vector3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ RR += w[j][i] * logR[i]; SS += w[j][i] * logS[i]; l += w[j][i] * L[i]; } SS = expSym(SS); if(frechetSum){ RR = frechetSO(R, w[j]); }else{ RR = expSO(RR); } At[j] = affine(SS*RR, l); }else if(blendMode==1){ // rigid transformation Matrix4d EE=Matrix4d::Zero(); Matrix3d SS=Matrix3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ EE += w[j][i] * logSE[i]; SS += w[j][i] * logS[i]; } if(frechetSum){ EE = frechetSE(SE, w[j]); }else{ EE = expSE(EE); } At[j] = affine(expSym(SS),Vector3d::Zero())*EE; }else if(blendMode == 2){ //logmatrix3 Matrix3d G=Matrix3d::Zero(); Vector3d l=Vector3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ G += w[j][i] * logGL[i]; l += w[j][i] * L[i]; } At[j] = affine(G.exp(), l); }else if(blendMode == 3){ // logmatrix4 Matrix4d A=Matrix4d::Zero(); for(unsigned int i=0; i<numPrb; i++) A += w[j][i] * logAff[i]; At[j] = A.exp(); }else if(blendMode == 5){ // quaternion Vector4d q=Vector4d::Zero(); Matrix3d SS=Matrix3d::Zero(); Vector3d l=Vector3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ q += w[j][i] * quat[i]; SS += w[j][i] * logS[i]; l += w[j][i] * L[i]; } SS = expSym(SS); Quaternion<double> Q(q); Matrix3d RR = Q.matrix().transpose(); At[j] = affine(SS*RR, l); }else if(blendMode==10){ At[j] = Matrix4d::Zero(); for(unsigned int i=0; i<numPrb; i++){ At[j] += w[j][i] * aff[i]; } } } // compute target vertices position MatrixXd G=MatrixXd::Zero(numTet+numPts,3); arapG(At, PI, meshTriangles, aff, G); MatrixXd Sol = solver.solve(G); for(unsigned int i=0;i<numPts;i++){ pts[i].x=Sol(i,0); pts[i].y=Sol(i,1); pts[i].z=Sol(i,2); pts[i] *= localToWorldMatrix.inverse(); } itGeo.setAllPositions(pts); return MS::kSuccess; }
MStatus AlembicCurvesNode::compute(const MPlug &plug, MDataBlock &dataBlock) { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute"); MStatus status; // update the frame number to be imported const double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } AbcG::ICurves obj(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mObj = obj; mSchema = obj.getSchema(); mCurvesData = MObject::kNullObj; } if (!mSchema.valid()) { return MStatus::kFailure; } { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (!mCurvesData.isNull() && mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; const float blend = (float)sampleInfo.alpha; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (blend != 0.0f) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions(); Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); const bool applyBlending = (blend == 0.0f) ? false : (samplePos->size() == samplePos2->size()); Abc::FloatArraySamplePtr pKnotVec = getKnotVector(mObj); Abc::UInt16ArraySamplePtr pOrders = getCurveOrders(mObj); MArrayDataHandle arrh = dataBlock.outputArrayValue(mOutGeometryAttr); MArrayDataBuilder builder = arrh.builder(); // reference: // http://download.autodesk.com/us/maya/2010help/API/multi_curve_node_8cpp-example.html const int degree = (sample.getType() == AbcG::kCubic) ? 3 : 1; const bool closed = (sample.getWrap() == AbcG::kPeriodic); unsigned int pointOffset = 0; unsigned int knotOffset = 0; for (int ii = 0; ii < nbVertices->size(); ++ii) { const unsigned int nbCVs = (unsigned int)nbVertices->get()[ii]; const int ldegree = (pOrders) ? pOrders->get()[ii] : degree; const int nbSpans = (int)nbCVs - ldegree; MDoubleArray knots; if (pKnotVec) { const unsigned int nb_knot = nbCVs + ldegree - 1; for (unsigned int i = 0; i < nb_knot; ++i) { knots.append(pKnotVec->get()[knotOffset + i]); } knotOffset += nb_knot; } else { for (int span = 0; span <= nbSpans; ++span) { knots.append(double(span)); if (span == 0 || span == nbSpans) { for (int m = 1; m < degree; ++m) { knots.append(double(span)); } } } } MPointArray points; if (samplePos->size() > 0) { points.setLength((unsigned int)nbCVs); if (applyBlending) { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals1 = samplePos->get()[pointOffset + i]; const Abc::P3fArraySample::value_type &vals2 = samplePos2->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals1.x + (vals2.x - vals1.x) * blend; pt.y = vals1.y + (vals2.y - vals1.y) * blend; pt.z = vals1.z + (vals2.z - vals1.z) * blend; } } else { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals = samplePos->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals.x; pt.y = vals.y; pt.z = vals.z; } } pointOffset += nbCVs; } // create a subd either with or without uvs MObject mmCurvesData = MFnNurbsCurveData().create(); if (ldegree == 1 || ldegree == 3) mCurves.create(points, knots, ldegree, closed ? MFnNurbsCurve::kClosed : MFnNurbsCurve::kOpen, false, false, mmCurvesData); builder.addElement(ii).set(mmCurvesData); } arrh.set(builder); arrh.setAllClean(); return MStatus::kSuccess; }
MStatus puttyNode::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& worldMatrix, unsigned int multiIndex) { // MGlobal::displayInfo("deform"); MStatus status = MS::kSuccess; ///////////////////////////////////////////////////////////////////////////////////////////////// // // get inputs // // get the node ready flag MDataHandle dh = block.inputValue(aScriptSourced,&status); SYS_ERROR_CHECK(status, "Error getting aScriptSourced data handle\n"); bool scriptSourced = dh.asBool(); if (!scriptSourced) return MS::kSuccess; dh = block.inputValue(aNodeReady,&status); SYS_ERROR_CHECK(status, "Error getting node ready data handle\n"); bool nodeReady = dh.asBool(); // if it's not ready, don't do anything if (!nodeReady) return MS::kSuccess; dh = block.inputValue(aDefSpace,&status); SYS_ERROR_CHECK(status, "Error getting defSpace data handle\n"); short defSpace = dh.asShort(); dh = block.inputValue(aDefWeights,&status); SYS_ERROR_CHECK(status, "Error getting defWeights data handle\n"); short defWeights = dh.asShort(); dh = block.inputValue(aDefEnvelope,&status); SYS_ERROR_CHECK(status, "Error getting defEnvelope data handle\n"); short defEnvelope = dh.asShort(); // get the command dh = block.inputValue(aCmdBaseName,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString script = dh.asString(); /* if (script == "") { status = MS::kFailure; USER_ERROR_CHECK(status, "no script provided!\n"); } */ ///////////////////////////////////////////////////////////////////////////////////////////////// // // build mel cmd string // // check if it's a valid cmd // get the envelope // double env = 1; if (defEnvelope == MSD_ENVELOPE_AUTO) { dh = block.inputValue(envelope,&status); SYS_ERROR_CHECK(status, "Error getting envelope data handle\n"); env = double(dh.asFloat()); // early stop 'cause there is nothing more to do if (env == 0.0) return MS::kSuccess; } // get the points, transform them into the right space if needed // int count = iter.count(); MVectorArray points(count); for ( ; !iter.isDone(); iter.next()) points[iter.index()] = iter.position(); if ( defSpace == MSD_SPACE_WORLD ) { for (int i = 0;i<count;i++) points[i] = MPoint(points[i]) * worldMatrix; } // get the weights // MDoubleArray weights; if ( defWeights == MSD_WEIGHTS_AUTO) { weights.setLength(count); for (int i = 0;i<count;i++) weights[i] = weightValue(block,multiIndex,i); } // get the object name and type // get the input geometry, traverse through the data handles MArrayDataHandle adh = block.outputArrayValue( input, &status ); SYS_ERROR_CHECK(status,"error getting input array data handle.\n"); status = adh.jumpToElement( multiIndex ); SYS_ERROR_CHECK(status, "input jumpToElement failed.\n"); // compound data MDataHandle cdh = adh.inputValue( &status ); SYS_ERROR_CHECK(status, "error getting input inputValue\n"); // input geometry child dh = cdh.child( inputGeom ); MObject dInputGeometry = dh.data(); // get the type MString geometryType = dInputGeometry.apiTypeStr(); // get the name // MFnDagNode dagFn( dInputGeometry, &status); // SYS_ERROR_CHECK(status, "error converting geometry obj to dag node\n"); // MString geometryName = dagFn.fullPathName(&status); // SYS_ERROR_CHECK(status, "error getting full path name \n"); // MString geometryType = ""; // MString geometryName = ""; ///////////////////////////////////////////////////////////////////////////////////////////////// // // set the current values on the temp plugs for the script to be picked up // // the position MObject thisNode = thisMObject(); MPlug currPlug(thisNode,aCurrPosition); MFnVectorArrayData vecD; MObject currObj = vecD.create(points,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currPosPlug value\n"); // the weights currPlug =MPlug(thisNode,aCurrWeight); MFnDoubleArrayData dblD; currObj = dblD.create(weights,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWeightsPlug value\n"); // world matrix currPlug =MPlug(thisNode,aCurrWorldMatrix); MFnMatrixData matD; currObj = matD.create(worldMatrix,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWorldMatrixPlug value\n"); // the multi index currPlug =MPlug(thisNode,aCurrMultiIndex); currPlug.setValue(int(multiIndex)); SYS_ERROR_CHECK(status, "error setting currMultiIndexPlug value\n"); // geometry name/type // currPlug =MPlug(thisNode,aCurrGeometryName); // currPlug.setValue(geometryName); // SYS_ERROR_CHECK(status, "error setting aCurrGeometryName value\n"); currPlug =MPlug(thisNode,aCurrGeometryType); currPlug.setValue(geometryType); SYS_ERROR_CHECK(status, "error setting aCurrGeometryType value\n"); ///////////////////////////////////////////////////////////////////////////////////////////////// // // execute the mel script // MString melCmd = script+"(\"" +name()+"\","+count+")"; MCommandResult melResult; status = MGlobal::executeCommand(melCmd,melResult); // if the command did not work, then try to resource the script // (might have been that we were in a fresh scene and nothing was ready yet if (status != MS::kSuccess) { dh = block.inputValue(aScript,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString scriptFile = dh.asString(); // try to source the script MString cmd = "source \"" + scriptFile+"\""; MCommandResult melResult; status = MGlobal::executeCommand(cmd,melResult); // if successfull, retry the command if (!status.error()) { status = MGlobal::executeCommand(melCmd,melResult); } } USER_ERROR_CHECK(status, "Error executing mel command, please check the function you provided is valid, error free and has the appropriate parameters!"); // check the result type if ((melResult.resultType()) != (MCommandResult::kDoubleArray)) { USER_ERROR_CHECK(MS::kFailure, "result of mel command has wrong type, should be doubleArray (which will be interpreted as vectorArray)!"); } // get the result as a double array MDoubleArray newP; status = melResult.getResult(newP); USER_ERROR_CHECK(status, "Error getting result of mel command!"); int newCount = newP.length()/3; // size check if (newCount != count) { USER_ERROR_CHECK(MS::kFailure, "the size of the result does not match the size of the input!"); } // convert the double array into a vector array MPointArray newPoints(newCount); for(int i=0;i<newCount;i++) newPoints[i]=MPoint(newP[i*3],newP[i*3+1],newP[i*3+2]); ///////////////////////////////////////////////////////////////////////////////////////////////// // // interprete and apply the result // // do the envelope and weights if ((defEnvelope == MSD_ENVELOPE_AUTO)||((defWeights == MSD_WEIGHTS_AUTO))) { MDoubleArray envPP(count, env); if (defWeights == MSD_WEIGHTS_AUTO) { for (int i = 0;i<count;i++) envPP[i] *= weights[i]; } // linear interpolation between old and new points for (int i = 0;i<count;i++) newPoints[i] = (points[i] * (1-envPP[i])) + (newPoints[i] * envPP[i]); } // retransform the result if it was in world space if ( defSpace == MSD_SPACE_WORLD ) { MMatrix worldMatrixInv = worldMatrix.inverse(); for (int i = 0;i<count;i++) newPoints[i] *= worldMatrixInv; } // set the points iter.reset(); for ( ; !iter.isDone(); iter.next()) iter.setPosition(newPoints[iter.index()]); return status; }
MStatus sgIkSmoothStretch::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ( plug == aOutputDistance ) { MArrayDataHandle hArrInputDistance = data.inputArrayValue( aInputDistance ); MDataHandle hStretchAble = data.inputValue( aStretchAble ); MDataHandle hSmoothArea = data.inputValue( aSmoothArea ); float stretchAble = hStretchAble.asFloat(); double allDistance = 0.0; int arrayCount = hArrInputDistance.elementCount(); double* outputDistances = new double[arrayCount]; int multMinus = 1; for( int i=0; i<arrayCount; i++ ) { MDataHandle hInputDistance = hArrInputDistance.inputValue(); double inputDistance = hInputDistance.asDouble(); if( inputDistance < 0 ) { multMinus = -1; outputDistances[i] = -inputDistance; } else { outputDistances[i] = inputDistance; } allDistance += outputDistances[i]; hArrInputDistance.next(); } MDataHandle hInPosition = data.inputValue( aInPosition ); MDataHandle hInPositionX = hInPosition.child( aInPositionX ); MDataHandle hInPositionY = hInPosition.child( aInPositionY ); MDataHandle hInPositionZ = hInPosition.child( aInPositionZ ); double smoothArea = hSmoothArea.asDouble()*0.1; double poseDistance = sqrt( pow( hInPositionX.asDouble(), 2 )+pow( hInPositionY.asDouble(), 2 )+pow( hInPositionZ.asDouble(), 2 ) ) ; allDistance = fabs( allDistance ); double stretchRate = getSmoothStretchRate( outputDistances[0], outputDistances[1], poseDistance, smoothArea ); double smoothRate = getSmoothRate( outputDistances[0], outputDistances[1], poseDistance, smoothArea ); double currentRate = ( 1-stretchAble )*smoothRate + stretchAble*stretchRate; outputDistances[0] *= currentRate*multMinus; outputDistances[1] *= currentRate*multMinus; MArrayDataHandle hArrOutputDistance = data.outputArrayValue( aOutputDistance ); MArrayDataBuilder bArrOutputDistance( aOutputDistance, arrayCount, &stat ); for( int i=0; i<arrayCount; i++ ) { MDataHandle hOutputDistance = bArrOutputDistance.addElement( i ); hOutputDistance.set( outputDistances[i] ); } hArrOutputDistance.set( bArrOutputDistance ); hArrOutputDistance.setAllClean(); data.setClean( plug ); } return MS::kSuccess; }
//----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- MStatus CVstWeldNode::compute( const MPlug &mPlug, MDataBlock &mDataBlock ) { if ( mPlug == m_oaWeldOutput || mPlug == m_oaTranslate || mPlug == m_oaRotate || mPlug == m_oaTranslateX || mPlug == m_oaTranslateY || mPlug == m_oaTranslateZ || mPlug == m_oaRotateX || mPlug == m_oaRotateY || mPlug == m_oaRotateZ ) { const MObject geoObj = mDataBlock.inputValue( m_iaWorldGeometry ).data(); if ( geoObj.apiType() == MFn::kMeshData ) { MStatus mStatus; MObject meshObj = mDataBlock.inputValue( m_iaWorldGeometry ).asMeshTransformed(); MFnMesh meshFn( meshObj ); MItMeshPolygon pIt( meshObj ); MPointArray facePoints; MArrayDataHandle wiAH = mDataBlock.inputArrayValue( m_iaWeldInput ); MArrayDataHandle woAH = mDataBlock.outputArrayValue( m_oaWeldOutput, &mStatus ); MArrayDataBuilder woADB = woAH.builder( &mStatus ); const int nWeldCount = wiAH.elementCount(); for ( int i = 0; i < nWeldCount; ++i, wiAH.next() ) { MDataHandle wiDH = wiAH.inputValue(); const MMatrix &offsetMatrix = wiDH.child( m_iaOffsetMatrix ).asMatrix(); const MMatrix &inverseParentSpace = wiDH.child( m_iaInverseParentSpace ).asMatrix(); const MEulerRotation::RotationOrder rotationOrder = static_cast< MEulerRotation::RotationOrder >( wiDH.child( m_iaRotateOrder ).asShort() ); MMatrix geoMatrix; switch ( wiDH.child( m_iaType ).asShort() ) { case kMeshFace: { const int nMeshFaceIndex = wiDH.child( m_iaInt ).asInt(); GetMeshMatrix( pIt, nMeshFaceIndex, geoMatrix ); } break; default: merr << "Unknown Weld Type " << wiDH.child( m_iaType ).asShort() << std::endl; break; } const int nWeldIndex = wiAH.elementIndex(); MDataHandle woDH = woADB.addElement( nWeldIndex ); MTransformationMatrix L( inverseParentSpace * offsetMatrix * geoMatrix ); woDH.child( m_oaTranslate ).set( L.getTranslation( MSpace::kWorld ) ); MEulerRotation e = L.rotation().asEulerRotation(); e.reorder( rotationOrder ); woDH.child( m_oaRotate ).set( e.asVector() ); } } else { merr << "Invalid .inputGeometry data of type: " << geoObj.apiTypeStr() << " found while computing " << mPlug.info() << std::endl; return MS::kFailure; } return MS::kSuccess; } return MS::kUnknownParameter; }
MStatus stringFormat::compute (const MPlug& plug, MDataBlock& data) { MStatus status; // Check that the requested recompute is one of the output values // if (plug == attrOutput) { // Read the input values // MDataHandle inputData = data.inputValue (attrFormat, &status); CHECK_MSTATUS( status ); MString format = inputData.asString(); // Get input data handle, use outputArrayValue since we do not // want to evaluate all inputs, only the ones related to the // requested multiIndex. This is for efficiency reasons. // MArrayDataHandle vals = data.outputArrayValue(attrValues, &status); CHECK_MSTATUS( status ); int indx = 0; int param; char letter; while ((indx = findNextMatch(format, indx, param, letter)) > 0) { double val = 0.; status = vals.jumpToElement(param); if (status == MStatus::kSuccess) { MDataHandle thisVal = vals.inputValue( &status ); if (status == MStatus::kSuccess) { val = thisVal.asDouble(); } } MString replace; bool valid = false; switch (letter) { case 'd': // Integer val = floor(val+.5); // No break here case 'f': // Float replace.set(val); valid = true; break; case 't': // Timecode { const char * sign = ""; if (val<0) { sign = "-"; val = -val; } int valInt = (int)(val+.5); int sec = valInt / 24; int frame = valInt - sec * 24; int min = sec / 60; sec -= min * 60; int hour = min / 60; min -= hour * 60; char buffer[90]; if (hour>0) sprintf(buffer, "%s%d:%02d:%02d.%02d", sign, hour, min, sec, frame); else sprintf(buffer, "%s%02d:%02d.%02d", sign, min, sec, frame); replace = buffer; } valid = true; break; } if (valid) { format = format.substring(0, indx-2) + replace + format.substring(indx+2, format.length()-1); indx += replace.length() - 3; } } // Store the result // MDataHandle output = data.outputValue(attrOutput, &status ); CHECK_MSTATUS( status ); output.set( format ); } else { return MS::kUnknownParameter; } 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 multiCurve::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ( plug == outputCurves ) { MDataHandle numCurvesHandle = data.inputValue(numCurves, &stat); PERRORfail(stat, "multiCurve::compute getting numCurves"); int num = numCurvesHandle.asLong(); MDataHandle curveOffsetHandle = data.inputValue(curveOffset, &stat); PERRORfail(stat, "multiCurve::compute getting curveOffset"); double baseOffset = curveOffsetHandle.asDouble(); MDataHandle inputCurveHandle = data.inputValue(inputCurve, &stat); PERRORfail(stat, "multiCurve::compute getting inputCurve"); MObject inputCurveObject ( inputCurveHandle.asNurbsCurveTransformed() ); MFnNurbsCurve inCurveFS ( inputCurveObject ); MArrayDataHandle outputArray = data.outputArrayValue(outputCurves, &stat); PERRORfail(stat, "multiCurve::compute getting output data handle"); // Create an array data build that is preallocated to hold just // the number of curves we plan on creating. When this builder // is set in to the MArrayDataHandle at the end of the compute // method, the new array will replace the existing array in the // scene. // // If the number of elements of the multi does not change between // compute cycles, then one can reuse the space allocated on a // previous cycle by extracting the existing builder from the // MArrayDataHandle: // MArrayDataBuilder builder( outputArray.builder(&stat) ); // this later form of the builder will allow you to rewrite elements // of the array, and to grow it, but the array can only be shrunk by // explicitly removing elements with the method // MArrayDataBuilder::removeElement(unsigned index); // MArrayDataBuilder builder(outputCurves, num, &stat); PERRORfail(stat, "multiCurve::compute creating builder"); for (int curveNum = 0; curveNum < num; curveNum++) { MDataHandle outHandle = builder.addElement(curveNum); MFnNurbsCurveData dataCreator; MObject outCurveData = dataCreator.create(); MObject outputCurve = inCurveFS.copy(inputCurveObject, outCurveData, &stat); PERRORfail(stat, "multiCurve::compute copying curve"); MFnNurbsCurve outCurveFS ( outputCurve ); MPointArray cvs; double offset = baseOffset * (curveNum+1); outCurveFS.getCVs ( cvs, MSpace::kWorld ); int numCVs = cvs.length(); for (int i = 0; i < numCVs; i++) { cvs[i].x += offset; } outCurveFS.setCVs ( cvs ); outHandle.set(outCurveData); } // Set the builder back into the output array. This statement // is always required, no matter what constructor was used to // create the builder. stat = outputArray.set(builder); PERRORfail(stat, "multiCurve::compute setting the builder"); // Since we compute all the elements of the array, instead of // just marking the plug we were asked to compute as clean, mark // every element of the array as clean to prevent further calls // to this compute method during this DG evaluation cycle. stat = outputArray.setAllClean(); PERRORfail(stat, "multiCurve::compute cleaning outputCurves"); } else { return MS::kUnknownParameter; } return stat; }