MStatus splatDeformer::compute(const MPlug& plug, MDataBlock& data) { // do this if we are using an OpenMP implementation that is not the same as Maya's. // Even if it is the same, it does no harm to make this call. MThreadUtils::syncNumOpenMPThreads(); MStatus status = MStatus::kUnknownParameter; if (plug.attribute() != outputGeom) { return status; } unsigned int index = plug.logicalIndex(); MObject thisNode = this->thisMObject(); // get input value MPlug inPlug(thisNode,input); inPlug.selectAncestorLogicalIndex(index,input); MDataHandle hInput = data.inputValue(inPlug, &status); MCheckStatus(status, "ERROR getting input mesh\n"); // get the input geometry MDataHandle inputData = hInput.child(inputGeom); if (inputData.type() != MFnData::kMesh) { printf("Incorrect input geometry type\n"); return MStatus::kFailure; } // get the input groupId - ignored for now... MDataHandle hGroup = inputData.child(groupId); unsigned int groupId = hGroup.asLong(); // get deforming mesh MDataHandle deformData = data.inputValue(deformingMesh, &status); MCheckStatus(status, "ERROR getting deforming mesh\n"); if (deformData.type() != MFnData::kMesh) { printf("Incorrect deformer geometry type %d\n", deformData.type()); return MStatus::kFailure; } MObject dSurf = deformData.asMeshTransformed(); MFnMesh fnDeformingMesh; fnDeformingMesh.setObject( dSurf ) ; MDataHandle outputData = data.outputValue(plug); outputData.copy(inputData); if (outputData.type() != MFnData::kMesh) { printf("Incorrect output mesh type\n"); return MStatus::kFailure; } MItGeometry iter(outputData, groupId, false); // create fast intersector structure MMeshIntersector intersector; intersector.create(dSurf); // get all points at once. Faster to query, and also better for // threading than using iterator MPointArray verts; iter.allPositions(verts); int nPoints = verts.length(); // use bool variable as lightweight object for failure check in loop below bool failed = false; MTimer timer; timer.beginTimer(); #ifdef _OPENMP #pragma omp parallel for #endif for(int i=0; i<nPoints; i++) { // Cannot break out of an OpenMP loop, so if one of the // intersections failed, skip the rest if(failed) continue; // mesh point object must be in loop-local scope to avoid race conditions MPointOnMesh meshPoint; // Do intersection. Need to use per-thread status value as // MStatus has internal state and may trigger race conditions // if set from multiple threads. Probably benign in this case, // but worth being careful. MStatus localStatus = intersector.getClosestPoint(verts[i], meshPoint); if(localStatus != MStatus::kSuccess) { // NOTE - we cannot break out of an OpenMP region, so set // bad status and skip remaining iterations failed = true; continue; } // default OpenMP scheduling breaks traversal into large // chunks, so low risk of false sharing here in array write. verts[i] = meshPoint.getPoint(); } timer.endTimer(); printf("Runtime for threaded loop %f\n", timer.elapsedTime()); // write values back onto output using fast set method on iterator iter.setAllPositions(verts); if(failed) { printf("Closest point failed\n"); return MStatus::kFailure; } return status; }
MStatus AlembicCurvesLocatorNode::compute(const MPlug &plug, MDataBlock &dataBlock) { ESS_PROFILE_SCOPE("AlembicCurvesLocatorNode::compute"); MStatus status; // update the frame number to be imported double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); AbcG::ICurves obj; // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } obj = AbcG::ICurves(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mSchema = obj.getSchema(); } if (!mSchema.valid()) { return MStatus::kFailure; } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (mNbCurves == 0 || mLastSampleInfo.floorIndex != sampleInfo.floorIndex || mLastSampleInfo.ceilIndex != sampleInfo.ceilIndex) { AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (sampleInfo.alpha != 0.0) { mSchema.get(sample2, sampleInfo.ceilIndex); } // update the indices Abc::P3fArraySamplePtr samplePos = sample.getPositions(); if (mNbCurves != sample.getNumCurves() || mNbVertices != samplePos->size()) { mNbCurves = (unsigned int)sample.getNumCurves(); mNbVertices = (unsigned int)samplePos->size(); Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); mIndices.clear(); unsigned int offset = 0; for (unsigned int i = 0; i < mNbCurves; i++) { unsigned int verticesPerCurve = nbVertices->get()[i]; for (unsigned j = 0; j < verticesPerCurve - 1; j++) { mIndices.push_back(offset); offset++; mIndices.push_back(offset); } offset++; } } if (mPositions.size() != samplePos->size()) { mPositions.resize(samplePos->size()); } // check if we need to interpolate bool done = false; mBoundingBox.clear(); if (sampleInfo.alpha != 0.0) { Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions(); if (samplePos->size() == samplePos2->size()) { float alpha = float(sampleInfo.alpha); float ialpha = 1.0f - alpha; for (unsigned int i = 0; i < samplePos->size(); i++) { mPositions[i].x = ialpha * samplePos->get()[i].x + alpha * samplePos2->get()[i].x; mPositions[i].y = ialpha * samplePos->get()[i].y + alpha * samplePos2->get()[i].y; mPositions[i].z = ialpha * samplePos->get()[i].z + alpha * samplePos2->get()[i].z; mBoundingBox.expand( MPoint(mPositions[i].x, mPositions[i].y, mPositions[i].z)); } done = true; } } if (!done) { for (unsigned int i = 0; i < samplePos->size(); i++) { mPositions[i].x = samplePos->get()[i].x; mPositions[i].y = samplePos->get()[i].y; mPositions[i].z = samplePos->get()[i].z; mBoundingBox.expand( MPoint(mPositions[i].x, mPositions[i].y, mPositions[i].z)); } } // get the colors // mColors.clear(); Abc::IC4fArrayProperty propColor; if (getArbGeomParamPropertyAlembic(obj, "color", propColor)) { mColors.clear(); SampleInfo colorSampleInfo = getSampleInfo( inputTime, propColor.getTimeSampling(), propColor.getNumSamples()); Abc::C4fArraySamplePtr sampleColor = propColor.getValue(colorSampleInfo.floorIndex); mColors.resize(mPositions.size()); if (sampleColor->size() == 1) { for (unsigned int i = 0; i < (unsigned int)mColors.size(); i++) { mColors[i].r = sampleColor->get()[0].r; mColors[i].g = sampleColor->get()[0].g; mColors[i].b = sampleColor->get()[0].b; mColors[i].a = sampleColor->get()[0].a; } } else if (sampleColor->size() == mPositions.size()) { for (unsigned int i = 0; i < sampleColor->size(); i++) { mColors[i].r = sampleColor->get()[i].r; mColors[i].g = sampleColor->get()[i].g; mColors[i].b = sampleColor->get()[i].b; mColors[i].a = sampleColor->get()[i].a; } } else if (sampleColor->size() == mNbCurves) { Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); unsigned int offset = 0; for (unsigned int i = 0; i < nbVertices->size(); i++) { for (unsigned j = 0; j < (unsigned int)nbVertices->get()[i]; j++) { mColors[offset].r = sampleColor->get()[i].r; mColors[offset].g = sampleColor->get()[i].g; mColors[offset].b = sampleColor->get()[i].b; mColors[offset].a = sampleColor->get()[i].a; offset++; } } } } } mLastSampleInfo = sampleInfo; MDataHandle outSent = dataBlock.outputValue(mSentinelAttr); // increment, this tells the draw routine that the display list needs to be // regenerated outSent.set((mSent + 1 % 10)); dataBlock.setClean(mSentinelAttr); return MStatus::kSuccess; }
MStatus MG_nurbsRivet::compute(const MPlug& plug,MDataBlock& dataBlock) { //Get recompute value MDataHandle recomputeH = dataBlock.inputValue(recompute); bool recomputeV = recomputeH.asBool(); //input mesh MDataHandle inputNurbsH = dataBlock.inputValue(inputNurbSurface); MObject inputNurb = inputNurbsH.asNurbsSurfaceTransformed(); MMatrix offsetMatrixV = dataBlock.inputValue(offsetMatrix).asMatrix(); double U,V; MFnNurbsSurface nurbsFn ; nurbsFn.setObject(inputNurb); MStatus stat; if (recomputeV == true) { //input point MDataHandle inputPointH = dataBlock.inputValue(inputPoint); MPoint inputP = inputPointH.asVector(); MPoint closestP = nurbsFn.closestPoint(inputP,NULL,NULL,false,1e+99,MSpace::kObject); stat = nurbsFn.getParamAtPoint(closestP,U,V,MSpace::kObject); //Handle to U and V MDataHandle uValueH =dataBlock.outputValue(uValue); MDataHandle vValueH =dataBlock.outputValue(vValue); uValueH.set(float(U)); vValueH.set(float(V)); uValueH.setClean(); vValueH.setClean(); MDataHandle recomputeOutH = dataBlock.outputValue(recompute); } MDataHandle uH = dataBlock.inputValue(uValue); MDataHandle vH = dataBlock.inputValue(vValue); U = uH.asFloat(); V = vH.asFloat(); MPoint outPoint ; MVector uVec ; MVector vVec; MVector normal; //Get point stat = nurbsFn.getPointAtParam(U,V,outPoint,MSpace::kObject); //Since if getting both the U and V tangent was leading to some little rotation snapping //of the rivet I only used the U tangent and calculated the next one by dot product //of the normal and U tangent leading to a 100% stable rivet nurbsFn.getTangents(U,V,uVec,vVec,MSpace::kObject); uVec.normalize(); vVec.normalize(); MVector vVecCross; //Get normal normal = nurbsFn.normal(U,V,MSpace::kObject); normal.normalize(); vVecCross =(uVec^normal); //Build the maya matrix double myMatrix[4][4]={ { uVec.x, uVec.y , uVec.z, 0}, { normal[0], normal[1] , normal[2], 0}, {vVecCross.x, vVecCross.y , vVecCross.z, 0}, { outPoint[0], outPoint[1] , outPoint[2], 1}}; MMatrix rotMatrix (myMatrix); MMatrix offsetMatrixV2 = offsetMatrixV*rotMatrix; MTransformationMatrix matrixFn(offsetMatrixV2); double angles[3]; MTransformationMatrix::RotationOrder rotOrder; rotOrder =MTransformationMatrix::kXYZ; matrixFn.getRotation(angles,rotOrder,MSpace::kObject ); //get back radians value double radX,radY,radZ; radX=angles[0]; radY=angles[1]; radZ=angles[2]; //convert to degree double rotX,rotY,rotZ; rotX = radX*toDeg; rotY = radY*toDeg; rotZ = radZ*toDeg; MDataHandle outputRotateH = dataBlock.outputValue(outputRotate); outputRotateH.set3Double(rotX,rotY,rotZ); outputRotateH.setClean(); //let set the output matrix too MDataHandle outMH= dataBlock.outputValue(outputMatrix); outMH.set(rotMatrix); outMH.setClean(); MDataHandle outputH = dataBlock.outputValue(output); outputH.set(offsetMatrixV2[3][0],offsetMatrixV2[3][1],offsetMatrixV2[3][2]); outputH.setClean(); return MS::kSuccess; }
void connectingNode::turnOffTrigger(MDataBlock &data){ MStatus status=MStatus::kSuccess; MDataHandle triggerHandle=data.outputValue(trigger,&status); triggerHandle.setBool(false); }
MStatus AlembicCurvesNode::compute(const MPlug &plug, MDataBlock &dataBlock) { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute"); MStatus status; // update the frame number to be imported const double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } AbcG::ICurves obj(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mObj = obj; mSchema = obj.getSchema(); mCurvesData = MObject::kNullObj; } if (!mSchema.valid()) { return MStatus::kFailure; } { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (!mCurvesData.isNull() && mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; const float blend = (float)sampleInfo.alpha; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (blend != 0.0f) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions(); Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); const bool applyBlending = (blend == 0.0f) ? false : (samplePos->size() == samplePos2->size()); Abc::FloatArraySamplePtr pKnotVec = getKnotVector(mObj); Abc::UInt16ArraySamplePtr pOrders = getCurveOrders(mObj); MArrayDataHandle arrh = dataBlock.outputArrayValue(mOutGeometryAttr); MArrayDataBuilder builder = arrh.builder(); // reference: // http://download.autodesk.com/us/maya/2010help/API/multi_curve_node_8cpp-example.html const int degree = (sample.getType() == AbcG::kCubic) ? 3 : 1; const bool closed = (sample.getWrap() == AbcG::kPeriodic); unsigned int pointOffset = 0; unsigned int knotOffset = 0; for (int ii = 0; ii < nbVertices->size(); ++ii) { const unsigned int nbCVs = (unsigned int)nbVertices->get()[ii]; const int ldegree = (pOrders) ? pOrders->get()[ii] : degree; const int nbSpans = (int)nbCVs - ldegree; MDoubleArray knots; if (pKnotVec) { const unsigned int nb_knot = nbCVs + ldegree - 1; for (unsigned int i = 0; i < nb_knot; ++i) { knots.append(pKnotVec->get()[knotOffset + i]); } knotOffset += nb_knot; } else { for (int span = 0; span <= nbSpans; ++span) { knots.append(double(span)); if (span == 0 || span == nbSpans) { for (int m = 1; m < degree; ++m) { knots.append(double(span)); } } } } MPointArray points; if (samplePos->size() > 0) { points.setLength((unsigned int)nbCVs); if (applyBlending) { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals1 = samplePos->get()[pointOffset + i]; const Abc::P3fArraySample::value_type &vals2 = samplePos2->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals1.x + (vals2.x - vals1.x) * blend; pt.y = vals1.y + (vals2.y - vals1.y) * blend; pt.z = vals1.z + (vals2.z - vals1.z) * blend; } } else { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals = samplePos->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals.x; pt.y = vals.y; pt.z = vals.z; } } pointOffset += nbCVs; } // create a subd either with or without uvs MObject mmCurvesData = MFnNurbsCurveData().create(); if (ldegree == 1 || ldegree == 3) mCurves.create(points, knots, ldegree, closed ? MFnNurbsCurve::kClosed : MFnNurbsCurve::kOpen, false, false, mmCurvesData); builder.addElement(ii).set(mmCurvesData); } arrh.set(builder); arrh.setAllClean(); return MStatus::kSuccess; }
/* This function gets called by Maya to evaluate the texture. */ MStatus shiftNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ((plug != aOutColor) && (plug.parent() != aOutColor)) return MS::kUnknownParameter; MDataHandle colorH; MFloatVector color; MDataHandle shiftH = data.inputValue( aShift, &stat); PERRORfail(stat, "compute getting shift attr"); bool shiftIt = shiftH.asBool(); MDataHandle distH = data.inputValue( aDist, &stat); PERRORfail(stat, "compute getting distance attr"); float distance = distH.asFloat(); MFloatVector clr; if ( shiftIt && distance != 0.0 ) { // first evaluate color at default sample posiiton clr = data.inputValue( aColor ).asFloatVector(); // uv is used by 2d textures // refPointCamera is used by 3d textures MDataHandle refPointCamH = data.inputValue( aRefPointCamera, &stat); PERRORfail(stat, "compute getting refPointCamera attr"); MFloatVector refPC = refPointCamH.asFloatVector(); // get current UV const float2 & oldUV = data.inputValue(aUv).asFloat2(); // shift and set the uv/refPointCamera values so // we can sample around the current uv/refPointCamera MDataHandle outUV = data.outputValue( aUv ); MDataHandle outPC = data.outputValue( aRefPointCamera ); outUV.set( oldUV[0]-distance, oldUV[1] ); outPC.set( refPC.x + distance, refPC.y + distance, refPC.z + distance); colorH = data.inputValue( aColor, &stat); // evaluate at new pos color = colorH.asFloatVector(); clr += color; outUV.set( oldUV[0]+distance, oldUV[1] ); outPC.set( refPC.x - distance, refPC.y + distance, refPC.z + distance); colorH = data.inputValue( aColor, &stat); // evaluate at new pos color = colorH.asFloatVector(); clr += color; outUV.set( oldUV[0], oldUV[1]-distance ); outPC.set( refPC.x + distance, refPC.y - distance, refPC.z + distance); colorH = data.inputValue( aColor, &stat); // evaluate at new pos color = colorH.asFloatVector(); clr += color; outUV.set( oldUV[0], oldUV[1]+distance ); outPC.set( refPC.x - distance, refPC.y - distance, refPC.z + distance); colorH = data.inputValue( aColor, &stat); // evaluate at new pos color = colorH.asFloatVector(); clr += color; clr /= 5.0; // average the colors from all locations // set sample data back to original values outUV.set( oldUV[0], oldUV[1] ); outPC.set( refPC.x, refPC.y, refPC.z ); } else { colorH = data.inputValue( aColor, &stat); clr = colorH.asFloatVector(); } MDataHandle outColorHandle = data.outputValue( aOutColor ); MFloatVector& oclr = outColorHandle.asFloatVector(); oclr = clr; outColorHandle.setClean(); return MS::kSuccess; }
MStatus puttyNode::compute( const MPlug& plug, MDataBlock& block ) { MStatus status; if ( plug == aNodeReady ) { // MGlobal::displayInfo("compute"); bool result =false; MString cmdBaseName; // get the source flag MDataHandle dh = block.inputValue(aSource,&status); SYS_ERROR_CHECK(status, "Error getting source data handle\n"); bool source = dh.asBool(); // get the command dh = block.inputValue(aScript,&status); SYS_ERROR_CHECK(status, "Error getting reload script handle\n"); MString script = dh.asString(); if (script == "") { MGlobal::displayError("no script provided!\n"); } else { // chech if script is sourced dh = block.inputValue(aScriptSourced,&status); SYS_ERROR_CHECK(status, "Error getting aScriptSourced data handle\n"); bool scriptSourced = dh.asBool(); // if it's not ready, don't do anything if (!scriptSourced) return MS::kSuccess; else { MCommandResult melResult; // now get the real name of the function and store it in a separate attribute MString cmd="basenameEx \"" + script+"\""; status = MGlobal::executeCommand(cmd,melResult); melResult.getResult(cmdBaseName); result = true; MDataHandle dhCBN = block.outputValue(aCmdBaseName,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName data handle\n"); dhCBN.set(cmdBaseName); dhCBN.setClean(); // see if an interface function is present, if yes, execute it cmd= "if(exists(\"" + cmdBaseName +".interface\")) {"; cmd+= "string $attr[] = `deleteAttr -q " +name()+"`; string $a;"; cmd+="for($a in $attr) deleteAttr (\""+name()+".\"+$a);"; cmd+= cmdBaseName +".interface(\"" +name()+"\");}"; status = MGlobal::executeCommand(cmd); } } // check the current status // set the result MDataHandle dhNodeReady = block.outputValue(aNodeReady,&status); SYS_ERROR_CHECK(status, "Error getting reload data handle\n"); dhNodeReady.set(result); dhNodeReady.setClean(); return MS::kSuccess; } else if (plug==aScriptSourced) { // this part of the function sources the script // try to source the script // cerr << "\nsource"; MStatus status; bool result = true; // get the source flag MDataHandle dh = block.inputValue(aSource,&status); SYS_ERROR_CHECK(status, "Error getting source data handle\n"); bool source = dh.asBool(); // get the script dh = block.inputValue(aScript,&status); SYS_ERROR_CHECK(status, "Error getting reload script handle\n"); MString script = dh.asString(); MString cmd = "source \"" + script+"\""; MCommandResult melResult; status = MGlobal::executeCommand(cmd,melResult); if (status.error()) { MGlobal::displayError( "Error sourcing mel script, please check the function you provided is valid!"); result = false; } // set the result MDataHandle dhScriptSourced = block.outputValue(aScriptSourced,&status); SYS_ERROR_CHECK(status, "Error getting ScriptSourced data handle\n"); dhScriptSourced.set(result); dhScriptSourced.setClean(); return MS::kSuccess; } return MS::kUnknownParameter; }
MStatus MG_dotProduct::compute(const MPlug& plug,MDataBlock& dataBlock) { MStatus returnStatus; if ((plug==dotProductA)|| (plug==dotProductMax)|| (plug==proj1on2)|| (plug==proj2on1)|| (plug==angleInBetweenAttr)|| (plug==angleX)|| (plug==angleY)|| (plug==angleZ)) /*get time */ { //creating handles to the input values MDataHandle vector1DataH = dataBlock.inputValue(vector1); MFloatPoint vector1V = vector1DataH.asFloatVector(); MDataHandle vector2DataH = dataBlock.inputValue(vector2); MFloatPoint vector2V = vector2DataH.asFloatVector(); MDataHandle xAxisH = dataBlock.inputValue(projAxisX); MFloatPoint xAxisData = xAxisH.asFloatVector(); MDataHandle yAxisH = dataBlock.inputValue(projAxisY); MFloatPoint yAxisData = yAxisH.asFloatVector(); MDataHandle zAxisH = dataBlock.inputValue(projAxisZ); MFloatPoint zAxisData = zAxisH.asFloatVector(); MDataHandle normData = dataBlock.inputValue(normalize); bool norm =normData.asBool(); //Creating some neededs variables float dotResult; // variable that will hold the dot product result float maxValue; //variable that will hold the dot product max value float distance1; // variable that will hold the vector 1 lenght float distance2; //variable that will hold the vector 2 lenght float angleDeg; //variable that will hold the angle inbetween the two vectors //float cosRad ; //variable that will hold the cosine value in radiants //Dot product math float vec1Array[3] = {vector1V[0],vector1V[1],vector1V[2]}; vector <float> vec1 = makeVector(vec1Array) ; float vec2Array[3] = {vector2V[0],vector2V[1],vector2V[2]}; vector <float> vec2 = makeVector(vec2Array) ; dotResult = vecDotProduct(vec1,vec2); distance1 = vectorLength(vec1); distance2 = vectorLength(vec2); maxValue = distance1*distance2; if (norm == 1) { if (maxValue ==0) { dotResult=0; }else{ dotResult = dotResult/maxValue; } } //Projection v2 on v1 float projV2=0; //variable that will hold the value projection of v2 projected on v1 vector <float> v1Norm; // variable that will hold the normalized v1 vector vector<float> v2Vec; // variable that will hold the projected vector if (distance1 != 0) { projV2 = projVector(vec2,vec1); v1Norm = normVector(vec1); v2Vec = scalarVector(v1Norm,projV2); }else{ //initialize the vector as 0 0 0 float zeroVec2[3]= {0,0,0}; v2Vec=makeVector(zeroVec2); } //Projection v1 on v2 float projV1=0; //variable that will hold the value projection of v1 projected on v2 vector <float> v2Norm;// variable that will hold the normalized v2 vector vector <float> v1Vec;// variable that will hold the projected vector if (distance2 != 0) { projV1 = projVector(vec1,vec2); v2Norm = normVector(vec2); v1Vec = scalarVector(v2Norm,projV1); }else{ //initialize the vector as 0 0 0 float zeroVec1[3]= {0,0,0}; v1Vec=makeVector(zeroVec1); } //Angle in between if ((distance2*distance1)!=0) { angleDeg=angleInbetweenVector(vec1,vec2); }else{ angleDeg=0; } //Angle inbetween splitted into X,Y,Z world rotation //float dotResultV1X; // splitting inbetween angle into X Y Z rotation //converting axis from node into vector class float xAxisArray[3] = {xAxisData[0],xAxisData[1],xAxisData[2]}; vector<float> xAxisVec = makeVector(xAxisArray) ; float yAxisArray[3] = {yAxisData[0],yAxisData[1],yAxisData[2]}; vector<float> yAxisVec = makeVector(yAxisArray) ; float zAxisArray[3] = {zAxisData[0],zAxisData[1],zAxisData[2]}; vector<float> zAxisVec = makeVector(zAxisArray) ; float angleProjXYDeg=0 ; float angleProjYZDeg=0 ; float angleProjXZDeg=0 ; // angle Z vector<float> projectedV1; vector<float> projectedV2; projectedV1= projectVectorOnPlane(vec1,xAxisVec,yAxisVec); projectedV2= projectVectorOnPlane(vec2,xAxisVec,yAxisVec); angleProjXYDeg=angleInbetweenVector(projectedV1,projectedV2); // angle X projectedV1= projectVectorOnPlane(vec1,zAxisVec,yAxisVec); projectedV2= projectVectorOnPlane(vec2,zAxisVec,yAxisVec); angleProjYZDeg=angleInbetweenVector(projectedV1,projectedV2); // angle Y projectedV1= projectVectorOnPlane(vec1,zAxisVec,xAxisVec); projectedV2= projectVectorOnPlane(vec2,zAxisVec,xAxisVec); angleProjXZDeg=angleInbetweenVector(projectedV1,projectedV2); //Setting output values MDataHandle output = dataBlock.outputValue(dotProductA); MDataHandle outputMax = dataBlock.outputValue(dotProductMax); MDataHandle projV1Output = dataBlock.outputValue(proj1on2); MDataHandle projV2Output = dataBlock.outputValue(proj2on1); MDataHandle angleInBetweenOutput = dataBlock.outputValue(angleInBetweenAttr); MDataHandle angleXout = dataBlock.outputValue(angleX); MDataHandle angleYout = dataBlock.outputValue(angleY); MDataHandle angleZout = dataBlock.outputValue(angleZ); output.set(dotResult); outputMax.set(maxValue); projV1Output.set(v1Vec[0],v1Vec[1],v1Vec[2]); projV2Output.set(v2Vec[0],v2Vec[1],v2Vec[2]); angleInBetweenOutput.set(angleDeg); angleXout.set(angleProjYZDeg); angleYout.set(angleProjXZDeg); angleZout.set(angleProjXYDeg); //SetClean tells maya attribute is update outputMax.setClean(); output.setClean(); projV1Output.setClean(); projV2Output.setClean(); angleInBetweenOutput.setClean(); angleXout.setClean(); angleYout.setClean(); angleZout.setClean(); } 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 proWater::compute(const MPlug& plug, MDataBlock& dataBlock) { MStatus status = MStatus::kUnknownParameter; if (plug.attribute() == outputGeom) { // get the input corresponding to this output // unsigned int index = plug.logicalIndex(); MObject thisNode = this->thisMObject(); MPlug inPlug(thisNode,input); inPlug.selectAncestorLogicalIndex(index,input); MDataHandle hInput = dataBlock.inputValue(inPlug); // get the input geometry and input groupId // MDataHandle hGeom = hInput.child(inputGeom); MDataHandle hGroup = hInput.child(groupId); unsigned int groupId = hGroup.asLong(); MDataHandle hOutput = dataBlock.outputValue(plug); hOutput.copy(hGeom); MStatus returnStatus; MDataHandle envData = dataBlock.inputValue(envelope, &returnStatus); if (MS::kSuccess != returnStatus) return returnStatus; float env = envData.asFloat(); MDataHandle timeData = dataBlock.inputValue(time, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double t = timeData.asDouble(); MDataHandle dirData = dataBlock.inputValue(dir, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double dirDeg = dirData.asDouble(); MDataHandle bigData = dataBlock.inputValue(bigFreq, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double bigFreqAmp = bigData.asDouble(); MDataHandle ampData = dataBlock.inputValue(amplitude1, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double amp1 = ampData.asDouble(); MDataHandle freqData = dataBlock.inputValue(frequency1, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double freq1 = freqData.asDouble(); MDataHandle ampData2 = dataBlock.inputValue(amplitude2, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double amp2 = ampData2.asDouble(); MDataHandle freqData2 = dataBlock.inputValue(frequency2, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double freq2 = freqData2.asDouble(); // Get the MFnMesh MStatus stat; MObject inputObj = hOutput.data(); MFnMesh * meshFn = new MFnMesh(inputObj, &stat); // do the deformation // MItGeometry iter(hOutput,groupId,false); for ( ; !iter.isDone(); iter.next()) { MPoint pt = iter.position(); //float2 uvPoint; //float u,v; //uvPoint[0] = u; //uvPoint[1] = v; //meshFn->getUVAtPoint(pt, uvPoint, MSpace::kObject); float u = pt.x; //uvPoint[0]*100; float v = pt.z; //uvPoint[1]*100; float degDir = dirDeg; float dir = degDir* M_PI/180; float dirX = cos(dir); float dirY = sin(dir); float bigFreq = 0.01; float bigWaves = scaled_raw_noise_3d(0, 1, (u + 3*t*dirX)*bigFreq*dirX, (v + 3*t*dirY)*bigFreq*dirY*2, t*0.01); float frequency1 = freq1/10;//0.2; float amplitude1 = amp1;//1.3; float firstOctave = -(std::abs(scaled_raw_noise_3d(-amplitude1, amplitude1, (float)(u + 0.7*t*dirX)*frequency1*0.4, (float)(v + 0.7*t*dirY)*frequency1*0.6, 0.05*t))-amplitude1); float frequency2 = freq2/10; float amplitude2 = amp2; float secondOctave = - (std::abs(scaled_raw_noise_3d(-amplitude2, amplitude2, (float)(u + 0.7*t*dirX)*frequency2*0.35, (float)(v + 0.7*t*dirY)*frequency2*0.65, 0.005*t))-amplitude2); float frequency3 = freq1/10; float amplitude3 = amp1/1.5; float thirdOctave = - (std::abs(scaled_raw_noise_3d(-amplitude3, amplitude3, (float)(u + t*0.5*dirX)*frequency3*0.4, (float)(v + t*0.5*dirY)*frequency3*0.6, 30))-amplitude3); float frequency4 = freq2/10; float amplitude4 = amp2/1.5; float fourthOctave = scaled_raw_noise_3d(-amplitude4, amplitude4, (float)(u + t*0.5*dirX)*frequency4*0.4, (float)(v + t*0.5*dirY)*frequency4*0.6, 50); float frequency5 = freq2; float amplitude5 = amp2/2; float fifthOctave = scaled_raw_noise_3d(-amplitude5, amplitude5, (float)(u + t*0.5*dirX)*frequency5*0.15, (float)(v + t*0.5*dirY)*frequency5*0.85, 0.001*t); float disp = bigFreqAmp*bigWaves + 7*(bigWaves)*firstOctave + secondOctave + thirdOctave*thirdOctave + fourthOctave + std::abs(bigWaves-1)*fifthOctave; pt = pt + iter.normal()*disp; iter.setPosition(pt); } delete meshFn; status = MStatus::kSuccess; } return status; }
MStatus splitUVNode::compute( const MPlug& plug, MDataBlock& data ) // // Description: // This method computes the value of the given output plug based // on the values of the input attributes. // // Arguments: // plug - the plug to compute // data - object that provides access to the attributes for this node // { MStatus status = MS::kSuccess; MDataHandle stateData = data.outputValue( state, &status ); MCheckStatus( status, "ERROR getting state" ); // Check for the HasNoEffect/PassThrough flag on the node. // // (stateData is an enumeration standard in all depend nodes - stored as short) // // (0 = Normal) // (1 = HasNoEffect/PassThrough) // (2 = Blocking) // ... // if( stateData.asShort() == 1 ) { MDataHandle inputData = data.inputValue( inMesh, &status ); MCheckStatus(status,"ERROR getting inMesh"); MDataHandle outputData = data.outputValue( outMesh, &status ); MCheckStatus(status,"ERROR getting outMesh"); // Simply redirect the inMesh to the outMesh for the PassThrough effect // outputData.set(inputData.asMesh()); } else { // Check which output attribute we have been asked to // compute. If this node doesn't know how to compute it, // we must return MS::kUnknownParameter // if (plug == outMesh) { MDataHandle inputData = data.inputValue( inMesh, &status ); MCheckStatus(status,"ERROR getting inMesh"); MDataHandle outputData = data.outputValue( outMesh, &status ); MCheckStatus(status,"ERROR getting outMesh"); // Now, we get the value of the uvList and use it to perform // the operation on this mesh // MDataHandle inputUVs = data.inputValue( uvList, &status); MCheckStatus(status,"ERROR getting uvList"); // Copy the inMesh to the outMesh, and now you can // perform operations in-place on the outMesh // outputData.set(inputData.asMesh()); MObject mesh = outputData.asMesh(); // Retrieve the UV list from the component list. // // Note, we use a component list to store the components // because it is more compact memory wise. (ie. comp[81:85] // is smaller than comp[81], comp[82],...,comp[85]) // MObject compList = inputUVs.data(); MFnComponentListData compListFn( compList ); unsigned i; int j; MIntArray uvIds; for( i = 0; i < compListFn.length(); i++ ) { MObject comp = compListFn[i]; if( comp.apiType() == MFn::kMeshMapComponent ) { MFnSingleIndexedComponent uvComp( comp ); for( j = 0; j < uvComp.elementCount(); j++ ) { int uvId = uvComp.element(j); uvIds.append( uvId ); } } } // Set the mesh object and uvList on the factory // fSplitUVFactory.setMesh( mesh ); fSplitUVFactory.setUVIds( uvIds ); // Now, perform the splitUV // status = fSplitUVFactory.doIt(); // Mark the output mesh as clean // outputData.setClean(); } else { status = MS::kUnknownParameter; } } return status; }
MStatus VmIslandNode::compute( const MPlug& i_plug, MDataBlock& io_dataBlock ) { MStatus status; fprintf( stderr, "VmIslandNode::compute()...\n" ); //Check plugs if( i_plug == oa_update ) { //Make sure all internal structures are up to date with attributes fprintf( stderr, "VmIslandNode::compute(oa_update)\n" ); MDataHandle seedHandle = io_dataBlock.inputValue( ia_seed, & status); const long seed = seedHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle roughnessHandle = io_dataBlock.inputValue( ia_roughness, & status); const float roughness = roughnessHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle planeHeightHandle = io_dataBlock.inputValue( ia_planeHeight, & status); const long planeHeight = planeHeightHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle smoothHandle = io_dataBlock.inputValue( ia_smooth, & status); const long smooth = smoothHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle resolutionHandle = io_dataBlock.inputValue( ia_resolution, & status); const long resolution = resolutionHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle planeSizeHandle = io_dataBlock.inputValue( ia_planeSize, & status); const long planeSize = planeSizeHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle gridSizeHandle = io_dataBlock.inputValue( ia_gridSize, & status); const long gridSize = gridSizeHandle.asLong(); m_gridSize = (int) gridSize; CHECK_MSTATUS( status ); //Grass //-------------- MDataHandle baseWidthHandle = io_dataBlock.inputValue( ia_baseWidth, & status); const float baseWidth = baseWidthHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle grassMultiplierHandle = io_dataBlock.inputValue( ia_grassMultiplier, & status); const long grassMultiplier = grassMultiplierHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle grassSegmentLengthHandle = io_dataBlock.inputValue( ia_grassSegmentLength, & status); const float grassSegmentLength = grassSegmentLengthHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle grassNumSegmentsHandle = io_dataBlock.inputValue( ia_grassNumSegments, & status); const long grassNumSegments = grassNumSegmentsHandle.asLong(); CHECK_MSTATUS( status ); //MDataHandle windDirectionHandle = io_dataBlock.inputValue( ia_windDirection, & status); MFloatVector& windDirVec = io_dataBlock.inputValue( ia_windDirection, & status).asFloatVector(); const Vcore::Vec3 windDirection = Vec3(windDirVec.x, windDirVec.y, windDirVec.z); CHECK_MSTATUS( status ); MDataHandle grassBendAmountHandle = io_dataBlock.inputValue( ia_grassBendAmount, & status); const float grassBendAmount = grassBendAmountHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle windSpreadHandle = io_dataBlock.inputValue( ia_windSpread, & status); const float windSpread = windSpreadHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle clockHandle = io_dataBlock.inputValue( ia_clock, & status); const float clock = clockHandle.asLong(); CHECK_MSTATUS( status ); //Colours //----------------- MFloatVector& grassBaseColour1Vec = io_dataBlock.inputValue( ia_grassBaseColour1, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour1 = Vec3(grassBaseColour1Vec.x, grassBaseColour1Vec.y, grassBaseColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour1Vec = io_dataBlock.inputValue( ia_grassTipColour1, & status).asFloatVector(); const Vcore::Vec3 grassTipColour1 = Vec3(grassTipColour1Vec.x, grassTipColour1Vec.y, grassTipColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassBaseColour2Vec = io_dataBlock.inputValue( ia_grassBaseColour2, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour2 = Vec3(grassBaseColour2Vec.x, grassBaseColour2Vec.y, grassBaseColour2Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour2Vec = io_dataBlock.inputValue( ia_grassTipColour2, & status).asFloatVector(); const Vcore::Vec3 grassTipColour2 = Vec3(grassTipColour2Vec.x, grassTipColour2Vec.y, grassTipColour2Vec.z); CHECK_MSTATUS( status ); //Update paramters of external lib system and rebuild m_island.setPlaneParameters( planeSize, planeHeight, seed, roughness, resolution, gridSize, grassMultiplier, baseWidth, grassSegmentLength, grassNumSegments, windDirection, grassBendAmount, windSpread, clock, smooth, grassBaseColour1, grassTipColour1, grassBaseColour2, grassTipColour2 ); //Rebuild object and check for success const bool updateOK = m_island.build(); m_cachedVertices = m_island.getComponents( Vcore::Visland::VERTICES ); m_cachedColours = m_island.getComponents( Vcore::Visland::COLOURS ); m_cachedNormals = m_island.getComponents( Vcore::Visland::NORMALS ); m_cachedIndices = m_island.getAllIndices(); m_geomInstances = m_island.getAllGeometryInstances(); // We must set a value for the plug we have been asked to evaluate, // even if we are not going to use it. We set it in the data-block, // and to set it we use outputValue(). // // Here we usually set the result to true. The caller who triggered the // computation for this attribute might not look at the value that // we are setting this plug to. But they do ask for the value of this plug, // only to trigger an update of the internal structures. See the draw() // and boundingBox() methods to see how this is done. MDataHandle updateHandle = io_dataBlock.outputValue( i_plug ); updateHandle.set( updateOK ); //Need to set plug to clean to refresh it io_dataBlock.setClean( i_plug ); } else if( i_plug == oa_rib ) { //Set up rib system to ready renderman values fprintf( stderr, "VmIslandNode::compute(oa_rib)\n" ); MDataHandle seedHandle = io_dataBlock.inputValue( ia_seed, & status); const long seed = seedHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle smoothHandle = io_dataBlock.inputValue( ia_smooth, & status); const float smooth = smoothHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle roughnessHandle = io_dataBlock.inputValue( ia_roughness, & status); const float roughness = roughnessHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle rmanResolutionHandle = io_dataBlock.inputValue( ia_rmanResolution, & status); const long rmanResolution = rmanResolutionHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle planeHeightHandle = io_dataBlock.inputValue( ia_planeHeight, & status); const long planeHeight = planeHeightHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle planeSizeHandle = io_dataBlock.inputValue( ia_planeSize, & status); const long planeSize = planeSizeHandle.asLong(); CHECK_MSTATUS( status ); //Grass //---------------- MDataHandle gridSizeHandle = io_dataBlock.inputValue( ia_gridSize, & status); const long gridSize = gridSizeHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle grassMultiplierHandle = io_dataBlock.inputValue( ia_grassMultiplier, & status); const long grassMultiplier = grassMultiplierHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle baseWidthHandle = io_dataBlock.inputValue( ia_baseWidth, & status); const float baseWidth = baseWidthHandle.asFloat(); m_gridSize = (int) baseWidth; CHECK_MSTATUS( status ); MDataHandle grassSegmentLengthHandle = io_dataBlock.inputValue( ia_grassSegmentLength, & status); const float grassSegmentLength = grassSegmentLengthHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle grassNumSegmentsHandle = io_dataBlock.inputValue( ia_grassNumSegments, & status); const long grassNumSegments = grassNumSegmentsHandle.asLong(); CHECK_MSTATUS( status ); MFloatVector& windDirVec = io_dataBlock.inputValue( ia_windDirection, & status).asFloatVector(); const Vcore::Vec3 windDirection = Vec3(windDirVec.x, windDirVec.y, windDirVec.z); CHECK_MSTATUS( status ); MDataHandle grassBendAmountHandle = io_dataBlock.inputValue( ia_grassBendAmount, & status); const float grassBendAmount = grassBendAmountHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle windSpreadHandle = io_dataBlock.inputValue( ia_windSpread, & status); const float windSpread = windSpreadHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle clockHandle = io_dataBlock.inputValue( ia_clock, & status); const float clock = clockHandle.asLong(); CHECK_MSTATUS( status ); //Colours //------------------- MFloatVector& grassBaseColour1Vec = io_dataBlock.inputValue( ia_grassBaseColour1, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour1 = Vec3(grassBaseColour1Vec.x, grassBaseColour1Vec.y, grassBaseColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour1Vec = io_dataBlock.inputValue( ia_grassTipColour1, & status).asFloatVector(); const Vcore::Vec3 grassTipColour1 = Vec3(grassTipColour1Vec.x, grassTipColour1Vec.y, grassTipColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassBaseColour2Vec = io_dataBlock.inputValue( ia_grassBaseColour2, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour2 = Vec3(grassBaseColour2Vec.x, grassBaseColour2Vec.y, grassBaseColour2Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour2Vec = io_dataBlock.inputValue( ia_grassTipColour2, & status).asFloatVector(); const Vcore::Vec3 grassTipColour2 = Vec3(grassTipColour2Vec.x, grassTipColour2Vec.y, grassTipColour2Vec.z); CHECK_MSTATUS( status ); char rib[4096]; sprintf( rib, "seed=%d;roughness=%f;planeHeight=%d;planeSize=%d;resolution=%d;gridSize=%d;grassMultiplier=%d;baseWidth=%f;grassSegmentLength=%f;grassNumSegments=%d;windDirectionX=%f;windDirectionY=%f;windDirectionZ=%f;grassBendAmount=%f;windSpread=%f;clock=%d;smooth=%d;grassBaseColour1X=%f;grassBaseColour1Y=%f;grassBaseColour1Z=%f;grassTipColour1X=%f;grassTipColour1Y=%f;grassTipColour1Z=%f;grassBaseColour2X=%f;grassBaseColour2Y=%f;grassBaseColour2Z=%f;grassTipColour2X=%f;grassTipColour2Y=%f;grassTipColour2Z=%f;", (int) seed, (float) roughness, (int) planeHeight, (int) planeSize, (int) rmanResolution , (int) gridSize, (int) grassMultiplier, (float) baseWidth, (float) grassSegmentLength, (int) grassNumSegments, (float) windDirection.x, (float) windDirection.y, (float) windDirection.z, (float) grassBendAmount, (float) windSpread, (int) clock, (int) smooth, (float) grassBaseColour1.x, (float) grassBaseColour1.y, (float) grassBaseColour1.z, (float) grassTipColour1.x, (float) grassTipColour1.y, (float) grassTipColour1.z, (float) grassBaseColour2.x, (float) grassBaseColour2.y, (float) grassBaseColour2.z, (float) grassTipColour2.x, (float) grassTipColour2.y, (float) grassTipColour2.z ); // We must set a value for the plug we have been asked to evaluate, // even if we are not going to use it. We set it in the data-block, // and to set it we use outputValue(). // // Here we are calculating a string value, and that value will // be used by the caller in a "rib-gen" operation - a process in // which a RIB file is generated for Renderman. // // Notice also that strings in Maya or more complicated than numbers. // We need to make a data object for the string data. MFnStringData stringDataFn; MObject stringDataObj = stringDataFn.create( rib, & status ); CHECK_MSTATUS( status ); MDataHandle ribHandle = io_dataBlock.outputValue( i_plug ); ribHandle.set( stringDataObj ); io_dataBlock.setClean( i_plug ); } else { //Shouldn't be here. return MStatus::kSuccess; } }
MStatus meshOpNode::compute( const MPlug& plug, MDataBlock& data ) // // Description: // This method computes the value of the given output plug based // on the values of the input attributes. // // Arguments: // plug - the plug to compute // data - object that provides access to the attributes for this node // { MStatus status = MS::kSuccess; MDataHandle stateData = data.outputValue( state, &status ); MCheckStatus( status, "ERROR getting state" ); // Check for the HasNoEffect/PassThrough flag on the node. // // (stateData is an enumeration standard in all depend nodes) // // (0 = Normal) // (1 = HasNoEffect/PassThrough) // (2 = Blocking) // ... // if( stateData.asShort() == 1 ) { MDataHandle inputData = data.inputValue( inMesh, &status ); MCheckStatus(status,"ERROR getting inMesh"); MDataHandle outputData = data.outputValue( outMesh, &status ); MCheckStatus(status,"ERROR getting outMesh"); // Simply redirect the inMesh to the outMesh for the PassThrough effect // outputData.set(inputData.asMesh()); } else { // Check which output attribute we have been asked to // compute. If this node doesn't know how to compute it, // we must return MS::kUnknownParameter // if (plug == outMesh) { MDataHandle inputData = data.inputValue( inMesh, &status ); MCheckStatus(status,"ERROR getting inMesh"); MDataHandle outputData = data.outputValue( outMesh, &status ); MCheckStatus(status,"ERROR getting outMesh"); // Now, we get the value of the component list and the operation // type and use it to perform the mesh operation on this mesh // MDataHandle inputIDs = data.inputValue( cpList, &status); MCheckStatus(status,"ERROR getting componentList"); MDataHandle opTypeData = data.inputValue( opType, &status); MCheckStatus(status,"ERROR getting opType"); // Copy the inMesh to the outMesh, so you can // perform operations directly on outMesh // outputData.set(inputData.asMesh()); MObject mesh = outputData.asMesh(); // Retrieve the ID list from the component list. // // Note, we use a component list to store the components // because it is more compact memory wise. (ie. comp[81:85] // is smaller than comp[81], comp[82],...,comp[85]) // MObject compList = inputIDs.data(); MFnComponentListData compListFn( compList ); // Get what operation is requested and // what type of component is expected for this operation. MeshOperation operationType = (MeshOperation) opTypeData.asShort(); MFn::Type componentType = meshOpFty::getExpectedComponentType(operationType); unsigned i; int j; MIntArray cpIds; for( i = 0; i < compListFn.length(); i++ ) { MObject comp = compListFn[i]; if( comp.apiType() == componentType ) { MFnSingleIndexedComponent siComp( comp ); for( j = 0; j < siComp.elementCount(); j++ ) cpIds.append( siComp.element(j) ); } } // Set the mesh object and component List on the factory // fmeshOpFactory.setMesh( mesh ); fmeshOpFactory.setComponentList( compList ); fmeshOpFactory.setComponentIDs( cpIds ); fmeshOpFactory.setMeshOperation( operationType ); // Now, perform the meshOp // status = fmeshOpFactory.doIt(); // Mark the output mesh as clean // outputData.setClean(); } else { status = MS::kUnknownParameter; } } return status; }
MStatus resetVtxRemapNode::compute( const MPlug& plug, MDataBlock& data ) // // Description: // This method computes the value of the given output plug based // on the values of the input attributes. // // Arguments: // plug - the plug to compute // data - object that provides access to the attributes for this node // { MStatus status = MS::kSuccess; MDataHandle stateData = data.outputValue( state, &status ); MCheckStatus( status, "ERROR getting state" ); // Check for the HasNoEffect/PassThrough flag on the node. // // (stateData is an enumeration standard in all depend nodes - stored as short) // // (0 = Normal) // (1 = HasNoEffect/PassThrough) // (2 = Blocking) // ... // if( stateData.asShort() == 1 ) { MDataHandle inputData = data.inputValue( inMesh, &status ); MCheckStatus(status,"ERROR getting inMesh"); MDataHandle outputData = data.outputValue( outMesh, &status ); MCheckStatus(status,"ERROR getting outMesh"); // Simply redirect the inMesh to the outMesh for the PassThrough effect // outputData.set(inputData.asMesh()); } else { // Check which output attribute we have been asked to // compute. If this node doesn't know how to compute it, // we must return MS::kUnknownParameter // if (plug == outMesh) { MDataHandle inputData = data.inputValue( inMesh, &status ); MCheckStatus(status,"ERROR getting inMesh"); MDataHandle outputData = data.outputValue( outMesh, &status ); MCheckStatus(status,"ERROR getting outMesh"); // Copy the inMesh to the outMesh, and now you can // perform operations in-place on the outMesh // outputData.set(inputData.asMesh()); MObject mesh = outputData.asMesh(); fresetVtxRemapFactory.setMesh( mesh ); status = fresetVtxRemapFactory.doIt(); outputData.setClean(); } else { status = MS::kUnknownParameter; } } return status; }
MStatus vixo_visImport::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat=MS::kSuccess; if(plug.array()!=vis) return MS::kSuccess; //cout<<plug.info().asChar()<<endl; int objIdx=plug.logicalIndex(); MDataHandle file_handle=data.inputValue(file); MString filename=file_handle.asString(); MDataHandle timeHandle=data.inputValue(time); int t=timeHandle.asTime().as(MTime::Unit::kFilm); if(mapObjName.count(objIdx)<=0) return MS::kSuccess; //cout<<"test"<<endl; MString objNameValue(mapObjName.find(objIdx)->second.c_str()); bool res=true; ifstream fin(filename.asChar(),ios_base::in|ios_base::binary); if(fin.fail()) { MDataHandle eleHandle=data.outputValue(plug); eleHandle.set(res); data.setClean(plug); return MS::kSuccess; } int objNum=0; fin.read((char*)&objNum,sizeof(int)); vector<struct_visBasicInfo> objIndexes(objNum); fin.read((char*)&objIndexes[0],sizeof(struct_visBasicInfo)*objNum); int fileObjIndex=-1; for(int i=0;i<objNum;i++) { MStringArray tempArr; MString tempStr(objIndexes[i].objName); tempStr.split(':',tempArr); if(tempArr[tempArr.length()-1]==objNameValue) { fileObjIndex=i; break; } } if(fileObjIndex==-1) { MDataHandle eleHandle=data.outputValue(plug); eleHandle.set(res); data.setClean(plug); fin.close(); return MS::kSuccess; } //cout<<"test1"<<endl; if(t<objIndexes[fileObjIndex].startFrame||t>objIndexes[fileObjIndex].endFrame) { fin.close(); MDataHandle eleHandle=data.outputValue(plug); eleHandle.set(res); data.setClean(plug); return MS::kSuccess; } //cout<<"test2"<<endl; fin.seekg(objIndexes[fileObjIndex].visBegin.operator+(sizeof(char)*(t-objIndexes[fileObjIndex].startFrame))); char value; fin.read((char *)&value,sizeof(char)); fin.close(); //cout<<t<<" "<<(int)value<<endl; if(value==0) res=0; MDataHandle eleHandle=data.outputValue(plug); eleHandle.set(res); data.setClean(plug); return MS::kSuccess; }
// COMPUTE ====================================== MStatus gear_percentageToU::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; // Error check if (plug != percentage) return MS::kUnknownParameter; // Curve MFnNurbsCurve crv( data.inputValue( curve ).asNurbsCurve() ); // Sliders bool in_normU = data.inputValue( normalizedU ).asBool(); double in_percentage = (double)data.inputValue( percentage ).asFloat() * .01; const unsigned in_steps = data.inputValue( steps ).asShort(); // Process // Get length MVectorArray u_subpos(in_steps); MPoint pt; MDoubleArray u_list(in_steps); for(unsigned i = 0 ; i < in_steps ; i++ ){ u_list[i] = normalizedUToU(i /(in_steps - 1.0), crv.numCVs()); crv.getPointAtParam(u_list[i], pt, MSpace::kWorld); u_subpos[i] = MVector(pt); } double t_length = 0; MDoubleArray dist(in_steps); MVector v; for (unsigned i = 0; i < in_steps ; i++){ if (i>0){ v = u_subpos[i] - u_subpos[i-1]; t_length += v.length(); dist[i] = t_length; } } MDoubleArray u_perc(in_steps); for (unsigned i = 0; i < in_steps ; i++){ u_perc[i] = dist[i] / t_length; } // Get closest indices unsigned index = findClosestInArray(in_percentage, u_perc); unsigned indexA, indexB; if (in_percentage <= u_perc[index]){ indexA = abs(int(index)); indexB = index; if ( indexA > indexB){ indexA = indexB; indexB = indexA+1; } } else { indexA = index; indexB = index + 1; } // blend value double blend = set01range(in_percentage, u_perc[indexA], u_perc[indexB]); double out_u = linearInterpolate(u_list[indexA], u_list[indexB], blend); if (in_normU) out_u = uToNormalizedU(out_u, crv.numCVs()); // Ouput MDataHandle h = data.outputValue( u ); h.setDouble( out_u ); data.setClean( plug ); return MS::kSuccess; }
MStatus MG_poseReader::compute(const MPlug& plug,MDataBlock& dataBlock) { MMatrix poseM = dataBlock.inputValue(poseMatrix).asMatrix(); MMatrix readerM = dataBlock.inputValue(readerMatrix).asMatrix(); // aim axis value //0 =x //1 =y //2 =z int axis = dataBlock.inputValue(aimAxis).asInt(); MVector poseAimV; if (axis==0) { poseAimV.x=poseM[0][0]; poseAimV.y=poseM[0][1]; poseAimV.z=poseM[0][2]; } else if (axis==1) { poseAimV.x=poseM[1][0]; poseAimV.y=poseM[1][1]; poseAimV.z=poseM[1][2]; }else { poseAimV.x=poseM[2][0]; poseAimV.y=poseM[2][1]; poseAimV.z=poseM[2][2]; } MVector x (readerM[0][0],readerM[0][1],readerM[0][2]); MVector y (readerM[1][0],readerM[1][1],readerM[1][2]); MVector z (readerM[2][0],readerM[2][1],readerM[2][2]); double porjX =projVector (poseAimV,x); double porjXNeg =projVector (poseAimV,x*-1); double porjY =projVector (poseAimV,y); double porjYNeg =projVector (poseAimV,y*-1); double porjZ =projVector (poseAimV,z); double porjZNeg =projVector (poseAimV,z*-1); dataBlock.outputValue(xPositive).set(porjX); dataBlock.outputValue(xPositive).setClean(); dataBlock.outputValue(xNegative).set(porjXNeg); dataBlock.outputValue(xNegative).setClean(); dataBlock.outputValue(yPositive).set(porjY); dataBlock.outputValue(yPositive).setClean(); dataBlock.outputValue(yNegative).set(porjYNeg); dataBlock.outputValue(yNegative).setClean(); dataBlock.outputValue(zPositive).set(porjZ); dataBlock.outputValue(zPositive).setClean(); dataBlock.outputValue(zNegative).set(porjZNeg); dataBlock.outputValue(zNegative).setClean(); return MS::kSuccess; }
void rigidBodyNode::computeWorldMatrix(const MPlug& plug, MDataBlock& data) { if (!m_rigid_body) return; // std::cout << "rigidBodyNode::computeWorldMatrix" << std::endl; MObject thisObject(thisMObject()); MFnDagNode fnDagNode(thisObject); MObject update; MPlug(thisObject, ca_rigidBody).getValue(update); MPlug(thisObject, ca_rigidBodyParam).getValue(update); vec3f pos; quatf rot; MStatus status; MFnTransform fnParentTransform(fnDagNode.parent(0, &status)); double mscale[3]; fnParentTransform.getScale(mscale); m_rigid_body->get_transform(pos, rot); if(dSolverNode::isStartTime) { // allow to edit ptranslation and rotation MVector mtranslation = fnParentTransform.getTranslation(MSpace::kTransform, &status); MQuaternion mrotation; fnParentTransform.getRotation(mrotation, MSpace::kTransform); float deltaPX = (float)mtranslation.x - pos[0]; float deltaPY = (float)mtranslation.y - pos[1]; float deltaPZ = (float)mtranslation.z - pos[2]; float deltaRX = (float)mrotation.x - rot[1]; float deltaRY = (float)mrotation.y - rot[2]; float deltaRZ = (float)mrotation.z - rot[3]; float deltaRW = (float)mrotation.w - rot[0]; float deltaSq = deltaPX * deltaPX + deltaPY * deltaPY + deltaPZ * deltaPZ + deltaRX * deltaRX + deltaRY * deltaRY + deltaRZ * deltaRZ + deltaRW * deltaRW; if(deltaSq > FLT_EPSILON) { m_rigid_body->set_transform(vec3f((float)mtranslation.x, (float)mtranslation.y, (float)mtranslation.z), quatf((float)mrotation.w, (float)mrotation.x, (float)mrotation.y, (float)mrotation.z)); m_rigid_body->set_interpolation_transform(vec3f((float)mtranslation.x, (float)mtranslation.y, (float)mtranslation.z), quatf((float)mrotation.w, (float)mrotation.x, (float)mrotation.y, (float)mrotation.z)); m_rigid_body->update_constraint(); MDataHandle hInitPos = data.outputValue(ia_initialPosition); float3 &ihpos = hInitPos.asFloat3(); ihpos[0] = (float)mtranslation.x; ihpos[1] = (float)mtranslation.y; ihpos[2] = (float)mtranslation.z; MDataHandle hInitRot = data.outputValue(ia_initialRotation); float3 &ihrot = hInitRot.asFloat3(); MEulerRotation newrot(mrotation.asEulerRotation()); ihrot[0] = rad2deg((float)newrot.x); ihrot[1] = rad2deg((float)newrot.y); ihrot[2] = rad2deg((float)newrot.z); } } else { // if not start time, lock position and rotation for active rigid bodies float mass = 0.f; MPlug(thisObject, rigidBodyNode::ia_mass).getValue(mass); if(mass > 0.f) { fnParentTransform.setTranslation(MVector(pos[0], pos[1], pos[2]), MSpace::kTransform); fnParentTransform.setRotation(MQuaternion(rot[1], rot[2], rot[3], rot[0])); } } float mass = 0.f; MPlug(thisObject, rigidBodyNode::ia_mass).getValue(mass); float curMass = m_rigid_body->get_mass(); bool changedMassStatus= false; if ((curMass > 0.f) != (mass > 0.f)) { changedMassStatus = true; } if (changedMassStatus) solver_t::remove_rigid_body(m_rigid_body); m_rigid_body->set_mass(mass); m_rigid_body->set_inertia((float)mass * m_rigid_body->collision_shape()->local_inertia()); if (changedMassStatus) solver_t::remove_rigid_body(m_rigid_body); float restitution = 0.f; MPlug(thisObject, rigidBodyNode::ia_restitution).getValue(restitution); m_rigid_body->set_restitution(restitution); float friction = 0.5f; MPlug(thisObject, rigidBodyNode::ia_friction).getValue(friction); m_rigid_body->set_friction(friction); float linDamp = 0.f; MPlug(thisObject, rigidBodyNode::ia_linearDamping).getValue(linDamp); m_rigid_body->set_linear_damping(linDamp); float angDamp = 0.f; MPlug(thisObject, rigidBodyNode::ia_angularDamping).getValue(angDamp); m_rigid_body->set_angular_damping(angDamp); data.setClean(plug); //set the scale to the collision shape m_rigid_body->collision_shape()->set_scale(vec3f((float)mscale[0], (float)mscale[1], (float)mscale[2])); }
MStatus sseDeformer::compute(const MPlug& plug, MDataBlock& data) { MStatus status; if (plug.attribute() != outputGeom) { printf("Ignoring requested plug\n"); return status; } unsigned int index = plug.logicalIndex(); MObject thisNode = this->thisMObject(); // get input value MPlug inPlug(thisNode,input); inPlug.selectAncestorLogicalIndex(index,input); MDataHandle hInput = data.inputValue(inPlug, &status); MCheckStatus(status, "ERROR getting input mesh\n"); // get the input geometry MDataHandle inputData = hInput.child(inputGeom); if (inputData.type() != MFnData::kMesh) { printf("Incorrect input geometry type\n"); return MStatus::kFailure; } MObject iSurf = inputData.asMesh() ; MFnMesh inMesh; inMesh.setObject( iSurf ) ; MDataHandle outputData = data.outputValue(plug); outputData.copy(inputData); if (outputData.type() != MFnData::kMesh) { printf("Incorrect output mesh type\n"); return MStatus::kFailure; } MObject oSurf = outputData.asMesh() ; if(oSurf.isNull()) { printf("Output surface is NULL\n"); return MStatus::kFailure; } MFnMesh outMesh; outMesh.setObject( oSurf ) ; MCheckStatus(status, "ERROR setting points\n"); // get all points at once for demo purposes. Really should get points from the current group using iterator MFloatPointArray pts; outMesh.getPoints(pts); int nPoints = pts.length(); MDataHandle envData = data.inputValue(envelope, &status); float env = envData.asFloat(); MDataHandle sseData = data.inputValue(sseEnabled, &status); bool sseEnabled = (bool) sseData.asBool(); // NOTE: Using MTimer and possibly other classes disables // autovectorization with Intel <=10.1 compiler on OSX and Linux!! // Must compile this function with -fno-exceptions on OSX and // Linux to guarantee autovectorization is done. Use -fvec_report2 // to check for vectorization status messages with Intel compiler. MTimer timer; timer.beginTimer(); if(sseEnabled) { // Innter loop will autovectorize. Around 3x faster than the // loop below it. It would be faster if first element was // guaranteed to be aligned on 16 byte boundary. for(int i=0; i<nPoints; i++) { float* ptPtr = &pts[i].x; for(int j=0; j<4; j++) { ptPtr[j] = env * (cosf(ptPtr[j]) * sinf(ptPtr[j]) * tanf(ptPtr[j])); } } } else { // This inner loop will not autovectorize. for(int i=0; i<nPoints; i++) { MFloatPoint& pt = pts[i]; for(int j=0; j<3; j++) { pt[j] = env * (cosf(pt[j]) * sinf(pt[j]) * tanf(pt[j])); } } } timer.endTimer(); if(sseEnabled) { printf("SSE enabled, runtime %f\n", timer.elapsedTime()); } else { printf("SSE disabled, runtime %f\n", timer.elapsedTime()); } outMesh.setPoints(pts); return status; }
// // Calls applyRotationLocks && applyRotationLimits // This method verifies that the passed value can be set on the // rotate plugs. In the base class, limits as well as locking are // checked by this method. // // The compute, validateAndSetValue, and rotateTo functions // all use this method. // MStatus rockingTransformCheckNode::checkAndSetRotation(MDataBlock &block, const MPlug& plug, const MEulerRotation& newRotation, MSpace::Space space ) { const MDGContext context = block.context(); updateMatrixAttrs(context); MStatus status = MS::kSuccess; MEulerRotation outRotation = newRotation; if (context.isNormal()) { // For easy reading. // MPxTransformationMatrix *xformMat = baseTransformationMatrix; // Get the current translation in transform space for // clamping and locking. // MEulerRotation savedRotation = xformMat->eulerRotation(MSpace::kTransform, &status); ReturnOnError(status); // Translate to transform space, since the limit test needs the // values in transform space. The locking test needs the values // in the same space as the savedR value - which is transform // space as well. // status = baseTransformationMatrix->rotateTo(newRotation, space); ReturnOnError(status); outRotation = xformMat->eulerRotation(MSpace::kTransform, &status); ReturnOnError(status); // Now that everything is in the same space, apply limits // and change the value to adhere to plug locking. // outRotation = applyRotationLimits(outRotation, block, &status); ReturnOnError(status); outRotation = applyRotationLocks(outRotation, savedRotation, &status); ReturnOnError(status); // The value that remain is in transform space. // status = xformMat->rotateTo(outRotation, MSpace::kTransform); ReturnOnError(status); // Get the value that was just set. It needs to be in transform // space since it is used to set the datablock values at the // end of this method. Getting the vaolue right before setting // ensures that the transformation matrix and data block will // be synchronized. // outRotation = xformMat->eulerRotation(MSpace::kTransform, &status); ReturnOnError(status); } else { // Get the rotation for clamping and locking. This will get the // rotate value in transform space. // double3 &s3 = block.inputValue(rotate).asDouble3(); MEulerRotation savedRotation(s3[0], s3[1], s3[2]); // Create a local transformation matrix for non-normal context // calculations. // MPxTransformationMatrix *local = createTransformationMatrix(); if (NULL == local) { MGlobal::displayError("rockingTransformCheck::checkAndSetRotation internal error"); return status; } // Fill the newly created transformation matrix. // status = computeLocalTransformation(local, block); if ( MS::kSuccess != status) { delete local; return status; } // Translate the values to transform space. This will allow the // limit and locking tests to work properly. // status = local->rotateTo(newRotation, space); if ( MS::kSuccess != status) { delete local; return status; } outRotation = local->eulerRotation(MSpace::kTransform, &status); if ( MS::kSuccess != status) { delete local; return status; } // Apply limits // outRotation = applyRotationLimits(outRotation, block, &status); if ( MS::kSuccess != status) { delete local; return status; } outRotation = applyRotationLocks(outRotation, savedRotation, &status); if ( MS::kSuccess != status) { delete local; return status; } status = local->rotateTo(outRotation, MSpace::kTransform); if ( MS::kSuccess != status) { delete local; return status; } // Get the rotate value in transform space for placement in the // datablock. // outRotation = local->eulerRotation(MSpace::kTransform, &status); if ( MS::kSuccess != status) { delete local; return status; } delete local; } MDataHandle handle = block.outputValue(plug, &status); if ( MS::kSuccess != status) { return status; } if (plug == rotate) { handle.set(outRotation.x, outRotation.y, outRotation.z); } else if (plug == rotateX) { handle.set(outRotation.x); } else if (plug == rotateY) { handle.set(outRotation.y); } else { handle.set(outRotation.z); } return status; }
MStatus testNpassiveNode::compute(const MPlug &plug, MDataBlock &data) { MStatus stat; if ( plug == currentState ) { // get old positions and numVerts // if num verts is different, reset topo and zero velocity // if num verts is the same, compute new velocity int ii,jj; // initialize MnCloth MObject inMeshObj = data.inputValue(inputGeom).asMesh(); MFnMesh inputMesh(inMeshObj); unsigned int numVerts = 0; numVerts = inputMesh.numVertices(); unsigned int prevNumVerts; fNObject.getNumVertices(prevNumVerts); if(numVerts != prevNumVerts) { int numPolygons = inputMesh.numPolygons(); int * faceVertCounts = new int[numPolygons]; int facesArrayLength = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); faceVertCounts[ii] = verts.length(); facesArrayLength += verts.length(); } int * faces = new int[facesArrayLength]; int currIndex = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); for(jj=0;jj<(int)verts.length();jj++) { faces[currIndex++] = verts[jj]; } } int numEdges = inputMesh.numEdges(); int * edges = new int[2*numEdges]; currIndex = 0; for(ii=0;ii<numEdges;ii++) { int2 edge; inputMesh.getEdgeVertices(ii,edge); edges[currIndex++] = edge[0]; edges[currIndex++] = edge[1]; } // When you are doing the initialization, the first call must to be setTopology(). All other // calls must come after this. fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges ); delete[] faceVertCounts; delete[] faces; delete[] edges; MFloatPointArray vertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.setPositions(vertexArray,true); MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = 0.0f; velocitiesArray[ii].y = 0.0f; velocitiesArray[ii].z = 0.0f; velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); } else { MFloatPointArray vertexArray; MFloatPointArray prevVertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.getPositions(prevVertexArray); // you may want to get the playback rate for the dt // double dt = MAnimControl::playbackBy() \ 24.0; // or get the real dt by caching the last eval time double dt = 1.0/24.0; MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = (float)( (vertexArray[ii].x - prevVertexArray[ii].x)/dt); velocitiesArray[ii].y = (float)( (vertexArray[ii].y - prevVertexArray[ii].y)/dt); velocitiesArray[ii].z = (float)( (vertexArray[ii].x - prevVertexArray[ii].z)/dt); velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); fNObject.setPositions(vertexArray,true); } // in real life, you'd get these attribute values each frame and set them fNObject.setThickness(0.1f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setCollisionFlags(true, true, true); MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle currStateOutputHandle = data.outputValue(currentState); currStateOutputHandle.set(outputData.object()); } if ( plug == startState ) { int ii,jj; // initialize MnCloth MObject inMeshObj = data.inputValue(inputGeom).asMesh(); MFnMesh inputMesh(inMeshObj); int numPolygons = inputMesh.numPolygons(); int * faceVertCounts = new int[numPolygons]; int facesArrayLength = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); faceVertCounts[ii] = verts.length(); facesArrayLength += verts.length(); } int * faces = new int[facesArrayLength]; int currIndex = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); for(jj=0;jj<(int)verts.length();jj++) { faces[currIndex++] = verts[jj]; } } int numEdges = inputMesh.numEdges(); int * edges = new int[2*numEdges]; currIndex = 0; for(ii=0;ii<numEdges;ii++) { int2 edge; inputMesh.getEdgeVertices(ii,edge); edges[currIndex++] = edge[0]; edges[currIndex++] = edge[1]; } // When you are doing the initialization, the first call must to be setTopology(). All other // calls must come after this. fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges ); delete[] faceVertCounts; delete[] faces; delete[] edges; unsigned int numVerts = 0; numVerts = inputMesh.numVertices(); MFloatPointArray vertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.setPositions(vertexArray,true); MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = 0.0f; velocitiesArray[ii].y = 0.0f; velocitiesArray[ii].z = 0.0f; velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); fNObject.setThickness(0.1f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setCollisionFlags(true, true, true); MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle startStateOutputHandle = data.outputValue(startState); startStateOutputHandle.set(outputData.object()); } else { stat = MS::kUnknownParameter; } return stat; }
// // 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 PtexUVNode::compute( const MPlug &plug, MDataBlock &data ) { MStatus stat; bool hasNoEffect = false; MDataHandle inMeshHnd = data.inputValue( inMesh ); MDataHandle outMeshHnd = data.outputValue( outMesh ); MDataHandle stateHnd = data.inputValue( state ); int state = stateHnd.asInt(); if( state == 1 ) // No Effect/Pass through hasNoEffect = true; if( !hasNoEffect && plug == outMesh ) { MObject inMeshData = inMeshHnd.asMesh(); if( !hasNoEffect ) { MFnMeshData meshDataFn; MObject newMeshData = meshDataFn.create(); MFnMesh inMeshFn( inMeshData ); inMeshFn.copy( inMeshData, newMeshData ); MFnMesh meshFn( newMeshData ); MPointArray pts; meshFn.getPoints( pts ); MStringArray uvSetNames; meshFn.getUVSetNames( uvSetNames ); unsigned int defaultUvSetCount = (unsigned int)uvSetNames.length(); int num_faces = meshFn.numPolygons(); MIntArray uvCounts; uvCounts.setLength( num_faces ); for ( int i_f = 0; i_f < num_faces; i_f++ ) { int deg = meshFn.polygonVertexCount( i_f ); uvCounts[ i_f ] = deg; if ( deg != 4 ) { return MS::kFailure; } } MIntArray uvIds; uvIds.setLength( 4 * num_faces ); if ( defaultUvSetCount == 1 ) { int currentUVCount = meshFn.numUVs( uvSetNames[0] ); MFloatArray us, vs; us.setLength( 4 * num_faces ); vs.setLength( 4 * num_faces ); for ( int i_f = 0; i_f < num_faces; i_f++ ) { float f = (float)i_f; uvIds[ 4 * i_f + 0 ] = 4 * i_f + 0; uvIds[ 4 * i_f + 1 ] = 4 * i_f + 1; uvIds[ 4 * i_f + 2 ] = 4 * i_f + 2; uvIds[ 4 * i_f + 3 ] = 4 * i_f + 3; us[ 4 * i_f + 0 ] = (float)i_f; vs[ 4 * i_f + 0 ] = 0.0f; us[ 4 * i_f + 1 ] = (float)i_f + 1.0f; vs[ 4 * i_f + 1 ] = 0.0f; us[ 4 * i_f + 2 ] = (float)i_f + 1.0f; vs[ 4 * i_f + 2 ] = 1.0f; us[ 4 * i_f + 3 ] = (float)i_f; vs[ 4 * i_f + 3 ] = 1.0f; } stat = meshFn.setUVs( us, vs, &uvSetNames[0] ); stat = meshFn.assignUVs( uvCounts, uvIds, &uvSetNames[0] ); } meshFn.updateSurface(); meshFn.syncObject(); outMeshHnd.set( newMeshData ); } } else return MS::kUnknownParameter; if( hasNoEffect ) outMeshHnd.set( inMeshHnd.asMesh() ); data.setClean( plug ); return stat; }
MStatus latticeNoiseNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; float noiseAmplitude; float noiseFreq; if( plug == output ) { // Get the lattice data from the input attribute. First get the // data object, and then use the lattice data function set to extract // the actual lattice. // // Get the data handle // MDataHandle inputData = data.inputValue( input, &returnStatus ); McheckErr( returnStatus, "ERROR getting lattice data handle\n" ); // Get the data object // MObject latticeData = inputData.data(); MFnLatticeData dataFn( latticeData ); // Get the actual geometry // MObject lattice = dataFn.lattice(); MFnLattice lattFn( lattice, &returnStatus ); McheckErr( returnStatus, "ERROR getting lattice geometry\n" ); // Do the same for the output lattice // MDataHandle outputData = data.outputValue( output, &returnStatus ); McheckErr( returnStatus, "ERROR getting lattice data handle\n" ); // Get the data object // latticeData = outputData.data(); if ( latticeData.isNull() ) { // The data object for this attribute has not been created yet, so // we'll create it // latticeData = dataFn.create(); } else { // Use the data object that is already there // dataFn.setObject( latticeData ); } // Get the actual geometry // MObject outLattice = dataFn.lattice(); MFnLattice outLattFn( outLattice, &returnStatus ); McheckErr( returnStatus, "ERROR getting lattice geometry\n" ); // Get the amplitude and frequency // MDataHandle ampData = data.inputValue( amplitude, &returnStatus ); McheckErr( returnStatus, "ERROR getting amplitude\n" ); noiseAmplitude = ampData.asFloat(); MDataHandle freqData = data.inputValue( frequency, &returnStatus ); McheckErr( returnStatus, "ERROR getting frequency\n" ); noiseFreq = freqData.asFloat(); // Get the time. // MDataHandle timeData = data.inputValue( time, &returnStatus ); McheckErr( returnStatus, "ERROR getting time data handle\n" ); MTime time = timeData.asTime(); float seconds = (float)time.as( MTime::kSeconds ); // Easiest way to modify frequency is by modifying the time // seconds = seconds * noiseFreq; // We have the information we need now. We'll apply noise to the // points upon the lattice // unsigned s, t, u; lattFn.getDivisions( s, t, u ); // match up the divisions in the lattices // outLattFn.setDivisions( s, t, u ); for ( unsigned i = 0; i < s; i++ ) { for ( unsigned j = 0; j < t; j++ ) { for ( unsigned k = 0; k < u; k++ ) { MPoint & point = lattFn.point( i, j, k ); MPoint & outPoint = outLattFn.point( i, j, k ); pnt noisePnt = noise::atPointAndTime( (float)point.x, (float)point.y, (float)point.z, seconds ); // Make noise between -1 and 1 instead of 0 and 1 // noisePnt.x = ( noisePnt.x * 2.0F ) - 1.0F; noisePnt.y = ( noisePnt.y * 2.0F ) - 1.0F; noisePnt.z = ( noisePnt.z * 2.0F ) - 1.0F; outPoint.x = point.x + ( noisePnt.x * noiseAmplitude ); outPoint.y = point.y + ( noisePnt.y * noiseAmplitude ); outPoint.z = point.z + ( noisePnt.z * noiseAmplitude ); } } } outputData.set( latticeData ); data.setClean(plug); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus AlembicCurvesDeformNode::deform(MDataBlock &dataBlock, MItGeometry &iter, const MMatrix &localToWorld, unsigned int geomIndex) { // get the envelope data float env = dataBlock.inputValue(envelope).asFloat(); if (env == 0.0f) { // deformer turned off return MStatus::kSuccess; } // update the frame number to be imported double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } AbcG::ICurves obj(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mSchema = obj.getSchema(); } if (!mSchema.valid()) { return MStatus::kFailure; } { ESS_PROFILE_SCOPE("AlembicCurvesDeformNode::deform readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (sampleInfo.alpha != 0.0) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2; if (sampleInfo.alpha != 0.0) { samplePos2 = sample2.getPositions(); } // iteration should not be necessary. the iteration is only // required if the same mesh is attached to the same deformer // several times float blend = (float)sampleInfo.alpha; float iblend = 1.0f - blend; unsigned int index = 0; for (iter.reset(); !iter.isDone(); iter.next()) { index = iter.index(); // MFloatPoint pt = iter.position(); MPoint pt = iter.position(); MPoint abcPos = pt; float weight = weightValue(dataBlock, geomIndex, index) * env; if (weight == 0.0f) { continue; } float iweight = 1.0f - weight; if (index >= samplePos->size()) { continue; } bool done = false; if (sampleInfo.alpha != 0.0) { if (samplePos2->size() == samplePos->size()) { abcPos.x = iweight * pt.x + weight * (samplePos->get()[index].x * iblend + samplePos2->get()[index].x * blend); abcPos.y = iweight * pt.y + weight * (samplePos->get()[index].y * iblend + samplePos2->get()[index].y * blend); abcPos.z = iweight * pt.z + weight * (samplePos->get()[index].z * iblend + samplePos2->get()[index].z * blend); done = true; } } if (!done) { abcPos.x = iweight * pt.x + weight * samplePos->get()[index].x; abcPos.y = iweight * pt.y + weight * samplePos->get()[index].y; abcPos.z = iweight * pt.z + weight * samplePos->get()[index].z; } iter.setPosition(abcPos); } return MStatus::kSuccess; }
// The compute() method does the actual work of the node using the inputs // of the node to generate its output. // // 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 CXRayMtl::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 == aOutColorR || plug == aOutColorG || plug == aOutColorB || plug == aOutTransparency || plug == aOutTransR || plug == aOutTransG || plug == aOutTransB ) { 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 == aOutColorR || plug == aOutColorG || plug == aOutColorB) { // 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 == aOutTransR || plug == aOutTransG || plug == aOutTransB ) { 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 vixo_hairStyleMaya::compute(const MPlug& plug, MDataBlock& data) { if(plug==printBasicInfo) { if(data.inputValue(hairNum).asInt()==0) { return MS::kSuccess; } if(data.inputValue(inMesh).asMesh().hasFn(MFn::kMesh)==false) { return MS::kSuccess; } if(data.inputValue(hairInfoColorDir).asString()=="") { return MS::kSuccess; } MString hairInfoDirValue=data.inputValue(hairInfoColorDir).asString(); int hairNumValue=data.inputValue(hairNum).asInt(); //cout<<"hair"<<hairNumValue<<endl; MString follicleFileName=hairInfoDirValue+"/hairRoot.info"; MString uvFileName=hairInfoDirValue+"/uv.info"; exportFollicle(hairNumValue,uvFileName,follicleFileName,data); data.outputValue(printBasicInfo).setClean(); return MS::kSuccess; } if(plug==printColorInfo) { if(data.inputValue(refreshColorInfo).asBool()==false) return MS::kSuccess; MString hairInfoDirValue=data.inputValue(hairInfoColorDir).asString(); MString uvFileName=hairInfoDirValue+"/uv.info"; fstream fileExist(uvFileName.asChar(),ios_base::in|ios_base::binary); if(!fileExist) { data.outputValue(refreshColorInfo).set(false); return MS::kSuccess; } MString colorInfoFileName=hairInfoDirValue+"/hairColor.info"; exportColor(uvFileName,colorInfoFileName,data); data.outputValue(refreshColorInfo).set(false); data.outputValue(printColorInfo).setClean(); return MS::kSuccess; } if(plug==printStyleInfo) { if(data.inputValue(refreshStyleInfo).asBool()==false) return MS::kSuccess; //follicleδµ¼³ö MString hairInfoColorDirValue=data.inputValue(hairInfoColorDir).asString(); MString hairInfoStyleDirValue=data.inputValue(hairInfoStyleDir).asString(); if(hairInfoStyleDirValue=="") { data.outputValue(refreshStyleInfo).set(false); return MS::kSuccess; } MString uvFileName=hairInfoColorDirValue+"/uv.info"; fstream fileExist(uvFileName.asChar(),ios_base::in|ios_base::binary); if(!fileExist) return MS::kSuccess; MString noiseInfoFileName=hairInfoStyleDirValue+"/hairStyle.info"; exportNoise(uvFileName,noiseInfoFileName,data); data.outputValue(refreshStyleInfo).set(false); data.outputValue(printStyleInfo).setClean(); return MS::kSuccess; } return MS::kSuccess; }
MStatus dgTransform::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hTranslate = data.inputValue( aTranslate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hRotate = data.inputValue( aRotate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hScale = data.inputValue( aScale, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hShear = data.inputValue( aShear, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hJointOrient = data.inputValue( aJointOrient, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputTranslate = data.inputValue( aInputTranslate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputRotate = data.inputValue( aInputRotate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputScale = data.inputValue( aInputScale, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputShear = data.inputValue( aInputShear, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MPxTransformationMatrix inputMpxTrMtx; MEulerRotation inputEulerRot( hInputRotate.asVector() ); inputMpxTrMtx.translateTo( hInputTranslate.asVector() ); inputMpxTrMtx.rotateTo( inputEulerRot ); inputMpxTrMtx.scaleTo( hInputScale.asVector() ); inputMpxTrMtx.shearTo( hInputShear.asVector() ); MMatrix parentMatrix = inputMpxTrMtx.asMatrix(); MPxTransformationMatrix mpxTrMtx; MEulerRotation eulerRot( hRotate.asVector() ); MEulerRotation joEulerRot( hJointOrient.asVector() ); mpxTrMtx.translateTo( hTranslate.asVector() ); mpxTrMtx.rotateTo( eulerRot ); mpxTrMtx.rotateBy( joEulerRot ); mpxTrMtx.scaleTo( hScale.asVector() ); mpxTrMtx.shearTo( hShear.asVector() ); if( plug == aMatrix ) { //cout <<"matrix"<<endl; MDataHandle hMatrix = data.outputValue( aMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hMatrix.setMMatrix( mpxTrMtx.asMatrix() ); } if( plug == aInverseMatrix ) { //cout <<"inverseMatrix"<<endl; MDataHandle hInverseMatrix = data.outputValue( aInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hInverseMatrix.setMMatrix( mpxTrMtx.asMatrix().inverse() ); } if( plug == aWorldMatrix || plug == aWorldInverseMatrix ) { MMatrix worldMatrix = mpxTrMtx.asMatrix()*parentMatrix; if( plug == aWorldMatrix ) { //cout <<"worldMatrix"<<endl; MDataHandle hWorldMatrix = data.outputValue( aWorldMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hWorldMatrix.setMMatrix( worldMatrix ); } if( plug == aWorldInverseMatrix ) { //cout <<"worldInverseMatrix"<<endl; MDataHandle hWorldInverseMatrix = data.outputValue( aWorldInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hWorldInverseMatrix.setMMatrix( worldMatrix.inverse() ); } } if( plug == aParentMatrix ) { //cout <<"parentMatrix"<<endl; MDataHandle hParentMatrix = data.outputValue( aParentMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hParentMatrix.setMMatrix( parentMatrix ); } if( plug == aParentInverseMatrix ) { //cout <<"parentInverseMatrix"<<endl; MDataHandle hParentInverseMatrix = data.outputValue( aParentInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hParentInverseMatrix.setMMatrix( parentMatrix.inverse() ); } data.setClean( plug ); return status; }
// // A very simple implementation of validAndSetValue(). No lock // or limit checking on the rocking attribute is done in this method. // If you wish to apply locks and limits to the rocking attribute, you // would follow the approach taken in the rockingTransformCheck example. // Meaning you would implement methods similar to: // * applyRotationLocks(); // * applyRotationLimits(); // * checkAndSetRotation(); // but for the rocking attribute. The method checkAndSetRotation() // would be called below rather than updating the rocking attribute // directly. // MStatus rockingTransformNode::validateAndSetValue(const MPlug& plug, const MDataHandle& handle, const MDGContext& context) { MStatus status = MS::kSuccess; // Make sure that there is something interesting to process. // if (plug.isNull()) return MS::kFailure; MDataBlock block = forceCache(*(MDGContext *)&context); MDataHandle blockHandle = block.outputValue(plug, &status); ReturnOnError(status); MString cachename = block.inputValue( acachename ).asString(); MString meshname = block.inputValue( ameshname ).asString(); /* if ( plug == aRockInX ) { // Update our new rock in x value double rockInX = handle.asDouble(); blockHandle.set(rockInX); rockXValue = rockInX; // Update the custom transformation matrix to the // right rock value. rockingTransformMatrix *ltm = getRockingTransformMatrix(); if (ltm) ltm->setRockInX(rockXValue); else MGlobal::displayError("Failed to get rock transform matrix"); blockHandle.setClean(); // Mark the matrix as dirty so that DG information // will update. dirtyMatrix(); } */ if ( plug == aframe ) { // Update our new rock in x value double rockInX = handle.asDouble(); blockHandle.set(rockInX); rockXValue = rockInX; // Update the custom transformation matrix to the // right rock value. rockingTransformMatrix *ltm = getRockingTransformMatrix(); if (ltm) ltm->setRockInX(rockXValue, cachename, meshname); else MGlobal::displayError("Failed to get rock transform matrix"); blockHandle.setClean(); // Mark the matrix as dirty so that DG information // will update. dirtyMatrix(); } // Allow processing for other attributes return ParentClass::validateAndSetValue(plug, handle, context); }
/*! Compute function, gets the input surface, determines what type it is and calls the appropriate conversion function Encapsulates an cowpointer to the body into the naiadBodyData type and outputs it */ MStatus NBuddySurfaceToBodyNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if (plug == _outBody) { //Get the body name MDataHandle bodyNameHndl = data.inputValue( _bodyName, &status ); MString bodyName = bodyNameHndl.asString(); //Create the MFnPluginData for the naiadBody MFnPluginData dataFn; dataFn.create( MTypeId( naiadBodyData::id ), &status); NM_CheckMStatus( status, "Failed to create naiadBodyData in MFnPluginData"); //Get subdivision info from plugs so better approximations of meshes can be done int divisions = data.inputValue( _subDivide, &status ).asBool(); //Getting genericAttribute handle containing the surface and pick the correct conversion function MObject meshObj; MDataHandle inSurfaceHdl = data.inputValue( _inSurface, &status ); if (inSurfaceHdl.type() == MFnData::kNurbsSurface) { MFnNurbsSurface nurbsFn(inSurfaceHdl.asNurbsSurface()); // Create the data holder for the tesselated mesh MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); //Setup the tesselation parameters MTesselationParams tParams; tParams.setOutputType( MTesselationParams::kTriangles ); tParams.setFormatType( MTesselationParams::kGeneralFormat ); tParams.setUIsoparmType( MTesselationParams::kSpanEquiSpaced ); tParams.setVIsoparmType( MTesselationParams::kSpanEquiSpaced ); tParams.setUNumber( divisions+1 ); tParams.setVNumber( divisions+1 ); // Tesselate and get the returned mesh meshObj = nurbsFn.tesselate( tParams, newOutputData, &status ); NM_CheckMStatus( status, "NBuddySurfaceToBodyNode::compute Failed to tesselate nurbs surface to poly"); } else if (inSurfaceHdl.type() == MFnData::kMesh) { meshObj = inSurfaceHdl.asMesh(); if ( divisions > 0 ) { MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); MFnMesh meshFn(meshObj); MIntArray faceIds; for ( unsigned int i(0); i < meshFn.numPolygons(); ++i ) faceIds.append(i); meshFn.subdivideFaces( faceIds , divisions ); } } else if (inSurfaceHdl.type() == MFnData::kSubdSurface) { // Create the subd function set so we can tesselate MFnSubd subDfn(inSurfaceHdl.asSubdSurface()); // Create the data holder for the tesselated mesh MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); // Tesselate the subD surface meshObj = subDfn.tesselate(true, 1 , divisions , newOutputData, &status ); NM_CheckMStatus( status, "NBuddySurfaceToBodyNode::compute Failed to tesselate SubD surface to poly"); } else return status ; //Get the handle for the input transform MDataHandle inTransformHdl = data.inputValue( _inTransform, &status ); NM_CheckMStatus( status, "Failed to get inTransform handle"); MDataHandle useTransformHdl = data.inputValue( _useTransform, &status); NM_CheckMStatus( status, "Failed to get worldSpaceHdl "); bool useTransform = useTransformHdl.asBool(); //Get a new naiadBodyData naiadBodyData * newBodyData = (naiadBodyData*)dataFn.data( &status ); NM_CheckMStatus( status, "Failed to get naiadBodyData handle from MFnPluginData"); try { newBodyData->nBody = mayaMeshToNaiadBody( meshObj, std::string(bodyName.asChar()), useTransform, inTransformHdl.asMatrix() ); } catch(std::exception& ex) { NM_ExceptionPlugDisplayError("NBuddySurfaceToBodyNode::compute ", plug, ex ); } //Give the data to the output handle and set it clean MDataHandle bodyDataHnd = data.outputValue( _outBody, &status ); NM_CheckMStatus( status, "Failed to get outputData handle for outBody"); bodyDataHnd.set( newBodyData ); data.setClean( plug ); } return status; }