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; }
// // 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 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; }
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; }
void TestDeformer::initVertMapping(MDataBlock& data, MItGeometry& iter, const MMatrix& localToWorldMatrix, unsigned int mIndex) { MStatus status; MArrayDataHandle vertMapOutArrayData = data.outputArrayValue( vert_map, &status ); CHECK_MSTATUS( status ); // use vertMapOutArrayBuilder to modify vertMapOutArrayData iter.reset(); int count = iter.count(); MArrayDataBuilder vertMapOutArrayBuilder( vert_map, count, &status ); CHECK_MSTATUS( status ); MPointArray allPts;// world vertex position of the driven mesh allPts.clear(); // walk through the driven mesh /// copy MItGeometry's vertex to vertMapOutArrayData int i = 0; while( !iter.isDone(&status) ) { CHECK_MSTATUS( status ); MDataHandle initIndexDataHnd = vertMapOutArrayBuilder.addElement( i, &status ); CHECK_MSTATUS( status ); int negIndex = -1; initIndexDataHnd.setInt( negIndex ); initIndexDataHnd.setClean(); // append a vertex position(world coordination) to allPts CHECK_MSTATUS(allPts.append( iter.position() * localToWorldMatrix )); i = i+1; iter.next(); } CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); /// Append more vertex from each driver mesh to vertMapOutArrayData MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status ); CHECK_MSTATUS( status ); int numMeshes = meshAttrHandle.elementCount(); __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes); CHECK_MSTATUS(meshAttrHandle.jumpToElement(0)); for( int meshIndex=0; meshIndex < numMeshes; ++meshIndex ) { __debug("%s(), meshIndex=%d", __FUNCTION__, meshIndex); MDataHandle currentMesh = meshAttrHandle.inputValue(&status); CHECK_MSTATUS(status); MObject meshMobj = currentMesh.asMesh(); __debug("%s(), meshMobj.apiTypeStr()=%s", __FUNCTION__, meshMobj.apiTypeStr()); __debugMeshInfo(__FUNCTION__, meshMobj); { _initVertMapping_on_one_mesh(meshMobj, vertMapOutArrayBuilder, allPts);// Note: vertMapOutArrayBuilder is updated in this function! //CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); } if( !meshAttrHandle.next() ) { break; } }// for (mesh CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); }
MStatus 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 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 == geometrySurfaceConstraint::constraintGeometry ) { // block.inputValue(constraintParentInverseMatrix); // MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget ); unsigned int targetArrayCount = targetArray.elementCount(); double weight,selectedWeight = 0; if ( weightType == geometrySurfaceConstraintCommand::kSmallestWeight ) selectedWeight = FLT_MAX; MObject selectedMesh; unsigned int i; for ( i = 0; i < targetArrayCount; i++ ) { MDataHandle targetElement = targetArray.inputValue(); weight = targetElement.child(targetWeight).asDouble(); if ( !equivalent(weight,0.0)) { if ( weightType == geometrySurfaceConstraintCommand::kLargestWeight ) { if ( weight > selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh(); if ( !mesh.isNull() ) { selectedMesh = mesh; selectedWeight = weight; } } } else { if ( weight < selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh(); if ( !mesh.isNull() ) { selectedMesh = mesh; selectedWeight = weight; } } } } targetArray.next(); } // if ( selectedMesh.isNull() ) { block.setClean(plug); } else { // The transform node via the geometry attribute will take care of // updating the location of the constrained geometry. MDataHandle outputConstraintGeometryHandle = block.outputValue(constraintGeometry); outputConstraintGeometryHandle.setMObject(selectedMesh); } } else { return MS::kUnknownParameter; } return MS::kSuccess; }
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 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 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 sgIkSmoothStretch::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ( plug == aOutputDistance ) { MArrayDataHandle hArrInputDistance = data.inputArrayValue( aInputDistance ); MDataHandle hStretchAble = data.inputValue( aStretchAble ); MDataHandle hSmoothArea = data.inputValue( aSmoothArea ); float stretchAble = hStretchAble.asFloat(); double allDistance = 0.0; int arrayCount = hArrInputDistance.elementCount(); double* outputDistances = new double[arrayCount]; int multMinus = 1; for( int i=0; i<arrayCount; i++ ) { MDataHandle hInputDistance = hArrInputDistance.inputValue(); double inputDistance = hInputDistance.asDouble(); if( inputDistance < 0 ) { multMinus = -1; outputDistances[i] = -inputDistance; } else { outputDistances[i] = inputDistance; } allDistance += outputDistances[i]; hArrInputDistance.next(); } MDataHandle hInPosition = data.inputValue( aInPosition ); MDataHandle hInPositionX = hInPosition.child( aInPositionX ); MDataHandle hInPositionY = hInPosition.child( aInPositionY ); MDataHandle hInPositionZ = hInPosition.child( aInPositionZ ); double smoothArea = hSmoothArea.asDouble()*0.1; double poseDistance = sqrt( pow( hInPositionX.asDouble(), 2 )+pow( hInPositionY.asDouble(), 2 )+pow( hInPositionZ.asDouble(), 2 ) ) ; allDistance = fabs( allDistance ); double stretchRate = getSmoothStretchRate( outputDistances[0], outputDistances[1], poseDistance, smoothArea ); double smoothRate = getSmoothRate( outputDistances[0], outputDistances[1], poseDistance, smoothArea ); double currentRate = ( 1-stretchAble )*smoothRate + stretchAble*stretchRate; outputDistances[0] *= currentRate*multMinus; outputDistances[1] *= currentRate*multMinus; MArrayDataHandle hArrOutputDistance = data.outputArrayValue( aOutputDistance ); MArrayDataBuilder bArrOutputDistance( aOutputDistance, arrayCount, &stat ); for( int i=0; i<arrayCount; i++ ) { MDataHandle hOutputDistance = bArrOutputDistance.addElement( i ); hOutputDistance.set( outputDistances[i] ); } hArrOutputDistance.set( bArrOutputDistance ); hArrOutputDistance.setAllClean(); data.setClean( plug ); } return MS::kSuccess; }
MStatus OnbShader::compute(const MPlug& plug, MDataBlock& block) { // Sanity check if (plug != aOutColor && plug.parent() != aOutColor && plug != aOutTransparency && plug.parent() != aOutTransparency) { return MS::kUnknownParameter; } // Note that this currently only implements the diffuse portion of the // shader and ignores specular. The diffuse portion is the Oren-Nayar // computation from: // Engel, Wolfgang et al. Programming Vertex, Geometry, and Pixel Shaders // http://content.gpwiki.org/index.php/D3DBook:(Lighting)_Oren-Nayar // Further extensions could be added to this compute method to include // the intended Blinn specular component as well as ambient and // incandescence components. // See the VP2 fragment-based implementation in onbShaderOverride for the // full shader. MStatus status; MFloatVector resultColor(0.0f, 0.0f, 0.0f); MFloatVector resultTransparency(0.0f, 0.0f, 0.0f); // Get surface shading parameters from input block const MFloatVector& surfaceColor = block.inputValue(aColor, &status).asFloatVector(); CHECK_MSTATUS(status); const float roughness = block.inputValue(aRoughness, &status).asFloat(); CHECK_MSTATUS(status); const MFloatVector& transparency = block.inputValue(aTransparency, &status).asFloatVector(); CHECK_MSTATUS(status); const MFloatVector& surfaceNormal = block.inputValue(aNormalCamera, &status).asFloatVector(); CHECK_MSTATUS(status); const MFloatVector& rayDirection = block.inputValue(aRayDirection).asFloatVector(); const MFloatVector viewDirection = -rayDirection; // Pre-compute some values that do not vary with lights const float NV = viewDirection*surfaceNormal; const float acosNV = acosf(NV); const float roughnessSq = roughness*roughness; const float A = 1.0f - 0.5f*(roughnessSq/(roughnessSq + 0.57f)); const float B = 0.45f*(roughnessSq/(roughnessSq + 0.09f)); // Get light list MArrayDataHandle lightData = block.inputArrayValue(aLightData, &status); CHECK_MSTATUS(status); const int numLights = lightData.elementCount(&status); CHECK_MSTATUS(status); // Iterate through light list and get ambient/diffuse values for (int count=1; count<=numLights; count++) { // Get the current light MDataHandle currentLight = lightData.inputValue(&status); CHECK_MSTATUS(status); // Find diffuse component if (currentLight.child(aLightDiffuse).asBool()) { // Get the intensity and direction of that light const MFloatVector& lightIntensity = currentLight.child(aLightIntensity).asFloatVector(); const MFloatVector& lightDirection = currentLight.child(aLightDirection).asFloatVector(); // Compute the diffuse factor const float NL = lightDirection*surfaceNormal; const float acosNL = acosf(NL); const float alpha = std::max(acosNV, acosNL); const float beta = std::min(acosNV, acosNL); const float gamma = (viewDirection - (surfaceNormal*NV)) * (lightDirection - (surfaceNormal*NL)); const float C = sinf(alpha)*tanf(beta); const float factor = std::max(0.0f, NL)*(A + B*std::max(0.0f, gamma)*C); // Add to result color resultColor += lightIntensity*factor; } // Advance to the next light. if (count < numLights) { status = lightData.next(); CHECK_MSTATUS(status); } } // Factor incident light with surface color resultColor[0] = resultColor[0]*surfaceColor[0]; resultColor[1] = resultColor[1]*surfaceColor[1]; resultColor[2] = resultColor[2]*surfaceColor[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(); // Set the result and mark it clean outColor = resultColor; outColorHandle.setClean(); } // Set ouput transparency if (plug == aOutTransparency || plug.parent() == aOutTransparency) { // Get the handle to the attribute MDataHandle outTransHandle = block.outputValue(aOutTransparency, &status); CHECK_MSTATUS(status); MFloatVector& outTrans = outTransHandle.asFloatVector(); // Set the result and mark it clean outTrans = transparency; outTransHandle.setClean(); } return MS::kSuccess; }
MStatus HRBFSkinCluster::skinDQ(MMatrixArray& transforms, int numTransforms, MArrayDataHandle& weightListHandle, MItGeometry& iter) { MStatus returnStatus; // compute dual quaternions. we're storing them as a parallel array. std::vector<MQuaternion> tQuaternions(numTransforms); // translation quaterions std::vector<MQuaternion> rQuaternions(numTransforms); // rotation quaternions for (int i = 0; i < numTransforms; i++) { rQuaternions.at(i) = getRotationQuaternion(transforms[i]); rQuaternions.at(i).normalizeIt(); tQuaternions.at(i) = getTranslationQuaternion(transforms[i], rQuaternions.at(i)); #if DEBUG_PRINTS std::cout << "rota quaternion " << i << " is: " << rQuaternions.at(i) << std::endl; std::cout << "tran quaternion " << i << " is: " << tQuaternions.at(i) << std::endl; #endif } MQuaternion rBlend; // blended rotation quaternions MQuaternion tBlend; // blended translation quaternions MQuaternion scaleMe; // Maya's quaternion scaling is in-place double weight; // Iterate through each point in the geometry. // for (; !iter.isDone(); iter.next()) { MPoint pt = iter.position(); MPoint skinned; rBlend = MQuaternion(); // reset tBlend = MQuaternion(); // reset rBlend[3] = 0.0; tBlend[3] = 0.0; // get the weights for this point MArrayDataHandle weightsHandle = weightListHandle.inputValue().child(weights); // compute the skinning for (int i = 0; i<numTransforms; ++i) { if (MS::kSuccess == weightsHandle.jumpToElement(i)) { weight = weightsHandle.inputValue().asDouble(); scaleMe = rQuaternions.at(i); rBlend = rBlend + scaleMe.scaleIt(weight); scaleMe = tQuaternions.at(i); tBlend = tBlend + scaleMe.scaleIt(weight); } } MMatrix dqMatrix = makeDQMatrix(rBlend.normalizeIt(), tBlend); skinned = pt * dqMatrix; // Set the final position. iter.setPosition(skinned); // advance the weight list handle weightListHandle.next(); } return returnStatus; }
MStatus HRBFSkinCluster::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& m, unsigned int multiIndex) // // Method: deform1 // // Description: Deforms the point with a simple smooth skinning algorithm // // Arguments: // block : the datablock of the node // iter : an iterator for the geometry to be deformed // m : matrix to transform the point into world space // multiIndex : the index of the geometry that we are deforming // // { MStatus returnStatus; // get HRBF status MDataHandle HRBFstatusData = block.inputValue(rebuildHRBF, &returnStatus); McheckErr(returnStatus, "Error getting rebuildHRBF handle\n"); int rebuildHRBFStatusNow = HRBFstatusData.asInt(); // handle signaling to the rest of deform that HRBFs must be rebuild bool signalRebuildHRBF = false; signalRebuildHRBF = (rebuildHRBFStatus != rebuildHRBFStatusNow); MMatrixArray bindTFs; // store just the bind transforms in here. MMatrixArray boneTFs; // ALWAYS store just the bone transforms in here. // get HRBF export status MDataHandle exportCompositionData = block.inputValue(exportComposition, &returnStatus); McheckErr(returnStatus, "Error getting exportComposition handle\n"); int exportCompositionStatusNow = exportCompositionData.asInt(); MDataHandle HRBFExportSamplesData = block.inputValue(exportHRBFSamples, &returnStatus); McheckErr(returnStatus, "Error getting exportHRBFSamples handle\n"); std::string exportHRBFSamplesStatusNow = HRBFExportSamplesData.asString().asChar(); MDataHandle HRBFExportValuesData = block.inputValue(exportHRBFValues, &returnStatus); McheckErr(returnStatus, "Error getting exportHRBFValues handle\n"); std::string exportHRBFValuesStatusNow = HRBFExportValuesData.asString().asChar(); // get skinning type MDataHandle useDQData = block.inputValue(useDQ, &returnStatus); McheckErr(returnStatus, "Error getting useDQ handle\n"); int useDQNow = useDQData.asInt(); // determine if we're using HRBF MDataHandle useHRBFData = block.inputValue(useHRBF, &returnStatus); McheckErr(returnStatus, "Error getting useHRBFData handle\n"); int useHRBFnow = useHRBFData.asInt(); // get envelope because why not MDataHandle envData = block.inputValue(envelope, &returnStatus); float env = envData.asFloat(); // get point in space for evaluating HRBF MDataHandle checkHRBFAtData = block.inputValue(checkHRBFAt, &returnStatus); McheckErr(returnStatus, "Error getting useDQ handle\n"); double* data = checkHRBFAtData.asDouble3(); // get the influence transforms // MArrayDataHandle transformsHandle = block.inputArrayValue( matrix ); // tell block what we want int numTransforms = transformsHandle.elementCount(); if ( numTransforms == 0 ) { // no transforms, no problems return MS::kSuccess; } MMatrixArray transforms; // fetch transform matrices -> actual joint matrices for ( int i=0; i<numTransforms; ++i ) { MMatrix worldTF = MFnMatrixData(transformsHandle.inputValue().data()).matrix(); transforms.append(worldTF); boneTFs.append(worldTF); transformsHandle.next(); } // inclusive matrices inverse of the driving transform at time of bind // matrices for transforming vertices to joint local space MArrayDataHandle bindHandle = block.inputArrayValue( bindPreMatrix ); // tell block what we want if ( bindHandle.elementCount() > 0 ) { for ( int i=0; i<numTransforms; ++i ) { MMatrix bind = MFnMatrixData(bindHandle.inputValue().data()).matrix(); transforms[i] = bind * transforms[i]; bindHandle.next(); if (signalRebuildHRBF) bindTFs.append(bind); } } MArrayDataHandle weightListHandle = block.inputArrayValue(weightList); if (weightListHandle.elementCount() == 0) { // no weights - nothing to do std::cout << "no weights!" << std::endl; //rebuildHRBFStatus = rebuildHRBFStatusNow - 1; // HRBFs will need to rebuilt no matter what return MS::kSuccess; } // print HRBF samples if requested if (exportHRBFSamplesStatusNow != exportHRBFSamplesStatus) { std::cout << "instructed to export HRBF samples: " << exportHRBFSamplesStatusNow.c_str() << std::endl; exportHRBFSamplesStatus = exportHRBFSamplesStatusNow; // TODO: handle exporting HRBFs to the text file format hrbfMan->debugSamplesToConsole(exportHRBFSamplesStatus); } // print HRBF values if requested if (exportHRBFValuesStatusNow != exportHRBFValuesStatus) { std::cout << "instructed to export HRBF values: " << exportHRBFValuesStatusNow.c_str() << std::endl; exportHRBFValuesStatus = exportHRBFValuesStatusNow; // TODO: handle exporting HRBFs to the text file format hrbfMan->debugValuesToConsole(exportHRBFValuesStatus); } // print HRBF composition if requested if (exportCompositionStatusNow != exportCompositionStatus) { std::cout << "instructed to export HRBF composition." << std::endl; exportCompositionStatus = exportCompositionStatusNow; // TODO: handle exporting HRBFs to the text file format hrbfMan->debugCompositionToConsole(boneTFs, numTransforms); } // check the HRBF value if the new point is significantly different MPoint checkHRBFHereNow(data[0], data[1], data[2]); if ((checkHRBFHereNow - checkHRBFHere).length() > 0.0001) { if (hrbfMan->m_HRBFs.size() == numTransforms) { std::cout << "checking HRBF at x:" << data[0] << " y: " << data[1] << " z: " << data[2] << std::endl; hrbfMan->compose(boneTFs); float val = 0.0f; float dx = 0.0f; float dy = 0.0f; float dz = 0.0f; float grad = 0.0f; hrbfMan->mf_vals->trilinear(data[0], data[1], data[2], val); hrbfMan->mf_gradX->trilinear(data[0], data[1], data[2], dx); hrbfMan->mf_gradY->trilinear(data[0], data[1], data[2], dy); hrbfMan->mf_gradZ->trilinear(data[0], data[1], data[2], dz); hrbfMan->mf_gradMag->trilinear(data[0], data[1], data[2], grad); std::cout << "val: " << val << " dx: " << dx << " dy: " << dy << " dz: " << dz << " grad: " << grad << std::endl; checkHRBFHere = checkHRBFHereNow; } } // rebuild HRBFs if needed if (signalRebuildHRBF) { std::cout << "instructed to rebuild HRBFs" << std::endl; rebuildHRBFStatus = rebuildHRBFStatusNow; MArrayDataHandle parentIDCsHandle = block.inputArrayValue(jointParentIdcs); // tell block what we want std::vector<int> jointParentIndices(numTransforms); if (parentIDCsHandle.elementCount() > 0) { for (int i = 0; i<numTransforms; ++i) { jointParentIndices[i] = parentIDCsHandle.inputValue().asInt(); parentIDCsHandle.next(); } } MArrayDataHandle jointNamesHandle = block.inputArrayValue(jointNames); // tell block what we want std::vector<std::string> jointNames(numTransforms); if (jointNamesHandle.elementCount() > 0) { for (int i = 0; i<numTransforms; ++i) { jointNames[i] = jointNamesHandle.inputValue().asString().asChar(); jointNamesHandle.next(); } } // debug //std::cout << "got joint hierarchy info! it's:" << std::endl; //for (int i = 0; i < numTransforms; ++i) { // std::cout << i << ": " << jointNames[i].c_str() << " : " << jointParentIndices[i] << std::endl; //} std::cout << "rebuilding HRBFs... " << std::endl; hrbfMan->buildHRBFs(jointParentIndices, jointNames, bindTFs, boneTFs, weightListHandle, iter, weights); std::cout << "done rebuilding!" << std::endl; weightListHandle.jumpToElement(0); // reset this, it's an iterator. trust me. iter.reset(); // reset this iterator so we can go do normal skinning } // perform traditional skinning if (useDQNow != 0) { returnStatus = skinDQ(transforms, numTransforms, weightListHandle, iter); } else { returnStatus = skinLB(transforms, numTransforms, weightListHandle, iter); } // do HRBF corrections if (useHRBFnow != 0) { if (hrbfMan->m_HRBFs.size() == numTransforms) { hrbfMan->compose(boneTFs); iter.reset(); hrbfMan->correct(iter); } } return returnStatus; }
// // 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 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 liqSurfaceNode::compute( const MPlug& plug, MDataBlock& block ) { // outColor or individual R, G, B channel if( (plug == aOutColor) || (plug.parent() == aOutColor) || (plug == aOutTransparency) || (plug.parent() == aOutTransparency) ) { //cout <<"compute... "<<endl; // init shader MStatus status; MFloatVector theColor( 0.0f, 0.0f, 0.0f ); MFloatVector& cColor = block.inputValue(aColor).asFloatVector(); MFloatVector& cTrans = block.inputValue(aOpacity).asFloatVector(); MFloatVector& ctex = block.inputValue(aGLPreviewTexture).asFloatVector(); // exploit maya's free openGL preview if ( ctex != MFloatVector( -1.0, -1.0, -1.0 ) ) theColor = ctex; else theColor = cColor; MFloatVector resultColor( 0.0, 0.0, 0.0 ); MFloatVector resultTrans( cTrans ); // lambert calc ------------------- bool& ignoreLights = block.inputValue( aMayaIgnoreLights, &status ).asBool(); float& Ka = block.inputValue( aMayaKa, &status ).asFloat(); float& Kd = block.inputValue( aMayaKd, &status ).asFloat(); // get surface normal MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector(); CHECK_MSTATUS( status ); if ( ignoreLights ) { MFloatVector cam( 0.0, 0.0, 1.0 ); float cosln = cam * surfaceNormal; if ( cosln > 0.0f ) { float diff = cosln * cosln * Kd + Ka; resultColor = diff * theColor; } } else { // Get light list MArrayDataHandle lightData = block.inputArrayValue( aLightData, &status ); CHECK_MSTATUS( status ); int numLights = lightData.elementCount( &status ); CHECK_MSTATUS( status ); // 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 * Kd ; } // Advance to the next light. if ( count < numLights ) { status = lightData.next(); CHECK_MSTATUS( status ); } } resultColor[0] *= theColor[0]; resultColor[1] *= theColor[1]; resultColor[2] *= theColor[2]; } resultTrans[0] = ( 1 - resultTrans[0] ); resultTrans[1] = ( 1 - resultTrans[1] ); resultTrans[2] = ( 1 - resultTrans[2] ); // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); MDataHandle outTransHandle = block.outputValue( aOutTransparency ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = resultTrans; outTransHandle.setClean(); } else return MS::kUnknownParameter; return MS::kSuccess; }
MStatus BCIViz::compute( const MPlug& plug, MDataBlock& block ) { if( plug == outValue ) { MStatus status; MDagPath path; MDagPath::getAPathTo(thisMObject(), path); MMatrix worldInverseSpace = path.inclusiveMatrixInverse(); MDataHandle inputdata = block.inputValue(ainput, &status); if(status) { const MMatrix drvSpace = inputdata.asMatrix(); fDriverPos.x = drvSpace(3, 0); fDriverPos.y = drvSpace(3, 1); fDriverPos.z = drvSpace(3, 2); fDriverPos *= worldInverseSpace; } fTargetPositions.clear(); MArrayDataHandle htarget = block.inputArrayValue( atargets ); unsigned numTarget = htarget.elementCount(); fTargetPositions.setLength(numTarget); for(unsigned i = 0; i<numTarget; i++) { MDataHandle tgtdata = htarget.inputValue(&status); if(status) { const MMatrix tgtSpace = tgtdata.asMatrix(); MPoint tgtPos(tgtSpace(3,0), tgtSpace(3,1), tgtSpace(3,2)); tgtPos *= worldInverseSpace; MVector disp = tgtPos; disp.normalize(); tgtPos = disp; fTargetPositions[i] = tgtPos; } htarget.next(); } m_hitTriangle = 0; neighbourId[0] = 0; neighbourId[1] = 1; neighbourId[2] = 2; if(!checkTarget()) { MGlobal::displayWarning("convex hull must have no less than 4 targes."); return MS::kSuccess; } if(!checkFirstFour(fTargetPositions)) { MGlobal::displayWarning("first 4 targes cannot sit on the same plane."); return MS::kSuccess; } if(!constructHull()) { MGlobal::displayWarning("convex hull failed on construction."); return MS::kSuccess; } findNeighbours(); calculateWeight(); MArrayDataHandle outputHandle = block.outputArrayValue( outValue ); int numWeight = fTargetPositions.length(); m_resultWeights.setLength(numWeight); for(int i=0; i < numWeight; i++) m_resultWeights[i] = 0.0; m_resultWeights[neighbourId[0]] = fAlpha; m_resultWeights[neighbourId[1]] = fBeta; m_resultWeights[neighbourId[2]] = fGamma; MArrayDataBuilder builder(outValue, numWeight, &status); for(int i=0; i < numWeight; i++) { MDataHandle outWeightHandle = builder.addElement(i); outWeightHandle.set( m_resultWeights[i] ); //MGlobal::displayInfo(MString("wei ") + i + " " + weights[i]); } outputHandle.set(builder); outputHandle.setAllClean(); } return MS::kSuccess; }
MStatus NBuddyEMPSaverNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if (plug == _outTrigger) { MDataHandle outputPathHdl = data.inputValue( _empOutputPath, &status ); NM_CheckMStatus( status, "Failed to get the output path handle"); MString outputPath = outputPathHdl.asString(); // Get the input time MDataHandle timeHdl = data.inputValue( _time, &status ); NM_CheckMStatus( status, "Failed to get time handle"); MTime time = timeHdl.asTime(); // Get the frame padding MDataHandle framePaddingHdl = data.inputValue( _framePadding, &status ); NM_CheckMStatus( status, "Failed to get the framePadding handle"); int numPad = framePaddingHdl.asInt(); // Get the frame padding MDataHandle timeStepHdl = data.inputValue( _timeStep, &status ); NM_CheckMStatus( status, "Failed to get the timeStep handle"); int timeStep = timeStepHdl.asInt(); // Get the time in frames int frameNr = (int)floor( time.as( time.uiUnit() ) ); //Create the writer, givin it the time index in seconds Nb::EmpWriter* writer = new Nb::EmpWriter( "", outputPath.asChar(), // absolute fullpath of emp frameNr, // frame timeStep, // timestep numPad, // zero-padding time.as( MTime::kSeconds ) // emp timestamp ); // Then get the inputBodies MArrayDataHandle inBodyArrayData = data.inputArrayValue( _inBodies, &status ); NM_CheckMStatus( status, "Failed to create get inBodyArrayData handle"); // Loop the input in the inBody multi plug unsigned int numBodies = inBodyArrayData.elementCount(); if ( numBodies > 0 ) { //Jump to the first element in the array inBodyArrayData.jumpToArrayElement(0); //Loop all the body inputs and add them to the empWriter for ( unsigned int i(0); i < numBodies; ++i) { MDataHandle bodyDataHnd = inBodyArrayData.inputValue( &status ); MFnPluginData dataFn(bodyDataHnd.data()); //Get naiad body from datatype naiadBodyData * bodyData = (naiadBodyData*)dataFn.data( &status ); if ( bodyData && bodyData->nBody() ) { //Add body to writer try{ Nb::String channels("*.*"); writer->write(bodyData->nBody(),channels); } catch(std::exception& e) { std::cerr << "NBuddyEMPSaverNode::compute() " << e.what() << std::endl; } } else std::cerr << "NBuddyEMPSaverNode::compute() :: No body in input " << inBodyArrayData.elementIndex() << std::endl; //Next body in the input multi inBodyArrayData.next(); } } try{ writer->close(); // Get rid of the writer object delete writer; } catch(std::exception& e) { std::cerr << "NBuddyEMPSaverNode::compute() " << e.what() << std::endl; } //Set the output to be clean indicating that we have saved out the file MDataHandle outTriggerHnd = data.outputValue( _outTrigger, &status ); outTriggerHnd.set(true); data.setClean( plug ); } return status; }
// ========================================================================================================== // ========================================================================================================== 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; }
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; }
// 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 CVstWeldNode::compute( const MPlug &mPlug, MDataBlock &mDataBlock ) { if ( mPlug == m_oaWeldOutput || mPlug == m_oaTranslate || mPlug == m_oaRotate || mPlug == m_oaTranslateX || mPlug == m_oaTranslateY || mPlug == m_oaTranslateZ || mPlug == m_oaRotateX || mPlug == m_oaRotateY || mPlug == m_oaRotateZ ) { const MObject geoObj = mDataBlock.inputValue( m_iaWorldGeometry ).data(); if ( geoObj.apiType() == MFn::kMeshData ) { MStatus mStatus; MObject meshObj = mDataBlock.inputValue( m_iaWorldGeometry ).asMeshTransformed(); MFnMesh meshFn( meshObj ); MItMeshPolygon pIt( meshObj ); MPointArray facePoints; MArrayDataHandle wiAH = mDataBlock.inputArrayValue( m_iaWeldInput ); MArrayDataHandle woAH = mDataBlock.outputArrayValue( m_oaWeldOutput, &mStatus ); MArrayDataBuilder woADB = woAH.builder( &mStatus ); const int nWeldCount = wiAH.elementCount(); for ( int i = 0; i < nWeldCount; ++i, wiAH.next() ) { MDataHandle wiDH = wiAH.inputValue(); const MMatrix &offsetMatrix = wiDH.child( m_iaOffsetMatrix ).asMatrix(); const MMatrix &inverseParentSpace = wiDH.child( m_iaInverseParentSpace ).asMatrix(); const MEulerRotation::RotationOrder rotationOrder = static_cast< MEulerRotation::RotationOrder >( wiDH.child( m_iaRotateOrder ).asShort() ); MMatrix geoMatrix; switch ( wiDH.child( m_iaType ).asShort() ) { case kMeshFace: { const int nMeshFaceIndex = wiDH.child( m_iaInt ).asInt(); GetMeshMatrix( pIt, nMeshFaceIndex, geoMatrix ); } break; default: merr << "Unknown Weld Type " << wiDH.child( m_iaType ).asShort() << std::endl; break; } const int nWeldIndex = wiAH.elementIndex(); MDataHandle woDH = woADB.addElement( nWeldIndex ); MTransformationMatrix L( inverseParentSpace * offsetMatrix * geoMatrix ); woDH.child( m_oaTranslate ).set( L.getTranslation( MSpace::kWorld ) ); MEulerRotation e = L.rotation().asEulerRotation(); e.reorder( rotationOrder ); woDH.child( m_oaRotate ).set( e.asVector() ); } } else { merr << "Invalid .inputGeometry data of type: " << geoObj.apiTypeStr() << " found while computing " << mPlug.info() << std::endl; return MS::kFailure; } return MS::kSuccess; } return MS::kUnknownParameter; }