Example #1
0
MStatus sgBulgeDeformer::deform(MDataBlock& dataBlock, MItGeometry& iter, const MMatrix& mtx, unsigned int index)
{
	MStatus status;

	float bulgeWeight = dataBlock.inputValue(aBulgeWeight).asFloat();
	double bulgeRadius = dataBlock.inputValue(aBulgeRadius).asDouble();

	MArrayDataHandle hArrInputs = dataBlock.inputArrayValue(aBulgeInputs);

	MPointArray allPositions;
	iter.allPositions(allPositions);

	if (mem_resetElements)
	{
		unsigned int elementCount = hArrInputs.elementCount();
		mem_meshInfosInner.resize(mem_maxLogicalIndex);
		mem_meshInfosOuter.resize(mem_maxLogicalIndex);

		for (unsigned int i = 0; i < elementCount; i++, hArrInputs.next())
		{
			MDataHandle hInput = hArrInputs.inputValue();
			MDataHandle hMatrix = hInput.child(aMatrix);
			MDataHandle hMesh   = hInput.child(aMesh);

			MMatrix mtxMesh = hMatrix.asMatrix();
			MObject oMesh   = hMesh.asMesh();

			MFnMeshData meshDataInner, meshDataOuter;
			MObject oMeshInner = meshDataInner.create();
			MObject oMeshOuter = meshDataOuter.create();
			MFnMesh fnMesh;
			fnMesh.copy(oMesh, oMeshInner);
			fnMesh.copy(oMesh, oMeshOuter);

			sgMeshInfo* newMeshInfoInner = new sgMeshInfo(oMeshInner, hMatrix.asMatrix());
			sgMeshInfo* newMeshInfoOuter = new sgMeshInfo(oMeshOuter, hMatrix.asMatrix());

			mem_meshInfosInner[hArrInputs.elementIndex()] = newMeshInfoInner;
			mem_meshInfosOuter[hArrInputs.elementIndex()] = newMeshInfoOuter;
		}
	}
	
	for (unsigned int i = 0; i < elementCount; i++)
	{
		mem_meshInfosInner[i]->setBulge(bulgeWeight, MSpace::kWorld );
	}
	
	MFloatArray weightList;
	weightList.setLength(allPositions.length());
	for (unsigned int i = 0; i < weightList.length(); i++)
		weightList[i] = 0.0f;
	MMatrixArray inputMeshMatrixInverses;
	inputMeshMatrixInverses.setLength(elementCount);
	for (unsigned int i = 0; i < elementCount; i++)
	{
		inputMeshMatrixInverses[i] = mem_meshInfosInner[i]->matrix();
	}

	for (unsigned int i = 0; i < allPositions.length(); i++)
	{
		float resultWeight = 0;
		for (unsigned int infoIndex = 0; infoIndex < elementCount; infoIndex++)
		{
			MPoint localPoint = allPositions[i] * mtx* inputMeshMatrixInverses[infoIndex];
			MPoint innerPoint = mem_meshInfosInner[infoIndex]->getClosestPoint(localPoint);
			MPoint outerPoint = mem_meshInfosOuter[infoIndex]->getClosestPoint(localPoint);
			MVector innerVector = innerPoint - localPoint;
			MVector outerVector = outerPoint - localPoint;

			if (innerVector * outerVector < 0)
			{
				double innerLength = innerVector.length();
				double outerLength = outerVector.length();
				double allLength = innerLength + outerLength;

				float numerator = float( innerLength * outerLength );
				float denominator = float( pow(allLength / 2.0, 2) );

				resultWeight = numerator / denominator;
			}
		}
		weightList[i] = resultWeight;
	}

	for (unsigned int i = 0; i < allPositions.length(); i++)
	{
		allPositions[i] += weightList[i] * MVector(0, 1, 0);
	}
	
	iter.setAllPositions(allPositions);

	return MS::kSuccess;
}
Example #2
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;
}
Example #3
0
MStatus testNobjectNode::compute(const MPlug &plug, MDataBlock &data)
{
	MStatus stat;

	if ( plug == outputGeom )
	{
		MObject inMeshObj = data.inputValue(inputGeom).asMesh();
		
        cerr<<"pull on outputGeom\n";

		MFnMeshData meshDataFn;
        MFnMesh inputMesh(inMeshObj);
		MObject newMeshObj = meshDataFn.create();
		MFnMesh newMeshFn;
		newMeshFn.copy( inMeshObj, newMeshObj );        

        //get the value of the currentTime so it can correctly dirty the
        //startState, currentState.
        data.inputValue(currentTime).asTime();

		// pull on next state.  This will cause the solver to pull on either
        // the startState or the currentState, depending on the time of solve.
        // When we return the state to the solver, it will do the solve and update
        // The N Object data directly.
		MObject nextNObj = data.inputValue(nextState).data();
        MFloatPointArray pts;        

        //At this point the N Object's internal state should have been updated
        //by the solver.  Read it out and set the output mesh.
        fNObject.getPositions(pts);
        if(pts.length() == (unsigned int) inputMesh.numVertices()) {
            newMeshFn.setPoints(pts);
        }

		newMeshFn.setObject( newMeshObj );

		data.outputValue(outputGeom).set(newMeshObj);
		data.setClean(plug);

	}
	if ( plug == currentState )
	{               
        MFnNObjectData outputData;
        MObject mayaNObjectData = outputData.create();
        outputData.setObject(mayaNObjectData);
        
        outputData.setObjectPtr(&fNObject);        
        outputData.setCached(false);

        MDataHandle currStateOutputHandle = data.outputValue(currentState);
        currStateOutputHandle.set(outputData.object());
	  
        cerr<<"pull on currentState\n";
	}
	if ( plug == startState )
	{
	    int ii,jj;
        // initialize MnCloth
        MObject inMeshObj = data.inputValue(inputGeom).asMesh();
				
        MFnMesh inputMesh(inMeshObj);		

        int numPolygons = inputMesh.numPolygons();
        int * faceVertCounts = new int[numPolygons];
                
        
        int facesArrayLength = 0;
        for(ii=0;ii<numPolygons;ii++) {
            MIntArray verts;
            inputMesh.getPolygonVertices(ii,verts);
            faceVertCounts[ii] = verts.length();
            facesArrayLength += verts.length();
        }
        int * faces = new int[facesArrayLength];
        int currIndex = 0;
        for(ii=0;ii<numPolygons;ii++) {
            MIntArray verts;
            inputMesh.getPolygonVertices(ii,verts);
            for(jj=0;jj<(int)verts.length();jj++) {
                faces[currIndex++] = verts[jj];
            }
        }

        int numEdges = inputMesh.numEdges();
        int * edges = new int[2*numEdges];
        currIndex = 0;
        for(ii=0;ii<numEdges;ii++) {
            int2 edge;
            inputMesh.getEdgeVertices(ii,edge);
            edges[currIndex++] = edge[0];
            edges[currIndex++] = edge[1];
        }

        // When you are doing the initialization, the first call must to be setTopology().  All other
        // calls must come after this.
        fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges );
        delete[] faceVertCounts;
        delete[] faces;
        delete[] edges;        


        unsigned int numVerts = 0;
        numVerts = inputMesh.numVertices();        

        MFloatPointArray vertexArray;
        inputMesh.getPoints(vertexArray);
        fNObject.setPositions(vertexArray,true);

        MFloatPointArray velocitiesArray;
        velocitiesArray.setLength(numVerts);
        for(ii=0;ii<(int)numVerts;ii++) {
            velocitiesArray[ii].x = 0.0f;
            velocitiesArray[ii].y = 0.0f;
            velocitiesArray[ii].z = 0.0f;
            velocitiesArray[ii].w = 0.0f;
        }
        fNObject.setVelocities(velocitiesArray);
        fNObject.setThickness(0.05f);
        fNObject.setInverseMass(1.0f);
        fNObject.setBounce(0.0f);
        fNObject.setFriction(0.1f);
        fNObject.setDamping(0.0f);
        fNObject.setBendResistance(0.0f);
        fNObject.setMaxIterations(100);        
        fNObject.setMaxSelfCollisionIterations(100);
        fNObject.setStretchAndCompressionResistance(20.0f,10.0f);
        fNObject.setSelfCollisionFlags(false);
        fNObject.setCollisionFlags(true);        	    

        
        MFnNObjectData outputData;
        MObject mayaNObjectData = outputData.create();
        outputData.setObject(mayaNObjectData);
        
        outputData.setObjectPtr(&fNObject);        
        outputData.setCached(false);

        MDataHandle startStateOutputHandle = data.outputValue(startState);
        startStateOutputHandle.set(outputData.object());

        cerr<<"pull on startState\n";
	}
	else {
		stat = MS::kUnknownParameter;
	}
	return stat;
}