示例#1
0
MStatus polyModifierCmd::undoModifyPoly()
{
	MStatus status = MS::kSuccess;

	if( !fHasHistory && !fHasRecordHistory )
	{
		status = undoDirectModifier();
	}
	else
	{
		fDGModifier.undoIt();

		// undoCachedMesh must be called before undoTweakProcessing because 
		// undoCachedMesh copies the original mesh *without* tweaks back onto
		// the existing mesh. Any changes done before the copy will be lost.
		//
		if( !fHasHistory )
		{
			status = undoCachedMesh();
			MCheckStatus( status, "undoCachedMesh" );
			fDagModifier.undoIt();
		}

		status = undoTweakProcessing();
		MCheckStatus( status, "undoTweakProcessing" );
	}

	return status;
}
示例#2
0
MStatus polyModifierCmd::cacheMeshData()
{
	MStatus status = MS::kSuccess;

	MFnDependencyNode depNodeFn;
	MFnDagNode dagNodeFn;

	MObject meshNode = fDagPath.node();
	MObject dupMeshNode;
	MPlug dupMeshNodeOutMeshPlug;

	// Duplicate the mesh
	//
	dagNodeFn.setObject( meshNode );
	dupMeshNode = dagNodeFn.duplicate();

	MDagPath dupMeshDagPath;
	MDagPath::getAPathTo( dupMeshNode, dupMeshDagPath );
	dupMeshDagPath.extendToShape();

	depNodeFn.setObject( dupMeshDagPath.node() );
	dupMeshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
	MCheckStatus( status, "Could not retrieve outMesh" );

	// Retrieve the meshData
	//
	status = dupMeshNodeOutMeshPlug.getValue( fMeshData );
	MCheckStatus( status, "Could not retrieve meshData" );

	// Delete the duplicated node
	//
	MGlobal::deleteNode( dupMeshNode );

	return status;
}
示例#3
0
MStatus polyModifierCmd::redoModifyPoly()
{
	MStatus status = MS::kSuccess;

	if( !fHasHistory && !fHasRecordHistory )
	{
		MObject meshNode = fDagPath.node();

		// Call the directModifier - No need to pre-process the mesh data again
		//							 since we already have it.
		//
		status = directModifier( meshNode );
	}
	else
	{
		// Call the redo on the DG and DAG modifiers
		//
		if( !fHasHistory )
		{
//########################################################################### tima/
			status = tima_tempForUndoDeleteDuplicate_modifier.undoIt();
/*#ifdef _DEBUG
if(status)cout<<endl<<"tima_tempForUndoDeleteDuplicate_modifier.undoIt - success"<<endl;
else cout<<endl<<"tima_tempForUndoDeleteDuplicate_modifier.undoIt - failed"<<endl;
#endif*/
			MCheckStatus( status, "tima_tempForUndoDeleteDuplicate_modifier.undoIt" );
//########################################################################### /tima
			fDagModifier.doIt();
		}
		status = fDGModifier.doIt();
		setZeroTweaks();
	}

	return status;
}
示例#4
0
MStatus splatDeformer::initialize()
{
	// local attribute initialization
	MStatus status;
	MFnTypedAttribute mAttr;
 	deformingMesh=mAttr.create( "deformingMesh", "dm", MFnMeshData::kMesh);
	mAttr.setStorable(true);

 	//  deformation attributes
 	status = addAttribute( deformingMesh );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( deformingMesh, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");

	return MStatus::kSuccess;
}
示例#5
0
MStatus sseDeformer::initialize()
{
    // local attribute initialization
    MStatus status;
    MFnNumericAttribute mSSEAttr;
    sseEnabled=mSSEAttr.create( "enableSSE", "sse", MFnNumericData::kBoolean, 0, &status);
    mSSEAttr.setStorable(true);

    //  deformation attributes
    status = addAttribute( sseEnabled );
    MCheckStatus(status, "ERROR in addAttribute\n");

    status = attributeAffects( sseEnabled, outputGeom );
    MCheckStatus(status, "ERROR in attributeAffects\n");

    return MStatus::kSuccess;
}
示例#6
0
MStatus splitUV::pruneUVs( MIntArray& validUVIndices )
//
// Description:
//
//		This method will remove any invalid UVIds from the component list and UVId array.
//		The benefit of this is to reduce the amount of extra processing that the node would
//		have to perform. It will result in less iterations through the mesh as there are
//		less UVs to search for.
//
{
	MStatus status;

	unsigned i;
	MIntArray validUVIds;

	for( i = 0; i < validUVIndices.length(); i++ )
	{
		int uvIndex = validUVIndices[i];
		validUVIds.append( fSelUVs[uvIndex] );
	}

	// Replace the local int array of UVIds
	//
	fSelUVs.clear();
	fSelUVs = validUVIds;

	// Build the list of valid components
	//
	MFnSingleIndexedComponent compFn;
	compFn.create( MFn::kMeshMapComponent, &status );
	MCheckStatus( status, "compFn.create( MFn::kMeshMapComponent )" );
	status = compFn.addElements( validUVIds );
	MCheckStatus( status, "compFn.addElements( validUVIds )" );
	MObject component = compFn.object();

	// Replace the component list
	//
	MFnComponentListData compListFn;
	compListFn.create();
	status = compListFn.add( component );
	MCheckStatus( status, "compListFn.add( component )" );

	fComponentList = compListFn.object();

	return status;
}
示例#7
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::undoModifyPoly()
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	if( !fHasHistory && !fHasRecordHistory )
	{
		status = undoDirectModifier();
	}
	else
	{

		// Merke: Das MObject zur ModifierNode sollte jetzt zerstrt werden, da es ungueltig wird, wenn der modifier rueckgngig gemacht wird.
		// Ansonsten gibts nen absturz
		myModifierNode = MObject::kNullObj;

		if(createAnimCurves)
		{
			createSlideAnim.undoIt();
		}

		fDGModifier.undoIt();

		// undoCachedMesh must be called before undoTweakProcessing because 
		// undoCachedMesh copies the original mesh *without* tweaks back onto
		// the existing mesh. Any changes done before the copy will be lost.
		//
		if( !fHasHistory )
		{
			status = undoCachedMesh();
			MCheckStatus( status, "undoCachedMesh" );
			//fDagModifier.undoIt();
			deleteDuplicate.undoIt();
			reparentDuplicate.undoIt();
			createDuplicate.undoIt();
		}

		status = undoTweakProcessing();
		MCheckStatus( status, "undoTweakProcessing" );
	}

	return status;
}
示例#8
0
MStatus polyModifierCmd::undoModifyPoly()
{
	MStatus status = MS::kSuccess;

	if( !fHasHistory && !fHasRecordHistory )
	{
		status = undoDirectModifier();
	}
	else
	{
		fDGModifier.undoIt();

		// undoCachedMesh must be called before undoTweakProcessing because 
		// undoCachedMesh copies the original mesh *without* tweaks back onto
		// the existing mesh. Any changes done before the copy will be lost.
		//
		if( !fHasHistory )
		{
			status = undoCachedMesh();
			MCheckStatus( status, "undoCachedMesh" );
//by_tima:			fDagModifier.undoIt();
//########################################################################### tima/
			MFnDagNode tmpDagNodeFn( fDuplicateDagPath);
			tima_tempForUndoDeleteDuplicate_modifier.deleteNode(tmpDagNodeFn.object());
			status = tima_tempForUndoDeleteDuplicate_modifier.doIt();
/*#ifdef _DEBUG
MGlobal::displayInfo( "tima_upstreamNodeTransform_name = " + tmpDagNodeFn.name());
if(status)cout<<endl<<"tima_tempForUndoDeleteDuplicate_modifier.doIt - success"<<endl;
else cout<<endl<<"tima_tempForUndoDeleteDuplicate_modifier.doIt - failed"<<endl;
#endif*/
			MCheckStatus( status, "tima_tempForUndoDeleteDuplicate_modifier.doIt" );
//########################################################################### /tima
		}

		status = undoTweakProcessing();
		MCheckStatus( status, "undoTweakProcessing" );

	}

	return status;
}
示例#9
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::processModifierNode( MObject modifierNode,
											  modifyPolyData& data )
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	MFnDependencyNode depNodeFn ( modifierNode );
	data.modifierNodeSrcAttr = depNodeFn.attribute( "outMesh" , &status);

	MCheckStatus( status, "Finden des outMesh Attributes" );

	data.modifierNodeDestAttr = depNodeFn.attribute( "inMesh" , &status );


	return status;
}
MStatus
PolyColourNode::compute( const MPlug& plug, MDataBlock& data )
{
	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 inputMesh = data.inputValue( m_inMesh, &status );
		//MCheckStatus(status,"ERROR getting inMesh");

		//MDataHandle outputMesh = data.outputValue( m_outMesh, &status );
		//MCheckStatus(status,"ERROR getting outMesh");

		// Simply redirect the inMesh to the outMesh for the PassThrough effect
		//
		//outputMesh.set(inputMesh.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 (1)
		{
		}
		else
		{
			status = MS::kUnknownParameter;
		}
	}

	return status;
}
示例#11
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::connectNodes( MObject modifierNode )
// --------------------------------------------------------------------------------------------
//
//	Description:
//
//		This method connects up the modifier nodes, while accounting for DG factors
//		such as construction history and tweaks. The method has a series of steps which
//		it runs through to process nodes under varying circumstances:
//
//		1) Gather meshNode connection data (ie. attributes and plugs)
//
//		2) Gather upstreamNode data - This is history-dependent. If the node has history,
//									  an actual upstreamNode exists and that is used to
//									  drive the input of our modifierNode.
//
//									  Otherwise, if the node ds not have history, the
//									  meshNode is duplicated, set as an intermediate object
//									  and regarded as our new upstreamNode which will drive
//									  the input of our modifierNode. The case with history
//									  already has this duplicate meshNode at the top, driving
//									  all other history nodes and serving as a reference
//									  to the "original state" of the node before any
//									  modifications.
//
//		3) Gather modifierNode connection data
//
//		4) Process tweak data (if it exists) - This is history-dependent. If there is
//											   history, the tweak data is extracted and deleted
//											   from the meshNode and encapsulated inside a
//											   polyTweak node. The polyTweak node is then
//											   inserted ahead of the modifier node.
//
//											   If there is no history, the same is done as
//											   in the history case, except the tweaks are
//											   deleted from the duplicate meshNode in addition
//											   to the actual meshNode.
//
//		5) Connect the nodes
//
//		6) Collapse/Bake nodes into the actual meshNode if the meshNode had no previous
//		   construction history and construction history recording is turned off.
//		   (ie. (!fHasHistory && !fHasRecordHistory) == true )
//
{
	MStatus status;

	// Declare our internal processing data structure (see polyModifierCmd.h for definition)
	//
	modifyPolyData data;	//->jetzt als ElementVariable

	// Get the mesh node, plugs and attributes
	//
	status = processMeshNode( data );
	MCheckStatus( status, "processMeshNode" );

	// Get upstream node, plugs and attributes
	//
	status = processUpstreamNode( data );
	MCheckStatus( status, "processUpstreamNode" );

	// Get the modifierNode attributes
	//
	status = processModifierNode( modifierNode,
						 data );
	MCheckStatus( status, "processModifierNode" );

	// Process tweaks on the meshNode
	//
	status = processTweaks( data );
	MCheckStatus( status, "processTweaks" );



	
	

	if( fHasTweaks )
	{

		status = fDGModifier.connect( data.upstreamNodeShape,
							 data.upstreamNodeSrcAttr,
							 data.tweakNode,
							 data.tweakNodeDestAttr );
		MCheckStatus( status, "upstream-tweak connect failed" );

		status = fDGModifier.connect( data.tweakNode,
							 data.tweakNodeSrcAttr,
							 modifierNode,
							 data.modifierNodeDestAttr );
		MCheckStatus( status, "tweak-modifier connect failed" );
	}
	else
	{
		//hier muessen die Plugs verwendet werden, weil die Attribute eventuell multis sind
		
		MPlug destPlug(modifierNode,data.modifierNodeDestAttr );
		
		INVIS(cout<<data.upstreamNodeSrcPlug.name().asChar()<<" --> "<<destPlug.name().asChar()<<endl);

		status = fDGModifier.connect( data.upstreamNodeSrcPlug,
										destPlug
									);
		MCheckStatus( status, "upstream-modifier connect failed" );
	}



	
	
	// outMesh mit inputMesh verbinden
	//
	fDGModifier.connect(MPlug(modifierNode,data.modifierNodeSrcAttr), data.meshNodeDestPlug);
	
	
	// Ausserdem das MatrixAttribut des Meshes mit dem meshMatrix Attr der Node verbinden
	//
	MFnDependencyNode depFn( modifierNode );
	MPlug	meshMatrix( modifierNode, depFn.attribute("meshMatrix") );



	depFn.setObject(data.meshNodeTransform);
	MPlug	shapeMatrix( data.meshNodeTransform, depFn.attribute("worldMatrix") );

	fDGModifier.connect(shapeMatrix.elementByLogicalIndex( 0 ), meshMatrix );


	
	

	// Jetzt die ModifierNode mit der VisNode connecten
/*	
	status = fDGModifier.connect( modifierNode,
						 data.modifierNodeSrcAttr,
						 data.meshNodeShape,
						 data.meshNodeDestAttr );
*/


//	MCheckStatus( status, "modifier-mesh connect failed" );



	status = fDGModifier.doIt();
	MCheckStatus( status, "modifier-mesh DOIT failed" );


	if(createAnimCurves)
	{
		//AnimCurve erstellen(dies ist nur hier moeglich, da die Node erst nach dem DoIt wirklich existiert (scheinbar)
		MFnAnimCurve	aCurve;

		MFnDependencyNode myDepNodeFn(modifierNode);

		aCurve.create(modifierNode,myDepNodeFn.attribute("csl"),MFnAnimCurve::kAnimCurveUU,&createSlideAnim,&status);
	}

	return status;
}
示例#12
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::processUpstreamNode( modifyPolyData& data )
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	// Declare our function sets - Although dagNodeFn derives from depNodeFn, we need
	//							   both since dagNodeFn can only refer to DAG objects.
	//							   We will use depNodeFn for all times other when dealing
	//							   with the DAG.
	//
	MFnDependencyNode	depNodeFn;
	MFnDagNode			dagNodeFn;

	// Use the selected node's plug connections to find the upstream plug.
	// Since we are looking at the selected node's inMesh attribute, it will
	// always have only one connection coming in if it has history, and none
	// otherwise.
	//
	// If there is no history, copy the selected node and place it ahead of the
	// modifierNode as the new upstream node so that the modifierNode has an
	// input mesh to operate on.
	//

	//save the meshDagPath for later use
	MDagPath::getAPathTo(data.meshNodeShape,myMeshPath);

	MPlugArray tempPlugArray;

 	if( fHasHistory )
	{
		// Since we have history, look for what connections exist on the
		// meshNode "inMesh" plug. "inMesh" plugs should only ever have one
		// connection.
		//
		data.meshNodeDestPlug.connectedTo( tempPlugArray, true, false);
		

		// ASSERT: Only one connection should exist on meshNodeShape.inMesh!
		//
		MStatusAssert( (tempPlugArray.length() == 1),
					   "tempPlugArray.length() == 1 -- 0 or >1 connections on meshNodeShape.inMesh" );
		data.upstreamNodeSrcPlug = tempPlugArray[0];

		
		// Construction history only deals with shapes, so we can grab the
		// upstreamNodeShape off of the source plug.
		//
		// Dieser Bereich muss bleiben, weil diese Attribute noch bentigt werden
		data.upstreamNodeShape = data.upstreamNodeSrcPlug.node();
		depNodeFn.setObject( data.upstreamNodeShape );
		data.upstreamNodeSrcAttr = data.upstreamNodeSrcPlug.attribute();
		

		// Disconnect the upstream node and the selected node, so we can
		// replace them with our own connections below.
		//
		MPlug	nodePlug(data.meshNodeShape,data.meshNodeDestAttr ) ;
		INVIS(cout<<data.upstreamNodeSrcPlug.name().asChar()<<" --|-- "<<nodePlug.name().asChar()<<endl);
		status =	fDGModifier.disconnect( data.upstreamNodeSrcPlug,
											nodePlug );
											
		
		MCheckStatus( status, "Disconnect Upstream mit meshNode" );


	}
	else	// No History (!fHasHistory)
	{
		// Use the DAG node function set to duplicate the shape of the meshNode.
		// The duplicate method will return an MObject handle to the transform
		// of the duplicated shape, so traverse the dag to locate the shape. Store
		// this duplicate shape as our "upstream" node to drive the input for the 
		// modifierNode.
		//
		depNodeFn.setObject( data.meshNodeShape );
		data.upstreamNodeTransform = createDuplicate.createNode("mesh");
		createDuplicate.doIt();

		dagNodeFn.setObject( data.upstreamNodeTransform );
		

		// Ensure that our upstreamNode is pointing to a shape.
		//
		MStatusAssert( (0 < dagNodeFn.childCount()),
					   "0 < dagNodeFn.childCount() -- Duplicate meshNode transform has no shape." );
		data.upstreamNodeShape = dagNodeFn.child(0);

		MPlug outMeshPlug = depNodeFn.findPlug("outMesh");
		depNodeFn.setObject(data.upstreamNodeShape);

		//jetzt inMesh upstreamNodeShape mit outMesh meshShape füllen
		MDGModifier tempMod;
		tempMod.connect(outMeshPlug,depNodeFn.findPlug("inMesh"));
		tempMod.doIt();

		//force DGEVAL
		MString cmd = "dgeval -src ";
		cmd += depNodeFn.name();
		cmd += ".outMesh";
		MGlobal::executeCommand(cmd,false,false);

		tempMod.undoIt();

		
		// Re-parent the upstreamNodeShape under our original transform
		//
		reparentDuplicate.reparentNode( data.upstreamNodeShape, data.meshNodeTransform );
		reparentDuplicate.doIt();


		deleteDuplicate.deleteNode( data.upstreamNodeTransform );
		deleteDuplicate.doIt();
		/*
		status = fDagModifier.reparentNode( data.upstreamNodeShape, data.meshNodeTransform );
		MCheckStatus( status, "reparentNode" );

		// Perform the DAG re-parenting
		// 
		// Note: This reparent must be performed before the deleteNode() is called.
		//		 See polyModifierCmd.h (see definition of fDagModifier) for more details.
		//
		status = fDagModifier.doIt();
		MCheckStatus( status, "fDagModifier.doIt()" );
		*/
		// Mark the upstreamNodeShape (the original shape) as an intermediate object
		// (making it invisible to the user)
		//
		dagNodeFn.setObject( data.upstreamNodeShape );
		dagNodeFn.setIntermediateObject( true );

		// Get the upstream node source attribute
		//
		data.upstreamNodeSrcAttr = dagNodeFn.attribute( "outMesh" );
		data.upstreamNodeSrcPlug = MPlug(data.upstreamNodeShape, data.upstreamNodeSrcAttr);

		/*
		// Remove the duplicated transform node (clean up)
		//
		status = fDagModifier.deleteNode( data.upstreamNodeTransform );
		MCheckStatus( status, "deleteNode" );

		// Perform the DAG delete node
		//
		// Note: This deleteNode must be performed after the reparentNode() method is
		//		 completed. See polyModifierCmd.h (see definition of fDagModifier) for
		//		 details.
		//
		status = fDagModifier.doIt();
		MCheckStatus( status, "fDagModifier.doIt()" );
		*/

		// Cache the DAG path to the duplicate shape
		//
		dagNodeFn.getPath( fDuplicateDagPath );

		//finally delete the tweaks to avoid double transformation
		deleteTweaks();
	}

	return status;
}
示例#13
0
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;
}
示例#14
0
MStatus sseDeformer::compute(const MPlug& plug, MDataBlock& data)
{
    MStatus status;
    if (plug.attribute() != outputGeom) {
        printf("Ignoring requested plug\n");
        return status;
    }
    unsigned int index = plug.logicalIndex();
    MObject thisNode = this->thisMObject();

    // get input value
    MPlug inPlug(thisNode,input);
    inPlug.selectAncestorLogicalIndex(index,input);
    MDataHandle hInput = data.inputValue(inPlug, &status);
    MCheckStatus(status, "ERROR getting input mesh\n");

    // get the input geometry
    MDataHandle inputData = hInput.child(inputGeom);
    if (inputData.type() != MFnData::kMesh) {
        printf("Incorrect input geometry type\n");
        return MStatus::kFailure;
    }

    MObject iSurf = inputData.asMesh() ;
    MFnMesh inMesh;
    inMesh.setObject( iSurf ) ;

    MDataHandle outputData = data.outputValue(plug);
    outputData.copy(inputData);
    if (outputData.type() != MFnData::kMesh) {
        printf("Incorrect output mesh type\n");
        return MStatus::kFailure;
    }

    MObject oSurf = outputData.asMesh() ;
    if(oSurf.isNull()) {
        printf("Output surface is NULL\n");
        return MStatus::kFailure;
    }

    MFnMesh outMesh;
    outMesh.setObject( oSurf ) ;
    MCheckStatus(status, "ERROR setting points\n");

    // get all points at once for demo purposes. Really should get points from the current group using iterator
    MFloatPointArray pts;
    outMesh.getPoints(pts);

    int nPoints = pts.length();

    MDataHandle envData = data.inputValue(envelope, &status);
    float env = envData.asFloat();

    MDataHandle sseData = data.inputValue(sseEnabled, &status);
    bool sseEnabled = (bool) sseData.asBool();

    // NOTE: Using MTimer and possibly other classes disables
    // autovectorization with Intel <=10.1 compiler on OSX and Linux!!
    // Must compile this function with -fno-exceptions on OSX and
    // Linux to guarantee autovectorization is done. Use -fvec_report2
    // to check for vectorization status messages with Intel compiler.
    MTimer timer;
    timer.beginTimer();

    if(sseEnabled) {

        // Innter loop will autovectorize. Around 3x faster than the
        // loop below it. It would be faster if first element was
        // guaranteed to be aligned on 16 byte boundary.
        for(int i=0; i<nPoints; i++) {
            float* ptPtr = &pts[i].x;
            for(int j=0; j<4; j++) {
                ptPtr[j] = env * (cosf(ptPtr[j]) * sinf(ptPtr[j]) * tanf(ptPtr[j]));
            }
        }

    } else {

        // This inner loop will not autovectorize.
        for(int i=0; i<nPoints; i++) {
            MFloatPoint& pt = pts[i];
            for(int j=0; j<3; j++) {
                pt[j] = env * (cosf(pt[j]) * sinf(pt[j]) * tanf(pt[j]));
            }

        }
    }

    timer.endTimer();
    if(sseEnabled) {
        printf("SSE enabled, runtime %f\n", timer.elapsedTime());
    } else {
        printf("SSE disabled, runtime %f\n", timer.elapsedTime());
    }

    outMesh.setPoints(pts);

    return status;
}
示例#15
0
//----------------------------------------------------------------------------
MStatus		BPT_InsertVtx::initialize()
//----------------------------------------------------------------------------
{
	
	
	MFnEnumAttribute	FnEnumAttr;
	MFnTypedAttribute	FnTypedAttr;
	MFnNumericAttribute	FnFloatAttr;
	MStatus				status;

	

	IVinMesh = FnTypedAttr.create("inMesh","in",MFnData::kMesh);
	FnTypedAttr.setStorable(true);
	//FnTypedAttr.setCached(false);
	FnTypedAttr.setInternal(true);
	

	IVoutMesh = FnTypedAttr.create("outMesh","out",MFnData::kMesh);
	FnTypedAttr.setStorable(true);
	FnTypedAttr.setWritable(false);



	IVcount = FnFloatAttr.create("count","c",MFnNumericData::kLong);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setInternal(true);
	FnFloatAttr.setKeyable(true);
	FnFloatAttr.setMin(1);
	FnFloatAttr.setSoftMax(15);
	
	

	IVselEdgeIDs = FnTypedAttr.create("edgeIDs","eID",MFnData::kIntArray);
	FnTypedAttr.setStorable(true);
	FnTypedAttr.setHidden(true);
	FnTypedAttr.setConnectable(false);


	
	IVselVertIDs = FnTypedAttr.create("vertIDs","vID",MFnData::kIntArray);
	FnTypedAttr.setStorable(true);
	FnTypedAttr.setHidden(true);
	FnTypedAttr.setConnectable(false);


	
	IVoptions = FnTypedAttr.create("options","op",MFnData::kIntArray);
	FnTypedAttr.setStorable(true);
	FnTypedAttr.setHidden(true);
	FnTypedAttr.setConnectable(false);


	IVslide = FnFloatAttr.create("slide","sl",MFnNumericData::kDouble);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setInternal(true);
//	FnFloatAttr.setMin(0.0);
//	FnFloatAttr.setMax(1.0);
	FnFloatAttr.setKeyable(true);

	IVnormal = FnFloatAttr.create("alongNormal","an",MFnNumericData::kDouble);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setDefault(0.0);
	FnFloatAttr.setKeyable(true);

	IVslideRelative = FnFloatAttr.create("slideRelative","sr",MFnNumericData::kLong);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setMin(0.0);
	FnFloatAttr.setMax(1.0);
	FnFloatAttr.setKeyable(true);
	

	IVnormalRelative = FnFloatAttr.create("normalRelative","nr",MFnNumericData::kLong);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setMin(0.0);
	FnFloatAttr.setMax(1.0);
	FnFloatAttr.setKeyable(true);


	IVwhichSide = FnFloatAttr.create("side","si",MFnNumericData::kLong);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setMin(0.0);
	FnFloatAttr.setMax(1.0);
	FnFloatAttr.setKeyable(true);

	IVSlideLimited = FnFloatAttr.create("slideLimited","sll",MFnNumericData::kLong);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setMin(0.0);
	FnFloatAttr.setMax(1.0);
	FnFloatAttr.setKeyable(false);


	IVspin = FnFloatAttr.create("spin","sp",MFnNumericData::kLong);
	FnFloatAttr.setStorable(true);
	FnFloatAttr.setMin(0.0);
	FnFloatAttr.setKeyable(true);
	FnFloatAttr.setInternal(true);



	// Add attributes

	status = addAttribute(IVslideRelative);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVnormalRelative);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVwhichSide);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVnormal);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVslide);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVSlideLimited);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVoptions);
	MCheckStatus(status, "AddAttrIVNode");
		
	status = addAttribute(IVspin);
	MCheckStatus(status, "AddAttrIVNode");
	
	status = addAttribute(IVcount);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVselEdgeIDs);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVselVertIDs);
	MCheckStatus(status, "AddAttrIVNode");



	status = addAttribute(IVoutMesh);
	MCheckStatus(status, "AddAttrIVNode");

	status = addAttribute(IVinMesh);
	MCheckStatus(status, "AddAttrIVNode");





	// Add attribute affects

	status = attributeAffects( IVspin, IVoutMesh );
	MCheckStatus(status, "AddAttrAffectsIVNode");

	status = attributeAffects( IVcount, IVoutMesh );
	MCheckStatus(status, "AddAttrAffectsIVNode");

	status = attributeAffects( IVinMesh, IVoutMesh );
	MCheckStatus(status, "AddAttrAffectsIVNode");

	status = attributeAffects( IVslide, IVoutMesh);
	MCheckStatus(status, "AddAttrAffectsIVNode");
		
	status = attributeAffects( IVslideRelative, IVoutMesh);
	MCheckStatus(status, "AddAttrAffectsIVNode");

	status = attributeAffects( IVnormalRelative, IVoutMesh);
	MCheckStatus(status, "AddAttrAffectsIVNode");

	status = attributeAffects( IVwhichSide, IVoutMesh);
	MCheckStatus(status, "AddAttrAffectsIVNode");
		
	status = attributeAffects( IVnormal, IVoutMesh);
	MCheckStatus(status, "AddAttrAffectsIVNode");



	// Zuletzt die SoftTransformationAttribute hinzufuegen
	// Per Macro - dirty, aber funktioniert - wie machen die ALIAS Typen das ??? Die leiten auch stuendig von einer BaseNode ab, und da gehen dann keine Attribute flueten
	// Oder werden unbrauchbar so wie bei mir, so dass im Endeffekt suemtliche Attribute ein eindeutiges statisches Attribut haben muessen

	STE_ADD_ATTRIBUTES(IV)


		return status;
}
示例#16
0
MStatus polyModifierCmd::connectNodes( MObject modifierNode )
//
//	Description:
//
//		This method connects up the modifier nodes, while accounting for DG factors
//		such as construction history and tweaks. The method has a series of steps which
//		it runs through to process nodes under varying circumstances:
//
//		1) Gather meshNode connection data (ie. attributes and plugs)
//
//		2) Gather upstreamNode data - This is history-dependent. If the node has history,
//									  an actual upstreamNode exists and that is used to
//									  drive the input of our modifierNode.
//
//									  Otherwise, if the node does not have history, the
//									  meshNode is duplicated, set as an intermediate object
//									  and regarded as our new upstreamNode which will drive
//									  the input of our modifierNode. The case with history
//									  already has this duplicate meshNode at the top, driving
//									  all other history nodes and serving as a reference
//									  to the "original state" of the node before any
//									  modifications.
//
//		3) Gather modifierNode connection data
//
//		4) Process tweak data (if it exists) - This is history-dependent. If there is
//											   history, the tweak data is extracted and deleted
//											   from the meshNode and encapsulated inside a
//											   polyTweak node. The polyTweak node is then
//											   inserted ahead of the modifier node.
//
//											   If there is no history, the same is done as
//											   in the history case, except the tweaks are
//											   deleted from the duplicate meshNode in addition
//											   to the actual meshNode.
//
//		5) Connect the nodes
//
//		6) Collapse/Bake nodes into the actual meshNode if the meshNode had no previous
//		   construction history and construction history recording is turned off.
//		   (ie. (!fHasHistory && !fHasRecordHistory) == true )
//
{
	MStatus status;

	// Declare our internal processing data structure (see polyModifierCmd.h for definition)
	//
	modifyPolyData data;

	// Get the mesh node, plugs and attributes
	//
	status = processMeshNode( data );
	MCheckStatus( status, "processMeshNode" );

	// Get upstream node, plugs and attributes
	//
	status = processUpstreamNode( data );
	MCheckStatus( status, "processUpstreamNode" );

	// Get the modifierNode attributes
	//
	status = processModifierNode( modifierNode,
						 data );
	MCheckStatus( status, "processModifierNode" );

	// Process tweaks on the meshNode
	//
	status = processTweaks( data );
	MCheckStatus( status, "processTweaks" );

	// Connect the nodes
	//
	if( fHasTweaks )
	{
		status = fDGModifier.connect( data.upstreamNodeShape,
							 data.upstreamNodeSrcAttr,
							 data.tweakNode,
							 data.tweakNodeDestAttr );
		MCheckStatus( status, "upstream-tweak connect failed" );

		status = fDGModifier.connect( data.tweakNode,
							 data.tweakNodeSrcAttr,
							 modifierNode,
							 data.modifierNodeDestAttr );
		MCheckStatus( status, "tweak-modifier connect failed" );
	}
	else
	{
		status = fDGModifier.connect( data.upstreamNodeShape,
							 data.upstreamNodeSrcAttr,
							 modifierNode,
							 data.modifierNodeDestAttr );
		MCheckStatus( status, "upstream-modifier connect failed" );
	}
	
	status = fDGModifier.connect( modifierNode,
						 data.modifierNodeSrcAttr,
						 data.meshNodeShape,
						 data.meshNodeDestAttr );
	MCheckStatus( status, "modifier-mesh connect failed" );
	
	status = fDGModifier.doIt();

	return status;
}
示例#17
0
MStatus polyModifierCmd::processUpstreamNode( modifyPolyData& data )
{
	MStatus status = MS::kSuccess;

	// Declare our function sets - Although dagNodeFn derives from depNodeFn, we need
	//							   both since dagNodeFn can only refer to DAG objects.
	//							   We will use depNodeFn for all times other when dealing
	//							   with the DAG.
	//
	MFnDependencyNode	depNodeFn;
	MFnDagNode			dagNodeFn;

	// Use the selected node's plug connections to find the upstream plug.
	// Since we are looking at the selected node's inMesh attribute, it will
	// always have only one connection coming in if it has history, and none
	// otherwise.
	//
	// If there is no history, copy the selected node and place it ahead of the
	// modifierNode as the new upstream node so that the modifierNode has an
	// input mesh to operate on.
	//
	MPlugArray tempPlugArray;

	if( fHasHistory )
	{
		// Since we have history, look for what connections exist on the
		// meshNode "inMesh" plug. "inMesh" plugs should only ever have one
		// connection.
		//
		data.meshNodeDestPlug.connectedTo( tempPlugArray, true, false);

		// ASSERT: Only one connection should exist on meshNodeShape.inMesh!
		//
		MStatusAssert( (tempPlugArray.length() == 1),
					   "tempPlugArray.length() == 1 -- 0 or >1 connections on meshNodeShape.inMesh" );
		data.upstreamNodeSrcPlug = tempPlugArray[0];

		// Construction history only deals with shapes, so we can grab the
		// upstreamNodeShape off of the source plug.
		//
		data.upstreamNodeShape = data.upstreamNodeSrcPlug.node();
		depNodeFn.setObject( data.upstreamNodeShape );
		data.upstreamNodeSrcAttr = data.upstreamNodeSrcPlug.attribute();

		// Disconnect the upstream node and the selected node, so we can
		// replace them with our own connections below.
		//
		fDGModifier.disconnect( data.upstreamNodeShape,
								data.upstreamNodeSrcAttr,
								data.meshNodeShape,
								data.meshNodeDestAttr );

	}
	else	// No History (!fHasHistory)
	{
		// Use the DAG node function set to duplicate the shape of the meshNode.
		// The duplicate method will return an MObject handle to the transform
		// of the duplicated shape, so traverse the dag to locate the shape. Store
		// this duplicate shape as our "upstream" node to drive the input for the 
		// modifierNode.
		//
		dagNodeFn.setObject( data.meshNodeShape );
		data.upstreamNodeTransform = dagNodeFn.duplicate( false, false );
		dagNodeFn.setObject( data.upstreamNodeTransform );


		// Ensure that our upstreamNode is pointing to a shape.
		//
		MStatusAssert( (0 < dagNodeFn.childCount()),
					   "0 < dagNodeFn.childCount() -- Duplicate meshNode transform has no shape." );
		data.upstreamNodeShape = dagNodeFn.child(0);

		// Re-parent the upstreamNodeShape under our original transform
		//
		status = fDagModifier.reparentNode( data.upstreamNodeShape, data.meshNodeTransform );
		MCheckStatus( status, "reparentNode" );

		// Perform the DAG re-parenting
		// 
		// Note: This reparent must be performed before the deleteNode() is called.
		//		 See polyModifierCmd.h (see definition of fDagModifier) for more details.
		//
		status = fDagModifier.doIt();
		MCheckStatus( status, "fDagModifier.doIt()" );

		// Mark the upstreamNodeShape (the original shape) as an intermediate object
		// (making it invisible to the user)
		//
		dagNodeFn.setObject( data.upstreamNodeShape );
		dagNodeFn.setIntermediateObject( true );

		// Get the upstream node source attribute
		//
		data.upstreamNodeSrcAttr = dagNodeFn.attribute( "outMesh" );

		// Remove the duplicated transform node (clean up)
		//
		status = fDagModifier.deleteNode( data.upstreamNodeTransform );
		MCheckStatus( status, "deleteNode" );

		// Perform the DAG delete node
		//
		// Note: This deleteNode must be performed after the reparentNode() method is
		//		 completed. See polyModifierCmd.h (see definition of fDagModifier) for
		//		 details.
		//
		status = fDagModifier.doIt();
		MCheckStatus( status, "fDagModifier.doIt()" );

		// Cache the DAG path to the duplicate shape
		//
		dagNodeFn.getPath( fDuplicateDagPath );
	}

	return status;
}
示例#18
0
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;
}
示例#19
0
MStatus splitUVNode::compute( const MPlug& plug, MDataBlock& data )
//
//	Description:
//		This method computes the value of the given output plug based
//		on the values of the input attributes.
//
//	Arguments:
//		plug - the plug to compute
//		data - object that provides access to the attributes for this node
//
{
	MStatus status = MS::kSuccess;
 
	MDataHandle stateData = data.outputValue( state, &status );
	MCheckStatus( status, "ERROR getting state" );

	// Check for the HasNoEffect/PassThrough flag on the node.
	//
	// (stateData is an enumeration standard in all depend nodes - stored as short)
	// 
	// (0 = Normal)
	// (1 = HasNoEffect/PassThrough)
	// (2 = Blocking)
	// ...
	//
	if( stateData.asShort() == 1 )
	{
		MDataHandle inputData = data.inputValue( inMesh, &status );
		MCheckStatus(status,"ERROR getting inMesh");

		MDataHandle outputData = data.outputValue( outMesh, &status );
		MCheckStatus(status,"ERROR getting outMesh");

		// Simply redirect the inMesh to the outMesh for the PassThrough effect
		//
		outputData.set(inputData.asMesh());
	}
	else
	{
		// Check which output attribute we have been asked to 
		// compute. If this node doesn't know how to compute it, 
		// we must return MS::kUnknownParameter
		// 
		if (plug == outMesh)
		{
			MDataHandle inputData = data.inputValue( inMesh, &status );
			MCheckStatus(status,"ERROR getting inMesh");

			MDataHandle outputData = data.outputValue( outMesh, &status );
			MCheckStatus(status,"ERROR getting outMesh"); 

			// Now, we get the value of the uvList and use it to perform
			// the operation on this mesh
			//
			MDataHandle inputUVs = data.inputValue( uvList, &status);
			MCheckStatus(status,"ERROR getting uvList"); 
			
			// Copy the inMesh to the outMesh, and now you can
			// perform operations in-place on the outMesh
			//
			outputData.set(inputData.asMesh());
			MObject mesh = outputData.asMesh();

			// Retrieve the UV list from the component list.
			//
			// Note, we use a component list to store the components
			// because it is more compact memory wise. (ie. comp[81:85]
			// is smaller than comp[81], comp[82],...,comp[85])
			//
			MObject compList = inputUVs.data();
			MFnComponentListData compListFn( compList );

			unsigned i;
			int j;
			MIntArray uvIds;

			for( i = 0; i < compListFn.length(); i++ )
			{
				MObject comp = compListFn[i];
				if( comp.apiType() == MFn::kMeshMapComponent )
				{
					MFnSingleIndexedComponent uvComp( comp );
					for( j = 0; j < uvComp.elementCount(); j++ )
					{
						int uvId = uvComp.element(j);
						uvIds.append( uvId );
					}
				}
			}

			// Set the mesh object and uvList on the factory
			//
			fSplitUVFactory.setMesh( mesh );
			fSplitUVFactory.setUVIds( uvIds );

			// Now, perform the splitUV
			//
			status = fSplitUVFactory.doIt();

			// Mark the output mesh as clean
			//
			outputData.setClean();
		}
		else
		{
			status = MS::kUnknownParameter;
		}
	}

	return status;
}
示例#20
0
MStatus updateTCCDataNode::initialize()
//
//    Description:
//        This method is called to create and initialize all of the attributes
//      and attribute dependencies for this node type.  This is only called 
//        once when the node type is registered with Maya.
//
//    Return Values:
//        MS::kSuccess
//        MS::kFailure
//        
{
    MStatus             status;

    MFnTypedAttribute   attrFn;
    MFnNumericAttribute attrNum;

    MIntArray defaultArray;
    MFnIntArrayData defaultArrayDataFn; 
    
    defaultArrayDataFn.create( defaultArray );
    vtxRemap = attrFn.create("vtxRemap", "vR", MFnData::kIntArray, defaultArrayDataFn.object());
    attrFn.setStorable(true);

    defaultArrayDataFn.create( defaultArray );
    polyOrder = attrFn.create("polyOrder", "pO", MFnData::kIntArray, defaultArrayDataFn.object());
    attrFn.setStorable(true);
    
    defaultArrayDataFn.create( defaultArray );
    cShift = attrFn.create("cShift", "cS", MFnData::kIntArray, defaultArrayDataFn.object());
    attrFn.setStorable(true);
    
    defaultArrayDataFn.create( defaultArray );
    delta_F = attrFn.create("delta_F", "dF", MFnData::kIntArray, defaultArrayDataFn.object());
    attrFn.setStorable(true);
    
    defaultArrayDataFn.create( defaultArray );
    delta_nFV = attrFn.create("delta_nFV", "dnFV", MFnData::kIntArray, defaultArrayDataFn.object());
    attrFn.setStorable(true);
    
    nV = attrNum.create("nV", "nV", MFnNumericData::kInt, 0.0);
    attrFn.setStorable(true);
    
    inMesh = attrFn.create("inMesh", "iM", MFnMeshData::kMesh);
    attrFn.setStorable(true);


    outMesh = attrFn.create("outMesh", "om", MFnMeshData::kMesh);
    attrFn.setStorable(false);
    attrFn.setWritable(false);


    
    
    status = addAttribute( vtxRemap );
    MCheckStatus(status,"ERROR addAttribute"); 

    status = addAttribute( polyOrder );
    MCheckStatus(status,"ERROR addAttribute"); 

    status = addAttribute( cShift );
    MCheckStatus(status,"ERROR addAttribute"); 
    
    status = addAttribute( delta_F );
    MCheckStatus(status,"ERROR addAttribute"); 

    status = addAttribute( delta_nFV );
    MCheckStatus(status,"ERROR addAttribute"); 

    status = addAttribute( nV );
    MCheckStatus(status,"ERROR addAttribute"); 

    status = addAttribute( inMesh );
    MCheckStatus(status,"ERROR addAttribute"); 

    status = addAttribute( outMesh);
    MCheckStatus(status,"ERROR addAttribute"); 



    
    status = attributeAffects( inMesh, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 

    status = attributeAffects( vtxRemap, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 

    status = attributeAffects( polyOrder, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 

    status = attributeAffects( cShift, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 
    
    status = attributeAffects( delta_F, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 
    
    status = attributeAffects( delta_nFV, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 
    
    status = attributeAffects( nV, outMesh );
    MCheckStatus(status,"ERROR attributeAffects"); 

    return MS::kSuccess;

}
示例#21
0
MStatus updateTCCDataNode::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"); 

            MIntArray vR = MFnIntArrayData( data.inputValue( vtxRemap ).data() ).array(&status);
            MCheckStatus(status,"ERROR getting vtxRemap");
            
            MIntArray pO = MFnIntArrayData( data.inputValue( polyOrder ).data() ).array(&status);
            MCheckStatus(status,"ERROR getting polyOrder");

            MIntArray cS = MFnIntArrayData( data.inputValue( cShift ).data() ).array(&status);
            MCheckStatus(status,"ERROR getting cShift");
            
            MIntArray dnFV = MFnIntArrayData( data.inputValue( delta_nFV ).data() ).array(&status);
            MCheckStatus(status,"ERROR getting deltanFV");

            MIntArray dF = MFnIntArrayData( data.inputValue( delta_F ).data() ).array(&status);
            MCheckStatus(status,"ERROR getting deltaF");
            
            int nVtx = data.inputValue( nV ).asInt();
            MCheckStatus(status,"ERROR getting nV");
            
            // 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();
            
            fupdateTCCDataFactory.setMesh( mesh );
            fupdateTCCDataFactory.setVtxRemap( vR );
            fupdateTCCDataFactory.setPolyOrder( pO );
            fupdateTCCDataFactory.setCShift( cS );
            fupdateTCCDataFactory.setDelta_nFV( dnFV );
            fupdateTCCDataFactory.setDelta_F( dF );
            fupdateTCCDataFactory.setnV( nVtx );

            // Now, perform the updateTCCData
            //
            status = fupdateTCCDataFactory.doIt();

            // Mark the output mesh as clean
            //
            outputData.setClean();
        }
        else
        {
            status = MS::kUnknownParameter;
        }
    }

    return status;
}
示例#22
0
MStatus finalproject::initialize()
{
	// local attribute initialization
	MStatus status;
	MFnTypedAttribute mAttr;
 	deformingMesh=mAttr.create( "deformingMesh", "dm", MFnMeshData::kMesh);
 	
 	MFnNumericAttribute nAttrt;
 	transX = nAttrt.create( "transX", "tx", MFnNumericData::kDouble);
 	nAttrt.setStorable(true);
 	
 	status = addAttribute( transX );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( transX, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");
	
	transY = nAttrt.create( "transY", "ty", MFnNumericData::kDouble);
 	nAttrt.setStorable(true);
 	
 	status = addAttribute( transY );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( transY, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");
	
	transZ = nAttrt.create( "transZ", "tz", MFnNumericData::kDouble);
 	nAttrt.setStorable(true);
 	
 	status = addAttribute( transZ );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( transZ, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");
	
	tesla = nAttrt.create( "tesla", "tes", MFnNumericData::kDouble);
	nAttrt.setStorable(true);
	nAttrt.setKeyable(true);
	nAttrt.setDefault(0.0);
	nAttrt.setMin(0.0);
	nAttrt.setMax(300.0);
	
 	status = addAttribute( tesla );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( tesla, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");
	
   positivelycharged = nAttrt.create( "positivelycharged", "pc", MFnNumericData::kBoolean);
	nAttrt.setStorable(true);
	nAttrt.setKeyable(true);
	nAttrt.setDefault(true);
	
 	status = addAttribute( positivelycharged );
	MCheckStatus(status, "ERROR in addAttribute\n");

	MCheckStatus(status, "ERROR in attributeAffects\n");
 	
 	MFnNumericAttribute nAttrO;
 	offload=nAttrO.create( "offload", "ol", MFnNumericData::kBoolean);
 	nAttrO.setStorable(true);
 	nAttrO.setDefault(false);
 	nAttrO.setKeyable(true);
	
 	//  deformation attributes
 	status = addAttribute( deformingMesh );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( deformingMesh, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");
	
   status = addAttribute( offload );
	MCheckStatus(status, "ERROR in addAttribute\n");

 	status = attributeAffects( offload, outputGeom );
	MCheckStatus(status, "ERROR in attributeAffects\n");

	return MStatus::kSuccess;
}
示例#23
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::undoCachedMesh()
// --------------------------------------------------------------------------------------------
{
	MStatus status;

	// Only need to restore the cached mesh if there was no history. Also
	// check to make sure that we are in the record history state.
	//
	MStatusAssert( (fHasRecordHistory), "fHasRecordHistory == true" );

	if( !fHasHistory )
	{
		MFnDependencyNode depNodeFn;

		MString meshNodeName;
		MObject meshNodeShape;
		MPlug	meshNodeDestPlug;
		MPlug	meshNodeOutMeshPlug;
		MObject dupMeshNodeShape;
		MPlug	dupMeshNodeSrcPlug;

		meshNodeShape = fDagPath.node();
		dupMeshNodeShape = fDuplicateDagPath.node();

		depNodeFn.setObject( meshNodeShape );
		meshNodeName = depNodeFn.name();
		meshNodeDestPlug = depNodeFn.findPlug( "inMesh", &status );
		MCheckStatus( status, "Could not retrieve inMesh" );
		meshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
		MCheckStatus( status, "Could not retrieve outMesh" );

		depNodeFn.setObject( dupMeshNodeShape );
		dupMeshNodeSrcPlug = depNodeFn.findPlug( "outMesh", &status );
		MCheckStatus( status, "Could not retrieve outMesh" );

		// For the case with tweaks, we cannot write the mesh directly back onto
		// the cachedInMesh, since the shape can have out of date information from the
		// cachedInMesh, thus we temporarily connect the duplicate mesh shape to the
		// mesh shape and force a DG evaluation.
		//
		// For the case without tweaks, we can simply write onto the outMesh, since
		// the shape relies solely on an outMesh when there is no history nor tweaks.
		//
		if( fHasTweaks )
		{
			MDGModifier dgModifier;
			dgModifier.connect( dupMeshNodeSrcPlug, meshNodeDestPlug );
			status = dgModifier.doIt();
			MCheckStatus( status, "Could not connect dupMeshNode -> meshNode" );

			// Need to force a DG evaluation now that the input has been changed.
			//
			MString cmd( "dgeval -src " );
			cmd += meshNodeName;
			cmd += ".outMesh";	//outMesh statt inMesh, damit undo (ohne history) funzt
			status = MGlobal::executeCommand( cmd, false, false );
			MCheckStatus( status, "Could not force DG eval" );

			// Disconnect the duplicate meshNode now
			//
			dgModifier.undoIt();

			
		}
		else
		{
			MObject meshData;
			status = dupMeshNodeSrcPlug.getValue( meshData );
			MCheckStatus( status, "Could not retrieve meshData" );

			status = meshNodeOutMeshPlug.setValue( meshData );
			MCheckStatus( status, "Could not set outMesh" );

			
		}
	}

	return status;
}
示例#24
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::undoDirectModifier()
// --------------------------------------------------------------------------------------------
{
	MStatus status;

	MFnDependencyNode depNodeFn;
	MFnDagNode dagNodeFn;

	MObject meshNode = fDagPath.node();
	depNodeFn.setObject( meshNode );
	
	// For the case with tweaks, we cannot write the mesh directly back onto
	// the cachedInMesh, since the shape can have out of date information from the
	// cachedInMesh. Thus we temporarily create an duplicate mesh, place our
	// old mesh on the outMesh attribute of our duplicate mesh, connect the
	// duplicate mesh shape to the mesh shape, and force a DG evaluation.
	//
	// For the case without tweaks, we can simply write onto the outMesh, since
	// the shape relies solely on an outMesh when there is no history nor tweaks.
	//
	if( fHasTweaks )
	{
		// Retrieve the inMesh and name of our mesh node (for the DG eval)
		//
		depNodeFn.setObject( meshNode );
		MPlug meshNodeInMeshPlug = depNodeFn.findPlug( "inMesh", &status );
		MCheckStatus( status, "Could not retrieve inMesh" );
		MString meshNodeName = depNodeFn.name();

		// Duplicate our current mesh
		//
		dagNodeFn.setObject( meshNode );
		MObject dupMeshNode = dagNodeFn.duplicate();

		// The dagNodeFn::duplicate() returns a transform, but we need a shape
		// so retrieve the DAG path and extend it to the shape.
		//
		MDagPath dupMeshDagPath;
		MDagPath::getAPathTo( dupMeshNode, dupMeshDagPath );
		dupMeshDagPath.extendToShape();

		// Retrieve the outMesh of the duplicate mesh and set our mesh data back
		// on it.
		//
		depNodeFn.setObject( dupMeshDagPath.node() );
		MPlug dupMeshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
		MCheckStatus( status, "Could not retrieve outMesh" );
		status = dupMeshNodeOutMeshPlug.setValue( fMeshData );

		// Temporarily connect the duplicate mesh node to our mesh node
		//
		MDGModifier dgModifier;
		dgModifier.connect( dupMeshNodeOutMeshPlug, meshNodeInMeshPlug );
		status = dgModifier.doIt();
		MCheckStatus( status, "Could not connect dupMeshNode -> meshNode" );

		// Need to force a DG evaluation now that the input has been changed.
		//
		MString cmd("dgeval -src ");
		cmd += meshNodeName;
		cmd += ".inMesh";
		status = MGlobal::executeCommand( cmd, false, false );
		MCheckStatus( status, "Could not force DG eval" );

		// Disconnect and delete the duplicate mesh node now
		//
		dgModifier.undoIt();
		MGlobal::deleteNode( dupMeshNode );

		// Restore the tweaks on the mesh
		//
		status = undoTweakProcessing();
	}
	else
	{
		// Restore the original mesh by writing the old mesh data (fMeshData) back
		// onto the outMesh of our meshNode
		//
		depNodeFn.setObject( meshNode );
		MPlug meshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
		MCheckStatus( status, "Could not retrieve outMesh" );
		status = meshNodeOutMeshPlug.setValue( fMeshData );
		MCheckStatus( status, "Could not set meshData" );
	}

	return status;
}
示例#25
0
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;
}
示例#26
0
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;
}