Beispiel #1
0
MFloatPointArray ropeGenerator::createHalfRope( int pointsCount, float radius )
{
	MFloatPointArray points;
	MPoint baseVector( 1,0,0 );
	baseVector =  baseVector * radius;
	points.append( MFloatPoint( baseVector.x, baseVector.y, baseVector.z, 1.0 ) );
	float fbaseAngle = 180.0 / float( pointsCount );
	for (int d = 1; d < pointsCount; d++)
	{
		if (d == 1)
		{
			MAngle baseAngle((fbaseAngle * 0.25), MAngle::kDegrees  );
			MVector vVector( baseVector );
			vVector = vVector.rotateBy( MVector::kYaxis, baseAngle.asRadians() );
			points.append( MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) );
		}
		MAngle baseAngle((fbaseAngle * float( d ) ), MAngle::kDegrees  );
		MVector vVector( baseVector );
		vVector = vVector.rotateBy( MVector::kYaxis, baseAngle.asRadians() );
		points.append( MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) );
		if ( d == pointsCount - 1 )
		{
			MAngle baseAngle((fbaseAngle * ( d + 0.75 )), MAngle::kDegrees  );
			MVector vVector( baseVector );
			vVector = vVector.rotateBy( MVector::kYaxis, baseAngle.asRadians() );
			points.append( MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) );
		}

	}
	return points;
}
Beispiel #2
0
MObject animCube::createMesh(const MTime& time,
							  MObject& outData,
							  MStatus& stat)

{
	int				numVertices, frame;
	float			cubeSize;
	MFloatPointArray		points;
	MFnMesh			meshFS;

	// Scale the cube on the frame number, wrap every 10 frames.
	frame = (int)time.as( MTime::kFilm );
	if (frame == 0)
	  frame = 1;
	cubeSize		    		= 0.5f * (float)( frame % 10);

	const int numFaces			= 6;
	numVertices					= 8;
	const int numFaceConnects	= 24;

	MFloatPoint vtx_1( -cubeSize, -cubeSize, -cubeSize );
	MFloatPoint vtx_2(  cubeSize, -cubeSize, -cubeSize );
	MFloatPoint vtx_3(  cubeSize, -cubeSize,  cubeSize );
	MFloatPoint vtx_4( -cubeSize, -cubeSize,  cubeSize );
	MFloatPoint vtx_5( -cubeSize,  cubeSize, -cubeSize );
	MFloatPoint vtx_6( -cubeSize,  cubeSize,  cubeSize );
	MFloatPoint vtx_7(  cubeSize,  cubeSize,  cubeSize );
	MFloatPoint vtx_8(  cubeSize,  cubeSize, -cubeSize );
	points.append( vtx_1 );
	points.append( vtx_2 );
	points.append( vtx_3 );
	points.append( vtx_4 );
	points.append( vtx_5 );
	points.append( vtx_6 );
	points.append( vtx_7 );
	points.append( vtx_8 );

	// Set up an array containing the number of vertices
	// for each of the 6 cube faces (4 verticies per face)
	//
	int face_counts[numFaces] = { 4, 4, 4, 4, 4, 4 };
	MIntArray faceCounts( face_counts, numFaces );

	// Set up and array to assign vertices from points to each face 
	//
	int face_connects[ numFaceConnects ] = {	0, 1, 2, 3,
												4, 5, 6, 7,
												3, 2, 6, 5,
												0, 3, 5, 4,
												0, 4, 7, 1,
												1, 7, 6, 2	};
	MIntArray faceConnects( face_connects, numFaceConnects );

	MObject newMesh = meshFS.create(numVertices, numFaces,
									points, faceCounts, faceConnects,
									outData, &stat);

	return newMesh;
}
Beispiel #3
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 #4
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;
}
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 #6
0
void ropeGenerator::createCriclePoints( int pointsCount, MMatrix bMatrix, MFloatPointArray &points, float radius )
{
	MPoint baseVector2( radius,0,0 );
	baseVector2 = baseVector2 * bMatrix;
	points.append( MFloatPoint( baseVector2.x, baseVector2.y, baseVector2.z, 1.0 ) );
	float baseAngle = 360.0f / float( pointsCount );
	for (int d = 1; d < pointsCount; d++ )
	{
		MVector vVector( radius,0,0 );
		vVector = vVector.rotateBy( MVector::kYaxis, 
							MAngle( baseAngle * float( d ),MAngle::kDegrees).asRadians() );
		MPoint point( vVector.x, vVector.y, vVector.z );
		point = point * bMatrix;
		points.append( MFloatPoint( point.x, point.y, point.z, 1.0 ));
	}

}
MObject AniMesh::readFrame(const MTime& time,MObject& outData,MStatus& stat)

