Exemple #1
0
static
bool
_GetLightingParam(
        const MIntArray& intValues,
        const MFloatArray& floatValues,
        GfVec4f& paramValue)
{
    bool gotParamValue = false;

    if (intValues.length() >= 3) {
        paramValue[0] = intValues[0];
        paramValue[1] = intValues[1];
        paramValue[2] = intValues[2];
        if (intValues.length() > 3) {
            paramValue[3] = intValues[3];
        }
        gotParamValue = true;
    } else if (floatValues.length() >= 3) {
        paramValue[0] = floatValues[0];
        paramValue[1] = floatValues[1];
        paramValue[2] = floatValues[2];
        if (floatValues.length() > 3) {
            paramValue[3] = floatValues[3];
        }
        gotParamValue = true;
    }

    return gotParamValue;
}
Exemple #2
0
// #### buildUVList
//
// Face-varying data expects a list of per-face per-vertex
// floats.  This method reads the UVs from the mesh and 
// concatenates them into such a list.
//
MStatus
OsdMeshData::buildUVList( MFnMesh& meshFn, std::vector<float>& uvList )
{
    MStatus status = MS::kSuccess;

    MItMeshPolygon polyIt( _meshDagPath );

    MFloatArray uArray;
    MFloatArray vArray;

    // If user hasn't given us a UV set, use the current one
    MString *uvSetPtr=NULL;
    if ( _uvSet.numChars() > 0 ) {
        if (uvSetNameIsValid(meshFn, _uvSet)) {
            uvSetPtr = &_uvSet;
        }
        else {
            MGlobal::displayWarning(MString("OpenSubdivShader:  uvSet \""+_uvSet+"\" does not exist."));
        }
    } else {
        uvSetPtr = NULL;
    }

    // pull UVs from Maya mesh
    status = meshFn.getUVs( uArray, vArray, uvSetPtr );
    MCHECK_RETURN(status, "OpenSubdivShader: Error reading UVs");

    if ( uArray.length() == 0 || vArray.length() == 0 )
    {
        MGlobal::displayWarning("OpenSubdivShader: Mesh has no UVs");
        return MS::kFailure;
    }

    // list of UV values
    uvList.clear();
    uvList.resize( meshFn.numFaceVertices()*2 );
    int uvListIdx = 0;

    // for each face-vertex copy UVs into list, adjusting for renderman orientation
    for ( polyIt.reset(); !polyIt.isDone(); polyIt.next() ) 
    { 
        int          faceIdx      = polyIt.index(); 
        unsigned int numPolyVerts = polyIt.polygonVertexCount();

        for ( unsigned int faceVertIdx = 0; 
                           faceVertIdx < numPolyVerts; 
                           faceVertIdx++ )
        {
            int uvIdx;
            polyIt.getUVIndex( faceVertIdx, uvIdx, uvSetPtr );
            // convert maya UV orientation to renderman orientation
            uvList[ uvListIdx++ ] = uArray[ uvIdx ];
            uvList[ uvListIdx++ ] = 1.0f - vArray[ uvIdx ];
        }
    }

    return status;
}
unsigned int peltOverlap::checkCrossingEdges(
    MFloatArray &face1Orig,
    MFloatArray &face1Vec,
    MFloatArray &face2Orig,
    MFloatArray &face2Vec
)
// Check if there are crossing edges between two faces. Return true
// if there are crossing edges and false otherwise. A face is represented
// by a series of edges(rays), i.e.
// faceOrig[] = {orig1u, orig1v, orig2u, orig2v, ... }
// faceVec[]  = {vec1u,  vec1v,  vec2u,  vec2v,  ... }
{
    unsigned int face1Size = face1Orig.length();
    unsigned int face2Size = face2Orig.length();
    for (unsigned int i = 0; i < face1Size; i += 2) {
        float o1x = face1Orig[i];
        float o1y = face1Orig[i+1];
        float v1x = face1Vec[i];
        float v1y = face1Vec[i+1];
        float n1x =  v1y;
        float n1y = -v1x;
        for (unsigned int j = 0; j < face2Size; j += 2) {
            // Given ray1(O1, V1) and ray2(O2, V2)
            // Normal of ray1 is (V1.y, V1.x)
            float o2x = face2Orig[j];
            float o2y = face2Orig[j+1];
            float v2x = face2Vec[j];
            float v2y = face2Vec[j+1];
            float n2x =  v2y;
            float n2y = -v2x;

            // Find t for ray2
            // t = [(o1x-o2x)n1x + (o1y-o2y)n1y] / (v2x * n1x + v2y * n1y)
            float denum = v2x * n1x + v2y * n1y;
            // Edges are parallel if denum is close to 0.
            if (fabs(denum) < 0.000001f) continue;
            float t2 = ((o1x-o2x)* n1x + (o1y-o2y) * n1y) / denum;
            if (t2 < 0.00001f || t2 > 0.99999f) continue;

            // Find t for ray1
            // t = [(o2x-o1x)n2x + (o2y-o1y)n2y] / (v1x * n2x + v1y * n2y)
            denum = v1x * n2x + v1y * n2y;
            // Edges are parallel if denum is close to 0.
            if (fabs(denum) < 0.000001f) continue;
            float t1 = ((o2x-o1x)* n2x + (o2y-o1y) * n2y) / denum;

            // Edges intersect
            if (t1 > 0.00001f && t1 < 0.99999f) return 1;
        }
    }
    return 0;
}
// We try to do some image processing on a normal rgb image before finding the contours.
// An example when this could be useful is if we want to separate all bricks in a brick wall.
// We can do this by using the texture of the brick wall as input.
// However it doesnt work that well :(
MStatus SplitFromImage::splitFromRGBImage(MFnMesh &mesh, MString image) {
	cout << "Image filename: " << image.asChar() << endl;

	// Load image
	cv::Mat img, imgGray;
	img = cv::imread(image.asChar(), CV_LOAD_IMAGE_COLOR);
	if (!img.data) // Check for invalid input
	{
		cout << "Could not open or find the image" << endl;
		return MS::kFailure;
	}

	int thresh = 100;
	int max_thresh = 255;
	cv::RNG rng(12345);

	// Convert image to gray and blur it
	cv::cvtColor(img, imgGray, CV_BGR2GRAY);
	cv::blur(imgGray, imgGray, cv::Size(3, 3));

	cv::Mat canny_output;
	std::vector<std::vector<cv::Point> > contours;
	std::vector<cv::Vec4i> hierarchy;

	// Detect edges using canny
	cv::Canny(imgGray, canny_output, thresh, thresh * 2, 3);
	// Find contours
	cv::findContours(img, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

	for (int i = 0; i < contours.size(); i++) {
		MFloatArray uPoints;
		MFloatArray vPoints;

		for (int j = 0; j < contours[i].size(); j++) {
			cv::Point pt = contours[i][j];
			float u = (float)pt.x / img.cols;
			float v = (float)pt.y / img.rows;
			uPoints.append(u);
			vPoints.append(v);
		}

		MObject newMesh;
		if (addPlaneSubMesh(newMesh, uPoints, vPoints, mesh) == MS::kSuccess)
			cout << "Added plane sub mesh!" << endl;
		else
			cout << "Couldn't add plane sub mesh!" << endl;
	}

	return MS::kSuccess;
}
Exemple #5
0
void ropeGenerator::createCircleUvs( int pointsCount, float uvCapSize, MFloatArray &uArray, MFloatArray &vArray, float direction)
{
	MPoint baseVector( 0.5 * uvCapSize,0,0 );
	uArray.append( baseVector.x + 0.5 );
	vArray.append( baseVector.z + 0.5 );
	for ( int d = 1; d < pointsCount; d++ )
	{
		MVector vVector( baseVector );
		vVector = vVector.rotateBy( MVector::kYaxis, 
			MAngle(( 360.0 * direction / float( pointsCount )) * float( d ),MAngle::kDegrees).asRadians() );
		uArray.append( vVector.x + 0.5 );
		vArray.append( vVector.z + 0.5 );
	}
}
Exemple #6
0
// uScale and vScale switched because first edge pointing in v direction
void copy_patch_uvs(int &kV, int &kHE, MFloatArray &u_src, MFloatArray &v_src, MIntArray &uvIdx_src, MFloatArray &u_dst, MFloatArray &v_dst, float vScale, float uScale, MFloatArray &sc_u_dst, MFloatArray &sc_v_dst, MIntArray &uvIdx_dst, float lineThickness)
{
    int nHE = uvIdx_src.length();
    for (int k=0; k<nHE; k++)
    {
        uvIdx_dst[kHE] = kV + uvIdx_src[k]; // offset by beginning of this block of UVs
        
        kHE++;
    }
    
//    float offset_u = (uScale - 1) * 0.5*lineThickness;
//    float offset_v = (vScale - 1) * 0.5*lineThickness;
    
    lineThickness = 0.5 * lineThickness; 
    
    float offset_u = lineThickness * (uScale - 1.0)/(uScale - 2*lineThickness);
    float offset_v = lineThickness * (vScale - 1.0)/(vScale - 2*lineThickness);

    int nV = u_src.length();
    for (int k=0; k<nV; k++)
    {
        u_dst[kV] = u_src[k] * (1.0 - 2.0*offset_u) + offset_u;
        v_dst[kV] = v_src[k] * (1.0 - 2.0*offset_v) + offset_v;
        
        sc_u_dst[kV] = uScale * u_src[k];
        sc_v_dst[kV] = vScale * v_src[k];
        
        kV++;
    }
}
Exemple #7
0
void create_subdivided_face(int sdRes, int nV, double *uvs, double *itv, int Tidx, MFloatArray &uA, MFloatArray &vA, MIntArray &uvIdx)
{
    HDS hds;
    
    hds.V.setDims(2, nV); memcpy(&hds.V.v[0], uvs, 2*nV*sizeof(double));
    hds.nFV.setDims(1, 1); hds.nFV[0] = nV;

    hds.tip.setDims(1, nV); 
    for (size_t k=0; k<nV; k++) 
    {
        hds.tip[k] = k;
    }
    finalize_HDS(hds);
    
    size_t nHE = hds.nHE(), nIHE = hds.nIHE();⟵
    hds.T.setDims(1, nHE);
    hds.itv.setDims(1, nHE);

    memset(&hds.T.v[0], 0, nHE*sizeof(bool)); if (nV==5) hds.T[Tidx] = 1;
    memcpy(&hds.itv.v[0], itv, nV*sizeof(double));

    // border halfedge tags
    for (size_t k=nIHE; k<nHE; k++) 
    {
        hds.itv[k] = hds.itv[hds.twin[k]];
    }
    
    TCC_MAX::linear_subdivide(hds, sdRes);
    
    int sd_nV = hds.nV();
    int sd_nIHE = hds.nIHE();

    uA.setLength(sd_nV);
    vA.setLength(sd_nV);
    for (int k=0; k<sd_nV; k++)
    {
        uA[k] = hds.V[2*k+0];
        vA[k] = hds.V[2*k+1];
    }
    
    uvIdx.setLength(sd_nIHE);
    for (int k=0; k<sd_nIHE; k++)
    {
        uvIdx[k]=hds.tip[k];
    }
}
void peltOverlap::createBoundingCircle(const MStringArray &flattenFaces, MFloatArray &center, MFloatArray &radius)
//
// Description
//     Represent a face by a center and radius, i.e.
//     center = {center1u, center1v, center2u, center2v, ... }
//     radius = {radius1, radius2,  ... }
//
{
    center.setLength(2 * flattenFaces.length());
    radius.setLength(flattenFaces.length());
    for(unsigned int i = 0; i < flattenFaces.length(); i++) {
        MSelectionList selList;
        selList.add(flattenFaces[i]);
        MDagPath dagPath;
        MObject  comp;
        selList.getDagPath(0, dagPath, comp);
        MItMeshPolygon iter(dagPath, comp);

        MFloatArray uArray, vArray;
        iter.getUVs(uArray, vArray);
        // Loop through all vertices to construct edges/rays
        float cu = 0.f;
        float cv = 0.f;
        unsigned int j;
        for(j = 0; j < uArray.length(); j++) {
            cu += uArray[j];
            cv += vArray[j];
        }
        cu = cu / uArray.length();
        cv = cv / vArray.length();
        float rsqr = 0.f;
        for(j = 0; j < uArray.length(); j++) {
            float du = uArray[j] - cu;
            float dv = vArray[j] - cv;
            float dsqr = du*du + dv*dv;
            rsqr = dsqr > rsqr ? dsqr : rsqr;
        }
        center[2*i]   = cu;
        center[2*i+1] = cv;
        radius[i]  = sqrt(rsqr);
    }
}
Exemple #9
0
void ropeGenerator::createRopesUvs( int ropesCount, int pointsCount, float ropeStrength, float uvCapSize,MFloatArray &uArray, MFloatArray &vArray, float direction )
{
	MAngle angle( (180.0/ ropesCount ), MAngle::kDegrees );
	float distanceToMoveRope = cos( angle.asRadians() );
	float singleRopeRadius = sin( angle.asRadians() );
	float baseAngle = 360.0f / float( ropesCount ); 
	for ( int d = 1; d < ropesCount + 1; d++)
	{
		MFloatPointArray ropePoints( createHalfRope( pointsCount, singleRopeRadius ) );
		for ( int ropP = 0; ropP < ropePoints.length(); ropP++)
		{
			MFloatPoint ropPoint( ropePoints[ropP] );
			MVector ropV( ropPoint.x, ropPoint.y, ropPoint.z * ropeStrength );
			ropV = ropV + MVector( 0,0,-distanceToMoveRope );
			ropV = ropV.rotateBy( MVector::kYaxis, MAngle( baseAngle * float( d ), MAngle::kDegrees).asRadians() );
			ropV = ropV * 0.5 * uvCapSize;
			uArray.append( (( ropV.x * direction) + 0.5 ) );
			vArray.append( ropV.z + 0.5 );
		}
	}

}
MStatus SplitFromImage::splitFromBinaryImage(MFnMesh &mesh, MString image) {
	cout << "Image filename: " << image.asChar() << endl;

	// Load image
	cv::Mat img;
	img = cv::imread(image.asChar(), CV_LOAD_IMAGE_GRAYSCALE);
	if (!img.data) // Check for invalid input
	{
		cout << "Could not open or find the image" << endl;
		return MS::kFailure;
	}

	std::vector<std::vector<cv::Point> > contours;
	std::vector<cv::Vec4i> hierarchy;
	// Find contours
	cv::findContours(img, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

	for (int i = 0; i < contours.size(); i++) {
		MFloatArray uPoints;
		MFloatArray vPoints;

		for (int j = 0; j < contours[i].size(); j++) {
			cv::Point pt = contours[i][j];
			float u = (float)pt.x / img.cols;
			float v = (float)pt.y / img.rows;
			uPoints.append(u);
			vPoints.append(v);
		}

		MObject newMesh;
		if (addPlaneSubMesh(newMesh, uPoints, vPoints, mesh) == MS::kSuccess)
			cout << "Added plane sub mesh!" << endl;
		else
			cout << "Couldn't add plane sub mesh!" << endl;
 	}

	return MS::kSuccess;
}
float peltOverlap::area(const MFloatArray &orig)
{
    float sum = 0.f;
    unsigned int num = orig.length() / 2;
    for (unsigned int i = 0; i < num; i++) {
        unsigned int idx  = 2 * i;
        unsigned int idy  = (i + 1 ) % num;
        idy = 2 * idy + 1;
        unsigned int idy2 = (i + num - 1) % num;
        idy2 = 2 * idy2 + 1;
        sum += orig[idx] * (orig[idy] - orig[idy2]);
    }
    return fabs(sum) * 0.5f;
}
bool peltOverlap::createRayGivenFace(const MString &face, MFloatArray &orig, MFloatArray &vec)
//
// Description
//     Represent a face by a series of edges(rays), i.e.
//     orig = {orig1u, orig1v, orig2u, orig2v, ... }
//     vec  = {vec1u,  vec1v,  vec2u,  vec2v,  ... }
//
//     return false if no valid uv's.
{
    MSelectionList selList;
    selList.add(face);
    MDagPath dagPath;
    MObject  comp;
    selList.getDagPath(0, dagPath, comp);
    MItMeshPolygon iter(dagPath, comp);

    MFloatArray uArray, vArray;
    iter.getUVs(uArray, vArray);

    if (uArray.length() == 0 || vArray.length() == 0) return false;

    orig.setLength(2 * uArray.length());
    vec.setLength( 2 * uArray.length());

    // Loop through all vertices to construct edges/rays
    float u = uArray[uArray.length() - 1];
    float v = vArray[vArray.length() - 1];
    for(unsigned int j = 0; j < uArray.length(); j++) {
        orig[2*j]   = uArray[j];
        orig[2*j+1] = vArray[j];
        vec[2*j]    = u - uArray[j];
        vec[2*j+1]  = v - vArray[j];
        u = uArray[j];
        v = vArray[j];
    }
    return true;
}
MStatus
XmlCacheFormat::readFloatArray( MFloatArray& array, unsigned arraySize )
{
	MStringArray value;
	readXmlTagValue(floatArrayTag, value);

	assert( value.length() == arraySize );
	array.setLength( arraySize );
	for ( unsigned int i = 0; i < value.length(); i++ )
	{
		array[i] = (float)strtod( value[i].asChar(), NULL );
	}
	
	return MS::kSuccess;
}
Exemple #14
0
static
bool
_GetLightingParam(
        const MIntArray& intValues,
        const MFloatArray& floatValues,
        float& paramValue)
{
    bool gotParamValue = false;

    if (floatValues.length() > 0) {
        paramValue = floatValues[0];
        gotParamValue = true;
    }

    return gotParamValue;
}
MStatus
XmlCacheFormat::writeFloatArray( const MFloatArray& array )
{
	int size = array.length();
	assert(size != 0);

	writeXmlTagValue(sizeTag,size);

	startXmlBlock( floatArrayTag );
	for(int i = 0; i < size; i++)
	{
	    writeXmlValue(array[i]);
	}
	endXmlBlock();
	return MS::kSuccess;
}
Exemple #16
0
static
bool
_GetLightingParam(
        const MIntArray& intValues,
        const MFloatArray& floatValues,
        bool& paramValue)
{
    bool gotParamValue = false;

    if (intValues.length() > 0) {
        paramValue = (intValues[0] == 1);
        gotParamValue = true;
    } else if (floatValues.length() > 0) {
        paramValue = GfIsClose(floatValues[0], 1.0f, 1e-5);
        gotParamValue = true;
    }

    return gotParamValue;
}
Exemple #17
0
MStatus TransferUV::redoIt()
{
    MStatus status;

    MFnMesh sourceFnMesh(sourceDagPath);
    MFnMesh targetFnMesh(targetDagPath);
    
    // Get current UV sets and keep them to switch back to them at the last
    MString currentSourceUVSet = sourceFnMesh.currentUVSetName();
    MString currentTargetUVSet = targetFnMesh.currentUVSetName();

    // Switch to uv sets specified in flags before starting transfer process
    // This is required because MFnMesh does not work properly with
    // "Non-current" UV sets
    sourceFnMesh.setCurrentUVSetName(sourceUvSet);
    targetFnMesh.setCurrentUVSetName(targetUvSet);
    
    MString* sourceUvSetPtr = &sourceUvSet;
    MString* targetUvSetPtr = &targetUvSet;

    MFloatArray sourceUarray;
    MFloatArray sourceVarray;
    MIntArray sourceUvCounts;
    MIntArray sourceUvIds;

    // Get mesh information for each
    status = sourceFnMesh.getUVs(sourceUarray, sourceVarray, sourceUvSetPtr);
    if (status != MS::kSuccess) {
        MGlobal::displayError("Failed to get source UVs");
        CHECK_MSTATUS_AND_RETURN_IT(status);
    }
    status = targetFnMesh.getUVs(originalUarray, originalVarray, targetUvSetPtr);
    if (status != MS::kSuccess) {
        MGlobal::displayError("Failed to get original UVs");
        CHECK_MSTATUS_AND_RETURN_IT(status);
    }
    status = sourceFnMesh.getAssignedUVs(sourceUvCounts, sourceUvIds, sourceUvSetPtr);
    if (status != MS::kSuccess) {
        MGlobal::displayError("Failed to get source assigned UVs");
        CHECK_MSTATUS_AND_RETURN_IT(status);
    }
    status = targetFnMesh.getAssignedUVs(originalUvCounts, originalUvIds, targetUvSetPtr);
    if (status != MS::kSuccess) {
        MGlobal::displayError("Failed to get original assigned UVs");
        CHECK_MSTATUS_AND_RETURN_IT(status);
    }

    // Resize source uv array so it becomes same size as number of targets uv
    unsigned int targetNumUVs = targetFnMesh.numUVs();
    if (targetNumUVs > sourceUarray.length()) {
        sourceUarray.setLength(targetNumUVs);
        sourceVarray.setLength(targetNumUVs);
    }

    status = targetFnMesh.setUVs(sourceUarray, sourceVarray, targetUvSetPtr);
    if (MS::kSuccess != status) {
        MGlobal::displayError("Failed to set source UVs");
        return status;
    }

    status = targetFnMesh.assignUVs(sourceUvCounts, sourceUvIds, targetUvSetPtr);
    if (MS::kSuccess != status) {
        MGlobal::displayError("Failed to assign source UVs");
        return status;
    }

    // Switch back to originals
    sourceFnMesh.setCurrentUVSetName(currentSourceUVSet);
    targetFnMesh.setCurrentUVSetName(currentTargetUVSet);
    
    return MS::kSuccess;
}
void ToMayaMeshConverter::addUVSet( MFnMesh &fnMesh, const MIntArray &polygonCounts, IECore::ConstMeshPrimitivePtr mesh, const std::string &sPrimVarName, const std::string &tPrimVarName, const std::string &stIdPrimVarName, MString *uvSetName ) const
{
	IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( sPrimVarName );
	bool haveS = sIt != mesh->variables.end();
	IECore::PrimitiveVariableMap::const_iterator tIt = mesh->variables.find( tPrimVarName );
	bool haveT = tIt != mesh->variables.end();
	IECore::PrimitiveVariableMap::const_iterator stIdIt = mesh->variables.find( stIdPrimVarName );
	bool haveSTId = stIdIt != mesh->variables.end();

	if ( haveS && haveT )
	{
		if ( sIt->second.interpolation != IECore::PrimitiveVariable::FaceVarying )
		{
			IECore::msg( IECore::Msg::Warning,"ToMayaMeshConverter::doConversion",  boost::format(  "PrimitiveVariable \"%s\" has unsupported interpolation (expected FaceVarying).") % sPrimVarName );
			return;
		}

		if ( tIt->second.interpolation != IECore::PrimitiveVariable::FaceVarying )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported interpolation (expected FaceVarying).") % tPrimVarName);
			return;
		}

		if ( !sIt->second.data )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has no data." ) % sPrimVarName );
		}

		if ( !tIt->second.data )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has no data." ) % tPrimVarName );
		}

		/// \todo Employ some M*Array converters to simplify this
		int numUVs = mesh->variableSize( IECore::PrimitiveVariable::FaceVarying );

		IECore::ConstFloatVectorDataPtr u = IECore::runTimeCast<const IECore::FloatVectorData>(sIt->second.data);

		if ( !u )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % sPrimVarName % sIt->second.data->typeName() );
			return;
		}

		assert( (int)u->readable().size() == numUVs );
		
		IECore::ConstFloatVectorDataPtr v = IECore::runTimeCast<const IECore::FloatVectorData>(tIt->second.data);
		if ( !v )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % tPrimVarName % tIt->second.data->typeName() );
			return;
		}

		assert( (int)v->readable().size() == numUVs );
		
		const std::vector<float> &uAll = u->readable();
		const std::vector<float> &vAll = v->readable();

		if ( uvSetName )
		{
			bool setExists = false;
			MStringArray existingSets;
			fnMesh.getUVSetNames( existingSets );
			for ( unsigned i=0; i < existingSets.length(); ++i )
			{
				if ( *uvSetName == existingSets[i] )
				{
					fnMesh.clearUVs( uvSetName );
					setExists = true;
					break;
				}
			}
			
			if ( !setExists )
			{
				MDagPath dag;
				MStatus s = fnMesh.getPath( dag );
				if ( s )
				{
					fnMesh.createUVSetWithName( *uvSetName );
				}
				else
				{
					fnMesh.createUVSetDataMeshWithName( *uvSetName );
				}
			}
		}
		
		MIntArray uvIds;
		uvIds.setLength( numUVs );
		MFloatArray uArray;
		MFloatArray vArray;
		
		if( haveSTId )
		{
			// Get compressed uv values by matching them with their uvId.
			IECore::ConstIntVectorDataPtr uvId = IECore::runTimeCast<const IECore::IntVectorData>(stIdIt->second.data);
			if ( !uvId )
			{
				IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % stIdPrimVarName % stIdIt->second.data->typeName() );
				return;
			}
			
			const std::vector<int> &uvIdData = uvId->readable();
	
			assert( (int)uvIdData.size() == numUVs );
			
			int highestId = 0;
			for ( int i = 0; i < numUVs; i++)
			{
				uvIds[i] = uvIdData[i];
				if( uvIdData[i] > highestId )
				{
					highestId = uvIdData[i];
				}
			}
			
			// u and v arrays need only be as long as the number of unique uvIds
			uArray.setLength( highestId + 1 );
			vArray.setLength( highestId + 1 );
			
			for ( int i = 0; i < numUVs; i++ )
			{
				uArray[ uvIds[i] ] = uAll[i];
				// FromMayaMeshConverter does the opposite of this
				vArray[ uvIds[i] ] = 1 - vAll[i];
			}
		}
		else
		{
			// If for some reason we cannot find the uv indices, set the UVs using the old way
			// the performances in maya won't be good (for weigth painting in particular)
			uArray.setLength( numUVs );
			vArray.setLength( numUVs );

			for ( int i = 0; i < numUVs; i++)
			{
				uArray[i] = u->readable()[i];
				// FromMayaMeshConverter does the opposite of this
				vArray[i] = 1 - v->readable()[i];
			}
			
			for ( int i = 0; i < numUVs; i++)
			{
				uvIds[i] = i;
			}
		}
		
		MStatus s = fnMesh.setUVs( uArray, vArray, uvSetName );
		if ( !s )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to set UVs." );
			return;
		}

		s = fnMesh.assignUVs( polygonCounts, uvIds, uvSetName );
		if ( !s )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to assign UVs." );
			return;
		}

	}
	else if ( haveS )
	{
		IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "Primitive variable \"%s\" found, but not \"%s\"." ) % sPrimVarName % tPrimVarName );
	}
	else if ( haveT )
	{
		IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "Primitive variable \"%s\" found, but not \"%s\"." ) % tPrimVarName % sPrimVarName );
	}
	else
	{
		assert( !uvSetName );
	}
}
PXR_NAMESPACE_OPEN_SCOPE

