/* virtual */ bool wingVizNode::setInternalValueInContext( const MPlug& plug, const MDataHandle& handle, MDGContext&) { bool handledAttribute = false; if (plug == acachename) { handledAttribute = true; m_cachename = (MString) handle.asString(); } else if(plug == aratio) { handledAttribute = true; m_scale = handle.asFloat(); } else if(plug == awind) { handledAttribute = true; m_wind = handle.asFloat(); } return handledAttribute; }
MStatus blendTwoMatrixDecompose::compute( const MPlug& plug, MDataBlock& block ) { MStatus stat; MDataHandle hMatrix1 = block.inputValue( aMatrix1, &stat ); MDataHandle hMatrix2 = block.inputValue( aMatrix2, &stat ); MDataHandle hBlender = block.inputValue( aBlender ); MMatrix matrix = hMatrix1.asMatrix()*( 1-hBlender.asFloat() ) + hMatrix2.asMatrix()*hBlender.asFloat(); MPxTransformationMatrix trMtx( matrix ); MDataHandle hOutputTranslate = block.outputValue( aOutputTranslate ); MDataHandle hOutputRotate = block.outputValue( aOutputRotate ); MDataHandle hOutputScale = block.outputValue( aOutputScale ); MDataHandle hOutputShear = block.outputValue( aOutputShear ); MVector translate = trMtx.translation(); hOutputTranslate.set( translate ); MVector rotate = trMtx.eulerRotation().asVector(); hOutputRotate.set( rotate ); MVector scale = trMtx.scale(); hOutputScale.set( scale ); MVector shear = trMtx.shear(); hOutputShear.set( shear ); block.setClean( plug ); return MS::kSuccess; }
MStatus SwirlDeformer::deform( MDataBlock& block, MItGeometry &iter, const MMatrix &localToWorld, unsigned int geomIndex ) { MStatus stat; MDataHandle envData = block.inputValue( envelope ); float env = envData.asFloat(); if( env == 0.0 ) // Deformer has no effect return MS::kSuccess; MDataHandle matData = block.inputValue( deformSpace ); MMatrix mat = matData.asMatrix(); MMatrix invMat = mat.inverse(); MDataHandle startDistHnd = block.inputValue( startDist ); double startDist = startDistHnd.asDouble(); MDataHandle endDistHnd = block.inputValue( endDist ); double endDist = endDistHnd.asDouble(); MPoint pt; float weight; double dist; double ang; double cosAng; double sinAng; double x; double distFactor; for( iter.reset(); !iter.isDone(); iter.next() ) { weight = weightValue( block, geomIndex, iter.index() ); if( weight == 0.0f ) continue; pt = iter.position(); pt *= invMat; dist = sqrt( pt.x * pt.x + pt.z * pt.z ); if( dist < startDist || dist > endDist ) continue; distFactor = 1 - ((dist - startDist) / (endDist - startDist)); ang = distFactor * M_PI * 2.0 * env * weight; if( ang == 0.0 ) continue; cosAng = cos( ang ); sinAng = sin( ang ); x = pt.x * cosAng - pt.z * sinAng; pt.z = pt.x * sinAng + pt.z * cosAng; pt.x = x; pt *= mat; iter.setPosition( pt ); } return stat; }
MStatus Cell3D::compute(const MPlug& plug, MDataBlock& block) { if ( (plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha) && (plug != aOutBorderDist) && (plug != aOutF0) && (plug != aOutF1) && (plug != aOutN0) ) return MS::kUnknownParameter; const float3& worldPos = block.inputValue(aPointWorld).asFloat3(); const MFloatMatrix& m = block.inputValue(aPlaceMat).asFloatMatrix(); const MFloatVector& cGain = block.inputValue(aColorGain).asFloatVector(); const MFloatVector& cOff = block.inputValue(aColorOffset).asFloatVector(); MFloatPoint q(worldPos[0], worldPos[1], worldPos[2]); q *= m; // Convert into solid space float n0, f0, f1; cellFunc(R3(q.x, q.y, q.z), n0, f0, f1); MDataHandle outHandle = block.outputValue(aOutF0); outHandle.asFloat() = f0; outHandle.setClean(); outHandle = block.outputValue(aOutF1); outHandle.asFloat() = f1; outHandle.setClean(); outHandle = block.outputValue(aOutN0); outHandle.asFloat() = n0; outHandle.setClean(); outHandle = block.outputValue(aOutBorderDist); outHandle.asFloat() = 0.5f*(f1 - f0); outHandle.setClean(); outHandle = block.outputValue( aOutColor ); MFloatVector & outColor = outHandle.asFloatVector(); outColor = cGain * f0 + cOff; outHandle.setClean(); outHandle = block.outputValue(aOutAlpha); outHandle.asFloat() = f0; outHandle.setClean(); return MS::kSuccess; }
// The compute method is called by Maya when the input values // change and the output values need to be recomputed. // The input values are read then using sinf() and cosf() // the output values are stored on the output plugs. // MStatus circle::compute (const MPlug& plug, MDataBlock& data) { MStatus returnStatus; // Check that the requested recompute is one of the output values // if (plug == sOutput || plug == cOutput) { // Read the input values // MDataHandle inputData = data.inputValue (input, &returnStatus); CHECK_MSTATUS( returnStatus ); MDataHandle scaleData = data.inputValue (scale, &returnStatus); CHECK_MSTATUS( returnStatus ); MDataHandle framesData = data.inputValue (frames, &returnStatus); CHECK_MSTATUS( returnStatus ); // Compute the output values // float currentFrame = inputData.asFloat(); float scaleFactor = scaleData.asFloat(); float framesPerCircle = framesData.asFloat(); float angle = 6.2831853f * (currentFrame/framesPerCircle); float sinResult = sinf (angle) * scaleFactor; float cosResult = cosf (angle) * scaleFactor; // Store them on the output plugs // MDataHandle sinHandle = data.outputValue( circle::sOutput, &returnStatus ); CHECK_MSTATUS( returnStatus ); MDataHandle cosHandle = data.outputValue( circle::cOutput, &returnStatus ); CHECK_MSTATUS( returnStatus ); sinHandle.set( sinResult ); cosHandle.set( cosResult ); CHECK_MSTATUS( data.setClean( plug ) ); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus offset::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& /*m*/, unsigned int multiIndex) // // Method: deform // // Description: Deform the point with a squash algorithm // // Arguments: // block : the datablock of the node // iter : an iterator for the geometry to be deformed // m : matrix to transform the point into world space // multiIndex : the index of the geometry that we are deforming // // { MStatus returnStatus; // Envelope data from the base class. // The envelope is simply a scale factor. // MDataHandle envData = block.inputValue(envelope, &returnStatus); if (MS::kSuccess != returnStatus) return returnStatus; float env = envData.asFloat(); // Get the matrix which is used to define the direction and scale // of the offset. // MDataHandle matData = block.inputValue(offsetMatrix, &returnStatus ); if (MS::kSuccess != returnStatus) return returnStatus; MMatrix omat = matData.asMatrix(); MMatrix omatinv = omat.inverse(); // iterate through each point in the geometry // for ( ; !iter.isDone(); iter.next()) { MPoint pt = iter.position(); pt *= omatinv; float weight = weightValue(block,multiIndex,iter.index()); // offset algorithm // pt.y = pt.y + env*weight; // // end of offset algorithm pt *= omat; iter.setPosition(pt); } return returnStatus; }
MStatus DucttapeMergeDeformer::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& m, unsigned int multiIndex) { MStatus status; MDataHandle envData = block.inputValue(envelope,&status); const float env = envData.asFloat(); if(env < 1e-3f) return status; if(multiIndex == 0) { if(m_inputGeomIter) { delete m_inputGeomIter; m_inputGeomIter = NULL; } MDataHandle hmesh = block.inputValue(ainmesh); MItGeometry * aiter = new MItGeometry( hmesh, true, &status ); if(!status) { AHelper::Info<int>("DucttapeMergeDeformer error no geom it", 0); return status; } m_inputGeomIter = aiter; } if(!m_inputGeomIter) return status; MPoint pd; MVector dv; for (; !iter.isDone(); iter.next()) { if(m_inputGeomIter->isDone() ) return status; float wei = env * weightValue(block, multiIndex, iter.index() ); if(wei > 1e-3f) { pd = iter.position(); dv = m_inputGeomIter->position() - pd; pd = pd + dv * wei; iter.setPosition(pd); } m_inputGeomIter->next(); } return status; }
// // DESCRIPTION: /////////////////////////////////////////////////////// MStatus DispNode::compute( const MPlug& plug, MDataBlock& block ) { if ((plug == aOutColor) || (plug.parent() == aOutColor) || (plug == aOutDisplacement)) { MFloatVector resultColor(0.0,0.0,0.0); MFloatVector& InputColor = block.inputValue( aColor ).asFloatVector(); float MultValue = block.inputValue( aInputValue ).asFloat(); resultColor = InputColor; float scalar = resultColor[0] + resultColor[1] + resultColor[2]; if (scalar != 0.0) { scalar /= 3.0; scalar *= MultValue; } // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); MDataHandle outDispHandle = block.outputValue( aOutDisplacement ); float& outDisp = outDispHandle.asFloat(); outDisp = scalar; outDispHandle.setClean( ); } else if ((plug == aOutTransparency) || (plug.parent() == aOutTransparency)) { // set output transparency to be opaque MFloatVector transparency(0.0,0.0,0.0); MDataHandle outTransHandle = block.outputValue( aOutTransparency ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = transparency; outTransHandle.setClean( ); } else return MS::kUnknownParameter; return MS::kSuccess; }
//- 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 simpleNode::compute( const MPlug& plug, MDataBlock& data ) { //- Check which output attribute we have been asked to compute. If this //- node doesn't know how to compute it, you must return MS::kUnknownParameter. if( plug == simpleNode::output ) { //- Get a handle to the input attribute that we will need for the //- computation. If the value is being supplied via a connection //- in the dependency graph, then this call will cause all upstream //- connections to be evaluated so that the correct value is supplied. MDataHandle inputData = data.inputValue( simpleNode::input ); //- Read the input value from the handle. float result = inputData.asFloat(); //- Get a handle to the output attribute. This is similar to the //- "inputValue" call above except that no dependency graph //- computation will be done as a result of this call. //- Get a handle on the output attribute MDataHandle outputHandle = data.outputValue( simpleNode::output ); //- Set the new output value to the handle. outputHandle.set( result * 2 ); //- Mark the destination plug as being clean. This will prevent the //- dependency graph from repeating this calculation until an input //- attribute of this node which affects this output attribute changes. //- Tell Maya the plug is now clean data.setClean(plug); //- Return success to Maya return MS::kSuccess; } //- Tell Maya that we do not know how to handle this plug, but let give a chance //- to our parent class to evaluate it. return MS::kUnknownParameter; }
MStatus myComp::compute(const MPlug& plug, MDataBlock& block) { // outColor or individial R, G, B channel if((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha)) return MS::kUnknownParameter; MFloatVector resultColor; MFloatVector& fore = block.inputValue( aForegroundColor ).asFloatVector(); MFloatVector& back = block.inputValue( aBackgroundColor ).asFloatVector(); MFloatVector& bclr = block.inputValue( aBackColor ).asFloatVector(); float& alpha = block.inputValue( aMask ).asFloat(); if ( alpha > 0.99999f ) alpha = 1.f; else if ( alpha < 0.00001 ) alpha = 0.f; resultColor = fore + ((bclr - back) * (1.0f - alpha)); // normalize output color if (resultColor[0] < 0.f ) resultColor[0] = 0.f; if (resultColor[1] < 0.f ) resultColor[1] = 0.f; if (resultColor[2] < 0.f ) resultColor[2] = 0.f; if (resultColor[0] > 1.f ) resultColor[0] = 1.f; if (resultColor[1] > 1.f ) resultColor[1] = 1.f; if (resultColor[2] > 1.f ) resultColor[2] = 1.f; // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); MDataHandle outAlphaHandle = block.outputValue( aOutAlpha ); float& outAlpha = outAlphaHandle.asFloat(); outAlpha = ( resultColor.x + resultColor.y + resultColor.z ) / 3.0f; outAlphaHandle.setClean(); return MS::kSuccess; }
// // This function gets called by Maya to evaluate the texture. // MStatus mySChecker::compute(const MPlug& plug, MDataBlock& block) { // outColor or individial R, G, B channel, or alpha if((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha)) return MS::kUnknownParameter; MFloatVector resultColor; float3 & worldPos = block.inputValue(aPointWorld).asFloat3(); MFloatMatrix& mat = block.inputValue(aPlaceMat).asFloatMatrix(); float3 & bias = block.inputValue(aBias).asFloat3(); MFloatPoint pos(worldPos[0], worldPos[1], worldPos[2]); pos *= mat; // Convert into solid space // normalize the point int count = 0; if (pos.x - floor(pos.x) < bias[0]) count++; if (pos.y - floor(pos.y) < bias[1]) count++; if (pos.z - floor(pos.z) < bias[2]) count++; if (count & 1) resultColor = block.inputValue(aColor2).asFloatVector(); else resultColor = block.inputValue(aColor1).asFloatVector(); // Set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); // Set ouput alpha attribute MDataHandle outAlphaHandle = block.outputValue( aOutAlpha ); float& outAlpha = outAlphaHandle.asFloat(); outAlpha = ( count & 1) ? 1.0f : 0.0f; outAlphaHandle.setClean(); return MS::kSuccess; }
MStatus simpleEvaluationNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; if( plug == output ) { MDataHandle inputData = data.inputValue( input, &returnStatus ); if( returnStatus != MS::kSuccess ) { cerr << "ERROR getting data" << endl; } else { MDataHandle inputTimeData = data.inputValue( aTimeInput, &returnStatus ); if( returnStatus != MS::kSuccess ) { cerr << "ERROR getting data" << endl; } else { if ( ! cachedValueIsValid ) { MTime time = inputTimeData.asTime(); cachedValue = doExpensiveCalculation( inputData.asFloat() , (float) time.value() ); cachedValueIsValid = true; } MDataHandle outputHandle = data.outputValue( simpleEvaluationNode::output ); outputHandle.set( cachedValue ); data.setClean(plug); } } } else { return MS::kUnknownParameter; } return MS::kSuccess; }
// // This function gets called by Maya to evaluate the texture. // MStatus noise3::compute(const MPlug& plug, MDataBlock& block) { // outColor or individial R, G, B channel, or alpha if((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha)) return MS::kUnknownParameter; MFloatVector resultColor; MFloatVector & col1 = block.inputValue(aColor1).asFloatVector(); MFloatVector & col2 = block.inputValue(aColor2).asFloatVector(); float3 & worldPos = block.inputValue( aPointWorld ).asFloat3(); MFloatMatrix& mat = block.inputValue( aPlaceMat ).asFloatMatrix(); float& sc = block.inputValue( aScale ).asFloat(); float& bi = block.inputValue( aBias ).asFloat(); MFloatPoint solidPos(worldPos[0], worldPos[1], worldPos[2]); solidPos *= mat; // Convert into solid space float val = fabsf( pnoise3( solidPos ) * sc + bi ); if (val < 0.) val = 0.; if (val > 1.) val = 1.; resultColor = col1 * val + col2*(1-val); // Set output color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); MDataHandle outAlphaHandle = block.outputValue( aOutAlpha ); float& outAlpha = outAlphaHandle.asFloat(); outAlpha = val; outAlphaHandle.setClean(); return MS::kSuccess; }
MStatus CheckerNode::compute( const MPlug& plug, MDataBlock& block ) { // outColor or individial R, G, B channel, or alpha if((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha)) return MS::kUnknownParameter; MFloatVector resultColor; float2 & uv = block.inputValue( aUVCoord ).asFloat2(); float2 & bias = block.inputValue( aBias ).asFloat2(); int count = 0; if (uv[0] - floorf(uv[0]) < bias[0]) count++; if (uv[1] - floorf(uv[1]) < bias[1]) count++; if (count & 1) resultColor = block.inputValue( aColor2 ).asFloatVector(); else resultColor = block.inputValue( aColor1 ).asFloatVector(); // Set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); // Set ouput alpha attribute MDataHandle outAlphaHandle = block.outputValue( aOutAlpha ); float& outAlpha = outAlphaHandle.asFloat(); outAlpha = (count & 1) ? 1.f : 0.f; outAlphaHandle.setClean(); return MS::kSuccess; }
MStatus sine::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; if( plug == output ) { MDataHandle inputData = data.inputValue( input, &returnStatus ); if( returnStatus != MS::kSuccess ) cerr << "ERROR getting data" << endl; else { float result = sinf( inputData.asFloat() ) * 10.0f; MDataHandle outputHandle = data.outputValue( sine::output ); outputHandle.set( result ); data.setClean(plug); } } else { return MS::kUnknownParameter; } return MS::kSuccess; }
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; }
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; } }
// // DESCRIPTION: /////////////////////////////////////////////////////// MStatus clearcoat::compute( const MPlug& plug, MDataBlock& block ) { if( plug == aOutValue ) { MFloatVector& surfaceNormal = block.inputValue( aNormalCamera ).asFloatVector(); MFloatVector& rayDirection = block.inputValue( aRayDirection ).asFloatVector(); float index = block.inputValue(aIndex).asFloat(); float scale = block.inputValue(aScale).asFloat(); float bias = block.inputValue(aBias).asFloat(); // This is Jim Craighead's code. Ripped straight from Studio... /* This basically computes a fresnel reflection coeficient. */ /* It could probably use some optimization, but the trig */ /* identities are left as an exercise for the masochistic. */ /* Also note that this is reasonably accurate for refractive */ /* indices greater than 1, but a complete hack for smaller */ /* values. There are still problems with values below 0.6 */ /* such as Gold and Silver. */ float origCosne = - (rayDirection * surfaceNormal); float ninety = (float) kPi * 0.5f; float I = (float) acos( origCosne ); float transSin = (float) sin(I) / (float)(index); float ccFresnel = 1.0; float ccBlend = 0.0; float sum = 0.0; float difference = 0.0; if( transSin > 1.0 ) { float limit = (float) asin( (float)(index)); sum = limit + ninety; difference = limit - ninety; } else { float T = (float) asin( transSin ); sum = I + T; difference = I - T; } if( ! (fabs(difference) < kFloatEpsilon ) ) { float fudgedScale = (float)(scale) * 2.0f; float fudgedBias = (float)(bias) * 1.0f; if( sum < ninety ) { float parallel = (float) (tan(difference) / tan(sum)); float perpendicular = (float) (sin(difference) / sin(sum)); ccFresnel = 0.5f * ( perpendicular * perpendicular + parallel * parallel ); } else { float perpendicular = (float) sin(difference); ccFresnel = 0.5f * ( perpendicular * perpendicular ); } ccBlend = ccFresnel * fudgedScale + fudgedBias; if( ccBlend > 1.0 ) ccBlend = 1.0; else if( ccBlend < 0.0 ) ccBlend = 0.0; } // set ouput color attribute MDataHandle outHandle = block.outputValue( aOutValue ); float& outV = outHandle.asFloat(); outV = ccBlend; outHandle.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 retargetLocator::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hDiscMatrix = data.inputValue( aDiscMatrix ); MDataHandle hDiscAxis = data.inputValue( aDiscAxis ); MDataHandle hDiscAngle = data.inputValue( aDiscAngle ); MDataHandle hDiscDivision = data.inputValue( aDiscDivision ); MDataHandle hDiscOffset = data.inputValue( aDiscOffset ); MDataHandle hDiscSize = data.inputValue( aDiscSize ); MDataHandle hDiscActiveColor = data.inputValue( aDiscActiveColor ); MDataHandle hDiscLeadColor = data.inputValue( aDiscLeadColor ); MDataHandle hDiscDefaultColor = data.inputValue( aDiscDefaultColor ); MDataHandle hDiscFillAlpha = data.inputValue( aDiscFillAlpha ); MDataHandle hDiscLineAlpha = data.inputValue( aDiscLineAlpha ); discAxis = hDiscAxis.asInt(); discDivision = hDiscDivision.asInt(); discAngle = hDiscAngle.asDouble(); discSize = hDiscSize.asVector(); discOffset = hDiscOffset.asVector(); discActiveColor = hDiscActiveColor.asFloat3(); discLeadColor = hDiscLeadColor.asFloat3(); discDefaultColor = hDiscDefaultColor.asFloat3(); discFillAlpha = hDiscFillAlpha.asFloat(); discLineAlpha = hDiscLineAlpha.asFloat(); MArrayDataHandle hArrArrow = data.inputArrayValue( aArrow ); arrowNum = hArrArrow.elementCount(); inheritMatrix.setLength( arrowNum ); aimMatrix.setLength( arrowNum ); inputMeshObj.setLength( arrowNum ); startSize.setLength( arrowNum ); size.setLength( arrowNum ); activeColor.setLength( arrowNum ); leadColor.setLength( arrowNum ); defaultColor.setLength( arrowNum ); fillAlpha.setLength( arrowNum ); lineAlpha.setLength( arrowNum ); offset.setLength( arrowNum ); for( int i =0; i < arrowNum; i++ ) { MDataHandle hArrow = hArrArrow.inputValue(); MDataHandle hInheritMatrix = hArrow.child( aInheritMatrix ); MDataHandle hAimMatrix = hArrow.child( aAimMatrix ); MDataHandle hInputMesh = hArrow.child( aInputMesh ); MDataHandle hStartSize = hArrow.child( aStartSize ); MDataHandle hSize = hArrow.child( aSize ); MDataHandle hActiveColor = hArrow.child( aActiveColor ); MDataHandle hLeadColor = hArrow.child( aLeadColor ); MDataHandle hDefaultColor = hArrow.child( aDefaultColor ); MDataHandle hFillAlpha = hArrow.child( aFillAlpha ); MDataHandle hLineAlpha = hArrow.child( aLineAlpha ); MDataHandle hOffset = hArrow.child( aOffset ); inheritMatrix[i] = hInheritMatrix.asBool(); aimMatrix[i] = hAimMatrix.asMatrix()*hDiscMatrix.asMatrix().inverse(); inputMeshObj[i] = hInputMesh.asMesh(); startSize[i] = hStartSize.asFloat(); size[i] = hSize.asFloat(); activeColor[i] = hActiveColor.asFloat3(); leadColor[i] = hLeadColor.asFloat3(); defaultColor[i] = hDefaultColor.asFloat3(); fillAlpha[i] = hFillAlpha.asFloat(); lineAlpha[i] = hLineAlpha.asFloat(); offset[i] = hOffset.asVector(); hArrArrow.next(); } MDataHandle hOutput = data.outputValue( aOutput ); hOutput.set( 1.0 ); data.setClean( plug ); return MS::kSuccess; }
/* virtual */ bool hwColorPerVertexShader::setInternalValueInContext( const MPlug& plug, const MDataHandle& handle, MDGContext&) { bool handledAttribute = false; if (plug == aNormalsPerVertex) { handledAttribute = true; mNormalsPerVertex = (unsigned int) handle.asInt(); } else if (plug == aColorsPerVertex) { handledAttribute = true; mColorsPerVertex = (unsigned int) handle.asInt(); } else if (plug == aColorSetName) { handledAttribute = true; mColorSetName = (MString) handle.asString(); } else if (plug == aTexRotateX) { handledAttribute = true; mTexRotateX = handle.asFloat(); } else if (plug == aTexRotateY) { handledAttribute = true; mTexRotateY = handle.asFloat(); } else if (plug == aTexRotateZ) { handledAttribute = true; mTexRotateZ = handle.asFloat(); } else if (plug == aColorGain) { handledAttribute = true; float3 & val = handle.asFloat3(); if (val[0] != mColorGain[0] || val[1] != mColorGain[1] || val[2] != mColorGain[2]) { mColorGain[0] = val[0]; mColorGain[1] = val[1]; mColorGain[2] = val[2]; mAttributesChanged = true; } } else if (plug == aColorBias) { handledAttribute = true; float3 &val = handle.asFloat3(); if (val[0] != mColorBias[0] || val[1] != mColorBias[1] || val[2] != mColorBias[2]) { mColorBias[0] = val[0]; mColorBias[1] = val[1]; mColorBias[2] = val[2]; mAttributesChanged = true; } } else if (plug == aTranspGain) { handledAttribute = true; float val = handle.asFloat(); if (val != mTranspGain) { mTranspGain = val; mAttributesChanged = true; } } else if (plug == aTranspBias) { handledAttribute = true; float val = handle.asFloat(); if (val != mTranspBias) { mTranspBias = val; mAttributesChanged = true; } } return handledAttribute; }
MStatus sgIkSmoothStretch::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ( plug == aOutputDistance ) { MArrayDataHandle hArrInputDistance = data.inputArrayValue( aInputDistance ); MDataHandle hStretchAble = data.inputValue( aStretchAble ); MDataHandle hSmoothArea = data.inputValue( aSmoothArea ); float stretchAble = hStretchAble.asFloat(); double allDistance = 0.0; int arrayCount = hArrInputDistance.elementCount(); double* outputDistances = new double[arrayCount]; int multMinus = 1; for( int i=0; i<arrayCount; i++ ) { MDataHandle hInputDistance = hArrInputDistance.inputValue(); double inputDistance = hInputDistance.asDouble(); if( inputDistance < 0 ) { multMinus = -1; outputDistances[i] = -inputDistance; } else { outputDistances[i] = inputDistance; } allDistance += outputDistances[i]; hArrInputDistance.next(); } MDataHandle hInPosition = data.inputValue( aInPosition ); MDataHandle hInPositionX = hInPosition.child( aInPositionX ); MDataHandle hInPositionY = hInPosition.child( aInPositionY ); MDataHandle hInPositionZ = hInPosition.child( aInPositionZ ); double smoothArea = hSmoothArea.asDouble()*0.1; double poseDistance = sqrt( pow( hInPositionX.asDouble(), 2 )+pow( hInPositionY.asDouble(), 2 )+pow( hInPositionZ.asDouble(), 2 ) ) ; allDistance = fabs( allDistance ); double stretchRate = getSmoothStretchRate( outputDistances[0], outputDistances[1], poseDistance, smoothArea ); double smoothRate = getSmoothRate( outputDistances[0], outputDistances[1], poseDistance, smoothArea ); double currentRate = ( 1-stretchAble )*smoothRate + stretchAble*stretchRate; outputDistances[0] *= currentRate*multMinus; outputDistances[1] *= currentRate*multMinus; MArrayDataHandle hArrOutputDistance = data.outputArrayValue( aOutputDistance ); MArrayDataBuilder bArrOutputDistance( aOutputDistance, arrayCount, &stat ); for( int i=0; i<arrayCount; i++ ) { MDataHandle hOutputDistance = bArrOutputDistance.addElement( i ); hOutputDistance.set( outputDistances[i] ); } hArrOutputDistance.set( bArrOutputDistance ); hArrOutputDistance.setAllClean(); data.setClean( plug ); } return MS::kSuccess; }
MStatus puttyNode::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& worldMatrix, unsigned int multiIndex) { // MGlobal::displayInfo("deform"); MStatus status = MS::kSuccess; ///////////////////////////////////////////////////////////////////////////////////////////////// // // get inputs // // get the node ready flag MDataHandle dh = block.inputValue(aScriptSourced,&status); SYS_ERROR_CHECK(status, "Error getting aScriptSourced data handle\n"); bool scriptSourced = dh.asBool(); if (!scriptSourced) return MS::kSuccess; dh = block.inputValue(aNodeReady,&status); SYS_ERROR_CHECK(status, "Error getting node ready data handle\n"); bool nodeReady = dh.asBool(); // if it's not ready, don't do anything if (!nodeReady) return MS::kSuccess; dh = block.inputValue(aDefSpace,&status); SYS_ERROR_CHECK(status, "Error getting defSpace data handle\n"); short defSpace = dh.asShort(); dh = block.inputValue(aDefWeights,&status); SYS_ERROR_CHECK(status, "Error getting defWeights data handle\n"); short defWeights = dh.asShort(); dh = block.inputValue(aDefEnvelope,&status); SYS_ERROR_CHECK(status, "Error getting defEnvelope data handle\n"); short defEnvelope = dh.asShort(); // get the command dh = block.inputValue(aCmdBaseName,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString script = dh.asString(); /* if (script == "") { status = MS::kFailure; USER_ERROR_CHECK(status, "no script provided!\n"); } */ ///////////////////////////////////////////////////////////////////////////////////////////////// // // build mel cmd string // // check if it's a valid cmd // get the envelope // double env = 1; if (defEnvelope == MSD_ENVELOPE_AUTO) { dh = block.inputValue(envelope,&status); SYS_ERROR_CHECK(status, "Error getting envelope data handle\n"); env = double(dh.asFloat()); // early stop 'cause there is nothing more to do if (env == 0.0) return MS::kSuccess; } // get the points, transform them into the right space if needed // int count = iter.count(); MVectorArray points(count); for ( ; !iter.isDone(); iter.next()) points[iter.index()] = iter.position(); if ( defSpace == MSD_SPACE_WORLD ) { for (int i = 0;i<count;i++) points[i] = MPoint(points[i]) * worldMatrix; } // get the weights // MDoubleArray weights; if ( defWeights == MSD_WEIGHTS_AUTO) { weights.setLength(count); for (int i = 0;i<count;i++) weights[i] = weightValue(block,multiIndex,i); } // get the object name and type // get the input geometry, traverse through the data handles MArrayDataHandle adh = block.outputArrayValue( input, &status ); SYS_ERROR_CHECK(status,"error getting input array data handle.\n"); status = adh.jumpToElement( multiIndex ); SYS_ERROR_CHECK(status, "input jumpToElement failed.\n"); // compound data MDataHandle cdh = adh.inputValue( &status ); SYS_ERROR_CHECK(status, "error getting input inputValue\n"); // input geometry child dh = cdh.child( inputGeom ); MObject dInputGeometry = dh.data(); // get the type MString geometryType = dInputGeometry.apiTypeStr(); // get the name // MFnDagNode dagFn( dInputGeometry, &status); // SYS_ERROR_CHECK(status, "error converting geometry obj to dag node\n"); // MString geometryName = dagFn.fullPathName(&status); // SYS_ERROR_CHECK(status, "error getting full path name \n"); // MString geometryType = ""; // MString geometryName = ""; ///////////////////////////////////////////////////////////////////////////////////////////////// // // set the current values on the temp plugs for the script to be picked up // // the position MObject thisNode = thisMObject(); MPlug currPlug(thisNode,aCurrPosition); MFnVectorArrayData vecD; MObject currObj = vecD.create(points,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currPosPlug value\n"); // the weights currPlug =MPlug(thisNode,aCurrWeight); MFnDoubleArrayData dblD; currObj = dblD.create(weights,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWeightsPlug value\n"); // world matrix currPlug =MPlug(thisNode,aCurrWorldMatrix); MFnMatrixData matD; currObj = matD.create(worldMatrix,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWorldMatrixPlug value\n"); // the multi index currPlug =MPlug(thisNode,aCurrMultiIndex); currPlug.setValue(int(multiIndex)); SYS_ERROR_CHECK(status, "error setting currMultiIndexPlug value\n"); // geometry name/type // currPlug =MPlug(thisNode,aCurrGeometryName); // currPlug.setValue(geometryName); // SYS_ERROR_CHECK(status, "error setting aCurrGeometryName value\n"); currPlug =MPlug(thisNode,aCurrGeometryType); currPlug.setValue(geometryType); SYS_ERROR_CHECK(status, "error setting aCurrGeometryType value\n"); ///////////////////////////////////////////////////////////////////////////////////////////////// // // execute the mel script // MString melCmd = script+"(\"" +name()+"\","+count+")"; MCommandResult melResult; status = MGlobal::executeCommand(melCmd,melResult); // if the command did not work, then try to resource the script // (might have been that we were in a fresh scene and nothing was ready yet if (status != MS::kSuccess) { dh = block.inputValue(aScript,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString scriptFile = dh.asString(); // try to source the script MString cmd = "source \"" + scriptFile+"\""; MCommandResult melResult; status = MGlobal::executeCommand(cmd,melResult); // if successfull, retry the command if (!status.error()) { status = MGlobal::executeCommand(melCmd,melResult); } } USER_ERROR_CHECK(status, "Error executing mel command, please check the function you provided is valid, error free and has the appropriate parameters!"); // check the result type if ((melResult.resultType()) != (MCommandResult::kDoubleArray)) { USER_ERROR_CHECK(MS::kFailure, "result of mel command has wrong type, should be doubleArray (which will be interpreted as vectorArray)!"); } // get the result as a double array MDoubleArray newP; status = melResult.getResult(newP); USER_ERROR_CHECK(status, "Error getting result of mel command!"); int newCount = newP.length()/3; // size check if (newCount != count) { USER_ERROR_CHECK(MS::kFailure, "the size of the result does not match the size of the input!"); } // convert the double array into a vector array MPointArray newPoints(newCount); for(int i=0;i<newCount;i++) newPoints[i]=MPoint(newP[i*3],newP[i*3+1],newP[i*3+2]); ///////////////////////////////////////////////////////////////////////////////////////////////// // // interprete and apply the result // // do the envelope and weights if ((defEnvelope == MSD_ENVELOPE_AUTO)||((defWeights == MSD_WEIGHTS_AUTO))) { MDoubleArray envPP(count, env); if (defWeights == MSD_WEIGHTS_AUTO) { for (int i = 0;i<count;i++) envPP[i] *= weights[i]; } // linear interpolation between old and new points for (int i = 0;i<count;i++) newPoints[i] = (points[i] * (1-envPP[i])) + (newPoints[i] * envPP[i]); } // retransform the result if it was in world space if ( defSpace == MSD_SPACE_WORLD ) { MMatrix worldMatrixInv = worldMatrix.inverse(); for (int i = 0;i<count;i++) newPoints[i] *= worldMatrixInv; } // set the points iter.reset(); for ( ; !iter.isDone(); iter.next()) iter.setPosition(newPoints[iter.index()]); return status; }
MStatus HRBFSkinCluster::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& m, unsigned int multiIndex) // // Method: deform1 // // Description: Deforms the point with a simple smooth skinning algorithm // // Arguments: // block : the datablock of the node // iter : an iterator for the geometry to be deformed // m : matrix to transform the point into world space // multiIndex : the index of the geometry that we are deforming // // { MStatus returnStatus; // get HRBF status MDataHandle HRBFstatusData = block.inputValue(rebuildHRBF, &returnStatus); McheckErr(returnStatus, "Error getting rebuildHRBF handle\n"); int rebuildHRBFStatusNow = HRBFstatusData.asInt(); // handle signaling to the rest of deform that HRBFs must be rebuild bool signalRebuildHRBF = false; signalRebuildHRBF = (rebuildHRBFStatus != rebuildHRBFStatusNow); MMatrixArray bindTFs; // store just the bind transforms in here. MMatrixArray boneTFs; // ALWAYS store just the bone transforms in here. // get HRBF export status MDataHandle exportCompositionData = block.inputValue(exportComposition, &returnStatus); McheckErr(returnStatus, "Error getting exportComposition handle\n"); int exportCompositionStatusNow = exportCompositionData.asInt(); MDataHandle HRBFExportSamplesData = block.inputValue(exportHRBFSamples, &returnStatus); McheckErr(returnStatus, "Error getting exportHRBFSamples handle\n"); std::string exportHRBFSamplesStatusNow = HRBFExportSamplesData.asString().asChar(); MDataHandle HRBFExportValuesData = block.inputValue(exportHRBFValues, &returnStatus); McheckErr(returnStatus, "Error getting exportHRBFValues handle\n"); std::string exportHRBFValuesStatusNow = HRBFExportValuesData.asString().asChar(); // get skinning type MDataHandle useDQData = block.inputValue(useDQ, &returnStatus); McheckErr(returnStatus, "Error getting useDQ handle\n"); int useDQNow = useDQData.asInt(); // determine if we're using HRBF MDataHandle useHRBFData = block.inputValue(useHRBF, &returnStatus); McheckErr(returnStatus, "Error getting useHRBFData handle\n"); int useHRBFnow = useHRBFData.asInt(); // get envelope because why not MDataHandle envData = block.inputValue(envelope, &returnStatus); float env = envData.asFloat(); // get point in space for evaluating HRBF MDataHandle checkHRBFAtData = block.inputValue(checkHRBFAt, &returnStatus); McheckErr(returnStatus, "Error getting useDQ handle\n"); double* data = checkHRBFAtData.asDouble3(); // get the influence transforms // MArrayDataHandle transformsHandle = block.inputArrayValue( matrix ); // tell block what we want int numTransforms = transformsHandle.elementCount(); if ( numTransforms == 0 ) { // no transforms, no problems return MS::kSuccess; } MMatrixArray transforms; // fetch transform matrices -> actual joint matrices for ( int i=0; i<numTransforms; ++i ) { MMatrix worldTF = MFnMatrixData(transformsHandle.inputValue().data()).matrix(); transforms.append(worldTF); boneTFs.append(worldTF); transformsHandle.next(); } // inclusive matrices inverse of the driving transform at time of bind // matrices for transforming vertices to joint local space MArrayDataHandle bindHandle = block.inputArrayValue( bindPreMatrix ); // tell block what we want if ( bindHandle.elementCount() > 0 ) { for ( int i=0; i<numTransforms; ++i ) { MMatrix bind = MFnMatrixData(bindHandle.inputValue().data()).matrix(); transforms[i] = bind * transforms[i]; bindHandle.next(); if (signalRebuildHRBF) bindTFs.append(bind); } } MArrayDataHandle weightListHandle = block.inputArrayValue(weightList); if (weightListHandle.elementCount() == 0) { // no weights - nothing to do std::cout << "no weights!" << std::endl; //rebuildHRBFStatus = rebuildHRBFStatusNow - 1; // HRBFs will need to rebuilt no matter what return MS::kSuccess; } // print HRBF samples if requested if (exportHRBFSamplesStatusNow != exportHRBFSamplesStatus) { std::cout << "instructed to export HRBF samples: " << exportHRBFSamplesStatusNow.c_str() << std::endl; exportHRBFSamplesStatus = exportHRBFSamplesStatusNow; // TODO: handle exporting HRBFs to the text file format hrbfMan->debugSamplesToConsole(exportHRBFSamplesStatus); } // print HRBF values if requested if (exportHRBFValuesStatusNow != exportHRBFValuesStatus) { std::cout << "instructed to export HRBF values: " << exportHRBFValuesStatusNow.c_str() << std::endl; exportHRBFValuesStatus = exportHRBFValuesStatusNow; // TODO: handle exporting HRBFs to the text file format hrbfMan->debugValuesToConsole(exportHRBFValuesStatus); } // print HRBF composition if requested if (exportCompositionStatusNow != exportCompositionStatus) { std::cout << "instructed to export HRBF composition." << std::endl; exportCompositionStatus = exportCompositionStatusNow; // TODO: handle exporting HRBFs to the text file format hrbfMan->debugCompositionToConsole(boneTFs, numTransforms); } // check the HRBF value if the new point is significantly different MPoint checkHRBFHereNow(data[0], data[1], data[2]); if ((checkHRBFHereNow - checkHRBFHere).length() > 0.0001) { if (hrbfMan->m_HRBFs.size() == numTransforms) { std::cout << "checking HRBF at x:" << data[0] << " y: " << data[1] << " z: " << data[2] << std::endl; hrbfMan->compose(boneTFs); float val = 0.0f; float dx = 0.0f; float dy = 0.0f; float dz = 0.0f; float grad = 0.0f; hrbfMan->mf_vals->trilinear(data[0], data[1], data[2], val); hrbfMan->mf_gradX->trilinear(data[0], data[1], data[2], dx); hrbfMan->mf_gradY->trilinear(data[0], data[1], data[2], dy); hrbfMan->mf_gradZ->trilinear(data[0], data[1], data[2], dz); hrbfMan->mf_gradMag->trilinear(data[0], data[1], data[2], grad); std::cout << "val: " << val << " dx: " << dx << " dy: " << dy << " dz: " << dz << " grad: " << grad << std::endl; checkHRBFHere = checkHRBFHereNow; } } // rebuild HRBFs if needed if (signalRebuildHRBF) { std::cout << "instructed to rebuild HRBFs" << std::endl; rebuildHRBFStatus = rebuildHRBFStatusNow; MArrayDataHandle parentIDCsHandle = block.inputArrayValue(jointParentIdcs); // tell block what we want std::vector<int> jointParentIndices(numTransforms); if (parentIDCsHandle.elementCount() > 0) { for (int i = 0; i<numTransforms; ++i) { jointParentIndices[i] = parentIDCsHandle.inputValue().asInt(); parentIDCsHandle.next(); } } MArrayDataHandle jointNamesHandle = block.inputArrayValue(jointNames); // tell block what we want std::vector<std::string> jointNames(numTransforms); if (jointNamesHandle.elementCount() > 0) { for (int i = 0; i<numTransforms; ++i) { jointNames[i] = jointNamesHandle.inputValue().asString().asChar(); jointNamesHandle.next(); } } // debug //std::cout << "got joint hierarchy info! it's:" << std::endl; //for (int i = 0; i < numTransforms; ++i) { // std::cout << i << ": " << jointNames[i].c_str() << " : " << jointParentIndices[i] << std::endl; //} std::cout << "rebuilding HRBFs... " << std::endl; hrbfMan->buildHRBFs(jointParentIndices, jointNames, bindTFs, boneTFs, weightListHandle, iter, weights); std::cout << "done rebuilding!" << std::endl; weightListHandle.jumpToElement(0); // reset this, it's an iterator. trust me. iter.reset(); // reset this iterator so we can go do normal skinning } // perform traditional skinning if (useDQNow != 0) { returnStatus = skinDQ(transforms, numTransforms, weightListHandle, iter); } else { returnStatus = skinLB(transforms, numTransforms, weightListHandle, iter); } // do HRBF corrections if (useHRBFnow != 0) { if (hrbfMan->m_HRBFs.size() == numTransforms) { hrbfMan->compose(boneTFs); iter.reset(); hrbfMan->correct(iter); } } return returnStatus; }
MStatus snapDeformer::deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex) { MStatus stat; //lets see if we need to do anything MDataHandle DataHandle = data.inputValue(envelope, &stat); float env = DataHandle.asFloat(); if (env == 0) return stat; DataHandle = data.inputValue(weight, &stat); const float weight = DataHandle.asFloat(); if (weight == 0) return stat; env = (env*weight); //space target DataHandle = data.inputValue(space, &stat); int SpaceInt = DataHandle.asInt(); //space source DataHandle = data.inputValue(spaceSource, &stat); int SpaceSourceInt = DataHandle.asInt(); //pointlist MArrayDataHandle pointArrayHandle = data.inputArrayValue(pointList); //snapMesh MFnMesh SnapMesh; DataHandle = data.inputValue(snapMesh, &stat); if (!stat) return Err(stat,"Can't get mesh to snap to"); MObject SnapMeshObj = DataHandle.asMesh(); SnapMesh.setObject(SnapMeshObj); MPointArray snapPoints; if (SpaceSourceInt==0) SnapMesh.getPoints(snapPoints, MSpace::kWorld); else SnapMesh.getPoints(snapPoints, MSpace::kObject); iter.reset(); for ( ; !iter.isDone(); iter.next()) { //check for painted weights float currEnv = env * weightValue(data, multiIndex, iter.index()); //get point to snap to unsigned int index; stat = pointArrayHandle.jumpToElement(iter.index()); if (!stat) index = 0; else { DataHandle = pointArrayHandle.outputValue(); index = DataHandle.asInt(); } if (index != -1) { //calc point location MPoint currPoint; if (snapPoints.length() > index) currPoint = snapPoints[index]; if (SpaceInt == 0) currPoint *= mat.inverse(); if (currEnv !=1) { MPoint p = (currPoint- iter.position()); currPoint = iter.position() + (p*currEnv); } //set point location iter.setPosition(currPoint); } } return stat; }
void TestDeformer::_deform_on_one_mesh(MDataBlock& data, MItGeometry& iter, const MMatrix& localToWorldMatrix, unsigned int mIndex, MObject &driver_mesh, const MDataHandle &envelopeHandle, MArrayDataHandle &vertMapArrayData, MPointArray &tempOutputPts) { MStatus status; float env = envelopeHandle.asFloat(); // use driver_meshVertIter to walk through the vertex of the current driver mesh MItMeshVertex driver_meshVertIter( driver_mesh, &status ); CHECK_MSTATUS( status ); int i = 0; iter.reset(); while( !iter.isDone(&status) ) { CHECK_MSTATUS( status ); // get the weight float weight = weightValue( data, mIndex, iter.index() ); //painted weight float ww = weight * env; if ( fabs(ww) > FLT_EPSILON )//if ( ww != 0 ) { __debug("%s(), vertMapArrayData.elementCount()=%d, iter.index()=%d", __FUNCTION__, vertMapArrayData.elementCount(), iter.index()); // get index_mapped to which the currrent vertex vI is mapped CHECK_MSTATUS(vertMapArrayData.jumpToElement(iter.index())); int index_mapped = vertMapArrayData.inputValue(&status).asInt(); CHECK_MSTATUS( status ); if( index_mapped >= 0 ) { __debug("index_mapped=%d", index_mapped); int prevInt; CHECK_MSTATUS( driver_meshVertIter.setIndex(index_mapped, prevInt) ); // vertex wrold position on driver mesh MPoint mappedPt = driver_meshVertIter.position( MSpace::kWorld, &status ); CHECK_MSTATUS( status ); // vertex wrold position on driven mesh MPoint iterPt = iter.position(MSpace::kObject, &status) * localToWorldMatrix; CHECK_MSTATUS( status ); // use ww to interpolate between mappedPt and iterPt MPoint pt = iterPt + ((mappedPt - iterPt) * ww ); pt = pt * localToWorldMatrix.inverse(); /// put the deform points to tempOutputPts tempOutputPts[i] += pt; } }//if CHECK_MSTATUS(iter.next()); ++i; }//while }
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 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; }
/*! * Description: Deform the point using the Sederberg-Parry FFD algorithm. * * Arguments: * block : the datablock of the node * iter : an iterator for the geometry to be deformed * m : matrix to transform the point into world space * multiIndex : the index of the geometry that we are deforming */ MStatus ffdPlanar::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& /*m*/, unsigned int multiIndex ) { MStatus status = MS::kSuccess; // Determine the displacement lattice points. MDataHandle row1Data = block.inputValue( latticeRow1, &status ); MCheckErr( status, "Error getting r1 data handle\n" ); MVector row1Vector = row1Data.asVector(); MDataHandle row2Data = block.inputValue( latticeRow2, &status ); MCheckErr( status, "Error getting r2 data handle\n" ); MVector row2Vector = row2Data.asVector(); MDataHandle row3Data = block.inputValue( latticeRow3, &status ); MCheckErr( status, "Error getting r3 data\n" ); MVector row3Vector = row3Data.asVector(); // Determine the envelope (this is a global scale factor for the deformer). MDataHandle envData = block.inputValue(envelope,&status); MCheckErr(status, "Error getting envelope data handle\n"); float env = envData.asFloat(); // Generate the FFD lattice. MVector lattice[FFD_LATTICE_POINTS_S][FFD_LATTICE_POINTS_T][FFD_LATTICE_POINTS_U] = { // Since dimensions known ahead of time, generate array now. { // x = 0 { MVector(0.f, row1Vector.x, 0.f), MVector(0.f, row1Vector.y, .5f), MVector(0.f, row1Vector.z, 1.f) }, // y = 0 }, { // x = 1 { MVector(.5f, row2Vector.x, 0.f), MVector(.5f, row2Vector.y, .5f), MVector(.5f, row2Vector.z, 1.f) }, // y = 0 }, { // x = 2 { MVector(1.f, row3Vector.x, 0.f), MVector(1.f, row3Vector.y, .5f), MVector(1.f, row3Vector.z, 1.f) }, // y = 0 } }; MBoundingBox boundingBox; status = getBoundingBox( block, multiIndex, boundingBox ); MCheckErr( status, "Error getting bounding box\n" ); MTransformationMatrix transform = getXyzToStuTransformation( boundingBox ); MMatrix transformMatrix = transform.asMatrix(); MMatrix inverseMatrix = transform.asMatrixInverse(); // Iterate through each point in the geometry. for ( ; !iter.isDone(); iter.next() ) { MPoint pt = iter.position(); MPoint ptStu = pt * transformMatrix; MPoint deformed = getDeformedPoint( ptStu, lattice ) * inverseMatrix; if ( env != 1.f ) { MVector diff = deformed - pt; deformed = pt + env * diff; } iter.setPosition( deformed ); } return status; }
/* 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; }