{
	MFloatPointArray points;
	MFnMesh         meshFS;
	int frame = (int)time.as( MTime::kFilm );
	if (frame == 0)
		frame = 1; 
	vector<size_t> face_v;
	vector<double> points_v;
	char cfilename[256];
	sprintf(cfilename, "%s%d.vrml",import_prefix.c_str(),frame);
	//sprintf(cfilename, "%s%d.vrml",import_prefix.c_str(),0);
	string filename = string(cfilename);
	fstream fp;
	fp.open(filename,ios::in);
	if (fp)
	{
		ImportVrml2 (filename, face_v, points_v);
	}else{
		sprintf(cfilename, "%s%d.vrml",import_prefix.c_str(),0);
		string filename = string(cfilename); 
		ImportVrml2(filename,face_v,points_v);
	}
	
	size_t numVertices = points_v.size()/3;
	size_t numFaces = face_v.size()/3;
	for(vector<double>::const_iterator it = points_v.begin();it != points_v.end();it+=3) {
		MFloatPoint vtx(*it,*(it+1),*(it+2));
		points.append(vtx);
	}

	vector<int> face_count;
	for(int i=0;i<numFaces;i++) {
		face_count.push_back(3);
	}
	MIntArray faceCounts(&face_count[0],numFaces);

	vector<int> face_connects;
	face_connects.resize(face_v.size());
	for(int i=0;i<face_v.size();++i)
	{
		face_connects[i] = face_v[i];
	}

	MIntArray faceConnects( &face_connects[0], face_connects.size() );
	MObject newMesh=meshFS.create(numVertices, numFaces,points, faceCounts, faceConnects,outData,&stat);
	return newMesh;

}
Beispiel #8
0
void ropeGenerator::createRopesRings( int ropesCount, MMatrix bMatrix, MFloatPointArray &points, int pointsCount, float ropeStrength, float radius )
{
	MAngle angle( (180.0/ ropesCount ), MAngle::kDegrees );
	float distanceToMoveRope = cos( angle.asRadians() );
	float singleRopeRadius = sin( angle.asRadians() );
	float baseAngle = 360.0f / float( ropesCount ); 
	for ( int d = 1; d < ropesCount + 1; d++)
	{
		MFloatPointArray ropePoints( createHalfRope( pointsCount, singleRopeRadius ) );
		for ( int ropP = 0; ropP < ropePoints.length(); ropP++)
		{
			MFloatPoint ropPoint( ropePoints[ropP] );
			MVector ropV( ropPoint.x, ropPoint.y, ropPoint.z * ropeStrength );
			ropV = ropV + MVector( 0,0,-distanceToMoveRope );
			ropV = ropV.rotateBy( MVector::kYaxis, MAngle( baseAngle * float( d ), MAngle::kDegrees).asRadians() );
			MPoint ropFinalPoint( ropV * radius );
			ropFinalPoint = ropFinalPoint * bMatrix;
			points.append( MFloatPoint( ropFinalPoint.x, ropFinalPoint.y, ropFinalPoint.z ) );
		}
	}
}
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 #10
0
MStatus meshOpFty::doLightningSplit(MFnMesh& meshFn)
//
//	Description:
//		Performs the kSplitLightning operation on the selected mesh
//      and components. It may not split all the selected components.
//
{
	unsigned int i, j;

	// These are the input arrays to the split function. The following
	// algorithm fills them in with the arguments for a continuous
	// split that goes through some of the selected faces.
	//
	MIntArray placements;
	MIntArray edgeIDs;
	MFloatArray edgeFactors;
	MFloatPointArray internalPoints;
	
	// The following array is going to be used to determine which faces
	// have been split. Since the split function can only split faces
	// which are adjacent to the earlier face, we may not split
	// all the faces
	//
	bool* faceTouched = new bool[fComponentIDs.length()];
	for (i = 0; i < fComponentIDs.length(); ++i)
		faceTouched[i] = false;
	
	// We need a starting point. For this example, the first face in
	// the component list is picked. Also get a polygon iterator
	// to this face.
	// 
	MItMeshPolygon itPoly(fMesh);
	for (; !itPoly.isDone(); itPoly.next())
	{
		if (fComponentIDs[0] == itPoly.index()) break;
	}
	if (itPoly.isDone())
	{
		// Should never happen.
		//
		delete [] faceTouched;
		return MS::kFailure;
	}
	
	// In this example, edge0 is called the starting edge and
	// edge1 is called the destination edge. This algorithm will split
	// each face from the starting edge to the destination edge
	// while going through two inner points inside each face.
	//
	int edge0, edge1;
	MPoint innerVert0, innerVert1;
	int nextFaceIndex = 0;
	
	// We need a starting edge. For this example, the first edge in the
	// edge list is used.
	//
	MIntArray edgeList;
	itPoly.getEdges(edgeList);
	edge0 = edgeList[0];
	
	bool done = false;
	while (!done)
	{
		// Set this face as touched so that we don't try to split it twice
		//
		faceTouched[nextFaceIndex] = true;
		
		// Get the current face's center. It is used later in the
		// algorithm to calculate inner vertices.
		//
		MPoint faceCenter = itPoly.center();
			
		// Iterate through the connected faces to find an untouched,
		// selected face and get the ID of the shared edge. That face
		// will become the next face to be split.
		//
		MIntArray faceList;
		itPoly.getConnectedFaces(faceList);
		nextFaceIndex = -1;
		for (i = 0; i < fComponentIDs.length(); ++i)
		{
			for (j = 0; j < faceList.length(); ++j)
			{
				if (fComponentIDs[i] == faceList[j] && !faceTouched[i])
				{
					nextFaceIndex = i;
					break;
				}
			}
			if (nextFaceIndex != -1) break;
		}
		
		if (nextFaceIndex == -1)
		{
			// There is no selected and untouched face adjacent to this
			// face, so this algorithm is done. Pick the first edge that
			// is not the starting edge as the destination edge.
			//
			done = true;
			edge1 = -1;
			for (i = 0; i < edgeList.length(); ++i)
			{
				if (edgeList[i] != edge0)
				{
					edge1 = edgeList[i];
					break;
				}
			}
			if (edge1 == -1)
			{
				// This should not happen, since there should be more than
				// one edge for each face
				//
				delete [] faceTouched;
				return MS::kFailure;
			}
		}
		else
		{
			// The next step is to find out which edge is shared between
			// the two faces and use it as the destination edge. To do
			// that, we need to iterate through the faces and get the
			// next face's list of edges.
			//
			itPoly.reset();
			for (; !itPoly.isDone(); itPoly.next())
			{
				if (fComponentIDs[nextFaceIndex] == itPoly.index()) break;
			}
			if (itPoly.isDone()) 
			{
				// Should never happen.
				//
				delete [] faceTouched;
				return MS::kFailure;
			}
			
			// Look for a common edge ID in the two faces edge lists
			//
			MIntArray nextFaceEdgeList;
			itPoly.getEdges(nextFaceEdgeList);
			edge1 = -1;
			for (i = 0; i < edgeList.length(); ++i)
			{
				for (j = 0; j < nextFaceEdgeList.length(); ++j)
				{
					if (edgeList[i] == nextFaceEdgeList[j])
					{
						edge1 = edgeList[i];
						break;
					}
				}
				if (edge1 != -1) break;
			}
			if (edge1 == -1)
			{
				// Should never happen.
				//
				delete [] faceTouched;
				return MS::kFailure;
			}
			
			// Save the edge list for the next iteration
			//
			edgeList = nextFaceEdgeList;
		}
		
		// Calculate the two inner points that the split will go through.
		// For this example, the midpoints between the center and the two
		// farthest vertices of the edges are used.
		//
		// Find the 3D positions of the edges' vertices
		//
		MPoint edge0vert0, edge0vert1, edge1vert0, edge1vert1;
		MItMeshEdge itEdge(fMesh, MObject::kNullObj );
		for (; !itEdge.isDone(); itEdge.next())
		{
			if (itEdge.index() == edge0)
			{
				edge0vert0 = itEdge.point(0);
				edge0vert1 = itEdge.point(1);
			}
			if (itEdge.index() == edge1)
			{
				edge1vert0 = itEdge.point(0);
				edge1vert1 = itEdge.point(1);
			}
		}
		
		// Figure out which are the farthest from each other
		//
		double distMax = edge0vert0.distanceTo(edge1vert0);
		MPoint max0, max1;
		max0 = edge0vert0;
		max1 = edge1vert0;
		double newDist = edge0vert1.distanceTo(edge1vert0);
		if (newDist > distMax)
		{
			max0 = edge0vert1;
			max1 = edge1vert0;
			distMax = newDist;
		}
		newDist = edge0vert0.distanceTo(edge1vert1);
		if (newDist > distMax)
		{
			max0 = edge0vert0;
			max1 = edge1vert1;
			distMax = newDist;
		}
		newDist = edge0vert1.distanceTo(edge1vert1);
		if (newDist > distMax)
		{
			max0 = edge0vert1;
			max1 = edge1vert1;
		}
		
		// Calculate the two inner points
		//
		innerVert0 = (faceCenter + max0) / 2.0;
		innerVert1 = (faceCenter + max1) / 2.0;
		
		// Add this split's information to the input arrays. If this is
		// the last split, also add the destination edge's split information.
		//
		placements.append((int) MFnMesh::kOnEdge);
		placements.append((int) MFnMesh::kInternalPoint);
		placements.append((int) MFnMesh::kInternalPoint);
		if (done) placements.append((int) MFnMesh::kOnEdge);
		
		edgeIDs.append(edge0);
		if (done) edgeIDs.append(edge1);
		
		edgeFactors.append(0.5f);
		if (done) edgeFactors.append(0.5f);
		
		MFloatPoint point1((float)innerVert0[0], (float)innerVert0[1],
			(float)innerVert0[2], (float)innerVert0[3]);
		MFloatPoint point2((float)innerVert1[0], (float)innerVert1[1],
			(float)innerVert1[2], (float)innerVert1[3]);
		internalPoints.append(point1);
		internalPoints.append(point2);
		
		// For the next iteration, the current destination
		// edge becomes the start edge.
		//
		edge0 = edge1;
	}

	// Release the dynamically-allocated memory and do the actual split
	//
	delete [] faceTouched;
	return meshFn.split(placements, edgeIDs, edgeFactors, internalPoints);
}
//----------------------------------------------------------------------------------------------------------------------
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);
}
Beispiel #12
0
MObject ClothSimMayaPlugin::createMesh(const MTime& time,
	MObject& outData,
	MStatus& stat)