bool
MayaMeshWriter::_GetMeshUVSetData(
        const MFnMesh& mesh,
        const MString& uvSetName,
        VtArray<GfVec2f>* uvArray,
        TfToken* interpolation,
        VtArray<int>* assignmentIndices)
{
    MStatus status;

    // Sanity check first to make sure this UV set even has assigned values
    // before we attempt to do anything with the data.
    MIntArray uvCounts, uvIds;
    status = mesh.getAssignedUVs(uvCounts, uvIds, &uvSetName);
    if (status != MS::kSuccess) {
        return false;
    }
    if (uvCounts.length() == 0 || uvIds.length() == 0) {
        return false;
    }

    // using itFV.getUV() does not always give us the right answer, so
    // instead, we have to use itFV.getUVIndex() and use that to index into the
    // UV set.
    MFloatArray uArray;
    MFloatArray vArray;
    mesh.getUVs(uArray, vArray, &uvSetName);
    if (uArray.length() != vArray.length()) {
        return false;
    }

    // We'll populate the assignment indices for every face vertex, but we'll
    // only push values into the data if the face vertex has a value. All face
    // vertices are initially unassigned/unauthored.
    const unsigned int numFaceVertices = mesh.numFaceVertices(&status);
    uvArray->clear();
    assignmentIndices->assign((size_t)numFaceVertices, -1);
    *interpolation = UsdGeomTokens->faceVarying;

    MItMeshFaceVertex itFV(mesh.object());
    unsigned int fvi = 0;
    for (itFV.reset(); !itFV.isDone(); itFV.next(), ++fvi) {
        if (!itFV.hasUVs(uvSetName)) {
            // No UVs for this faceVertex, so leave it unassigned.
            continue;
        }

        int uvIndex;
        itFV.getUVIndex(uvIndex, &uvSetName);
        if (uvIndex < 0 || static_cast<size_t>(uvIndex) >= uArray.length()) {
            return false;
        }

        GfVec2f value(uArray[uvIndex], vArray[uvIndex]);
        uvArray->push_back(value);
        (*assignmentIndices)[fvi] = uvArray->size() - 1;
    }

    PxrUsdMayaUtil::MergeEquivalentIndexedValues(uvArray,
                                                 assignmentIndices);
    PxrUsdMayaUtil::CompressFaceVaryingPrimvarIndices(mesh,
                                                      interpolation,
                                                      assignmentIndices);

    return true;
}
MStatus exportJointClusterData::doIt( const MArgList& args )
//
// Process the command	
// 1. parse the args
// 2. find the jointClusters in the scene
// 3. iterate over their members, writing their weight data out to file	
//
{
	// parse args to get the file name from the command-line
	//
	MStatus stat = parseArgs(args);
	if (stat != MS::kSuccess) {
		return stat;
	}

	// count the processed jointClusters
	//
	unsigned int jcCount = 0;

	// Iterate through graph and search for jointCluster nodes
	//
	MItDependencyNodes iter( MFn::kJointCluster);
	for ( ; !iter.isDone(); iter.next() ) {
		MObject object = iter.item();
		MFnWeightGeometryFilter jointCluster(object);

		// get the joint driving this cluster
		//
		MObject joint = jointForCluster(object);
		if (joint.isNull()) {
			displayError("Joint is not attached to cluster.");
			continue;
		}

		MObject deformSet = jointCluster.deformerSet(&stat);
		CheckError(stat,"Error getting deformer set.");
			
		MFnSet setFn(deformSet, &stat);	//need the fn to get the members
		CheckError(stat,"Error getting deformer set fn.");
		
		MSelectionList clusterSetList;

		//get all the members
		//
		stat = setFn.getMembers(clusterSetList, true);
		CheckError(stat,"Could not make member list with getMembers.");

		// print out the name of joint and the number of associated skins
		//
		MFnDependencyNode fnJoint(joint);
		fprintf(file,"%s %u\n",fnJoint.name().asChar(),
				clusterSetList.length());
		
		for (unsigned int kk = 0; kk < clusterSetList.length(); ++kk) {
			MDagPath skinpath;
			MObject components;
			MFloatArray weights;

			clusterSetList.getDagPath(kk,skinpath,components);
			jointCluster.getWeights(skinpath,components,weights);

			// print out the path name of the skin & the weight count
			//
			fprintf(file,
					"%s %u\n",skinpath.partialPathName().asChar(),
					weights.length());

			// loop through the components and print their index and weight
			//
			unsigned counter =0;
			MItGeometry gIter(skinpath,components);
			for (/* nothing */ ; !gIter.isDone() &&
								   counter < weights.length(); gIter.next()) {
				fprintf(file,"%d %f\n",gIter.index(),weights[counter]);
				counter++;
			}
		}
		jcCount++;
	}

	fclose(file);

	if (0 == jcCount) {
		displayError("No jointClusters found in this scene.");
		return MS::kFailure;
	}

	return MS::kSuccess;
}
Exemple #21
0
void MayaObject::getMeshData(MPointArray& points, MFloatVectorArray& normals, MFloatArray& uArray, MFloatArray& vArray, MIntArray& triPointIndices, MIntArray& triNormalIndices, MIntArray& triUvIndices, MIntArray& triMatIndices)
{

	MStatus stat;
	MObject meshObject = this->mobject;
	MMeshSmoothOptions options;
	MFnMesh tmpMesh(this->mobject, &stat);

	MFnMeshData meshData;
	MObject dataObject;
	MObject smoothedObj;

	// create smooth mesh if needed
	if (tmpMesh.findPlug("displaySmoothMesh").asBool())
	{
		stat = tmpMesh.getSmoothMeshDisplayOptions(options);
		if (stat)
		{
			if (!tmpMesh.findPlug("useSmoothPreviewForRender", false, &stat).asBool())
			{
				//Logging::debug(MString("useSmoothPreviewForRender turned off"));
				int smoothLevel = tmpMesh.findPlug("renderSmoothLevel", false, &stat).asInt();
				options.setDivisions(smoothLevel);
			}
			if (options.divisions() > 0)
			{
				dataObject = meshData.create();
				smoothedObj = tmpMesh.generateSmoothMesh(dataObject, &options, &stat);
				if (stat)
				{
					meshObject = smoothedObj;
				}
			}
		}
	}

	MFnMesh meshFn(meshObject, &stat);
	CHECK_MSTATUS(stat);
	MItMeshPolygon faceIt(meshObject, &stat);
	CHECK_MSTATUS(stat);

	meshFn.getPoints(points);
	meshFn.getNormals(normals, MSpace::kObject);
	meshFn.getUVs(uArray, vArray);

	uint numVertices = points.length();
	uint numNormals = normals.length();
	uint numUvs = uArray.length();

	//Logging::debug(MString("numVertices ") + numVertices);
	//Logging::debug(MString("numNormals ") + numNormals);
	//Logging::debug(MString("numUvs ") + numUvs);

	// some meshes may have no uv's
	// to avoid problems I add a default uv coordinate
	if (numUvs == 0)
	{
		Logging::warning(MString("Object has no uv's: ") + this->shortName);
		uArray.append(0.0);
		vArray.append(0.0);
	}
	for (uint nid = 0; nid < numNormals; nid++)
	{
		if (normals[nid].length() < 0.1f)
			Logging::warning(MString("Malformed normal in ") + this->shortName);
	}
	MPointArray triPoints;
	MIntArray triVtxIds;
	MIntArray faceVtxIds;
	MIntArray faceNormalIds;

	for (faceIt.reset(); !faceIt.isDone(); faceIt.next())
	{
		int faceId = faceIt.index();
		int numTris;
		faceIt.numTriangles(numTris);
		faceIt.getVertices(faceVtxIds);

		int perFaceShadingGroup = 0;
		if (this->perFaceAssignments.length() > 0)
			perFaceShadingGroup = this->perFaceAssignments[faceId];
		
		MIntArray faceUVIndices;
		
		faceNormalIds.clear();
		for (uint vtxId = 0; vtxId < faceVtxIds.length(); vtxId++)
		{
			faceNormalIds.append(faceIt.normalIndex(vtxId));
			int uvIndex;
			if (numUvs == 0)
			{
				faceUVIndices.append(0);
			}
			else{
				faceIt.getUVIndex(vtxId, uvIndex);
				//if (uvIndex > uArray.length())
				//	Logging::info(MString("-----------------> UV Problem!!! uvIndex ") + uvIndex + " > uvArray in object " + this->shortName);
				faceUVIndices.append(uvIndex);
			}
		}

		for (int triId = 0; triId < numTris; triId++)
		{
			int faceRelIds[3];
			faceIt.getTriangle(triId, triPoints, triVtxIds);

			for (uint triVtxId = 0; triVtxId < 3; triVtxId++)
			{
				for (uint faceVtxId = 0; faceVtxId < faceVtxIds.length(); faceVtxId++)
				{
					if (faceVtxIds[faceVtxId] == triVtxIds[triVtxId])
					{
						faceRelIds[triVtxId] = faceVtxId;
					}
				}
			}

			uint vtxId0 = faceVtxIds[faceRelIds[0]];
			uint vtxId1 = faceVtxIds[faceRelIds[1]];
			uint vtxId2 = faceVtxIds[faceRelIds[2]];
			uint normalId0 = faceNormalIds[faceRelIds[0]];
			uint normalId1 = faceNormalIds[faceRelIds[1]];
			uint normalId2 = faceNormalIds[faceRelIds[2]];
			uint uvId0 = faceUVIndices[faceRelIds[0]];
			uint uvId1 = faceUVIndices[faceRelIds[1]];
			uint uvId2 = faceUVIndices[faceRelIds[2]];

			triPointIndices.append(vtxId0);
			triPointIndices.append(vtxId1);
			triPointIndices.append(vtxId2);

			triNormalIndices.append(normalId0);
			triNormalIndices.append(normalId1);
			triNormalIndices.append(normalId2);

			triUvIndices.append(uvId0);
			triUvIndices.append(uvId1);
			triUvIndices.append(uvId2);

			triMatIndices.append(perFaceShadingGroup);

			//Logging::debug(MString("vtxIds ") + vtxId0 + " " + vtxId1 + " " + vtxId2);
			//Logging::debug(MString("nIds ") + normalId0 + " " + normalId1 + " " + normalId2);
			//Logging::debug(MString("uvIds ") + uvId0 + " " + uvId1 + " " + uvId2);
		}
	}

}
Exemple #22
0
MStatus Mesh::load(MDagPath& meshDag,MDagPath *pDagPath)
{
	MStatus stat;
	std::vector<MFloatArray> weights;
	std::vector<MIntArray> Ids;
	std::vector<MIntArray> jointIds;
	unsigned int numJoints = 0;
	std::vector<vertexInfo> vertices;
	MFloatPointArray points;
	MFloatVectorArray normals;

	if (!meshDag.hasFn(MFn::kMesh))
		return MS::kFailure;

	MFnMesh mesh(meshDag);
	/*{
		mesh.getPoints(points,MSpace::kWorld);
		MPoint pos;
		mesh.getPoint(1,pos,MSpace::kWorld);
		for(unsigned i = 0;i < points.length();i++)
		{
			MFloatPoint fp = points[i];
			float x = fp.x;
			float y = fp.y;
			float z = fp.z;
			fp = fp;
		}
	}*/
	int numVertices = mesh.numVertices();
	vertices.resize(numVertices);
	weights.resize(numVertices);
	Ids.resize(numVertices);
	jointIds.resize(numVertices);

	// 获取UV坐标集的名称
	MStringArray uvsets;
	int numUVSets = mesh.numUVSets();
	if (numUVSets > 0)
	{
		stat = mesh.getUVSetNames(uvsets);
		if (MS::kSuccess != stat)
		{
			std::cout << "Error retrieving UV sets names\n";
			return MS::kFailure;
		}
	}
	// 保存UV集信息
	for (int i=m_uvsets.size(); i<uvsets.length(); i++)
	{
		uvset uv;
		uv.size = 2;
		uv.name = uvsets[i].asChar();
		m_uvsets.push_back(uv);
	}

	MStringArray colorSetsNameArray;
	m_colorSets.clear();
	int numColorSets = mesh.numColorSets();
	if (numColorSets > 0)
	{
		mesh.getColorSetNames(colorSetsNameArray);
	}
	for (int i = 0; i != colorSetsNameArray.length(); ++i)
	{
		std::string name = colorSetsNameArray[i].asChar();
		m_colorSets.push_back(name);
	}
	// 检查法线是否反
	bool opposite = false;
	mesh.findPlug("opposite",true).getValue(opposite);

	// get connected skin cluster (if present)
	bool foundSkinCluster = false;
	MItDependencyNodes kDepNodeIt( MFn::kSkinClusterFilter );            
	for( ;!kDepNodeIt.isDone() && !foundSkinCluster; kDepNodeIt.next()) 
	{            
		MObject kObject = kDepNodeIt.item();
		m_pSkinCluster = new MFnSkinCluster(kObject);
		unsigned int uiNumGeometries = m_pSkinCluster->numOutputConnections();
		for(unsigned int uiGeometry = 0; uiGeometry < uiNumGeometries; ++uiGeometry ) 
		{
			unsigned int uiIndex = m_pSkinCluster->indexForOutputConnection(uiGeometry);
			MObject kOutputObject = m_pSkinCluster->outputShapeAtIndex(uiIndex);
			if(kOutputObject == mesh.object()) 
			{
				foundSkinCluster = true;
			}
			else
			{
				delete m_pSkinCluster;
				m_pSkinCluster = NULL;
			}
		}

		// load connected skeleton (if present)
		if (m_pSkinCluster)
		{
			if (!m_pSkeleton)
				m_pSkeleton = new skeleton();
			stat = m_pSkeleton->load(m_pSkinCluster);
			if (MS::kSuccess != stat)
				std::cout << "Error loading skeleton data\n";
		}
		else
		{
//			breakable;
		}
	}
	// get connected shaders
	MObjectArray shaders;
	MIntArray shaderPolygonMapping;
	stat = mesh.getConnectedShaders(0,shaders,shaderPolygonMapping);
	if (MS::kSuccess != stat)
	{
		std::cout << "Error getting connected shaders\n";
		return MS::kFailure;
	}

	if (shaders.length() <= 0)
	{
		std::cout << "No connected shaders, skipping mesh\n";
		return MS::kFailure;
	}

	// create a series of arrays of faces for each different submesh
	std::vector<faceArray> polygonSets;
	polygonSets.resize(shaders.length());

	// Get faces data
	// prepare vertex table
	for (int i=0; i<vertices.size(); i++)
		vertices[i].next = -2;
	//get vertex positions from mesh data

	mesh.getPoints(points,MSpace::kWorld);
	mesh.getNormals(normals,MSpace::kWorld);

	//get list of vertex weights
	if (m_pSkinCluster)
	{
		MItGeometry iterGeom(meshDag);
		for (int i=0; !iterGeom.isDone(); iterGeom.next(), i++)
		{
			weights[i].clear();
			Ids[i].clear();
			MObject component = iterGeom.component();
			MFloatArray vertexWeights;
			stat=m_pSkinCluster->getWeights(meshDag,component,vertexWeights,numJoints);
			int nWeights = vertexWeights.length();
			for(int j = 0;j<nWeights;j++)
			{
				if(vertexWeights[j] >= 0.00001f || vertexWeights[j] <= -0.00001f  )
				{
					// 记录该节点j
					Ids[i].append(j);
					weights[i].append(vertexWeights[j]);
				}
			}
		
			//weights[i]= vertexWeights;

			if (MS::kSuccess != stat)
			{
				std::cout << "Error retrieving vertex weights\n";
			}
			// get ids for the joints
			if (m_pSkeleton)
			{
				jointIds[i].clear();
				if(weights[i].length() > 0 )
				{
					MDagPathArray influenceObjs;
					m_pSkinCluster->influenceObjects(influenceObjs,&stat);
					if (MS::kSuccess != stat)
					{
						std::cout << "Error retrieving influence objects for given skin cluster\n";
					}
					jointIds[i].setLength(weights[i].length());
					for (int j=0; j<jointIds[i].length(); j++)
					{
						bool foundJoint = false;
						for (int k=0; k<m_pSkeleton->getJoints().size() && !foundJoint; k++)
						{
							if (influenceObjs[Ids[i][j]].partialPathName() == m_pSkeleton->getJoints()[k].name)
							{
								foundJoint=true;
								jointIds[i][j] = m_pSkeleton->getJoints()[k].id;
							}
						}
					}
				}
				
			}
		}
	}
	// create an iterator to go through mesh polygons
	if (mesh.numPolygons() > 0)
	{
		const char *name = mesh.name().asChar();
		MItMeshPolygon faceIter(mesh.object(),&stat);
		if (MS::kSuccess != stat)
		{
			std::cout << "Error accessing mesh polygons\n";
			return MS::kFailure;
		}

		// iterate over mesh polygons
		for (; !faceIter.isDone(); faceIter.next())
		{
			int numTris=0;
			faceIter.numTriangles(numTris);
			// for every triangle composing current polygon extract triangle info
			for (int iTris=0; iTris<numTris; iTris++)
			{
				MPointArray triPoints;
				MIntArray tempTriVertexIdx,triVertexIdx;
				int idx;
				// create a new face to store triangle info
				face newFace;
				// extract triangle vertex indices
				faceIter.getTriangle(iTris,triPoints,tempTriVertexIdx);
				// convert indices to face-relative indices
				MIntArray polyIndices;
				faceIter.getVertices(polyIndices);
				unsigned int iPoly, iObj;
				for (iObj=0; iObj < tempTriVertexIdx.length(); ++iObj)
				{
					// iPoly is face-relative vertex index
					for (iPoly=0; iPoly < polyIndices.length(); ++iPoly)
					{
						if (tempTriVertexIdx[iObj] == polyIndices[iPoly]) 
						{
							triVertexIdx.append(iPoly);
							break;
						}
					}
				}
				// iterate over triangle's vertices
				for (int i=0; i<3; i++)
				{
					bool different = true;
					int vtxIdx = faceIter.vertexIndex(triVertexIdx[i]);
					int nrmIdx = faceIter.normalIndex(triVertexIdx[i]);

					// get vertex color
					MColor color;
					if (faceIter.hasColor(triVertexIdx[i]))
					{
						//This method gets the average color of the all the vertices in this face
						stat = faceIter.getColor(color,triVertexIdx[i]);
						if (MS::kSuccess != stat)
						{
							color = MColor(1,1,1,1);
						}
						if (color.r > 1)
							color.r = 1;
						if (color.g > 1)
							color.g = 1;
						if (color.b > 1)
							color.b = 1;
						if (color.a > 1)
							color.a = 1;
					}
					else
					{
						color = MColor(1,1,1,1);
					}
					if (vertices[vtxIdx].next == -2)	// first time we encounter a vertex in this position
					{
						// save vertex position
						points[vtxIdx].cartesianize();
						vertices[vtxIdx].pointIdx = vtxIdx;
						// save vertex normal
						vertices[vtxIdx].normalIdx = nrmIdx;
						// save vertex colour
						vertices[vtxIdx].r = color.r;
						vertices[vtxIdx].g = color.g;
						vertices[vtxIdx].b = color.b;
						vertices[vtxIdx].a = color.a;
						// save vertex texture coordinates
						vertices[vtxIdx].u.resize(uvsets.length());
						vertices[vtxIdx].v.resize(uvsets.length());
						// save vbas
						vertices[vtxIdx].vba.resize(weights[vtxIdx].length());
						for (int j=0; j<weights[vtxIdx].length(); j++)
						{
							vertices[vtxIdx].vba[j] = (weights[vtxIdx])[j];
						}
						// save joint ids
						vertices[vtxIdx].jointIds.resize(jointIds[vtxIdx].length());
						for (int j=0; j<jointIds[vtxIdx].length(); j++)
						{
							vertices[vtxIdx].jointIds[j] = (jointIds[vtxIdx])[j];
						}
						// save uv sets data
						for (int j=0; j<uvsets.length(); j++)
						{
							float2 uv;
							stat = faceIter.getUV(triVertexIdx[i],uv,&uvsets[j]);
							if (MS::kSuccess != stat)
							{
								uv[0] = 0;
								uv[1] = 0;
							}
							vertices[vtxIdx].u[j] = uv[0];
							vertices[vtxIdx].v[j] = (-1)*(uv[1]-1);
						}
						// save vertex index in face info
						newFace.v[i] = vtxIdx;
						// update value of index to next vertex info (-1 means nothing next)
						vertices[vtxIdx].next = -1;
					}
					else	// already found at least 1 vertex in this position
					{
						// check if a vertex with same attributes has been saved already
						for (int k=vtxIdx; k!=-1 && different; k=vertices[k].next)
						{
							different = false;

							MFloatVector n1 = normals[vertices[k].normalIdx];
							MFloatVector n2 = normals[nrmIdx];
							if (n1.x!=n2.x || n1.y!=n2.y || n1.z!=n2.z)
							{
								different = true;
							}


							if (vertices[k].r!=color.r || vertices[k].g!=color.g || vertices[k].b!= color.b || vertices[k].a!=color.a)
							{
								different = true;
							}

							for (int j=0; j<uvsets.length(); j++)
							{
								float2 uv;
								stat = faceIter.getUV(triVertexIdx[i],uv,&uvsets[j]);
								if (MS::kSuccess != stat)
								{
									uv[0] = 0;
									uv[1] = 0;
								}
								uv[1] = (-1)*(uv[1]-1);
								if (vertices[k].u[j]!=uv[0] || vertices[k].v[j]!=uv[1])
								{
									different = true;
								}
							}

							idx = k;
						}
						// if no identical vertex has been saved, then save the vertex info
						if (different)
						{
							vertexInfo vtx;
							// save vertex position
							vtx.pointIdx = vtxIdx;
							// save vertex normal
							vtx.normalIdx = nrmIdx;
							// save vertex colour
							vtx.r = color.r;
							vtx.g = color.g;
							vtx.b = color.b;
							vtx.a = color.a;
							// save vertex vba
							vtx.vba.resize(weights[vtxIdx].length());
							for (int j=0; j<weights[vtxIdx].length(); j++)
							{
								vtx.vba[j] = (weights[vtxIdx])[j];
							}
							// save joint ids
							vtx.jointIds.resize(jointIds[vtxIdx].length());
							for (int j=0; j<jointIds[vtxIdx].length(); j++)
							{
								vtx.jointIds[j] = (jointIds[vtxIdx])[j];
							}
							// save vertex texture coordinates
							vtx.u.resize(uvsets.length());
							vtx.v.resize(uvsets.length());
							for (int j=0; j<uvsets.length(); j++)
							{
								float2 uv;
								stat = faceIter.getUV(triVertexIdx[i],uv,&uvsets[j]);
								if (MS::kSuccess != stat)
								{
									uv[0] = 0;
									uv[1] = 0;
								}
								vtx.u[j] = uv[0];
								vtx.v[j] = (-1)*(uv[1]-1);
							}
							vtx.next = -1;
							vertices.push_back(vtx);
							// save vertex index in face info
							newFace.v[i] = vertices.size()-1;
							vertices[idx].next = vertices.size()-1;
						}
						else
						{
							newFace.v[i] = idx;
						}
					}
				} // end iteration of triangle vertices
				// add face info to the array corresponding to the submesh it belongs
				// skip faces with no shaders assigned
				if (shaderPolygonMapping[faceIter.index()] >= 0)
					polygonSets[shaderPolygonMapping[faceIter.index()]].push_back(newFace);
			} // end iteration of triangles
		}
	}
	std::cout << "done reading mesh triangles\n";

	// create a submesh for every different shader linked to the mesh
	unsigned shaderLength = shaders.length();
	for (int i=0; i<shaderLength; i++)
	{
		// check if the submesh has at least 1 triangle
		if (polygonSets[i].size() > 0)
		{
			//create new submesh
			SubMesh* pSubmesh = new SubMesh();
const char *nm = mesh.name().asChar();
const char *nm1 = mesh.partialPathName().asChar();
const char *nm2 = mesh.parentNamespace().asChar();
const char *nm3 = mesh.fullPathName().asChar();
const char *nm4 = meshDag.fullPathName().asChar();

			pSubmesh->m_name = meshDag.partialPathName();
			if(pDagPath)
				pSubmesh->m_name = pDagPath->partialPathName();
			const char *szName = pSubmesh->m_name.asChar();

			if(shaderLength > 1)
			{
				char a[256];
				sprintf(a,"%d",i);
				pSubmesh->m_name += a;
			}
			OutputDebugString(pSubmesh->m_name.asChar());
			OutputDebugString("\n");

			//OutputDebugString(szName);
			//OutputDebugString("\n");

			//load linked shader
			stat = pSubmesh->loadMaterial(shaders[i],uvsets);
			if (stat != MS::kSuccess)
			{
				MFnDependencyNode shadingGroup(shaders[i]);
				std::cout << "Error loading submesh linked to shader " << shadingGroup.name().asChar() << "\n";
				return MS::kFailure;
			}

			//load vertex and face data
			stat = pSubmesh->load(polygonSets[i],vertices,points,normals,opposite);

			//add submesh to current mesh
			m_submeshes.push_back(pSubmesh);
		}
	}

	return MS::kSuccess;
}
MStatus	Molecule3Cmd::redoIt()
{
	MStatus stat;
	MDagPath dagPath;
	MFnMesh meshFn;
		
	// Create a ball
	int nBallPolys;
	MPointArray ballVerts;
	MIntArray ballPolyCounts;
	MIntArray ballPolyConnects;
	MFloatArray ballUCoords;
	MFloatArray ballVCoords;
	MIntArray ballFvUVIDs;
	genBall( MPoint::origin, ballRodRatio * radius.value(), segs, nBallPolys, 
			 ballVerts, ballPolyCounts, ballPolyConnects,
			 true, ballUCoords, ballVCoords, ballFvUVIDs );
		
	unsigned int i, j, vertOffset;
	MPointArray meshVerts;
	MPoint p0, p1;
	MObject objTransform;
	
	// Setup for rods
	int nRodPolys;
	MPointArray rodVerts;
	MIntArray rodPolyCounts;
	MIntArray rodPolyConnects;
	MFloatArray rodUCoords;
	MFloatArray rodVCoords;
	MIntArray rodFvUVIDs;
	
	// Setup for newMesh
	int nNewPolys;
	MPointArray newVerts;
	MIntArray newPolyCounts;
	MIntArray newPolyConnects;
	MFloatArray newUCoords;
	MFloatArray newVCoords;
	MIntArray newFvUVIDs;
	
	int uvOffset; 
	MDagModifier dagMod;
	MFnDagNode dagFn;
	
	objTransforms.clear();
	
	// Iterate over the meshes
	unsigned int mi;
	for( mi=0; mi < selMeshes.length(); mi++ )
	{								
		dagPath = selMeshes[mi];
		meshFn.setObject( dagPath );
		
		uvOffset = 0;
		nNewPolys = 0;
		newVerts.clear();
		newPolyCounts.clear();
		newPolyConnects.clear();
		newUCoords.clear();
		newVCoords.clear();
		newFvUVIDs.clear();
		
		// Generate balls
		meshFn.getPoints( meshVerts, MSpace::kWorld );
		for( i=0; i < meshVerts.length(); i++ )
		{
			vertOffset = newVerts.length();
			
			// Add the ball to the new mesh
			nNewPolys += nBallPolys;
			
			// Move the ball vertices to the mesh vertex. Add it to the newMesh
			for( j=0; j < ballVerts.length(); j++ )
				newVerts.append( meshVerts[i] + ballVerts[j] );
				
			for( j=0; j < ballPolyCounts.length(); j++ )
				newPolyCounts.append( ballPolyCounts[j] );
				
			for( j=0; j < ballPolyConnects.length(); j++ )
				newPolyConnects.append( vertOffset + ballPolyConnects[j] );
		
			// Only add the uv coordinates once, since they are shared
			// by all balls
			if( i == 0 )
			{
				for( j=0; j < ballUCoords.length(); j++ )
				{
					newUCoords.append( ballUCoords[j] );
					newVCoords.append( ballVCoords[j] );
				}				
			}
			
			for( j=0; j < ballFvUVIDs.length(); j++ )
			{
				newFvUVIDs.append( uvOffset + ballFvUVIDs[j] );
			}
		}
		
		uvOffset = newUCoords.length();
		
		// Generate rods
		int nRods = 0;
		MItMeshEdge edgeIter( dagPath );
		for( ; !edgeIter.isDone(); edgeIter.next(), nRods++  )
		{	
			p0 = edgeIter.point( 0, MSpace::kWorld );		
			p1 = edgeIter.point( 1, MSpace::kWorld );
			
			// N.B. Generate the uv coordinates only once since they
			// are referenced by all rods
			genRod( p0, p1, 
					radius.value(), segs, nRodPolys, 
					rodVerts, rodPolyCounts, rodPolyConnects,
					nRods == 0,	rodUCoords, rodVCoords,
					rodFvUVIDs ); 

			vertOffset = newVerts.length();
			
			// Add the rod to the mesh
			nNewPolys += nRodPolys;
			
			for( i=0; i < rodVerts.length(); i++ )
				newVerts.append( rodVerts[i] );
				
			for( i=0; i < rodPolyCounts.length(); i++ )
				newPolyCounts.append( rodPolyCounts[i] );
				
			for( i=0; i < rodPolyConnects.length(); i++ )
				newPolyConnects.append( vertOffset + rodPolyConnects[i] );

			// First rod
			if( nRods == 0 )
			{
				// Add rod's uv coordinates to the list
				for( i=0; i < rodUCoords.length(); i++ )
				{
					newUCoords.append( rodUCoords[i] );
					newVCoords.append( rodVCoords[i] );
				}
			}
			
			// Set the face-vertex-uvIDs
			for( i=0; i < rodFvUVIDs.length(); i++ )
			{
				newFvUVIDs.append( uvOffset + rodFvUVIDs[i] );
			}
		}
		
		objTransform = meshFn.create( newVerts.length(), nNewPolys, newVerts, 
									  newPolyCounts, newPolyConnects,
									  newUCoords, newVCoords, 
									  MObject::kNullObj, &stat ); 
		if( !stat )
		{
			MGlobal::displayError( MString( "Unable to create mesh: " ) + stat.errorString() );
			return stat;
		}	
		
		objTransforms.append( objTransform );
				
		meshFn.assignUVs( newPolyCounts, newFvUVIDs );
				
		meshFn.updateSurface();
		
		// Rename transform node
		dagFn.setObject( objTransform );
		dagFn.setName( "molecule" );
				
		// Put mesh into the initial shading group
		dagMod.commandToExecute( MString( "sets -e -fe initialShadingGroup " ) + meshFn.name() );
	}

	// Select all the newly created molecule meshes
	MString cmd( "select -r" );
	for( i=0; i < objTransforms.length(); i++ )
	{
		dagFn.setObject( objTransforms[i] );
		cmd += " " + dagFn.name();	
	}

	dagMod.commandToExecute( cmd );
	
	return dagMod.doIt();
}
Exemple #24
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;
}
    // -------------------------------------------
    // set the sampling function from the UI/command line.
    // Returns validity of the function
    bool AnimationHelper::setSamplingFunction ( const MFloatArray& function )
    {
        std::vector<SamplingInterval> parsedFunction;

        // Order and parse the given floats as a function
        uint elementCount = function.length();
        if ( elementCount > 1 && elementCount % 3 != 0 ) return false;

        if ( elementCount == 0 )
        {
            generateSamplingFunction();
            return true;
        }
        else if ( elementCount == 1 )
        {
            SamplingInterval interval;
            interval.start = ( float ) animationStartTime().as ( MTime::kSeconds );
            interval.end = ( float ) animationEndTime().as ( MTime::kSeconds );
            interval.period = function[0];
            parsedFunction.push_back ( interval );
        }
        else
        {
            uint intervalCount = elementCount / 3;
            parsedFunction.resize ( intervalCount );
            for ( uint i = 0; i < intervalCount; ++i )
            {
                SamplingInterval& interval = parsedFunction[i];
                interval.start = function[i * 3];
                interval.end = function[i * 3 + 1];
                interval.period = function[i * 3 + 2];
            }
        }

        // Check for a valid sampling function
        uint parsedFunctionSize = ( uint ) parsedFunction.size();
        for ( uint i = 0; i < parsedFunctionSize; ++i )
        {
            SamplingInterval& interval = parsedFunction[i];
            if ( interval.end <= interval.start ) return false;
            if ( interval.period > interval.end - interval.start ) return false;
            if ( i > 0 && parsedFunction[i - 1].end > interval.start ) return false;
            if ( interval.period <= 0.0f ) return false;
        }

        // Gather the sampling times
        mSamplingTimes.clear();

        float previousTime = ( float ) animationStartTime().as ( MTime::kSeconds );
        float previousPeriodTakenRatio = 1.0f;

        for ( std::vector<SamplingInterval>::iterator it = parsedFunction.begin(); it != parsedFunction.end(); ++it )
        {
            SamplingInterval& interval = ( *it );
            float time = interval.start;
            if ( time == previousTime )
            {
                // Continuity in the sampling, calculate overlap start time
                time = time + ( 1.0f - previousPeriodTakenRatio ) * interval.period;
            }

            for ( ; time <= interval.end - interval.period + FLT_TOLERANCE; time += interval.period )
            {
                mSamplingTimes.push_back ( time );
            }

            mSamplingTimes.push_back ( time );

            previousTime = interval.end;
            previousPeriodTakenRatio = ( interval.end - time ) / interval.period;
        }

        return true;
    }
