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 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; }
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 sgHair_controlJoint::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hStaticRotation = data.inputValue( aStaticRotation ); m_bStaticRotation = hStaticRotation.asBool(); if( m_isDirtyMatrix ) { MDataHandle hInputBaseCurveMatrix = data.inputValue( aInputBaseCurveMatrix ); m_mtxBaseCurve = hInputBaseCurveMatrix.asMatrix(); } if( m_isDirtyParentMatrixBase ) { MDataHandle hJointParenBasetMatrix = data.inputValue( aJointParentBaseMatrix ); m_mtxJointParentBase = hJointParenBasetMatrix.asMatrix(); } if( m_isDirtyCurve || m_isDirtyParentMatrixBase ) { MDataHandle hInputBaseCurve = data.inputValue( aInputBaseCurve ); MFnNurbsCurve fnCurve = hInputBaseCurve.asNurbsCurve(); fnCurve.getCVs( m_cvs ); getJointPositionBaseWorld(); } if( m_isDirtyGravityOption || m_isDirtyCurve || m_isDirtyParentMatrixBase ) { MDataHandle hGravityParam = data.inputValue( aGravityParam ); MDataHandle hGravityRange = data.inputValue( aGravityRange ); MDataHandle hGravityWeight = data.inputValue( aGravityWeight ); MDataHandle hGravityOffsetMatrix = data.inputValue( aGravityOffsetMatrix ); m_paramGravity = hGravityParam.asDouble(); m_rangeGravity = hGravityRange.asDouble(); m_weightGravity = hGravityWeight.asDouble(); m_mtxGravityOffset = hGravityOffsetMatrix.asMatrix(); m_mtxGravityOffset( 3,0 ) = 0.0; m_mtxGravityOffset( 3,1 ) = 0.0; m_mtxGravityOffset( 3,2 ) = 0.0; setGravityJointPositionWorld(); } setOutput(); MArrayDataHandle hArrOutput = data.outputValue( aOutput ); MArrayDataBuilder builderOutput( aOutput, m_cvs.length() ); for( int i=0; i< m_cvs.length(); i++ ) { MDataHandle hOutput = builderOutput.addElement( i ); MDataHandle hOutTrans = hOutput.child( aOutTrans ); MDataHandle hOutOrient = hOutput.child( aOutOrient ); hOutTrans.set( m_vectorArrTransJoint[i] ); hOutOrient.set( m_vectorArrRotateJoint[i] ); } hArrOutput.set( builderOutput ); hArrOutput.setAllClean(); data.setClean( plug ); m_isDirtyMatrix = false; m_isDirtyCurve = false; m_isDirtyGravityOption = false; m_isDirtyParentMatrixBase = false; 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 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 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; }