Пример #1
0
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void ConnectIntWeld( vm::CUndo &undo, const MObject &weldNodeObj, const MDagPath &toWeldPath, int nType, int nIntValue, const MMatrix &offsetMatrix )
{
	MFnDependencyNode weldFn( weldNodeObj );
	MFnDagNode toWeldFn( toWeldPath );

	MPlug wiAP = weldFn.findPlug( CVstWeldNode::m_iaWeldInput );
	const uint nWeldIndex = vm::NextAvailable( wiAP );
	MPlug wiP = wiAP.elementByLogicalIndex( nWeldIndex );

	undo.SetAttr( wiP.child( CVstWeldNode::m_iaType ), nType );
	undo.SetAttr( wiP.child( CVstWeldNode::m_iaInt ), nIntValue );

	MFnMatrixData dFn;
	MObject mdObj = dFn.create( offsetMatrix );
	undo.SetAttr( wiP.child( CVstWeldNode::m_iaOffsetMatrix ), mdObj );

	undo.Connect( toWeldFn.findPlug( "parentInverseMatrix" ).elementByLogicalIndex( toWeldPath.instanceNumber() ), wiP.child( CVstWeldNode::m_iaInverseParentSpace ), true );
	undo.Connect( toWeldFn.findPlug( "rotateOrder" ), wiP.child( CVstWeldNode::m_iaRotateOrder ), true );

	MPlug woAP = weldFn.findPlug( CVstWeldNode::m_oaWeldOutput );
	MPlug woP = woAP.elementByLogicalIndex( nWeldIndex );
	MPlug tP = woP.child( CVstWeldNode::m_oaTranslate );

	undo.Connect( tP.child( CVstWeldNode::m_oaTranslateX ), toWeldFn.findPlug( "translateX" ) );
	undo.Connect( tP.child( CVstWeldNode::m_oaTranslateY ), toWeldFn.findPlug( "translateY" ) );
	undo.Connect( tP.child( CVstWeldNode::m_oaTranslateZ ), toWeldFn.findPlug( "translateZ" ) );

	MPlug rP = woP.child( CVstWeldNode::m_oaRotate );

	undo.Connect( rP.child( CVstWeldNode::m_oaRotateX ), toWeldFn.findPlug( "rotateX" ) );
	undo.Connect( rP.child( CVstWeldNode::m_oaRotateY ), toWeldFn.findPlug( "rotateY" ) );
	undo.Connect( rP.child( CVstWeldNode::m_oaRotateZ ), toWeldFn.findPlug( "rotateZ" ) );
}
Пример #2
0
//############################################### tima:
bool polyModifierCmd::setZeroTweaks()
{
	MFnNumericData numDataFn;
	MObject nullVector;
	MFnDependencyNode depNodeFn;

	numDataFn.create( MFnNumericData::k3Float );
	numDataFn.setData( 0, 0, 0 );
	nullVector = numDataFn.object();

	MObject object = fDagPath.node();
	depNodeFn.setObject( object);
	MPlug meshTweakPlug = depNodeFn.findPlug( "pnts" );
	MPlug tweak;

	unsigned numTweaks = fTweakIndexArray.length();

	if( !meshTweakPlug.isNull() )
	{
		for( unsigned i = 0; i < numTweaks; i++ )
		{
			tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			tweak.setValue( nullVector );
		}
	}
	
	return true;
}
//-----------------------------------------------------------------------------
// This is here for reference. It isn't currently used
//-----------------------------------------------------------------------------
void CVsSkinnerCmd::DoConnectGeometry(
	const MDagPath &skinnerPath,
	const MDagPath &gDagPath )
{
	MObject skinnerObj( skinnerPath.node() );
	const MFnDependencyNode vsSkinnerFn( skinnerObj );
	const MFnMesh meshFn( gDagPath );

	// Connect things up

	MPlug sP;
	MPlug dP;

	MDagModifier &mDagModifier( m_undo.DagModifier() );

	// Connect mesh.worldMatrix[#] vsSkinner.geometryWorldMatrix
	sP = meshFn.findPlug( "worldMatrix" );
	sP = sP.elementByLogicalIndex( gDagPath.instanceNumber() );
	dP = vsSkinnerFn.findPlug( "geometryWorldMatrix" );
	mDagModifier.connect( sP, dP );

	sP = meshFn.findPlug( "outMesh" );
	dP = vsSkinnerFn.findPlug( "inputGeometry" );
	mDagModifier.connect( sP, dP );

	mDagModifier.doIt();

	// Add the default volume
	MSelectionList emptyList;
	MGlobal::setActiveSelectionList( DoNewVolumes( skinnerPath, emptyList ), MGlobal::kReplaceList );
}
    //---------------------------------------------------
    bool DagHelper::connectToList ( const MPlug& source, const MObject& destination, const MString& destinationAttribute, int* _index )
    {
        MStatus status;
        MFnDependencyNode destFn ( destination );
        MPlug dest = destFn.findPlug ( destinationAttribute, &status );

        if ( status != MStatus::kSuccess ) return false;

        if ( !dest.isArray() ) return false;

        int index = ( _index != NULL ) ? *_index : -1;

        if ( index < 0 )
        {
            index = getNextAvailableIndex ( dest, ( int ) dest.evaluateNumElements() );

            if ( _index != NULL ) *_index = index;
        }

        MPlug d = dest.elementByLogicalIndex ( index );

        MDGModifier modifier;
        modifier.connect ( source, d );
        status = modifier.doIt();
        return status == MStatus::kSuccess;
    }
    //---------------------------------------------------
    // Retrieve the bind pose for a controller/joint std::pair
    //
    MMatrix DagHelper::getBindPoseInverse ( const MObject& controller, const MObject& influence )
    {
        MStatus status;
        if ( controller.apiType() == MFn::kSkinClusterFilter )
        {
            MFnSkinCluster controllerFn ( controller );

            // Find the correct index for the pre-bind matrix
            uint index = controllerFn.indexForInfluenceObject ( MDagPath::getAPathTo ( influence ), &status );
            if ( status != MStatus::kSuccess ) return MMatrix::identity;

            MPlug preBindMatrixPlug = controllerFn.findPlug ( "bindPreMatrix", &status );
            preBindMatrixPlug = preBindMatrixPlug.elementByLogicalIndex ( index, &status );
            if ( status != MStatus::kSuccess ) return MMatrix::identity;

            // Get the plug's matrix
            MMatrix ret;
            if ( !DagHelper::getPlugValue ( preBindMatrixPlug, ret ) ) return MMatrix::identity;

            return ret;
        }

        else if ( controller.apiType() == MFn::kJointCluster )
        {
            MMatrix ret;
            DagHelper::getPlugValue ( influence, "bindPose", ret );
            return ret.inverse();
        }

        else return MMatrix::identity;
    }
    //---------------------------------------------------
    MObject DagHelper::createExpression ( const MPlug& plug, const MString& expression )
    {
        MFnDependencyNode expressionFn;
        MObject expressionObj = expressionFn.create ( "expression" );
        DagHelper::setPlugValue ( expressionObj, "expression", expression );

        MPlug output = expressionFn.findPlug ( "output" );
        MPlug firstOutput = output.elementByLogicalIndex ( 0 );
        DagHelper::connect ( firstOutput, plug );
        return expressionObj;
    }
 // -------------------------------------------
 MPlug AnimationHelper::getTargetedPlug ( MPlug parentPlug, int index )
 {
     if ( index >= 0 && parentPlug.isCompound() )
     {
         return parentPlug.child ( index );
     }
     else if ( index >= 0 && parentPlug.isArray() )
     {
         return parentPlug.elementByLogicalIndex ( index );
     }
     else return parentPlug;
 }
    //---------------------------------------------------
    // set the bind pose for a transform
    //
    MStatus DagHelper::setBindPoseInverse ( const MObject& node, const MMatrix& bindPoseInverse )
    {
        MStatus status;
        MFnDependencyNode dgFn ( node );
        MPlug bindPosePlug = dgFn.findPlug ( "bindPose", &status );
        if ( status != MS::kSuccess )
        {
            MGlobal::displayWarning ( MString ( "No bindPose found on node " ) + dgFn.name() );
            return status;
        }

        MFnMatrixData matrixFn;
        MObject val = matrixFn.create ( bindPoseInverse.inverse(), &status );
        MObject invval = matrixFn.create ( bindPoseInverse, &status );
        if ( status != MS::kSuccess )
        {
            MGlobal::displayWarning ( MString ( "Error setting bindPose on node " ) + dgFn.name() );
            return status;
        }

        // set the bind pose on the joint itself
        bindPosePlug.setValue ( val );

        // Now, perhaps more significantly, see if there's a
        // skinCluster using this bone and update its bind
        // pose (as the joint bind pose is not connected to
        // the skin - it's set at bind time from the joint's
        // current position, and our importer may not want to
        // disturb the current scene state just to put bones
        // in a bind position before creating skin clusters)
        MObject _node ( node );
        MItDependencyGraph it ( _node, MFn::kSkinClusterFilter );
        while ( !it.isDone() )
        {
            MPlug plug = it.thisPlug();
            unsigned int idx = plug.logicalIndex();
            MFnDependencyNode skinFn ( plug.node() );
            MPlug skinBindPosePlug = skinFn.findPlug ( "bindPreMatrix", &status );

            if ( status == MS::kSuccess )
            {
                // The skinCluster stores inverse inclusive matrix
                // so notice we use invval (the MObject created off
                // the inverse matrix here)
                skinBindPosePlug = skinBindPosePlug.elementByLogicalIndex ( idx );
                skinBindPosePlug.setValue ( invval );
            }

            it.next();
        }

        return status;
    }
Пример #9
0
void SurfaceAttach::inUVs(MFnDependencyNode &fn) {
    MPlug inUVPlug = fn.findPlug("inUV");
    const std::uint32_t numElements = inUVPlug.numElements();

    this->uInputs.resize((size_t)(numElements));
    this->vInputs.resize((size_t)(numElements));

    for (std::uint32_t i=0; i < numElements; i++){
        MPlug uvPlug = inUVPlug.elementByLogicalIndex(i);
        this->uInputs[i] = uvPlug.child(0).asDouble();
        this->vInputs[i] = uvPlug.child(1).asDouble();
    }
}
Пример #10
0
    //---------------------------------------------------
    // get the first empty item in the named array plug
    unsigned DagHelper::getFirstEmptyElementId ( const MPlug& parent )
    {
        unsigned num_element = 1;

        if ( parent.numElements() > num_element ) num_element = parent.numElements();

        for ( unsigned i = 0; i< num_element; i++ )
        {
            if ( !parent.elementByLogicalIndex ( i ).isConnected() ) return i;
        }

        return parent.numElements() +1;
    }
IECore::ObjectPtr FromMayaTransformConverter::doConversion( const MDagPath &dagPath, IECore::ConstCompoundObjectPtr operands ) const
{
	MTransformationMatrix transform;

	if( m_spaceParameter->getNumericValue()==Local )
	{
		MFnTransform fnT( dagPath );
		transform = fnT.transformation();
	}
	else
	{
		unsigned instIndex = dagPath.instanceNumber();

		MObject dagNode = dagPath.node();
		MFnDependencyNode fnN( dagNode );

		MPlug plug = fnN.findPlug( "worldMatrix" );
		MPlug instPlug = plug.elementByLogicalIndex( instIndex );

		MObject matrix;
		instPlug.getValue( matrix );

		MFnMatrixData fnM( matrix );
		transform = fnM.transformation();

		if ( m_spaceParameter->getNumericValue() == Custom )
		{
			// multiply world transform by the inverse of the custom space matrix.
			transform = transform.asMatrix() * IECore::convert< MMatrix, Imath::M44f >( operands->member< IECore::M44fData >("customSpace", true)->readable().inverse() );
		}
	}

	if( m_zeroPivotsParameter->getTypedValue() )
	{
		transform.setScalePivot( MPoint( 0, 0, 0 ), MSpace::kTransform, true );
		transform.setRotatePivot( MPoint( 0, 0, 0 ), MSpace::kTransform, true );
	}

	if( m_eulerFilterParameter->getTypedValue() && m_lastRotationValid )
	{
		transform.rotateTo( transform.eulerRotation().closestSolution( m_lastRotation ) );
	}

	m_lastRotation = transform.eulerRotation();
	m_lastRotationValid = true;

	return new IECore::TransformationMatrixdData( IECore::convert<IECore::TransformationMatrixd, MTransformationMatrix>( transform ) );
}
Пример #12
0
    //---------------------------------------------------
    int DagHelper::getNextAvailableIndex ( const MPlug& p, int startIndex )
    {
        if ( startIndex < 0 ) startIndex = 0;

        // Look for the next available plug
        for ( uint i = ( uint ) startIndex; i < ( uint ) startIndex + 100; ++i )
        {
            MPlug possibleDestination = p.elementByLogicalIndex ( i );

            if ( !DagHelper::hasConnection ( possibleDestination ) )
            {
                return i;
            }
        }

        return -1;
    }