Exemple #26
0
MStatus meshOpFty::doLightningSplit(MFnMesh& meshFn)
//
//	Description:
//		Performs the kSplitLightning operation on the selected mesh
//      and components. It may not split all the selected components.
//
{
	unsigned int i, j;

	// These are the input arrays to the split function. The following
	// algorithm fills them in with the arguments for a continuous
	// split that goes through some of the selected faces.
	//
	MIntArray placements;
	MIntArray edgeIDs;
	MFloatArray edgeFactors;
	MFloatPointArray internalPoints;
	
	// The following array is going to be used to determine which faces
	// have been split. Since the split function can only split faces
	// which are adjacent to the earlier face, we may not split
	// all the faces
	//
	bool* faceTouched = new bool[fComponentIDs.length()];
	for (i = 0; i < fComponentIDs.length(); ++i)
		faceTouched[i] = false;
	
	// We need a starting point. For this example, the first face in
	// the component list is picked. Also get a polygon iterator
	// to this face.
	// 
	MItMeshPolygon itPoly(fMesh);
	for (; !itPoly.isDone(); itPoly.next())
	{
		if (fComponentIDs[0] == itPoly.index()) break;
	}
	if (itPoly.isDone())
	{
		// Should never happen.
		//
		delete [] faceTouched;
		return MS::kFailure;
	}
	
	// In this example, edge0 is called the starting edge and
	// edge1 is called the destination edge. This algorithm will split
	// each face from the starting edge to the destination edge
	// while going through two inner points inside each face.
	//
	int edge0, edge1;
	MPoint innerVert0, innerVert1;
	int nextFaceIndex = 0;
	
	// We need a starting edge. For this example, the first edge in the
	// edge list is used.
	//
	MIntArray edgeList;
	itPoly.getEdges(edgeList);
	edge0 = edgeList[0];
	
	bool done = false;
	while (!done)
	{
		// Set this face as touched so that we don't try to split it twice
		//
		faceTouched[nextFaceIndex] = true;
		
		// Get the current face's center. It is used later in the
		// algorithm to calculate inner vertices.
		//
		MPoint faceCenter = itPoly.center();
			
		// Iterate through the connected faces to find an untouched,
		// selected face and get the ID of the shared edge. That face
		// will become the next face to be split.
		//
		MIntArray faceList;
		itPoly.getConnectedFaces(faceList);
		nextFaceIndex = -1;
		for (i = 0; i < fComponentIDs.length(); ++i)
		{
			for (j = 0; j < faceList.length(); ++j)
			{
				if (fComponentIDs[i] == faceList[j] && !faceTouched[i])
				{
					nextFaceIndex = i;
					break;
				}
			}
			if (nextFaceIndex != -1) break;
		}
		
		if (nextFaceIndex == -1)
		{
			// There is no selected and untouched face adjacent to this
			// face, so this algorithm is done. Pick the first edge that
			// is not the starting edge as the destination edge.
			//
			done = true;
			edge1 = -1;
			for (i = 0; i < edgeList.length(); ++i)
			{
				if (edgeList[i] != edge0)
				{
					edge1 = edgeList[i];
					break;
				}
			}
			if (edge1 == -1)
			{
				// This should not happen, since there should be more than
				// one edge for each face
				//
				delete [] faceTouched;
				return MS::kFailure;
			}
		}
		else
		{
			// The next step is to find out which edge is shared between
			// the two faces and use it as the destination edge. To do
			// that, we need to iterate through the faces and get the
			// next face's list of edges.
			//
			itPoly.reset();
			for (; !itPoly.isDone(); itPoly.next())
			{
				if (fComponentIDs[nextFaceIndex] == itPoly.index()) break;
			}
			if (itPoly.isDone()) 
			{
				// Should never happen.
				//
				delete [] faceTouched;
				return MS::kFailure;
			}
			
			// Look for a common edge ID in the two faces edge lists
			//
			MIntArray nextFaceEdgeList;
			itPoly.getEdges(nextFaceEdgeList);
			edge1 = -1;
			for (i = 0; i < edgeList.length(); ++i)
			{
				for (j = 0; j < nextFaceEdgeList.length(); ++j)
				{
					if (edgeList[i] == nextFaceEdgeList[j])
					{
						edge1 = edgeList[i];
						break;
					}
				}
				if (edge1 != -1) break;
			}
			if (edge1 == -1)
			{
				// Should never happen.
				//
				delete [] faceTouched;
				return MS::kFailure;
			}
			
			// Save the edge list for the next iteration
			//
			edgeList = nextFaceEdgeList;
		}
		
		// Calculate the two inner points that the split will go through.
		// For this example, the midpoints between the center and the two
		// farthest vertices of the edges are used.
		//
		// Find the 3D positions of the edges' vertices
		//
		MPoint edge0vert0, edge0vert1, edge1vert0, edge1vert1;
		MItMeshEdge itEdge(fMesh, MObject::kNullObj );
		for (; !itEdge.isDone(); itEdge.next())
		{
			if (itEdge.index() == edge0)
			{
				edge0vert0 = itEdge.point(0);
				edge0vert1 = itEdge.point(1);
			}
			if (itEdge.index() == edge1)
			{
				edge1vert0 = itEdge.point(0);
				edge1vert1 = itEdge.point(1);
			}
		}
		
		// Figure out which are the farthest from each other
		//
		double distMax = edge0vert0.distanceTo(edge1vert0);
		MPoint max0, max1;
		max0 = edge0vert0;
		max1 = edge1vert0;
		double newDist = edge0vert1.distanceTo(edge1vert0);
		if (newDist > distMax)
		{
			max0 = edge0vert1;
			max1 = edge1vert0;
			distMax = newDist;
		}
		newDist = edge0vert0.distanceTo(edge1vert1);
		if (newDist > distMax)
		{
			max0 = edge0vert0;
			max1 = edge1vert1;
			distMax = newDist;
		}
		newDist = edge0vert1.distanceTo(edge1vert1);
		if (newDist > distMax)
		{
			max0 = edge0vert1;
			max1 = edge1vert1;
		}
		
		// Calculate the two inner points
		//
		innerVert0 = (faceCenter + max0) / 2.0;
		innerVert1 = (faceCenter + max1) / 2.0;
		
		// Add this split's information to the input arrays. If this is
		// the last split, also add the destination edge's split information.
		//
		placements.append((int) MFnMesh::kOnEdge);
		placements.append((int) MFnMesh::kInternalPoint);
		placements.append((int) MFnMesh::kInternalPoint);
		if (done) placements.append((int) MFnMesh::kOnEdge);
		
		edgeIDs.append(edge0);
		if (done) edgeIDs.append(edge1);
		
		edgeFactors.append(0.5f);
		if (done) edgeFactors.append(0.5f);
		
		MFloatPoint point1((float)innerVert0[0], (float)innerVert0[1],
			(float)innerVert0[2], (float)innerVert0[3]);
		MFloatPoint point2((float)innerVert1[0], (float)innerVert1[1],
			(float)innerVert1[2], (float)innerVert1[3]);
		internalPoints.append(point1);
		internalPoints.append(point2);
		
		// For the next iteration, the current destination
		// edge becomes the start edge.
		//
		edge0 = edge1;
	}

	// Release the dynamically-allocated memory and do the actual split
	//
	delete [] faceTouched;
	return meshFn.split(placements, edgeIDs, edgeFactors, internalPoints);
}
/* static */
bool
UsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh(
        const UsdGeomPrimvar& primvar,
        MFnMesh& meshFn)
{
    const TfToken& primvarName = primvar.GetPrimvarName();

    // Get the raw data before applying any indexing.
    VtVec2fArray uvValues;
    if (!primvar.Get(&uvValues) || uvValues.empty()) {
        TF_WARN("Could not read UV values from primvar '%s' on mesh: %s",
                primvarName.GetText(),
                primvar.GetAttr().GetPrimPath().GetText());
        return false;
    }

    // This is the number of UV values assuming the primvar is NOT indexed.
    VtIntArray assignmentIndices;
    if (primvar.GetIndices(&assignmentIndices)) {
        // The primvar IS indexed, so the indices array is what determines the
        // number of UV values.
        int unauthoredValuesIndex = primvar.GetUnauthoredValuesIndex();

        // Replace any index equal to unauthoredValuesIndex with -1.
        if (unauthoredValuesIndex != -1) {
            for (int& index : assignmentIndices) {
                if (index == unauthoredValuesIndex) {
                    index = -1;
                }
            }
        }

        // Furthermore, if unauthoredValuesIndex is valid for uvValues, then
        // remove it from uvValues and shift the indices (we don't want to
        // import the unauthored value into Maya, where it has no meaning).
        if (unauthoredValuesIndex >= 0 &&
                static_cast<size_t>(unauthoredValuesIndex) < uvValues.size()) {
            // This moves [unauthoredValuesIndex + 1, end) to
            // [unauthoredValuesIndex, end - 1), erasing the
            // unauthoredValuesIndex.
            std::move(
                    uvValues.begin() + unauthoredValuesIndex + 1,
                    uvValues.end(),
                    uvValues.begin() + unauthoredValuesIndex);
            uvValues.pop_back();

            for (int& index : assignmentIndices) {
                if (index > unauthoredValuesIndex) {
                    index = index - 1;
                }
            }
        }
    }

    // Go through the UV data and add the U and V values to separate
    // MFloatArrays.
    MFloatArray uCoords;
    MFloatArray vCoords;
    for (const GfVec2f& v : uvValues) {
        uCoords.append(v[0]);
        vCoords.append(v[1]);
    }

    MStatus status;
    MString uvSetName(primvarName.GetText());
    if (primvarName == UsdUtilsGetPrimaryUVSetName()) {
        // We assume that the primary USD UV set maps to Maya's default 'map1'
        // set which always exists, so we shouldn't try to create it.
        uvSetName = "map1";
    } else {
        status = meshFn.createUVSet(uvSetName);
        if (status != MS::kSuccess) {
            TF_WARN("Unable to create UV set '%s' for mesh: %s",
                    uvSetName.asChar(),
                    meshFn.fullPathName().asChar());
            return false;
        }
    }

    // The following two lines should have no effect on user-visible state but
    // prevent a Maya crash in MFnMesh.setUVs after creating a crease set.
    // XXX this workaround is needed pending a fix by Autodesk.
    MString currentSet = meshFn.currentUVSetName();
    meshFn.setCurrentUVSetName(currentSet);

    // Create UVs on the mesh from the values we collected out of the primvar.
    // We'll assign mesh components to these values below.
    status = meshFn.setUVs(uCoords, vCoords, &uvSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Unable to set UV data on UV set '%s' for mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    const TfToken& interpolation = primvar.GetInterpolation();

    // Build an array of value assignments for each face vertex in the mesh.
    // Any assignments left as -1 will not be assigned a value.
    MIntArray uvIds = _GetMayaFaceVertexAssignmentIds(meshFn,
                                                      interpolation,
                                                      assignmentIndices,
                                                      -1);

    MIntArray vertexCounts;
    MIntArray vertexList;
    status = meshFn.getVertices(vertexCounts, vertexList);
    if (status != MS::kSuccess) {
        TF_WARN("Could not get vertex counts for UV set '%s' on mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    status = meshFn.assignUVs(vertexCounts, uvIds, &uvSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Could not assign UV values to UV set '%s' on mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    return true;
}
// h�mta all n�dv�ndig data och l�gger det i ett MeshData-objekt, som senare anv�nds vid exportering.
bool Exporter::ExtractMeshData(MFnMesh &mesh, UINT index)
{
	MeshData mesh_data;

	MFloatPointArray points;

	MFloatVectorArray normals;

	MSpace::Space world_space = MSpace::kTransform;

	// DAG-path
	mesh_data.mesh_path = mesh.dagPath();

	// namn och id
	mesh_data.name = mesh.name();
	mesh_data.id = index;

	std::string name = mesh.partialPathName().asChar();
	if (!strcmp(name.substr(0, 5).c_str(), "Blend")){
		return true;
	}

	// triangulera meshen innan man h�mtar punkterna
	MString command = "polyTriangulate -ch 1 " + mesh_data.name;
	if (!MGlobal::executeCommand(command))
	{
		return false;
	}

	// h�mta icke-indexerade vertexpunkter
	if (!mesh.getPoints(points, world_space))
	{
		return false;
	}

	for (int i = 0; i < points.length(); i++){
		point temppoints = { points[i].x, points[i].y, points[i].z };
		vec3 temppurepoints = { points[i].x, points[i].y, points[i].z };
		mesh_data.points.push_back(temppoints);
		mesh_data.purepoints.push_back(temppurepoints);
	}

	// h�mta icke-indexerade normaler
	if (!mesh.getNormals(normals, world_space))
	{
		return false;
	}

	for (int i = 0; i < normals.length(); i++){
		vec3 tempnormals = { normals[i].x, normals[i].y, normals[i].z };
		mesh_data.normals.push_back(tempnormals);
	}

	//variabler f�r att mellanlagra uvdata och tangenter/bitangenter
	MStringArray uvSets;
	mesh.getUVSetNames(uvSets);

	uvSet tempUVSet;
	MFloatArray Us;
	MFloatArray Vs;
	vec2 UVs;

	// iterera �ver uvsets och ta ut koordinater, tangenter och bitangenter
	for (int i = 0; i < uvSets.length(); i++)
	{
		MString currentSet = uvSets[i];
		mesh.getUVs(Us, Vs, &currentSet);
		for (int a = 0; a < Us.length(); a++){
			UVs.u = Us[a];
			UVs.v = Vs[a];
			//1-Vs in order to get correct UV angles
			tempUVSet.UVs.push_back(UVs);
		}
		mesh.getTangents(tempUVSet.tangents, world_space, &currentSet);
		mesh.getBinormals(tempUVSet.binormals, world_space, &currentSet);
		mesh_data.uvSets.push_back(tempUVSet);
	}

	//itererar �ver trianglar och returnerar ID:n f�r associerade vertiser, normaler och uvset
	MItMeshPolygon itFaces(mesh.dagPath());
	while (!itFaces.isDone()) {
		face tempface;

		//		printf("%d", itFaces.vertexIndex(0));
		//		printf(" %d", itFaces.vertexIndex(1));
		//		printf(" %d\n", itFaces.vertexIndex(2));

		int vc = itFaces.polygonVertexCount();
		for (int i = 0; i < vc; ++i) {
			tempface.verts[i].pointID = itFaces.vertexIndex(i);
			tempface.verts[i].normalID = itFaces.normalIndex(i);

			for (int k = 0; k < uvSets.length(); ++k) {
				int temptexCoordsID;
				itFaces.getUVIndex(i, temptexCoordsID, &uvSets[k]);

				tempface.verts[i].texCoordsID.push_back(temptexCoordsID);
			}
		}

		mesh_data.faces.push_back(tempface);
		itFaces.next();
	}

	// l�gg till mesh_data i scen-datan
	scene_.meshes.push_back(mesh_data);

	return true;
}
Exemple #29
0
//
// Change the UVS for the given selection on this mesh object.
//
///////////////////////////////////////////////////////////////////////////////
MStatus flipUVCmd::getTweakedUVs(
    const MObject & meshObj,					// Object
    MIntArray & uvList,						// UVs to move
    MFloatArray & uPos,						// Moved UVs
    MFloatArray & vPos )					// Moved UVs
{
    MStatus status;
    unsigned int i;
    MFloatArray uArray;
    MFloatArray vArray;

    MFnMesh mesh( meshObj );

    // Read all UVs from the poly object
    status = mesh.getUVs(uArray, vArray);
    CHECK_MSTATUS_AND_RETURN_IT(status);

    unsigned int nbUvShells = 1;
    MIntArray uvShellIds;
    if ((!flipGlobal) || extendToShell)
    {
        // First, extract the UV shells.
        status = mesh.getUvShellsIds(uvShellIds, nbUvShells);
        CHECK_MSTATUS_AND_RETURN_IT(status);
    }

    if (extendToShell)
    {
        // Find all shells that have at least a selected UV.
        bool *selected = new bool[nbUvShells];
        for (i = 0 ; i<nbUvShells ; i++)
            selected[i] = false;

        for (i = 0 ; i<uvList.length() ; i++)
        {
            int indx = uvList[i];
            selected[uvShellIds[indx]] = true;
        }

        // Now recompute a new list of UVs to modify.

        unsigned int numUvs = mesh.numUVs();
        unsigned int numSelUvs = 0;

        // Preallocate a buffer, large enough to hold all Ids. This
        // prevents multiple reallocation from happening when growing
        // the array.
        uvList.setLength(numUvs);

        for (i = 0 ; i<numUvs ; i++)
        {
            if (selected[uvShellIds[i]])
                uvList[numSelUvs++] = i;
        }

        // clamp the array to the proper size.
        uvList.setLength(numSelUvs);

        delete [] selected;
    }

    // For global flips, just pretend there is only one shell
    if (flipGlobal) nbUvShells = 1;

    float *minMax = new float[nbUvShells*4];

    for (i = 0 ; i<nbUvShells ; i++)
    {
        minMax[4*i+0] =  1e30F;				// Min U
        minMax[4*i+1] =  1e30F;				// Min V
        minMax[4*i+2] = -1e30F;				// Max U
        minMax[4*i+3] = -1e30F;				// Max V
    }

    // Get the bounding box of the UVs, for each shell if flipGlobal
    // is true, or for the whole selection if false.
    for (i = 0 ; i<uvList.length() ; i++)
    {
        int indx = uvList[i];
        int shellId = 0;
        if (!flipGlobal) shellId = uvShellIds[indx];

        if (uArray[indx] < minMax[4*shellId+0])
            minMax[4*shellId+0] = uArray[indx];
        if (vArray[indx] < minMax[4*shellId+1])
            minMax[4*shellId+1] = vArray[indx];
        if (uArray[indx] > minMax[4*shellId+2])
            minMax[4*shellId+2] = uArray[indx];
        if (vArray[indx] > minMax[4*shellId+3])
            minMax[4*shellId+3] = vArray[indx];
    }

    // Adjust the size of the output arrays
    uPos.setLength(uvList.length());
    vPos.setLength(uvList.length());

    for (i = 0 ; i<uvList.length() ; i++)
    {
        int shellId = 0;
        int indx = uvList[i];
        if (!flipGlobal) shellId = uvShellIds[indx];

        // Flip U or V along the bounding box center.
        if (horizontal)
        {
            uPos[i] = minMax[4*shellId+0] + minMax[4*shellId+2] -
                      uArray[indx];
            vPos[i] = vArray[indx];
        }
        else
        {
            uPos[i] = uArray[indx];
            vPos[i] = minMax[4*shellId+1] + minMax[4*shellId+3] -
                      vArray[indx];
        }
    }

    delete [] minMax;

    return MS::kSuccess;
}
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;
}