{
	double t = time.as(MTime::kSeconds);
	if (t <= 1.0 / 24 && m_prevTime > 1.0/24)
	{
		m_simMesh.reset(0);
	}

	int nx = 60;
	int ny = 60;

	if (!m_simMesh.get())
	{

		Eigen::VectorXf v((nx+1) * (ny+1) * 3);
		Eigen::VectorXf x((nx + 1) * (ny + 1) * 3);
		Eigen::VectorXf uv((nx + 1) * (ny + 1) * 2);

		for (int i = 0; i <= nx; ++i)
		{
			for (int j = 0; j <= ny; ++j)
			{
				int base = i + (nx+1) * j;
				uv[2 * base + 0] = (float)i / nx - 0.5f;
				uv[2 * base + 1] = (float)j / ny - 0.5f;

				x[3 * base + 0] = uv[2 * base + 0];
				x[3 * base + 1] = 0;
				x[3 * base + 2] = uv[2 * base + 1];

				v[3 * base + 0] = v[3 * base + 1] = v[3 * base + 2] = 0;
			}
		}

		std::vector<int> triangleInds;
		for (int i = 0; i < nx; ++i)
		{
			for (int j = 0; j < ny; ++j)
			{
				int base = i + (nx + 1) * j;

				triangleInds.push_back(base + 0);
				triangleInds.push_back(base + 1);
				triangleInds.push_back(base + (nx + 1));

				triangleInds.push_back(base + 1);
				triangleInds.push_back(base + (nx + 2));
				triangleInds.push_back(base + (nx + 1));

			}
		}

		m_simMesh.reset(
			new ClothMesh<float>(
				x, v, uv, triangleInds,
				0.01f, 1000000.0f, 1000000.0f,
				0.01f, 1000.0f, 1000.0f,
				1.0f
			)
		);
	}

	std::vector<int> constraintIndices;
	std::vector< Eigen::Matrix3f > constraintMatrices;

	
	Eigen::VectorXf constraintVelocityDeltas(m_simMesh->x().size());
	constraintVelocityDeltas.setConstant(0);

	for (int i = 0; i <= nx; ++i)
	{
		for (int j = 0; j <= ny; ++j)
		{
			int idx = i + (nx + 1) * j;
			float x = (float)i / nx - 0.5f;
			float y = (float)j / ny - 0.5f;

			if (x * x + y * y < 0.3 * 0.3)
			{
				constraintIndices.push_back(idx);
				constraintMatrices.push_back(Eigen::Matrix3f::Zero());
			}
		}
	}

	if (t > m_prevTime)
	{
		ConstrainedCGSolver<float> solver(
			constraintIndices,
			constraintMatrices,
			constraintVelocityDeltas,
			0.01f,
			400
		);

		GravityField<float> g( m_simMesh->m(), Eigen::Vector3f( 0,-9.8f, 0 ) );
		std::vector< ForceField<float>* > forceFields;
		forceFields.push_back( &g );

		try
		{
			std::cerr << "advance" << std::endl;
			m_simMesh->advance(forceFields, float(t - m_prevTime)*0.5f, solver);
			m_simMesh->advance(forceFields, float(t - m_prevTime)*0.5f, solver);
			std::cerr << "done" << std::endl;
		}
		catch (const std::exception &e)
		{
			std::cerr << e.what() << std::endl;
			stat = MStatus::kFailure;
			return MObject();
		}
		catch (...)
		{
			std::cerr << "unknown exception" << std::endl;
			stat = MStatus::kFailure;
			return MObject();
		}
	}

	m_prevTime = t;

	MFloatPointArray points;
	for (int i = 0; i < m_simMesh->x().size(); i += 3)
	{
		MFloatPoint p(m_simMesh->x()[i], m_simMesh->x()[i + 1], m_simMesh->x()[i + 2]);
		points.append(p);
	}

	MFnMesh meshFS;
	MIntArray faceCounts((int)m_simMesh->triangleIndices().size()/3, 3);
	MIntArray faceConnects;
	for (unsigned i = 0; i < m_simMesh->triangleIndices().size(); ++i)
	{
		faceConnects.append(m_simMesh->triangleIndices()[i]);
	}

	MObject newMesh = meshFS.create((int)m_simMesh->x().size() / 3, (int)m_simMesh->triangleIndices().size() / 3, points, faceCounts, faceConnects, outData, &stat);

	return newMesh;
}
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
/*

	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;
}