Beispiel #1
0
void SoftBodyNode::createHelperMesh(MFnMesh &mayaMesh, std::vector<int> &triIndices, std::vector<float> &triVertices, MSpace::Space space)
{
	MFloatPointArray ptArray;
	mayaMesh.getPoints(ptArray, space);	

	// append vertex locations (x, y, z) into "flattened array"
	for(int i = 0; i < ptArray.length(); i++)
	{
		MFloatPoint pt;		
		pt = ptArray[i];
		pt.cartesianize();		
		triVertices.push_back(pt.x);
		triVertices.push_back(pt.y);
		triVertices.push_back(pt.z);

	}
	std::cout << std::endl;

	// create vector of triangle indices
	MIntArray tCounts;
	MIntArray tVerts;
	mayaMesh.getTriangles(tCounts, tVerts);
	triIndices.resize(tVerts.length());
	for(int i = 0; i < tVerts.length(); i ++)
	{
		triIndices[i] = tVerts[i];	
	} 	
}
Beispiel #2
0
static void makeCubes(std::vector<cube> &cubes, MString &name, MStatus *stat)
{
    MFnMesh fnMesh;
    MObject result;

    MFloatPointArray points;
    MIntArray faceCounts;
    MIntArray faceConnects;

    int index_offset = 0;
    for (std::vector<cube>::iterator cit = cubes.begin(); cit != cubes.end(); ++cit)
    {
        point3 diag = cit->diagonal();
        float scale = diag.x;
        point3 pos = cit->start + (diag * .5f);

        MFloatVector mpos(pos.x, pos.y, pos.z);

        addCube(scale, mpos, index_offset * (8), points, faceCounts, faceConnects);
        index_offset += 1;
    }

    unsigned int vtx_cnt = points.length();
    unsigned int face_cnt = faceCounts.length();

    MObject newMesh =
        fnMesh.create(
            /* numVertices */ vtx_cnt,
            /* numFaces */ face_cnt,
            points,
            faceCounts,
            faceConnects,
            MObject::kNullObj,
            stat);

    /* Harden all edges. */
    int n_edges = fnMesh.numEdges(stat);
    for (int i = 0; i < n_edges; ++i)
    {
        fnMesh.setEdgeSmoothing(i, false);
    }
    fnMesh.cleanupEdgeSmoothing(); /* Must be called after editing edges. */

    fnMesh.updateSurface();

    /* Assign Shader. */
    MSelectionList sel_list;
    if (!MFAIL(sel_list.add("initialShadingGroup")))
    {
        MObject set_obj;
        sel_list.getDependNode(0, set_obj);
        MFnSet set(set_obj);
        set.addMember(newMesh);
    }

    /* Give it a swanky name. */
    MFnDagNode parent(fnMesh.parent(0));
    name = parent.setName("polyMengerSponge", false, stat);
}
MStatus metro_model_translator::create_shape( const m2033::mesh_ptr m )
{
	MFloatPointArray v;
	MVectorArray norm;
	MIntArray p;
	MIntArray idx;

	MFnTransform transform_fn;
	MObject transform_obj = transform_fn.create( MObject::kNullObj );
	transform_fn.setName( m->get_name().c_str() );

	m2033::mesh::vertices mv = m->get_vertices();
	m2033::mesh::indices mi = m->get_indices();
	m2033::mesh::texcoords mt = m->get_tex_coords();
	m2033::mesh::normals mn = m->get_normals();

	for( unsigned i = 0; i < mv.size(); i++ ) {
		v.append( -mv[i].x, mv[i].y, mv[i].z );
		norm.append( MVector( -mn[i].x, mn[i].y, mn[i].z ) );
	}

	for( unsigned i = 0; i < mi.size() / 3; i++ ) {
		idx.append( mi[i*3+2] );
		idx.append( mi[i*3+1] );
		idx.append( mi[i*3] );
		p.append( 3 );
	}

	MFloatArray u_values, v_values;
	for( unsigned i = 0; i < mt.size(); i++ ) {
		u_values.append( mt[i].x );
		v_values.append( -mt[i].y );
	}

	MFnMesh meshFn;
	MObject mesh = meshFn.create( v.length(), p.length(), v, p, idx, u_values, v_values, transform_obj );
	MString name = m->get_name().c_str();
	meshFn.setName( name + MString("_shape") );

	MStatus s = meshFn.assignUVs( p, idx, 0 );
	if( !s ) {
		return s;
	}

	s = meshFn.unlockVertexNormals( idx );
	if( !s ) {
		return s;
	}
	meshFn.setVertexNormals( norm, idx );

	MObject mat = create_material( m->get_texture_name(), &s );
	if( !s ) {
		return s;
	}
	MFnSet mat_fn(mat);
	mat_fn.addMember(mesh);

	return MS::kSuccess;
}
Beispiel #4
0
MStatus testNucleusNode::compute(const MPlug &plug, MDataBlock &data)
{
	MStatus stat;

	if ( plug == nextState )
	{
        
        //get the value of the currentTime 
        MTime currTime = data.inputValue(currentTime).asTime();        
        MObject inputData;
        //pull on start state or current state depending on the current time.
        if(currTime.value() <= 0.0) {
            MArrayDataHandle multiDataHandle = data.inputArrayValue(startState);
            multiDataHandle.jumpToElement(0);
            inputData =multiDataHandle.inputValue().data();
        }
        else {
            MArrayDataHandle multiDataHandle = data.inputArrayValue(currentState);
            multiDataHandle.jumpToElement(0);
            inputData =multiDataHandle.inputValue().data();
        }                
                
        MFnNObjectData inputNData(inputData);                
        MnCloth * nObj = NULL;
        inputNData.getObjectPtr(nObj);        
        
        MFloatPointArray points;
        nObj->getPositions(points);
        unsigned int ii;
        for(ii=0;ii<points.length();ii++) {            
            points[ii].y = (float) sin(points[ii].x + currTime.value()*4.0f*(3.1415f/180.0f));
        }
        nObj->setPositions(points);

        delete nObj;        
        data.setClean(plug);
	}
	else if ( plug == currentState )
	{        
	    data.setClean(plug);

	}
    else if (plug == startState) {        
	    data.setClean(plug);
    }
    else {
		stat = MS::kUnknownParameter;
	}
	return stat;
}
Beispiel #5
0
bool kgLocator::getPoints( MFloatPointArray &pts ) 
{
	
	MFloatPoint pt;
	
	pt.x = -0.5f; pt.y = 0.0f; pt.z = 0.0f;
	pts.append( pt );
	pt.x = 0.5f; pt.y = 0.0f; pt.z = 0.0f;
	pts.append( pt );
	pt.x = 0.0f; pt.y = 0.0f; pt.z = -0.5f;
	pts.append( pt );
	pt.x = 0.0f; pt.y = 0.0f; pt.z = 0.5f;
	pts.append( pt );
	assert( pts.length() == 4 );
	return true;
}
Beispiel #6
0
MBoundingBox BasicLocator::boundingBox() const
{
	MBoundingBox bbox;
	MFloatPointArray points;
	points.clear();
	points.setSizeIncrement(4);
	points.append(-1.0, 0.0, 0.0);
	points.append(1.0, 0.0, 0.0);
	points.append(0.0, 0.0, 1.0);
	points.append(0.0, 0.0, -1.0);

	for (unsigned int i = 0; i < points.length(); i++)
		bbox.expand(points[i]);

	return bbox;
}
Beispiel #7
0
void store_in_hds(HDS &hds, MFloatPointArray &points, MIntArray &nFV, MIntArray &F)
{
    size_t nV = points.length();
    hds.V.setDims(3, nV);
    for (size_t k=0; k<nV; k++) 
    {
        hds.V[3*k+0] = points[k](0);
        hds.V[3*k+1] = points[k](1);
        hds.V[3*k+2] = points[k](2);
    }
    
    hds.nFV.setDims(1,nFV.length());
    for (size_t k=0; k<nFV.length(); k++) hds.nFV[k] = nFV[k];
    
    hds.tip.setDims(1,F.length());
    for (size_t k=0; k<F.length(); k++) hds.tip[k] = F[k];
}                      
void MayaGeoAttribute::transferValueFromMaya(MPlug &plug, MDataBlock &data){
	MDataHandle dataHandle = data.inputValue(plug);
	MFnMesh meshFn(dataHandle.asMesh());
	
	MFloatPointArray mayaPoints;
	meshFn.getPoints(mayaPoints);
	
	// collect points
	std::vector<Imath::V3f> coralPoints;
	for(int i = 0; i < mayaPoints.length(); ++i){
		MFloatPoint* mayaPoint = &mayaPoints[i];
		coralPoints.push_back(Imath::V3f(mayaPoint->x, mayaPoint->y, mayaPoint->z));
	}
	
	// collect faces
	int numPolys =  meshFn.numPolygons();
	std::vector<std::vector<int> > coralFaces(numPolys);
	for(int polyId = 0; polyId < numPolys; ++polyId){
		MIntArray mayaVertexList;
		meshFn.getPolygonVertices(polyId, mayaVertexList);
		
		int polyPoints = mayaVertexList.length();
		std::vector<int> coralFace(polyPoints);
		for(int i = 0; i < polyPoints; ++i){
			int pointId = mayaVertexList[i];
			coralFace[i] = pointId;
		}
		
		coralFaces[polyId] = coralFace;
	}
	
	// create coral geo
	coral::Geo *coralGeo = outValue();
	
	if(coralGeo->hasSameTopology(coralFaces)){
		coralGeo->setPoints(coralPoints);
	}
	else{
		coralGeo->build(coralPoints, coralFaces);
	}
	
	valueChanged();
}
void
OsdMeshData::updateGeometry(const MHWRender::MVertexBuffer *points, const MHWRender::MVertexBuffer *normals)
{
    // Update coarse vertex
    if (!_positionBuffer) return;
    if (!_normalBuffer) return;

    int nCoarsePoints = _pointArray.length();

    OpenSubdiv::OsdCpuVertexBuffer *cpuPos = dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer*>(_positionBuffer);
    OpenSubdiv::OsdCpuVertexBuffer *cpuNormal = dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer*>(_normalBuffer);

    if (cpuPos) {
        // I know, this is very inefficient...
        float *d_pos = cpuPos->GetCpuBuffer();
        float *d_normal = cpuNormal->GetCpuBuffer();

        glBindBuffer(GL_ARRAY_BUFFER, *(GLuint*)points->resourceHandle());
        glGetBufferSubData(GL_ARRAY_BUFFER, 0, nCoarsePoints*3*sizeof(float), d_pos);
        glBindBuffer(GL_ARRAY_BUFFER, *(GLuint*)normals->resourceHandle());
        glGetBufferSubData(GL_ARRAY_BUFFER, 0, nCoarsePoints*3*sizeof(float), d_normal);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    } else {
        glBindBuffer(GL_COPY_READ_BUFFER, *(GLuint*)points->resourceHandle());
        glBindBuffer(GL_COPY_WRITE_BUFFER, _positionBuffer->GetGpuBuffer());
        glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, nCoarsePoints*3*sizeof(float));
        
        glBindBuffer(GL_COPY_READ_BUFFER, *(GLuint*)normals->resourceHandle());
        glBindBuffer(GL_COPY_WRITE_BUFFER, _normalBuffer->GetGpuBuffer());
        glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, nCoarsePoints*3*sizeof(float));
        
        glBindBuffer(GL_COPY_READ_BUFFER, 0);
        glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
    }

    _osdmesh->Subdivide(_positionBuffer, NULL);
    _osdmesh->Subdivide(_normalBuffer, NULL);

    _needsUpdate = false;
}
Beispiel #10
0
void write_to_TCCNodeData(TCCData &tcc, MFloatPointArray &V, TCCNodeData &nd)
{
    size_t nV = V.length();
    nd.V.setDims(3, nV);
    for (size_t k=0; k<nV; k++) 
    {
        nd.V[3*k+0] = V[k](0);
        nd.V[3*k+1] = V[k](1);
        nd.V[3*k+2] = V[k](2);
    }
    
    // vertex data 
    nd.pole.setDims(1,tcc.pole.length());
    for (size_t k=0; k<tcc.pole.length(); k++) nd.pole[k] = tcc.pole[k]==1;

    nd.corner.setDims(1,tcc.corner.length());
    for (size_t k=0; k<tcc.corner.length(); k++) nd.corner[k] = tcc.corner[k];
    
    // halfedge data
    nd.T.setDims(1,tcc.T.length());
    for (size_t k=0; k<tcc.T.length(); k++) nd.T[k] = tcc.T[k];
    
    nd.itv.setDims(1,tcc.itv.length());
    for (size_t k=0; k<tcc.itv.length(); k++) nd.itv[k] = tcc.itv[k];
    
    nd.eqc.setDims(1,tcc.eqc.length());
    for (size_t k=0; k<tcc.eqc.length(); k++) nd.eqc[k] = tcc.eqc[k];

    // err is not needed!
    
    nd.nFV.setDims(1,tcc.nFV.length());
    for (size_t k=0; k<tcc.nFV.length(); k++) nd.nFV[k] = tcc.nFV[k];
    
    nd.tip.setDims(1,tcc.F.length());
    for (size_t k=0; k<tcc.F.length(); k++) nd.tip[k] = tcc.F[k];

    nd.selHE.setDims(1,tcc.selHE.length());
    for (size_t k=0; k<tcc.selHE.length(); k++) nd.selHE[k] = tcc.selHE[k];
}
void MayaGeoAttribute::transferValueToMaya(MPlug &plug, MDataBlock &data){
	coral::Geo *coralGeo = value();
	const std::vector<Imath::V3f> &coralPoints = coralGeo->points();
	
	// transfer points
	MFloatPointArray mayaPoints;
	for(int i = 0; i < coralPoints.size(); ++i){
		const Imath::V3f *coralPoint = &coralPoints[i];
		mayaPoints.append(MFloatPoint(coralPoint->x, coralPoint->y, coralPoint->z));
	}
	
	// transfer faces
	MIntArray mayaFaceCount;
	MIntArray mayaFaceVertices;
	
	const std::vector<std::vector<int> > coralFaces = coralGeo->rawFaces();
	for(int polyId = 0; polyId < coralFaces.size(); ++polyId){
		const std::vector<int> *coralFace = &coralFaces[polyId];
		int faceVertexCount = coralFace->size();
		mayaFaceCount.append(faceVertexCount);
		
		for(int i = 0; i < faceVertexCount; ++i){
			mayaFaceVertices.append(coralFace->at(i));
		}
	}
	
	// create maya mesh
	MDataHandle dataHandle = data.outputValue(plug);
	
	MFnMeshData dataCreator;
	MObject newOutputData = dataCreator.create();
	
	MFnMesh newMesh;
	newMesh.create(mayaPoints.length(), coralFaces.size(), mayaPoints, mayaFaceCount, mayaFaceVertices, newOutputData);
	dataHandle.set(newOutputData);
}
Beispiel #12
0
void readPoly(double iFrame, MFnMesh & ioMesh, MObject & iParent,
              PolyMeshAndFriends & iNode, bool iInitialized)
{
    Alembic::AbcGeom::IPolyMeshSchema schema = iNode.mMesh.getSchema();
    Alembic::AbcGeom::MeshTopologyVariance ttype = schema.getTopologyVariance();

    Alembic::AbcCoreAbstract::index_t index, ceilIndex;
    double alpha = getWeightAndIndex(iFrame,
                                     schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex);

    MFloatPointArray pointArray;
    Alembic::Abc::P3fArraySamplePtr ceilPoints;

    // we can just read the points
    if (ttype != Alembic::AbcGeom::kHeterogenousTopology && iInitialized)
    {

        Alembic::Abc::P3fArraySamplePtr points = schema.getPositionsProperty(
                ).getValue(Alembic::Abc::ISampleSelector(index));

        if (alpha != 0.0)
        {
            ceilPoints = schema.getPositionsProperty().getValue(
                             Alembic::Abc::ISampleSelector(ceilIndex) );
        }

        fillPoints(pointArray, points, ceilPoints, alpha);
        if(pointArray.length() > 0)
        {
            ioMesh.setPoints(pointArray, MSpace::kObject);
        }

        setColorsAndUVs(iFrame, ioMesh, schema.getUVsParam(),
                        iNode.mV2s, iNode.mC3s, iNode.mC4s, !iInitialized);

        if (schema.getNormalsParam().getNumSamples() > 1)
        {
            setPolyNormals(iFrame, ioMesh, schema.getNormalsParam());
        }

        return;
    }

    // we need to read the topology
    Alembic::AbcGeom::IPolyMeshSchema::Sample samp;
    schema.get(samp, Alembic::Abc::ISampleSelector(index));

    if (alpha != 0.0 && ttype != Alembic::AbcGeom::kHeterogenousTopology)
    {
        ceilPoints = schema.getPositionsProperty().getValue(
                         Alembic::Abc::ISampleSelector(ceilIndex) );
    }

    fillPoints(pointArray, samp.getPositions(), ceilPoints, alpha);

    fillTopology(ioMesh, iParent, pointArray, samp.getFaceIndices(),
                 samp.getFaceCounts());

    setPolyNormals(iFrame, ioMesh, schema.getNormalsParam());
    setColorsAndUVs(iFrame, ioMesh, schema.getUVsParam(),
                    iNode.mV2s, iNode.mC3s, iNode.mC4s, !iInitialized);
}
Beispiel #13
0
//
//  Recursively traverse a mesh by processing each face, and the neighbouring faces along it's edges.
//  The initial invocation of this routine provides the basis for the new first vertex/edge
//  and faces.  
//
//  The result of this routine is an array of values that map the old CV indices to the new ones. Along
//  the a new list of reindexed CVs is built, along with a list of poly counts and connetions. These
//  can be used to build a new mesh with the reordering specfied by the seed face and vertices.
//
//
//  Inputs: 
//		path				: Path to the object being traversed
//		faceIdx				: Current face being traversed
//		v0, v1				: Veretices that define the direction of travel along the face
//		faceTraversal		: An array booleans to track which faces have been 
//							: traversed, controls the recursion  
//		origVertices		: The vertices from the original mesh. The could be obtained
//							: from the path, but are passed in for efficiency
//
// 	Outputs:
//		cvMapping			: Mapping of the existing vertices to their new indices
//							: the fist values in the final array will be the intial v0, v1
//		cvMappingInverse	: The inverse of the cvMapping
//							: the value of items v0 and v1 will be 0 and 1 respectively
//		newPolygonCounts	: Vertex counts for each of the new faces
//		newPolygonConnects  : Connections, specified in terms of new CV indices
//		newVertices			: The orginal vertices resorted based on the reindexing
//
//
MStatus meshMapUtils::traverseFace( 
	MDagPath&	path,
	int faceIdx, 
	int v0, 
	int v1, 
	MIntArray& faceTraversal,
	MIntArray& cvMapping,
	MIntArray& cvMappingInverse,
	MIntArray& newPolygonCounts,
	MIntArray& newPolygonConnects,
	MFloatPointArray& origVertices,
	MFloatPointArray& newVertices
)
{
	int vtxCnt = -1;
	int dir = 0;
	int dummy;		// For setIndex calls

	MStatus stat = MStatus::kSuccess;

	MFnMesh theMesh( path, &stat );
	MItMeshPolygon polyIt( path );
	MItMeshEdge edgeIt( path );

	if( stat != MStatus::kSuccess )
	{
		MGlobal::displayError( " theMesh.getPoint failed");
		return stat;
	}


	//
	// Skip over any faces already processed, this is not a failure
	// 
	if( faceTraversal[faceIdx] )
	{
		return MStatus::kSuccess;
	}

	//
	// get the vertex/edge information and sort it based on the user seed
	//
	MIntArray vtxOrig;
	MIntArray edgeOrig;

	polyIt.setIndex( faceIdx, dummy );
	polyIt.getEdges( edgeOrig );	   
	polyIt.getVertices( vtxOrig );	   

	vtxCnt = vtxOrig.length();

	// 
	// the sorted V/E info
	// 
	MIntArray vtxSorted( vtxCnt );
	MIntArray edgeSorted( vtxCnt );

	//
	// Build a new array ordered with v0, then v1, first figure out the 
	// starting point, and direction 
	//
	int v0Idx =	-1;
	int i;
	for( i = 0; i < vtxCnt; i++ )
	{
		if( vtxOrig[i] == v0 )
		{
			// We've found v0, now find in what direction we need to travel to find v1
					
			v0Idx =	i;
			
			if( vtxOrig[IDX(i+1, vtxCnt)] == v1 )
			{
				dir = 1;
			}
			else if( vtxOrig[IDX(i-1, vtxCnt)] == v1 )
			{
				dir = -1;
			}
			break;
		}
	}

	if (dir == 0)
	{
		MGlobal::displayError("Selected vertices are not adjacent");
		return MS::kFailure;
	}

	// Now sort the vertex/edge arrays
	for( i = 0; i < vtxCnt; i++ )
	{
		vtxSorted[i] = vtxOrig[IDX( v0Idx + i * dir, vtxCnt )];
		if( dir == 1 )
		{
			edgeSorted[i] = edgeOrig[IDX( v0Idx + i * dir, vtxCnt )];
		}
		else
		{
			edgeSorted[i] = edgeOrig[IDX( v0Idx - 1 + i * dir, vtxCnt )];
		}
	}


	// Add any new CVs to the vertex array being constructed
	for ( i = 0; i < vtxCnt; i++ )
	{
		MPoint pos;
		int index = vtxSorted[i];

		if( cvMapping[index] == -1  )
		{
			if( stat != MStatus::kSuccess )
			{
				MGlobal::displayError( " theMesh.getPoint failed");
				return stat;
			}

			// Added the new CV, and mark it as transferred
			newVertices.append( origVertices[index] );

			// Store the mapping from the old CV indices to the new ones
			cvMapping[index] = newVertices.length()-1;
			cvMappingInverse[newVertices.length()-1] = index;
		}

	}

	//
	//  Add the new face count 
	//
	newPolygonCounts.append( vtxCnt );

	//
	//  Add the new polyConnects
	
	for ( i = 0; i < vtxCnt; i++ )
	{
		newPolygonConnects.append( cvMapping[vtxSorted[i]] );
	}

	// Mark this face as complete 
	faceTraversal[faceIdx] = true;

	//
	//  Now recurse over the edges of this face
	// 
	for( i = 0; i < (int)edgeSorted.length(); i++ )
	{
		int nextEdge = edgeSorted[i];

		int2 nextEdgeVtx;
		stat = theMesh.getEdgeVertices(nextEdge, nextEdgeVtx );

		//
		// Find the vertex, in the sorted array, that starts the next edge
		int baseIdx = -1;
		bool swap = false;
		int j;
		for( j = 0; j < (int)vtxSorted.length(); j++ )
		{
			if( vtxSorted[j] == nextEdgeVtx[0] )
			{
				baseIdx = j;
				break;
			}
		}

		assert( baseIdx != -1 );
	
		// 
		// Now look forward and backward in the vertex array to find the
		// edge's other point, this indicates the edges direction. This
		// is needed to guide the next recursion level, and keep the
		// normals pointed consistenly
		//
		if( vtxSorted[IDX(baseIdx+1, vtxCnt)] == nextEdgeVtx[1] )
		{
			// Nothing
		}
		else if ( vtxSorted[IDX(baseIdx-1, vtxCnt)] == nextEdgeVtx[1] )
		{
			swap = true;
		}


		MIntArray connectedFaces;
		edgeIt.setIndex( nextEdge, dummy );
		edgeIt.getConnectedFaces( connectedFaces );

		// A single face is simply the current one. Recurse over the others
		if( connectedFaces.length() > 1 )
		{
			int nextFace;
			if( connectedFaces[0] == faceIdx )
			{
			   	nextFace = connectedFaces[1];
			}
			else
			{
			   	nextFace = connectedFaces[0];
			}

			int nextVtx0 = -1;
			int nextVtx1 = -1;
			if ( !swap )
			{
				nextVtx0 = nextEdgeVtx[1];
				nextVtx1 = nextEdgeVtx[0];
			}
			else
			{
				nextVtx0 = nextEdgeVtx[0];
				nextVtx1 = nextEdgeVtx[1];
			}

			stat = traverseFace( path, nextFace, nextVtx0, nextVtx1, faceTraversal,
					cvMapping, cvMappingInverse, 
					newPolygonCounts, newPolygonConnects, 
					origVertices, newVertices );

			// Break out of edge loop on error
			if( stat != MStatus::kSuccess )
			{
				break;
			}	
		}
	}

	return stat;
}
Beispiel #14
0
MObject blindDataMesh::createMesh(long seed, MObject& outData, MStatus& stat)
{
	MFloatPointArray vertices;
	MIntArray faceDegrees;
	MIntArray faceVertices;
	int i, j;

	srand(seed);

	float planeSize = 20.0f;
	float planeOffset = planeSize / 2.0f;
	float planeDim = 0.5f;

	int numDivisions = (int) (planeSize / planeDim);
	// int numVertices = (numDivisions + 1) * (numDivisions + 1);
	// int numEdge = (2 * numDivisions) * (numDivisions + 1);
	int numFaces = numDivisions * numDivisions;

	// Set up an array containing the vertex positions for the plane. The
	// vertices are placed equi-distant on the X-Z plane to form a square
	// grid that has a side length of "planeSize".
	//
	// The Y-coordinate of each vertex is the average of the neighbors already
	// calculated, if there are any, with a small random offset added. Because
	// of the way the vertices are calculated, the whole plane will look like
	// it is streaked in a diagonal direction with mountains and depressions.
	//
	for (i = 0; i < (numDivisions + 1); ++i)
	{
		for (j = 0; j < (numDivisions + 1); ++j)
		{
			float height;

			if (i == 0 && j == 0)
			{
				height = ((rand() % 101) / 100.0f - 0.5f);
			}
			else if (i == 0)
			{
				float previousHeight = vertices[j - 1][1];
				height = previousHeight + ((rand() % 101) / 100.0f - 0.5f);
			}
			else if (j == 0)
			{
				float previousHeight = vertices[(i-1)*(numDivisions + 1)][1];
				height = previousHeight + ((rand() % 101) / 100.0f - 0.5f);
			}
			else
			{
				float previousHeight
					= vertices[(i-1)*(numDivisions + 1) + j][1];
				float previousHeight2
					= vertices[i*(numDivisions + 1) + j - 1][1];
				height = (previousHeight + previousHeight2)
					/ 2.0f + ((rand() % 101) / 100.0f - 0.5f);
			}

			MFloatPoint vtx( i * planeDim - planeOffset, height,
				j * planeDim - planeOffset );
			vertices.append(vtx);
		}
	}

	// Set up an array containing the number of vertices
	// for each of the plane's faces
	//
	for (i = 0; i < numFaces; ++i)
	{
		faceDegrees.append(4);
	}

	// Set up an array to assign the vertices for each face
	//
	for (i = 0; i < numDivisions; ++i)
	{
		for (j = 0; j < numDivisions; ++j)
		{
			faceVertices.append(i*(numDivisions+1) + j);
			faceVertices.append(i*(numDivisions+1) + j + 1);
			faceVertices.append((i+1)*(numDivisions+1) + j + 1);
			faceVertices.append((i+1)*(numDivisions+1) + j);
		}
	}

	MFnMesh	meshFn;
	MObject newMesh = meshFn.create(vertices.length(), numFaces, vertices,
		faceDegrees, faceVertices, outData, &stat);

	return newMesh;
}
Beispiel #15
0
MStatus TCC::createSubdividedMesh(int sdRes, int sdRefRes, MFnMesh &srcMesh, TCCData &tccData, MDataHandle outMeshHandle, float lineThickness, MStatus& stat)
{   
    HDS hds;
    bool shouldCreateUVs = true;
    
    size_t nV = srcMesh.numVertices();
    size_t nF = srcMesh.numPolygons();
    size_t nIHE = tccData.F.length();
    
    bool consistentSizes= (tccData.pole.length()==nV) && (tccData.T.length()==nIHE) && (tccData.itv.length()==nIHE) & (tccData.corner.length()==nV);
    
    if ((nV==0)||(nF==0)||(!consistentSizes)) return MS::kFailure;

    MFloatArray uArray, vArray, sc_uArray, sc_vArray;
    MIntArray uvIdx;
    if (shouldCreateUVs)
    {
        createUVset(tccData, sdRes, uArray, vArray, sc_uArray, sc_vArray, uvIdx, lineThickness);
    }
    
    
    MFloatPointArray points;
    srcMesh.getPoints(points);
    
    store_in_hds(hds, points, tccData.nFV, tccData.F);     // convert to HDS

    finalize_HDS(hds);
    size_t nHE = hds.nHE();

    hds.T.setDims(1, nHE);
    hds.itv.setDims(1, nHE);
    hds.corner.setDims(1, nV);
    
    // interior halfedge tags
    for (size_t k=0; k<nV; k++) 
    {
        hds.corner[k] = tccData.corner[k];
    }

    // interior halfedge tags
    for (size_t k=0; k<nIHE; k++) 
    {
        hds.T[k] = tccData.T[k];
        hds.itv[k] = tccData.itv[k];
    }
    
    // border halfedge tags
    for (size_t k=nIHE; k<nHE; k++) 
    {
        hds.T[k] = false;
        hds.itv[k] = hds.itv[hds.twin[k]];
    }
        
    TCC_MAX::subdivide(hds, sdRes);
    
    if (sdRefRes>0)
    {
        HDS hds2;
        copy_HDS(hds, hds2);
        TCC_MAX::subdivide(hds2, sdRefRes);
        memcpy(&hds.V[0], &hds2.V[0], hds.V.size() * sizeof(double));
    }
    

    
    MObject outMeshObj = outMeshHandle.asMesh();
    MFnMesh outMeshFn(outMeshObj);
    
    // if no topology change necessary, just update points!
    if ( (outMeshFn.numFaceVertices() == hds.nIHE()) && (outMeshFn.numPolygons() == hds.nF()) )
    {
        size_t nV   = hds.nV();
        points.setLength(nV);
        for (size_t k=0; k<nV; k++) 
        {
            points[k](0) = hds.V[3*k+0];
            points[k](1) = hds.V[3*k+1];
            points[k](2) = hds.V[3*k+2];
        }
        stat = outMeshFn.setPoints(points); McheckErr(stat, "ERROR creating outputData");
        
        if (shouldCreateUVs)
        {
            MString uvSet = "UnitPatchUVs";
            MString sc_uvSet = "ScaledPatchUVs";
            stat = outMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs");
            stat = outMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs");
        }
        
        return MS::kSuccess;
    }

    
    // Have to update connectivity and geometry

    load_from_hds(hds, points, tccData.nFV, tccData.F);

    nV = points.length();
    nF = tccData.nFV.length();
    
    MFnMeshData dataCreator;
    MObject newOutputData = dataCreator.create(&stat); McheckErr(stat, "ERROR creating outputData");
    MFnMesh newOutMeshFn;
    
    MObject newMesh;
    
    newMesh = newOutMeshFn.create(nV, nF, points, tccData.nFV, tccData.F, newOutputData, &stat); McheckErr(stat, "ERROR in MFnMesh.create\n");

    if (shouldCreateUVs)
    {
        MString uvSet = "UnitPatchUVs";
        MString sc_uvSet = "ScaledPatchUVs";
        
        uvSet = newOutMeshFn.createUVSetDataMeshWithName(uvSet, &stat); McheckErr(stat, "ERROR creating UVset");
        stat = newOutMeshFn.clearUVs(&uvSet);
        stat = newOutMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs");
        stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &uvSet); McheckErr(stat, "ERROR assigning UVs");
        
        sc_uvSet = newOutMeshFn.createUVSetDataMeshWithName(sc_uvSet, &stat); McheckErr(stat, "ERROR creating UVset");
        stat = newOutMeshFn.clearUVs(&sc_uvSet);
        stat = newOutMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs");
        stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &sc_uvSet); McheckErr(stat, "ERROR assigning UVs");
    }
    
    
    if (stat == MS::kSuccess)
    {
        outMeshHandle.set(newOutputData);
    }
    
    
    return MS::kSuccess;
}
Beispiel #16
0
collision_shape_t::pointer collisionShapeNode::createCollisionShape(const MObject& node)
{

	collision_shape_t::pointer collision_shape = 0;

	MObject thisObject(thisMObject());
	MPlug plgType(thisObject, ia_type);
	int type;
	plgType.getValue(type);

	switch(type) {
	case 0:  
		{
			//convex hull
			{
				if(node.hasFn(MFn::kMesh)) {
					MDagPath dagPath;
					MDagPath::getAPathTo(node, dagPath);
					MFnMesh fnMesh(dagPath);
					MFloatPointArray mpoints;
					MFloatVectorArray mnormals;
					MIntArray mtrianglecounts;
					MIntArray mtrianglevertices;
					fnMesh.getPoints(mpoints, MSpace::kObject);
					fnMesh.getNormals(mnormals, MSpace::kObject);
					fnMesh.getTriangles(mtrianglecounts, mtrianglevertices);

					std::vector<vec3f> vertices(mpoints.length());
					std::vector<vec3f> normals(mpoints.length());
					std::vector<unsigned int> indices(mtrianglevertices.length());

					btAlignedObjectArray<btVector3> btVerts; //mb

					for(size_t i = 0; i < vertices.size(); ++i) {
						vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z);
						normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z);

#if UPDATE_SHAPE //future collision margin adjust
						btVerts.push_back(btVector3(mpoints[i].x, mpoints[i].y, mpoints[i].z)); //mb
#endif
					}
					for(size_t i = 0; i < indices.size(); ++i) {
						indices[i] = mtrianglevertices[i];
					}

#if UPDATE_SHAPE //future collision margin adjust
					btAlignedObjectArray<btVector3> planeEquations;
					btGeometryUtil::getPlaneEquationsFromVertices(btVerts, planeEquations);

					btAlignedObjectArray<btVector3> shiftedPlaneEquations;
					for (int p=0;p<planeEquations.size();p++)
					{
						btVector3 plane = planeEquations[p];
						plane[3] += collisionShapeNode::collisionMarginOffset;
						shiftedPlaneEquations.push_back(plane);
					}

					btAlignedObjectArray<btVector3> shiftedVertices;
					btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations, shiftedVertices);

					std::vector<vec3f> shiftedVerticesVec3f(shiftedVertices.size());
					for(size_t i = 0; i < shiftedVertices.size(); ++i) 
					{
						shiftedVerticesVec3f[i] = vec3f(shiftedVertices[i].getX(), shiftedVertices[i].getY(), shiftedVertices[i].getZ());
						//std::cout << "orig verts: " << vertices[i][0] << " " << vertices[i][1] << " " << vertices[i][2] << std::endl;
						//std::cout << "shft verts: " << shiftedVertices[i].getX() << " " << shiftedVertices[i].getY() << " " << shiftedVertices[i].getZ() << std::endl;
						//std::cout << std::endl;
					}

					collision_shape = solver_t::create_convex_hull_shape(&(shiftedVerticesVec3f[0]), shiftedVerticesVec3f.size(), &(normals[0]), &(indices[0]), indices.size());

#endif

#if UPDATE_SHAPE == 0
					collision_shape = solver_t::create_convex_hull_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size()); //original
#endif
				}
			}
		}

		break;
	case 1:
		{
			//mesh
			{
				if(node.hasFn(MFn::kMesh)) {
					MDagPath dagPath;
					MDagPath::getAPathTo(node, dagPath);
					MFnMesh fnMesh(dagPath);
					MFloatPointArray mpoints;
					MFloatVectorArray mnormals;
					MIntArray mtrianglecounts;
					MIntArray mtrianglevertices;
					fnMesh.getPoints(mpoints, MSpace::kObject);
					fnMesh.getNormals(mnormals, MSpace::kObject);
					fnMesh.getTriangles(mtrianglecounts, mtrianglevertices);

					std::vector<vec3f> vertices(mpoints.length());
					std::vector<vec3f> normals(mpoints.length());
					std::vector<unsigned int> indices(mtrianglevertices.length());

					for(size_t i = 0; i < vertices.size(); ++i) {
						vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z);
						normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z);
					}
					for(size_t i = 0; i < indices.size(); ++i) {
						indices[i] = mtrianglevertices[i];
					}
					bool dynamicMesh = true;
					collision_shape = solver_t::create_mesh_shape(&(vertices[0]), vertices.size(), &(normals[0]),
						&(indices[0]), indices.size(),dynamicMesh);
				}
			}
		}
		break;
	case 2:
		//cylinder
		break;
	case 3:
		//capsule
		break;

	case 7:
		//btBvhTriangleMeshShape
		{

				if(node.hasFn(MFn::kMesh)) {
					MDagPath dagPath;
					MDagPath::getAPathTo(node, dagPath);
					MFnMesh fnMesh(dagPath);
					MFloatPointArray mpoints;
					MFloatVectorArray mnormals;
					MIntArray mtrianglecounts;
					MIntArray mtrianglevertices;
					fnMesh.getPoints(mpoints, MSpace::kObject);
					fnMesh.getNormals(mnormals, MSpace::kObject);
					fnMesh.getTriangles(mtrianglecounts, mtrianglevertices);

					std::vector<vec3f> vertices(mpoints.length());
					std::vector<vec3f> normals(mpoints.length());
					std::vector<unsigned int> indices(mtrianglevertices.length());

					for(size_t i = 0; i < vertices.size(); ++i) {
						vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z);
						normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z);
					}
					for(size_t i = 0; i < indices.size(); ++i) {
						indices[i] = mtrianglevertices[i];
					}
					bool dynamicMesh = false;
					collision_shape = solver_t::create_mesh_shape(&(vertices[0]), vertices.size(), &(normals[0]),
						&(indices[0]), indices.size(),dynamicMesh);
			}
		}
		break;
	case 8:
		//hacd convex decomposition
		{

			{
				if(node.hasFn(MFn::kMesh)) {
					MDagPath dagPath;
					MDagPath::getAPathTo(node, dagPath);
					MFnMesh fnMesh(dagPath);
					MFloatPointArray mpoints;
					MFloatVectorArray mnormals;
					MIntArray mtrianglecounts;
					MIntArray mtrianglevertices;
					fnMesh.getPoints(mpoints, MSpace::kObject);
					fnMesh.getNormals(mnormals, MSpace::kObject);
					fnMesh.getTriangles(mtrianglecounts, mtrianglevertices);

					std::vector<vec3f> vertices(mpoints.length());
					std::vector<vec3f> normals(mpoints.length());
					std::vector<unsigned int> indices(mtrianglevertices.length());

					for(size_t i = 0; i < vertices.size(); ++i) {
						vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z);
						normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z);
					}
					for(size_t i = 0; i < indices.size(); ++i) {
						indices[i] = mtrianglevertices[i];
					}
					bool dynamicMesh = false;
					collision_shape = solver_t::create_hacd_shape(&(vertices[0]), vertices.size(), &(normals[0]),
						&(indices[0]), indices.size(),dynamicMesh);
				}
			}
		}
		break;
	default:
		{
		}
	}

	return collision_shape;
}
Beispiel #17
0
/*

	emits particles with color sampled from specified
	shading node/shading engine

*/
MStatus sampleParticles::doIt( const MArgList& args )
{
	unsigned int i;
	bool shadow = 0;
	bool reuse = 0;

	for ( i = 0; i < args.length(); i++ )
		if ( args.asString(i) == MString("-shadow") || 
			args.asString(i) == MString("-s") )
			shadow = 1;
		else if ( args.asString(i) == MString("-reuse") || 
			args.asString(i) == MString("-r") )
			reuse = 1;
		else
			break;
	if ( args.length() - i < 5 )
	{
		displayError( "Usage: sampleParticles [-shadow|-reuse] particleName <shadingEngine|shadingNode.plug> resX resY scale\n"
			"  Example: sampleParticles -shadow particle1 phong1SG 64 64 10;\n"
			"  Example: sampleParticles particle1 file1.outColor 128 128 5;\n" );
		return MS::kFailure;
	}
	if ( reuse && !shadow )	// can only reuse if shadow is turned on
		reuse = 0;

	MString particleName = args.asString( i );
	MString node = args.asString( i+1 );
	int resX = args.asInt( i+2 );
	int resY = args.asInt( i+3 );
	double scale = args.asDouble( i+4 );

	if ( scale <= 0.0 )
		scale = 1.0;

	MFloatArray uCoord, vCoord;
	MFloatPointArray points;
	MFloatVectorArray normals, tanUs, tanVs;

	if ( resX <= 0 )
		resX = 1;
	if ( resY <= 0 )
		resY = 1;

	MString command( "emit -o " );
	command += particleName;
	char tmp[2048];

	float stepU = (float) (1.0 / resX);
	float stepV = (float) (1.0 / resY);

	// stuff sample data by iterating over grid
	// Y is set to arch along the X axis

	int x, y;
	for ( y = 0; y < resY; y++ )
		for ( x = 0; x < resX; x++ )
		{
			uCoord.append( stepU * x );
			vCoord.append( stepV * y );

			float curY = (float) (sin( stepU * (x) * M_PI )*2.0);

			MFloatPoint curPt(
				(float) (stepU * x * scale),
				curY,
				(float) (stepV * y * scale ));

			MFloatPoint uPt(
				(float) (stepU * (x+1) * scale),
				(float) (sin( stepU * (x+1) * M_PI )*2.0),
				(float) (stepV * y * scale ));

			MFloatPoint vPt(
				(float) (stepU * (x) * scale),
				curY,
				(float) (stepV * (y+1) * scale ));

			MFloatVector du, dv, n;
			du = uPt-curPt;
			dv = vPt-curPt;

			n = dv^du;	// normal is based on dU x dV
			n = n.normal();
			normals.append( n );

			du.normal();
			dv.normal();
			tanUs.append( du );
			tanVs.append( dv );

			points.append( curPt );
		}

	// get current camera's world matrix

	MDagPath cameraPath;
	M3dView::active3dView().getCamera( cameraPath );
	MMatrix mat = cameraPath.inclusiveMatrix();
	MFloatMatrix cameraMat( mat.matrix );

	MFloatVectorArray colors, transps;
	if ( MS::kSuccess == MRenderUtil::sampleShadingNetwork( 
			node, 
			points.length(),
			shadow,
			reuse,

			cameraMat,

			&points,
			&uCoord,
			&vCoord,
			&normals,
			&points,
			&tanUs,
			&tanVs,
			NULL,	// don't need filterSize

			colors,
			transps ) )
	{
		fprintf( stderr, "%u points sampled...\n", points.length() );
		for ( i = 0; i < uCoord.length(); i++ )
		{
			sprintf( tmp, " -pos %g %g %g -at velocity -vv %g %g %g -at rgbPP -vv %g %g %g",
				points[i].x,
				points[i].y,
				points[i].z,

				normals[i].x,
				normals[i].y,
				normals[i].z,

				colors[i].x,
				colors[i].y,
				colors[i].z );

			command += MString( tmp );

			// execute emit command once every 512 samples
			if ( i % 512 == 0 )
			{
				fprintf( stderr, "%u...\n", i );
				MGlobal::executeCommand( command, false, false );
				command = MString( "emit -o " );
				command += particleName;
			}
		}

		if ( i % 512 )
			MGlobal::executeCommand( command, true, true );
	}
	else
	{
		displayError( node + MString(" is not a shading engine!  Specify node.attr or shading group node." ) );
	}

	return MS::kSuccess;
}
//----------------------------------------------------------------------------------------------------------------------
void OceanNode::createGrid(int _resolution, double _time, double _choppiness, MObject& _outputData, MStatus &_status){
    int numTris = (_resolution-1)*(_resolution-1)*2;

    MFloatPointArray vertices;
    MIntArray numFaceVertices;
    MIntArray faceVertices;
    int tris[numTris*3];

    int width = 500;
    int depth = 500;

    // calculate the deltas for the x,z values of our point
    float wStep=(float)width/(float)_resolution;
    float dStep=(float)depth/(float)_resolution;
    // now we assume that the grid is centered at 0,0,0 so we make
    // it flow from -w/2 -d/2
    float xPos=-((float)width/2.0);
    float zPos=-((float)depth/2.0);

    // now loop from top left to bottom right and generate points

    m_ocean->update(_time);

    float2* heights = m_ocean->getHeights();
    float2* chopXArray = m_ocean->getChopX();
    float2* chopZArray = m_ocean->getChopZ();

    // Sourced form Jon Macey's NGL library
    for(int z=0; z<_resolution; z++){
        for(int x=0; x<_resolution; x++){
            // Divide the values we get out of the FFT by 50000 to get them in a suitable range
            float height = heights[z * _resolution + x].x/50000.0;
            float chopX = _choppiness * chopXArray[z * _resolution + x].x/50000.0;
            float chopZ= _choppiness * chopZArray[z * _resolution + x].x/50000.0;
            int sign = 1.0;
            if ((x+z) % 2 != 0){
                sign = -1.0;
            }
            vertices.append((xPos + (chopX * sign)), height * sign, (zPos + (chopZ * sign)));
            // calculate the new position
            zPos+=dStep;
        }
        // now increment to next z row
        xPos+=wStep;
        // we need to re-set the xpos for new row
        zPos=-((float)depth/2.0);
    }

    // Array for num vertices in each face
    for (int i=0; i<numTris; i++){
        numFaceVertices.append(3);
    }

    // Assign vertices to each face
    int fidx = 0;
    for (int i=0; i<(_resolution-1); i++){
        for (int j=0; j<(_resolution-1); j++){
            tris[fidx*3+0] = (i+1)*_resolution+j;
            tris[fidx*3+1] = i*_resolution+j+1;
            tris[fidx*3+2] = i*_resolution+j;
            fidx++;
            tris[fidx*3+0] = (i+1)*_resolution+j;
            tris[fidx*3+1] = (i+1)*_resolution+j+1;
            tris[fidx*3+2] = i*_resolution+j+1;
            fidx++;
        }
    }

    for (uint i=0; i<sizeof(tris)/sizeof(int); i++){
        faceVertices.append(tris[i]);
    }

   MFnMesh grid;
   grid.create(vertices.length(), numTris, vertices, numFaceVertices, faceVertices, _outputData, &_status);
}
void collisionShapeNode::computeCollisionShape(const MPlug& plug, MDataBlock& data)
{
  //  std::cout << "collisionShapeNode::computeCollisionShape" << std::endl;

    MObject thisObject(thisMObject());

    MPlug plgInShape(thisObject, ia_shape);

    MPlug plgType(thisObject, ia_type);
    int type;
    plgType.getValue(type);
    switch(type) {
    case 0:  
        {
        //convex hull
        MPlugArray plgaConnectedTo;
        plgInShape.connectedTo(plgaConnectedTo, true, true);
        if(plgaConnectedTo.length() > 0) {
            MObject node = plgaConnectedTo[0].node();
            if(node.hasFn(MFn::kMesh)) {
                MDagPath dagPath;
                MDagPath::getAPathTo(node, dagPath);
                MFnMesh fnMesh(dagPath);
                MFloatPointArray mpoints;
                MFloatVectorArray mnormals;
                MIntArray mtrianglecounts;
                MIntArray mtrianglevertices;
                fnMesh.getPoints(mpoints, MSpace::kObject);
                fnMesh.getNormals(mnormals, MSpace::kObject);
                fnMesh.getTriangles(mtrianglecounts, mtrianglevertices);

                std::vector<vec3f> vertices(mpoints.length());
                std::vector<vec3f> normals(mpoints.length());
                std::vector<unsigned int> indices(mtrianglevertices.length());

                for(size_t i = 0; i < vertices.size(); ++i) {
                    vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z);
                    normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z);
                }
                for(size_t i = 0; i < indices.size(); ++i) {
                    indices[i] = mtrianglevertices[i];
                }
                m_collision_shape = solver_t::create_convex_hull_shape(&(vertices[0]), vertices.size(), &(normals[0]),
                                                                       &(indices[0]), indices.size());
            }
        }
        }
        break;
    case 1:
        //mesh
        {
        //convex hull
        MPlugArray plgaConnectedTo;
        plgInShape.connectedTo(plgaConnectedTo, true, true);
        if(plgaConnectedTo.length() > 0) {
            MObject node = plgaConnectedTo[0].node();
            if(node.hasFn(MFn::kMesh)) {
                MDagPath dagPath;
                MDagPath::getAPathTo(node, dagPath);
                MFnMesh fnMesh(dagPath);
                MFloatPointArray mpoints;
                MFloatVectorArray mnormals;
                MIntArray mtrianglecounts;
                MIntArray mtrianglevertices;
                fnMesh.getPoints(mpoints, MSpace::kObject);
                fnMesh.getNormals(mnormals, MSpace::kObject);
                fnMesh.getTriangles(mtrianglecounts, mtrianglevertices);

                std::vector<vec3f> vertices(mpoints.length());
                std::vector<vec3f> normals(mpoints.length());
                std::vector<unsigned int> indices(mtrianglevertices.length());

                for(size_t i = 0; i < vertices.size(); ++i) {
                    vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z);
                    normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z);
                }
                for(size_t i = 0; i < indices.size(); ++i) {
                    indices[i] = mtrianglevertices[i];
                }
                m_collision_shape = solver_t::create_mesh_shape(&(vertices[0]), vertices.size(), &(normals[0]),
                                                                &(indices[0]), indices.size());
            }
        }
        }
        break;
    case 2:
        //cylinder
        break;
    case 3:
        //capsule
        break;
    case 4:
        //box
        m_collision_shape = solver_t::create_box_shape();
        break;
    case 5:
        //sphere
        m_collision_shape = solver_t::create_sphere_shape();
        break;
    case 6:
        //plane
        m_collision_shape = solver_t::create_plane_shape();
        break;
    }

    assert(m_collision_shape);

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

	MFloatPointArray points;

	MFloatVectorArray normals;

	MSpace::Space world_space = MSpace::kTransform;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return true;
}
bool		preFrame(
				const MObject		hairSystem,
				const double		curTime,
				void				**privateData )
{
	MStatus status;

	// If you need want to perform any preprocessing on your collision
	// objects pre-frame, do it here. One option for storing the pre-
	// processed data is on a typed attribute on the hairSystem node.
	// That data could be fetched and updated here.
	//
	// In our example, we'll just compute a bounding box here and NOT use
	// attribute storage. That is an exercise for the reader.
	//
	MFnDependencyNode fnHairSystem( hairSystem, &status );
	CHECK_MSTATUS_AND_RETURN( status, false );
	fprintf( stderr,
			"preFrame: calling hairSystem node=`%s', time=%g\n",
			fnHairSystem.name().asChar(), curTime );
	MObjectArray	cols;
	MIntArray		logIdxs;
	CHECK_MSTATUS_AND_RETURN( MHairSystem::getCollisionObject( hairSystem,
			cols, logIdxs ), false );
	int nobj = cols.length();

	// Allocate private data.
	// This allows us to pre-process data on a pre-frame basis to avoid
	// calculating it per hair inside the collide() call. As noted earlier
	// we could allocate this in preFrame() and hang it off the hairSystem
	// node via a dynamic attribute.
	// Instead we'll allocate it here.
	//
	COLLISION_INFO *collisionInfo = (COLLISION_INFO *) malloc(
			sizeof( COLLISION_INFO ) );
	collisionInfo->objs = (COLLISION_OBJ *) malloc(
			nobj * sizeof( COLLISION_OBJ ) );
	collisionInfo->numObjs = nobj;

	// Create the private data that we'll make available to the collide
	// method. The data should actually be stored in a way that it can
	// be cleaned up (such as storing the pointer on the hairSystem node
	// using a dynamic attribute). As it stands right now, there is a
	// memory leak with this plug-in because the memory we're allocating
	// for the private data is never cleaned up.
	//
	// Note that when using the dynamic attribute approach, it is still
	// wise to set *privateData because this avoids the need to look up
	// the plug inside the collide() routine which is a high-traffic
	// method.
	//
	*privateData = (void *) collisionInfo;

	// Loop through the collision objects and pre-process, storing the
	// results in the collisionInfo structure.
	//
	int	   obj;
	for ( obj = 0; obj < nobj; ++obj ) {
		// Get the ith collision geometry we are connected to.
		//
		MObject colObj = cols[obj];

		// Get the DAG path for the collision object so we can transform
		// the vertices to world space.
		//
		MFnDagNode fnDagNode( colObj, &status );
		CHECK_MSTATUS_AND_RETURN( status, false );
		MDagPath path;
		status = fnDagNode.getPath( path );
		CHECK_MSTATUS_AND_RETURN( status, false );
		MFnMesh fnMesh( path, &status );
		if ( MS::kSuccess != status ) {
			fprintf( stderr,
					"%s:%d: collide was not passed a valid mesh shape\n",
					__FILE__, __LINE__ );
			return( false );
		}

		// Get the vertices of the object transformed to world space.
		//
		MFloatPointArray	verts;
		status = fnMesh.getPoints( verts, MSpace::kWorld );
		CHECK_MSTATUS_AND_RETURN( status, false );

		// Compute the bounding box for the collision object.
		// As this is a quick and dirty demo, we'll just support collisions
		// between hair and the bbox.
		//
		double minx, miny, minz, maxx, maxy, maxz, x, y, z;
		minx = maxx = verts[0].x;
		miny = maxy = verts[0].y;
		minz = maxz = verts[0].z;
		int nv = verts.length();
		int i;
		for ( i = 1; i < nv; ++i ) {
			x = verts[i].x;
			y = verts[i].y;
			z = verts[i].z;

			if ( x < minx ) {
				minx = x;
			}
			if ( y < miny ) {
				miny = y;
			}
			if ( z < minz ) {
				minz = z;
			}

			if ( x > maxx ) {
				maxx = x;
			}
			if ( y > maxy ) {
				maxy = y;
			}
			if ( z > maxz ) {
				maxz = z;
			}
		}

		// Store this precomputed informantion into our private data
		// structure.
		//
		collisionInfo->objs[obj].numVerts = nv;
		collisionInfo->objs[obj].minx = minx;
		collisionInfo->objs[obj].miny = miny;
		collisionInfo->objs[obj].minz = minz;
		collisionInfo->objs[obj].maxx = maxx;
		collisionInfo->objs[obj].maxy = maxy;
		collisionInfo->objs[obj].maxz = maxz;
		fprintf( stderr, "Inside preFrameInit, bbox=%g %g %g %g %g %g\n",
				minx,miny,minz,maxx,maxy,maxz);
	}

	return( true );
}
Beispiel #22
0
MStatus sseDeformer::compute(const MPlug& plug, MDataBlock& data)
{
    MStatus status;
    if (plug.attribute() != outputGeom) {
        printf("Ignoring requested plug\n");
        return status;
    }
    unsigned int index = plug.logicalIndex();
    MObject thisNode = this->thisMObject();

    // get input value
    MPlug inPlug(thisNode,input);
    inPlug.selectAncestorLogicalIndex(index,input);
    MDataHandle hInput = data.inputValue(inPlug, &status);
    MCheckStatus(status, "ERROR getting input mesh\n");

    // get the input geometry
    MDataHandle inputData = hInput.child(inputGeom);
    if (inputData.type() != MFnData::kMesh) {
        printf("Incorrect input geometry type\n");
        return MStatus::kFailure;
    }

    MObject iSurf = inputData.asMesh() ;
    MFnMesh inMesh;
    inMesh.setObject( iSurf ) ;

    MDataHandle outputData = data.outputValue(plug);
    outputData.copy(inputData);
    if (outputData.type() != MFnData::kMesh) {
        printf("Incorrect output mesh type\n");
        return MStatus::kFailure;
    }

    MObject oSurf = outputData.asMesh() ;
    if(oSurf.isNull()) {
        printf("Output surface is NULL\n");
        return MStatus::kFailure;
    }

    MFnMesh outMesh;
    outMesh.setObject( oSurf ) ;
    MCheckStatus(status, "ERROR setting points\n");

    // get all points at once for demo purposes. Really should get points from the current group using iterator
    MFloatPointArray pts;
    outMesh.getPoints(pts);

    int nPoints = pts.length();

    MDataHandle envData = data.inputValue(envelope, &status);
    float env = envData.asFloat();

    MDataHandle sseData = data.inputValue(sseEnabled, &status);
    bool sseEnabled = (bool) sseData.asBool();

    // NOTE: Using MTimer and possibly other classes disables
    // autovectorization with Intel <=10.1 compiler on OSX and Linux!!
    // Must compile this function with -fno-exceptions on OSX and
    // Linux to guarantee autovectorization is done. Use -fvec_report2
    // to check for vectorization status messages with Intel compiler.
    MTimer timer;
    timer.beginTimer();

    if(sseEnabled) {

        // Innter loop will autovectorize. Around 3x faster than the
        // loop below it. It would be faster if first element was
        // guaranteed to be aligned on 16 byte boundary.
        for(int i=0; i<nPoints; i++) {
            float* ptPtr = &pts[i].x;
            for(int j=0; j<4; j++) {
                ptPtr[j] = env * (cosf(ptPtr[j]) * sinf(ptPtr[j]) * tanf(ptPtr[j]));
            }
        }

    } else {

        // This inner loop will not autovectorize.
        for(int i=0; i<nPoints; i++) {
            MFloatPoint& pt = pts[i];
            for(int j=0; j<3; j++) {
                pt[j] = env * (cosf(pt[j]) * sinf(pt[j]) * tanf(pt[j]));
            }

        }
    }

    timer.endTimer();
    if(sseEnabled) {
        printf("SSE enabled, runtime %f\n", timer.elapsedTime());
    } else {
        printf("SSE disabled, runtime %f\n", timer.elapsedTime());
    }

    outMesh.setPoints(pts);

    return status;
}
Beispiel #23
0
// the arrays being passed in are assumed to be empty
void MayaMeshWriter::fillTopology(
    std::vector<float> & oPoints,
    std::vector<Alembic::Util::int32_t> & oFacePoints,
    std::vector<Alembic::Util::int32_t> & oPointCounts)
{
    MStatus status = MS::kSuccess;
    MFnMesh lMesh( mDagPath, &status );
    if ( !status )
    {
        MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" );
    }

    MFloatPointArray pts;

    lMesh.getPoints(pts);

    if (pts.length() < 3 && pts.length() > 0)
    {
        MString err = lMesh.fullPathName() +
            " is not a valid mesh, because it only has ";
        err += pts.length();
        err += " points.";
        MGlobal::displayError(err);
        return;
    }

    unsigned int numPolys = lMesh.numPolygons();

    if (numPolys == 0)
    {
        MGlobal::displayWarning(lMesh.fullPathName() + " has no polygons.");
        return;
    }

    unsigned int i;
    int j;

    oPoints.resize(pts.length() * 3);

    // repack the float
    for (i = 0; i < pts.length(); i++)
    {
        size_t local = i * 3;
        oPoints[local] = pts[i].x;
        oPoints[local+1] = pts[i].y;
        oPoints[local+2] = pts[i].z;
    }

    /*
        oPoints -
        oFacePoints - vertex list
        oPointCounts - number of points per polygon
    */

    MIntArray faceArray;

    for (i = 0; i < numPolys; i++)
    {
        lMesh.getPolygonVertices(i, faceArray);

        if (faceArray.length() < 3)
        {
            MGlobal::displayWarning("Skipping degenerate polygon");
            continue;
        }

        // write backwards cause polygons in Maya are in a different order
        // from Renderman (clockwise vs counter-clockwise?)
        int faceArrayLength = faceArray.length() - 1;
        for (j = faceArrayLength; j > -1; j--)
        {
            oFacePoints.push_back(faceArray[j]);
        }

        oPointCounts.push_back(faceArray.length());
    }
}
Beispiel #24
0
MStatus intersectCmd::doIt(const MArgList& args)

