Exemplo n.º 1
0
MTransformationMatrix SurfaceAttach::matrix(const MFnNurbsSurface &fnSurface, const int plugID, const double dataOffset,
                                            const bool dataReverse, const short dataGenus, const double dataStaticLength,
                                            const MMatrix &dataParentInverse, const short dataDirection) {
    // Do all the Fancy stuff to input UV values
    double parmU = this->uInputs[plugID];
    double parmV = this->vInputs[plugID];

    // Fix U Flipping from 1.0 to 0.0
    if (uInputs[plugID] == 1.0 && parmU == 0.0)
        parmU = 1.0;
    if (vInputs[plugID] == 1.0 && parmV == 0.0)
        parmV = 1.0;

    if (dataDirection == 0)
        this->calculateUV(plugID, dataOffset, dataReverse, dataGenus, dataStaticLength, parmU);
    else
        this->calculateUV(plugID, dataOffset, dataReverse, dataGenus, dataStaticLength, parmV);

    // Calculate transformations from UV values
    const MVector normal = fnSurface.normal(parmU, parmV, MSpace::Space::kWorld);

    MPoint point;
    fnSurface.getPointAtParam(parmU, parmV, point, MSpace::Space::kWorld);

    MVector tanU, tanV;
    fnSurface.getTangents(parmU, parmV, tanU, tanV, MSpace::Space::kWorld);

    const double dubArray[4][4] = { tanU.x, tanU.y, tanU.z, 0.0,
                                    normal.x, normal.y, normal.z, 0.0,
                                    tanV.x, tanV.y, tanV.z, 0.0,
                                    point.x, point.y, point.z, 1.0 };
    const MMatrix mat (dubArray);

    return MTransformationMatrix (mat * dataParentInverse);
}
Exemplo n.º 2
0
MStatus cvColor::compute( const MPlug& plug, MDataBlock& data )
{ 
	MStatus stat;

	// cout << "cvColor::compute\n";

	if ( plug == cvLocations ) {
		MDataHandle inputData = data.inputValue ( inputSurface, &stat );
		if (!stat) {
			stat.perror("cvColor::compute get inputSurface");
			return stat;
		}

		MObject surf = inputData.asNurbsSurface();
		MFnNurbsSurface surfFn (surf, &stat);
		if (!stat) {
			stat.perror("cvColor::compute surface creator");
			return stat;
		}

		MDataHandle outputData = data.outputValue ( cvLocations, &stat );
		if (!stat) {
			stat.perror("cvColor::compute get cvLocations");
			return stat;
		}
		
		MObject cvs = outputData.data();
		MFnPointArrayData cvData(cvs, &stat);
		if (!stat) {
			stat.perror("cvColor::compute point array data creator");
			return stat;
		}

		MPointArray cvArray;
		stat = surfFn.getCVs( cvArray, MSpace::kObject);
		if (!stat) {
			stat.perror("cvColor::compute getCVs");
			return stat;
		}

		stat = cvData.set ( cvArray );
		if (!stat) {
			stat.perror("cvColor::compute setCVs");
			return stat;
		}

		outputData.set ( cvs );

		stat = data.setClean ( plug );
		if (!stat) {
			stat.perror("cvColor::compute setClean");
			return stat;
		}
	} else {
		return MS::kUnknownParameter;
	}

	return MS::kSuccess;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
void SurfaceAttach::surfaceLengthsV(const MFnNurbsSurface &fnSurface, const double parmU) {
    MPoint pointA;
    fnSurface.getPointAtParam(parmU, 0.0, pointA, MSpace::Space::kWorld);

    this->length = 0.0;
    MPoint pointB;

    double *s = &this->sampler[0];
    double *d = &this->distances[0];

    for (size_t i=0; i < this->sampleCount; i++){
        fnSurface.getPointAtParam(parmU, *s++, pointB, MSpace::Space::kWorld);

        // Add the measured distanced to 'length' and set the measured length in 'distances'
        this->length += pointA.distanceTo(pointB);
        *d++ = this->length;

        pointA.x = pointB.x;
        pointA.y = pointB.y;
        pointA.z = pointB.z;
    }
}
Exemplo n.º 5
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;
}
Exemplo n.º 7
0
MStatus MG_nurbsRivet::compute(const MPlug& plug,MDataBlock& dataBlock)
	{
		


			
			//Get recompute value
			MDataHandle recomputeH = dataBlock.inputValue(recompute);
	  		bool recomputeV = recomputeH.asBool();





			//input mesh 
			MDataHandle inputNurbsH = dataBlock.inputValue(inputNurbSurface);
			MObject inputNurb = inputNurbsH.asNurbsSurfaceTransformed();
			MMatrix offsetMatrixV = dataBlock.inputValue(offsetMatrix).asMatrix(); 
			
			double U,V;
			MFnNurbsSurface nurbsFn ;
			nurbsFn.setObject(inputNurb);
			
			MStatus stat;

			if (recomputeV == true)
			{

			
				//input point 

				MDataHandle inputPointH = dataBlock.inputValue(inputPoint);
				MPoint inputP = inputPointH.asVector();
				

				
				
				MPoint closestP = nurbsFn.closestPoint(inputP,NULL,NULL,false,1e+99,MSpace::kObject);

				
				

				stat = nurbsFn.getParamAtPoint(closestP,U,V,MSpace::kObject);
				
				


				//Handle to U and V 
				MDataHandle uValueH =dataBlock.outputValue(uValue);
				MDataHandle vValueH =dataBlock.outputValue(vValue);
				
				uValueH.set(float(U));
				vValueH.set(float(V));
				uValueH.setClean();
				vValueH.setClean();



				MDataHandle recomputeOutH = dataBlock.outputValue(recompute);

	
			}  

			MDataHandle uH = dataBlock.inputValue(uValue);
			MDataHandle vH = dataBlock.inputValue(vValue);
			
			U = uH.asFloat(); 
			V = vH.asFloat();

			MPoint outPoint ;
			MVector uVec ;
			MVector vVec;
			MVector normal;
			//Get point
			stat = nurbsFn.getPointAtParam(U,V,outPoint,MSpace::kObject);
			
			//Since if getting both the U and V tangent was leading to some little rotation snapping 
			//of the rivet I only used the U tangent and calculated the next one by dot product
			//of the normal and U tangent leading to a 100% stable rivet 
			nurbsFn.getTangents(U,V,uVec,vVec,MSpace::kObject);
			
			uVec.normalize();
			vVec.normalize();
			MVector vVecCross;

	


			//Get normal



			

			normal = nurbsFn.normal(U,V,MSpace::kObject);
			normal.normalize();

			vVecCross =(uVec^normal);
			
			
			



			//Build the maya matrix 
			double myMatrix[4][4]={	{ uVec.x, uVec.y , uVec.z, 0},
									{ normal[0], normal[1] , normal[2], 0},
									{vVecCross.x, vVecCross.y , vVecCross.z, 0},
									{ outPoint[0], outPoint[1] , outPoint[2], 1}};
 
			
			MMatrix rotMatrix (myMatrix);
			MMatrix offsetMatrixV2 = offsetMatrixV*rotMatrix; 
			 
			MTransformationMatrix matrixFn(offsetMatrixV2);
			double angles[3];
			MTransformationMatrix::RotationOrder rotOrder;
			rotOrder =MTransformationMatrix::kXYZ;
			matrixFn.getRotation(angles,rotOrder,MSpace::kObject );
			//get back radians value
			double radX,radY,radZ;

			radX=angles[0]; 
			radY=angles[1];
			radZ=angles[2];
 
			

			//convert to degree

			double rotX,rotY,rotZ;

			rotX = radX*toDeg;
			rotY = radY*toDeg;
			rotZ = radZ*toDeg;
			

			MDataHandle outputRotateH = dataBlock.outputValue(outputRotate);
			
			outputRotateH.set3Double(rotX,rotY,rotZ);
			outputRotateH.setClean();

			//let set the output matrix too

			MDataHandle outMH= dataBlock.outputValue(outputMatrix);
			outMH.set(rotMatrix);
			outMH.setClean();

			MDataHandle outputH = dataBlock.outputValue(output);
			outputH.set(offsetMatrixV2[3][0],offsetMatrixV2[3][1],offsetMatrixV2[3][2]);
			outputH.setClean();

			 

 

		return MS::kSuccess;
	}