Example #1
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;
}
Example #2
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;
}
MObject readNurbs(double iFrame, Alembic::AbcGeom::INuPatch & iNode,
    MObject & iObject)
{
    MStatus status;
    MObject obj;

    Alembic::AbcGeom::INuPatchSchema schema = iNode.getSchema();

    // no interpolation for now
    Alembic::AbcCoreAbstract::index_t index, ceilIndex;
    getWeightAndIndex(iFrame, schema.getTimeSampling(),
        schema.getNumSamples(), index, ceilIndex);

    Alembic::AbcGeom::INuPatchSchema::Sample samp;
    schema.get(samp, Alembic::Abc::ISampleSelector(index));

    Alembic::Abc::P3fArraySamplePtr pos = samp.getPositions();
    Alembic::Abc::FloatArraySamplePtr weights = samp.getPositionWeights();

    MString surfaceName(iNode.getName().c_str());

    unsigned int degreeU  = samp.getUOrder() - 1;
    unsigned int degreeV  = samp.getVOrder() - 1;
    unsigned int numCVInU = samp.getNumU();
    unsigned int numCVInV = samp.getNumV();

    // cv points
    unsigned int numCV = numCVInU*numCVInV;
    unsigned int curPos = 0;

    MPointArray controlVertices;
    controlVertices.setLength(numCV);

    for (unsigned int v = 0; v < numCVInV; ++v)
    {
        for (unsigned int u = 0; u < numCVInU; ++u, ++curPos)
        {
            unsigned int mayaIndex = u * numCVInV + (numCVInV - v - 1);
            MPoint pt((*pos)[curPos].x, (*pos)[curPos].y, (*pos)[curPos].z);

            if (weights)
            {
                pt.w = (*weights)[curPos];
            }

            // go from u,v order to reversed v, u order
            controlVertices.set(pt, mayaIndex);
        }
    }

    // Nurbs form
    // Alemblic file does not record the form of nurb surface, we get the form
    // by checking the CV data. If the first degree number CV overlap the last
    // degree number CV, then the form is kPeriodic. If only the first CV overlaps
    // the last CV, then the form is kClosed.
    MFnNurbsSurface::Form formU = MFnNurbsSurface::kPeriodic;
    MFnNurbsSurface::Form formV = MFnNurbsSurface::kPeriodic;
    // Check all curves
    bool notOpen = true;
    for (unsigned int v = 0; notOpen && v < numCVInV; v++) {
        for (unsigned int u = 0; u < degreeU; u++) {
            unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1);
            unsigned int lastPeriodicIndex = (numCVInU - degreeU + u) * numCVInV + (numCVInV - v - 1);
            if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) {
                formU = MFnNurbsSurface::kOpen;
                notOpen = false;
                break;
            }
        }
    }

    if (formU == MFnNurbsSurface::kOpen) {
        formU = MFnNurbsSurface::kClosed;
        for (unsigned int v = 0; v < numCVInV; v++) {
            unsigned int lastUIndex = (numCVInU - 1) * numCVInV + (numCVInV - v - 1);
            if (! controlVertices[numCVInV-v-1].isEquivalent(controlVertices[lastUIndex])) {
                formU = MFnNurbsSurface::kOpen;
                break;
            }
        }
    }

    notOpen = true;
    for (unsigned int u = 0; notOpen && u < numCVInU; u++) {
        for (unsigned int v = 0; v < degreeV; v++) {
            unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1);
            unsigned int lastPeriodicIndex = u * numCVInV + (degreeV - v - 1); //numV - (numV - vDegree + v) - 1;
            if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) {
                formV = MFnNurbsSurface::kOpen;
                notOpen = false;
                break;
            }
        }
    }
    if (formV == MFnNurbsSurface::kOpen) {
        formV = MFnNurbsSurface::kClosed;
        for (unsigned int u = 0; u < numCVInU; u++) {
            if (! controlVertices[u * numCVInV + (numCVInV-1)].isEquivalent(controlVertices[u * numCVInV])) {
                formV = MFnNurbsSurface::kOpen;
                break;
            }
        }
    }


    Alembic::Abc::FloatArraySamplePtr uKnot = samp.getUKnot();
    Alembic::Abc::FloatArraySamplePtr vKnot = samp.getVKnot();

    unsigned int numKnotsInU = static_cast<unsigned int>(uKnot->size() - 2);
    MDoubleArray uKnotSequences;
    uKnotSequences.setLength(numKnotsInU);
    for (unsigned int i = 0; i < numKnotsInU; ++i)
    {
        uKnotSequences.set((*uKnot)[i+1], i);
    }

    unsigned int numKnotsInV = static_cast<unsigned int>(vKnot->size() - 2);
    MDoubleArray vKnotSequences;
    vKnotSequences.setLength(numKnotsInV);
    for (unsigned int i = 0; i < numKnotsInV; i++)
    {
        vKnotSequences.set((*vKnot)[i+1], i);
    }

    // Node creation try the API first
    MFnNurbsSurface mFn;
    obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences,
        degreeU, degreeV, formU, formV,
        true, iObject, &status);

    // something went wrong, try open/open create
    if (status != MS::kSuccess && (formU != MFnNurbsSurface::kOpen ||
        formV != MFnNurbsSurface::kOpen))
    {
        obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences,
            degreeU, degreeV,  MFnNurbsSurface::kOpen,  MFnNurbsSurface::kOpen,
            true, iObject, &status);
    }

    if (status == MS::kSuccess)
    {
        mFn.setName(surfaceName);
    }
    else
    {
        MString errorMsg = "Could not create Nurbs Surface: ";
        errorMsg += surfaceName;
        MGlobal::displayError(errorMsg);
    }

    trimSurface(samp, mFn);

    return obj;
}