// Description:
// 		Determine if the ray from the spotlight intersects the mesh.
//		If it does, display the intersection points.

{
	MStatus stat = MStatus::kSuccess;

	if (args.length() != 2) 
	{
		MGlobal::displayError("Need 2 items!");
		return MStatus::kFailure;
	}

	MSelectionList activeList;
	int i;
	
	for ( i = 0; i < 2; i++)
	{
		MString strCurrSelection;
		stat = args.get(i, strCurrSelection);
		if (MStatus::kSuccess == stat) activeList.add(strCurrSelection);
	}

	MItSelectionList iter(activeList);
	MFnSpotLight fnLight;  
	MFnMesh fnMesh;
	MFnDagNode dagNod;
	MFnDependencyNode fnDN;

	float fX = 0;
	float fY = 0;
	float fZ = 0;

	for ( ; !iter.isDone(); iter.next() )
	{
		MObject tempObjectParent, tempObjectChild;
		iter.getDependNode(tempObjectParent);

		if (tempObjectParent.apiType() == MFn::kTransform)
		{
			dagNod.setObject(tempObjectParent);
			tempObjectChild = dagNod.child(0, &stat);
		}

		// check what type of object is selected
		if (tempObjectChild.apiType() == MFn::kSpotLight)
		{
			MDagPath pathToLight;
			MERR_CHK(MDagPath::getAPathTo(tempObjectParent, pathToLight), "Couldn't get a path to the spotlight");
			MERR_CHK(fnLight.setObject(pathToLight), "Failure on assigning light");
			
			stat = fnDN.setObject(tempObjectParent);

			MPlug pTempPlug = fnDN.findPlug("translateX", &stat);
			if (MStatus::kSuccess == stat)
			{
				pTempPlug.getValue(fX);
			}

			pTempPlug = fnDN.findPlug("translateY", &stat);
			if (MStatus::kSuccess == stat)
			{
				pTempPlug.getValue(fY);
			}

			pTempPlug = fnDN.findPlug("translateZ", &stat);
			if (MStatus::kSuccess == stat)
			{
				pTempPlug.getValue(fZ);
			}	
		}
		else if (tempObjectChild.apiType() == MFn::kMesh)
		{
			MDagPath pathToMesh;
			MERR_CHK(MDagPath::getAPathTo(tempObjectChild, pathToMesh), "Couldn't get a path to the spotlight");
			MERR_CHK(fnMesh.setObject(pathToMesh), "Failure on assigning light");	
		}
		else
		{
			MGlobal::displayError("Need a spotlight and a mesh");
			return MStatus::kFailure;
		}
	}

	MFloatPoint fpSource(fX, fY, fZ);
	MFloatVector fvRayDir = fnLight.lightDirection(0, MSpace::kWorld, &stat);
	MFloatPoint hitPoint;
	
	MMeshIsectAccelParams mmAccelParams = fnMesh.autoUniformGridParams();
	
	float fHitRayParam, fHitBary1, fHitBary2;
	int nHitFace, nHitTriangle;

	// a large positive number is used here for the maxParam parameter
	bool bAnyIntersection = fnMesh.anyIntersection(fpSource, fvRayDir, NULL, NULL, false,				MSpace::kWorld, (float)9999, false, &mmAccelParams, hitPoint, &fHitRayParam, &nHitFace, &nHitTriangle, 		&fHitBary1, &fHitBary2, (float)1e-6, &stat);
	
	if (! bAnyIntersection) 
	{
		MGlobal::displayInfo("There were no intersection points detected");
		return stat;
	}

	MFloatPointArray hitPoints;
	MFloatArray faHitRayParams;
	MIntArray iaHitFaces;
	MIntArray iaHitTriangles;
	MFloatArray faHitBary1;
	MFloatArray faHitBary2;

	bool bAllIntersections = fnMesh.allIntersections(fpSource, fvRayDir, NULL, NULL, false, MSpace::kWorld, 9999, false, NULL, false, hitPoints, &faHitRayParams, &iaHitFaces, &iaHitTriangles, &faHitBary1, &faHitBary2, 0.000001f, &stat);
	
	if (! bAllIntersections)
	{
		MGlobal::displayInfo("Error getting all intersections");
		return stat;
	}
	
	// check how many intersections are found
	unsigned int nNumberHitPoints = hitPoints.length();

	if (! nNumberHitPoints)
	{
		MGlobal::displayInfo("No hit points detected");
		return MStatus::kSuccess;
	}

	// Intersection exists; display intersections as spheres
	MString strCommandString = "string $strBall[] = `polySphere -r 0.5`;";
	strCommandString += "$strBallName = $strBall[0];";

	float x = 0;
	float y = 0;
	float z = 0;

	for (i = 0; i < (int)nNumberHitPoints; i++)
	{
		// get the points
		x = hitPoints[i][0];
		y = hitPoints[i][1];
		z = hitPoints[i][2];

		// execute some MEL to create a small sphere
		strCommandString += "setAttr ($strBallName + \".tx\") ";
		strCommandString += x;
		strCommandString += ";";

		strCommandString += "setAttr ($strBallName + \".ty\") ";
		strCommandString += y;
		strCommandString += ";";

		strCommandString += "setAttr ($strBallName + \".tz\") ";
		strCommandString += z;
		strCommandString += ";";

		MGlobal::executeCommand(strCommandString);
	}

	return stat;
}
Beispiel #25
0
MStatus testNobjectNode::compute(const MPlug &plug, MDataBlock &data)
{
	MStatus stat;

	if ( plug == outputGeom )
	{
		MObject inMeshObj = data.inputValue(inputGeom).asMesh();
		
        cerr<<"pull on outputGeom\n";

		MFnMeshData meshDataFn;
        MFnMesh inputMesh(inMeshObj);
		MObject newMeshObj = meshDataFn.create();
		MFnMesh newMeshFn;
		newMeshFn.copy( inMeshObj, newMeshObj );        

        //get the value of the currentTime so it can correctly dirty the
        //startState, currentState.
        data.inputValue(currentTime).asTime();

		// pull on next state.  This will cause the solver to pull on either
        // the startState or the currentState, depending on the time of solve.
        // When we return the state to the solver, it will do the solve and update
        // The N Object data directly.
		MObject nextNObj = data.inputValue(nextState).data();
        MFloatPointArray pts;        

        //At this point the N Object's internal state should have been updated
        //by the solver.  Read it out and set the output mesh.
        fNObject.getPositions(pts);
        if(pts.length() == (unsigned int) inputMesh.numVertices()) {
            newMeshFn.setPoints(pts);
        }

		newMeshFn.setObject( newMeshObj );

		data.outputValue(outputGeom).set(newMeshObj);
		data.setClean(plug);

	}
	if ( plug == currentState )
	{               
        MFnNObjectData outputData;
        MObject mayaNObjectData = outputData.create();
        outputData.setObject(mayaNObjectData);
        
        outputData.setObjectPtr(&fNObject);        
        outputData.setCached(false);

        MDataHandle currStateOutputHandle = data.outputValue(currentState);
        currStateOutputHandle.set(outputData.object());
	  
        cerr<<"pull on currentState\n";
	}
	if ( plug == startState )
	{
	    int ii,jj;
        // initialize MnCloth
        MObject inMeshObj = data.inputValue(inputGeom).asMesh();
				
        MFnMesh inputMesh(inMeshObj);		

        int numPolygons = inputMesh.numPolygons();
        int * faceVertCounts = new int[numPolygons];
                
        
        int facesArrayLength = 0;
        for(ii=0;ii<numPolygons;ii++) {
            MIntArray verts;
            inputMesh.getPolygonVertices(ii,verts);
            faceVertCounts[ii] = verts.length();
            facesArrayLength += verts.length();
        }
        int * faces = new int[facesArrayLength];
        int currIndex = 0;
        for(ii=0;ii<numPolygons;ii++) {
            MIntArray verts;
            inputMesh.getPolygonVertices(ii,verts);
            for(jj=0;jj<(int)verts.length();jj++) {
                faces[currIndex++] = verts[jj];
            }
        }

        int numEdges = inputMesh.numEdges();
        int * edges = new int[2*numEdges];
        currIndex = 0;
        for(ii=0;ii<numEdges;ii++) {
            int2 edge;
            inputMesh.getEdgeVertices(ii,edge);
            edges[currIndex++] = edge[0];
            edges[currIndex++] = edge[1];
        }

        // When you are doing the initialization, the first call must to be setTopology().  All other
        // calls must come after this.
        fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges );
        delete[] faceVertCounts;
        delete[] faces;
        delete[] edges;        


        unsigned int numVerts = 0;
        numVerts = inputMesh.numVertices();        

        MFloatPointArray vertexArray;
        inputMesh.getPoints(vertexArray);
        fNObject.setPositions(vertexArray,true);

        MFloatPointArray velocitiesArray;
        velocitiesArray.setLength(numVerts);
        for(ii=0;ii<(int)numVerts;ii++) {
            velocitiesArray[ii].x = 0.0f;
            velocitiesArray[ii].y = 0.0f;
            velocitiesArray[ii].z = 0.0f;
            velocitiesArray[ii].w = 0.0f;
        }
        fNObject.setVelocities(velocitiesArray);
        fNObject.setThickness(0.05f);
        fNObject.setInverseMass(1.0f);
        fNObject.setBounce(0.0f);
        fNObject.setFriction(0.1f);
        fNObject.setDamping(0.0f);
        fNObject.setBendResistance(0.0f);
        fNObject.setMaxIterations(100);        
        fNObject.setMaxSelfCollisionIterations(100);
        fNObject.setStretchAndCompressionResistance(20.0f,10.0f);
        fNObject.setSelfCollisionFlags(false);
        fNObject.setCollisionFlags(true);        	    

        
        MFnNObjectData outputData;
        MObject mayaNObjectData = outputData.create();
        outputData.setObject(mayaNObjectData);
        
        outputData.setObjectPtr(&fNObject);        
        outputData.setCached(false);

        MDataHandle startStateOutputHandle = data.outputValue(startState);
        startStateOutputHandle.set(outputData.object());

        cerr<<"pull on startState\n";
	}
	else {
		stat = MS::kUnknownParameter;
	}
	return stat;
}