Пример #13
0
void V3Manipulator::getPlugValues( MPlug &plug, double *values )
{
	if( plug.numChildren() == 3 )
	{
		for( unsigned i = 0; i<3; i++ )
		{
			MPlug child = plug.child( i );
			*values = child.asDouble();
			values++;
		}
	}
	else
	{
		for( unsigned i = 0; i<3; i++ )
		{
			MPlug element = plug.elementByLogicalIndex( i );
			*values = element.asDouble();
			values++;
		}
	}
}
Пример #14
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::undoTweakProcessing()
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	if( fHasTweaks )
	{
		MFnDependencyNode depNodeFn;

		MObject	meshNodeShape;
		MPlug	meshTweakPlug;
		MPlug	tweak;
		MObject	tweakData;

		meshNodeShape = fDagPath.node();
		depNodeFn.setObject( meshNodeShape );
		meshTweakPlug = depNodeFn.findPlug( "pnts" );

		MStatusAssert( (meshTweakPlug.isArray()),
					   "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );

		unsigned i;
		unsigned numElements = fTweakIndexArray.length();

		for( i = 0; i < numElements; i++ )
		{
			tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			getFloat3asMObject( fTweakVectorArray[i], tweakData );
			tweak.setValue( tweakData );
		}

		// In the case of no history, the duplicate node shape will be disconnected on undo
		// so, there is no need to undo the tweak processing on it.
		//
	}

	return status;
}
Пример #15
0
PXR_NAMESPACE_OPEN_SCOPE



