Beispiel #1
0
MObject MG_poseReader::makePlane(const MVector& p1,const MVector& p2,const MVector& p3){

	MFnMesh meshFn;

	MPoint p1p (p1);
	MPoint p2p (p2);
	MPoint p3p (p3);
	MPointArray pArray;
	pArray.append(p1p);
	pArray.append(p2p);
	pArray.append(p3p);

	MIntArray polyCount;
	polyCount.append(3);
	MIntArray polyConnect;
	polyConnect.append(0);
	polyConnect.append(1);
	polyConnect.append(2);
	

	MFnMeshData data;
	MObject polyData = data.create();

	MStatus stat;
	meshFn.create(3,1,pArray,polyCount,polyConnect,polyData,&stat);
		


	
	return polyData;

}
Beispiel #2
0
/**
 * @brief Compute the parallelogram from one edge and one point (mouse position).
 *
 * [AB]: Input clicked edge
 * P: mouse position on press
 * M: moving mouse
 * [DC]: the computed edge keeping AB length and AP==DM
 *
 *     A ____________ D
 *      /           /
 *   P +           + M
 *    /           /
 * B /___________/ C
 *
 * This computation is in 2D Camera Space.
 *
 * @param[in] view Viewort
 * @param[in] onPressEdgeData clicked edge information
 * @param[in] onPressCSMousePos clicked mouse position in Camera Space coordinates
 * @param[out] intermediateCSEdgePoints the 2 new points (D and C) of the parallelogram
 */
