MStatus inverseSkinCluster::deform(MDataBlock& data, MItGeometry& itGeo, const MMatrix& localToWorldMatrix, unsigned int geomIndex) { MStatus status; MMatrix geomMatrix; bool updateSkinInfo; MDataHandle hInMesh = data.inputValue( aInMesh, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MObject oInMesh = hInMesh.asMesh(); if( oInMesh.isNull() ) return MS::kFailure; MFnMesh inMesh = oInMesh; inMesh.getPoints( m_meshPoints ); if( originalMeshUpdated ) { itGeo.allPositions( pTaskData->basePoints ); originalMeshUpdated = false; } MDataHandle hGeomMatrix = data.inputValue( aGeomMatrix ); geomMatrix = hGeomMatrix.asMatrix(); MDataHandle hUpdateWeightList = data.inputValue( aUpdateWeightList ); updateSkinInfo = hUpdateWeightList.asBool(); MDataHandle hEnvelop = data.inputValue( envelope ); envelopValue = hEnvelop.asFloat(); pTaskData->envelop = envelopValue; pTaskData->invEnv = 1.0f - envelopValue; pTaskData->beforePoints = m_meshPoints; if( updateSkinInfo ) { MDataHandle hUpdateSkinInfoOutput = data.outputValue( aUpdateWeightList ); hUpdateSkinInfoOutput.set( false ); weightListUpdated = false; } if( logicalIndexArray.length() == 0 ) updateLogicalIndexArray(); MDataHandle hUpdateMatrix = data.inputValue( aUpdateMatrix ); if( hUpdateMatrix.asBool() ) { matrixAttrUpdated = false; matrixInfoUpdated = false; } MArrayDataHandle hArrMatrix = data.inputArrayValue( aMatrix ); MArrayDataHandle hArrBindPreMatrix = data.inputArrayValue( aBindPreMatrix ); updateMatrixAttribute( hArrMatrix, hArrBindPreMatrix ); if( !matrixInfoUpdated ) { updateMatrixInfo( hArrMatrix, hArrBindPreMatrix ); } if( !weightListUpdated ) { pTaskData->afterPoints.setLength( m_meshPoints.length() ); pTaskData->envPoints.setLength( m_meshPoints.length() ); updateWeightList(); } if( !matrixInfoUpdated || !weightListUpdated ) { if( pSkinInfo->weightsArray.size() > 0 ) getWeightedMatrices( geomMatrix ); else return MS::kFailure; matrixInfoUpdated = true; weightListUpdated = true; } if( envelopValue ) { setThread(); MThreadPool::newParallelRegion( parallelCompute, pThread ); endThread(); itGeo.setAllPositions( pTaskData->envPoints ); } else { itGeo.setAllPositions( pTaskData->basePoints ); } return MS::kSuccess; }
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; }
// 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 inSpecular::compute( const MPlug& plug, MDataBlock& block ) { // The plug parameter will allow us to determine which output attribute // needs to be calculated. // if( plug == aOutColor || plug == aOutTransparency || plug.parent() == aOutColor || plug.parent() == aOutTransparency ) { MStatus status; MFloatVector resultColor( 0.0, 0.0, 0.0 ); // Get surface shading parameters from input block // MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector(); CHECK_MSTATUS( status ); MFloatVector& surfaceColor = block.inputValue( aColor, &status ).asFloatVector(); CHECK_MSTATUS( status ); MFloatVector& incandescence = block.inputValue( aIncandescence, &status ).asFloatVector(); CHECK_MSTATUS( status ); float diffuseReflectivity = block.inputValue( aDiffuseReflectivity, &status ).asFloat(); CHECK_MSTATUS( status ); // float translucenceCoeff = block.inputValue( aTranslucenceCoeff, // &status ).asFloat(); // CHECK_MSTATUS( status ); // Get light list // MArrayDataHandle lightData = block.inputArrayValue( aLightData, &status ); CHECK_MSTATUS( status ); int numLights = lightData.elementCount( &status ); CHECK_MSTATUS( status ); // Calculate the effect of the lights in the scene on the color // // Iterate through light list and get ambient/diffuse values // for( int count=1; count <= numLights; count++ ) { // Get the current light out of the array // MDataHandle currentLight = lightData.inputValue( &status ); CHECK_MSTATUS( status ); // Get the intensity of that light // MFloatVector& lightIntensity = currentLight.child( aLightIntensity ).asFloatVector(); // Find ambient component // if ( currentLight.child( aLightAmbient ).asBool() ) { resultColor += lightIntensity; } // Find diffuse component // if ( currentLight.child( aLightDiffuse ).asBool() ) { MFloatVector& lightDirection = currentLight.child( aLightDirection ).asFloatVector(); float cosln = lightDirection * surfaceNormal; if ( cosln > 0.0f ) { resultColor += lightIntensity * ( cosln * diffuseReflectivity ); } } // Advance to the next light. // if ( count < numLights ) { status = lightData.next(); CHECK_MSTATUS( status ); } } // Factor incident light with surface color and add incandescence // resultColor[0] = resultColor[0] * surfaceColor[0] + incandescence[0]; resultColor[1] = resultColor[1] * surfaceColor[1] + incandescence[1]; resultColor[2] = resultColor[2] * surfaceColor[2] + incandescence[2]; // Set ouput color attribute // if ( plug == aOutColor || plug.parent() == aOutColor ) { // Get the handle to the attribute // MDataHandle outColorHandle = block.outputValue( aOutColor, &status ); CHECK_MSTATUS( status ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; // Set the output value outColorHandle.setClean(); // Mark the output value as clean } // Set ouput transparency // if ( plug == aOutTransparency || plug.parent() == aOutTransparency ) { MFloatVector& transparency = block.inputValue( aInTransparency, &status ).asFloatVector(); CHECK_MSTATUS( status ); // Get the handle to the attribute // MDataHandle outTransHandle = block.outputValue( aOutTransparency, &status ); CHECK_MSTATUS( status ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = transparency; // Set the output value outTransHandle.setClean(); // Mark the output value as clean } } else { return( MS::kUnknownParameter ); // We got an unexpected plug } return( MS::kSuccess ); }
MStatus liqSurfaceNode::compute( const MPlug& plug, MDataBlock& block ) { //CM_TRACE_FUNC("liqSurfaceNode::compute(job="<<plug.name()<<",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& 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 ) ) cColor = 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 * cColor; } } 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] *= cColor[0]; resultColor[1] *= cColor[1]; resultColor[2] *= cColor[2]; } resultTrans[0] = ( 1.0 - resultTrans[0] ); resultTrans[1] = ( 1.0 - resultTrans[1] ); resultTrans[2] = ( 1.0 - 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 OnbShader::compute(const MPlug& plug, MDataBlock& block) { // Sanity check if (plug != aOutColor && plug.parent() != aOutColor && plug != aOutTransparency && plug.parent() != aOutTransparency) { return MS::kUnknownParameter; } // Note that this currently only implements the diffuse portion of the // shader and ignores specular. The diffuse portion is the Oren-Nayar // computation from: // Engel, Wolfgang et al. Programming Vertex, Geometry, and Pixel Shaders // http://content.gpwiki.org/index.php/D3DBook:(Lighting)_Oren-Nayar // Further extensions could be added to this compute method to include // the intended Blinn specular component as well as ambient and // incandescence components. // See the VP2 fragment-based implementation in onbShaderOverride for the // full shader. MStatus status; MFloatVector resultColor(0.0f, 0.0f, 0.0f); MFloatVector resultTransparency(0.0f, 0.0f, 0.0f); // Get surface shading parameters from input block const MFloatVector& surfaceColor = block.inputValue(aColor, &status).asFloatVector(); CHECK_MSTATUS(status); const float roughness = block.inputValue(aRoughness, &status).asFloat(); CHECK_MSTATUS(status); const MFloatVector& transparency = block.inputValue(aTransparency, &status).asFloatVector(); CHECK_MSTATUS(status); const MFloatVector& surfaceNormal = block.inputValue(aNormalCamera, &status).asFloatVector(); CHECK_MSTATUS(status); const MFloatVector& rayDirection = block.inputValue(aRayDirection).asFloatVector(); const MFloatVector viewDirection = -rayDirection; // Pre-compute some values that do not vary with lights const float NV = viewDirection*surfaceNormal; const float acosNV = acosf(NV); const float roughnessSq = roughness*roughness; const float A = 1.0f - 0.5f*(roughnessSq/(roughnessSq + 0.57f)); const float B = 0.45f*(roughnessSq/(roughnessSq + 0.09f)); // Get light list MArrayDataHandle lightData = block.inputArrayValue(aLightData, &status); CHECK_MSTATUS(status); const int numLights = lightData.elementCount(&status); CHECK_MSTATUS(status); // Iterate through light list and get ambient/diffuse values for (int count=1; count<=numLights; count++) { // Get the current light MDataHandle currentLight = lightData.inputValue(&status); CHECK_MSTATUS(status); // Find diffuse component if (currentLight.child(aLightDiffuse).asBool()) { // Get the intensity and direction of that light const MFloatVector& lightIntensity = currentLight.child(aLightIntensity).asFloatVector(); const MFloatVector& lightDirection = currentLight.child(aLightDirection).asFloatVector(); // Compute the diffuse factor const float NL = lightDirection*surfaceNormal; const float acosNL = acosf(NL); const float alpha = std::max(acosNV, acosNL); const float beta = std::min(acosNV, acosNL); const float gamma = (viewDirection - (surfaceNormal*NV)) * (lightDirection - (surfaceNormal*NL)); const float C = sinf(alpha)*tanf(beta); const float factor = std::max(0.0f, NL)*(A + B*std::max(0.0f, gamma)*C); // Add to result color resultColor += lightIntensity*factor; } // Advance to the next light. if (count < numLights) { status = lightData.next(); CHECK_MSTATUS(status); } } // Factor incident light with surface color resultColor[0] = resultColor[0]*surfaceColor[0]; resultColor[1] = resultColor[1]*surfaceColor[1]; resultColor[2] = resultColor[2]*surfaceColor[2]; // Set ouput color attribute if (plug == aOutColor || plug.parent() == aOutColor) { // Get the handle to the attribute MDataHandle outColorHandle = block.outputValue(aOutColor, &status); CHECK_MSTATUS(status); MFloatVector& outColor = outColorHandle.asFloatVector(); // Set the result and mark it clean outColor = resultColor; outColorHandle.setClean(); } // Set ouput transparency if (plug == aOutTransparency || plug.parent() == aOutTransparency) { // Get the handle to the attribute MDataHandle outTransHandle = block.outputValue(aOutTransparency, &status); CHECK_MSTATUS(status); MFloatVector& outTrans = outTransHandle.asFloatVector(); // Set the result and mark it clean outTrans = transparency; outTransHandle.setClean(); } return MS::kSuccess; }
//----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- MStatus CVstWeldNode::compute( const MPlug &mPlug, MDataBlock &mDataBlock ) { if ( mPlug == m_oaWeldOutput || mPlug == m_oaTranslate || mPlug == m_oaRotate || mPlug == m_oaTranslateX || mPlug == m_oaTranslateY || mPlug == m_oaTranslateZ || mPlug == m_oaRotateX || mPlug == m_oaRotateY || mPlug == m_oaRotateZ ) { const MObject geoObj = mDataBlock.inputValue( m_iaWorldGeometry ).data(); if ( geoObj.apiType() == MFn::kMeshData ) { MStatus mStatus; MObject meshObj = mDataBlock.inputValue( m_iaWorldGeometry ).asMeshTransformed(); MFnMesh meshFn( meshObj ); MItMeshPolygon pIt( meshObj ); MPointArray facePoints; MArrayDataHandle wiAH = mDataBlock.inputArrayValue( m_iaWeldInput ); MArrayDataHandle woAH = mDataBlock.outputArrayValue( m_oaWeldOutput, &mStatus ); MArrayDataBuilder woADB = woAH.builder( &mStatus ); const int nWeldCount = wiAH.elementCount(); for ( int i = 0; i < nWeldCount; ++i, wiAH.next() ) { MDataHandle wiDH = wiAH.inputValue(); const MMatrix &offsetMatrix = wiDH.child( m_iaOffsetMatrix ).asMatrix(); const MMatrix &inverseParentSpace = wiDH.child( m_iaInverseParentSpace ).asMatrix(); const MEulerRotation::RotationOrder rotationOrder = static_cast< MEulerRotation::RotationOrder >( wiDH.child( m_iaRotateOrder ).asShort() ); MMatrix geoMatrix; switch ( wiDH.child( m_iaType ).asShort() ) { case kMeshFace: { const int nMeshFaceIndex = wiDH.child( m_iaInt ).asInt(); GetMeshMatrix( pIt, nMeshFaceIndex, geoMatrix ); } break; default: merr << "Unknown Weld Type " << wiDH.child( m_iaType ).asShort() << std::endl; break; } const int nWeldIndex = wiAH.elementIndex(); MDataHandle woDH = woADB.addElement( nWeldIndex ); MTransformationMatrix L( inverseParentSpace * offsetMatrix * geoMatrix ); woDH.child( m_oaTranslate ).set( L.getTranslation( MSpace::kWorld ) ); MEulerRotation e = L.rotation().asEulerRotation(); e.reorder( rotationOrder ); woDH.child( m_oaRotate ).set( e.asVector() ); } } else { merr << "Invalid .inputGeometry data of type: " << geoObj.apiTypeStr() << " found while computing " << mPlug.info() << std::endl; return MS::kFailure; } return MS::kSuccess; } return MS::kUnknownParameter; }
MStatus ropeGenerator::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if ( plug == outMesh ) { //Get Curve MDataHandle inCurve_Hdl = data.inputValue( inCurve, &status ); if (status != MS::kSuccess ){ MGlobal::displayError( "Node ropeGenerator needs an Input Curve" ); return MS::kSuccess; } MObject inCurveObj = inCurve_Hdl.asNurbsCurve(); MFnNurbsCurve curveFn( inCurveObj ); //Get Attributes int inDiv = data.inputValue( divisions ).asInt(); bool inCreateRope = data.inputValue( createRope ).asBool(); int inRopesCount = data.inputValue( ropesCount ).asInt(); int inPointsPerRope = data.inputValue( pointsPerRope ).asInt(); int inPointsCount = data.inputValue( pointsCount ).asInt(); float inRopesStrength = data.inputValue( ropesStrength ).asFloat(); float inRadius = data.inputValue( radius ).asFloat(); MRampAttribute inRadRamp( thisMObject(), taperRamp ); float inTwist = data.inputValue( twist ).asFloat(); MRampAttribute inTwistRamp( thisMObject(), twistRamp ); float inUvWidth = data.inputValue( uvWidth ).asFloat(); float inUvHeight = data.inputValue( uvHeight ).asFloat(); float inUvCapSize = data.inputValue( uvCapSize ).asFloat(); MFnMesh fnMesh; MFnMeshData dataCreator; MObject outMeshData; outMeshData = dataCreator.create(); MDataHandle outputHandle = data.outputValue(outMesh); //createBase MIntArray faceCounts, faceConnects, uvIds; MFloatArray uArray, vArray; MFloatPointArray points; faceCounts.clear(); faceConnects.clear(); points.clear(); if (inCreateRope) inPointsCount = ( inPointsPerRope + 2 ) * inRopesCount; int numVertices = ( inDiv + 1 ) * inPointsCount; int numFaces = ( inPointsCount * inDiv ) + 2; float param; float lengPerDiv = curveFn.length() / inDiv; PrevNormal = MVector( curveFn.normal( 0.0, MSpace::kWorld ).normal() ); float baseLeng = lengPerDiv; float baseParamForRamp = 0; float paramForRamp = 1.0 / float( inDiv ); float uDivNumber = inUvWidth / float( inPointsCount ); float vDivNumber = inUvHeight / float( inDiv ); for (int d = 0; d < inDiv + 1; d++) { if (d == 0) { param = 0; faceCounts.append( inPointsCount ); for ( int i = inPointsCount - 1; i >= 0; i-- ) { faceConnects.append( i ); } for ( int i = 0; i < inPointsCount; i++ ) { uvIds.append( i ); } MFloatArray uTmpArray, vTmpArray; if (inCreateRope) createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, 1.0 ); else createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, 1.0 ); for ( int u = uTmpArray.length() - 1; u >= 0 ; u-- ) { uArray.append( uTmpArray[u] + 1.0 ); vArray.append( vTmpArray[u] ); } for ( int i = 0; i < inPointsCount + 1; i++ ) { uArray.append( uDivNumber * float( i ) ); vArray.append( vDivNumber * float( d ) ); } }else{ param = curveFn.findParamFromLength( baseLeng ); for ( int i = 0; i < inPointsCount + 1; i++ ) { uArray.append( uDivNumber * float( i ) ); vArray.append( vDivNumber * float( d ) ); } for ( int f = 0; f < inPointsCount; f++ ) { faceCounts.append( 4 ); if( f == ( inPointsCount - 1 )) { faceConnects.append( ( f + 1 + ( d * inPointsCount ) ) - inPointsCount - inPointsCount ); faceConnects.append( ( f + 1 + ( d * inPointsCount ) - inPointsCount ) ); faceConnects.append( f + 1 + ( d * inPointsCount ) - 1 ); faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount - 1 ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f); }else{ faceConnects.append( ( f + ( d * inPointsCount ) ) - inPointsCount ); faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount ); faceConnects.append( f + 1 + ( d * inPointsCount ) ); faceConnects.append( ( f + ( d * inPointsCount )) ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f); } } if ( d == inDiv ) { faceCounts.append( inPointsCount ); for ( int i = 0; i < inPointsCount; i++ ) { faceConnects.append( ( inPointsCount * inDiv ) + i ); uvIds.append( ( inPointsCount * ( inDiv + 2)) + i + inDiv + 1 ); } MFloatArray uTmpArray, vTmpArray; if (inCreateRope) createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, -1.0 ); else createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, -1.0 ); for ( int u = 0; u < uTmpArray.length(); u++ ) { uArray.append( uTmpArray[u] + 2.0 ); vArray.append( vTmpArray[u] ); } } baseLeng += lengPerDiv; } float divTwist; inTwistRamp.getValueAtPosition( baseParamForRamp, divTwist ); float divTaper; inRadRamp.getValueAtPosition( baseParamForRamp, divTaper ); baseParamForRamp += paramForRamp; if (inCreateRope) createRopesRings( inRopesCount, getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ), points, inPointsPerRope, inRopesStrength, inRadius * divTaper); else createCriclePoints( inPointsCount, getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ), points, inRadius * divTaper ); } fnMesh.create( numVertices, numFaces, points, faceCounts, faceConnects, uArray, vArray, outMeshData ); fnMesh.assignUVs( faceCounts, uvIds ); outputHandle.set(outMeshData); outputHandle.setClean(); } return MS::kSuccess; }
MStatus MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; // 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 == a_output ) { bool createdSubdMesh = false; int subdivisionLevel = data.inputValue(a_subdivisionLevels).asInt(); short stateH = data.inputValue(state).asShort(); if ((subdivisionLevel > 0) and (stateH !=1)) { // == Retrieve input mesh ==================================== // Get attr values MObject inMeshObj = data.inputValue(a_inputPolymesh).asMesh(); short vertBoundaryMethod = data.inputValue(a_vertBoundaryMethod).asShort(); short fvarBoundaryMethod = data.inputValue(a_fvarBoundaryMethod).asShort(); bool fvarPropCorners = data.inputValue(a_fvarPropagateCorners).asBool(); bool smoothTriangles = data.inputValue(a_smoothTriangles).asBool(); short creaseMethodVal = data.inputValue(a_creaseMethod).asShort(); // == Get Mesh Functions and Iterators ========================== MFnMeshData inMeshDat(inMeshObj); MFnMesh inMeshFn(inMeshObj, &status); MCHECKERR(status, "ERROR getting inMeshFn\n"); MItMeshPolygon inMeshItPolygon(inMeshObj, &status); MCHECKERR(status, "ERROR getting inMeshItPolygon\n"); // Convert attr values to OSD enums OpenSubdiv::Sdc::SchemeType type = OpenSubdiv::Sdc::SCHEME_CATMARK; // // Create Far topology // OpenSubdiv::Sdc::Options options; options.SetVtxBoundaryInterpolation(ConvertMayaVtxBoundary(vertBoundaryMethod)); options.SetFVarLinearInterpolation(ConvertMayaFVarBoundary(fvarBoundaryMethod, fvarPropCorners)); options.SetCreasingMethod(creaseMethodVal ? OpenSubdiv::Sdc::Options::CREASE_CHAIKIN : OpenSubdiv::Sdc::Options::CREASE_UNIFORM); options.SetTriangleSubdivision(smoothTriangles ? OpenSubdiv::Sdc::Options::TRI_SUB_SMOOTH : OpenSubdiv::Sdc::Options::TRI_SUB_CATMARK); float maxCreaseSharpness=0.0f; OpenSubdiv::Far::TopologyRefiner * refiner = gatherTopology(inMeshFn, inMeshItPolygon, type, options, &maxCreaseSharpness); assert(refiner); // Refine & Interpolate refiner->RefineUniform(OpenSubdiv::Far::TopologyRefiner::UniformOptions(subdivisionLevel)); Vertex const * controlVerts = reinterpret_cast<Vertex const *>(inMeshFn.getRawPoints(&status)); std::vector<Vertex> refinedVerts( refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices()); Vertex const * srcVerts = controlVerts; Vertex * dstVerts = &refinedVerts[0]; for (int level = 1; level <= subdivisionLevel; ++level) { OpenSubdiv::Far::PrimvarRefiner(*refiner).Interpolate(level, srcVerts, dstVerts); srcVerts = dstVerts; dstVerts += refiner->GetLevel(level).GetNumVertices(); } // == Convert subdivided OpenSubdiv mesh to MFnMesh Data outputMesh ============= // Create New Mesh Data Object MFnMeshData newMeshData; MObject newMeshDataObj = newMeshData.create(&status); MCHECKERR(status, "ERROR creating outputData"); // Create out mesh status = convertToMayaMeshData(*refiner, refinedVerts, inMeshFn, newMeshDataObj); MCHECKERR(status, "ERROR convertOsdFarToMayaMesh"); // Propagate objectGroups from inMesh to outMesh (for per-facet shading, etc) status = createSmoothMesh_objectGroups(inMeshFn, inMeshDat, newMeshData, subdivisionLevel, refiner->GetLevel(subdivisionLevel).GetNumFaces()); // Write to output plug MDataHandle outMeshH = data.outputValue(a_output, &status); MCHECKERR(status, "ERROR getting polygon data handle\n"); outMeshH.set(newMeshDataObj); int isolation = std::min(10,(int)ceil(maxCreaseSharpness)+1); data.outputValue(a_recommendedIsolation).set(isolation); // == Cleanup OSD ============================================ // REVISIT: Re-add these deletes delete refiner; // note that the subd mesh was created (see the section below if !createdSubdMesh) createdSubdMesh = true; } // Pass-through inMesh to outMesh if not created the subd mesh if (!createdSubdMesh) { MDataHandle outMeshH = data.outputValue(a_output, &status); status = outMeshH.copy(data.outputValue(a_inputPolymesh, &status)); MCHECKERR(status, "ERROR getting polygon data handle\n"); } // Clean up Maya Plugs data.setClean(plug); } else { // Unhandled parameter in this compute function, so return MS::kUnknownParameter // so it is handled in a parent compute() function. return MS::kUnknownParameter; } return MS::kSuccess; }
// COMPUTE ====================================== MStatus gear_rollSplineKine::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; // Error check if (plug != output) return MS::kUnknownParameter; // Get inputs matrices ------------------------------ // Inputs Parent MArrayDataHandle adh = data.inputArrayValue( ctlParent ); int count = adh.elementCount(); if (count < 1) return MS::kFailure; MMatrixArray inputsP(count); for (int i = 0 ; i < count ; i++){ adh.jumpToElement(i); inputsP[i] = adh.inputValue().asMatrix(); } // Inputs adh = data.inputArrayValue( inputs ); if (count != adh.elementCount()) return MS::kFailure; MMatrixArray inputs(count); for (int i = 0 ; i < count ; i++){ adh.jumpToElement(i); inputs[i] = adh.inputValue().asMatrix(); } adh = data.inputArrayValue( inputsRoll ); if (count != adh.elementCount()) return MS::kFailure; MDoubleArray roll(adh.elementCount()); for (int i = 0 ; i < count ; i++){ adh.jumpToElement(i); roll[i] = degrees2radians((double)adh.inputValue().asFloat()); } // Output Parent MDataHandle ha = data.inputValue( outputParent ); MMatrix outputParent = ha.asMatrix(); // Get inputs sliders ------------------------------- double in_u = (double)data.inputValue( u ).asFloat(); bool in_resample = data.inputValue( resample ).asBool(); int in_subdiv = data.inputValue( subdiv ).asShort(); bool in_absolute = data.inputValue( absolute ).asBool(); // Process ------------------------------------------ // Get roll, pos, tan, rot, scl MVectorArray pos(count); MVectorArray tan(count); MQuaternion *rot; rot = new MQuaternion[count]; MVectorArray scl(count); double threeDoubles[3]; for (int i = 0 ; i < count ; i++){ MTransformationMatrix tp(inputsP[i]); MTransformationMatrix t(inputs[i]); pos[i] = t.getTranslation(MSpace::kWorld); rot[i] = tp.rotation(); t.getScale(threeDoubles, MSpace::kWorld); scl[i] = MVector(threeDoubles[0], threeDoubles[1], threeDoubles[2]); tan[i] = MVector(threeDoubles[0] * 2.5, 0, 0).rotateBy(t.rotation()); } // Get step and indexes // We define between wich controlers the object is to be able to // calculate the bezier 4 points front this 2 objects double step = 1.0 / max( 1, count-1.0 ); int index1 = (int)min( count-2.0, in_u/step ); int index2 = index1+1; int index1temp = index1; int index2temp = index2; double v = (in_u - step * double(index1)) / step; double vtemp = v; // calculate the bezier MVector bezierPos; MVector xAxis, yAxis, zAxis; if(!in_resample){ // straight bezier solve MVectorArray results = bezier4point(pos[index1],tan[index1],pos[index2],tan[index2],v); bezierPos = results[0]; xAxis = results[1]; } else if(!in_absolute){ MVectorArray presample(in_subdiv); MVectorArray presampletan(in_subdiv); MDoubleArray samplelen(in_subdiv); double samplestep = 1.0 / double(in_subdiv-1); double sampleu = samplestep; presample[0] = pos[index1]; presampletan[0] = tan[index1]; MVector prevsample(presample[0]); MVector diff; samplelen[0] = 0; double overalllen = 0; MVectorArray results(2); for(long i=1;i<in_subdiv;i++,sampleu+=samplestep){ results = bezier4point(pos[index1],tan[index1],pos[index2],tan[index2],sampleu); presample[i] = results[0]; presampletan[i] = results[1]; diff = presample[i] - prevsample; overalllen += diff.length(); samplelen[i] = overalllen; prevsample = presample[i]; } // now as we have the sampleu = 0; for(long i=0;i<in_subdiv-1;i++,sampleu+=samplestep){ samplelen[i+1] = samplelen[i+1] / overalllen; if(v>=samplelen[i] && v <= samplelen[i+1]){ v = (v - samplelen[i]) / (samplelen[i+1] - samplelen[i]); bezierPos = linearInterpolate(presample[i],presample[i+1],v); xAxis = linearInterpolate(presampletan[i],presampletan[i+1],v); break; } } } else{ MVectorArray presample(in_subdiv); MVectorArray presampletan(in_subdiv); MDoubleArray samplelen(in_subdiv); double samplestep = 1.0 / double(in_subdiv-1); double sampleu = samplestep; presample[0] = pos[0]; presampletan[0] = tan[0]; MVector prevsample(presample[0]); MVector diff; samplelen[0] = 0; double overalllen = 0; MVectorArray results; for(long i=1;i<in_subdiv;i++,sampleu+=samplestep){ index1 = (int)min(count-2,sampleu / step); index2 = index1+1; v = (sampleu - step * double(index1)) / step; results = bezier4point(pos[index1],tan[index1],pos[index2],tan[index2],v); presample[i] = results[0]; presampletan[i] = results[1]; diff = presample[i] - prevsample; overalllen += diff.length(); samplelen[i] = overalllen; prevsample = presample[i]; } // now as we have the sampleu = 0; for(long i=0;i<in_subdiv-1;i++,sampleu+=samplestep){ samplelen[i+1] = samplelen[i+1] / overalllen; if(in_u>=samplelen[i] && in_u <= samplelen[i+1]){ in_u = (in_u - samplelen[i]) / (samplelen[i+1] - samplelen[i]); bezierPos = linearInterpolate(presample[i],presample[i+1],in_u); xAxis = linearInterpolate(presampletan[i],presampletan[i+1],in_u); break; } } } // compute the scaling (straight interpolation!) MVector scl1 = linearInterpolate(scl[index1temp], scl[index2temp],vtemp); // compute the rotation! MQuaternion q = slerp(rot[index1temp], rot[index2temp], vtemp); yAxis = MVector(0,1,0); yAxis = yAxis.rotateBy(q); // use directly or project the roll values! // print roll double a = linearInterpolate(roll[index1temp], roll[index2temp], vtemp); yAxis = yAxis.rotateBy( MQuaternion(xAxis.x * sin(a/2.0), xAxis.y * sin(a/2.0), xAxis.z * sin(a/2.0), cos(a/2.0))); zAxis = xAxis ^ yAxis; zAxis.normalize(); yAxis = zAxis ^ xAxis; yAxis.normalize(); // Output ------------------------------------------- MTransformationMatrix result; // translation result.setTranslation(bezierPos, MSpace::kWorld); // rotation q = getQuaternionFromAxes(xAxis,yAxis,zAxis); result.setRotationQuaternion(q.x, q.y, q.z, q.w); // scaling threeDoubles[0] = 1; threeDoubles[0] = scl1.y; threeDoubles[0] = scl1.z; result.setScale(threeDoubles, MSpace::kWorld); MDataHandle h = data.outputValue( output ); h.setMMatrix( result.asMatrix() * outputParent.inverse() ); data.setClean( plug ); return MS::kSuccess; }
MStatus finalproject::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; } MDataHandle offloadData = data.inputValue(offload, &status); //gathers world space positions of the object and the magnet MObject dSurf = deformData.asMeshTransformed(); MObject iSurf = inputData.asMeshTransformed(); MFnMesh fnDeformingMesh, fnInputMesh; fnDeformingMesh.setObject( dSurf ) ; fnInputMesh.setObject( iSurf ) ; 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); // get all points at once. Faster to query, and also better for // threading than using iterator MPointArray objVerts; iter.allPositions(objVerts); int objNumPoints = objVerts.length(); MPointArray magVerts, tempverts; fnDeformingMesh.getPoints(magVerts); fnInputMesh.getPoints(tempverts); int magNumPoints = magVerts.length(); double min = DBL_MAX, max = -DBL_MAX; //finds min and max z-coordinate values to determine middle point (choice of z-axis was ours) for (int i = 0; i < magNumPoints; i++) { min = magVerts[i].z < min ? magVerts[i].z : min; max = magVerts[i].z > max ? magVerts[i].z : max; } double middle = (min + max) / 2; double polarity[magNumPoints]; //assigns polarity based on middle point of mesh for (int i = 0; i < magNumPoints; i++) { polarity[i] = magVerts[i].z > middle ? max / magVerts[i].z : -min / magVerts[i].z; } double* objdVerts = (double *)malloc(sizeof(double) * objNumPoints * 3); double* magdVerts = (double *)malloc(sizeof(double) * magNumPoints * 3); //creates handles to use attribute data MDataHandle vecX = data.inputValue(transX, &status); MDataHandle vecY = data.inputValue(transY, &status); MDataHandle vecZ = data.inputValue(transZ, &status); //gathers previously stored coordinates of the center of the object double moveX = vecX.asFloat(); double moveY = vecY.asFloat(); double moveZ = vecZ.asFloat(); //translates object based on the position stored in the attribute values for (int i=0; i<objNumPoints; i++) { objdVerts[i * 3] = tempverts[i].x + moveX; objdVerts[i * 3 + 1] = tempverts[i].y + moveY; objdVerts[i * 3 + 2] = tempverts[i].z + moveZ; } for (int i=0; i<magNumPoints; i++) { magdVerts[i * 3] = magVerts[i].x; magdVerts[i * 3 + 1] = magVerts[i].y; magdVerts[i * 3 + 2] = magVerts[i].z; } double teslaData = data.inputValue(tesla, &status).asDouble(); MDataHandle posiData = data.inputValue(positivelycharged, &status); double pivot[6] = {DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX}; //finds the pivot point of the object in world space prior to being affected by the magnet for (int i = 0; i < tempverts.length(); i++) { pivot[0] = tempverts[i].x < pivot[0] ? tempverts[i].x : pivot[0]; pivot[1] = tempverts[i].x > pivot[1] ? tempverts[i].x : pivot[1]; pivot[2] = tempverts[i].y < pivot[2] ? tempverts[i].y : pivot[2]; pivot[3] = tempverts[i].y > pivot[3] ? tempverts[i].y : pivot[3]; pivot[4] = tempverts[i].z < pivot[4] ? tempverts[i].z : pivot[4]; pivot[5] = tempverts[i].z > pivot[5] ? tempverts[i].z : pivot[5]; } MTimer timer; timer.beginTimer(); //main function call magnetForce(magNumPoints, objNumPoints, teslaData, magdVerts, objdVerts, polarity, posiData.asBool(), offloadData.asBool()); timer.endTimer(); printf("Runtime for threaded loop %f\n", timer.elapsedTime()); for (int i=0; i<objNumPoints; i++) { objVerts[i].x = objdVerts[i * 3 + 0]; objVerts[i].y = objdVerts[i * 3 + 1]; objVerts[i].z = objdVerts[i * 3 + 2]; } //finds the pivot point of object in world space after being affected by the magnet double objCenter[6] = {DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX}; for (int i = 0; i < tempverts.length(); i++) { objCenter[0] = objVerts[i].x < objCenter[0] ? objVerts[i].x : objCenter[0]; objCenter[1] = objVerts[i].x > objCenter[1] ? objVerts[i].x : objCenter[1]; objCenter[2] = objVerts[i].y < objCenter[2] ? objVerts[i].y : objCenter[2]; objCenter[3] = objVerts[i].y > objCenter[3] ? objVerts[i].y : objCenter[3]; objCenter[4] = objVerts[i].z < objCenter[4] ? objVerts[i].z : objCenter[4]; objCenter[5] = objVerts[i].z > objCenter[5] ? objVerts[i].z : objCenter[5]; } //creates vector based on the two calculated pivot points moveX = (objCenter[0] + objCenter[1]) / 2 - (pivot[0] + pivot[1]) / 2; moveY = (objCenter[2] + objCenter[3]) / 2 - (pivot[2] + pivot[3]) / 2; moveZ = (objCenter[4] + objCenter[5]) / 2 - (pivot[4] + pivot[5]) / 2; //stores pivot vector for next computation if (teslaData) { vecX.setFloat(moveX); vecY.setFloat(moveY); vecZ.setFloat(moveZ); } // write values back onto output using fast set method on iterator iter.setAllPositions(objVerts, MSpace::kWorld); free(objdVerts); free(magdVerts); return status; }
MStatus fishVizNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MObject arbitaryMesh = data.inputValue(aInMesh).asMesh(); MDoubleArray ptc_time_offset; MDoubleArray ptc_amplitude; MDoubleArray ptc_bend; MDoubleArray ptc_scale; MDoubleArray masses; MString cacheName = data.inputValue(acachename, &status).asString(); MTime currentTime = data.inputValue(atime, &status).asTime(); cacheName = cacheName+"."+250*int(currentTime.value())+".pdc"; pdcFile* fpdc = new pdcFile(); if(fpdc->load(cacheName.asChar())==1) { //MGlobal::displayInfo(MString("FishViz loaded cache file: ")+cacheName); fpdc->readPositions(ptc_positions, ptc_velocities, ptc_ups, ptc_views, ptc_time_offset, ptc_amplitude, ptc_bend, ptc_scale, masses); } else MGlobal::displayWarning(MString("FishViz cannot open cache file: ")+cacheName); if(currentTime.value()!=int(currentTime.value())) { float delta_t = currentTime.value()-int(currentTime.value()); for(int i=0; i<fpdc->getParticleCount(); i++) { ptc_positions[i] += ptc_velocities[i]*delta_t/24.0f; } } delete fpdc; double flapping = zGetDoubleAttr(data, aFlapping); double bending= zGetDoubleAttr(data, aBending); double oscillate= zGetDoubleAttr(data, aOscillate); double length = zGetDoubleAttr(data, aLength); m_fish_length = length; double frequency = zGetDoubleAttr(data, aFrequency); unsigned num_bones = zGetIntAttr(data, aNBone); unsigned int nptc = ptc_positions.length(); MPointArray vertices; MATRIX44F mat44, mat_bone; XYZ vert, front, up, side; MDataHandle outputHandle = data.outputValue(outMesh, &status); zCheckStatus(status, "ERROR getting polygon data handle\n"); if(m_num_fish != nptc || m_num_bone != num_bones) { m_num_bone = num_bones; m_num_fish = nptc; unsigned int vertex_count; unsigned int face_count; MIntArray pcounts; MIntArray pconnect; unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertex_count = inmeshnv * nptc; face_count = inmeshnp * nptc; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices.append(MPoint(vert.x, vert.y, vert.z)); } for(unsigned int j=0; j<inmeshnp; j++) { pcounts.append(count_inmesh[j]); } } int acc=0; for(unsigned int i=0; i<nptc; i++) { for(unsigned int j=0; j<connect_inmesh.length(); j++) { pconnect.append(connect_inmesh[j]+acc); } acc += inmeshnv; } MObject m_mesh = outputHandle.asMesh(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); zCheckStatusNR(status, "ERROR creating outputData"); MFnMesh meshFn; m_mesh= meshFn.create( vertex_count, // number of vertices face_count, // number of polygons vertices, // The points pcounts, // # of vertex for each poly pconnect, // Vertices index for each poly newOutputData, // Dependency graph data object &status ); zCheckStatusNR(status, "ERROE creating mesh"); // Update surface // outputHandle.set(newOutputData); } else { MObject m_mesh = outputHandle.asMesh(); MFnMesh meshFn(m_mesh); unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertices.setLength(nptc*inmeshnv); int acc=0; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices[j+acc] = MPoint(vert.x, vert.y, vert.z); } acc += inmeshnv; } meshFn.setPoints(vertices); outputHandle.set(meshFn.object()); } //delete fmat; data.setClean( plug ); return MS::kSuccess; }
MStatus stringFormat::compute (const MPlug& plug, MDataBlock& data) { MStatus status; // Check that the requested recompute is one of the output values // if (plug == attrOutput) { // Read the input values // MDataHandle inputData = data.inputValue (attrFormat, &status); CHECK_MSTATUS( status ); MString format = inputData.asString(); // Get input data handle, use outputArrayValue since we do not // want to evaluate all inputs, only the ones related to the // requested multiIndex. This is for efficiency reasons. // MArrayDataHandle vals = data.outputArrayValue(attrValues, &status); CHECK_MSTATUS( status ); int indx = 0; int param; char letter; while ((indx = findNextMatch(format, indx, param, letter)) > 0) { double val = 0.; status = vals.jumpToElement(param); if (status == MStatus::kSuccess) { MDataHandle thisVal = vals.inputValue( &status ); if (status == MStatus::kSuccess) { val = thisVal.asDouble(); } } MString replace; bool valid = false; switch (letter) { case 'd': // Integer val = floor(val+.5); // No break here case 'f': // Float replace.set(val); valid = true; break; case 't': // Timecode { const char * sign = ""; if (val<0) { sign = "-"; val = -val; } int valInt = (int)(val+.5); int sec = valInt / 24; int frame = valInt - sec * 24; int min = sec / 60; sec -= min * 60; int hour = min / 60; min -= hour * 60; char buffer[90]; if (hour>0) sprintf(buffer, "%s%d:%02d:%02d.%02d", sign, hour, min, sec, frame); else sprintf(buffer, "%s%02d:%02d.%02d", sign, min, sec, frame); replace = buffer; } valid = true; break; } if (valid) { format = format.substring(0, indx-2) + replace + format.substring(indx+2, format.length()-1); indx += replace.length() - 3; } } // Store the result // MDataHandle output = data.outputValue(attrOutput, &status ); CHECK_MSTATUS( status ); output.set( format ); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
// // DESCRIPTION: /////////////////////////////////////////////////////// MStatus VolumeNode::compute(const MPlug& plug, MDataBlock& block ) { if ((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutTransparency) && (plug.parent() != aOutTransparency)) return MS::kUnknownParameter; MFloatVector& InputColor = block.inputValue( aColor ).asFloatVector(); float Distance = block.inputValue( aInputValue ).asFloat(); MFloatVector& FarCamera = block.inputValue( aFarPointC ).asFloatVector(); MFloatVector& FarObject = block.inputValue( aFarPointO ).asFloatVector(); MFloatVector& FarWorld = block.inputValue( aFarPointW ).asFloatVector(); MFloatVector& PointCam = block.inputValue( aPointC ).asFloatVector(); MFloatVector& PointObj = block.inputValue( aPointO ).asFloatVector(); MFloatVector& PointWor = block.inputValue( aPointW ).asFloatVector(); bool Camera = block.inputValue( aToggleCamera ).asBool(); bool Object = block.inputValue( aToggleObject ).asBool(); bool World = block.inputValue( aToggleWorld ).asBool(); MFloatVector interval(0.0,0.0,0.0); if (Camera) { interval = FarCamera - PointCam; } if (Object) { interval = FarObject - PointObj; } if (World) { interval = FarWorld - PointWor; } double value,dist; if ((value = ((interval[0]*interval[0]) + (interval[1]*interval[1]) + (interval[2]*interval[2])) )) { dist = sqrt ( value ); } else dist = 0.0; MFloatVector resultColor(0.0,0.0,0.0); if (dist <= Distance) { resultColor[0] = InputColor[0]; resultColor[1] = InputColor[1]; resultColor[2] = InputColor[2]; } // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); // set output transparency MFloatVector transparency(resultColor[2],resultColor[2],resultColor[2]); MDataHandle outTransHandle = block.outputValue( aOutTransparency ); MFloatVector& outTrans = outTransHandle.asFloatVector(); outTrans = transparency; outTransHandle.setClean( ); MDataHandle outAlphaHandle = block.outputValue( aOutAlpha ); float& outAlpha = outAlphaHandle.asFloat(); outAlpha = resultColor[2]; outAlphaHandle.setClean( ); return MS::kSuccess; }
MStatus meshCacheNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; MString path = data.inputValue( input ).asString(); double time = data.inputValue( frame ).asTime().value(); int minfrm = data.inputValue( aminframe ).asInt(); //int maxfrm = data.inputValue( amaxframe ).asInt(); int frmstep = data.inputValue( aframestep ).asInt(); if( time < minfrm ) time = minfrm; int frame_lo = minfrm + int(time-minfrm)/frmstep*frmstep; int frame_hi = frame_lo+frmstep; char filename[256]; sprintf( filename, "%s.%d.mcf", path.asChar(), frame_lo ); FMCFMesh mesh; if(mesh.load(filename) != 1) { sprintf( filename, "%s.mcf", path.asChar()); if(mesh.load(filename) != 1) { MGlobal::displayError( MString("Failed to open file: ") + filename ); return MS::kFailure; } } int lo_n_vertex = mesh.getNumVertex(); vertexArray.clear(); vertexFArray.clear(); uArray.clear(); vArray.clear(); polygonCounts.clear(); polygonConnects.clear(); polygonUVs.clear(); for(unsigned int i = 0; i < mesh.getNumFace(); i++ ) { polygonCounts.append( mesh.getFaceCount(i) ); } for(unsigned int i = 0; i < mesh.getNumFaceVertex(); i++) { polygonConnects.append( mesh.getVertexId(i) ); polygonUVs.append( mesh.getUVId(i) ); } XYZ tp; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { mesh.getVertex(tp, i); vertexArray.append( MPoint( tp.x, tp.y, tp.z ) ); } for(unsigned int i = 0; i < mesh.getNumUV(); i++) { uArray.append( mesh.getS(i) ); vArray.append( mesh.getT(i) ); } if( time > frame_lo ) { sprintf( filename, "%s.%d.mcf", path.asChar(), frame_hi ); if(mesh.load(filename) != 1) { MGlobal::displayError( MString("Failed to open file: ") + filename ); } else if(mesh.getNumVertex() == lo_n_vertex) { XYZ tp; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { mesh.getVertex(tp, i); vertexFArray.append( MPoint( tp.x, tp.y, tp.z ) ); } double alpha = double(time-frame_lo) / (double)frmstep; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { vertexArray[i] = vertexArray[i] + alpha * ( vertexFArray[i] - vertexArray[i] ); } } } if( plug == outMesh ) { MDataHandle meshh = data.outputValue(outMesh, &stat); MFnMeshData dataCreator; MObject outMeshData = dataCreator.create(&stat); int numVertex = vertexArray.length(); int numPolygon = polygonCounts.length(); MFnMesh meshFn; meshFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat ); if( !stat ) { char log[256]; sprintf( log, "Failed to create mesh %s", filename ); MGlobal::displayError( log ); return MS::kFailure; } if( polygonUVs.length() != 0 ) { meshFn.setUVs ( uArray, vArray ); meshFn.assignUVs ( polygonCounts, polygonUVs ); } meshh.set(outMeshData); data.setClean(plug); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus sweptEmitter::compute(const MPlug& plug, MDataBlock& block) // // Descriptions: // Call emit emit method to generate new particles. // { MStatus status; // Determine if we are requesting the output plug for this emitter node. // if( !(plug == mOutput) ) return( MS::kUnknownParameter ); // Get the logical index of the element this plug refers to, // because the node can be emitting particles into more // than one particle shape. // int multiIndex = plug.logicalIndex( &status ); McheckErr(status, "ERROR in plug.logicalIndex.\n"); // Get output data arrays (position, velocity, or parentId) // that the particle shape is holding from the previous frame. // MArrayDataHandle hOutArray = block.outputArrayValue(mOutput, &status); McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n"); // Create a builder to aid in the array construction efficiently. // MArrayDataBuilder bOutArray = hOutArray.builder( &status ); McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n"); // Get the appropriate data array that is being currently evaluated. // MDataHandle hOut = bOutArray.addElement(multiIndex, &status); McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n"); // Get the data and apply the function set. // MFnArrayAttrsData fnOutput; MObject dOutput = fnOutput.create ( &status ); McheckErr(status, "ERROR in fnOutput.create.\n"); // Check if the particle object has reached it's maximum, // hence is full. If it is full then just return with zero particles. // bool beenFull = isFullValue( multiIndex, block ); if( beenFull ) { return( MS::kSuccess ); } // Get deltaTime, currentTime and startTime. // If deltaTime <= 0.0, or currentTime <= startTime, // do not emit new pariticles and return. // MTime cT = currentTimeValue( block ); MTime sT = startTimeValue( multiIndex, block ); MTime dT = deltaTimeValue( multiIndex, block ); if( (cT <= sT) || (dT <= 0.0) ) { // We do not emit particles before the start time, // and do not emit particles when moving backwards in time. // // This code is necessary primarily the first time to // establish the new data arrays allocated, and since we have // already set the data array to length zero it does // not generate any new particles. // hOut.set( dOutput ); block.setClean( plug ); return( MS::kSuccess ); } // Get speed, direction vector, and inheritFactor attributes. // double speed = speedValue( block ); MVector dirV = directionVector( block ); double inheritFactor = inheritFactorValue( multiIndex, block ); // Get the position and velocity arrays to append new particle data. // MVectorArray fnOutPos = fnOutput.vectorArray("position", &status); MVectorArray fnOutVel = fnOutput.vectorArray("velocity", &status); // Convert deltaTime into seconds. // double dt = dT.as( MTime::kSeconds ); // Apply rotation to the direction vector MVector rotatedV = useRotation ( dirV ); // position, MVectorArray inPosAry; // velocity MVectorArray inVelAry; // emission rate MIntArray emitCountPP; // Get the swept geometry data // MObject thisObj = this->thisMObject(); MPlug sweptPlug( thisObj, mSweptGeometry ); if ( sweptPlug.isConnected() ) { MDataHandle sweptHandle = block.inputValue( mSweptGeometry ); // MObject sweptData = sweptHandle.asSweptGeometry(); MObject sweptData = sweptHandle.data(); MFnDynSweptGeometryData fnSweptData( sweptData ); // Curve emission // if (fnSweptData.lineCount() > 0) { int numLines = fnSweptData.lineCount(); for ( int i=0; i<numLines; i++ ) { inPosAry.clear(); inVelAry.clear(); emitCountPP.clear(); MDynSweptLine line = fnSweptData.sweptLine( i ); // ... process current line ... MVector p1 = line.vertex( 0 ); MVector p2 = line.vertex( 1 ); inPosAry.append( p1 ); inPosAry.append( p2 ); inVelAry.append( MVector( 0,0,0 ) ); inVelAry.append( MVector( 0,0,0 ) ); // emit Rate for two points on line emitCountPP.clear(); status = emitCountPerPoint( plug, block, 2, emitCountPP ); emit( inPosAry, inVelAry, emitCountPP, dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel ); } } // Surface emission (nurb or polygon) // if (fnSweptData.triangleCount() > 0) { int numTriangles = fnSweptData.triangleCount(); for ( int i=0; i<numTriangles; i++ ) { inPosAry.clear(); inVelAry.clear(); emitCountPP.clear(); MDynSweptTriangle tri = fnSweptData.sweptTriangle( i ); // ... process current triangle ... MVector p1 = tri.vertex( 0 ); MVector p2 = tri.vertex( 1 ); MVector p3 = tri.vertex( 2 ); MVector center = p1 + p2 + p3; center /= 3.0; inPosAry.append( center ); inVelAry.append( MVector( 0,0,0 ) ); // emit Rate for two points on line emitCountPP.clear(); status = emitCountPerPoint( plug, block, 1, emitCountPP ); emit( inPosAry, inVelAry, emitCountPP, dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel ); } } } // Update the data block with new dOutput and set plug clean. // hOut.set( dOutput ); block.setClean( plug ); return( MS::kSuccess ); }
// // DESCRIPTION: /////////////////////////////////////////////////////// MStatus PhongNode::compute( const MPlug& plug, MDataBlock& block ) { if ((plug != aOutColor) && (plug.parent() != aOutColor)) return MS::kUnknownParameter; MFloatVector resultColor(0.0,0.0,0.0); // get sample surface shading parameters MFloatVector& surfaceNormal = block.inputValue( aNormalCamera ).asFloatVector(); MFloatVector& cameraPosition = block.inputValue( aPointCamera ).asFloatVector(); // use for raytracing api enhancement below MFloatVector point = cameraPosition; MFloatVector normal = surfaceNormal; MFloatVector& surfaceColor = block.inputValue( aColor ).asFloatVector(); MFloatVector& incandescence = block.inputValue( aIncandescence ).asFloatVector(); float diffuseReflectivity = block.inputValue( aDiffuseReflectivity ).asFloat(); // float translucenceCoeff = block.inputValue( aTranslucenceCoeff ).asFloat(); // User-defined Reflection Color Gain float reflectGain = block.inputValue( aReflectGain ).asFloat(); // Phong shading attributes float power = block.inputValue( aPower ).asFloat(); float spec = block.inputValue( aSpecularity ).asFloat(); float specularR, specularG, specularB; float diffuseR, diffuseG, diffuseB; diffuseR = diffuseG = diffuseB = specularR = specularG = specularB = 0.0; // get light list MArrayDataHandle lightData = block.inputArrayValue( aLightData ); int numLights = lightData.elementCount(); // iterate through light list and get ambient/diffuse values for( int count=1; count <= numLights; count++ ) { MDataHandle currentLight = lightData.inputValue(); MFloatVector& lightIntensity = currentLight.child(aLightIntensity).asFloatVector(); // Find the blind data void*& blindData = currentLight.child( aLightBlindData ).asAddr(); // find ambient component if( currentLight.child(aLightAmbient).asBool() ) { diffuseR += lightIntensity[0]; diffuseG += lightIntensity[1]; diffuseB += lightIntensity[2]; } MFloatVector& lightDirection = currentLight.child(aLightDirection).asFloatVector(); if ( blindData == NULL ) { // find diffuse and specular component if( currentLight.child(aLightDiffuse).asBool() ) { float cosln = lightDirection * surfaceNormal;; if( cosln > 0.0f ) // calculate only if facing light { diffuseR += lightIntensity[0] * ( cosln * diffuseReflectivity ); diffuseG += lightIntensity[1] * ( cosln * diffuseReflectivity ); diffuseB += lightIntensity[2] * ( cosln * diffuseReflectivity ); } CHECK_MSTATUS( cameraPosition.normalize() ); if( cosln > 0.0f ) // calculate only if facing light { float RV = ( ( (2*surfaceNormal) * cosln ) - lightDirection ) * cameraPosition; if( RV > 0.0 ) RV = 0.0; if( RV < 0.0 ) RV = -RV; if ( power < 0 ) power = -power; float s = spec * powf( RV, power ); specularR += lightIntensity[0] * s; specularG += lightIntensity[1] * s; specularB += lightIntensity[2] * s; } } } else { float cosln = MRenderUtil::diffuseReflectance( blindData, lightDirection, point, surfaceNormal, true ); if( cosln > 0.0f ) // calculate only if facing light { diffuseR += lightIntensity[0] * ( cosln * diffuseReflectivity ); diffuseG += lightIntensity[1] * ( cosln * diffuseReflectivity ); diffuseB += lightIntensity[2] * ( cosln * diffuseReflectivity ); } CHECK_MSTATUS ( cameraPosition.normalize() ); if ( currentLight.child(aLightSpecular).asBool() ) { MFloatVector specLightDirection = lightDirection; MDataHandle directionH = block.inputValue( aRayDirection ); MFloatVector direction = directionH.asFloatVector(); float lightAttenuation = 1.0; specLightDirection = MRenderUtil::maximumSpecularReflection( blindData, lightDirection, point, surfaceNormal, direction ); lightAttenuation = MRenderUtil::lightAttenuation( blindData, point, surfaceNormal, false ); // Are we facing the light if ( specLightDirection * surfaceNormal > 0.0f ) { float power2 = block.inputValue( aPower ).asFloat(); MFloatVector rv = 2 * surfaceNormal * ( surfaceNormal * direction ) - direction; float s = spec * powf( rv * specLightDirection, power2 ); specularR += lightIntensity[0] * s * lightAttenuation; specularG += lightIntensity[1] * s * lightAttenuation; specularB += lightIntensity[2] * s * lightAttenuation; } } } if( !lightData.next() ) break; } // factor incident light with surface color and add incandescence resultColor[0] = ( diffuseR * surfaceColor[0] ) + specularR + incandescence[0]; resultColor[1] = ( diffuseG * surfaceColor[1] ) + specularG + incandescence[1]; resultColor[2] = ( diffuseB * surfaceColor[2] ) + specularB + incandescence[2]; // add the reflection color if (reflectGain > 0.0) { MStatus status; // required attributes for using raytracer // origin, direction, sampler, depth, and object id. // MDataHandle originH = block.inputValue( aRayOrigin, &status); MFloatVector origin = originH.asFloatVector(); MDataHandle directionH = block.inputValue( aRayDirection, &status); MFloatVector direction = directionH.asFloatVector(); MDataHandle samplerH = block.inputValue( aRaySampler, &status); void*& samplerPtr = samplerH.asAddr(); MDataHandle depthH = block.inputValue( aRayDepth, &status); short depth = depthH.asShort(); MDataHandle objH = block.inputValue( aObjectId, &status); void*& objId = objH.asAddr(); MFloatVector reflectColor; MFloatVector reflectTransparency; MFloatVector& triangleNormal = block.inputValue( aTriangleNormalCamera ).asFloatVector(); // compute reflected ray MFloatVector l = -direction; float dot = l * normal; if( dot < 0.0 ) dot = -dot; MFloatVector refVector = 2 * normal * dot - l; // reflection ray float dotRef = refVector * triangleNormal; if( dotRef < 0.0 ) { const float s = 0.01f; MFloatVector mVec = refVector - dotRef * triangleNormal; mVec.normalize(); refVector = mVec + s * triangleNormal; } CHECK_MSTATUS ( refVector.normalize() ); status = MRenderUtil::raytrace( point, // origin refVector, // direction objId, // object id samplerPtr, // sampler info depth, // ray depth reflectColor, // output color and transp reflectTransparency); // add in the reflection color resultColor[0] += reflectGain * (reflectColor[0]); resultColor[1] += reflectGain * (reflectColor[1]); resultColor[2] += reflectGain * (reflectColor[2]); } // set ouput color attribute MDataHandle outColorHandle = block.outputValue( aOutColor ); MFloatVector& outColor = outColorHandle.asFloatVector(); outColor = resultColor; outColorHandle.setClean(); return MS::kSuccess; }
MStatus pointOnSubd::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 returnStatus; // 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 == aPoint) || (plug == aNormal) || (plug == aPointX) || (plug == aNormalX) || (plug == aPointY) || (plug == aNormalY) || (plug == aPointZ) || (plug == aNormalZ) ) { // 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. // do { MDataHandle subdHandle = data.inputValue( aSubd, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get subd\n" ); break; } MDataHandle faceFirstHandle = data.inputValue( aFaceFirst, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get face first\n" ); break; } MDataHandle faceSecondHandle = data.inputValue( aFaceSecond, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get face2\n" ); break; } MDataHandle uHandle = data.inputValue( aU, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get u\n" ); break; } MDataHandle vHandle = data.inputValue( aV, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get v\n" ); break; } MDataHandle relHandle = data.inputValue( aRelativeUV, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get relative UV\n" ); break; } // Read the input value from the handle. // MStatus stat; MObject subdValue = subdHandle.asSubdSurface(); MFnSubd subdFn( subdValue, &stat ); McheckErr(stat,"ERROR creating subd function set"); int faceFirstValue = faceFirstHandle.asLong(); int faceSecondValue = faceSecondHandle.asLong(); double uValue = uHandle.asDouble(); double vValue = vHandle.asDouble(); bool relUV = relHandle.asBool(); MPoint point; MVector normal; MUint64 polyId; stat = MFnSubdNames::fromSelectionIndices( polyId, faceFirstValue, faceSecondValue ); McheckErr(stat,"ERROR converting indices"); stat = subdFn.evaluatePositionAndNormal( polyId, uValue, vValue, relUV, point, normal ); normal.normalize(); McheckErr(stat,"ERROR evaluating the position and the normal"); // Get handles to the output attributes. This is similar to the // "inputValue" call above except that no dependency graph // computation will be done as a result of this call. // MDataHandle pointHandle = data.outputValue( aPoint ); pointHandle.set( point.x, point.y, point.z ); data.setClean(plug); MDataHandle normalHandle = data.outputValue( aNormal ); normalHandle.set( normal.x, normal.y, normal.z ); data.setClean(plug); } while( false ); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus buildRotation::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; if ((plug == rotate) || (plug.parent() == rotate) || (plug == rotateMatrix)) { MDataHandle upData = data.inputValue( up, &returnStatus ); McheckErr(returnStatus,"ERROR getting up vector data"); MDataHandle forwardData = data.inputValue( forward, &returnStatus ); McheckErr(returnStatus,"ERROR getting forward vector data"); MVector up = upData.asVector(); MVector forward = forwardData.asVector(); // Make sure that the up and forward vectors are orthogonal // if ( fabs( up * forward ) > EPSILON ) { // Non-zero dot product // MVector orthoVec = up ^ forward; MVector newForward = orthoVec ^ up; if ( forward * newForward < 0.0 ) { // Reverse the vector // newForward *= -1.0; } forward = newForward; } // Calculate the rotation required to align the y-axis with the up // vector // MTransformationMatrix firstRot; MVector rotAxis = MVector::yAxis ^ up; rotAxis.normalize(); firstRot.setToRotationAxis( rotAxis, MVector::yAxis.angle( up ) ); // Calculate the second rotation required to align the forward vector // MTransformationMatrix secondRot; MVector transformedForward = firstRot.asMatrix() * forward; transformedForward.normalize(); double angle = transformedForward.angle( MVector::zAxis ); if ( transformedForward.x < 0.0 ) { // Compensate for the fact that the angle method returns // the absolute value // angle *= -1.0; } secondRot.setToRotationAxis( up, angle ); // Get the requested rotation order // MDataHandle orderHandle = data.inputValue( rotateOrder ); short order = orderHandle.asShort(); MTransformationMatrix::RotationOrder rotOrder; switch ( order ) { case ROTATE_ORDER_XYZ: rotOrder = MTransformationMatrix::kXYZ; break; case ROTATE_ORDER_YZX: rotOrder = MTransformationMatrix::kYZX; break; case ROTATE_ORDER_ZXY: rotOrder = MTransformationMatrix::kZXY; break; case ROTATE_ORDER_XZY: rotOrder = MTransformationMatrix::kXZY; break; case ROTATE_ORDER_YXZ: rotOrder = MTransformationMatrix::kYXZ; break; case ROTATE_ORDER_ZYX: rotOrder = MTransformationMatrix::kZYX; break; default: rotOrder = MTransformationMatrix::kInvalid; break; } MTransformationMatrix result = firstRot.asMatrix() * secondRot.asMatrix(); result.reorderRotation( rotOrder ); double rotation[3]; result.getRotation( rotation, rotOrder, MSpace::kTransform ); MDataHandle outputRot = data.outputValue( rotate ); outputRot.set( rotation[0], rotation[1], rotation[2] ); outputRot.setClean(); MDataHandle outputMatrix = data.outputValue( rotateMatrix ); outputMatrix.set( result.asMatrix() ); outputMatrix.setClean(); } else return MS::kUnknownParameter; return MS::kSuccess; }
MStatus geometrySurfaceConstraint::compute( const MPlug& plug, MDataBlock& block ) { MStatus returnStatus; if ( plug == geometrySurfaceConstraint::constraintGeometry ) { // block.inputValue(constraintParentInverseMatrix); // MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget ); unsigned int targetArrayCount = targetArray.elementCount(); double weight,selectedWeight = 0; if ( weightType == geometrySurfaceConstraintCommand::kSmallestWeight ) selectedWeight = FLT_MAX; MObject selectedMesh; unsigned int i; for ( i = 0; i < targetArrayCount; i++ ) { MDataHandle targetElement = targetArray.inputValue(); weight = targetElement.child(targetWeight).asDouble(); if ( !equivalent(weight,0.0)) { if ( weightType == geometrySurfaceConstraintCommand::kLargestWeight ) { if ( weight > selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh(); if ( !mesh.isNull() ) { selectedMesh = mesh; selectedWeight = weight; } } } else { if ( weight < selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh(); if ( !mesh.isNull() ) { selectedMesh = mesh; selectedWeight = weight; } } } } targetArray.next(); } // if ( selectedMesh.isNull() ) { block.setClean(plug); } else { // The transform node via the geometry attribute will take care of // updating the location of the constrained geometry. MDataHandle outputConstraintGeometryHandle = block.outputValue(constraintGeometry); outputConstraintGeometryHandle.setMObject(selectedMesh); } } else { return MS::kUnknownParameter; } return MS::kSuccess; }
/* 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 AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock) { MStatus status; // update the frame number to be imported MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status); double speed = speedHandle.asDouble(); MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status); double offset = offsetHandle.asDouble(); MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status); MTime t = timeHandle.asTime(); double inputTime = t.as(MTime::kSeconds); double fps = getFPS(); // scale and offset inputTime. inputTime = computeAdjustedTime(inputTime, speed, offset/fps); // this should be done only once per file if (mFileInitialized == false) { mFileInitialized = true; //Get list of input filenames MFnDependencyNode depNode(thisMObject()); MPlug layerFilesPlug = depNode.findPlug("abc_layerFiles"); MFnStringArrayData fnSAD( layerFilesPlug.asMObject() ); MStringArray storedFilenames = fnSAD.array(); //Legacy support for single-filename input if( storedFilenames.length() == 0 ) { MFileObject fileObject; MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr); fileObject.setRawFullName(dataHandle.asString()); MString fileName = fileObject.resolvedFullName(); storedFilenames.append( fileName ); } std::vector<std::string> abcFilenames; for(unsigned int i = 0; i < storedFilenames.length(); i++) abcFilenames.push_back( storedFilenames[i].asChar() ); Alembic::Abc::IArchive archive; Alembic::AbcCoreFactory::IFactory factory; factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy); archive = factory.getArchive( abcFilenames ); if (!archive.valid()) { MString theError = "Error opening these alembic files: "; const unsigned int numFilenames = storedFilenames.length(); for( unsigned int i = 0; i < numFilenames; i++ ) { theError += storedFilenames[ i ]; if( i != (numFilenames - 1) ) theError += ", "; } printError(theError); } // initialize some flags for plug update mSubDInitialized = false; mPolyInitialized = false; // When an alembic cache will be imported at the first time using // AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be // mIncludeFilterString for later use. When we save a maya scene(.ma) // mIncludeFilterAttr will be saved. Then when we load the saved // .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr. MDataHandle includeFilterHandle = dataBlock.inputValue(mIncludeFilterAttr, &status); MString& includeFilterString = includeFilterHandle.asString(); if (mIncludeFilterString.length() > 0) { includeFilterHandle.set(mIncludeFilterString); dataBlock.setClean(mIncludeFilterAttr); } else if (includeFilterString.length() > 0) { mIncludeFilterString = includeFilterString; } MDataHandle excludeFilterHandle = dataBlock.inputValue(mExcludeFilterAttr, &status); MString& excludeFilterString = excludeFilterHandle.asString(); if (mExcludeFilterString.length() > 0) { excludeFilterHandle.set(mExcludeFilterString); dataBlock.setClean(mExcludeFilterAttr); } else if (excludeFilterString.length() > 0) { mExcludeFilterString = excludeFilterString; } MFnDependencyNode dep(thisMObject()); MPlug allSetsPlug = dep.findPlug("allColorSets"); CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(), MObject::kNullObj, CreateSceneVisitor::NONE, "", mIncludeFilterString, mExcludeFilterString); visitor.walk(archive); if (visitor.hasSampledData()) { // information retrieved from the hierarchy traversal // and given to AlembicNode to provide update visitor.getData(mData); mData.getFrameRange(mSequenceStartTime, mSequenceEndTime); MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr, &status); startFrameHandle.set(mSequenceStartTime*fps); MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr, &status); endFrameHandle.set(mSequenceEndTime*fps); } } // Retime MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status); short playType = cycleHandle.asShort(); inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime, playType); clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime); // update only when the time lapse is big enough if (fabs(inputTime - mCurTime) > 0.00001) { mOutRead = std::vector<bool>(mOutRead.size(), false); mCurTime = inputTime; } if (plug == mOutPropArrayAttr) { if (mOutRead[0]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[0] = true; unsigned int propSize = static_cast<unsigned int>(mData.mPropList.size()); if (propSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPropArrayAttr, &status); unsigned int outHandleIndex = 0; MDataHandle outHandle; // for all of the nodes with sampled attributes for (unsigned int i = 0; i < propSize; i++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(); } else { continue; } if (mData.mPropList[i].mArray.valid()) { readProp(mCurTime, mData.mPropList[i].mArray, outHandle); } else if (mData.mPropList[i].mScalar.valid()) { // for visibility only if (mData.mPropList[i].mScalar.getName() == Alembic::AbcGeom::kVisibilityPropertyName) { Alembic::Util::int8_t visVal = 1; mData.mPropList[i].mScalar.get(&visVal, Alembic::Abc::ISampleSelector(mCurTime, Alembic::Abc::ISampleSelector::kNearIndex )); outHandle.setGenericBool(visVal != 0, false); } else { // for all scalar props readProp(mCurTime, mData.mPropList[i].mScalar, outHandle); } } outArrayHandle.next(); } outArrayHandle.setAllClean(); } } else if (plug == mOutTransOpArrayAttr ) { if (mOutRead[1]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[1] = true; unsigned int xformSize = static_cast<unsigned int>(mData.mXformList.size()); if (xformSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutTransOpArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < xformSize; i++) { std::vector<double> sampleList; if (mData.mIsComplexXform[i]) { readComplex(mCurTime, mData.mXformList[i], sampleList); } else { Alembic::AbcGeom::XformSample samp; read(mCurTime, mData.mXformList[i], sampleList, samp); } unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutLocatorPosScaleArrayAttr ) { if (mOutRead[8]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[8] = true; unsigned int locSize = static_cast<unsigned int>(mData.mLocList.size()); if (locSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < locSize; i++) { std::vector< double > sampleList; read(mCurTime, mData.mLocList[i], sampleList); unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutSubDArrayAttr) { if (mOutRead[2]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutSubDArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[2] = true; unsigned int subDSize = static_cast<unsigned int>(mData.mSubDList.size()); if (subDSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < subDSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j], mSubDInitialized); outHandle.set(obj); } } mSubDInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mSubDInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutPolyArrayAttr) { if (mOutRead[3]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[3] = true; unsigned int polySize = static_cast<unsigned int>(mData.mPolyMeshList.size()); if (polySize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < polySize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j], mPolyInitialized); outHandle.set(obj); } } mPolyInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPolyArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(&status); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mPolyInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutCameraArrayAttr) { if (mOutRead[4]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[4] = true; unsigned int cameraSize = static_cast<unsigned int>(mData.mCameraList.size()); if (cameraSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutCameraArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr); double angleConversion = 1.0; switch (MAngle::uiUnit()) { case MAngle::kRadians: angleConversion = 0.017453292519943295; break; case MAngle::kAngMinutes: angleConversion = 60.0; break; case MAngle::kAngSeconds: angleConversion = 3600.0; break; default: break; } MDataHandle outHandle; unsigned int index = 0; for (unsigned int cameraIndex = 0; cameraIndex < cameraSize; cameraIndex++) { Alembic::AbcGeom::ICamera & cam = mData.mCameraList[cameraIndex]; std::vector<double> array; read(mCurTime, cam, array); for (unsigned int dataIndex = 0; dataIndex < array.size(); dataIndex++, index++) { // skip over sparse elements if (index != outArrayHandle.elementIndex()) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); // not shutter angle index, so not an angle if (dataIndex != 11) { outHandle.set(array[dataIndex]); } else { outHandle.set(array[dataIndex] * angleConversion); } } // for the per camera data handles } // for each camera outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsSurfaceArrayAttr) { if (mOutRead[5]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[5] = true; unsigned int nSurfaceSize = static_cast<unsigned int>(mData.mNurbsList.size()); if (nSurfaceSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < nSurfaceSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) continue; outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kNurbsSurface)) { readNurbs(mCurTime, mData.mNurbsList[j], obj); outHandle.set(obj); } } outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsCurveGrpArrayAttr) { if (mOutRead[6]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[6] = true; unsigned int nCurveGrpSize = static_cast<unsigned int>(mData.mCurvesList.size()); if (nCurveGrpSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); MDataHandle outHandle; std::vector<MObject> curvesObj; for (unsigned int i = 0; i < nCurveGrpSize; ++i) { readCurves(mCurTime, mData.mCurvesList[i], mData.mNumCurves[i], curvesObj); } std::size_t numChild = curvesObj.size(); // not the best way to do this // only reading bunches of curves based on the connections would be // more efficient when there is a bunch of broken connections for (unsigned int i = 0; i < numChild; i++) { if (outArrayHandle.elementIndex() != i) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); status = outHandle.set(curvesObj[i]); } outArrayHandle.setAllClean(); } } else { return MS::kUnknownParameter; } dataBlock.setClean(plug); return status; }
MStatus weightList::compute( const MPlug& plug, MDataBlock& block) { MStatus status = MS::kSuccess; unsigned i, j; MObject thisNode = thisMObject(); MPlug wPlug(thisNode, aWeights); // Write into aWeightList for( i = 0; i < 3; i++) { status = wPlug.selectAncestorLogicalIndex( i, aWeightsList ); MDataHandle wHandle = wPlug.constructHandle(block); MArrayDataHandle arrayHandle(wHandle, &status); McheckErr(status, "arrayHandle construction failed\n"); MArrayDataBuilder arrayBuilder = arrayHandle.builder(&status); McheckErr(status, "arrayBuilder accessing/construction failed\n"); for( j = 0; j < i+2; j++) { MDataHandle handle = arrayBuilder.addElement(j,&status); McheckErr(status, "addElement to arrayBuilder failed\n"); float val = 1.0f*(i+j); handle.set(val); } status = arrayHandle.set(arrayBuilder); McheckErr(status, "set arrayBuilder failed\n"); wPlug.setValue(wHandle); wPlug.destructHandle(wHandle); } // Read from aWeightList and print out result MArrayDataHandle arrayHandle = block.inputArrayValue(aWeightsList, &status); McheckErr(status, "arrayHandle construction for aWeightsList failed\n"); unsigned count = arrayHandle.elementCount(); for( i = 0; i < count; i++) { arrayHandle.jumpToElement(i); MDataHandle eHandle = arrayHandle.inputValue(&status).child(aWeights); McheckErr(status, "handle evaluation failed\n"); MArrayDataHandle eArrayHandle(eHandle, &status); McheckErr(status, "arrayHandle construction for aWeights failed\n"); unsigned eCount = eArrayHandle.elementCount(); for( j = 0; j < eCount; j++) { eArrayHandle.jumpToElement(j); float weight = eArrayHandle.inputValue(&status).asFloat(); McheckErr(status, "weight evaluation error\n"); fprintf(stderr, "weightList[%u][%u] = %g\n",i,j,weight); } } // Read from aWeightList and print out result using the more // efficient jumpToArrayElement() call arrayHandle = block.inputArrayValue(aWeightsList, &status); McheckErr(status, "arrayHandle construction for aWeightsList failed\n"); count = arrayHandle.elementCount(); for( i = 0; i < count; i++) { arrayHandle.jumpToArrayElement(i); MDataHandle eHandle = arrayHandle.inputValue(&status).child(aWeights); McheckErr(status, "handle evaluation failed\n"); MArrayDataHandle eArrayHandle(eHandle, &status); McheckErr(status, "arrayHandle construction for aWeights failed\n"); unsigned eCount = eArrayHandle.elementCount(); for( j = 0; j < eCount; j++) { eArrayHandle.jumpToArrayElement(j); float weight = eArrayHandle.inputValue(&status).asFloat(); McheckErr(status, "weight evaluation error\n"); fprintf(stderr, "weightList[%d][%d] = %g\n",i,j,weight); } } 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 TCC::createSubdividedMesh(int sdRes, int sdRefRes, MFnMesh &srcMesh, TCCData &tccData, MDataHandle outMeshHandle, float lineThickness, MStatus& stat) { HDS hds; bool shouldCreateUVs = true; size_t nV = srcMesh.numVertices(); size_t nF = srcMesh.numPolygons(); size_t nIHE = tccData.F.length(); bool consistentSizes= (tccData.pole.length()==nV) && (tccData.T.length()==nIHE) && (tccData.itv.length()==nIHE) & (tccData.corner.length()==nV); if ((nV==0)||(nF==0)||(!consistentSizes)) return MS::kFailure; MFloatArray uArray, vArray, sc_uArray, sc_vArray; MIntArray uvIdx; if (shouldCreateUVs) { createUVset(tccData, sdRes, uArray, vArray, sc_uArray, sc_vArray, uvIdx, lineThickness); } MFloatPointArray points; srcMesh.getPoints(points); store_in_hds(hds, points, tccData.nFV, tccData.F); // convert to HDS finalize_HDS(hds); size_t nHE = hds.nHE(); hds.T.setDims(1, nHE); hds.itv.setDims(1, nHE); hds.corner.setDims(1, nV); // interior halfedge tags for (size_t k=0; k<nV; k++) { hds.corner[k] = tccData.corner[k]; } // interior halfedge tags for (size_t k=0; k<nIHE; k++) { hds.T[k] = tccData.T[k]; hds.itv[k] = tccData.itv[k]; } // border halfedge tags for (size_t k=nIHE; k<nHE; k++) { hds.T[k] = false; hds.itv[k] = hds.itv[hds.twin[k]]; } TCC_MAX::subdivide(hds, sdRes); if (sdRefRes>0) { HDS hds2; copy_HDS(hds, hds2); TCC_MAX::subdivide(hds2, sdRefRes); memcpy(&hds.V[0], &hds2.V[0], hds.V.size() * sizeof(double)); } MObject outMeshObj = outMeshHandle.asMesh(); MFnMesh outMeshFn(outMeshObj); // if no topology change necessary, just update points! if ( (outMeshFn.numFaceVertices() == hds.nIHE()) && (outMeshFn.numPolygons() == hds.nF()) ) { size_t nV = hds.nV(); points.setLength(nV); for (size_t k=0; k<nV; k++) { points[k](0) = hds.V[3*k+0]; points[k](1) = hds.V[3*k+1]; points[k](2) = hds.V[3*k+2]; } stat = outMeshFn.setPoints(points); McheckErr(stat, "ERROR creating outputData"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; stat = outMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = outMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); } return MS::kSuccess; } // Have to update connectivity and geometry load_from_hds(hds, points, tccData.nFV, tccData.F); nV = points.length(); nF = tccData.nFV.length(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&stat); McheckErr(stat, "ERROR creating outputData"); MFnMesh newOutMeshFn; MObject newMesh; newMesh = newOutMeshFn.create(nV, nF, points, tccData.nFV, tccData.F, newOutputData, &stat); McheckErr(stat, "ERROR in MFnMesh.create\n"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; uvSet = newOutMeshFn.createUVSetDataMeshWithName(uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&uvSet); stat = newOutMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &uvSet); McheckErr(stat, "ERROR assigning UVs"); sc_uvSet = newOutMeshFn.createUVSetDataMeshWithName(sc_uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&sc_uvSet); stat = newOutMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &sc_uvSet); McheckErr(stat, "ERROR assigning UVs"); } if (stat == MS::kSuccess) { outMeshHandle.set(newOutputData); } return MS::kSuccess; }
/*! 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; }
MStatus multiCurve::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ( plug == outputCurves ) { MDataHandle numCurvesHandle = data.inputValue(numCurves, &stat); PERRORfail(stat, "multiCurve::compute getting numCurves"); int num = numCurvesHandle.asLong(); MDataHandle curveOffsetHandle = data.inputValue(curveOffset, &stat); PERRORfail(stat, "multiCurve::compute getting curveOffset"); double baseOffset = curveOffsetHandle.asDouble(); MDataHandle inputCurveHandle = data.inputValue(inputCurve, &stat); PERRORfail(stat, "multiCurve::compute getting inputCurve"); MObject inputCurveObject ( inputCurveHandle.asNurbsCurveTransformed() ); MFnNurbsCurve inCurveFS ( inputCurveObject ); MArrayDataHandle outputArray = data.outputArrayValue(outputCurves, &stat); PERRORfail(stat, "multiCurve::compute getting output data handle"); // Create an array data build that is preallocated to hold just // the number of curves we plan on creating. When this builder // is set in to the MArrayDataHandle at the end of the compute // method, the new array will replace the existing array in the // scene. // // If the number of elements of the multi does not change between // compute cycles, then one can reuse the space allocated on a // previous cycle by extracting the existing builder from the // MArrayDataHandle: // MArrayDataBuilder builder( outputArray.builder(&stat) ); // this later form of the builder will allow you to rewrite elements // of the array, and to grow it, but the array can only be shrunk by // explicitly removing elements with the method // MArrayDataBuilder::removeElement(unsigned index); // MArrayDataBuilder builder(outputCurves, num, &stat); PERRORfail(stat, "multiCurve::compute creating builder"); for (int curveNum = 0; curveNum < num; curveNum++) { MDataHandle outHandle = builder.addElement(curveNum); MFnNurbsCurveData dataCreator; MObject outCurveData = dataCreator.create(); MObject outputCurve = inCurveFS.copy(inputCurveObject, outCurveData, &stat); PERRORfail(stat, "multiCurve::compute copying curve"); MFnNurbsCurve outCurveFS ( outputCurve ); MPointArray cvs; double offset = baseOffset * (curveNum+1); outCurveFS.getCVs ( cvs, MSpace::kWorld ); int numCVs = cvs.length(); for (int i = 0; i < numCVs; i++) { cvs[i].x += offset; } outCurveFS.setCVs ( cvs ); outHandle.set(outCurveData); } // Set the builder back into the output array. This statement // is always required, no matter what constructor was used to // create the builder. stat = outputArray.set(builder); PERRORfail(stat, "multiCurve::compute setting the builder"); // Since we compute all the elements of the array, instead of // just marking the plug we were asked to compute as clean, mark // every element of the array as clean to prevent further calls // to this compute method during this DG evaluation cycle. stat = outputArray.setAllClean(); PERRORfail(stat, "multiCurve::compute cleaning outputCurves"); } else { return MS::kUnknownParameter; } return stat; }
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 NuiMayaDeviceGrabber::compute( const MPlug& plug, MDataBlock& datablock ) // // 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 // { assert(m_pCache); if(!m_pCache) return MS::kFailure; MStatus returnStatus; /* Get time */ MDataHandle timeData = datablock.inputValue( aTime, &returnStatus ); MCHECKERROR(returnStatus, "Error getting time data handle\n") MTime time = timeData.asTime(); //!< 30 frames per second int frame = (int)time.as( MTime::kNTSCFrame ) - 1;//Noted: The first frame in MAYA is 1; if(m_pDevice) { std::shared_ptr<NuiCompositeFrame> pFrame = m_pDevice->popFrame(); if(pFrame) { pFrame->m_depthFrame.SetMinDepth(getShortValue(aMinDepth)); pFrame->m_depthFrame.SetMaxDepth(getShortValue(aMaxDepth)); if(m_pSLAM /*&& m_pSLAM->m_tracker.isThreadOn()*/) { std::shared_ptr<NuiVisualFrame> pVisualFrame = std::make_shared<NuiVisualFrame>(); pVisualFrame->acquireFromCompositeFrame(pFrame.get()); m_pSLAM->m_tracker.pushbackFrame(pVisualFrame); pVisualFrame.reset(); } m_pCache->pushbackFrame(pFrame); pFrame.reset(); } } std::shared_ptr<NuiCompositeFrame> pCurrentFrame = m_pCache->getLatestFrame(); if ( plug == aOutputMappable ) { std::shared_ptr<NuiCLMappableData> clData(nullptr); MDataHandle outHandle = datablock.outputValue( aOutputMappable ); NuiMayaMappableData* clmData = static_cast<NuiMayaMappableData*>(outHandle.asPluginData()); if(!clmData) { // Create some user defined geometry data and access the // geometry so we can set it // MFnPluginData fnDataCreator; MTypeId tmpid( NuiMayaMappableData::id ); fnDataCreator.create( tmpid, &returnStatus ); MCHECKERROR( returnStatus, "compute : error creating mappableData") clmData = (NuiMayaMappableData*)fnDataCreator.data( &returnStatus ); MCHECKERROR( returnStatus, "compute : error gettin at proxy mappableData object") clData = std::shared_ptr<NuiCLMappableData>(new NuiCLMappableData()); clmData->setData(clData); returnStatus = outHandle.set( clmData ); MCHECKERROR( returnStatus, "compute : error gettin at proxy mappableData object") }
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; }
// Main entry // virtual MStatus compute( const MPlug& plug, MDataBlock& dataBlock ) { // enable this node or not if ( dataBlock.inputValue(aEnable).asBool() == false ) return MS::kSuccess; // execution when rendering if ( dataBlock.inputValue(aEnableRender).asBool() == true ) if ( MRenderUtil::mayaRenderState() == MRenderUtil::kNotRendering ) //MGlobal::displayInfo( "not rendering"); return MS::kSuccess; // Execution when the specified output attributes need to be updated if ( !( plug == aOutColor || plug == aUVCoord ) ) return MS::kSuccess; // Check if the aShape is connected if ( isPlugConnect(aShape) != true ) return MS::kSuccess; // From each pixel, sample required info, like point world, UV, .etc. // // 01. get W-space point MDataHandle PointWorldHandle = dataBlock.inputValue( aPointWorld ); MFloatVector pointWorld = PointWorldHandle.asFloatVector(); float uv[2]; // input shape is NURBS Surface // if ( dataBlock.inputValue( aShape ).type() == MFnData::kNurbsSurface ) { // 02. get each UV for the overlaped area // MObject nurbsShape = dataBlock.inputValue(aShape).asNurbsSurface(); getOverlapUVbyNurbs( nurbsShape, pointWorld, uv ); } // input shape is Mesh else if ( dataBlock.inputValue( aShape ).type() == MFnData::kMesh ) { // 02. get each UV for the overlaped area // MObject meshShape = dataBlock.inputValue(aShape).asMeshTransformed(); //W-space mesh getOverlapUVbyMesh( meshShape, pointWorld, uv ); } // if inpute object is neither Mesh nor Nurbs else { return MS::kSuccess; } MFloatVector resultColor( 0.0, 0.0, 0.0 ); // run super sampling function if ( dataBlock.inputValue(aIsSpuersampling).asBool() == true ) { float offsetUV = dataBlock.inputValue(aOffsetSample).asFloat(); int2& filterSize = dataBlock.inputValue(aFilterSize).asInt2(); int x_width = filterSize[0]; int y_width = filterSize[1]; //cout << "super!" << endl; resultColor = doSupersampling( dataBlock, aUVCoord, aColor, uv, x_width, y_width, offsetUV ); } else { // 1. u, v coordinate // 2. get get color by uv dataBlock.outputValue(aUVCoord).set( uv[0], uv[1] ); resultColor = dataBlock.inputValue(aColor).asFloatVector(); } dataBlock.outputValue(aOutColor).set(resultColor); return MS::kSuccess; }