// 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;
}
Exemplo n.º 2
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 );
	}
}
Exemplo n.º 3
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 7
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);
		}
	}

}
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();
}
Exemplo n.º 9
0
MStatus	grabUVContext::doDrag ( MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context)
{
	if (event.mouseButton() != MEvent::kLeftMouse || 
		!event.isModifierNone() )
		return MS::kFailure;

	MPxTexContext::doDrag(event, drawMgr, context);

	short x, y;
	event.getPosition( x, y );
	fLastScreenPoint = fCurrentScreenPoint;
	fCurrentScreenPoint = MPoint( x, y );

	double xView, yView;
	portToView(x, y, xView, yView);	// pos at viewrect coordinate

	fLastPoint = fCurrentPoint;
	fCurrentPoint = MPoint( xView, yView, 0.0 );

	if( fDragMode == kBrushSize )
	{
		double dis = fCurrentScreenPoint.distanceTo( fLastScreenPoint );
		if ( fCurrentScreenPoint[0] > fLastScreenPoint[0] )
			setSize( size() + float(dis) );
		else
			setSize( std::max( size() - float(dis), 0.01f ) );
	}
	else
	{
		fBrushCenterScreenPoint = MPoint( x, y );

		MFloatArray uUVsExported;
		MFloatArray vUVsExported;

		const MVector vec = fCurrentPoint - fLastPoint;

		if (!fCommand)
		{
			fCommand = (UVUpdateCommand *)(newToolCommand());
		}
		if (fCommand)
		{
			MFnMesh mesh(fDagPath);
			MString currentUVSetName;
			mesh.getCurrentUVSetName(currentUVSetName);

			int nbUVs = mesh.numUVs(currentUVSetName);
			MDoubleArray pinData;
			MUintArray uvPinIds;
			MDoubleArray fullPinData;
			mesh.getPinUVs(uvPinIds, pinData, &currentUVSetName);
			int len = pinData.length();

			fullPinData.setLength(nbUVs);
			for (unsigned int i = 0; i < nbUVs; i++) {
				fullPinData[i] = 0.0;
			}
			while( len-- > 0 ) {
				fullPinData[uvPinIds[len]] = pinData[len];
			}

			MFloatArray uValues;
			MFloatArray vValues;
			float pinWeight = 0;
			for (unsigned int i = 0; i < fCollectedUVs.length(); ++i)
			{
				float u, v;
				MStatus bGetUV = mesh.getUV(fCollectedUVs[i], u, v, &currentUVSetName);
				if (bGetUV == MS::kSuccess)
				{
					pinWeight = fullPinData[fCollectedUVs[i]];
					u += (float)vec[0]*(1-pinWeight);
					v += (float)vec[1]*(1-pinWeight);
					uValues.append( u );
					vValues.append( v ); 
				}
			}
			fCommand->setUVs( mesh.object(), fCollectedUVs, uValues, vValues, &currentUVSetName );
		}
	}
	return MS::kSuccess;
}