void MVGManipulator::getIntermediateCSEdgePoints(
    M3dView& view, const MVGManipulatorCache::EdgeData* onPressEdgeData,
    const MPoint& onPressCSMousePos, MPointArray& intermediateCSEdgePoints)
{
    assert(onPressEdgeData != NULL);
    // vertex 1
    MVector mouseToVertexCSOffset =
        MVGGeometryUtil::worldToCameraSpace(view, onPressEdgeData->vertex1->worldPosition) -
        onPressCSMousePos;
    intermediateCSEdgePoints.append(getMousePosition(view) + mouseToVertexCSOffset);
    // vertex 2
    mouseToVertexCSOffset =
        MVGGeometryUtil::worldToCameraSpace(view, onPressEdgeData->vertex2->worldPosition) -
        onPressCSMousePos;
    intermediateCSEdgePoints.append(getMousePosition(view) + mouseToVertexCSOffset);
}
void VoronoiShatter::getPolyFace(int faceId, MPointArray &a)
{/*
	int startFaceId;
	int endFaceId;
	startFaceId = (int)VDpolyIndex.at(polyId);
	endFaceId = (int)VDpolyIndex.at(polyId+1);
	

	for(int i=startFaceId; i<endFaceId; i++)
{*/
		int startEdgeId, endEdgeId;
		startEdgeId = VDfaceIndex.at(faceId);
		endEdgeId = VDfaceIndex.at( faceId+1 );

		for(int j=startEdgeId; j<endEdgeId; j++)
		{
			int startVertexId, endVertexId;
			startVertexId = VDedge.at(j).startVertexId;
			//endVertexId = VDedge.at(j).endVertexId;
			a.append(VDvertex.at(startVertexId).point);
			//a.append(VDvertex.at(endVertexId).point);
		}

	//
		//a.remove(a.length()-1);
	return;
}
Beispiel #4
0
bool HesperisCurveCreator::CreateACurve(Vector3F * pos, unsigned nv, MObject &target)
{
	MPointArray vertexArray;
    unsigned i=0;
	for(; i<nv; i++)
		vertexArray.append( MPoint( pos[i].x, pos[i].y, pos[i].z ) );
	const int degree = 2;
    const int spans = nv - degree;
	const int nknots = spans + 2 * degree - 1;
    MDoubleArray knotSequences;
	knotSequences.append(0.0);
	for(i = 0; i < nknots-2; i++)
		knotSequences.append( (double)i );
	knotSequences.append(nknots-3);
    
    MFnNurbsCurve curveFn;
	MStatus stat;
	curveFn.create(vertexArray,
					knotSequences, degree, 
					MFnNurbsCurve::kOpen, 
					false, false, 
					target, 
					&stat );
					
	return stat == MS::kSuccess;
}
Beispiel #5
0
MStatus makeSurf()
{
	cout << ">>>> Start creation of test surface <<<<" << endl;

	// Set up knots
	//
	MDoubleArray knotArray;
	int i;
    // Add extra starting knots so that the first CV matches the curve start point
	//
	knotArray.append( 0.0 );
	knotArray.append( 0.0 );
	for ( i = 0; i <= NUM_SPANS; i++ ) {
		knotArray.append( (double)i );
	}
	// Add extra ending knots so that the last CV matches the curve end point
	//
	knotArray.append( (double)i );
	knotArray.append( (double)i );
 
	// Now, Set up CVs
	//
	MPointArray cvArray;
	
	// We need a 2D array of CVs with NUM_SPANS + 3 CVs on a side
	//
	int last = NUM_SPANS + 3;
	for ( i = 0; i < last; i++ ) {
		for ( int j = 0; j < last; j++ ) {
			MPoint cv;
			cv.x = (((double)(j))/((double)(NUM_SPANS + 3)) * WIDTH) 
				- (WIDTH/2.0);
			cv.z = (((double)(i))/((double)(NUM_SPANS + 3)) * WIDTH) 
				- (WIDTH/2.0);
			double dist = sqrt( cv.x*cv.x + cv.z*cv.z );
			cv.y = cos( dist ) * VERTICAL_SCALING;
			cvArray.append( cv );
		}
	}

	// Create the surface
	// 
	MFnNurbsSurface mfnNurbsSurf;

	MStatus stat;
	mfnNurbsSurf.create( cvArray, knotArray, knotArray, 3, 3, 
						 MFnNurbsSurface::kOpen, MFnNurbsSurface::kOpen,
						 true, MObject::kNullObj, &stat );
 
	if ( stat ) {
		cout << ">>>> Test Surface Creation Successfull <<<<\n";
	} else {
		stat.perror("MFnNurbsSurface::create");
		cout << ">>>> Test Surface Creation Failed <<<<\n";
	}

	return stat;
}
Beispiel #6
0
// Draw visible items
void MVGManipulator::drawVisibleItems(M3dView& view) const
{
    MPointArray visiblesItemsPositions;
    for(std::vector<MVGPointCloudItem>::const_iterator itemIt = _visiblePointCloudItems.begin();
        itemIt != _visiblePointCloudItems.end(); ++itemIt)
        visiblesItemsPositions.append(MVGGeometryUtil::worldToViewSpace(view, itemIt->_position));
    MColor red(1.0, 0.0, 0.0);
    MVGDrawUtil::drawPoints2D(visiblesItemsPositions, red, 2.f);
}
Beispiel #7
0
MStatus helix::doIt( const MArgList& args )
{
	MStatus stat;

	const unsigned	deg 	= 3;			// Curve Degree
	const unsigned	ncvs 	= 20;			// Number of CVs
	const unsigned	spans 	= ncvs - deg;	// Number of spans
	const unsigned	nknots	= spans+2*deg-1;// Number of knots
	double	radius			= 4.0;			// Helix radius
	double	pitch 			= 0.5;			// Helix pitch
	unsigned	i;

	// Parse the arguments.
	for ( i = 0; i < args.length(); i++ )
		if ( MString( "-p" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			double tmp = args.asDouble( ++i, &stat );
			if ( MS::kSuccess == stat )
				pitch = tmp;
		}
		else if ( MString( "-r" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			double tmp = args.asDouble( ++i, &stat );
			if ( MS::kSuccess == stat )
				radius = tmp;
		}

	MPointArray	 controlVertices;
	MDoubleArray knotSequences;

	// Set up cvs and knots for the helix
	//
	for (i = 0; i < ncvs; i++)
		controlVertices.append( MPoint( radius * cos( (double)i ),
			pitch * (double)i, radius * sin( (double)i ) ) );

	for (i = 0; i < nknots; i++)
		knotSequences.append( (double)i );

	// Now create the curve
	//
	MFnNurbsCurve curveFn;

	curveFn.create( controlVertices,
					knotSequences, deg, 
					MFnNurbsCurve::kOpen, 
					false, false, 
					MObject::kNullObj, 
					&stat );

	if ( MS::kSuccess != stat )
		cout<<"Error creating curve."<<endl;

	return stat;
}
Beispiel #8
0
MStatus MG_curve::compute(const MPlug& plug,MDataBlock& dataBlock)
	{

		if (plug==output)
		{
			
			//MStatus
			MStatus stat;


			//Point array for the curve
			MPointArray pointArray ;

			//Get data from inputs
			MDataHandle degreeH = dataBlock.inputValue(degree);
			int degreeValue = degreeH.asInt();

			MDataHandle tmH = dataBlock.inputValue(transformMatrix);
			MMatrix tm = tmH.asMatrix();


			MArrayDataHandle inputMatrixH = dataBlock.inputArrayValue(inputMatrix);
			inputMatrixH.jumpToArrayElement(0);
			//Loop to get matrix data and convert in points

			for (int unsigned i=0;i<inputMatrixH.elementCount();i++,inputMatrixH.next())
			{
				

				MMatrix currentMatrix = inputMatrixH.inputValue(&stat).asMatrix() ;
				
				//Compensate the locator matrix
				
				MMatrix fixedMatrix = currentMatrix*tm.inverse();
				MPoint matrixP (fixedMatrix[3][0],fixedMatrix[3][1],fixedMatrix[3][2]);
				pointArray.append(matrixP);
				
			}
			
		MFnNurbsCurve curveFn;
		MFnNurbsCurveData curveDataFn;
		MObject curveData= curveDataFn.create();

		curveFn.createWithEditPoints(pointArray,degreeValue,MFnNurbsCurve::kOpen,0,0,0,curveData,&stat);
		
		MDataHandle outputH = dataBlock.outputValue(output);
		outputH.set(curveData);
		outputH.setClean();

		}


		return MS::kSuccess;
	}
Beispiel #9
0
void MVGManipulator::getIntersectedPoints(M3dView& view, MPointArray& positions,
                                          MVGManipulator::Space space) const
{
    MPointArray intersectedPositions;
    MVGManipulatorCache::MVGComponent intersectedComponent = _cache->getIntersectedComponent();
    switch(intersectedComponent.type)
    {
        case MFn::kBlindData:
        {
            MPoint pointCSPosition =
                intersectedComponent.vertex->blindData[_cache->getActiveCamera().getId()];
            intersectedPositions.append(MVGGeometryUtil::cameraToWorldSpace(view, pointCSPosition));
            break;
        }
        case MFn::kMeshVertComponent:
            intersectedPositions.append(intersectedComponent.vertex->worldPosition);
            break;
        case MFn::kMeshEdgeComponent:
            intersectedPositions.append(intersectedComponent.edge->vertex1->worldPosition);
            intersectedPositions.append(intersectedComponent.edge->vertex2->worldPosition);
            break;
        default:
            break;
    }
    if(intersectedPositions.length() <= 0)
        return;
    switch(space)
    {
        case kCamera:
            intersectedPositions = MVGGeometryUtil::worldToCameraSpace(view, intersectedPositions);
            break;
        case kView:
            intersectedPositions = MVGGeometryUtil::worldToViewSpace(view, intersectedPositions);
            break;
        case kWorld:
            break;
    }
    for(size_t i = 0; i < intersectedPositions.length(); ++i)
        positions.append(intersectedPositions[i]);
}
Beispiel #10
0
MStatus LSSolverNode::buildOutputMesh(MFnMesh& inputMesh, float* vertices, MObject &outputMesh)
{
	MStatus stat;
	MPointArray points;

	unsigned vIndex = 0;
	int numVertices = inputMesh.numVertices();
	for(int i=0; i<numVertices;i++)
	{
		double x = vertices[vIndex++];
		double y = vertices[vIndex++];
		double z = vertices[vIndex++];
		//std::cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
		MPoint point(x,y,z);
		points.append(point);
	}
	
	const int numFaces = inputMesh.numPolygons();
	int *face_counts = new int[numFaces];
	for(int i = 0 ; i < numFaces ; i++)
	{
		face_counts[i] = 3;
	}

	MIntArray faceCounts( face_counts, numFaces );

	// Set up and array to assign vertices from points to each face 
	int numFaceConnects = numFaces * 3;
	int *face_connects = new int[numFaceConnects];

	int faceConnectsIdx = 0;
	for ( int i=0; i<numFaces; i++ )
	{
		MIntArray polyVerts;
		inputMesh.getPolygonVertices( i, polyVerts );
		int pvc = polyVerts.length();

		face_connects[faceConnectsIdx++] = polyVerts[0];
		face_connects[faceConnectsIdx++]= polyVerts[1];
		face_connects[faceConnectsIdx++] = polyVerts[2];
	}

	MIntArray faceConnects( face_connects, numFaceConnects );
	
	MFnMesh meshFS;
	MObject newMesh = meshFS.create(numVertices, numFaces,
									points, faceCounts, faceConnects,
									outputMesh, &stat);

	return stat;

}
bool BasicLocator::getCirclePoints( MPointArray &pts ) const
{
MStatus stat;
MObject thisNode = thisMObject();
MFnDagNode dagFn( thisNode  );  

MPlug xWidthPlug = dagFn.findPlug( xWidth, &stat );
float xWidthValue;
xWidthPlug.getValue( xWidthValue );

MPlug zWidthPlug = dagFn.findPlug( zWidth, &stat );
float zWidthValue;
zWidthPlug.getValue( zWidthValue );

MPlug typePlug = dagFn.findPlug( dispType, &stat );
short typeValue;
typePlug.getValue( typeValue );

unsigned int nCirclePts;

switch( typeValue )
   {
   case 0:
       nCirclePts = 4;
       break;
   case 1:
       nCirclePts = 5;
       break;
   default:
       nCirclePts = 20;
       break;
   }

pts.clear();
pts.setSizeIncrement( nCirclePts );
   
MPoint pt;
pt.y = 0.0;
   
const double angleIncr = M_2PI / (nCirclePts - 1);
double angle = 0.0;
unsigned int i=0;
for( ; i < nCirclePts; i++, angle+=angleIncr )
	{
	pt.x = xWidthValue * cos( angle );
	pt.z = zWidthValue * sin( angle );
	pts.append( pt );
	}

return true;
}
Beispiel #12
0
MStatus create(double iFrame, const Alembic::AbcGeom::IPoints & iNode,
               MObject & iParent, MObject & iObject)
{
    MStatus status = MS::kSuccess;
    Alembic::AbcGeom::IPointsSchema schema = iNode.getSchema();

    // object has no samples, bail early
    if (schema.getNumSamples() == 0)
    {
        return status;
    }

    Alembic::AbcGeom::IPointsSchema::Sample samp;
    Alembic::AbcCoreAbstract::index_t index =
        schema.getTimeSampling()->getNearIndex(
            iFrame, schema.getNumSamples()).first;

    schema.get(samp, index);

    size_t pSize = samp.getPositions()->size();

    // bail early if there's no particle data at this frame
    if (pSize == 0)
    {
        return status;
    }

    // convert the data to Maya format
    MFnParticleSystem fnParticle;
    iObject = fnParticle.create(iParent, &status);
    fnParticle.setObject(iObject);
    fnParticle.setName(iNode.getName().c_str());

    MPointArray pArray;
    Alembic::Abc::P3fArraySamplePtr v3ptr = samp.getPositions();
    MVectorArray vArray;

    for (unsigned int pId = 0; pId < pSize; pId++)
    {
        pArray.append((*v3ptr)[pId].x,
                      (*v3ptr)[pId].y,
                      (*v3ptr)[pId].z);
    }

    status = fnParticle.emit(pArray);
    status = fnParticle.saveInitialState();

    return status;
}
Beispiel #13
0
void HelixButton::createHelix()
{
    MStatus st;
    const unsigned deg = 3;             // Curve Degree
    const unsigned ncvs = 20;            // Number of CVs
    const unsigned spans = ncvs - deg;    // Number of spans
    const unsigned nknots = spans + 2 * deg - 1; // Number of knots
    double         radius = 4.0;           // Helix radius
    double         pitch = 0.5;           // Helix pitch
    unsigned       i;
    MPointArray controlVertices;
    MDoubleArray knotSequences;
    // Set up cvs and knots for the helix
    for (i = 0; i < ncvs; i++) {
        controlVertices.append(
            MPoint(
                radius * cos((double)i),
                pitch * (double)i,
                radius * sin((double)i)
                )
            );
    }
    for (i = 0; i < nknots; i++)
        knotSequences.append((double)i);
    // Now create the curve
    MFnNurbsCurve curveFn;
    MObject curve = curveFn.create(
        controlVertices,
        knotSequences,
        deg,
        MFnNurbsCurve::kOpen,
        false,
        false,
        MObject::kNullObj,
        &st
        );
    MGlobal::displayInfo("Helix curve created!");

    if (!st) {
        MGlobal::displayError(
            HelixQtCmd::commandName + " - could not create helix: "
            + st.errorString()
            );
    }
}
//-----------------------------------------------------------------------------
MPointArray &cubeLocator::vertices () {
	static MPointArray vertices ;
	if ( vertices.length () != 0 )
		return (vertices) ;
	// Cube data
	static float cube [] [3] ={
		{ -0.5f, -0.5f, -0.5f }, { 0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, -0.5f }, { -0.5f, 0.5f, -0.5f }, 
		{ -0.5f, 0.5f, -0.5f }, { -0.5f, 0.5f, 0.5f }, { -0.5f, -0.5f, 0.5f }, { -0.5f, -0.5f, -0.5f }, 
		{ -0.5f, 0.5f, 0.5f }, { -0.5f, -0.5f, 0.5f }, { 0.5f, -0.5f, 0.5f }, { 0.5f, 0.5f, 0.5f }, 
		{ 0.5f, 0.5f, 0.5f }, { 0.5f, -0.5f, 0.5f }, { 0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, -0.5f }, 
		{ 0.5f, -0.5f, 0.5f }, { 0.5f, -0.5f, -0.5f }, { -0.5f, -0.5f, -0.5f }, { -0.5f, -0.5f, 0.5f }, 
		{ -0.5f, 0.5f, -0.5f }, { -0.5f, 0.5f, 0.5f }, { 0.5f, 0.5f, 0.5f }, { 0.5f, 0.5f, -0.5f }
	} ;
	int len =sizeof (cube) / sizeof (cube [0]) ;
	for ( int i =0 ; i < len ; i++ )
		vertices.append (cube [i] [0], cube [i] [1], cube [i] [2]) ;
	return (vertices) ;
}
//-----------------------------------------------------------------------------
MPointArray &ovalLocator::vertices () {
	static MPointArray vertices ;
	if ( vertices.length () != 0 )
		return (vertices) ;
	// Oval data
	static float oval [] [3] ={
		{ -2.00f, 0.0f, 0.0f }, { -1.90f, 0.0f, 0.309f }, { -1.618f, 0.0f, 0.588f }, { -1.176f, 0.0f, 0.809f }, 
		{ -0.618f, 0.0f, 0.951f }, { 0.0f, 0.0f, 1.00f }, { 0.618f, 0.0f, 0.951f}, { 1.176f, 0.0f, 0.809f}, 
		{ 1.618f, 0.0f, 0.588f}, { 1.90f, 0.0f, 0.309f}, { 2.00f, 0.0f, 0.0f}, { 1.90f, 0.0f, -0.309f}, 
		{ 1.618f, 0.0f, -0.588f}, { 1.176f, 0.0f, -0.809f}, { 0.618f, 0.0f, -0.951f}, { 0.0f, 0.0f, -1.00f }, 
		{ -0.618f, 0.0f, -0.951f}, { -1.176f, 0.0f, -0.809f}, { -1.618f, 0.0f, -0.588f}, { -1.90f, 0.0f, -0.309f}, 
		{ -2.00f, 0.0f, 0.0f }
	} ;
	int len =sizeof (oval) / sizeof (oval [0]) ;
	for ( int i =0 ; i < len ; i++ )
		vertices.append (oval [i] [0], oval [i] [1], oval [i] [2]) ;
	return (vertices) ;
}
Beispiel #16
0
void mesh::appendToMesh(MPointArray& points, MIntArray& faceCounts,MIntArray& faceConnects){
	for(int i=0;i<gPoints.length();i++){
		points.append(gPoints[i]);
	}
	for(int i=0;i<gFaceCounts.length();i++){
		faceCounts.append(gFaceCounts[i]);
	}
	for(int i=0;i<gFaceConnects.length();i++){
		faceConnects.append(gFaceConnects[i]);
	}
	if(gPoints.length()==0){
		std::string s=std::to_string((long double)gPoints.length());
		MGlobal::displayInfo(MString(s.c_str()));
		s=std::to_string((long double)gFaceCounts[0]);
		MGlobal::displayInfo(MString(s.c_str()));
		s=std::to_string((long double)gFaceConnects.length());
		MGlobal::displayInfo(MString(s.c_str()));
	}
}
Beispiel #17
0
void MVGManipulator::getTranslatedWSEdgePoints(M3dView& view,
                                               const MVGManipulatorCache::EdgeData* originEdgeData,
                                               MPoint& originCSPosition, MPoint& targetWSPosition,
                                               MPointArray& targetEdgeWSPositions) const
{
    assert(originEdgeData != NULL);
    MVector edgeCSVector =
        MVGGeometryUtil::worldToCameraSpace(view, originEdgeData->vertex1->worldPosition) -
        MVGGeometryUtil::worldToCameraSpace(view, originEdgeData->vertex2->worldPosition);
    MVector vertex1ToMouseCSVector =
        originCSPosition -
        MVGGeometryUtil::worldToCameraSpace(view, originEdgeData->vertex1->worldPosition);
    float ratioVertex1 = vertex1ToMouseCSVector.length() / edgeCSVector.length();
    float ratioVertex2 = 1.f - ratioVertex1;

    MVector edgeWSVector =
        originEdgeData->vertex1->worldPosition - originEdgeData->vertex2->worldPosition;
    targetEdgeWSPositions.append(targetWSPosition + ratioVertex1 * edgeWSVector);
    targetEdgeWSPositions.append(targetWSPosition - ratioVertex2 * edgeWSVector);
}
Beispiel #18
0
void CylinderMesh::appendToMesh(
    MPointArray& points, 
    MIntArray& faceCounts, 
    MIntArray& faceConnects)
{
    MPointArray cpoints;
    MVectorArray cnormals; 
    transform(cpoints, cnormals);    

    int startIndex = points.length(); // offset for indexes
    for (int i = 0; i < cpoints.length(); i++)
    {
        points.append(cpoints[i]);
    }
    for (int i = 0; i < gFaceCounts.length(); i++)
    {
        faceCounts.append(gFaceCounts[i]);
    }

    for (int i = 0; i < gFaceConnects.length(); i++)
    {
        faceConnects.append(gFaceConnects[i]+startIndex);
    }
}
Beispiel #19
0
void CylinderMesh::transform(MPointArray& points, MVectorArray& normals)
{
    MVector forward = mEnd - mStart;
    double s = forward.length();
    forward.normalize();

    MVector left = MVector(0,0,1)^forward;
    MVector up;
    if (left.length() < 0.0001)
    {
        up = forward^MVector(0,1,0);
        left = up^forward;
    }
    else
    {
        up = forward^left;
    }

    MMatrix mat;
    mat[0][0] = forward[0]; mat[0][1] = left[0]; mat[0][2] = up[0]; mat[0][3] = 0;
    mat[1][0] = forward[1];   mat[1][1] = left[1]; mat[1][2] = up[1]; mat[1][3] = 0;
    mat[2][0] = forward[2];   mat[2][1] = left[2]; mat[2][2] = up[2]; mat[2][3] = 0;
    mat[3][0] = 0;            mat[3][1] = 0;       mat[3][2] = 0;     mat[3][3] = 1;
    mat = mat.transpose();

    for (int i = 0; i < gPoints.length(); i++)
    {
        MPoint p = gPoints[i];
        p.x = p.x * s; // scale
        p = p * mat + mStart; // transform
        points.append(p);

        MVector n = gNormals[i] * mat;
        normals.append(n);
    }
}
MStatus DDConvexHullUtils::generateMayaHull(MObject &output,
                                const MPointArray &vertices,
                                const DDConvexHullUtils::hullOpts &hullOptions)
{
    // Allocate and push the vert list into the new array Mem Cleanup req.
    uint numInputVerts = vertices.length();
    double *inputVerts = new double[numInputVerts*3];
    for (uint i=0; i < numInputVerts; i++)
    {
        uint offset = i*3;
        inputVerts[offset]   = vertices[i].x;
        inputVerts[offset+1] = vertices[i].y;
        inputVerts[offset+2] = vertices[i].z;
    }
    
    // Setup the flags
    uint hullFlags = QF_DEFAULT;
    if (hullOptions.forceTriangles)
    {
        hullFlags |= QF_TRIANGLES;
    }
    if (hullOptions.useSkinWidth)
    {
        hullFlags |= QF_SKIN_WIDTH;
    }
    if (hullOptions.reverseTriangleOrder)
    {
        hullFlags |= QF_REVERSE_ORDER;
    }
    
    // Create the description
    HullDesc hullDescription;
    hullDescription.mFlags = hullFlags;
    hullDescription.mMaxVertices = hullOptions.maxOutputVertices;
    hullDescription.mSkinWidth = hullOptions.skinWidth;
    hullDescription.mNormalEpsilon = hullOptions.normalEpsilon;
    hullDescription.mVertexStride = sizeof(double)*3;
    hullDescription.mVcount = numInputVerts;
    hullDescription.mVertices = inputVerts;
    
    // Create the hull
    HullLibrary hullComputer;
    HullResult hullResult;
    HullError err = hullComputer.CreateConvexHull(hullDescription, hullResult);
    MStatus hullStat = MStatus::kSuccess;
    if (err == QE_OK)
    {
        // Grab the verts
        MPointArray outPoints;
        for (uint i=0; i < hullResult.mNumOutputVertices; i++)
        {
            uint offset = i*3;
            MPoint curPoint(hullResult.mOutputVertices[offset],
                            hullResult.mOutputVertices[offset+1],
                            hullResult.mOutputVertices[offset+2]);
            outPoints.append(curPoint);
        }
        
        // Check if the results are in polygons, or triangles. Depending on
        // which for the result is in, the way the face indices are setup
        // is different.
        MIntArray polyCounts;
        MIntArray vertexConnects;
        
        if (hullResult.mPolygons)
        {
            const uint *idx = hullResult.mIndices;
            for (uint i=0; i < hullResult.mNumFaces; i++)
            {
                uint pCount = *idx++;
                polyCounts.append(pCount);
                
                for (uint j=0; j < pCount; j++)
                {
                    uint val = idx[0];
                    vertexConnects.append(val);
                    idx++;
                }
            }
        }
        else
        {
            polyCounts.setLength(hullResult.mNumFaces);
            for (uint i=0; i < hullResult.mNumFaces; i++)
            {
                
                polyCounts[i] = 3;
                uint *idx = &hullResult.mIndices[i*3];
                
                vertexConnects.append(idx[0]);
                vertexConnects.append(idx[1]);
                vertexConnects.append(idx[2]);
            }
        }
        // Setup the outmesh
        MFnMesh outMeshFn(output);
        outMeshFn.create(hullResult.mNumOutputVertices,
                         hullResult.mNumFaces,
                         outPoints,
                         polyCounts,
                         vertexConnects,
                         output,
                         &hullStat);
    }
    else
    {
        hullStat = MStatus::kFailure;
    }
    
    // Mem Cleanup
    hullComputer.ReleaseResult(hullResult);
    delete[] inputVerts;
    
    return hullStat;
}
Beispiel #21
0
void uiDrawManagerDrawOverride::addUIDrawables(
    const MDagPath& objPath,
    MHWRender::MUIDrawManager& drawManager,
    const MHWRender::MFrameContext& frameContext,
    const MUserData* data)
{
    const uiDrawManagerData* thisdata = dynamic_cast<const uiDrawManagerData*>(data);
    if (!thisdata) {
        return;
    }

    switch (thisdata->fUIType) 
    {
    case uiDrawManager::kText: 
        {
            // Draw a text "uiDrawManager"
            // All drawing operations must take place between calls to beginDrawable()
            // and endDrawable().
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setFontSize(thisdata->fTextFontSize);
            drawManager.setFontIncline(thisdata->fTextIncline);
            drawManager.setFontWeight(thisdata->fTextWeight);
            drawManager.setFontStretch(thisdata->fTextStretch);
            drawManager.setFontLine(thisdata->fTextLine);

            MString faceName = uiDrawManagerData::fFontList[thisdata->fFontFaceIndex];
            drawManager.setFontName(faceName);
            int boxSize[] = { thisdata->fTextBoxWidth, thisdata->fTextBoxHeight };
            if (thisdata->fDraw2D) {
                // uiDrawManagerData::fPosition gives a screen space position 
                // where 2D UI item is located.                
                drawManager.text2d(thisdata->fPosition, thisdata->fText, thisdata->fTextAlignment, 
                    boxSize[0]+boxSize[1] == 0 ? NULL : boxSize, &thisdata->fTextBoxColor, false);
            }
            else {
                // for 3D items, place it at the origin of the world space.
                drawManager.text(thisdata->fPosition, thisdata->fText, thisdata->fTextAlignment, 
                    boxSize[0]+boxSize[1] == 0 ? NULL : boxSize, &thisdata->fTextBoxColor, false);
            }

            drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kLine:
	case uiDrawManager::kLineList:
	case uiDrawManager::kLineStrip:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setLineWidth(thisdata->fLineWidth);
            drawManager.setLineStyle(thisdata->fLineStyle);
			if (thisdata->fUIType == uiDrawManager::kLineStrip)
				drawManager.lineStrip(thisdata->fLines, thisdata->fDraw2D);
            else
				drawManager.lineList(thisdata->fLines, thisdata->fDraw2D);
			drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kPoint:
    case uiDrawManager::kPointList:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setPointSize(thisdata->fPointSize);
            drawManager.points(thisdata->fPoints, thisdata->fDraw2D);
            drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kRect:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setLineWidth(thisdata->fLineWidth);
            drawManager.setLineStyle(thisdata->fLineStyle);
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
            if (thisdata->fDraw2D) {
                // For 2d rectangle, an up vector in screen space is used to determine its X 
                // and Y directions. In addition, "fRectScaleX" and "fRectScaleY"(in pixels)
                // specify the half-lengths of the 2d rectangle.
                drawManager.rect2d(thisdata->fPosition, thisdata->fRectUp,
                    thisdata->fRectScaleX, thisdata->fRectScaleY, thisdata->fIsFilled);
            }
            else {
                // For 3d rectangle, the up vector should not be parallel with the normal vector.
				drawManager.rect(thisdata->fPosition, thisdata->fRectUp, thisdata->fRectNormal,
                    thisdata->fRectScaleX, thisdata->fRectScaleY, thisdata->fIsFilled);
            }

            drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kQuad:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setLineWidth(thisdata->fLineWidth);
            drawManager.setLineStyle(thisdata->fLineStyle);

            // prepare primitive type
            MUIDrawManager::Primitive mode = 
                thisdata->fIsFilled ? MUIDrawManager::kTriStrip : MUIDrawManager::kClosedLine;
            // prepare position list
            MPointArray position;
            for (int i = 0; i < 4; ++i) {
                position.append(thisdata->fQuadVertex[i]);
            }
            // prepare index
            MUintArray index;
            index.append(0);
            index.append(1);
            index.append(3);
            index.append(2);

            // draw mesh
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
            if (thisdata->fDraw2D) {
                drawManager.mesh2d(mode, position, NULL, thisdata->fIsFilled ? &index : NULL);
            }
            else {
                drawManager.mesh(mode, position, NULL, NULL, thisdata->fIsFilled ? &index : NULL);
            }

            drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kSphere:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setLineWidth(thisdata->fLineWidth);
            drawManager.setLineStyle(thisdata->fLineStyle);
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
			drawManager.sphere(thisdata->fPosition, thisdata->fRadius, thisdata->fIsFilled);

            drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kCircle:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setLineWidth(thisdata->fLineWidth);
            drawManager.setLineStyle(thisdata->fLineStyle);
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
            if (thisdata->fDraw2D) {
                // The radius in specified as pixel unit for 2d items.
				drawManager.circle2d(thisdata->fPosition, thisdata->fRadius, 
                    thisdata->fIsFilled);
            }
            else {
                drawManager.circle(thisdata->fPosition, thisdata->fCircleNormal, thisdata->fRadius, 
                    thisdata->fIsFilled);
            }

            drawManager.endDrawable();
        }
        break;

    case uiDrawManager::kArc:
        {
            drawManager.beginDrawable();

            drawManager.setColor(thisdata->fColor);
            drawManager.setLineWidth(thisdata->fLineWidth);
            drawManager.setLineStyle(thisdata->fLineStyle);
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
            if (thisdata->fDraw2D) {
                // If 2d, the range of the arc is defined by the start and end vectors 
                // specified in screen space.
                drawManager.arc2d(thisdata->fPosition, thisdata->fArcStart, thisdata->fArcEnd, 
                    thisdata->fRadius, thisdata->fIsFilled);
            }
            else {
                // For 3d arc, the projections of the start and end vectors onto the arc plane(
                // determined by the normal vector) determine the range of the arc.
                drawManager.arc(thisdata->fPosition, thisdata->fArcStart, thisdata->fArcEnd, 
                    thisdata->fArcNormal, thisdata->fRadius, thisdata->fIsFilled);
            }

            drawManager.endDrawable();
        }
        break;

	case uiDrawManager::kIcon:
		{	
            MString iconName = uiDrawManagerData::fIconList[thisdata->fIconIndex];
			drawManager.beginDrawable();
			drawManager.setColor(thisdata->fColor);
			drawManager.icon(thisdata->fPosition, iconName, thisdata->fIconScale);
			drawManager.endDrawable();
		}
		break;

	case uiDrawManager::kCone:
		{
			drawManager.beginDrawable();

			drawManager.setColor(thisdata->fColor);
			drawManager.setLineWidth(thisdata->fLineWidth);
			drawManager.setLineStyle(thisdata->fLineStyle);
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
			drawManager.cone(thisdata->fPosition,
							thisdata->fConeDirection,
							thisdata->fRadius, 
							thisdata->fConeHeight,
							thisdata->fIsFilled);

			drawManager.endDrawable();
		}
		break;

	case uiDrawManager::kBox:
		{
			drawManager.beginDrawable();

			drawManager.setColor(thisdata->fColor);
			drawManager.setLineWidth(thisdata->fLineWidth);
			drawManager.setLineStyle(thisdata->fLineStyle);
			drawManager.setPaintStyle(thisdata->fShaded ? 
				MUIDrawManager::kShaded : MUIDrawManager::kFlat);
			drawManager.box(thisdata->fPosition, 
							thisdata->fBoxUp,
							thisdata->fBoxRight,
							thisdata->fBoxScale[0],
							thisdata->fBoxScale[1],
							thisdata->fBoxScale[2],
							thisdata->fIsFilled);

			drawManager.endDrawable();
		}
		break;
	
	default:
        perror("unhandled ui types.");
        break;
    }
    
}
Beispiel #22
0
bool CSGSlicer::slice( const Cell& cell, const MeshSlicerInfo& info, MFnMesh& outMesh ) {
	// copy maya mesh to csg.js model
	csgjs_model jsModel;
	MItMeshVertex it(_sourceMesh);
	while( !it.isDone() ) {
		csgjs_vertex vtx;
		// get position
		MPoint pos = it.position(MSpace::kWorld);
		vtx.pos = csgjs_vector(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z));
		// add position
		jsModel.vertices.push_back(vtx);
		it.next();
	}
	MIntArray triangleCounts;
	MIntArray triangleVertices;
	MFnMesh(_sourceMesh).getTriangles(triangleCounts, triangleVertices);
	for( unsigned int i = 0; i < triangleVertices.length(); ++i ) {
		jsModel.indices.push_back(triangleVertices[i]);
	}

	// convert cell into csgjs_model
	csgjs_model cellModel;

	int indexOffset = 0;
	const auto& planePoints = cell.getPlanePoints();
	for( const auto& points : planePoints ) {
		for( const auto& pnt : points ) {
			csgjs_vertex vtx;
			vtx.pos = csgjs_vector(pnt.x, pnt.y, pnt.z);
			cellModel.vertices.push_back(vtx);
		}
		const auto& indices = HadanConvexTriangulate(points);
		for( const auto& idx : indices ) {
			cellModel.indices.push_back(indexOffset + idx[0]);
			cellModel.indices.push_back(indexOffset + idx[1]);
			cellModel.indices.push_back(indexOffset + idx[2]);
		}

		indexOffset += static_cast<int>(points.size());
	}

	// perform intersection
	const csgjs_model result = csgjs_intersection(jsModel, cellModel);

	// copy back to maya mesh
	MPointArray pointArray;
	for( const auto& vtx : result.vertices ) {
		pointArray.append(MPoint(vtx.pos.x, vtx.pos.y, vtx.pos.z));
	}
	MIntArray faceConnects;
	for( const auto& idx : result.indices ) {
		faceConnects.append(idx);
	}
	MIntArray faceCounts;
	for( size_t i = 0; i < result.indices.size() / 3; ++i ) {
		faceCounts.append(3);
	}
	{
		std::unique_lock<std::mutex> lock(CSGJS_CREATEMESH_MUTEX);
		outMesh.create(pointArray.length(), faceCounts.length(), pointArray, faceCounts, faceConnects);
	}

	return true;
}
Beispiel #23
0
MObject VMesh::createFeather()
{
	MStatus stat;
	MFnMeshData dataCreator;
	MObject outMeshData = dataCreator.create(&stat);
	
	int numVertex = 0;
	int numPolygon = 0;
	MPointArray vertexArray;
	MFloatArray uArray, vArray;
	MIntArray polygonCounts, polygonConnects, polygonUVs;

	MFnMesh meshFn(pgrow, &stat);
	MItMeshVertex vertIter(pgrow, &stat);
	MItMeshPolygon faceIter(pgrow,  &stat);
	
	MPoint S;
	MVector N, tang, ttang, binormal, dir, hair_up;
	MColor Cscale, Cerect, Crotate, Ccurl, Cwidth;
	float rot, lengreal;
	MATRIX44F hair_space;
	
	MString setScale("fb_scale");
	MString setErect("fb_erect");
	MString setRotate("fb_rotate");
	MString setCurl("fb_curl");
	MString setWidth("fb_width");
	MIntArray conn_face;
	
	for( int i=0; !vertIter.isDone(); vertIter.next(), i++ )
	{
		if(vertIter.onBoundary()) continue;
		vertIter.getNormal(N, MSpace::kWorld);
		N.normalize();
		
		vertIter.getColor(Cscale, &setScale);
		vertIter.getColor(Cerect, &setErect);
		vertIter.getColor(Crotate, &setRotate);
		vertIter.getColor(Ccurl, &setCurl);
		vertIter.getColor(Cwidth, &setWidth);
		
		vertIter.getConnectedFaces(conn_face);
		tang = MVector(0,0,0);
		for(int j=0; j<conn_face.length(); j++)
		{
			meshFn.getFaceVertexTangent (conn_face[j], i, ttang,  MSpace::kWorld);
			ttang.normalize();
			tang += ttang;
		}
		tang /= conn_face.length();
		conn_face.clear();
		tang.normalize();
		tang = N^tang;
		tang.normalize();
		
		binormal = N^tang;
		
		if(Crotate.r<0.5)
		{
			rot = (0.5 - Crotate.r)*2;
			tang = tang + (binormal-tang)*rot;
			tang.normalize();
			binormal = N^tang;
		}
		else
		{
			rot = (Crotate.r-0.5)*2;
			tang = tang + (binormal*-1-tang)*rot;
			tang.normalize();
			binormal = N^tang;
		}
		
		dir = tang + (N - tang)*Cerect.r;
		dir.normalize();
		
		//S = S+dir*Cscale.r*m_scale;
		//glVertex3f(S.x, S.y, S.z);
		
		hair_up = dir^binormal;
		
		hair_space.setIdentity();
		hair_space.setOrientations(XYZ(binormal.x, binormal.y, binormal.z), XYZ(hair_up.x, hair_up.y, hair_up.z), XYZ(dir.x, dir.y, dir.z));
		
		S = vertIter.position(MSpace::kWorld);
		
		hair_space.setTranslation(XYZ(S.x, S.y, S.z));
		
		lengreal = Cscale.r*m_scale;
		
		fb->create(lengreal, 0, lengreal*(Ccurl.r-0.5)*2);
		
		XYZ pw;
		MPoint pvx;
		
		MPoint pright = S + binormal*Cwidth.r*m_width*lengreal;
		MPoint pleft = S - binormal*Cwidth.r*m_width*lengreal;
		
		MPoint phit;
		int polyhit;
		meshFn.getClosestPoint (pright,  phit,  MSpace::kObject, &polyhit);
		MVector topright = phit - S;
		topright.normalize();
		topright *= Cwidth.r*m_width*lengreal;
		
		meshFn.getClosestPoint (pleft,  phit,  MSpace::kObject, &polyhit);
		MVector topleft = phit - S;
		topleft.normalize();
		topleft *= Cwidth.r*m_width*lengreal;
		
		//tws_binormal  = binormal*cos(0.2) + hair_up*sin(0.2);
	
		for(int j=0; j<NUMBENDSEG+1; j++)
		{
			fb->getPoint(j, pw);
			hair_space.transform(pw);
			
			pvx = MPoint(pw.x, pw.y, pw.z) + topleft;//- tws_binormal*Cwidth.r*m_width*lengreal;
			vertexArray.append(pvx);
			pvx = MPoint(pw.x, pw.y, pw.z);
			vertexArray.append(pvx);
			pvx = MPoint(pw.x, pw.y, pw.z) + topright;//tws_binormal*Cwidth.r*m_width*lengreal;
			vertexArray.append(pvx);
			
			uArray.append(0.0);
			vArray.append((float)j/NUMBENDSEG);
			
			uArray.append(0.5);
			vArray.append((float)j/NUMBENDSEG);
			
			uArray.append(1.0);
			vArray.append((float)j/NUMBENDSEG);
		}

		for(int j=0; j<NUMBENDSEG; j++)
		{
			polygonConnects.append(j*3 + numVertex);
			polygonConnects.append(j*3+3 + numVertex);
			polygonConnects.append(j*3+4 + numVertex);
			polygonConnects.append(j*3+1 + numVertex);
			
			polygonCounts.append(4);
			
			polygonConnects.append(j*3+1 + numVertex);
			polygonConnects.append(j*3+4 + numVertex);
			polygonConnects.append(j*3+5 + numVertex);
			polygonConnects.append(j*3+2 + numVertex);
			
			polygonCounts.append(4);
			
			polygonUVs.append(j*3 + numVertex);
			polygonUVs.append(j*3+3 + numVertex);
			polygonUVs.append(j*3+4 + numVertex);
			polygonUVs.append(j*3+1 + numVertex);
			
			polygonUVs.append(j*3+1 + numVertex);
			polygonUVs.append(j*3+4 + numVertex);
			polygonUVs.append(j*3+5 + numVertex);
			polygonUVs.append(j*3+2 + numVertex);
		}
		
		numVertex += (NUMBENDSEG+1)*3;
		numPolygon += NUMBENDSEG*2;
	}
	
	MIntArray connvert; 
	int idxpre;
	float averg_scale, averg_erect, averg_rotate, averg_curl, averg_width;
	for( int i=0; !faceIter.isDone(); faceIter.next(), i++ )
	{
		if(faceIter.onBoundary()) continue;
		faceIter.getNormal(N, MSpace::kWorld);
		N.normalize();
		
		faceIter.getVertices(connvert);
		
		averg_scale=averg_erect=averg_rotate=averg_curl=0;
		for(int j=0; j<connvert.length(); j++)
		{
			vertIter.setIndex(connvert[j], idxpre);
			
			vertIter.getColor(Cscale, &setScale);
			vertIter.getColor(Cerect, &setErect);
			vertIter.getColor(Crotate, &setRotate);
			vertIter.getColor(Ccurl, &setCurl);
			vertIter.getColor(Cwidth, &setWidth);
			
			averg_scale += Cscale.r;
			averg_erect += Cerect.r;
			averg_rotate += Crotate.r;
			averg_curl += Ccurl.r;
			averg_width += Cwidth.r;
		}
		
		averg_scale /= connvert.length();
		averg_erect /= connvert.length();
		averg_rotate /= connvert.length();
		averg_curl /= connvert.length();
		averg_width /= connvert.length();
		
		tang = MVector(0,0,0);
		for(int j=0; j<connvert.length(); j++)
		{
			meshFn.getFaceVertexTangent (i, connvert[j], ttang,  MSpace::kWorld);
			ttang.normalize();
			tang += ttang;
		}
		//tang /= conn_face.length();
		connvert.clear();
		tang.normalize();
		tang = N^tang;
		tang.normalize();
		
		binormal = N^tang;
		
		if(averg_rotate<0.5)
		{
			rot = (0.5 - averg_rotate)*2;
			tang = tang + (binormal-tang)*rot;
			tang.normalize();
			binormal = N^tang;
		}
		else
		{
			rot = (averg_rotate-0.5)*2;
			tang = tang + (binormal*-1-tang)*rot;
			tang.normalize();
			binormal = N^tang;
		}
		
		dir = tang + (N - tang)*averg_erect;
		dir.normalize();
		
		//S = S+dir*Cscale.r*m_scale;
		//glVertex3f(S.x, S.y, S.z);
		
		hair_up = dir^binormal;
		
		hair_space.setIdentity();
		hair_space.setOrientations(XYZ(binormal.x, binormal.y, binormal.z), XYZ(hair_up.x, hair_up.y, hair_up.z), XYZ(dir.x, dir.y, dir.z));
		
		S = faceIter.center(MSpace::kWorld);
		
		hair_space.setTranslation(XYZ(S.x, S.y, S.z));
		
		lengreal = Cscale.r*m_scale;
		
		fb->create(lengreal, 0, lengreal*(averg_curl-0.5)*2);
		
		MPoint pright = S + binormal*Cwidth.r*m_width*lengreal;
		MPoint pleft = S - binormal*Cwidth.r*m_width*lengreal;
		
		XYZ pw;
		MPoint pvx;
		
		MPoint phit;
		int polyhit;
		meshFn.getClosestPoint (pright,  phit,  MSpace::kObject, &polyhit);
		MVector topright = phit - S;
		topright.normalize();
		topright *= Cwidth.r*m_width*lengreal;
		
		meshFn.getClosestPoint (pleft,  phit,  MSpace::kObject, &polyhit);
		MVector topleft = phit - S;
		topleft.normalize();
		topleft *= Cwidth.r*m_width*lengreal;
		//tws_binormal  = binormal*cos(0.2) + hair_up*sin(0.2);
	
		for(int j=0; j<NUMBENDSEG+1; j++)
		{
			fb->getPoint(j, pw);
			hair_space.transform(pw);
			
			pvx = MPoint(pw.x, pw.y, pw.z) + topleft;//- tws_binormal*averg_width*m_width*lengreal;
			vertexArray.append(pvx);
			pvx = MPoint(pw.x, pw.y, pw.z);
			vertexArray.append(pvx);
			pvx = MPoint(pw.x, pw.y, pw.z) + topright;//tws_binormal*averg_width*m_width*lengreal;
			vertexArray.append(pvx);
			
			uArray.append(0.0);
			vArray.append((float)j/NUMBENDSEG);
			
			uArray.append(0.5);
			vArray.append((float)j/NUMBENDSEG);
			
			uArray.append(1.0);
			vArray.append((float)j/NUMBENDSEG);
		}

		for(int j=0; j<NUMBENDSEG; j++)
		{
			polygonConnects.append(j*3 + numVertex);
			polygonConnects.append(j*3+3 + numVertex);
			polygonConnects.append(j*3+4 + numVertex);
			polygonConnects.append(j*3+1 + numVertex);
			
			polygonCounts.append(4);
			
			polygonConnects.append(j*3+1 + numVertex);
			polygonConnects.append(j*3+4 + numVertex);
			polygonConnects.append(j*3+5 + numVertex);
			polygonConnects.append(j*3+2 + numVertex);
			
			polygonCounts.append(4);
			
			polygonUVs.append(j*3 + numVertex);
			polygonUVs.append(j*3+3 + numVertex);
			polygonUVs.append(j*3+4 + numVertex);
			polygonUVs.append(j*3+1 + numVertex);
			
			polygonUVs.append(j*3+1 + numVertex);
			polygonUVs.append(j*3+4 + numVertex);
			polygonUVs.append(j*3+5 + numVertex);
			polygonUVs.append(j*3+2 + numVertex);
		}
		
		numVertex += (NUMBENDSEG+1)*3;
		numPolygon += NUMBENDSEG*2;
		
	}

	
	MFnMesh meshCreateFn;
	meshCreateFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat );
	
	meshCreateFn.setUVs ( uArray, vArray );
	meshCreateFn.assignUVs ( polygonCounts, polygonUVs );
	
	return outMeshData;
}
		MStatus CreateCurves::createCurve(Model::Strand & strand) {
			MStatus status;

			std::cerr << "Working with strand defined by base: " << strand.getDefiningBase().getDagPath(status).fullPathName().asChar() << std::endl;

			/*
			 * Make sure this base is an end base (5')
			 */

			Model::Strand::BackwardIterator base_it = std::find_if(strand.reverse_begin(), strand.reverse_end(), Model::Strand::BaseTypeFunc(Model::Base::FIVE_PRIME_END));

			/*
			 * If we found an end base, use it, if not, it's a loop and it wont matter but we have to close the curve
			 */

			bool isLoop = base_it == strand.reverse_end();
			Model::Strand strand_(isLoop ? strand.getDefiningBase() : *base_it);

			std::cerr << "5' end or loop base: " << strand_.getDefiningBase().getDagPath(status).fullPathName().asChar() << std::endl;

			MPointArray pointArray;
			MDoubleArray knotSequences;
			
			/*
			 * Notice that the first point is different, it is as if it was inserted 4 times
			 * Also notice that radius is probably normally never changed, but is taken into account
			 * radius is only measured on the X,Y plane
			 */
			MVector translation;

			for(Model::Strand::ForwardIterator it = strand_.forward_begin(); it != strand_.forward_end(); ++it) {
				/*
				 * Extract our coordinates, then interpolate between the last coordinates and these m_degree times
				 */

				if (!(status = it->getTranslation(translation, MSpace::kWorld))) {
					status.perror("Base::getTranslation");
					return status;
				}

				pointArray.append(translation);
			}

			/*
			 * Now create the CV curve
			 */

			knotSequences.setSizeIncrement(pointArray.length() + 2 * (unsigned int) m_degree - 1);
			for(int i = 0; i < m_degree - 1; ++i)
				knotSequences.append(0);
			for(unsigned int i = 0; i < pointArray.length() - 2; ++i)
				knotSequences.append(i);
			for(int i = 0; i < m_degree - 1; ++i)
				knotSequences.append(pointArray.length() - 3);

			m_curve_data.push_back(Curve(pointArray, knotSequences, isLoop));
			
			if (!(status = m_curve_data.back().create(*this))) {
				status.perror("Curve::create");
				return status;
			}

			return MStatus::kSuccess;
		}
