예제 #1
0
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;
}
예제 #2
0
파일: quatcurve.cpp 프로젝트: jonntd/Public
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;
}
예제 #3
0
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 ));



}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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;
}