示例#1
0
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;
}
/*! 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;
}