MStatus	liqAttachPrefAttribute::redoIt()
{
  MFnTypedAttribute tAttr;
  MStatus status;

  for ( unsigned i( 0 ); i < objectNames.length(); i++ ) 
  {
    MSelectionList		nodeList;
    nodeList.add( objectNames[i] );
    MObject depNodeObj;
    nodeList.getDependNode( 0, depNodeObj );
    MDagPath dagNode;
    nodeList.getDagPath( 0, dagNode );
    MFnDependencyNode depNode( depNodeObj );
    MObject prefAttr;
    MString attrName, varName;

    // make sure the renderer description is up to date
    liqglo.liquidRenderer.setRenderer();

    // build the name of the attribute
    varName = ( ( exportN && depNodeObj.hasFn( MFn::kMesh ) )? "N":"P" );
    attrName = "rman";
    attrName += varName;
    attrName += ( ( liqglo.liquidRenderer.requires__PREF )? "__":"" );
    attrName += varName + "ref";

    // create the attribute
    prefAttr = tAttr.create( attrName, attrName, MFnData::kPointArray );


    if ( depNodeObj.hasFn( MFn::kNurbsSurface ) ) 
    {
      MFnNurbsSurface nodeFn( depNodeObj );
      MPointArray nodePArray;
      MItSurfaceCV cvs( dagNode, MObject::kNullObj, liqglo.liquidRenderer.requires_SWAPPED_UVS == false, &status );

      while( !cvs.isDone() ) 
      {
        while( !cvs.isRowDone() ) 
        {
          MPoint pt = (worldSpace)? cvs.position( MSpace::kWorld ) : cvs.position( MSpace::kObject );
          nodePArray.append( pt );
          cvs.next();
        }
        cvs.nextRow();
      }

      nodeFn.addAttribute( prefAttr );
      MFnPointArrayData pArrayData;

      MObject prefDefault = pArrayData.create( nodePArray );
      MPlug nodePlug( depNodeObj, prefAttr );
      nodePlug.setValue( prefDefault );
    } 
    else if ( depNodeObj.hasFn( MFn::kNurbsCurve ) ) 
    {
      // Carsten: added support for PREF on nurbs curves
      //
      MFnNurbsCurve nodeFn( depNodeObj );
      MPointArray nodePArray;
      nodeFn.getCVs( nodePArray );

      nodeFn.addAttribute( prefAttr );
      MFnPointArrayData pArrayData;

      MObject prefDefault = pArrayData.create( nodePArray );
      MPlug nodePlug( depNodeObj, prefAttr );
      nodePlug.setValue( prefDefault );
    } 
    else if ( depNodeObj.hasFn( MFn::kMesh ) ) 
    {
      MFnMesh nodeFn( depNodeObj );
      // Moritz: modified this line to dim nodePArray -- otherwise
      // nodePArray.set() in the wile loop below throws an exception
      // which was why __Pref didn't work
      MPointArray nodePArray( MFnMesh( depNodeObj ).numVertices() );
      unsigned count;

      nodeFn.addAttribute( prefAttr );

      if ( exportN ) 
      {
        // export Nref
        unsigned vertex;
        unsigned normal;
        unsigned face = 0;
        unsigned faceVertex = 0;
        unsigned int numNormals = nodeFn.numNormals();
        unsigned int numPoints  = nodeFn.numVertices();
        MFloatVectorArray normals;
        MVectorArray normalAttArray;
        nodeFn.getNormals( normals );

        if ( numNormals > numPoints ) 
        {
          // if we get more than 1 normal per vertex,
          // force the arraysize to the full facevarying size
          unsigned faceVaryingCount( 0 );
          for ( unsigned pOn( 0 ); pOn < nodeFn.numPolygons(); pOn++ ) 
            faceVaryingCount += nodeFn.polygonVertexCount( pOn );
          
          normalAttArray.setLength( faceVaryingCount );
        } 
        else 
          normalAttArray.setLength(normals.length());
        
        for ( MItMeshPolygon polyIt ( depNodeObj ); polyIt.isDone() == false; polyIt.next() ) 
        {
          count = polyIt.polygonVertexCount();
          while ( count > 0 ) 
          {
            --count;
            normal = polyIt.normalIndex( count );
            vertex = polyIt.vertexIndex( count );

            if( numNormals == numPoints )
              normalAttArray.set(normals[normal], vertex);
            else
              normalAttArray.set(normals[normal], faceVertex);

            ++faceVertex;
          }
          ++face;
        }

        MFnVectorArrayData pArrayData;
        MObject prefDefault = pArrayData.create( normalAttArray );
        MPlug nodePlug( depNodeObj, prefAttr );
        nodePlug.setValue( prefDefault );

      } 
      else 
      {
        // TODO: do we need to account for the altMeshExport algo that's
        // used in liquidRibMeshData?
        // Moritz: no, it's basically the same as the algo below
        for ( MItMeshPolygon polyIt( dagNode, MObject::kNullObj ); !polyIt.isDone(); polyIt.next()) 
        {
          count = polyIt.polygonVertexCount();

          while ( count > 0 ) 
          {
            --count;
            unsigned	vertexIndex = polyIt.vertexIndex( count );
            MPoint nodePoint = (worldSpace)? polyIt.point( count, MSpace::kWorld ) : polyIt.point( count, MSpace::kObject );
            // Moritz: this returns MS::kFailure but seems to work?!
            nodePArray.set( nodePoint, vertexIndex );
          }
        }

        MFnPointArrayData pArrayData;
        MObject prefDefault = pArrayData.create( nodePArray );
        MPlug nodePlug( depNodeObj, prefAttr );
        nodePlug.setValue( prefDefault );

      }
    } else cerr << "Neither a Nurbs nor a Mesh !!" << endl;
  }
  return MS::kSuccess;
}
Beispiel #26
0
void TestDeformer::initVertMapping(MDataBlock& data,
                          MItGeometry& iter,
                          const MMatrix& localToWorldMatrix,
                          unsigned int mIndex)
{
    MStatus status;


    MArrayDataHandle vertMapOutArrayData = data.outputArrayValue( vert_map, &status );
    CHECK_MSTATUS( status );

    // use vertMapOutArrayBuilder to modify vertMapOutArrayData
    iter.reset();
    int count = iter.count();
    MArrayDataBuilder vertMapOutArrayBuilder( vert_map, count, &status );
    CHECK_MSTATUS( status );


    MPointArray allPts;// world vertex position of the driven mesh
    allPts.clear();

    // walk through the driven mesh
    /// copy MItGeometry's vertex to vertMapOutArrayData
    int i = 0;
    while( !iter.isDone(&status) )
    {
        CHECK_MSTATUS( status );

        MDataHandle initIndexDataHnd = vertMapOutArrayBuilder.addElement( i, &status );
        CHECK_MSTATUS( status );

        int negIndex = -1;

        initIndexDataHnd.setInt( negIndex );
        initIndexDataHnd.setClean();

        // append a vertex position(world coordination) to allPts
        CHECK_MSTATUS(allPts.append( iter.position() * localToWorldMatrix ));
        i = i+1;
        iter.next();
    }
    CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder ));




    /// Append more vertex from each driver mesh to vertMapOutArrayData
    MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status );
    CHECK_MSTATUS( status );

    int numMeshes = meshAttrHandle.elementCount();
    __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes);

    CHECK_MSTATUS(meshAttrHandle.jumpToElement(0));
    for( int meshIndex=0; meshIndex < numMeshes; ++meshIndex )
    {
        __debug("%s(), meshIndex=%d", __FUNCTION__, meshIndex);

        MDataHandle currentMesh = meshAttrHandle.inputValue(&status);
        CHECK_MSTATUS(status);

        MObject meshMobj = currentMesh.asMesh();
        __debug("%s(), meshMobj.apiTypeStr()=%s", __FUNCTION__, meshMobj.apiTypeStr());

        __debugMeshInfo(__FUNCTION__, meshMobj);
        {
            _initVertMapping_on_one_mesh(meshMobj, vertMapOutArrayBuilder, allPts);// Note: vertMapOutArrayBuilder is updated in this function!
            //CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder ));
        }

        if( !meshAttrHandle.next() )
        {
            break;
        }
    }// for (mesh
    CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder ));



}
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();
}
Beispiel #28
0
MStatus TestDeformer::deform(MDataBlock& data,
                          MItGeometry& iter,
                          const MMatrix& localToWorldMatrix,
                          unsigned int mIndex)
{
    MStatus status;

    // get the current node state
    short initialized_mapping = data.inputValue( initialized_data, &status).asShort();
    CHECK_MSTATUS(status);
    __debug("%s(), initialized_mapping=%d, mIndex=%d", __FUNCTION__, initialized_mapping, mIndex);

    if( initialized_mapping == 1 )
    {
        initVertMapping(data, iter, localToWorldMatrix, mIndex);

        // set initialized_data to 2 automatically. User don't have to set it manully.
        MObject tObj  =  thisMObject();
        MPlug setInitMode = MPlug( tObj, initialized_data  );
        setInitMode.setShort( 2 );
        // and sync initialized_mapping from initialized_data
        // so, the code section:
        //     if (initialized_mapping == 2)
        //     {
        //         ...
        //     }
        // will be executed when this deform() function is called next time.
        initialized_mapping = data.inputValue( initialized_data, &status ).asShort();
        CHECK_MSTATUS(status);
    }

    if( initialized_mapping == 2 )
    {
        envelope = MPxDeformerNode::envelope;
        MDataHandle envelopeHandle = data.inputValue( envelope, &status );
        CHECK_MSTATUS( status );

        MArrayDataHandle vertMapArrayData  = data.inputArrayValue( vert_map, &status  );
        CHECK_MSTATUS( status );

        MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status );
        CHECK_MSTATUS( status );


        /// 1. init tempOutputPts to zero points
        MPointArray tempOutputPts;
        iter.reset();
        while( !iter.isDone(&status) )
        {
            CHECK_MSTATUS(tempOutputPts.append(MPoint(0, 0, 0)));
            CHECK_MSTATUS(iter.next());
        }
        assert(tempOutputPts.length() == iter.count());


        /// 2. set tempOutputPts to deform values which comes from each driver mesh
        iter.reset();

        int numMeshes = meshAttrHandle.elementCount();
        __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes);

        CHECK_MSTATUS(meshAttrHandle.jumpToElement(0));
        // for each driver mesh
        for( int count=0; count < numMeshes; ++count )
        {
            __debug("%s(), count=%d", __FUNCTION__, count);

            // for one driver mesh: currentMesh
            MDataHandle currentMesh = meshAttrHandle.inputValue(&status);
            CHECK_MSTATUS( status );
            MObject meshMobj = currentMesh.asMesh();
            __debugMeshInfo(__FUNCTION__, meshMobj);

            // accumulate deform values of currentMesh to tempOutputPts
            _deform_on_one_mesh(data, iter, localToWorldMatrix, mIndex,
                                meshMobj,
                                envelopeHandle, vertMapArrayData, tempOutputPts );


            if( !meshAttrHandle.next() )
            {
                break;
            }

        }// for each driver mesh


        /// 3. add deform value to this geometry(driven mesh)
        int i = 0;
        iter.reset();
        while( !iter.isDone(&status) )
        {
            MPoint p = iter.position(MSpace::kObject, &status);
            CHECK_MSTATUS(status);

            // add the deform value to this vertex
            CHECK_MSTATUS(iter.setPosition( p + tempOutputPts[i]/numMeshes ));

            CHECK_MSTATUS(iter.next());
            ++i;
        }
        assert(tempOutputPts.length() == iter.count());
    }// if

	return( MS::kSuccess );
}
Beispiel #29
0
MObject fullLoft::loft( MArrayDataHandle &inputArray, MObject &newSurfData,
					  MStatus &stat )
{
	MFnNurbsSurface surfFn;
	MPointArray cvs;
	MDoubleArray ku, kv;
	int i, j;
	int numCVs;
	int numCurves = inputArray.elementCount ();

	// Ensure that we have at least 1 element in the input array
	// We must not do an inputValue on an element that does not
	// exist.
	if ( numCurves < 1 )
		return MObject::kNullObj;

	// Count the number of CVs
	inputArray.jumpToElement(0);
	MDataHandle elementHandle = inputArray.inputValue(&stat);
	if (!stat) {
		stat.perror("fullLoft::loft: inputValue");
		return MObject::kNullObj;
	}
	MObject countCurve (elementHandle.asNurbsCurve());
	MFnNurbsCurve countCurveFn (countCurve);
	numCVs = countCurveFn.numCVs (&stat);
	PERRORnull("fullLoft::loft counting CVs");

	// Create knot vectors for U and V
	// U dimension contains one CV from each curve, triple knotted
	for (i = 0; i < numCurves; i++)
	{
		ku.append (double (i));
		ku.append (double (i));
		ku.append (double (i));
	}

	// V dimension contains all of the CVs from one curve, triple knotted at
	// the ends
	kv.append( 0.0 );
	kv.append( 0.0 );
	kv.append( 0.0 );

	for ( i = 1; i < numCVs - 3; i ++ )
		kv.append( (double) i );

	kv.append( numCVs-3 );
	kv.append( numCVs-3 );
	kv.append( numCVs-3 );

	// Build the surface's CV array
	for (int curveNum = 0; curveNum < numCurves; curveNum++)
	{
		MObject curve (inputArray.inputValue ().asNurbsCurve ());
		MFnNurbsCurve curveFn (curve);
		MPointArray curveCVs;

		stat = curveFn.getCVs (curveCVs, MSpace::kWorld);
		PERRORnull("fullLoft::loft getting CVs");

		if (curveCVs.length() != (unsigned)numCVs)
			stat = MS::kFailure;
		PERRORnull("fullLoft::loft inconsistent number of CVs - rebuild curves");

		// Triple knot for every curve but the first
		int repeats = (curveNum == 0) ? 1 : 3;

		for (j = 0; j < repeats; j++)
			for ( i = 0; i < numCVs; i++ )
				cvs.append (curveCVs [i]);

		stat = inputArray.next ();
	}
	MObject surf = surfFn.create(cvs, ku, kv, 3, 3,
								 MFnNurbsSurface::kOpen,
								 MFnNurbsSurface::kOpen,
								 false, newSurfData, &stat );
	PERRORnull ("fullLoft::Loft create surface");

	return surf;
}
bool ToMayaCurveConverter::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const
{
	MStatus s;

	IECore::ConstCurvesPrimitivePtr curves = IECore::runTimeCast<const IECore::CurvesPrimitive>( from );
	
	assert( curves );

	if ( !curves->arePrimitiveVariablesValid() || !curves->numCurves() )
	{
		return false;
	}
	
	int curveIndex = indexParameter()->getNumericValue();
	if( curveIndex < 0 || curveIndex >= (int)curves->numCurves() )
	{
		IECore::msg( IECore::Msg::Warning,"ToMayaCurveConverter::doConversion",  boost::format(  "Invalid curve index \"%d\"") % curveIndex );
		return false;
	}
	
	IECore::ConstV3fVectorDataPtr p = curves->variableData< IECore::V3fVectorData >( "P", IECore::PrimitiveVariable::Vertex );
	if( !p )
	{
		IECore::msg( IECore::Msg::Warning,"ToMayaCurveConverter::doConversion",  "Curve has no \"P\" data" );
		return false;
		
	}
	
	const std::vector<int>& verticesPerCurve = curves->verticesPerCurve()->readable();
	int curveBase = 0;
	for( int i=0; i<curveIndex; ++i )
	{
		curveBase += verticesPerCurve[i];
	}
	
	MPointArray vertexArray;
	
	int numVertices = verticesPerCurve[curveIndex];
	
	int cvOffset = 0;
	if( curves->basis() != IECore::CubicBasisf::linear() && !curves->periodic() )
	{
		// Maya implicitly duplicates end points, so they're explicitly duplicated in the CurvePrimitives.
		// We need to remove those duplicates when converting back to Maya. Remove 2 cvs at start, 2 at end.
		if( numVertices < 8 )
		{
			IECore::msg( IECore::Msg::Warning,"ToMayaCurveConverter::doConversion",  "The Curve Primitive does not have enough CVs to be converted into a Maya Curve. Needs at least 8." );
			return false;
		}
		
		cvOffset = 2;
	}
	
	const std::vector<Imath::V3f>& pts = p->readable();
	
	// triple up the start points for cubic periodic curves:
	if( curves->periodic() && curves->basis() != IECore::CubicBasisf::linear() )
	{
		vertexArray.append( IECore::convert<MPoint, Imath::V3f>( pts[curveBase] ) );
		vertexArray.append( vertexArray[0] );
	}
	
	for( int i = cvOffset; i < numVertices-cvOffset; ++i )
	{
		vertexArray.append( IECore::convert<MPoint, Imath::V3f>( pts[i + curveBase] ) );
	}
	
	// if the curve is periodic, the first N cvs must be identical to the last N cvs, where N is the degree
	// of the curve:
	if( curves->periodic() )
	{
		if( curves->basis() == IECore::CubicBasisf::linear() )
		{
			// linear: N = 1
			vertexArray.append( vertexArray[0] );
		}
		else
		{
			// cubic: N = 3
			vertexArray.append( vertexArray[0] );
			vertexArray.append( vertexArray[1] );
			vertexArray.append( vertexArray[2] );
		}
	}
	
	unsigned vertexArrayLength = vertexArray.length();
	
	MDoubleArray knotSequences;
	if( curves->basis() == IECore::CubicBasisf::linear() )
	{
		for( unsigned i=0; i < vertexArrayLength; ++i )
		{
			knotSequences.append( i );
		}
	}
	else
	{
		if( curves->periodic() )
		{
			// Periodic curve, knots must be spaced out.
			knotSequences.append( -1 );
			for( unsigned i=0; i < vertexArrayLength+1; ++i )
			{
				knotSequences.append( i );
			}
		}
		else
		{
			// For a cubic curve, the first three and last three knots must be duplicated for the curve start/end to start at the first/last CV.
			knotSequences.append( 0 );
			knotSequences.append( 0 );
			for( unsigned i=0; i < vertexArrayLength-2; ++i )
			{
				knotSequences.append( i );
			}
			knotSequences.append( vertexArrayLength-3 );
			knotSequences.append( vertexArrayLength-3 );
		}
	}
	
	MFnNurbsCurve fnCurve;
	fnCurve.create( vertexArray, knotSequences, curves->basis() == IECore::CubicBasisf::linear() ? 1 : 3, curves->periodic() ? MFnNurbsCurve::kPeriodic : MFnNurbsCurve::kOpen, false, false, to, &s );
	if (!s)
	{
		IECore::msg( IECore::Msg::Warning,"ToMayaCurveConverter::doConversion",  s.errorString().asChar() );
		return false;
	}
	
	return true;
}