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 HRBFSkinCluster::skinLB(MMatrixArray& transforms, int numTransforms, MArrayDataHandle& weightListHandle, MItGeometry& iter) { MStatus returnStatus; // Iterate through each point in the geometry. // for (; !iter.isDone(); iter.next()) { MPoint pt = iter.position(); MPoint skinned; // get the weights for this point -> must be dependent on the iterator somehow MArrayDataHandle weightsHandle = weightListHandle.inputValue().child(weights); // compute the skinning -> TODO: what's the order that the weights are given in? Appears to just be maya list relatives order. for (int i = 0; i<numTransforms; ++i) { if (MS::kSuccess == weightsHandle.jumpToElement(i)) { skinned += (pt * transforms[i]) * weightsHandle.inputValue().asDouble(); } } // Set the final position. iter.setPosition(skinned); // advance the weight list handle weightListHandle.next(); } return returnStatus; }
MStatus MG_curve::compute(const MPlug& plug,MDataBlock& dataBlock) { if (plug==output) { //MStatus MStatus stat; //Point array for the curve MPointArray pointArray ; //Get data from inputs MDataHandle degreeH = dataBlock.inputValue(degree); int degreeValue = degreeH.asInt(); MDataHandle tmH = dataBlock.inputValue(transformMatrix); MMatrix tm = tmH.asMatrix(); MArrayDataHandle inputMatrixH = dataBlock.inputArrayValue(inputMatrix); inputMatrixH.jumpToArrayElement(0); //Loop to get matrix data and convert in points for (int unsigned i=0;i<inputMatrixH.elementCount();i++,inputMatrixH.next()) { MMatrix currentMatrix = inputMatrixH.inputValue(&stat).asMatrix() ; //Compensate the locator matrix MMatrix fixedMatrix = currentMatrix*tm.inverse(); MPoint matrixP (fixedMatrix[3][0],fixedMatrix[3][1],fixedMatrix[3][2]); pointArray.append(matrixP); } MFnNurbsCurve curveFn; MFnNurbsCurveData curveDataFn; MObject curveData= curveDataFn.create(); curveFn.createWithEditPoints(pointArray,degreeValue,MFnNurbsCurve::kOpen,0,0,0,curveData,&stat); MDataHandle outputH = dataBlock.outputValue(output); outputH.set(curveData); outputH.setClean(); } return MS::kSuccess; }
// // DESCRIPTION: /////////////////////////////////////////////////////// MStatus ShadowMatte::compute( const MPlug& plug, MDataBlock& block ) { if ((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutTransparency) && (plug.parent() != aOutTransparency)) return MS::kUnknownParameter; MFloatVector shadowColor(0.0,0.0,0.0); bool ViewFlag = block.inputValue( aViewColor ).asBool(); // get light list MArrayDataHandle lightData = block.inputArrayValue( aLightData ); int numLights = lightData.elementCount(); // iterate through light list and get ambient/diffuse values for( int count=1; count <= numLights; count++ ) { MDataHandle currentLight = lightData.inputValue(); float lightShadow = currentLight.child(aLightShadowFraction).asFloat(); // shadow fraction tells how much an object is in shadow: // (1) totally in shadow // (0-1) partially in shadow // (0) not in shadow shadowColor[0] += lightShadow; shadowColor[1] += lightShadow; shadowColor[2] += lightShadow; if( !lightData.next() ) break; } // set ouput color attribute MFloatVector ghostColor(0.0,0.0,0.0); MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); if (ViewFlag) outColor = shadowColor; else outColor = ghostColor; outColorHandle.setClean(); // set ouput transparency MDataHandle outTransHandle = block.outputValue( aOutTransparency ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = shadowColor; outTransHandle.setClean(); return MS::kSuccess; }
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; }
// COMPUTE ====================================== MStatus gear_curveCns::deform( MDataBlock& data, MItGeometry& iter, const MMatrix &mat, unsigned int mIndex ) { MStatus returnStatus; MArrayDataHandle adh = data.inputArrayValue( inputs ); int deformer_count = adh.elementCount( &returnStatus ); // Process while (! iter.isDone()){ if (iter.index() < deformer_count){ adh.jumpToElement(iter.index()); MTransformationMatrix m(adh.inputValue().asMatrix() * mat.inverse()); MVector v = m.getTranslation(MSpace::kWorld, &returnStatus ); MPoint pt(v); iter.setPosition(pt); } iter.next(); } return MS::kSuccess; }
MStatus testNucleusNode::compute(const MPlug &plug, MDataBlock &data) { MStatus stat; if ( plug == nextState ) { //get the value of the currentTime MTime currTime = data.inputValue(currentTime).asTime(); MObject inputData; //pull on start state or current state depending on the current time. if(currTime.value() <= 0.0) { MArrayDataHandle multiDataHandle = data.inputArrayValue(startState); multiDataHandle.jumpToElement(0); inputData =multiDataHandle.inputValue().data(); } else { MArrayDataHandle multiDataHandle = data.inputArrayValue(currentState); multiDataHandle.jumpToElement(0); inputData =multiDataHandle.inputValue().data(); } MFnNObjectData inputNData(inputData); MnCloth * nObj = NULL; inputNData.getObjectPtr(nObj); MFloatPointArray points; nObj->getPositions(points); unsigned int ii; for(ii=0;ii<points.length();ii++) { points[ii].y = (float) sin(points[ii].x + currTime.value()*4.0f*(3.1415f/180.0f)); } nObj->setPositions(points); delete nObj; data.setClean(plug); } else if ( plug == currentState ) { data.setClean(plug); } else if (plug == startState) { data.setClean(plug); } else { stat = MS::kUnknownParameter; } return stat; }
MStatus ArrayAngleConstructorNode::compute(const MPlug& plug, MDataBlock& data) { if (plug != aOutput) return MS::kUnknownParameter; MStatus status; int index; MArrayDataHandle inputArrayHandle = data.inputArrayValue(aInput); int inputSize = inputArrayHandle.elementCount(); int outputSize = data.inputValue(aSize).asInt(); MDoubleArray outputArray(outputSize); MAngle::Unit uiUnit = MAngle::uiUnit(); for (int i = 0; i < inputSize; i++) { index = inputArrayHandle.elementIndex(); if (index >= outputSize) break; if (uiUnit == MAngle::kRadians) { outputArray[index] = inputArrayHandle.inputValue().asAngle().asRadians(); } else { outputArray[index] = inputArrayHandle.inputValue().asAngle().asDegrees(); } if (!inputArrayHandle.next()) break; } MFnDoubleArrayData outputArrayData; MObject outputData = outputArrayData.create(outputArray, &status); CHECK_MSTATUS_AND_RETURN_IT(status); MDataHandle outputHandle = data.outputValue(aOutput); outputHandle.setMObject(outputData); outputHandle.setClean(); return MS::kSuccess; }
MStatus anisotropicShaderNode::compute( const MPlug& plug, MDataBlock& block ) { if ((plug == aOutColor) || (plug.parent() == aOutColor)) { MFloatVector resultColor(0.0,0.0,0.0); MFloatVector diffuseColor( 0.0,0.0,0.0 ); MFloatVector specularColor( 0.0,0.0,0.0 ); MFloatVector ambientColor( 0.0,0.0,0.0 ); // get matrix MFloatMatrix& matrixOToW = block.inputValue( aMatrixOToW ).asFloatMatrix(); MFloatMatrix& matrixWToC = block.inputValue( aMatrixWToC ).asFloatMatrix(); // spin scratch around this vector (in object space ) MFloatVector& A = block.inputValue( aAxesVector ).asFloatVector(); A.normalize(); // spin scratch around this vector (in world space ) MFloatVector wa = A * matrixOToW; wa.normalize(); // spin scratch around this vector (in camera space ) MFloatVector ca = wa * matrixWToC; ca.normalize(); MFloatVector& surfacePoint = block.inputValue( aPointCamera ).asFloatVector(); // get sample surface shading parameters MFloatVector& N = block.inputValue( aNormalCamera ).asFloatVector(); MFloatVector& surfaceColor = block.inputValue( aColor ).asFloatVector(); float diffuseReflectivity = block.inputValue( aDiffuseReflectivity ).asFloat(); float specularCoeff = block.inputValue( aSpecularCoeff ).asFloat(); // get light list MArrayDataHandle lightData = block.inputArrayValue( aLightData ); int numLights = lightData.elementCount(); // iterate through light list and get ambient/diffuse values for( int count=0; count < numLights; count++ ) { MDataHandle currentLight = lightData.inputValue(); MFloatVector& lightIntensity = currentLight.child( aLightIntensity ).asFloatVector(); MFloatVector& lightDirection = currentLight.child( aLightDirection ).asFloatVector(); // find ambient component if( currentLight.child(aLightAmbient).asBool()) { ambientColor[0] += lightIntensity[0] * surfaceColor[0]; ambientColor[1] += lightIntensity[1] * surfaceColor[1]; ambientColor[2] += lightIntensity[2] * surfaceColor[2]; } float cosln = lightDirection * N; if( cosln > 0.0f ){ // illuminated! // find diffuse component if( currentLight.child(aLightDiffuse).asBool()) { float cosDif = cosln * diffuseReflectivity; diffuseColor[0] += lightIntensity[0] * cosDif * surfaceColor[0]; diffuseColor[1] += lightIntensity[1] * cosDif * surfaceColor[1]; diffuseColor[2] += lightIntensity[2] * cosDif * surfaceColor[2]; } // find specular component if( currentLight.child( aLightSpecular).asBool()){ MFloatVector& rayDirection = block.inputValue( aRayDirection ).asFloatVector(); MFloatVector viewDirection = -rayDirection; MFloatVector half = calcHalfVector( viewDirection, lightDirection ); // Beckmann function MFloatVector nA; if( fabs(1.0-fabs(N*ca)) <= 0.0001f ){ MFloatPoint oo( 0.0,0.0,0.0 ); MFloatPoint ow = oo * matrixOToW; MFloatPoint oc = ow * matrixWToC; MFloatVector origin( oc[0], oc[1], oc[2] ); nA = origin - surfacePoint; nA.normalize(); }else{ nA = ca; } MFloatVector x = N ^ nA; x.normalize(); MFloatVector y = N ^ x; y.normalize(); MFloatVector azimuthH = N ^ half; azimuthH = N ^ azimuthH; azimuthH.normalize(); float cos_phai = x * azimuthH; float sin_phai = 0.0; if( fabs(1 - cos_phai*cos_phai) < 0.0001 ){ sin_phai = 0.0; }else{ sin_phai = sqrtf( 1.0f - cos_phai*cos_phai ); } double co = pow( (half * N), 4.0f ); double t = tan( acos(half*N) ); t *= -t; float rough1 = block.inputValue( aRoughness1 ).asFloat(); float rough2 = block.inputValue( aRoughness2 ).asFloat(); double aaa = cos_phai / rough1; double bbb = sin_phai / rough2; t = t * ( aaa*aaa + bbb*bbb ); double D = pow( (1.0/((double)rough1*(double)rough2 * co)), t ); double aa = (2.0 * (N*half) * (N*viewDirection) ) / (viewDirection*half); double bb = (2.0 * (N*half) * (N*lightDirection) ) / (viewDirection*half); double cc = 1.0; double G = 0.0; G = MIN( aa, bb ); G = MIN( G, cc ); float s = (float) (D * G / (double)((N*lightDirection) * (N*viewDirection))); MFloatVector& specColor = block.inputValue( aSpecColor ).asFloatVector(); specularColor[0] += lightIntensity[0] * specColor[0] * s * specularCoeff; specularColor[1] += lightIntensity[1] * specColor[1] * s * specularCoeff; specularColor[2] += lightIntensity[2] * specColor[2] * s * specularCoeff; } } if( !lightData.next() ){ break; } } // result = specular + diffuse + ambient; resultColor = diffuseColor + specularColor + ambientColor; MFloatVector& transparency = block.inputValue( aInTransparency ).asFloatVector(); resultColor[0] *= ( 1.0f - transparency[0] ); resultColor[1] *= ( 1.0f - transparency[1] ); resultColor[2] *= ( 1.0f - transparency[2] ); // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); block.setClean( plug ); } else if ((plug == aOutTransparency) || (plug.parent() == aOutTransparency)) { MFloatVector& tr = block.inputValue( aInTransparency ).asFloatVector(); // set ouput color attribute MDataHandle outTransHandle = block.outputValue( aOutTransparency ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = tr; block.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
MStatus geometrySurfaceConstraint::compute( const MPlug& plug, MDataBlock& block ) { MStatus returnStatus; if(plug == constraintTranslateX || plug == constraintTranslateY || plug == constraintTranslateZ) { if(!m_isInitd) { // read rest position MDataHandle htgo = block.inputValue(targetRestP); double3 & tgo = htgo.asDouble3(); MGlobal::displayInfo(MString("target rest p ")+tgo[0]+" "+tgo[1]+" "+tgo[2]); m_restPos = MPoint(tgo[0],tgo[1],tgo[2]); m_isInitd = true; } MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget ); const unsigned int targetArrayCount = targetArray.elementCount(); MMatrix tm; tm.setToIdentity(); unsigned int i; for ( i = 0; i < targetArrayCount; i++ ) { MDataHandle targetElement = targetArray.inputValue(&returnStatus); if(!returnStatus) { MGlobal::displayInfo("failed to get input value target element"); } MDataHandle htm = targetElement.child(targetTransform); MFnMatrixData ftm(htm.data(), &returnStatus); if(!returnStatus) { MGlobal::displayInfo("failed to get matrix data"); } tm = ftm.matrix(); targetArray.next(); } MDataHandle hparentInvMat = block.inputValue(constraintParentInverseMatrix); MMatrix parentInvMat = hparentInvMat.asMatrix(); // world position MPoint curPos(tm(3,0), tm(3,1), tm(3,2)); // offset in local space m_offsetToRest = m_restPos - curPos; // object position in world space MPoint localP = m_offsetToRest * tm + curPos; // in local space localP *= parentInvMat; MDataHandle hout; if(plug == constraintTranslateX) { hout = block.outputValue(constraintTranslateX); hout.set(localP.x); } else if(plug == constraintTranslateY) { hout = block.outputValue(constraintTranslateY); hout.set(localP.y); } else if(plug == constraintTranslateZ) { hout = block.outputValue(constraintTranslateZ); hout.set(localP.z); } //MPlug pgTx(thisMObject(), constraintTargetX); //pgTx.setValue(m_lastPos.x); //MPlug pgTy(thisMObject(), constraintTargetY); //pgTy.setValue(m_lastPos.y); //MPlug pgTz(thisMObject(), constraintTargetZ); //pgTz.setValue(m_lastPos.z); MPlug pgOx(thisMObject(), constraintObjectX); pgOx.setValue(m_offsetToRest.x); MPlug pgOy(thisMObject(), constraintObjectY); pgOy.setValue(m_offsetToRest.y); MPlug pgOz(thisMObject(), constraintObjectZ); pgOz.setValue(m_offsetToRest.z); // MFnNumericData nd; //MObject offsetData = nd.create( MFnNumericData::k3Double); //nd.setData3Double(m_lastPos.x, m_lastPos.y, m_lastPos.z); //MPlug pgTgo(thisMObject(), targetOffset); //pgTgo.setValue(offsetData); } else return MS::kUnknownParameter; return MS::kSuccess; }
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; }
// // DESCRIPTION: /////////////////////////////////////////////////////// MStatus PhongNode::compute( const MPlug& plug, MDataBlock& block ) { if ((plug != aOutColor) && (plug.parent() != aOutColor)) return MS::kUnknownParameter; MFloatVector resultColor(0.0,0.0,0.0); // get sample surface shading parameters MFloatVector& surfaceNormal = block.inputValue( aNormalCamera ).asFloatVector(); MFloatVector& cameraPosition = block.inputValue( aPointCamera ).asFloatVector(); // use for raytracing api enhancement below MFloatVector point = cameraPosition; MFloatVector normal = surfaceNormal; MFloatVector& surfaceColor = block.inputValue( aColor ).asFloatVector(); MFloatVector& incandescence = block.inputValue( aIncandescence ).asFloatVector(); float diffuseReflectivity = block.inputValue( aDiffuseReflectivity ).asFloat(); // float translucenceCoeff = block.inputValue( aTranslucenceCoeff ).asFloat(); // User-defined Reflection Color Gain float reflectGain = block.inputValue( aReflectGain ).asFloat(); // Phong shading attributes float power = block.inputValue( aPower ).asFloat(); float spec = block.inputValue( aSpecularity ).asFloat(); float specularR, specularG, specularB; float diffuseR, diffuseG, diffuseB; diffuseR = diffuseG = diffuseB = specularR = specularG = specularB = 0.0; // get light list MArrayDataHandle lightData = block.inputArrayValue( aLightData ); int numLights = lightData.elementCount(); // iterate through light list and get ambient/diffuse values for( int count=1; count <= numLights; count++ ) { MDataHandle currentLight = lightData.inputValue(); MFloatVector& lightIntensity = currentLight.child(aLightIntensity).asFloatVector(); // Find the blind data void*& blindData = currentLight.child( aLightBlindData ).asAddr(); // find ambient component if( currentLight.child(aLightAmbient).asBool() ) { diffuseR += lightIntensity[0]; diffuseG += lightIntensity[1]; diffuseB += lightIntensity[2]; } MFloatVector& lightDirection = currentLight.child(aLightDirection).asFloatVector(); if ( blindData == NULL ) { // find diffuse and specular component if( currentLight.child(aLightDiffuse).asBool() ) { float cosln = lightDirection * surfaceNormal;; if( cosln > 0.0f ) // calculate only if facing light { diffuseR += lightIntensity[0] * ( cosln * diffuseReflectivity ); diffuseG += lightIntensity[1] * ( cosln * diffuseReflectivity ); diffuseB += lightIntensity[2] * ( cosln * diffuseReflectivity ); } CHECK_MSTATUS( cameraPosition.normalize() ); if( cosln > 0.0f ) // calculate only if facing light { float RV = ( ( (2*surfaceNormal) * cosln ) - lightDirection ) * cameraPosition; if( RV > 0.0 ) RV = 0.0; if( RV < 0.0 ) RV = -RV; if ( power < 0 ) power = -power; float s = spec * powf( RV, power ); specularR += lightIntensity[0] * s; specularG += lightIntensity[1] * s; specularB += lightIntensity[2] * s; } } } else { float cosln = MRenderUtil::diffuseReflectance( blindData, lightDirection, point, surfaceNormal, true ); if( cosln > 0.0f ) // calculate only if facing light { diffuseR += lightIntensity[0] * ( cosln * diffuseReflectivity ); diffuseG += lightIntensity[1] * ( cosln * diffuseReflectivity ); diffuseB += lightIntensity[2] * ( cosln * diffuseReflectivity ); } CHECK_MSTATUS ( cameraPosition.normalize() ); if ( currentLight.child(aLightSpecular).asBool() ) { MFloatVector specLightDirection = lightDirection; MDataHandle directionH = block.inputValue( aRayDirection ); MFloatVector direction = directionH.asFloatVector(); float lightAttenuation = 1.0; specLightDirection = MRenderUtil::maximumSpecularReflection( blindData, lightDirection, point, surfaceNormal, direction ); lightAttenuation = MRenderUtil::lightAttenuation( blindData, point, surfaceNormal, false ); // Are we facing the light if ( specLightDirection * surfaceNormal > 0.0f ) { float power2 = block.inputValue( aPower ).asFloat(); MFloatVector rv = 2 * surfaceNormal * ( surfaceNormal * direction ) - direction; float s = spec * powf( rv * specLightDirection, power2 ); specularR += lightIntensity[0] * s * lightAttenuation; specularG += lightIntensity[1] * s * lightAttenuation; specularB += lightIntensity[2] * s * lightAttenuation; } } } if( !lightData.next() ) break; } // factor incident light with surface color and add incandescence resultColor[0] = ( diffuseR * surfaceColor[0] ) + specularR + incandescence[0]; resultColor[1] = ( diffuseG * surfaceColor[1] ) + specularG + incandescence[1]; resultColor[2] = ( diffuseB * surfaceColor[2] ) + specularB + incandescence[2]; // add the reflection color if (reflectGain > 0.0) { MStatus status; // required attributes for using raytracer // origin, direction, sampler, depth, and object id. // MDataHandle originH = block.inputValue( aRayOrigin, &status); MFloatVector origin = originH.asFloatVector(); MDataHandle directionH = block.inputValue( aRayDirection, &status); MFloatVector direction = directionH.asFloatVector(); MDataHandle samplerH = block.inputValue( aRaySampler, &status); void*& samplerPtr = samplerH.asAddr(); MDataHandle depthH = block.inputValue( aRayDepth, &status); short depth = depthH.asShort(); MDataHandle objH = block.inputValue( aObjectId, &status); void*& objId = objH.asAddr(); MFloatVector reflectColor; MFloatVector reflectTransparency; MFloatVector& triangleNormal = block.inputValue( aTriangleNormalCamera ).asFloatVector(); // compute reflected ray MFloatVector l = -direction; float dot = l * normal; if( dot < 0.0 ) dot = -dot; MFloatVector refVector = 2 * normal * dot - l; // reflection ray float dotRef = refVector * triangleNormal; if( dotRef < 0.0 ) { const float s = 0.01f; MFloatVector mVec = refVector - dotRef * triangleNormal; mVec.normalize(); refVector = mVec + s * triangleNormal; } CHECK_MSTATUS ( refVector.normalize() ); status = MRenderUtil::raytrace( point, // origin refVector, // direction objId, // object id samplerPtr, // sampler info depth, // ray depth reflectColor, // output color and transp reflectTransparency); // add in the reflection color resultColor[0] += reflectGain * (reflectColor[0]); resultColor[1] += reflectGain * (reflectColor[1]); resultColor[2] += reflectGain * (reflectColor[2]); } // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); return MS::kSuccess; }
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 retargetLocator::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hDiscMatrix = data.inputValue( aDiscMatrix ); MDataHandle hDiscAxis = data.inputValue( aDiscAxis ); MDataHandle hDiscAngle = data.inputValue( aDiscAngle ); MDataHandle hDiscDivision = data.inputValue( aDiscDivision ); MDataHandle hDiscOffset = data.inputValue( aDiscOffset ); MDataHandle hDiscSize = data.inputValue( aDiscSize ); MDataHandle hDiscActiveColor = data.inputValue( aDiscActiveColor ); MDataHandle hDiscLeadColor = data.inputValue( aDiscLeadColor ); MDataHandle hDiscDefaultColor = data.inputValue( aDiscDefaultColor ); MDataHandle hDiscFillAlpha = data.inputValue( aDiscFillAlpha ); MDataHandle hDiscLineAlpha = data.inputValue( aDiscLineAlpha ); discAxis = hDiscAxis.asInt(); discDivision = hDiscDivision.asInt(); discAngle = hDiscAngle.asDouble(); discSize = hDiscSize.asVector(); discOffset = hDiscOffset.asVector(); discActiveColor = hDiscActiveColor.asFloat3(); discLeadColor = hDiscLeadColor.asFloat3(); discDefaultColor = hDiscDefaultColor.asFloat3(); discFillAlpha = hDiscFillAlpha.asFloat(); discLineAlpha = hDiscLineAlpha.asFloat(); MArrayDataHandle hArrArrow = data.inputArrayValue( aArrow ); arrowNum = hArrArrow.elementCount(); inheritMatrix.setLength( arrowNum ); aimMatrix.setLength( arrowNum ); inputMeshObj.setLength( arrowNum ); startSize.setLength( arrowNum ); size.setLength( arrowNum ); activeColor.setLength( arrowNum ); leadColor.setLength( arrowNum ); defaultColor.setLength( arrowNum ); fillAlpha.setLength( arrowNum ); lineAlpha.setLength( arrowNum ); offset.setLength( arrowNum ); for( int i =0; i < arrowNum; i++ ) { MDataHandle hArrow = hArrArrow.inputValue(); MDataHandle hInheritMatrix = hArrow.child( aInheritMatrix ); MDataHandle hAimMatrix = hArrow.child( aAimMatrix ); MDataHandle hInputMesh = hArrow.child( aInputMesh ); MDataHandle hStartSize = hArrow.child( aStartSize ); MDataHandle hSize = hArrow.child( aSize ); MDataHandle hActiveColor = hArrow.child( aActiveColor ); MDataHandle hLeadColor = hArrow.child( aLeadColor ); MDataHandle hDefaultColor = hArrow.child( aDefaultColor ); MDataHandle hFillAlpha = hArrow.child( aFillAlpha ); MDataHandle hLineAlpha = hArrow.child( aLineAlpha ); MDataHandle hOffset = hArrow.child( aOffset ); inheritMatrix[i] = hInheritMatrix.asBool(); aimMatrix[i] = hAimMatrix.asMatrix()*hDiscMatrix.asMatrix().inverse(); inputMeshObj[i] = hInputMesh.asMesh(); startSize[i] = hStartSize.asFloat(); size[i] = hSize.asFloat(); activeColor[i] = hActiveColor.asFloat3(); leadColor[i] = hLeadColor.asFloat3(); defaultColor[i] = hDefaultColor.asFloat3(); fillAlpha[i] = hFillAlpha.asFloat(); lineAlpha[i] = hLineAlpha.asFloat(); offset[i] = hOffset.asVector(); hArrArrow.next(); } MDataHandle hOutput = data.outputValue( aOutput ); hOutput.set( 1.0 ); data.setClean( plug ); 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 clusterControledCurve::compute( const MPlug& plug, MDataBlock& data ) { //MFnDependencyNode thisNode( thisMObject() ); //cout << thisNode.name() << ", start" << endl; MStatus status; MDataHandle hInputCurve = data.inputValue( aInputCurve, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputCurveMatrix = data.inputValue( aInputCurveMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hOutputCurve = data.outputValue( aOutputCurve, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MArrayDataHandle hArrBindPreMatrix = data.inputArrayValue( aBindPreMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MArrayDataHandle hArrMatrix = data.inputArrayValue( aMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MArrayDataHandle hArrWeightList = data.inputArrayValue( aWeightList, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hUpdate = data.inputValue( aUpdate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MObject oInputCurve = hInputCurve.asNurbsCurve(); int bindPreMatrixLength = hArrBindPreMatrix.elementCount(); int matrixLength = hArrMatrix.elementCount(); MFnNurbsCurve fnInputCurve = oInputCurve; int numCVs = fnInputCurve.numCVs(); int weightListLength = hArrWeightList.elementCount(); if( weightListLength > 100 ) { cout << "WeightList Count Error : " << weightListLength << endl; return MS::kFailure; } MPointArray inputCvPoints; MPointArray outputCvPoints; fnInputCurve.getCVs( inputCvPoints ); outputCvPoints.setLength( numCVs ); MMatrix matrix; MMatrix inputCurveMatrix = hInputCurveMatrix.asMatrix(); MMatrix inputCurveMatrixInverse = inputCurveMatrix.inverse(); if( requireUpdate ) CHECK_MSTATUS_AND_RETURN_IT( updateBindPreMatrix( oInputCurve, inputCurveMatrixInverse, hArrMatrix, hArrBindPreMatrix, hUpdate.asBool() ) ); for( int i=0; i< numCVs; i++ ) { inputCvPoints[i] *= inputCurveMatrix; } for( int i=0; i< numCVs; i++ ) { outputCvPoints[i] = MPoint( 0,0,0 ); double weight; for( int j=0; j< matrixLength; j++ ) { weight = setWeights[i][j]; hArrMatrix.jumpToElement( j ); matrix = hArrMatrix.inputValue().asMatrix(); outputCvPoints[i] += inputCvPoints[i]*bindPreMatrix[j]*matrix*weight; } } for( int i=0; i< numCVs; i++ ) { outputCvPoints[i] *= inputCurveMatrixInverse; } MFnNurbsCurveData outputCurveData; MObject oOutputCurve = outputCurveData.create(); fnInputCurve.copy( oInputCurve, oOutputCurve ); MFnNurbsCurve fnOutputCurve( oOutputCurve, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); fnOutputCurve.setCVs( outputCvPoints ); hOutputCurve.set( oOutputCurve ); data.setClean( plug ); //cout << thisNode.name() << ", end" << endl; return status; }
MStatus sgBulgeDeformer::deform(MDataBlock& dataBlock, MItGeometry& iter, const MMatrix& mtx, unsigned int index) { MStatus status; float bulgeWeight = dataBlock.inputValue(aBulgeWeight).asFloat(); double bulgeRadius = dataBlock.inputValue(aBulgeRadius).asDouble(); MArrayDataHandle hArrInputs = dataBlock.inputArrayValue(aBulgeInputs); MPointArray allPositions; iter.allPositions(allPositions); if (mem_resetElements) { unsigned int elementCount = hArrInputs.elementCount(); mem_meshInfosInner.resize(mem_maxLogicalIndex); mem_meshInfosOuter.resize(mem_maxLogicalIndex); for (unsigned int i = 0; i < elementCount; i++, hArrInputs.next()) { MDataHandle hInput = hArrInputs.inputValue(); MDataHandle hMatrix = hInput.child(aMatrix); MDataHandle hMesh = hInput.child(aMesh); MMatrix mtxMesh = hMatrix.asMatrix(); MObject oMesh = hMesh.asMesh(); MFnMeshData meshDataInner, meshDataOuter; MObject oMeshInner = meshDataInner.create(); MObject oMeshOuter = meshDataOuter.create(); MFnMesh fnMesh; fnMesh.copy(oMesh, oMeshInner); fnMesh.copy(oMesh, oMeshOuter); sgMeshInfo* newMeshInfoInner = new sgMeshInfo(oMeshInner, hMatrix.asMatrix()); sgMeshInfo* newMeshInfoOuter = new sgMeshInfo(oMeshOuter, hMatrix.asMatrix()); mem_meshInfosInner[hArrInputs.elementIndex()] = newMeshInfoInner; mem_meshInfosOuter[hArrInputs.elementIndex()] = newMeshInfoOuter; } } for (unsigned int i = 0; i < elementCount; i++) { mem_meshInfosInner[i]->setBulge(bulgeWeight, MSpace::kWorld ); } MFloatArray weightList; weightList.setLength(allPositions.length()); for (unsigned int i = 0; i < weightList.length(); i++) weightList[i] = 0.0f; MMatrixArray inputMeshMatrixInverses; inputMeshMatrixInverses.setLength(elementCount); for (unsigned int i = 0; i < elementCount; i++) { inputMeshMatrixInverses[i] = mem_meshInfosInner[i]->matrix(); } for (unsigned int i = 0; i < allPositions.length(); i++) { float resultWeight = 0; for (unsigned int infoIndex = 0; infoIndex < elementCount; infoIndex++) { MPoint localPoint = allPositions[i] * mtx* inputMeshMatrixInverses[infoIndex]; MPoint innerPoint = mem_meshInfosInner[infoIndex]->getClosestPoint(localPoint); MPoint outerPoint = mem_meshInfosOuter[infoIndex]->getClosestPoint(localPoint); MVector innerVector = innerPoint - localPoint; MVector outerVector = outerPoint - localPoint; if (innerVector * outerVector < 0) { double innerLength = innerVector.length(); double outerLength = outerVector.length(); double allLength = innerLength + outerLength; float numerator = float( innerLength * outerLength ); float denominator = float( pow(allLength / 2.0, 2) ); resultWeight = numerator / denominator; } } weightList[i] = resultWeight; } for (unsigned int i = 0; i < allPositions.length(); i++) { allPositions[i] += weightList[i] * MVector(0, 1, 0); } iter.setAllPositions(allPositions); return MS::kSuccess; }
MStatus AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock) { MStatus status; // update the frame number to be imported MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status); double speed = speedHandle.asDouble(); MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status); double offset = offsetHandle.asDouble(); MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status); MTime t = timeHandle.asTime(); double inputTime = t.as(MTime::kSeconds); double fps = getFPS(); // scale and offset inputTime. inputTime = computeAdjustedTime(inputTime, speed, offset/fps); // this should be done only once per file if (mFileInitialized == false) { mFileInitialized = true; MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr); MFileObject fileObject; fileObject.setRawFullName(dataHandle.asString()); MString fileName = fileObject.resolvedFullName(); // TODO, make sure the file name, or list of files create a valid // Alembic IArchive // initialize some flags for plug update mSubDInitialized = false; mPolyInitialized = false; // When an alembic cache will be imported at the first time using // AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be // mIncludeFilterString for later use. When we save a maya scene(.ma) // mIncludeFilterAttr will be saved. Then when we load the saved // .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr. MDataHandle includeFilterHandle = dataBlock.inputValue(mIncludeFilterAttr, &status); MString& includeFilterString = includeFilterHandle.asString(); if (mIncludeFilterString.length() > 0) { includeFilterHandle.set(mIncludeFilterString); dataBlock.setClean(mIncludeFilterAttr); } else if (includeFilterString.length() > 0) { mIncludeFilterString = includeFilterString; } MDataHandle excludeFilterHandle = dataBlock.inputValue(mExcludeFilterAttr, &status); MString& excludeFilterString = excludeFilterHandle.asString(); if (mExcludeFilterString.length() > 0) { excludeFilterHandle.set(mExcludeFilterString); dataBlock.setClean(mExcludeFilterAttr); } else if (excludeFilterString.length() > 0) { mExcludeFilterString = excludeFilterString; } MFnDependencyNode dep(thisMObject()); MPlug allSetsPlug = dep.findPlug("allColorSets"); CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(), MObject::kNullObj, CreateSceneVisitor::NONE, "", mIncludeFilterString, mExcludeFilterString); { mData.getFrameRange(mSequenceStartTime, mSequenceEndTime); MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr, &status); startFrameHandle.set(mSequenceStartTime*fps); MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr, &status); endFrameHandle.set(mSequenceEndTime*fps); } } // Retime MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status); short playType = cycleHandle.asShort(); inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime, playType); clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime); // update only when the time lapse is big enough if (fabs(inputTime - mCurTime) > 0.00001) { mOutRead = std::vector<bool>(mOutRead.size(), false); mCurTime = inputTime; } if (plug == mOutPropArrayAttr) { if (mOutRead[0]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[0] = true; unsigned int propSize = static_cast<unsigned int>(mData.mPropList.size()); if (propSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPropArrayAttr, &status); unsigned int outHandleIndex = 0; MDataHandle outHandle; // for all of the nodes with sampled attributes for (unsigned int i = 0; i < propSize; i++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(); } else { continue; } if (mData.mPropList[i].mArray.valid()) { readProp(mCurTime, mData.mPropList[i].mArray, outHandle); } else if (mData.mPropList[i].mScalar.valid()) { // for visibility only if (mData.mPropList[i].mScalar.getName() == Alembic::AbcGeom::kVisibilityPropertyName) { Alembic::Util::int8_t visVal = 1; mData.mPropList[i].mScalar.get(&visVal, Alembic::Abc::ISampleSelector(mCurTime, Alembic::Abc::ISampleSelector::kNearIndex )); outHandle.setGenericBool(visVal != 0, false); } else { // for all scalar props readProp(mCurTime, mData.mPropList[i].mScalar, outHandle); } } outArrayHandle.next(); } outArrayHandle.setAllClean(); } } else if (plug == mOutTransOpArrayAttr ) { if (mOutRead[1]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[1] = true; unsigned int xformSize = static_cast<unsigned int>(mData.mXformList.size()); if (xformSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutTransOpArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < xformSize; i++) { std::vector<double> sampleList; if (mData.mIsComplexXform[i]) { readComplex(mCurTime, mData.mXformList[i], sampleList); } else { Alembic::AbcGeom::XformSample samp; read(mCurTime, mData.mXformList[i], sampleList, samp); } unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutLocatorPosScaleArrayAttr ) { if (mOutRead[8]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[8] = true; unsigned int locSize = static_cast<unsigned int>(mData.mLocList.size()); if (locSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < locSize; i++) { std::vector< double > sampleList; read(mCurTime, mData.mLocList[i], sampleList); unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutSubDArrayAttr) { if (mOutRead[2]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutSubDArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[2] = true; unsigned int subDSize = static_cast<unsigned int>(mData.mSubDList.size()); if (subDSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < subDSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j], mSubDInitialized); outHandle.set(obj); } } mSubDInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mSubDInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutPolyArrayAttr) { if (mOutRead[3]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[3] = true; unsigned int polySize = static_cast<unsigned int>(mData.mPolyMeshList.size()); if (polySize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < polySize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j], mPolyInitialized); outHandle.set(obj); } } mPolyInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPolyArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(&status); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mPolyInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutCameraArrayAttr) { if (mOutRead[4]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[4] = true; unsigned int cameraSize = static_cast<unsigned int>(mData.mCameraList.size()); if (cameraSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutCameraArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr); double angleConversion = 1.0; switch (MAngle::uiUnit()) { case MAngle::kRadians: angleConversion = 0.017453292519943295; break; case MAngle::kAngMinutes: angleConversion = 60.0; break; case MAngle::kAngSeconds: angleConversion = 3600.0; break; default: break; } MDataHandle outHandle; unsigned int index = 0; for (unsigned int cameraIndex = 0; cameraIndex < cameraSize; cameraIndex++) { Alembic::AbcGeom::ICamera & cam = mData.mCameraList[cameraIndex]; std::vector<double> array; read(mCurTime, cam, array); for (unsigned int dataIndex = 0; dataIndex < array.size(); dataIndex++, index++) { // skip over sparse elements if (index != outArrayHandle.elementIndex()) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); // not shutter angle index, so not an angle if (dataIndex != 11) { outHandle.set(array[dataIndex]); } else { outHandle.set(array[dataIndex] * angleConversion); } } // for the per camera data handles } // for each camera outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsSurfaceArrayAttr) { if (mOutRead[5]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[5] = true; unsigned int nSurfaceSize = static_cast<unsigned int>(mData.mNurbsList.size()); if (nSurfaceSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < nSurfaceSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) continue; outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kNurbsSurface)) { readNurbs(mCurTime, mData.mNurbsList[j], obj); outHandle.set(obj); } } outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsCurveGrpArrayAttr) { if (mOutRead[6]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[6] = true; unsigned int nCurveGrpSize = static_cast<unsigned int>(mData.mCurvesList.size()); if (nCurveGrpSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); MDataHandle outHandle; std::vector<MObject> curvesObj; for (unsigned int i = 0; i < nCurveGrpSize; ++i) { readCurves(mCurTime, mData.mCurvesList[i], mData.mNumCurves[i], curvesObj); } std::size_t numChild = curvesObj.size(); // not the best way to do this // only reading bunches of curves based on the connections would be // more efficient when there is a bunch of broken connections for (unsigned int i = 0; i < numChild; i++) { if (outArrayHandle.elementIndex() != i) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); status = outHandle.set(curvesObj[i]); } outArrayHandle.setAllClean(); } } else { return MS::kUnknownParameter; } dataBlock.setClean(plug); return status; }
MStatus TestDeformer::deform(MDataBlock& data, MItGeometry& iter, const MMatrix& localToWorldMatrix, unsigned int mIndex) { MStatus status; // get the current node state short initialized_mapping = data.inputValue( initialized_data, &status).asShort(); CHECK_MSTATUS(status); __debug("%s(), initialized_mapping=%d, mIndex=%d", __FUNCTION__, initialized_mapping, mIndex); if( initialized_mapping == 1 ) { initVertMapping(data, iter, localToWorldMatrix, mIndex); // set initialized_data to 2 automatically. User don't have to set it manully. MObject tObj = thisMObject(); MPlug setInitMode = MPlug( tObj, initialized_data ); setInitMode.setShort( 2 ); // and sync initialized_mapping from initialized_data // so, the code section: // if (initialized_mapping == 2) // { // ... // } // will be executed when this deform() function is called next time. initialized_mapping = data.inputValue( initialized_data, &status ).asShort(); CHECK_MSTATUS(status); } if( initialized_mapping == 2 ) { envelope = MPxDeformerNode::envelope; MDataHandle envelopeHandle = data.inputValue( envelope, &status ); CHECK_MSTATUS( status ); MArrayDataHandle vertMapArrayData = data.inputArrayValue( vert_map, &status ); CHECK_MSTATUS( status ); MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status ); CHECK_MSTATUS( status ); /// 1. init tempOutputPts to zero points MPointArray tempOutputPts; iter.reset(); while( !iter.isDone(&status) ) { CHECK_MSTATUS(tempOutputPts.append(MPoint(0, 0, 0))); CHECK_MSTATUS(iter.next()); } assert(tempOutputPts.length() == iter.count()); /// 2. set tempOutputPts to deform values which comes from each driver mesh iter.reset(); int numMeshes = meshAttrHandle.elementCount(); __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes); CHECK_MSTATUS(meshAttrHandle.jumpToElement(0)); // for each driver mesh for( int count=0; count < numMeshes; ++count ) { __debug("%s(), count=%d", __FUNCTION__, count); // for one driver mesh: currentMesh MDataHandle currentMesh = meshAttrHandle.inputValue(&status); CHECK_MSTATUS( status ); MObject meshMobj = currentMesh.asMesh(); __debugMeshInfo(__FUNCTION__, meshMobj); // accumulate deform values of currentMesh to tempOutputPts _deform_on_one_mesh(data, iter, localToWorldMatrix, mIndex, meshMobj, envelopeHandle, vertMapArrayData, tempOutputPts ); if( !meshAttrHandle.next() ) { break; } }// for each driver mesh /// 3. add deform value to this geometry(driven mesh) int i = 0; iter.reset(); while( !iter.isDone(&status) ) { MPoint p = iter.position(MSpace::kObject, &status); CHECK_MSTATUS(status); // add the deform value to this vertex CHECK_MSTATUS(iter.setPosition( p + tempOutputPts[i]/numMeshes )); CHECK_MSTATUS(iter.next()); ++i; } assert(tempOutputPts.length() == iter.count()); }// if 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 )); }
// ========================================================================================================== // ========================================================================================================== virtual MStatus compute(const MPlug& plug, MDataBlock& dataBlock) { // enable this node or not if ( dataBlock.inputValue(aEnable).asBool() == false ) { return MS::kSuccess; } // check if the inpute attribute is connected // in Not, stop compute() // in order to avoid crash when disconnect input attributes on the fly //cout << "isPlugConnect: " << isPlugConnect(aVolumeObj) << endl; if ( isPlugConnect(aSourceObj) == false || isPlugConnect(aVolumeObj) == false ) { return MS::kSuccess; } // execution when output attr needs to be updated if ( plug == aOutValue || plug == aOutMesh || plug == aOutCompList ) { // test if input source object is a valid type if ( dataBlock.inputValue(aSourceObj).type() != MFnData::kMesh ) { MGlobal::displayInfo( MString("No Object Input!") ); return MS::kSuccess; } MObject sourceObj = dataBlock.inputValue(aSourceObj).asMeshTransformed(); MArrayDataHandle arrayHandle = dataBlock.inputValue(aVolumeObj); arrayHandle.jumpToArrayElement(0); MSelectionList sList; // add the vertice every ligal loop for ( int idx=0; idx < arrayHandle.elementCount(); idx++, arrayHandle.next() ) { // first, check if the sub-plug is un-connected if ( isPlugConnect( aVolumeObj, idx ) == false ) { cout << "No Data " << idx << endl; continue; } // second, check if the input object is mesh if ( arrayHandle.inputValue().type() != MFnData::kMesh ) { return MS::kSuccess; MGlobal::displayError( "input voulme objects is not mesh" ); } // input volume object as Wrold mesh MObject volumeObj = arrayHandle.inputValue().asMeshTransformed(); MFnMesh sourceMeshFn; MFnMesh volumeMeshFn; // third, test if the input obj is compatible with meshFn if ( volumeMeshFn.hasObj(sourceObj) && volumeMeshFn.hasObj(volumeObj) ) { volumeMeshFn.setObject(volumeObj); // check if object is closed if ( isClosedMesh(volumeObj) == false ) { if ( dataBlock.inputValue(aClosedObj).asBool() == true ) { //MGlobal::displayInfo( MString("The volume object is not closed!") ); continue; } } sourceMeshFn.setObject( sourceObj ); int numVtx = sourceMeshFn.numVertices(); vector<int> tmpCompArray; // an temporary int array to store component index // do hit test // to check if each source's component is inside // for ( int i=0; i < numVtx; i++ ) { // get each vertex of source object MPoint srcVtx; sourceMeshFn.getPoint( i, srcVtx, MSpace::kWorld ); // Test how much hit is for each vertex // declare parameters for allIntersection() MFloatPoint raySource; raySource.setCast(srcVtx); MFloatVector rayDirection(0, 0, 1); MFloatPointArray hitPoints; MIntArray hitFaces; bool hit = volumeMeshFn.allIntersections( raySource, rayDirection, NULL, NULL, false, MSpace::kWorld, 99999, false, NULL, true, hitPoints, NULL, &hitFaces, NULL, NULL, NULL, 1e-6 ); if (hit) { int isInside = hitFaces.length() % 2; // cout << "isInside: " << isInside << endl; // if the mod is odd, it's inside if ( isInside > 0 ) { tmpCompArray.push_back(i); } } } // declare a dynamic array to recieve All elements from tmpCompArray int* compArray = new int[tmpCompArray.size()]; // copy array data from tmpCompArray --> compArray memcpy( &compArray[0], &tmpCompArray[0], sizeof( int ) * tmpCompArray.size() ); // the below processes are to collect component data, and then select them in viewport // // first, get dagPath from the source object MDagPath dPathSrcObj = getConnectNodeDagPath(aSourceObj); // second, get the selection list storing components by feeding comopnet array MSelectionList vtxSelList = getVtxSelList( dPathSrcObj, compArray, tmpCompArray.size() ); sList.merge(vtxSelList); delete [] compArray; } } // end of loop // if so, actively select these component int compType = dataBlock.inputValue(aComponentType).asInt(); MSelectionList currCompSelList; if( dataBlock.inputValue(aKeepSel).asBool() == true ) { // clear if last-time is not keep selection if (flag==0) { addSelComponentList.clear(); flag = 1; } else { addSelComponentList.merge(sList); // merge the accumulative components currCompSelList = convertVtxSListToCompSList( addSelComponentList, compType ); MGlobal::setActiveSelectionList( currCompSelList, MGlobal::kReplaceList ); flag = 1; } } else { addSelComponentList.clear(); // celar all components addSelComponentList.merge(sList); currCompSelList = convertVtxSListToCompSList( addSelComponentList, compType ); MGlobal::setActiveSelectionList( currCompSelList, MGlobal::kReplaceList ); flag = 0; } // keep this node selecting if ( dataBlock.inputValue(aFixPanel).asBool() == true ) MGlobal::select( thisMObject(), MGlobal::kAddToList ); // **** OUTPUT ATTRIBUTE **** MObject currCompList = getCompListFromSList( currCompSelList ); MFnComponentListData compListDataFn; MObject currCompListData = compListDataFn.create(); // pointer to the component data compListDataFn.add( currCompList ); dataBlock.outputValue(aOutCompList).set( currCompListData ); // MFnMeshData outMeshDataFn; MObject outObj = outMeshDataFn.create(); MFnMesh outMeshFn( outObj ); outMeshFn.copy( sourceObj, outObj ); dataBlock.outputValue(aOutMesh).set( outObj ); } // end of if ( plug == aOutValue || plug == aOutMesh ) return MS::kSuccess; }
void TestDeformer::_deform_on_one_mesh(MDataBlock& data, MItGeometry& iter, const MMatrix& localToWorldMatrix, unsigned int mIndex, MObject &driver_mesh, const MDataHandle &envelopeHandle, MArrayDataHandle &vertMapArrayData, MPointArray &tempOutputPts) { MStatus status; float env = envelopeHandle.asFloat(); // use driver_meshVertIter to walk through the vertex of the current driver mesh MItMeshVertex driver_meshVertIter( driver_mesh, &status ); CHECK_MSTATUS( status ); int i = 0; iter.reset(); while( !iter.isDone(&status) ) { CHECK_MSTATUS( status ); // get the weight float weight = weightValue( data, mIndex, iter.index() ); //painted weight float ww = weight * env; if ( fabs(ww) > FLT_EPSILON )//if ( ww != 0 ) { __debug("%s(), vertMapArrayData.elementCount()=%d, iter.index()=%d", __FUNCTION__, vertMapArrayData.elementCount(), iter.index()); // get index_mapped to which the currrent vertex vI is mapped CHECK_MSTATUS(vertMapArrayData.jumpToElement(iter.index())); int index_mapped = vertMapArrayData.inputValue(&status).asInt(); CHECK_MSTATUS( status ); if( index_mapped >= 0 ) { __debug("index_mapped=%d", index_mapped); int prevInt; CHECK_MSTATUS( driver_meshVertIter.setIndex(index_mapped, prevInt) ); // vertex wrold position on driver mesh MPoint mappedPt = driver_meshVertIter.position( MSpace::kWorld, &status ); CHECK_MSTATUS( status ); // vertex wrold position on driven mesh MPoint iterPt = iter.position(MSpace::kObject, &status) * localToWorldMatrix; CHECK_MSTATUS( status ); // use ww to interpolate between mappedPt and iterPt MPoint pt = iterPt + ((mappedPt - iterPt) * ww ); pt = pt * localToWorldMatrix.inverse(); /// put the deform points to tempOutputPts tempOutputPts[i] += pt; } }//if CHECK_MSTATUS(iter.next()); ++i; }//while }
MObject fullLoft::loft( MArrayDataHandle &inputArray, MObject &newSurfData, MStatus &stat ) { MFnNurbsSurface surfFn; MPointArray cvs; MDoubleArray ku, kv; int i, j; int numCVs; int numCurves = inputArray.elementCount (); // Ensure that we have at least 1 element in the input array // We must not do an inputValue on an element that does not // exist. if ( numCurves < 1 ) return MObject::kNullObj; // Count the number of CVs inputArray.jumpToElement(0); MDataHandle elementHandle = inputArray.inputValue(&stat); if (!stat) { stat.perror("fullLoft::loft: inputValue"); return MObject::kNullObj; } MObject countCurve (elementHandle.asNurbsCurve()); MFnNurbsCurve countCurveFn (countCurve); numCVs = countCurveFn.numCVs (&stat); PERRORnull("fullLoft::loft counting CVs"); // Create knot vectors for U and V // U dimension contains one CV from each curve, triple knotted for (i = 0; i < numCurves; i++) { ku.append (double (i)); ku.append (double (i)); ku.append (double (i)); } // V dimension contains all of the CVs from one curve, triple knotted at // the ends kv.append( 0.0 ); kv.append( 0.0 ); kv.append( 0.0 ); for ( i = 1; i < numCVs - 3; i ++ ) kv.append( (double) i ); kv.append( numCVs-3 ); kv.append( numCVs-3 ); kv.append( numCVs-3 ); // Build the surface's CV array for (int curveNum = 0; curveNum < numCurves; curveNum++) { MObject curve (inputArray.inputValue ().asNurbsCurve ()); MFnNurbsCurve curveFn (curve); MPointArray curveCVs; stat = curveFn.getCVs (curveCVs, MSpace::kWorld); PERRORnull("fullLoft::loft getting CVs"); if (curveCVs.length() != (unsigned)numCVs) stat = MS::kFailure; PERRORnull("fullLoft::loft inconsistent number of CVs - rebuild curves"); // Triple knot for every curve but the first int repeats = (curveNum == 0) ? 1 : 3; for (j = 0; j < repeats; j++) for ( i = 0; i < numCVs; i++ ) cvs.append (curveCVs [i]); stat = inputArray.next (); } MObject surf = surfFn.create(cvs, ku, kv, 3, 3, MFnNurbsSurface::kOpen, MFnNurbsSurface::kOpen, false, newSurfData, &stat ); PERRORnull ("fullLoft::Loft create surface"); return surf; }
MStatus nwayDeformerNode::deform( MDataBlock& data, MItGeometry& itGeo, const MMatrix &localToWorldMatrix, unsigned int mIndex ) { // clock_t clock_start=clock(); MObject thisNode = thisMObject(); MStatus status; MThreadUtils::syncNumOpenMPThreads(); // for OpenMP MArrayDataHandle hBlendMesh = data.inputArrayValue(aBlendMesh); short numIter = data.inputValue( aIteration ).asShort(); short nblendMode = data.inputValue( aBlendMode ).asShort(); short ntetMode = data.inputValue( aTetMode ).asShort(); double visualisationMultiplier = data.inputValue(aVisualisationMultiplier).asDouble(); bool visualiseEnergy = data.inputValue( aVisualiseEnergy ).asBool(); bool nrotationCosistency = data.inputValue( aRotationConsistency ).asBool(); if( nrotationCosistency != rotationCosistency) { numMesh = 0; rotationCosistency = nrotationCosistency; } MPointArray Mpts; itGeo.allPositions(Mpts); int nnumMesh = hBlendMesh.elementCount(); int numPts = Mpts.length(); int numTet = (int)tetList.size()/4; // initialisation if(tetMode != ntetMode) { // clock_t clock_start=clock(); tetMode = ntetMode; numMesh = 0; // point list pts.resize(numPts); for(int i=0; i<numPts; i++) { pts[i] << Mpts[i].x, Mpts[i].y, Mpts[i].z; } std::vector<Matrix4d> P; getMeshData(data, input, inputGeom, mIndex, tetMode, pts, tetList, faceList, edgeList, vertexList, P); dim = removeDegenerate(tetMode, numPts, tetList, faceList, edgeList, vertexList, P); makeAdjacencyList(tetMode, tetList, edgeList, vertexList, adjacencyList); makeTetMatrix(tetMode, pts, tetList, faceList, edgeList, vertexList, P); // prepare ARAP solver numTet = (int)tetList.size()/4; PI.resize(numTet); for(int i=0; i<numTet; i++) { PI[i] = P[i].inverse().eval(); } std::vector<double> tetWeight(numTet,1.0); std::vector< std::map<int,double> > constraint(0); //constraint[0][0]=1.0; isError = ARAPprecompute(PI, tetList, tetWeight, constraint, EPSILON, dim, constraintMat, solver); // MString es="Init timing: "; // double timing=(double)(clock()- clock_start)/CLOCKS_PER_SEC; // es += timing; // MGlobal::displayInfo(es); } if(isError>0) return MS::kFailure; // if blend mesh is added, compute log for each tet logR.resize(nnumMesh); logS.resize(nnumMesh); R.resize(nnumMesh); S.resize(nnumMesh); GL.resize(nnumMesh); logGL.resize(nnumMesh); quat.resize(nnumMesh); L.resize(nnumMesh); // for recomputation of parametrisation if(numMesh>nnumMesh || nblendMode != blendMode) { numMesh =0; blendMode = nblendMode; } for(int j=numMesh; j<nnumMesh; j++) { hBlendMesh.jumpToElement(j); MFnMesh blendMesh(hBlendMesh.inputValue().asMesh()); MPointArray Mbpts; blendMesh.getPoints( Mbpts ); if(numPts != Mbpts.length()) { MGlobal::displayInfo("incompatible mesh"); return MS::kFailure; } std::vector<Vector3d> bpts(numPts); for(int i=0; i<numPts; i++) { bpts[i] << Mbpts[i].x, Mbpts[i].y, Mbpts[i].z; } std::vector<Matrix4d> Q(numTet); makeTetMatrix(tetMode, bpts, tetList, faceList, edgeList, vertexList, Q); logR[j].resize(numTet); logS[j].resize(numTet); R[j].resize(numTet); S[j].resize(numTet); GL[j].resize(numTet); logGL[j].resize(numTet); quat[j].resize(numTet); L[j].resize(numTet); for(int i=0; i<numTet; i++) { Matrix4d aff=PI[i]*Q[i]; GL[j][i]=aff.block(0,0,3,3); L[j][i]=transPart(aff); parametriseGL(GL[j][i], logS[j][i] ,R[j][i]); } if( blendMode == BM_LOG3) { for(int i=0; i<numTet; i++) logGL[j][i]=GL[j][i].log(); } else if( blendMode == BM_SQL) { for(int i=0; i<numTet; i++) { S[j][i]=expSym(logS[j][i]); Quaternion<double> q(R[j][i].transpose()); quat[j][i] << q.x(), q.y(), q.z(), q.w(); } } else if( blendMode == BM_SlRL) { for(int i=0; i<numTet; i++) { S[j][i]=expSym(logS[j][i]); } } // traverse tetrahedra to compute continuous log of rotation if(rotationCosistency) { std::set<int> remain; std::queue<int> later; // load initial rotation from the attr Matrix3d initR; double angle = data.inputValue(aInitRotation).asDouble(); initR << 0,M_PI * angle/180.0,0, -M_PI * angle/180.0,0,0, 0,0,0; std::vector<Matrix3d> prevSO(numTet, initR); // create the adjacency graph to traverse for(int i=0; i<numTet; i++) { remain.insert(remain.end(),i); } while(!remain.empty()) { int next; if( !later.empty()) { next = later.front(); later.pop(); remain.erase(next); } else { next = *remain.begin(); remain.erase(remain.begin()); } logR[j][next]=logSOc(R[j][next],prevSO[next]); for(int k=0; k<adjacencyList[next].size(); k++) { int f=adjacencyList[next][k]; if(remain.erase(f)>0) { prevSO[f]=logR[j][next]; later.push(f); } } } } else { for(int i=0; i<numTet; i++) logR[j][i] = logSO(R[j][i]); } } numMesh=nnumMesh; if(numMesh == 0) return MS::kSuccess; // load weights std::vector<double> weight(numMesh); MArrayDataHandle hWeight = data.inputArrayValue(aWeight); if(hWeight.elementCount() != numMesh) { return MS::kSuccess; } for(int i=0; i<numMesh; i++) { hWeight.jumpToArrayElement(i); weight[i]=hWeight.inputValue().asDouble(); } // compute ideal affine std::vector<Vector3d> new_pts(numPts); std::vector<Matrix4d> A(numTet); std::vector<Matrix3d> AR(numTet),AS(numTet); std::vector<Vector3d> AL(numTet); blendMatList(L, weight, AL); if(blendMode==BM_SRL) { blendMatList(logR, weight, AR); blendMatList(logS, weight, AS); #pragma omp parallel for for(int i=0; i<numTet; i++) { AR[i] = expSO(AR[i]); AS[i] = expSym(AS[i]); } } else if(blendMode == BM_LOG3) { // log blendMatList(logGL, weight, AR); #pragma omp parallel for for(int i=0; i<numTet; i++) { AR[i] = AR[i].exp(); AS[i] = Matrix3d::Identity(); } } else if(blendMode == BM_SQL) { // quaternion std::vector<Vector4d> Aq(numTet); blendMatLinList(S, weight, AS); blendQuatList(quat, weight, Aq); #pragma omp parallel for for(int i=0; i<numTet; i++) { Quaternion<double> Q(Aq[i]); AR[i] = Q.matrix().transpose(); } } else if(blendMode == BM_SlRL) { // expSO+linear Sym blendMatList(logR, weight, AR); blendMatLinList(S, weight, AS); #pragma omp parallel for for(int i=0; i<numTet; i++) { AR[i] = expSO(AR[i]); } } else if(blendMode == BM_AFF) { // linear blendMatLinList(GL, weight, AR); for(int i=0; i<numTet; i++) { AS[i] = Matrix3d::Identity(); } } else { return MS::kFailure; } MatrixXd G(dim+1,3),Sol; std::vector<double> tetEnergy(numTet); // iterate to determine vertices position for(int k=0; k<numIter; k++) { for(int i=0; i<numTet; i++) { A[i]=pad(AS[i]*AR[i],AL[i]); } // solve ARAP std::vector<Vector3d> constraintVector(0); std::vector<double> tetWeight(numTet,1.0); //constraintVector[0]=pts[0]; ARAPSolve(A, PI, tetList, tetWeight, constraintVector, EPSILON, dim, constraintMat, solver, Sol); // set new vertices position for(int i=0; i<numPts; i++) { new_pts[i][0]=Sol(i,0); new_pts[i][1]=Sol(i,1); new_pts[i][2]=Sol(i,2); } // if iteration continues if(k+1<numIter || visualiseEnergy) { std::vector<Matrix4d> Q(numTet); makeTetMatrix(tetMode, new_pts, tetList, faceList, edgeList, vertexList, Q); Matrix3d S,R; #pragma omp parallel for for(int i=0; i<numTet; i++) { polarHigham((PI[i]*Q[i]).block(0,0,3,3), S, AR[i]); tetEnergy[i] = (S-AS[i]).squaredNorm(); } } } // set new vertex position for(int i=0; i<numPts; i++) { Mpts[i].x=Sol(i,0); Mpts[i].y=Sol(i,1); Mpts[i].z=Sol(i,2); } itGeo.setAllPositions(Mpts); // set vertex color according to ARAP energy if(visualiseEnergy) { std::vector<double> ptsEnergy; makePtsWeightList(tetMode, numPts, tetList, faceList, edgeList, vertexList, tetEnergy, ptsEnergy); //double max_energy = *std::max_element(ptsEnergy.begin(), ptsEnergy.end()); outputAttr(data, aEnergy, ptsEnergy); for(int i=0; i<numPts; i++) { ptsEnergy[i] *= visualisationMultiplier; // or /= max_energy } visualise(data, outputGeom, ptsEnergy); } // MString es="Runtime timing: "; // double timing=(double)(clock()- clock_start)/CLOCKS_PER_SEC; // es += timing; // MGlobal::displayInfo(es); return MS::kSuccess; }
// Compute takes two parameters: plug and data. // - Plug is the the data value that needs to be recomputed // - Data provides handles to all of the nodes attributes, only these // handles should be used when performing computations. // MStatus asMicrofacet_brdf::compute( const MPlug& plug, MDataBlock& block ) { // The plug parameter will allow us to determine which output attribute // needs to be calculated. // if( plug == aOutColor || plug == aOutTransparency || plug.parent() == aOutColor || plug.parent() == aOutTransparency ) { MStatus status; MFloatVector resultColor( 0.0, 0.0, 0.0 ); // Get surface shading parameters from input block // MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector(); CHECK_MSTATUS( status ); MFloatVector& surfaceColor = block.inputValue( aColor, &status ).asFloatVector(); CHECK_MSTATUS( status ); MFloatVector& incandescence = block.inputValue( aIncandescence, &status ).asFloatVector(); CHECK_MSTATUS( status ); float diffuseReflectivity = block.inputValue( aDiffuseReflectivity, &status ).asFloat(); CHECK_MSTATUS( status ); // float translucenceCoeff = block.inputValue( aTranslucenceCoeff, // &status ).asFloat(); // CHECK_MSTATUS( status ); // Get light list // MArrayDataHandle lightData = block.inputArrayValue( aLightData, &status ); CHECK_MSTATUS( status ); int numLights = lightData.elementCount( &status ); CHECK_MSTATUS( status ); // Calculate the effect of the lights in the scene on the color // // Iterate through light list and get ambient/diffuse values // for( int count=1; count <= numLights; count++ ) { // Get the current light out of the array // MDataHandle currentLight = lightData.inputValue( &status ); CHECK_MSTATUS( status ); // Get the intensity of that light // MFloatVector& lightIntensity = currentLight.child( aLightIntensity ).asFloatVector(); // Find ambient component // if ( currentLight.child( aLightAmbient ).asBool() ) { resultColor += lightIntensity; } // Find diffuse component // if ( currentLight.child( aLightDiffuse ).asBool() ) { MFloatVector& lightDirection = currentLight.child( aLightDirection ).asFloatVector(); float cosln = lightDirection * surfaceNormal; if ( cosln > 0.0f ) { resultColor += lightIntensity * ( cosln * diffuseReflectivity ); } } // Advance to the next light. // if ( count < numLights ) { status = lightData.next(); CHECK_MSTATUS( status ); } } // Factor incident light with surface color and add incandescence // resultColor[0] = resultColor[0] * surfaceColor[0] + incandescence[0]; resultColor[1] = resultColor[1] * surfaceColor[1] + incandescence[1]; resultColor[2] = resultColor[2] * surfaceColor[2] + incandescence[2]; // Set ouput color attribute // if ( plug == aOutColor || plug.parent() == aOutColor ) { // Get the handle to the attribute // MDataHandle outColorHandle = block.outputValue( aOutColor, &status ); CHECK_MSTATUS( status ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; // Set the output value outColorHandle.setClean(); // Mark the output value as clean } // Set ouput transparency // if ( plug == aOutTransparency || plug.parent() == aOutTransparency ) { MFloatVector& transparency = block.inputValue( aInTransparency, &status ).asFloatVector(); CHECK_MSTATUS( status ); // Get the handle to the attribute // MDataHandle outTransHandle = block.outputValue( aOutTransparency, &status ); CHECK_MSTATUS( status ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = transparency; // Set the output value outTransHandle.setClean(); // Mark the output value as clean } } else { return( MS::kUnknownParameter ); // We got an unexpected 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; }