/* static */
bool 
PxrUsdMayaTranslatorMesh::Create(
        const UsdGeomMesh& mesh,
        MObject parentNode,
        const PxrUsdMayaPrimReaderArgs& args,
        PxrUsdMayaPrimReaderContext* context)
{
    if (!mesh) {
        return false;
    }

    const UsdPrim& prim = mesh.GetPrim();

    MStatus status;

    // Create node (transform)
    MObject mayaNodeTransformObj;
    if (!PxrUsdMayaTranslatorUtil::CreateTransformNode(prim,
                                                          parentNode,
                                                          args,
                                                          context,
                                                          &status,
                                                          &mayaNodeTransformObj)) {
        return false;
    }

    VtArray<GfVec3f> points;
    VtArray<GfVec3f> normals;
    VtArray<int>     faceVertexCounts;
    VtArray<int>     faceVertexIndices;
    
    UsdAttribute fvc = mesh.GetFaceVertexCountsAttr();
    if (fvc.ValueMightBeTimeVarying()){
        // at some point, it would be great, instead of failing, to create a usd/hydra proxy node
        // for the mesh, perhaps?  For now, better to give a more specific error
        MGlobal::displayError(
            TfStringPrintf("<%s> is a topologically varying Mesh (animated faceVertexCounts). Skipping...", 
                prim.GetPath().GetText()).c_str());
        return false;
    } else {
        // for any non-topo-varying mesh, sampling at zero will get us the right answer
        fvc.Get(&faceVertexCounts, 0);
    }

    UsdAttribute fvi = mesh.GetFaceVertexIndicesAttr();
    if (fvi.ValueMightBeTimeVarying()){
        // at some point, it would be great, instead of failing, to create a usd/hydra proxy node
        // for the mesh, perhaps?  For now, better to give a more specific error
        MGlobal::displayError(
            TfStringPrintf("<%s> is a topologically varying Mesh (animated faceVertexIndices). Skipping...", 
                prim.GetPath().GetText()).c_str());
        return false;
    } else {
        // for any non-topo-varying mesh, sampling at zero will get us the right answer
        fvi.Get(&faceVertexIndices, 0);
    }
        
    // Sanity Checks. If the vertex arrays are empty, skip this mesh
    if (faceVertexCounts.size() == 0 || faceVertexIndices.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("FaceVertex arrays are empty [Count:%zu Indices:%zu] on Mesh <%s>. Skipping...", 
                faceVertexCounts.size(), faceVertexIndices.size(), 
                prim.GetPath().GetText()).c_str());
        return false; // invalid mesh, so exit
    }

    // Gather points and normals
    // If args.GetReadAnimData() is TRUE,
    // pick the first avaiable sample or default
    UsdTimeCode pointsTimeSample=UsdTimeCode::EarliestTime();
    UsdTimeCode normalsTimeSample=UsdTimeCode::EarliestTime();
    std::vector<double> pointsTimeSamples;
    size_t pointsNumTimeSamples = 0;
    if (args.GetReadAnimData()) {
        PxrUsdMayaTranslatorUtil::GetTimeSamples(mesh.GetPointsAttr(), args,
                &pointsTimeSamples);
        pointsNumTimeSamples = pointsTimeSamples.size();
        if (pointsNumTimeSamples>0) {
            pointsTimeSample = pointsTimeSamples[0];
        }
    	std::vector<double> normalsTimeSamples;
        PxrUsdMayaTranslatorUtil::GetTimeSamples(mesh.GetNormalsAttr(), args,
                &normalsTimeSamples);
        if (normalsTimeSamples.size()) {
            normalsTimeSample = normalsTimeSamples[0];
        }
    }
    mesh.GetPointsAttr().Get(&points, pointsTimeSample);
    mesh.GetNormalsAttr().Get(&normals, normalsTimeSample);
    
    if (points.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("Points arrays is empty on Mesh <%s>. Skipping...", 
                prim.GetPath().GetText()).c_str());
        return false; // invalid mesh, so exit
    }


    // == Convert data
    size_t mayaNumVertices = points.size();
    MPointArray mayaPoints(mayaNumVertices);
    for (size_t i=0; i < mayaNumVertices; i++) {
        mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
    }

    MIntArray polygonCounts( faceVertexCounts.cdata(),  faceVertexCounts.size() );
    MIntArray polygonConnects( faceVertexIndices.cdata(), faceVertexIndices.size() );

    // == Create Mesh Shape Node
    MFnMesh meshFn;
    MObject meshObj = meshFn.create(mayaPoints.length(), 
                           polygonCounts.length(), 
                           mayaPoints, 
                           polygonCounts, 
                           polygonConnects,
                           mayaNodeTransformObj,
                           &status
                           );
                           
    if (status != MS::kSuccess) {
        return false;
    }

    // Since we are "decollapsing", we will create a xform and a shape node for each USD prim
    std::string usdPrimName(prim.GetName().GetText());
    std::string shapeName(usdPrimName); shapeName += "Shape";
    // Set mesh name and register
    meshFn.setName(MString(shapeName.c_str()), false, &status);
    if (context) {
        std::string usdPrimPath(prim.GetPath().GetText());
        std::string shapePath(usdPrimPath);
        shapePath += "/";
        shapePath += shapeName;
        context->RegisterNewMayaNode( shapePath, meshObj ); // used for undo/redo
    }

    // If a material is bound, create (or reuse if already present) and assign it
    // If no binding is present, assign the mesh to the default shader    
    const TfToken& shadingMode = args.GetShadingMode();
    PxrUsdMayaTranslatorMaterial::AssignMaterial(shadingMode, mesh, meshObj,
            context);
    
    // Mesh is a shape, so read Gprim properties
    PxrUsdMayaTranslatorGprim::Read(mesh, meshObj, context);

    // Set normals if supplied
    MIntArray normalsFaceIds;
    if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices())) {

        for (size_t i=0; i < polygonCounts.length(); i++) {
            for (int j=0; j < polygonCounts[i]; j++) {
                normalsFaceIds.append(i);
            }
        }
        if (normalsFaceIds.length() == static_cast<size_t>(meshFn.numFaceVertices())) {
            MVectorArray mayaNormals(normals.size());
            for (size_t i=0; i < normals.size(); i++) {
                mayaNormals.set( MVector(normals[i][0], normals[i][1], normals[i][2]), i);
            }
            if (meshFn.setFaceVertexNormals(mayaNormals, normalsFaceIds, polygonConnects) != MS::kSuccess) {
            }
        }
     }

    // Determine if PolyMesh or SubdivMesh
    TfToken subdScheme = PxrUsdMayaMeshUtil::setSubdivScheme(mesh, meshFn, args.GetDefaultMeshScheme());

    // If we are dealing with polys, check if there are normals
    // If we are dealing with SubdivMesh, read additional attributes and SubdivMesh properties
    if (subdScheme == UsdGeomTokens->none) {
        if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices())) {
            PxrUsdMayaMeshUtil::setEmitNormals(mesh, meshFn, UsdGeomTokens->none);
        }
    } else {
        PxrUsdMayaMeshUtil::setSubdivInterpBoundary(mesh, meshFn, UsdGeomTokens->edgeAndCorner);
        PxrUsdMayaMeshUtil::setSubdivFVLinearInterpolation(mesh, meshFn);
        _AssignSubDivTagsToMesh(mesh, meshObj, meshFn);
    }
 
    // Set Holes
    VtArray<int> holeIndices;
    mesh.GetHoleIndicesAttr().Get(&holeIndices);   // not animatable
    if ( holeIndices.size() != 0 ) {
        MUintArray mayaHoleIndices;
        mayaHoleIndices.setLength( holeIndices.size() );
        for (size_t i=0; i < holeIndices.size(); i++) {
            mayaHoleIndices[i] = holeIndices[i];
        }
        if (meshFn.setInvisibleFaces(mayaHoleIndices) == MS::kFailure) {
            MGlobal::displayError(TfStringPrintf("Unable to set Invisible Faces on <%s>", 
                            meshFn.fullPathName().asChar()).c_str());
        }
    }

    // GETTING PRIMVARS
    std::vector<UsdGeomPrimvar> primvars = mesh.GetPrimvars();
    TF_FOR_ALL(iter, primvars) {
        const UsdGeomPrimvar& primvar = *iter;
        const TfToken& name = primvar.GetBaseName();
        const SdfValueTypeName& typeName = primvar.GetTypeName();

        // If the primvar is called either displayColor or displayOpacity check
        // if it was really authored from the user.  It may not have been
        // authored by the user, for example if it was generated by shader
        // values and not an authored colorset/entity.
        // If it was not really authored, we skip the primvar.
        if (name == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName || 
                name == PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName) {
            if (!PxrUsdMayaRoundTripUtil::IsAttributeUserAuthored(primvar)) {
                continue;
            }
        }

        // XXX: Maya stores UVs in MFloatArrays and color set data in MColors
        // which store floats, so we currently only import primvars holding
        // float-typed arrays. Should we still consider other precisions
        // (double, half, ...) and/or numeric types (int)?
        if (typeName == SdfValueTypeNames->Float2Array) {
            // We assume that Float2Array primvars are UV sets.
            if (!_AssignUVSetPrimvarToMesh(primvar, meshFn)) {
                MGlobal::displayWarning(
                    TfStringPrintf("Unable to retrieve and assign data for UV set <%s> on mesh <%s>", 
                                   name.GetText(),
                                   mesh.GetPrim().GetPath().GetText()).c_str());
            }
        } else if (typeName == SdfValueTypeNames->FloatArray   || 
                   typeName == SdfValueTypeNames->Float3Array  || 
                   typeName == SdfValueTypeNames->Color3fArray ||
                   typeName == SdfValueTypeNames->Float4Array  || 
                   typeName == SdfValueTypeNames->Color4fArray) {
            if (!_AssignColorSetPrimvarToMesh(mesh, primvar, meshFn)) {
                MGlobal::displayWarning(
                    TfStringPrintf("Unable to retrieve and assign data for color set <%s> on mesh <%s>",
                                   name.GetText(),
                                   mesh.GetPrim().GetPath().GetText()).c_str());
            }
        }
    }

    // We only vizualize the colorset by default if it is "displayColor".  
    MStringArray colorSetNames;
    if (meshFn.getColorSetNames(colorSetNames)==MS::kSuccess) {
        for (unsigned int i=0; i < colorSetNames.length(); i++) {
            const MString colorSetName = colorSetNames[i];
            if (std::string(colorSetName.asChar()) 
                    == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetString()) {
                MFnMesh::MColorRepresentation csRep=
                    meshFn.getColorRepresentation(colorSetName);
                if (csRep==MFnMesh::kRGB || csRep==MFnMesh::kRGBA) {

                    // both of these are needed to show the colorset.
                    MPlug plg=meshFn.findPlug("displayColors");
                    if ( !plg.isNull() ) {
                        plg.setBool(true);
                    }
                    meshFn.setCurrentColorSetName(colorSetName);
                }
                break;
            }
        }
    }
    
    // == Animate points ==
    //   Use blendShapeDeformer so that all the points for a frame are contained in a single node
    //
    if (pointsNumTimeSamples > 0) {
        MPointArray mayaPoints(mayaNumVertices);
        MObject meshAnimObj;

        MFnBlendShapeDeformer blendFn;
        MObject blendObj = blendFn.create(meshObj);
        if (context) {
            context->RegisterNewMayaNode( blendFn.name().asChar(), blendObj ); // used for undo/redo
        }

        for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) {
             mesh.GetPointsAttr().Get(&points, pointsTimeSamples[ti]);

            for (unsigned int i=0; i < mayaNumVertices; i++) {
                mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
            }

            // == Create Mesh Shape Node
            MFnMesh meshFn;
            if ( meshAnimObj.isNull() ) {
                meshAnimObj = meshFn.create(mayaPoints.length(), 
                                       polygonCounts.length(), 
                                       mayaPoints, 
                                       polygonCounts, 
                                       polygonConnects,
                                       mayaNodeTransformObj,
                                       &status
                                       );
                if (status != MS::kSuccess) {
                    continue;
                }
            }
            else {
                // Reuse the already created mesh by copying it and then setting the points
                meshAnimObj = meshFn.copy(meshAnimObj, mayaNodeTransformObj, &status);
                meshFn.setPoints(mayaPoints);
            }

            // Set normals if supplied
            //
            // NOTE: This normal information is not propagated through the blendShapes, only the controlPoints.
            //
             mesh.GetNormalsAttr().Get(&normals, pointsTimeSamples[ti]);
             if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices()) &&
                normalsFaceIds.length() == static_cast<size_t>(meshFn.numFaceVertices())) {

                MVectorArray mayaNormals(normals.size());
                for (size_t i=0; i < normals.size(); i++) {
                    mayaNormals.set( MVector(normals[i][0], normals[i][1], normals[i][2]), i);
                }
                if (meshFn.setFaceVertexNormals(mayaNormals, normalsFaceIds, polygonConnects) != MS::kSuccess) {
                }
             }

            // Add as target and set as an intermediate object
            blendFn.addTarget(meshObj, ti, meshAnimObj, 1.0);
            meshFn.setIntermediateObject(true);
            if (context) {
                context->RegisterNewMayaNode( meshFn.fullPathName().asChar(), meshAnimObj ); // used for undo/redo
            }
        }

        // Animate the weights so that mesh0 has a weight of 1 at frame 0, etc.
        MFnAnimCurve animFn;

        // Construct the time array to be used for all the keys
        MTimeArray timeArray;
        timeArray.setLength(pointsNumTimeSamples);
        for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) {
            timeArray.set( MTime(pointsTimeSamples[ti]), ti);
        }

        // Key/Animate the weights
        MPlug plgAry = blendFn.findPlug( "weight" );
        if ( !plgAry.isNull() && plgAry.isArray() ) {
            for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) {
                MPlug plg = plgAry.elementByLogicalIndex(ti, &status);
                MDoubleArray valueArray(pointsNumTimeSamples, 0.0);
                valueArray[ti] = 1.0; // Set the time value where this mesh's weight should be 1.0
                MObject animObj = animFn.create(plg, NULL, &status);
                animFn.addKeys(&timeArray, &valueArray);
                if (context) {
                    context->RegisterNewMayaNode(animFn.name().asChar(), animObj ); // used for undo/redo
                }
            }
        }
    }

    return true;
}
Пример #16
0
MStatus componentScaleManip::connectToDependNode(const MObject &node)
{
	MStatus stat;
	
	MFnComponent componentFn(component);
	if (componentFn.elementCount() > numComponents)
	{
		delete [] initialPositions;
		delete [] initialControlPoint;
		numComponents = componentFn.elementCount();
		initialPositions = new MPoint[numComponents];
		initialControlPoint = new MPoint[numComponents];
	}

	// Iterate through the components, storing initial positions and find the
	// centroid.  Add manipToPlug callbacks for each component.
	//
	int i = 0;
	for (MItSurfaceCV iter(surfaceDagPath, component); !iter.isDone(); iter.next(), i++)
	{
		if (i >= numComponents)
		{
			MGlobal::displayWarning("More components found than expected.");
			break;
		}
		initialPositions[i] = iter.position(MSpace::kWorld);
		centroid += initialPositions[i];

		//
		// Create a manipToPlug callback that is invoked whenever the manipVal
		// changes.  The callback is added for every selected CV.
		//

		MFnDependencyNode nodeFn(node);
		MPlug controlPointArrayPlug = nodeFn.findPlug("controlPoints", &stat);
		if (controlPointArrayPlug.isNull())
		{
			MGlobal::displayError("Control point plug not found on node.");
			return MS::kFailure;
		}

		// The logical index from the component iterator is the same as the
		// logical index into the control points array.
		//
		MPlug controlPointPlug = 
			controlPointArrayPlug.elementByLogicalIndex(iter.index(), &stat);
		if (controlPointPlug.isNull())
		{
			MGlobal::displayError("Control point element not found.");
			return MS::kFailure;
		}

		// Store the initial value of the control point.
		//
		initialControlPoint[i] = vectorPlugValue(controlPointPlug);

		unsigned plugIndex = addManipToPlugConversion(controlPointPlug);

		// Plug indices should be allocated sequentially, starting at 0.  Each
		// manip container will have its own set of plug indices.  This code 
		// relies on the sequential allocation of indices, so trigger an error
		// if the indices are found to be different.
		//
		if (plugIndex != (unsigned)i)
		{
			MGlobal::displayError("Unexpected plug index returned.");
			return MS::kFailure;
		}
	}
	centroid = centroid / numComponents;

	MFnScaleManip scaleManip(fScaleManip);

	// Create a plugToManip callback that places the manipulator at the 
	// centroid of the CVs.
	//
	addPlugToManipConversion(scaleManip.scaleCenterIndex());

	finishAddingManips();
	MPxManipContainer::connectToDependNode(node);
	return stat;
}
bool FxAttributeFiller::FillPlug( DXCCEffectPath& parameter, MPlug& plug )
{
	HRESULT hr= S_OK;
	LPDXCCRESOURCE pResource= NULL;
	LPDIRECT3DBASETEXTURE9 pTexture= NULL;
	D3DXPARAMETER_DESC desc= parameter.End->Description;
	float NumericVals[16]= {0.0f};
	MString StringVal;
	LPCSTR StringValStr= "";

	bool RestoreFound= false;
	LPCVOID pRestoreData= NULL;
	size_t RestoreSize= 0;
	CComPtr<IDXCCPropertyCollection> pCollection;
	DXCCPROPERTY_KEY key= 0;

	if(Restore)
	{
		if( DXCC_SUCCEEDED( Restore->GetPath( parameter.End->LongPathName, &pCollection, &key) ) )
		{
			pCollection->GetPropertyValueAsData(key, &pRestoreData);
			DXCCPROPERTY_DESC desc= pCollection->GetPropertyDesc(key);

			if(desc == DXCCPD_STRING)
			{
				StringVal= (LPCSTR)pRestoreData;
				StringValStr= (LPCSTR)pRestoreData;

				RestoreFound= true;
			}
			else
			{
				size_t RestoreSize= DXCCPropertySize( desc, pRestoreData );
				memcpy( NumericVals, pRestoreData, RestoreSize);

				RestoreFound= true;
			}
		}
	}



	if((desc.Type == D3DXPT_BOOL)
	||(desc.Type == D3DXPT_INT)
	||(desc.Type == D3DXPT_FLOAT))
	{

		if(!RestoreFound)
		{

			if(plug.isArray())
			{
				hr=  Shader->Effect->GetFloatArray(parameter.End->Handle, NumericVals, 16);
					if(DXCC_FAILED(hr))
						DXCC_GOTO_EXIT(e_Exit, TRUE);
			}
			else
			{
				hr=  Shader->Effect->GetFloat(parameter.End->Handle, NumericVals);
				if(DXCC_FAILED(hr))
					DXCC_GOTO_EXIT(e_Exit, TRUE);
			}
		}

		if(plug.isArray())
		{
			int count= desc.Rows * desc.Columns;
			for(int i= 0; i < count; i++)
			{
				MPlug subPlug= plug.elementByLogicalIndex(i);
				DXCHECK_MSTATUS(subPlug.setValue( NumericVals[i] ));
			}
		}
		else
		{
			DXCHECK_MSTATUS(plug.setValue( NumericVals[0] ));
		}
	}
	else if((desc.Type == D3DXPT_TEXTURE)
	||(desc.Type == D3DXPT_TEXTURE1D)
	||(desc.Type == D3DXPT_TEXTURE2D)
	||(desc.Type == D3DXPT_TEXTURE3D)
	||(desc.Type == D3DXPT_TEXTURECUBE))
	{

		if(!RestoreFound)
		{
			hr=  Shader->Effect->GetTexture(parameter.End->Handle, &pTexture);
			if(DXCC_SUCCEEDED(hr) && pTexture != NULL)
			{
				hr= g_PreviewPipeline.AccessManager()->FindResourceByPointer(
						(LPUNKNOWN)pTexture, 
						NULL, 
						&pResource);
				if(DXCC_SUCCEEDED(hr))
				{
					StringVal= pResource->GetResourcePath();
				}
			}
			else
			{
				D3DXHANDLE hResourceAddy= Shader->Effect->GetAnnotationByName( parameter.End->Handle, "SasResourceAddress");
				if(hResourceAddy)
				{
					LPCSTR resourceAddressStr= NULL;
					Shader->Effect->GetString(hResourceAddy, &resourceAddressStr); 

					StringVal= resourceAddressStr;
				}
			}
		}

		DXCHECK_MSTATUS(plug.setValue( StringVal ));
	}
	else if(desc.Type == D3DXPT_STRING)
	{
		if(!RestoreFound)
		{
			hr=  Shader->Effect->GetString(parameter.End->Handle, &StringValStr);
			StringVal= StringValStr;
		}

		DXCHECK_MSTATUS(plug.setValue( StringVal ));
	}
	else
	{
		DXCC_STATUS_EXIT(hr, E_FAIL, e_Exit, TRUE);
	}

e_Exit:
	DXCC_RELEASE(pResource);
	DXCC_RELEASE(pTexture);

	return DXCC_SUCCEEDED(hr);
}
MStatus ColorSplineParameterHandler<S>::doSetValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	assert( parameter );
	typename IECore::TypedParameter< S >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter< S > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	MRampAttribute fnRAttr( plug );
	if ( !fnRAttr.isColorRamp() )
	{
		return MS::kFailure;
	}

	const S &spline = p->getTypedValue();

	MStatus s;
	MIntArray indicesToReuse;
	plug.getExistingArrayAttributeIndices( indicesToReuse, &s );
	assert( s );

	int nextNewLogicalIndex = 0;
	if( indicesToReuse.length() )
	{
		nextNewLogicalIndex = 1 + *std::max_element( MArrayIter<MIntArray>::begin( indicesToReuse ), MArrayIter<MIntArray>::end( indicesToReuse ) );
	}
	
	assert( indicesToReuse.length() == fnRAttr.getNumEntries() );

	size_t pointsSizeMinus2 = spline.points.size() - 2;
	unsigned pointIndex = 0;
	unsigned numExpectedPoints = 0;
	for ( typename S::PointContainer::const_iterator it = spline.points.begin(); it != spline.points.end(); ++it, ++pointIndex )
	{
		// we commonly double up the endpoints on cortex splines to force interpolation to the end.
		// maya does this implicitly, so we skip duplicated endpoints when passing the splines into maya.
		// this avoids users having to be responsible for managing the duplicates, and gives them some consistency
		// with the splines they edit elsewhere in maya.
		if( ( pointIndex==1 && *it == *spline.points.begin() ) || ( pointIndex==pointsSizeMinus2 && *it == *spline.points.rbegin() ) )
		{
			continue;
		}

		MPlug pointPlug;
		if( indicesToReuse.length() )
		{
			pointPlug = plug.elementByLogicalIndex( indicesToReuse[0] );
			indicesToReuse.remove( 0 );
		}
		else
		{
			pointPlug = plug.elementByLogicalIndex( nextNewLogicalIndex++ );		
		}
		
		s = pointPlug.child( 0 ).setValue( it->first ); assert( s );
		MPlug colorPlug = pointPlug.child( 1 );
		colorPlug.child( 0 ).setValue( it->second[0] );
		colorPlug.child( 1 ).setValue( it->second[1] );
		colorPlug.child( 2 ).setValue( it->second[2] );
		// hardcoding interpolation of 3 (spline) because the MRampAttribute::MInterpolation enum values don't actually
		// correspond to the necessary plug values at all.
		s = pointPlug.child( 2 ).setValue( 3 ); assert( s );

		numExpectedPoints++;
	}

	// delete any of the original indices which we didn't reuse. we can't use MRampAttribute::deleteEntries
	// here as it's utterly unreliable.
	if( indicesToReuse.length() )
	{
		MString plugName = plug.name();
		MObject node = plug.node();
		MFnDagNode fnDAGN( node );
		if( fnDAGN.hasObj( node ) )
		{
			plugName = fnDAGN.fullPathName() + "." + plug.partialName();
		}
		for( unsigned i=0; i<indicesToReuse.length(); i++ )
		{
			// using mel because there's no equivalant api method as far as i know.
			MString command = "removeMultiInstance -b true \"" + plugName + "[" + indicesToReuse[i] + "]\"";
			s = MGlobal::executeCommand( command );
			assert( s );
			if( !s )
			{
				return s;
			}
		}
	}

#ifndef NDEBUG
	{
		assert( fnRAttr.getNumEntries() == numExpectedPoints );

		MIntArray indices;
		MFloatArray positions;
		MColorArray colors;
		MIntArray interps;
		fnRAttr.getEntries( indices, positions, colors, interps, &s );
		assert( s );
		assert( numExpectedPoints == positions.length() );
		assert( numExpectedPoints == colors.length() );
		assert( numExpectedPoints == interps.length() );
		assert( numExpectedPoints == indices.length() );

		for ( unsigned i = 0; i < positions.length(); i++ )
		{
			float position = positions[ i ];
			const MVector color( colors[ i ][ 0 ], colors[ i ][ 1 ], colors[ i ][ 2 ] );

			bool found = false;

			for ( typename S::PointContainer::const_iterator it = spline.points.begin(); it != spline.points.end() && !found; ++it )
			{
				MVector color2( it->second[0], it->second[1], it->second[2] );
				if ( fabs( it->first - position ) < 1.e-3f && ( color2 - color ).length() < 1.e-3f )
				{
					found = true;
				}
			}
			assert( found );
		}
	}
#endif

	return MS::kSuccess;
}
Пример #19
0
MStatus CVstAimCmd::redoIt()
{
	MStatus mStatus;

	if ( !mStatus )
	{
		setResult( MString( "Cannot parse command line" ) + mStatus.errorString() );
		return MS::kFailure;
	}

	if ( m_mArgDatabase->isFlagSet( kHelp ) )
	{
		PrintHelp();
	}
	else
	{
		// See if there are two object specified

		MDagPath mDagPath;
		MSelectionList optSelectionList;

		// Validate specified items to whole dag nodes
		{
			MSelectionList tmpSelectionList;
			m_mArgDatabase->getObjects( tmpSelectionList );
			for ( MItSelectionList sIt( tmpSelectionList, MFn::kDagNode ); !sIt.isDone(); sIt.next() )
			{
				if ( sIt.getDagPath( mDagPath ) )
				{
					optSelectionList.add( mDagPath, MObject::kNullObj, true );
				}
			}
		}

		if ( m_mArgDatabase->isFlagSet( "create" ) || optSelectionList.length() >= 2 && m_mArgDatabase->numberOfFlagsUsed() == 0 )
		{
			// Error if there aren't at least two
			if ( optSelectionList.length() < 2 )
			{
				displayError( GetName() + " needs at least two objects specified or selected when -create is used" );
				return MS::kFailure;
			}

			// Get name command line arg
			MString optName;
			if ( m_mArgDatabase->isFlagSet( "name" ) )
			{
				m_mArgDatabase->getFlagArgument( "name", 0, optName );
			}

			m_undoable = true;
			m_mDagModifier = new MDagModifier;

			MObject vstAimObj( m_mDagModifier->MDGModifier::createNode( GetName() ) );
			if ( m_mDagModifier->doIt() != MS::kSuccess )
			{
				displayError( MString( "Couldn't create " ) + GetName() + " node" );
				m_mDagModifier->undoIt();
				delete m_mDagModifier;
				m_mDagModifier = NULL;
				m_undoable = false;

				return MS::kFailure;
			}

			m_mDagModifier->renameNode( vstAimObj, optName.length() ? optName : GetName() );
			if ( m_mDagModifier->doIt() != MS::kSuccess )
			{
				if ( optName.length() )
				{
					displayWarning( MString( "Couldn't rename newly created vstNode \"" ) + optName + "\"" );
				}
			}

			// Set options on the newly create vstAim node

			MFnDependencyNode vstAimFn( vstAimObj );

			MPlug sP;
			MPlug dP;

			if ( m_mArgDatabase->isFlagSet( kAim ) )
			{
				MVector aim;
				m_mArgDatabase->getFlagArgument( kAim, 0, aim.x );
				m_mArgDatabase->getFlagArgument( kAim, 1, aim.y );
				m_mArgDatabase->getFlagArgument( kAim, 2, aim.z );

				sP = vstAimFn.findPlug( "aimX" );
				sP.setValue( aim.x );

				sP = vstAimFn.findPlug( "aimY" );
				sP.setValue( aim.y );

				sP = vstAimFn.findPlug( "aimZ" );
				sP.setValue( aim.z );
			}

			if ( m_mArgDatabase->isFlagSet( kUp ) )
			{
				MVector up;
				m_mArgDatabase->getFlagArgument( kUp, 0, up.x );
				m_mArgDatabase->getFlagArgument( kUp, 1, up.y );
				m_mArgDatabase->getFlagArgument( kUp, 2, up.z );

				sP = vstAimFn.findPlug( "upX" );
				sP.setValue( up.x );

				sP = vstAimFn.findPlug( "upY" );
				sP.setValue( up.y );

				sP = vstAimFn.findPlug( "upZ" );
				sP.setValue( up.z );
			}

			// Now connect up the newly created vstAim node

			MDagPath toAim;
			optSelectionList.getDagPath( 1, toAim );
			const MFnDagNode toAimFn( toAim );

			if ( toAim.hasFn( MFn::kJoint ) )
			{
				MPlug joP( toAimFn.findPlug( "jointOrient" ) );
				if ( !joP.isNull() )
				{
					MAngle jox, joy, joz;
					joP.child( 0 ).getValue( jox );
					joP.child( 1 ).getValue( joy );
					joP.child( 2 ).getValue( joz );
					if ( abs( jox.value() ) > FLT_EPSILON || abs( joy.value() ) > FLT_EPSILON || abs( joz.value() ) > FLT_EPSILON )
					{
						mwarn << "Joint orient on node being constrained is non-zero ( " << jox.asDegrees() << " " << joy.asDegrees() << " " << joz.asDegrees() << " ), setting to 0" << std::endl;
						joP.child( 0 ).setValue( MAngle( 0.0 ) );
						joP.child( 1 ).setValue( MAngle( 0.0 ) );
						joP.child( 2 ).setValue( MAngle( 0.0 ) );
					}
				}
			}

			if ( toAim.hasFn( MFn::kTransform ) )
			{
				MPlug mP( toAimFn.findPlug( "rotateAxis" ) );
				if ( !mP.isNull() )
				{
					MAngle rx, ry, rz;
					mP.child( 0 ).getValue( rx );
					mP.child( 1 ).getValue( ry );
					mP.child( 2 ).getValue( rz );
					if ( abs( rx.value() ) > FLT_EPSILON || abs( ry.value() ) > FLT_EPSILON || abs( rz.value() ) > FLT_EPSILON )
					{
						mwarn << "Rotate Axis on node being constrained is non-zero ( " << rx.asDegrees() << " " << ry.asDegrees() << " " << rz.asDegrees() << " ), setting to 0" << std::endl;
						mP.child( 0 ).setValue( MAngle( 0.0 ) );
						mP.child( 1 ).setValue( MAngle( 0.0 ) );
						mP.child( 2 ).setValue( MAngle( 0.0 ) );
					}
				}
			}

			MDagPath aimAt;
			optSelectionList.getDagPath( 0, aimAt );
			const MFnDagNode aimAtFn( aimAt );

			// toAim.rotateOrder -> vstAim.rotateOrder
			sP = toAimFn.findPlug( "rotateOrder" );
			dP = vstAimFn.findPlug( "rotateOrder" );
			m_mDagModifier->connect( sP, dP );

			// toAim.translate -> vstAim.translate
			sP = toAimFn.findPlug( "translate" );
			dP = vstAimFn.findPlug( "translate" );
			m_mDagModifier->connect( sP, dP );

			// toAim.parentMatrix[ instance ] -> vstAim.parentSpace
			sP = toAimFn.findPlug( "parentMatrix" );
			sP = sP.elementByLogicalIndex( toAim.instanceNumber() );
			dP = vstAimFn.findPlug( "parentSpace" );
			m_mDagModifier->connect( sP, dP );

			// aimAt.worldMatrix[ instance ] -> vstAim.aimSpace
			sP = aimAtFn.findPlug( "worldMatrix" );
			sP = sP.elementByLogicalIndex( aimAt.instanceNumber() );
			dP = vstAimFn.findPlug( "aimSpace" );
			m_mDagModifier->connect( sP, dP );

			// vstAim.rotation -> toAim.rotation
			// These have to be connected individually because Maya plays stupid tricks
			// with rotateOrder if they aren't
			sP = vstAimFn.findPlug( "rotateX" );
			dP = toAimFn.findPlug( "rotateX" );
			m_mDagModifier->connect( sP, dP );

			sP = vstAimFn.findPlug( "rotateY" );
			dP = toAimFn.findPlug( "rotateY" );
			m_mDagModifier->connect( sP, dP );

			sP = vstAimFn.findPlug( "rotateZ" );
			dP = toAimFn.findPlug( "rotateZ" );
			m_mDagModifier->connect( sP, dP );

			if ( m_mDagModifier->doIt() != MS::kSuccess )
			{
				displayWarning( MString( GetName() ) + ": Couldn't connect everything when creating" );
			}

			// Save the current selection just in case we want to undo stuff
			MGlobal::getActiveSelectionList( m_mSelectionList );

			MGlobal::select( vstAimObj, MGlobal::kReplaceList );
			setResult( vstAimFn.name() );
		}
		else if ( m_mArgDatabase->isFlagSet( "select" ) )
		{
			MSelectionList mSelectionList;
			MDagPath mDagPath;

			for ( MItDag dagIt; !dagIt.isDone(); dagIt.next() )
			{
				if ( MFnDependencyNode( dagIt.item() ).typeName() == GetName() )
				{
					dagIt.getPath( mDagPath );
					mSelectionList.add( mDagPath, MObject::kNullObj, true );
				}
			}

			if ( mSelectionList.length() )
			{
				m_undoable = true;
				// Save the current selection just in case we want to undo stuff
				MGlobal::getActiveSelectionList( m_mSelectionList );
				MGlobal::setActiveSelectionList( mSelectionList, MGlobal::kReplaceList );
			}
		}
		else
		{
			displayError( GetName() + ": No valid operation specified via command line arguments\n" );
		}
	}

	return MS::kSuccess;
}
Пример #20
0
/* static */
bool
PxrUsdMayaTranslatorCurves::Create(
        const UsdGeomCurves& curves,
        MObject parentNode,
        const PxrUsdMayaPrimReaderArgs& args,
        PxrUsdMayaPrimReaderContext* context)
{
    if (not curves) {
        return false;
    }

    const UsdPrim& prim = curves.GetPrim();

    MStatus status;

    // Create node (transform)
    MObject mayaNodeTransformObj;
    if (not PxrUsdMayaTranslatorUtil::CreateTransformNode(prim,
                                                          parentNode,
                                                          args,
                                                          context,
                                                          &status,
                                                          &mayaNodeTransformObj)) {
        return false;
    }

    VtArray<GfVec3f> points;
    VtArray<int>     curveOrder;
    VtArray<int>     curveVertexCounts;
    VtArray<float>   curveWidths;
    VtArray<GfVec2d> curveRanges;
    VtArray<double>  curveKnots;

    // LIMITATION:  xxx REVISIT xxx
    //   Non-animated Attrs
    //   Assuming that a number of these USD attributes are assumed to not be animated
    //   Some we may want to expose as animatable later.
    //
    curves.GetCurveVertexCountsAttr().Get(&curveVertexCounts); // not animatable

    // XXX:
    // Only supporting single curve for now.
    // Sanity Checks
    if (curveVertexCounts.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("VertexCount arrays is empty on NURBS curves <%s>. Skipping...", 
                            prim.GetPath().GetText()).c_str());
        return false; // No verts for the curve, so exit
    } else if (curveVertexCounts.size() > 1) {
        MGlobal::displayWarning(
            TfStringPrintf("Multiple curves in <%s>. Reading first one...", 
                            prim.GetPath().GetText()).c_str());
    }

    int curveIndex = 0;
    curves.GetWidthsAttr().Get(&curveWidths); // not animatable

    // Gather points. If args.GetReadAnimData() is TRUE,
    // pick the first avaiable sample or default
    UsdTimeCode pointsTimeSample=UsdTimeCode::EarliestTime();
    std::vector<double> pointsTimeSamples;
    size_t numTimeSamples = 0;
    if (args.GetReadAnimData()) {
        curves.GetPointsAttr().GetTimeSamples(&pointsTimeSamples);
        numTimeSamples = pointsTimeSamples.size();
        if (numTimeSamples>0) {
            pointsTimeSample = pointsTimeSamples[0];
        }
    }
    curves.GetPointsAttr().Get(&points, pointsTimeSample);
    
    if (points.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("Points arrays is empty on NURBS curves <%s>. Skipping...", 
                            prim.GetPath().GetText()).c_str());
        return false; // invalid nurbscurves, so exit
    }

    if (UsdGeomNurbsCurves nurbsSchema = UsdGeomNurbsCurves(prim)) {
        nurbsSchema.GetOrderAttr().Get(&curveOrder);   // not animatable
        nurbsSchema.GetKnotsAttr().Get(&curveKnots);   // not animatable
        nurbsSchema.GetRangesAttr().Get(&curveRanges); // not animatable
    } else {

        // Handle basis curves originally modelled in Maya as nurbs.

        curveOrder.resize(1);
        UsdGeomBasisCurves basisSchema = UsdGeomBasisCurves(prim);
        TfToken typeToken;
        basisSchema.GetTypeAttr().Get(&typeToken);
        if (typeToken == UsdGeomTokens->linear) {
            curveOrder[0] = 2;
            curveKnots.resize(points.size());
            for (size_t i=0; i < curveKnots.size(); ++i) {
                curveKnots[i] = i;
            }
        } else {
            curveOrder[0] = 4;

            // Strip off extra end points; assuming this is non-periodic.
            VtArray<GfVec3f> tmpPts(points.size() - 2);
            std::copy(points.begin() + 1, points.end() - 1, tmpPts.begin());
            points.swap(tmpPts);

            // Cubic curves in Maya have numSpans + 2*3 - 1, and for geometry
            // that came in as basis curves, we have numCV's - 3 spans.  See the
            // MFnNurbsCurve documentation and the nurbs curve export
            // implementation in mojitoplugmaya for more details.
            curveKnots.resize(points.size() -3 + 5);
            int knotIdx = 0;
            for (size_t i=0; i < curveKnots.size(); ++i) {
                if (i < 3) {
                    curveKnots[i] = 0.0;
                } else {
                    if (i <= curveKnots.size() - 3) {
                        ++knotIdx;
                    }
                    curveKnots[i] = double(knotIdx);
                } 
            }
        }
    }

    // == Convert data
    size_t mayaNumVertices = points.size();
    MPointArray mayaPoints(mayaNumVertices);
    for (size_t i=0; i < mayaNumVertices; i++) {
        mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
    }

    double *knots=curveKnots.data();
    MDoubleArray mayaKnots( knots, curveKnots.size());

    int mayaDegree = curveOrder[curveIndex] - 1;

    MFnNurbsCurve::Form mayaCurveForm = MFnNurbsCurve::kOpen; // HARDCODED
    bool mayaCurveCreate2D = false;
    bool mayaCurveCreateRational = true;

    // == Create NurbsCurve Shape Node
    MFnNurbsCurve curveFn;
    MObject curveObj = curveFn.create(mayaPoints, 
                                     mayaKnots,
                                     mayaDegree,
                                     mayaCurveForm,
                                     mayaCurveCreate2D,
                                     mayaCurveCreateRational,
                                     mayaNodeTransformObj,
                                     &status
                                     );
     if (status != MS::kSuccess) {
         return false;
     }
    MString nodeName( prim.GetName().GetText() );
    nodeName += "Shape";
    curveFn.setName(nodeName, false, &status);

    std::string nodePath( prim.GetPath().GetText() );
    nodePath += "/";
    nodePath += nodeName.asChar();
    if (context) {
        context->RegisterNewMayaNode( nodePath, curveObj ); // used for undo/redo
    }

    // == Animate points ==
    //   Use blendShapeDeformer so that all the points for a frame are contained in a single node
    //   Almost identical code as used with MayaMeshReader.cpp
    //
    if (numTimeSamples > 0) {
        MPointArray mayaPoints(mayaNumVertices);
        MObject curveAnimObj;

        MFnBlendShapeDeformer blendFn;
        MObject blendObj = blendFn.create(curveObj);
        if (context) {
            context->RegisterNewMayaNode(blendFn.name().asChar(), blendObj ); // used for undo/redo
        }
        
        for (unsigned int ti=0; ti < numTimeSamples; ++ti) {
             curves.GetPointsAttr().Get(&points, pointsTimeSamples[ti]);

            for (unsigned int i=0; i < mayaNumVertices; i++) {
                mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
            }

            // == Create NurbsCurve Shape Node
            MFnNurbsCurve curveFn;
            if ( curveAnimObj.isNull() ) {
                curveAnimObj = curveFn.create(mayaPoints, 
                                     mayaKnots,
                                     mayaDegree,
                                     mayaCurveForm,
                                     mayaCurveCreate2D,
                                     mayaCurveCreateRational,
                                     mayaNodeTransformObj,
                                     &status
                                     );
                if (status != MS::kSuccess) {
                    continue;
                }
            }
            else {
                // Reuse the already created curve by copying it and then setting the points
                curveAnimObj = curveFn.copy(curveAnimObj, mayaNodeTransformObj, &status);
                curveFn.setCVs(mayaPoints);
            }
            blendFn.addTarget(curveObj, ti, curveAnimObj, 1.0);
            curveFn.setIntermediateObject(true);
            if (context) {
                context->RegisterNewMayaNode( curveFn.fullPathName().asChar(), curveAnimObj ); // used for undo/redo
            }
        }

        // Animate the weights so that curve0 has a weight of 1 at frame 0, etc.
        MFnAnimCurve animFn;

        // Construct the time array to be used for all the keys
        MTimeArray timeArray;
        timeArray.setLength(numTimeSamples);
        for (unsigned int ti=0; ti < numTimeSamples; ++ti) {
            timeArray.set( MTime(pointsTimeSamples[ti]), ti);
        }

        // Key/Animate the weights
        MPlug plgAry = blendFn.findPlug( "weight" );
        if ( !plgAry.isNull() && plgAry.isArray() ) {
            for (unsigned int ti=0; ti < numTimeSamples; ++ti) {
                MPlug plg = plgAry.elementByLogicalIndex(ti, &status);
                MDoubleArray valueArray(numTimeSamples, 0.0);
                valueArray[ti] = 1.0; // Set the time value where this curve's weight should be 1.0
                MObject animObj = animFn.create(plg, NULL, &status);
                animFn.addKeys(&timeArray, &valueArray);
                if (context) {
                    context->RegisterNewMayaNode(animFn.name().asChar(), animObj ); // used for undo/redo
                }
            }
        }
    }

    return true;
}
MStatus ColorSplineParameterHandler<S>::doSetValue( const MPlug &plug, IECore::ParameterPtr parameter ) const
{
	assert( parameter );

	typename IECore::TypedParameter< S >::Ptr p = IECore::runTimeCast<IECore::TypedParameter< S > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	S spline;

	MStatus s;
	MRampAttribute fnRAttr( plug, &s );
	assert( s );

	if ( !fnRAttr.isColorRamp() )
	{
		return MS::kFailure;
	}

	MIntArray indices;
	(const_cast<MPlug &>( plug )).getExistingArrayAttributeIndices( indices, &s );

	for( unsigned i = 0; i < indices.length(); i++ )
	{
		MPlug pointPlug = plug.elementByLogicalIndex( indices[i] );
		MPlug colorPlug = pointPlug.child( 1 );
				
		typename S::YType y( 1 );
		y[0] = colorPlug.child( 0 ).asDouble();
		y[1] = colorPlug.child( 1 ).asDouble();
		y[2] = colorPlug.child( 2 ).asDouble();
		
		spline.points.insert(
			typename S::PointContainer::value_type( pointPlug.child( 0 ).asDouble(), y )
		);
	}

	// maya seems to do an implicit doubling up of the end points to cause interpolation to the ends.
	// our spline has no such implicit behaviour so we explicitly double up.
	if( spline.points.size() )
	{
#ifndef NDEBUG
		size_t oldSplineSize = spline.points.size();
#endif

		assert( spline.points.begin()->first <= spline.points.rbegin()->first );
		spline.points.insert( *spline.points.begin() );
		spline.points.insert( *spline.points.rbegin() );
		assert( spline.points.size() == oldSplineSize + 2 );
	}

	p->setTypedValue( spline );

	if( spline.points.size() )
	{
		assert( spline.points.size() >= 2 );
		assert( spline.points.size() == fnRAttr.getNumEntries() + 2 );
	}

	return MS::kSuccess;
}
Пример #22
0
bool ToMayaSkinClusterConverter::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const
{
    MStatus s;

    IECore::ConstSmoothSkinningDataPtr skinningData = IECore::runTimeCast<const IECore::SmoothSkinningData>( from );
    assert( skinningData );

    const std::vector<std::string> &influenceNames = skinningData->influenceNames()->readable();
    const std::vector<Imath::M44f> &influencePoseData  = skinningData->influencePose()->readable();
    const std::vector<int> &pointIndexOffsets  = skinningData->pointIndexOffsets()->readable();
    const std::vector<int> &pointInfluenceCounts = skinningData->pointInfluenceCounts()->readable();
    const std::vector<int> &pointInfluenceIndices = skinningData->pointInfluenceIndices()->readable();
    const std::vector<float> &pointInfluenceWeights = skinningData->pointInfluenceWeights()->readable();

    MFnDependencyNode fnSkinClusterNode( to, &s );
    MFnSkinCluster fnSkinCluster( to, &s );
    if ( s != MS::kSuccess )
    {
        /// \todo: optional parameter to allow custom node types and checks for the necessary attributes
        /// \todo: create a new skinCluster if we want a kSkinClusterFilter and this isn't one
        throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid skinCluster" ) % fnSkinClusterNode.name() ).str() );
    }

    const unsigned origNumInfluences = influenceNames.size();
    unsigned numInfluences = origNumInfluences;
    std::vector<bool> ignoreInfluence( origNumInfluences, false );
    std::vector<int> indexMap( origNumInfluences, -1 );
    const bool ignoreMissingInfluences = m_ignoreMissingInfluencesParameter->getTypedValue();
    const bool ignoreBindPose = m_ignoreBindPoseParameter->getTypedValue();

    // gather the influence objects
    MObject mObj;
    MDagPath path;
    MSelectionList influenceList;
    MDagPathArray influencePaths;
    for ( unsigned i=0, index=0; i < origNumInfluences; i++ )
    {
        MString influenceName( influenceNames[i].c_str() );
        s = influenceList.add( influenceName );
        if ( !s )
        {
            if ( ignoreMissingInfluences )
            {
                ignoreInfluence[i] = true;
                MGlobal::displayWarning( MString( "ToMayaSkinClusterConverter: \"" + influenceName + "\" is not a valid influence" ) );
                continue;
            }

            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid influence" ) % influenceName ).str() );
        }

        influenceList.getDependNode( index, mObj );
        MFnIkJoint fnInfluence( mObj, &s );
        if ( !s )
        {
            if ( ignoreMissingInfluences )
            {
                ignoreInfluence[i] = true;
                influenceList.remove( index );
                MGlobal::displayWarning( MString( "ToMayaSkinClusterConverter: \"" + influenceName + "\" is not a valid influence" ) );
                continue;
            }

            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid influence" ) % influenceName ).str() );
        }

        fnInfluence.getPath( path );
        influencePaths.append( path );
        indexMap[i] = index;
        index++;
    }

    MPlugArray connectedPlugs;

    bool existingBindPose = true;
    MPlug bindPlug = fnSkinClusterNode.findPlug( "bindPose", true, &s );
    if ( !bindPlug.connectedTo( connectedPlugs, true, false ) )
    {
        existingBindPose = false;
        if ( !ignoreBindPose )
        {
            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" does not have a valid bindPose" ) % fnSkinClusterNode.name() ).str() );
        }
    }

    MPlug bindPoseMatrixArrayPlug;
    MPlug bindPoseMemberArrayPlug;
    if ( existingBindPose )
    {
        MFnDependencyNode fnBindPose( connectedPlugs[0].node() );
        if ( fnBindPose.typeName() != "dagPose" )
        {
            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid bindPose" ) % fnBindPose.name() ).str() );
        }

        bindPoseMatrixArrayPlug = fnBindPose.findPlug( "worldMatrix", true, &s );
        bindPoseMemberArrayPlug = fnBindPose.findPlug( "members", true, &s );
    }

    /// \todo: optional parameter to reset the skinCluster's geomMatrix plug

    // break existing influence connections to the skinCluster
    MDGModifier dgModifier;
    MMatrixArray ignoredPreMatrices;
    MPlug matrixArrayPlug = fnSkinClusterNode.findPlug( "matrix", true, &s );
    MPlug bindPreMatrixArrayPlug = fnSkinClusterNode.findPlug( "bindPreMatrix", true, &s );
    for ( unsigned i=0; i < matrixArrayPlug.numConnectedElements(); i++ )
    {
        MPlug matrixPlug = matrixArrayPlug.connectionByPhysicalIndex( i, &s );
        matrixPlug.connectedTo( connectedPlugs, true, false );
        if ( !connectedPlugs.length() )
        {
            continue;
        }

        MFnIkJoint fnInfluence( connectedPlugs[0].node() );
        fnInfluence.getPath( path );
        if ( ignoreMissingInfluences && !influenceList.hasItem( path ) )
        {
            MPlug preMatrixPlug = bindPreMatrixArrayPlug.elementByLogicalIndex( i );
            preMatrixPlug.getValue( mObj );
            MFnMatrixData matFn( mObj );
            ignoredPreMatrices.append( matFn.matrix() );
            ignoreInfluence.push_back( false );
            indexMap.push_back( influenceList.length() );
            influenceList.add( connectedPlugs[0].node() );
            numInfluences++;
        }
        dgModifier.disconnect( connectedPlugs[0], matrixPlug );
    }
    MPlug lockArrayPlug = fnSkinClusterNode.findPlug( "lockWeights", true, &s );
    for ( unsigned i=0; i < lockArrayPlug.numConnectedElements(); i++ )
    {
        MPlug lockPlug = lockArrayPlug.connectionByPhysicalIndex( i, &s );
        lockPlug.connectedTo( connectedPlugs, true, false );
        if ( connectedPlugs.length() )
        {
            dgModifier.disconnect( connectedPlugs[0], lockPlug );
        }
    }
    MPlug paintPlug = fnSkinClusterNode.findPlug( "paintTrans", true, &s );
    paintPlug.connectedTo( connectedPlugs, true, false );
    if ( connectedPlugs.length() )
    {
        dgModifier.disconnect( connectedPlugs[0], paintPlug );
    }

    // break existing influence connections to the bind pose
    if ( existingBindPose )
    {
        for ( unsigned i=0; i < bindPoseMatrixArrayPlug.numConnectedElements(); i++ )
        {
            MPlug matrixPlug = bindPoseMatrixArrayPlug.connectionByPhysicalIndex( i, &s );
            matrixPlug.connectedTo( connectedPlugs, true, false );
            if ( connectedPlugs.length() )
            {
                dgModifier.disconnect( connectedPlugs[0], matrixPlug );
            }
        }
        for ( unsigned i=0; i < bindPoseMemberArrayPlug.numConnectedElements(); i++ )
        {
            MPlug memberPlug = bindPoseMemberArrayPlug.connectionByPhysicalIndex( i, &s );
            memberPlug.connectedTo( connectedPlugs, true, false );
            if ( connectedPlugs.length() )
            {
                dgModifier.disconnect( connectedPlugs[0], memberPlug );
            }
        }
    }

    if ( !dgModifier.doIt() )
    {
        dgModifier.undoIt();
        throw IECore::Exception( "ToMayaSkinClusterConverter: Unable to break the influence connections" );
    }

    // make connections from influences to skinCluster and bindPose
    for ( unsigned i=0; i < numInfluences; i++ )
    {
        if ( ignoreInfluence[i] )
        {
            continue;
        }

        int index = indexMap[i];
        s = influenceList.getDependNode( index, mObj );
        MFnIkJoint fnInfluence( mObj, &s );
        MPlug influenceMatrixPlug = fnInfluence.findPlug( "worldMatrix", true, &s ).elementByLogicalIndex( 0, &s );
        MPlug influenceMessagePlug = fnInfluence.findPlug( "message", true, &s );
        MPlug influenceBindPosePlug = fnInfluence.findPlug( "bindPose", true, &s );
        MPlug influenceLockPlug = fnInfluence.findPlug( "lockInfluenceWeights", true, &s );
        if ( !s )
        {
            // add the lockInfluenceWeights attribute if it doesn't exist
            MFnNumericAttribute nAttr;
            MObject attribute = nAttr.create( "lockInfluenceWeights", "liw", MFnNumericData::kBoolean, false );
            fnInfluence.addAttribute( attribute );
            influenceLockPlug = fnInfluence.findPlug( "lockInfluenceWeights", true, &s );
        }

        // connect influence to the skinCluster
        MPlug matrixPlug = matrixArrayPlug.elementByLogicalIndex( index );
        MPlug lockPlug = lockArrayPlug.elementByLogicalIndex( index );
        dgModifier.connect( influenceMatrixPlug, matrixPlug );
        dgModifier.connect( influenceLockPlug, lockPlug );

        // connect influence to the bindPose
        if ( !ignoreBindPose )
        {
            MPlug bindPoseMatrixPlug = bindPoseMatrixArrayPlug.elementByLogicalIndex( index );
            MPlug memberPlug = bindPoseMemberArrayPlug.elementByLogicalIndex( index );
            dgModifier.connect( influenceMessagePlug, bindPoseMatrixPlug );
            dgModifier.connect( influenceBindPosePlug, memberPlug );
        }
    }
    unsigned firstIndex = find( ignoreInfluence.begin(), ignoreInfluence.end(), false ) - ignoreInfluence.begin();
    influenceList.getDependNode( firstIndex, mObj );
    MFnDependencyNode fnInfluence( mObj );
    MPlug influenceMessagePlug = fnInfluence.findPlug( "message", true, &s );
    dgModifier.connect( influenceMessagePlug, paintPlug );
    if ( !dgModifier.doIt() )
    {
        dgModifier.undoIt();
        throw IECore::Exception( "ToMayaSkinClusterConverter: Unable to create the influence connections" );
    }

    // use influencePoseData as bindPreMatrix
    for ( unsigned i=0; i < numInfluences; i++ )
    {
        if ( ignoreInfluence[i] )
        {
            continue;
        }

        MMatrix preMatrix = ( i < origNumInfluences ) ? IECore::convert<MMatrix>( influencePoseData[i] ) : ignoredPreMatrices[i-origNumInfluences];
        MPlug preMatrixPlug = bindPreMatrixArrayPlug.elementByLogicalIndex( indexMap[i], &s );
        s = preMatrixPlug.getValue( mObj );
        if ( s )
        {
            MFnMatrixData matFn( mObj );
            matFn.set( preMatrix );
            mObj = matFn.object();
        }
        else
        {
            MFnMatrixData matFn;
            mObj = matFn.create( preMatrix );
        }

        preMatrixPlug.setValue( mObj );
    }

    // remove unneeded bindPreMatrix children
    unsigned existingElements = bindPreMatrixArrayPlug.numElements();
    for ( unsigned i=influenceList.length(); i < existingElements; i++ )
    {
        MPlug preMatrixPlug = bindPreMatrixArrayPlug.elementByLogicalIndex( i, &s );
        /// \todo: surely there is a way to accomplish this in c++...
        MGlobal::executeCommand( ( boost::format( "removeMultiInstance %s" ) % preMatrixPlug.name() ).str().c_str() );
    }

    // get the geometry
    MObjectArray outputGeoObjs;
    if ( !fnSkinCluster.getOutputGeometry( outputGeoObjs ) )
    {
        throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: skinCluster \"%s\" does not have any output geometry!" ) % fnSkinCluster.name() ).str() );
    }
    MFnDagNode dagFn( outputGeoObjs[0] );
    MDagPath geoPath;
    dagFn.getPath( geoPath );

    // loop through all the points of the geometry and set the weights
    MItGeometry geoIt( outputGeoObjs[0] );
    MPlug weightListArrayPlug = fnSkinClusterNode.findPlug( "weightList", true, &s );
    for ( unsigned pIndex=0; !geoIt.isDone(); geoIt.next(), pIndex++ )
    {
        MPlug pointWeightsPlug = weightListArrayPlug.elementByLogicalIndex( pIndex, &s ).child( 0 );

        // remove existing influence weight plugs
        MIntArray existingInfluenceIndices;
        pointWeightsPlug.getExistingArrayAttributeIndices( existingInfluenceIndices );
        for( unsigned i=0; i < existingInfluenceIndices.length(); i++ )
        {
            MPlug influenceWeightPlug = pointWeightsPlug.elementByLogicalIndex( existingInfluenceIndices[i], &s );
            MGlobal::executeCommand( ( boost::format( "removeMultiInstance -break 1 %s" ) % influenceWeightPlug.name() ).str().c_str() );
        }

        // add new influence weight plugs
        int firstIndex = pointIndexOffsets[pIndex];
        for( int i=0; i < pointInfluenceCounts[pIndex]; i++ )
        {
            int influenceIndex = pointInfluenceIndices[ firstIndex + i ];
            if ( ignoreInfluence[ influenceIndex ] )
            {
                continue;
            }

            int skinClusterInfluenceIndex = fnSkinCluster.indexForInfluenceObject( influencePaths[ indexMap[ influenceIndex ] ] );
            MPlug influenceWeightPlug = pointWeightsPlug.elementByLogicalIndex( skinClusterInfluenceIndex, &s );
            influenceWeightPlug.setValue( pointInfluenceWeights[ firstIndex + i ] );
        }
    }

    return true;
}
Пример #23
0
//
//      Deform computation
//
MStatus jhMeshBlur::deform( MDataBlock& block,MItGeometry& iter,const MMatrix& m,unsigned int multiIndex)
{
    MStatus returnStatus;

    // Envelope
    float envData = block.inputValue(envelope, &returnStatus).asFloat();
	CHECK_MSTATUS(returnStatus);

    if(envData == 0)
		return MS::kFailure;

    /*
     VARIABLES
     */
    //float factor = block.inputValue(aShapeFactor, &returnStatus).asFloat();
    float fStrength = block.inputValue(aStrength, &returnStatus).asFloat();
	CHECK_MSTATUS(returnStatus);
	
	if (fStrength == 0)
		return MS::kFailure;
	
    float fThreshold = block.inputValue(aTreshhold, &returnStatus).asFloat();
	CHECK_MSTATUS(returnStatus);
    float fW = 0.0f; // weight
    float fDistance;
    fStrength *= envData;

    double dKracht = block.inputValue(aInterpPower, &returnStatus).asDouble();
	CHECK_MSTATUS(returnStatus);
    double dDotProduct;  // Dotproduct of the point

    bool bTweakblur = block.inputValue(aTweakBlur, &returnStatus).asBool();
	CHECK_MSTATUS(returnStatus);
	
    bool bQuad = block.inputValue(aQuadInterp, &returnStatus).asBool();
	CHECK_MSTATUS(returnStatus);
	
	MTime inTime = block.inputValue(aTime).asTime();
    int nTijd = (int)inTime.as(MTime::kFilm);


    MFloatVectorArray currentNormals;   // normals of mesh
    MFnPointArrayData fnPoints;         // help converting to MPointArrays
    MFloatVector dirVector;             // direction vector of the point
    MFloatVector normal;                // normal of the point
    MPointArray savedPoints;            // save all point before edited
    MMatrix matInv = m.inverse();       // inversed matrix
    MPoint ptA;                         // current point (iter mesh)
    MPoint ptB;                         // previous point (iter mesh)
    MPoint ptC;                         // mesh before previous point (iter mesh)

    // get node, use node to get inputGeom, use inputGeom to get mesh data, use mesh data to get normal data
    MFnDependencyNode nodeFn(this->thisMObject());

    MPlug inGeomPlug(nodeFn.findPlug(this->inputGeom,true));
    MObject inputObject(inGeomPlug.asMObject());
    MFnMesh inMesh(inputObject);

    inMesh.getVertexNormals(true, currentNormals);

    // get the previous mesh data
    MPlug oldMeshPlug = nodeFn.findPlug(MString("oldMesh"));
    MPlug oldMeshPositionsAPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 0);
    MPlug oldMeshPositionsBPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 1);
    MPlug oldMeshPositionsCPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 2); // cache for tweak mode
    MPlug oldMeshPositionsDPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 3); // cache for tweak mode

    // convert to MPointArrays
    MObject objOldMeshA;
    MObject objOldMeshB;
    MObject objOldMeshC; // cache
    MObject objOldMeshD; // cache

    oldMeshPositionsAPlug.getValue(objOldMeshA);
    oldMeshPositionsBPlug.getValue(objOldMeshB);
    oldMeshPositionsCPlug.getValue(objOldMeshC); // cache
    oldMeshPositionsDPlug.getValue(objOldMeshD); // cache

    fnPoints.setObject(objOldMeshA);
    MPointArray oldMeshPositionsA = fnPoints.array();
    
    fnPoints.setObject(objOldMeshB);
    MPointArray oldMeshPositionsB = fnPoints.array();
    
    fnPoints.setObject(objOldMeshC);
    MPointArray oldMeshPositionsC = fnPoints.array(); // cache
    
    fnPoints.setObject(objOldMeshD);
    MPointArray oldMeshPositionsD = fnPoints.array(); // cache

    
    
    // If mesh position variables are empty,fill them with default values
    if(oldMeshPositionsA.length() == 0 || nTijd <= 1){
        iter.allPositions(oldMeshPositionsA);

        for(int i=0; i < oldMeshPositionsA.length(); i++)
        {
            // convert to world
            oldMeshPositionsA[i] = oldMeshPositionsA[i] * m;
        }
		
        oldMeshPositionsB.copy(oldMeshPositionsA);
        oldMeshPositionsC.copy(oldMeshPositionsA); // cache
        oldMeshPositionsD.copy(oldMeshPositionsA); // cache
    }
	
	// get back old date again
	if (bTweakblur == true) { // restore cache
		oldMeshPositionsA.copy(oldMeshPositionsC);
		oldMeshPositionsB.copy(oldMeshPositionsD);
	}
    
    
    iter.allPositions(savedPoints);
    for(int i=0; i < savedPoints.length(); i++)
    {
        // convert points to world points
        savedPoints[i] = savedPoints[i] * m;
    }

    // Actual Iteration through points
    for (; !iter.isDone(); iter.next()){
        // get current position
        ptA = iter.position();
        // get old positions
        ptB = oldMeshPositionsA[iter.index()] * matInv;
        ptC = oldMeshPositionsB[iter.index()] * matInv;

        fDistance = ptA.distanceTo(ptB);
        fW = weightValue(block,multiIndex,iter.index());


        if (fDistance * (fStrength*fW) < fThreshold && fThreshold > 0){
            iter.setPosition(ptA);
        } else {
            // aim/direction vector to calculate strength
            dirVector = (ptA - ptB); // (per punt)
            dirVector.normalize();

            normal = currentNormals[iter.index()];

            dDotProduct = normal.x * dirVector.x + normal.y * dirVector.y + normal.z * dirVector.z;

            
            if(bQuad == true){
                MVector vecA(((ptB - ptC) + (ptA - ptB)) / 2);
                vecA.normalize();

                MPoint hiddenPt(ptB + (vecA * fDistance) * dKracht);
                ptA = quadInterpBetween(ptB, hiddenPt, ptA, (1 - fStrength * fW) + (linearInterp(dDotProduct, -1, 1) * (fStrength * fW) ) );
            } else {
                MPoint halfway = (ptA - ptB) * 0.5;
                MPoint offset = halfway * dDotProduct * (fStrength*fW);
                ptA = ptA - ((halfway * (fStrength*fW)) - offset); // + (offset * strength);
            }
            // set new value

            iter.setPosition(ptA);
        }
    }
    if(bTweakblur == false){
        oldMeshPositionsD.copy(oldMeshPositionsB);
        oldMeshPositionsC.copy(oldMeshPositionsA);
        oldMeshPositionsB.copy(oldMeshPositionsA);
        oldMeshPositionsA.copy(savedPoints);

        // Save back to plugs
        objOldMeshA = fnPoints.create(oldMeshPositionsA);
        objOldMeshB = fnPoints.create(oldMeshPositionsB);
        objOldMeshC = fnPoints.create(oldMeshPositionsC);
        objOldMeshD = fnPoints.create(oldMeshPositionsD);
		
        oldMeshPositionsAPlug.setValue(objOldMeshA);
        oldMeshPositionsBPlug.setValue(objOldMeshB);
        oldMeshPositionsCPlug.setValue(objOldMeshC);
        oldMeshPositionsDPlug.setValue(objOldMeshD);
    }
    
    return returnStatus;
}
Пример #24
0
//THIS FUNCTION IS QUITE COMPLICATED BECAUSE 
//IT HAS TO DEAL WITH MAYA NAME MANGLING!
//tokenize the path.
//add each token into the element list which tracks the attributes and indices
//for each entry added make sure there are no parents left out from maya name mangling.
//after the list is populated and missing elements area added 
//we reiterate and produce the final result.
MPlug		FxInternal::DecodePlug(const CStringA& plugStr)
{

	MPlug result;
	MFnDependencyNode depNode(GetSite());

	CAtlList<PathDecodeElement> elementList;

	//tokenize the path
	int iLastPos=0;
	int iThisPos=0;
	CStringA subStr;
	while( iLastPos= iThisPos, 
		subStr=plugStr.Tokenize(".[]", iThisPos), 
		iThisPos != -1 )
	{
		//char lastChar= subStr[iLastPos];
		//char thisChar= subStr[iThisPos];

		//are we looking at a named portion?
		if(iLastPos == 0 
			|| plugStr[iLastPos-1]=='.'
			|| (plugStr[iLastPos-1]==']' && plugStr[iLastPos]=='.'))
		{
			//if the name is length zero then it must be the case when 
			// you do last[#].  The situation is caused by  the sequence "]."
			//if we dont have a name we can skip since only 1d arrays are allowed.

			if(subStr.GetLength() > 0)
			{
		
				//everything we add is going to be based on the current tail.
				//because we are adding parents, as we find parents we can continue
				//to add them to this position so that they will order themselves properly
				POSITION insertPos= elementList.GetTailPosition();

				//calculate the cancel condition.
				//it is the current tail's object if a tail exists otherwise NULL
				//NULL indicates go all the way to the root
				MObject cancelObj= MObject::kNullObj;
				if(elementList.GetCount() > 0)
				{
					cancelObj= elementList.GetTail().Attribute.object();
				}


				//get the object we are currently working with
				MObject thisObj= depNode.attribute(subStr.GetString());
				if(thisObj.isNull())
					return MPlug();//Critical element of the path was not found...return NULL


				//add it to the list so that we have something to insertBefore
				elementList.AddTail();
				elementList.GetTail().Name= subStr;
				elementList.GetTail().Attribute.setObject(thisObj);



				//walk through all of the parents until we reach cancel condition.
				//we can add  the current element onto the list in the same way.
				for( MFnAttribute itrAttr( elementList.GetTail().Attribute.parent() );
					!itrAttr.object().isNull()  && (cancelObj != itrAttr.object());
					itrAttr.setObject(itrAttr.parent()))
				{
					PathDecodeElement element;
					element.Attribute.setObject( itrAttr.object() );

					//we change the position so that the grandparent is inserted before the parent
					insertPos= elementList.InsertBefore( insertPos, element);
				}
			}
		}
		//are we looking at a numbered portion?
		else if(plugStr[iLastPos-1]=='[' && plugStr[iThisPos-1]==']')
		{
			//if so change the array index.
			elementList.GetTail().IsArray= true;
			elementList.GetTail().Index = atoi( subStr.GetString() );
		}
		else
			DXCC_ASSERT(false);//VERY POORLY FORMED STRING

	}

	//produce the result plug off of the elementList.
	bool first= true;
	for(POSITION pos= elementList.GetHeadPosition();
		pos != NULL;
		elementList.GetNext(pos))
	{
		PathDecodeElement& element= elementList.GetAt(pos);

		if(first)
		{//on first one we initialize the result 
			first= false;
			result= MPlug( GetSite(), element.Attribute.object() );
		}
		else
		{
			result= result.child( element.Attribute.object() );
		}

		if(element.IsArray)
		{
			result= result.elementByLogicalIndex(element.Index);
		}


		if(result.isNull())
			return MPlug();//Critical element of the path was not found...return NULL
	}


	return result;
}
Пример #25
0
MStatus	CmpMeshModifierCmd::transferTweaks( const MDagPath &shapePath,
										    MObject &tweakNode, 
											MDagModifier &dagMod )
{
	// Get the tweaks from the mesh shape and apply them to the 
	// to the tweak node
	MFnDagNode shapeNodeFn( shapePath );
	MPlug srcTweaksPlug = shapeNodeFn.findPlug( "pnts" );
	
	MFnDependencyNode tweakNodeFn( tweakNode );
	MPlug dstTweaksPlug = tweakNodeFn.findPlug( "tweak" );
		
	//MGlobal::displayInfo( MString( "storing tweaks from " ) + shapePath.fullPathName() + "\n" );
	
	MPlugArray plugs;
	MPlug srcTweakPlug;
	MPlug dstTweakPlug;
	MObject dataObj;
	MFloatVector tweak;
	unsigned int nTweaks = srcTweaksPlug.numElements();
	unsigned int i, j, ci, logicalIndex;
	for( i=0; i < nTweaks; i++ )
	{
		srcTweakPlug = srcTweaksPlug.elementByPhysicalIndex( i );
		if( !srcTweakPlug.isNull() )
		{
			logicalIndex = srcTweakPlug.logicalIndex();
			
			// Set tweak node tweak element
			srcTweakPlug.getValue( dataObj );			
			MFnNumericData numDataFn( dataObj );
			numDataFn.getData( tweak[0], tweak[1], tweak[2] );
			
			dagMod.commandToExecute( MString( "setAttr " ) + tweakNodeFn.name() + ".tweak[" + logicalIndex + "] " + 
									 tweak[0] + " " + tweak[1] + " " + tweak[2] );

			// Handle transfer of incoming and outgoing connections to "pnts" elements
			dstTweakPlug = dstTweaksPlug.elementByLogicalIndex(logicalIndex);

			if( srcTweakPlug.isConnected() )
			{
				// As source, transfer source to tweak node tweak
				srcTweakPlug.connectedTo( plugs, false, true );
				for( j=0; j < plugs.length(); j++ )
				{
					dagMod.disconnect( srcTweakPlug, plugs[j] );
					dagMod.connect( dstTweakPlug, plugs[j] );
				}
				
				// As destination, transfer destination to tweak node tweak
				srcTweakPlug.connectedTo( plugs, true, false );
				if( plugs.length() == 1 ) // There can only be one input connection
				{
					dagMod.disconnect( plugs[0], srcTweakPlug );
					dagMod.connect( plugs[0], dstTweakPlug );
				}	
			}
			else // Check children
			{
				MPlug srcTweakChildPlug;
				MPlug dstTweakChildPlug;
				
				for( ci=0; ci < srcTweakPlug.numChildren(); ci++ )
				{
					srcTweakChildPlug = srcTweakPlug.child(ci);
					dstTweakChildPlug = dstTweakPlug.child(ci);
					if( srcTweakChildPlug.isConnected() )
					{
						// As souce, transfer source to tweak node tweak
						srcTweakChildPlug.connectedTo( plugs, false, true );
						for( j=0; j < plugs.length(); j++ )
						{
							dagMod.disconnect( srcTweakChildPlug, plugs[j] );
							dagMod.connect( dstTweakChildPlug, plugs[j] );
						}
						
						// As destination, transfer destination to tweak node tweak
						srcTweakChildPlug.connectedTo( plugs, true, false );
						if( plugs.length() == 1 ) // There can only be one input connection
						{
							dagMod.disconnect( plugs[0], srcTweakChildPlug );
							dagMod.connect( plugs[0], dstTweakChildPlug );
						}
					}	
				}				
			}
									
			// With the tweak values and any connections now transferred to
			// the tweak node's tweak element, this source element can be reset
			dagMod.commandToExecute( MString( "setAttr " ) + shapePath.fullPathName() + ".pnts[" + logicalIndex + "] 0 0 0" );									
			
			//MGlobal::displayInfo( MString(" tweak: ") + tweakIndices[i] + ": " + tweaks[i].x + ", " + tweaks[i].y + ", " + tweaks[i].z + "\n" );
		}
	}

	return MS::kSuccess;
}
IECore::ObjectPtr FromMayaSkinClusterConverter::doConversion( const MObject &object, IECore::ConstCompoundObjectPtr operands ) const
{
	MStatus stat;

	// our data storage objects
	IECore::StringVectorDataPtr influenceNamesData = new IECore::StringVectorData();
	IECore::M44fVectorDataPtr influencePoseData  = new IECore::M44fVectorData();
	IECore::IntVectorDataPtr pointIndexOffsetsData  = new IECore::IntVectorData();
	IECore::IntVectorDataPtr pointInfluenceCountsData = new IECore::IntVectorData();
	IECore::IntVectorDataPtr pointInfluenceIndicesData = new IECore::IntVectorData();
	IECore::FloatVectorDataPtr pointInfluenceWeightsData = new IECore::FloatVectorData();

	// get a skin cluster fn
	MFnSkinCluster skinClusterFn(object);

	MDagPathArray influencePaths;
	skinClusterFn.influenceObjects(influencePaths);

	// get the influence names
	int influencesCount = influencePaths.length();
	influenceNamesData->writable().reserve( influencesCount );

	InfluenceName in = (InfluenceName)m_influenceNameParameter->getNumericValue();
	switch( in )
	{
		case Partial :
		{
			for (int i=0; i < influencesCount; i++)
			{
				influenceNamesData->writable().push_back( influencePaths[i].partialPathName(&stat).asChar() );
			}
			break;
		}
		case Full :
		{
			for (int i=0; i < influencesCount; i++)
			{
				influenceNamesData->writable().push_back( influencePaths[i].fullPathName(&stat).asChar() );
			}
			break;
		}
	}

	// extract bind pose
	MFnDependencyNode skinClusterNodeFn( object );

	MPlug bindPreMatrixArrayPlug = skinClusterNodeFn.findPlug( "bindPreMatrix", true, &stat );

	for (int i=0; i < influencesCount; i++)
	{
		MPlug bindPreMatrixElementPlug = bindPreMatrixArrayPlug.elementByLogicalIndex(
				skinClusterFn.indexForInfluenceObject( influencePaths[i], NULL ), &stat);
		MObject matObj;
		bindPreMatrixElementPlug.getValue( matObj );
		MFnMatrixData matFn( matObj, &stat );
		MMatrix mat = matFn.matrix();
		Imath::M44f cmat = IECore::convert<Imath::M44f>( mat );

		influencePoseData->writable().push_back( cmat );
	}

	// extract the skinning information

	// get the first input geometry to the skin cluster
	// TODO: if needed, extend this to retrieve more than one output geometry
	MObjectArray outputGeoObjs;
	stat = skinClusterFn.getOutputGeometry( outputGeoObjs );

	if (! stat)
	{
		throw IECore::Exception( "FromMayaSkinClusterConverter: skinCluster node does not have any output geometry!" );
	}

	// get the dag path to the first object
	MFnDagNode dagFn( outputGeoObjs[0] );
	MDagPath geoPath;
	dagFn.getPath( geoPath );

	// generate a geo iterator for the components
	MItGeometry geoIt( outputGeoObjs[0] );
	int currentOffset = 0;

	// loop through all the points of the geometry to extract their bind information
	for ( ; !geoIt.isDone(); geoIt.next() )
	{
		MObject pointObj = geoIt.currentItem( &stat );
		MDoubleArray weights;
		unsigned int weightsCount;

		skinClusterFn.getWeights( geoPath, pointObj, weights, weightsCount );
		int pointInfluencesCount = 0;

		for ( int influenceId = 0; influenceId < int( weightsCount ); influenceId++ )
		{
			// ignore zero weights, we are generating a compressed (non-sparse) representation of the weights
			/// \todo: use a parameter to specify a threshold value rather than 0.0
			if ( weights[influenceId] != 0.0 )
			{
				pointInfluencesCount++;
				pointInfluenceWeightsData->writable().push_back( float( weights[influenceId] ) );
				pointInfluenceIndicesData->writable().push_back( influenceId );

			}
		}

		pointIndexOffsetsData->writable().push_back( currentOffset );
		pointInfluenceCountsData->writable().push_back( pointInfluencesCount );
		currentOffset += pointInfluencesCount;
	}

	// put all our results in a smooth skinning data object
	return new IECore::SmoothSkinningData( influenceNamesData, influencePoseData, pointIndexOffsetsData,
										pointInfluenceCountsData, pointInfluenceIndicesData, pointInfluenceWeightsData  );
}
Пример #27
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::processTweaks( modifyPolyData& data )
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	// Clear tweak undo information (to be rebuilt)
	//
	fTweakIndexArray.clear();
	fTweakVectorArray.clear();

	// Extract the tweaks and place them into a polyTweak node. This polyTweak node
	// will be placed ahead of the modifier node to maintain the order of operations.
	// Special care must be taken into recreating the tweaks:
	//
	//		1) Copy tweak info (including connections!)
	//		2) Remove tweak info from both meshNode and a duplicate meshNode (if applicable)
	//		3) Cache tweak info for undo operations
	//
	//if( fHasTweaks && fHasHistory && !speedupTweakProcessing())
	if( fHasTweaks && fHasHistory )
	{
		// Declare our function sets
		//
		MFnDependencyNode depNodeFn;

		// Declare our attributes and plugs
		//
		MPlug	meshTweakPlug;
		MPlug	upstreamTweakPlug;
		MObject tweakNodeTweakAttr;

		// Declare our tweak processing variables
		//
		MPlug				tweak;
		MPlug				tweakChild;
		MObject				tweakData;
		MObjectArray		tweakDataArray;
		MFloatVector		tweakVector;

		MIntArray			tweakSrcConnectionCountArray;
		MPlugArray			tweakSrcConnectionPlugArray;
		MIntArray			tweakDstConnectionCountArray;
		MPlugArray			tweakDstConnectionPlugArray;

		MPlugArray			tempPlugArray;

		unsigned i;
		unsigned j;
		unsigned k;

		// Create the tweak node and get its attributes
		//
		data.tweakNode = fDGModifier.MDGModifier::createNode( "polyTweak" );
		depNodeFn.setObject( data.tweakNode );
		data.tweakNodeSrcAttr = depNodeFn.attribute( "output" );
		data.tweakNodeDestAttr = depNodeFn.attribute( "inputPolymesh" );
		tweakNodeTweakAttr = depNodeFn.attribute( "tweak" );

		depNodeFn.setObject( data.meshNodeShape );
		meshTweakPlug = depNodeFn.findPlug( "pnts" );

		// ASSERT: meshTweakPlug should be an array plug!
		//
		MStatusAssert( (meshTweakPlug.isArray()),
					   "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
		unsigned numElements = meshTweakPlug.numElements();

		// Gather meshTweakPlug data
		//
		for( i = 0; i < numElements; i++ )
		{
			// MPlug::numElements() only returns the number of physical elements
			// in the array plug. Thus we must use elementByPhysical index when using
			// the index i.
			//
			tweak = meshTweakPlug.elementByPhysicalIndex(i);

			// If the method fails, the element is NULL. Only append the index
			// if it is a valid plug.
			//
			if( !tweak.isNull() )
			{
				// Cache the logical index of this element plug
				//
				unsigned logicalIndex = tweak.logicalIndex();

				// Collect tweak data and cache the indices and float vectors
				//
				tweak.getValue( tweakData );
				tweakDataArray.append( tweakData );
				getFloat3PlugValue( tweak, tweakVector );
				fTweakIndexArray.append( logicalIndex );
				fTweakVectorArray.append( tweakVector );

				// Collect tweak connection data
				//
				// Parse down to the deepest level of the plug tree and check
				// for connections - look at the child nodes of the element plugs.
				// If any connections are found, record the connection and disconnect
				// it.
				//

				// ASSERT: The element plug should be compound!
				//
				MStatusAssert( (tweak.isCompound()),
							   "tweak.isCompound() -- Element tweak plug is not compound" );

				unsigned numChildren = tweak.numChildren();
				for( j = 0; j < numChildren; j++ )
				{
					tweakChild = tweak.child(j);
					if( tweakChild.isConnected() )
					{
						// Get all connections with this plug as source, if they exist
						//
						tempPlugArray.clear();
						if( tweakChild.connectedTo( tempPlugArray, false, true ) )
						{
							unsigned numSrcConnections = tempPlugArray.length();
							tweakSrcConnectionCountArray.append( numSrcConnections );

							for( k = 0; k < numSrcConnections; k++ )
							{
								tweakSrcConnectionPlugArray.append( tempPlugArray[k] );
								fDGModifier.disconnect( tweakChild, tempPlugArray[k] );
							}
						}
						else
						{
							tweakSrcConnectionCountArray.append(0);
						}

						// Get the connection with this plug as destination, if it exists
						//
						tempPlugArray.clear();
						if( tweakChild.connectedTo( tempPlugArray, true, false ) )
						{
							// ASSERT: tweakChild should only have one connection as destination!
							//
							MStatusAssert( (tempPlugArray.length() == 1),
										   "tempPlugArray.length() == 1 -- 0 or >1 connections on tweakChild" );

							tweakDstConnectionCountArray.append(1);
							tweakDstConnectionPlugArray.append( tempPlugArray[0] );
							fDGModifier.disconnect( tempPlugArray[0], tweakChild );
						}
						else
						{
							tweakDstConnectionCountArray.append(0);
						}
					}
					else
					{
						tweakSrcConnectionCountArray.append(0);
						tweakDstConnectionCountArray.append(0);
					}
				}
			}
		}

		// Apply meshTweakPlug data to our polyTweak node
		//
		MPlug polyTweakPlug( data.tweakNode, tweakNodeTweakAttr );
		unsigned numTweaks = fTweakIndexArray.length();
		int srcOffset = 0;
		int dstOffset = 0;
		
		
		//Progress initialisieren
		progressBar progress("Processing Tweaks", numTweaks);
		

		for( i = 0; i < numTweaks; i++ )
		{
			// Apply tweak data
			//
			tweak = polyTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			tweak.setValue( tweakDataArray[i] );

			// ASSERT: Element plug should be compound!
			//
			MStatusAssert( (tweak.isCompound()),
						   "tweak.isCompound() -- Element plug, 'tweak', is not compound" );

			unsigned numChildren = tweak.numChildren();
			for( j = 0; j < numChildren; j++ )
			{
				tweakChild = tweak.child(j);

				// Apply tweak source connection data
				//
				if( 0 < tweakSrcConnectionCountArray[i*numChildren + j] )
				{
					for( k = 0;
						 k < (unsigned) tweakSrcConnectionCountArray[i*numChildren + j];
						 k++ )
					{
						fDGModifier.connect( tweakChild,
											 tweakSrcConnectionPlugArray[srcOffset] );
						srcOffset++;
					}
				}
						
				// Apply tweak destination connection data
				//
				if( 0 < tweakDstConnectionCountArray[i*numChildren + j] )
				{
					fDGModifier.connect( tweakDstConnectionPlugArray[dstOffset],
										 tweakChild );
					dstOffset++;
				}
			}

			if(i%50 == 0)
			{	
				progress.set(i);
			}
		}

		


		// Now, set the tweak values on the meshNode(s) to zero (History dependent)
		//
		MFnNumericData numDataFn;
		MObject nullVector;

		// Create a NULL vector (0,0,0) using MFnNumericData to pass into the plug
		//
		numDataFn.create( MFnNumericData::k3Float );
		numDataFn.setData( 0, 0, 0 );
		nullVector = numDataFn.object();

		for( i = 0; i < numTweaks; i++ )
		{
			// Access using logical indices since they are the only plugs guaranteed
			// to hold tweak data.
			//
			tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			tweak.setValue( nullVector );
		}

		// Only have to clear the tweaks off the duplicate mesh if we do not have history
		// and we want history.
		//
		if( !fHasHistory && fHasRecordHistory )
		{
			depNodeFn.setObject( data.upstreamNodeShape );
			upstreamTweakPlug = depNodeFn.findPlug( "pnts" );

			if( !upstreamTweakPlug.isNull() )
			{
				for( i = 0; i < numTweaks; i++ )
				{
					tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
					tweak.setValue( nullVector );
				}
			}
		}
	}
	else
		fHasTweaks = false;

	return status;
}
Пример #28
0
MStatus ribGenCmd::doIt( const MArgList& args)
{
	/*=========================================*
	  *		the parameters of command															
	  *	=========================================*/
	MString ribPath, shaderPath;					
	unsigned index;
	index = args.flagIndex("p", "ribPath");

	if(MArgList::kInvalidArgIndex != index)
		args.get(index+1, ribPath);
	
	index = args.flagIndex("sp", "shaderPath");
	if(MArgList::kInvalidArgIndex != index)
		args.get(index+1, shaderPath);

	/*=========================================*
	  *		shaderPath & ribPath																		
	  *=========================================*/
	RtToken shader= new char[50] , path=new char[50];
	strcpy(shader, shaderPath.asChar());
	strcpy(path, ribPath.asChar());

	char *curve[] = {"curves"};	

	RtMatrix identityMatrix =
	{	{ 1, 0, 0, 0 },
		{ 0, 1, 0, 0 },
		{ 0, 0, 1, 0 },
		{ 0, 0, 0, 1 }}; 
	
	RtInt ustep, vstep;
	ustep = vstep =1;

  /*=====================================*
	*		Begenning of writting out the .rib file.														
	*=====================================*/	
	RiBegin(path);
		RiAttributeBegin();
			RiTransformBegin();
				//RiSurface(shader);
			RiTransformEnd();


			//RiAttribute("identifier", "name", curve);
			RiConcatTransform(identityMatrix);
			RiShadingInterpolation(RI_SMOOTH);
			RiBasis(RiBezierBasis, ustep, RiBezierBasis, vstep);			



	int nodeId	= 0, knotNum = 0;
	float baseWidth = 0.0f, tipWidth	= 0.0f;
	MObject surface, node;
	/*=========================================*
	  *		get the informations of selected Objects in scene.																		
	  *=========================================*/	
	MSelectionList selection;
	MGlobal::getActiveSelectionList(selection);
	MItSelectionList iter(selection, MFn::kNurbsSurface );

	for(; !iter.isDone(); iter.next())
	{
		RtInt numCurves = 0;
		RtInt numVertexs = 0;

		/*======================================*
		  *		get the drawHairNode from selected NurbsSurface. 
		  *======================================*/
		iter.getDependNode(surface);
		MFnDependencyNode surfaceFn(surface);
		MStatus state;
		MPlug plug = surfaceFn.findPlug("worldSpace",false, &state);

		plug = plug.elementByLogicalIndex(0);
		MPlugArray desPlugs;
		plug.connectedTo(desPlugs,false,true);
		plug = desPlugs[0];
		node = plug.node();				//drawHairNode has found here!!

		/*=====================================*
		  *		get the attributes of drawHairNode. 
		  *=====================================*/
		MFnDependencyNode hairNodeFn(node);
		plug = hairNodeFn.findPlug("nodeId");
		plug.getValue(nodeId);
		MGlobal::displayInfo(MString(" nodeId: ")+nodeId);

		plug = hairNodeFn.findPlug("number");
		plug.getValue(numCurves);

		plug= hairNodeFn.findPlug("smooth");
		plug.getValue(knotNum);

		plug = hairNodeFn.findPlug("baseWidth");
		plug.getValue(baseWidth);

		plug = hairNodeFn.findPlug("tipWidth");
		plug.getValue(tipWidth);

		/*=====================================*
		  *		caculate the linear interpolate of the width of the curve.
		  *=====================================*/
		numVertexs = numCurves * knotNum;
		int widthNum = numCurves * (knotNum -2 );
		float *curveWidth = new float[widthNum];
		
		float widthStep = 0.0f;
		for(int c=0; c<widthNum; ++c){
			widthStep = ((c%(knotNum-2)) / (float)(knotNum-3)) *(tipWidth - baseWidth);
			if(widthStep < epslion)
				widthStep = 0.0f;
			curveWidth[c] = baseWidth + widthStep;
		}
		

		RtInt *nvertices = new RtInt[numCurves];						//the numbers of vertices on each curve.
		RtPoint *vertexs = new RtPoint[numVertexs];				//the total vertexs.

		/*=====================================*
		  *		nvertices[] assignment.														
		  *=====================================*/
		for(int j=0; j<numCurves ; ++j){
			nvertices[j] = knotNum;
		}



		/*=====================================*
		  *		get the hair's datas from the static member 
		  *		named "nodeManager" of the drawHairNode class. 
		  *=====================================*/
		nodeMap::iterator  iter =  drawHairNode::nodeManager.find(nodeId);
		vector<MPointArray> helixVec = iter->second;
		

		/*=====================================*
		  *		vertexs[] assignment.														
		  *=====================================*/	
		float x=0, y=0, z=0;
		int countVT=0;
		for(vector<MPointArray>::iterator it=helixVec.begin();  it != helixVec.end();  ++it){
			MPointArray helixCurve = (MPointArray)(*it);

			for(int k=0; k <  helixCurve.length() ; ++k){
				x = helixCurve[k].x;
				if(fabs(x) < epslion)
					vertexs[countVT][0] = 0;
				else
					vertexs[countVT][0] = helixCurve[k].x;
			
				y = helixCurve[k].y;
				if(fabs(y) < epslion)
					vertexs[countVT][1] = 0;
				else
					vertexs[countVT][1] = helixCurve[k].y;
			
				z = helixCurve[k].z;			
				if(fabs(z) < epslion)
					vertexs[countVT++][2] = 0;
				else
					vertexs[countVT++][2] = helixCurve[k].z;
			}
		}
		RiCurves( RI_CUBIC, numCurves, nvertices, RI_NONPERIODIC, RI_P, vertexs, RI_WIDTH, curveWidth, RI_NULL);
	}
	


		RiAttributeEnd();
	RiEnd();

	return redoIt();
}