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;
}
/* static */
bool
UsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh(
        const UsdGeomPrimvar& primvar,
        MFnMesh& meshFn)
{
    const TfToken& primvarName = primvar.GetPrimvarName();

    // Get the raw data before applying any indexing.
    VtVec2fArray uvValues;
    if (!primvar.Get(&uvValues) || uvValues.empty()) {
        TF_WARN("Could not read UV values from primvar '%s' on mesh: %s",
                primvarName.GetText(),
                primvar.GetAttr().GetPrimPath().GetText());
        return false;
    }

    // This is the number of UV values assuming the primvar is NOT indexed.
    VtIntArray assignmentIndices;
    if (primvar.GetIndices(&assignmentIndices)) {
        // The primvar IS indexed, so the indices array is what determines the
        // number of UV values.
        int unauthoredValuesIndex = primvar.GetUnauthoredValuesIndex();

        // Replace any index equal to unauthoredValuesIndex with -1.
        if (unauthoredValuesIndex != -1) {
            for (int& index : assignmentIndices) {
                if (index == unauthoredValuesIndex) {
                    index = -1;
                }
            }
        }

        // Furthermore, if unauthoredValuesIndex is valid for uvValues, then
        // remove it from uvValues and shift the indices (we don't want to
        // import the unauthored value into Maya, where it has no meaning).
        if (unauthoredValuesIndex >= 0 &&
                static_cast<size_t>(unauthoredValuesIndex) < uvValues.size()) {
            // This moves [unauthoredValuesIndex + 1, end) to
            // [unauthoredValuesIndex, end - 1), erasing the
            // unauthoredValuesIndex.
            std::move(
                    uvValues.begin() + unauthoredValuesIndex + 1,
                    uvValues.end(),
                    uvValues.begin() + unauthoredValuesIndex);
            uvValues.pop_back();

            for (int& index : assignmentIndices) {
                if (index > unauthoredValuesIndex) {
                    index = index - 1;
                }
            }
        }
    }

    // Go through the UV data and add the U and V values to separate
    // MFloatArrays.
    MFloatArray uCoords;
    MFloatArray vCoords;
    for (const GfVec2f& v : uvValues) {
        uCoords.append(v[0]);
        vCoords.append(v[1]);
    }

    MStatus status;
    MString uvSetName(primvarName.GetText());
    if (primvarName == UsdUtilsGetPrimaryUVSetName()) {
        // We assume that the primary USD UV set maps to Maya's default 'map1'
        // set which always exists, so we shouldn't try to create it.
        uvSetName = "map1";
    } else {
        status = meshFn.createUVSet(uvSetName);
        if (status != MS::kSuccess) {
            TF_WARN("Unable to create UV set '%s' for mesh: %s",
                    uvSetName.asChar(),
                    meshFn.fullPathName().asChar());
            return false;
        }
    }

    // The following two lines should have no effect on user-visible state but
    // prevent a Maya crash in MFnMesh.setUVs after creating a crease set.
    // XXX this workaround is needed pending a fix by Autodesk.
    MString currentSet = meshFn.currentUVSetName();
    meshFn.setCurrentUVSetName(currentSet);

    // Create UVs on the mesh from the values we collected out of the primvar.
    // We'll assign mesh components to these values below.
    status = meshFn.setUVs(uCoords, vCoords, &uvSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Unable to set UV data on UV set '%s' for mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    const TfToken& interpolation = primvar.GetInterpolation();

    // Build an array of value assignments for each face vertex in the mesh.
    // Any assignments left as -1 will not be assigned a value.
    MIntArray uvIds = _GetMayaFaceVertexAssignmentIds(meshFn,
                                                      interpolation,
                                                      assignmentIndices,
                                                      -1);

    MIntArray vertexCounts;
    MIntArray vertexList;
    status = meshFn.getVertices(vertexCounts, vertexList);
    if (status != MS::kSuccess) {
        TF_WARN("Could not get vertex counts for UV set '%s' on mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    status = meshFn.assignUVs(vertexCounts, uvIds, &uvSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Could not assign UV values to UV set '%s' on mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    return true;
}
void ToMayaMeshConverter::addUVSet( MFnMesh &fnMesh, const MIntArray &polygonCounts, IECore::ConstMeshPrimitivePtr mesh, const std::string &sPrimVarName, const std::string &tPrimVarName, const std::string &stIdPrimVarName, MString *uvSetName ) const
{
	IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( sPrimVarName );
	bool haveS = sIt != mesh->variables.end();
	IECore::PrimitiveVariableMap::const_iterator tIt = mesh->variables.find( tPrimVarName );
	bool haveT = tIt != mesh->variables.end();
	IECore::PrimitiveVariableMap::const_iterator stIdIt = mesh->variables.find( stIdPrimVarName );
	bool haveSTId = stIdIt != mesh->variables.end();

	if ( haveS && haveT )
	{
		if ( sIt->second.interpolation != IECore::PrimitiveVariable::FaceVarying )
		{
			IECore::msg( IECore::Msg::Warning,"ToMayaMeshConverter::doConversion",  boost::format(  "PrimitiveVariable \"%s\" has unsupported interpolation (expected FaceVarying).") % sPrimVarName );
			return;
		}

		if ( tIt->second.interpolation != IECore::PrimitiveVariable::FaceVarying )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported interpolation (expected FaceVarying).") % tPrimVarName);
			return;
		}

		if ( !sIt->second.data )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has no data." ) % sPrimVarName );
		}

		if ( !tIt->second.data )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has no data." ) % tPrimVarName );
		}

		/// \todo Employ some M*Array converters to simplify this
		int numUVs = mesh->variableSize( IECore::PrimitiveVariable::FaceVarying );

		IECore::ConstFloatVectorDataPtr u = IECore::runTimeCast<const IECore::FloatVectorData>(sIt->second.data);

		if ( !u )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % sPrimVarName % sIt->second.data->typeName() );
			return;
		}

		assert( (int)u->readable().size() == numUVs );
		
		IECore::ConstFloatVectorDataPtr v = IECore::runTimeCast<const IECore::FloatVectorData>(tIt->second.data);
		if ( !v )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % tPrimVarName % tIt->second.data->typeName() );
			return;
		}

		assert( (int)v->readable().size() == numUVs );
		
		const std::vector<float> &uAll = u->readable();
		const std::vector<float> &vAll = v->readable();

		if ( uvSetName )
		{
			bool setExists = false;
			MStringArray existingSets;
			fnMesh.getUVSetNames( existingSets );
			for ( unsigned i=0; i < existingSets.length(); ++i )
			{
				if ( *uvSetName == existingSets[i] )
				{
					fnMesh.clearUVs( uvSetName );
					setExists = true;
					break;
				}
			}
			
			if ( !setExists )
			{
				MDagPath dag;
				MStatus s = fnMesh.getPath( dag );
				if ( s )
				{
					fnMesh.createUVSetWithName( *uvSetName );
				}
				else
				{
					fnMesh.createUVSetDataMeshWithName( *uvSetName );
				}
			}
		}
		
		MIntArray uvIds;
		uvIds.setLength( numUVs );
		MFloatArray uArray;
		MFloatArray vArray;
		
		if( haveSTId )
		{
			// Get compressed uv values by matching them with their uvId.
			IECore::ConstIntVectorDataPtr uvId = IECore::runTimeCast<const IECore::IntVectorData>(stIdIt->second.data);
			if ( !uvId )
			{
				IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % stIdPrimVarName % stIdIt->second.data->typeName() );
				return;
			}
			
			const std::vector<int> &uvIdData = uvId->readable();
	
			assert( (int)uvIdData.size() == numUVs );
			
			int highestId = 0;
			for ( int i = 0; i < numUVs; i++)
			{
				uvIds[i] = uvIdData[i];
				if( uvIdData[i] > highestId )
				{
					highestId = uvIdData[i];
				}
			}
			
			// u and v arrays need only be as long as the number of unique uvIds
			uArray.setLength( highestId + 1 );
			vArray.setLength( highestId + 1 );
			
			for ( int i = 0; i < numUVs; i++ )
			{
				uArray[ uvIds[i] ] = uAll[i];
				// FromMayaMeshConverter does the opposite of this
				vArray[ uvIds[i] ] = 1 - vAll[i];
			}
		}
		else
		{
			// If for some reason we cannot find the uv indices, set the UVs using the old way
			// the performances in maya won't be good (for weigth painting in particular)
			uArray.setLength( numUVs );
			vArray.setLength( numUVs );

			for ( int i = 0; i < numUVs; i++)
			{
				uArray[i] = u->readable()[i];
				// FromMayaMeshConverter does the opposite of this
				vArray[i] = 1 - v->readable()[i];
			}
			
			for ( int i = 0; i < numUVs; i++)
			{
				uvIds[i] = i;
			}
		}
		
		MStatus s = fnMesh.setUVs( uArray, vArray, uvSetName );
		if ( !s )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to set UVs." );
			return;
		}

		s = fnMesh.assignUVs( polygonCounts, uvIds, uvSetName );
		if ( !s )
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to assign UVs." );
			return;
		}

	}
	else if ( haveS )
	{
		IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "Primitive variable \"%s\" found, but not \"%s\"." ) % sPrimVarName % tPrimVarName );
	}
	else if ( haveT )
	{
		IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "Primitive variable \"%s\" found, but not \"%s\"." ) % tPrimVarName % sPrimVarName );
	}
	else
	{
		assert( !uvSetName );
	}
}
Exemple #4
0
static MStatus
convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
    std::vector<Vertex> const & refinedVerts,
    bool hasUVs, std::vector<FVarVertexUV> const & refinedUVs,
    bool hasColors, std::vector<FVarVertexColor> const & refinedColors,
    MFnMesh & inMeshFn, MObject newMeshDataObj) {

    MStatus status;

    typedef OpenSubdiv::Far::ConstIndexArray IndexArray;

    int maxlevel = refiner.GetMaxLevel();

    OpenSubdiv::Far::TopologyLevel const & refLastLevel 
                                                = refiner.GetLevel(maxlevel);

    int nfaces = refLastLevel.GetNumFaces();

    // Init Maya Data

    // Face Counts
    MIntArray faceCounts(nfaces);
    for (int face=0; face < nfaces; ++face) {
        faceCounts[face] = 4;
    }

    // Face Connects
    MIntArray faceConnects(nfaces*4);
    for (int face=0, idx=0; face < nfaces; ++face) {
        IndexArray fverts = refLastLevel.GetFaceVertices(face);
        for (int vert=0; vert < fverts.size(); ++vert) {
            faceConnects[idx++] = fverts[vert];
        }
    }

    // Points
    int nverts = refLastLevel.GetNumVertices();
    int firstOfLastVert = refiner.GetNumVerticesTotal() 
                        - nverts 
                        - refiner.GetLevel(0).GetNumVertices();

    MFloatPointArray points(nverts);
    for (int vIt = 0; vIt < nverts; ++vIt) {
        Vertex const & v = refinedVerts[firstOfLastVert + vIt];
        points.set(vIt, v.position[0], v.position[1], v.position[2]);
    }

    // Create New Mesh from MFnMesh
    MFnMesh newMeshFn;
    MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(),
        points, faceCounts, faceConnects, newMeshDataObj, &status);
    MCHECKERR(status, "Cannot create new mesh");

    // Get face-varying set names and other info from the inMesh
    MStringArray uvSetNames;
    MStringArray colorSetNames;
    std::vector<int> colorSetChannels;
    std::vector<MFnMesh::MColorRepresentation> colorSetReps;
    int totalColorSetChannels = 0;
    status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames,
        colorSetChannels, colorSetReps, totalColorSetChannels);

    // Add new UVs back to the mesh if needed
    if (hasUVs) {

        MIntArray fvarConnects(faceConnects.length());
        int count = 0;
        for (int f = 0; f < refLastLevel.GetNumFaces(); ++f) {
            IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELUV);
            for (int index = 0 ; index < faceIndices.size() ; ++index) {
                fvarConnects[count++] = faceIndices[index];
            }
        }

        int nuvs = refLastLevel.GetNumFVarValues(CHANNELUV);
        int firstOfLastUvs = refiner.GetNumFVarValuesTotal(CHANNELUV) 
                             - nuvs
                             - refiner.GetLevel(0).GetNumFVarValues(CHANNELUV);

        MFloatArray uCoord(nuvs), vCoord(nuvs);
        for (int uvIt = 0; uvIt < nuvs; ++uvIt) {
            FVarVertexUV const & uv = refinedUVs[firstOfLastUvs + uvIt];
            uCoord[uvIt] = uv.u;
            vCoord[uvIt] = uv.v;
        }

        // Currently, the plugin only supports one UV set
        int uvSetIndex = 0;
        if (uvSetIndex > 0) {
            status = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] );
            MCHECKERR(status, "Cannot create UVSet");
        }
        static MString defaultUVName("map1");
        MString const * uvname = uvSetIndex==0 ? 
            &defaultUVName : &uvSetNames[uvSetIndex];
        status = newMeshFn.setUVs(uCoord, vCoord, uvname);                  
        MCHECKERR(status, "Cannot set UVs for set : "+*uvname);

        status = newMeshFn.assignUVs(faceCounts, fvarConnects, uvname);     
        MCHECKERR(status, "Cannot assign UVs");
    }

    // Add new colors back to the mesh if needed
    if (hasColors) {

        int count = 0;
        MIntArray fvarConnects2(faceConnects.length());
        for (int f = 0 ; f < refLastLevel.GetNumFaces(); ++f) {
            IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELCOLOR);
            for (int index = 0 ; index < faceIndices.size() ; ++index) {
                fvarConnects2[count++] = faceIndices[index];
            }
        }
  
        int ncols = refLastLevel.GetNumFVarValues(CHANNELCOLOR);
        int firstOfLastCols = refiner.GetNumFVarValuesTotal(CHANNELCOLOR) 
                              - ncols
                              - refiner.GetLevel(0).GetNumFVarValues(CHANNELCOLOR);

        MColorArray colorArray(ncols);
        for (int colIt = 0; colIt < ncols; ++colIt) {
            FVarVertexColor const & c = refinedColors[firstOfLastCols + colIt];
            colorArray.set(colIt, c.r, c.g, c.b, c.a);
        }

        // Currently, the plugin only supports one color sets
        int colorSetIndex = 0;

        // Assign color buffer and map the ids for each face-vertex
        // API Limitation: Cannot set MColorRepresentation here
        status = newMeshFn.createColorSetDataMesh(
            colorSetNames[colorSetIndex]);                                
        MCHECKERR(status, "Cannot create ColorSet");

        bool isColorClamped = inMeshFn.isColorClamped(
            colorSetNames[colorSetIndex], &status);                   
        MCHECKERR(status, "Can not get Color Clamped ");

        status = newMeshFn.setIsColorClamped(
            colorSetNames[colorSetIndex], isColorClamped);                     
        MCHECKERR(status, "Can not set Color Clamped : " + isColorClamped);

        status = newMeshFn.setColors(
            colorArray, &colorSetNames[colorSetIndex], 
            colorSetReps[colorSetIndex]);   
        MCHECKERR(status, "Can not set Colors");

        status = newMeshFn.assignColors(
            fvarConnects2, &colorSetNames[colorSetIndex]);                          
        MCHECKERR(status, "Can not assign Colors");
    }

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

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

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

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

	
	MFnMesh meshCreateFn;
	meshCreateFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat );
	
	meshCreateFn.setUVs ( uArray, vArray );
	meshCreateFn.assignUVs ( polygonCounts, polygonUVs );
	
	return outMeshData;
}
MStatus	Molecule3Cmd::redoIt()
{
	MStatus stat;
	MDagPath dagPath;
	MFnMesh meshFn;
		
	// Create a ball
	int nBallPolys;
	MPointArray ballVerts;
	MIntArray ballPolyCounts;
	MIntArray ballPolyConnects;
	MFloatArray ballUCoords;
	MFloatArray ballVCoords;
	MIntArray ballFvUVIDs;
	genBall( MPoint::origin, ballRodRatio * radius.value(), segs, nBallPolys, 
			 ballVerts, ballPolyCounts, ballPolyConnects,
			 true, ballUCoords, ballVCoords, ballFvUVIDs );
		
	unsigned int i, j, vertOffset;
	MPointArray meshVerts;
	MPoint p0, p1;
	MObject objTransform;
	
	// Setup for rods
	int nRodPolys;
	MPointArray rodVerts;
	MIntArray rodPolyCounts;
	MIntArray rodPolyConnects;
	MFloatArray rodUCoords;
	MFloatArray rodVCoords;
	MIntArray rodFvUVIDs;
	
	// Setup for newMesh
	int nNewPolys;
	MPointArray newVerts;
	MIntArray newPolyCounts;
	MIntArray newPolyConnects;
	MFloatArray newUCoords;
	MFloatArray newVCoords;
	MIntArray newFvUVIDs;
	
	int uvOffset; 
	MDagModifier dagMod;
	MFnDagNode dagFn;
	
	objTransforms.clear();
	
	// Iterate over the meshes
	unsigned int mi;
	for( mi=0; mi < selMeshes.length(); mi++ )
	{								
		dagPath = selMeshes[mi];
		meshFn.setObject( dagPath );
		
		uvOffset = 0;
		nNewPolys = 0;
		newVerts.clear();
		newPolyCounts.clear();
		newPolyConnects.clear();
		newUCoords.clear();
		newVCoords.clear();
		newFvUVIDs.clear();
		
		// Generate balls
		meshFn.getPoints( meshVerts, MSpace::kWorld );
		for( i=0; i < meshVerts.length(); i++ )
		{
			vertOffset = newVerts.length();
			
			// Add the ball to the new mesh
			nNewPolys += nBallPolys;
			
			// Move the ball vertices to the mesh vertex. Add it to the newMesh
			for( j=0; j < ballVerts.length(); j++ )
				newVerts.append( meshVerts[i] + ballVerts[j] );
				
			for( j=0; j < ballPolyCounts.length(); j++ )
				newPolyCounts.append( ballPolyCounts[j] );
				
			for( j=0; j < ballPolyConnects.length(); j++ )
				newPolyConnects.append( vertOffset + ballPolyConnects[j] );
		
			// Only add the uv coordinates once, since they are shared
			// by all balls
			if( i == 0 )
			{
				for( j=0; j < ballUCoords.length(); j++ )
				{
					newUCoords.append( ballUCoords[j] );
					newVCoords.append( ballVCoords[j] );
				}				
			}
			
			for( j=0; j < ballFvUVIDs.length(); j++ )
			{
				newFvUVIDs.append( uvOffset + ballFvUVIDs[j] );
			}
		}
		
		uvOffset = newUCoords.length();
		
		// Generate rods
		int nRods = 0;
		MItMeshEdge edgeIter( dagPath );
		for( ; !edgeIter.isDone(); edgeIter.next(), nRods++  )
		{	
			p0 = edgeIter.point( 0, MSpace::kWorld );		
			p1 = edgeIter.point( 1, MSpace::kWorld );
			
			// N.B. Generate the uv coordinates only once since they
			// are referenced by all rods
			genRod( p0, p1, 
					radius.value(), segs, nRodPolys, 
					rodVerts, rodPolyCounts, rodPolyConnects,
					nRods == 0,	rodUCoords, rodVCoords,
					rodFvUVIDs ); 

			vertOffset = newVerts.length();
			
			// Add the rod to the mesh
			nNewPolys += nRodPolys;
			
			for( i=0; i < rodVerts.length(); i++ )
				newVerts.append( rodVerts[i] );
				
			for( i=0; i < rodPolyCounts.length(); i++ )
				newPolyCounts.append( rodPolyCounts[i] );
				
			for( i=0; i < rodPolyConnects.length(); i++ )
				newPolyConnects.append( vertOffset + rodPolyConnects[i] );

			// First rod
			if( nRods == 0 )
			{
				// Add rod's uv coordinates to the list
				for( i=0; i < rodUCoords.length(); i++ )
				{
					newUCoords.append( rodUCoords[i] );
					newVCoords.append( rodVCoords[i] );
				}
			}
			
			// Set the face-vertex-uvIDs
			for( i=0; i < rodFvUVIDs.length(); i++ )
			{
				newFvUVIDs.append( uvOffset + rodFvUVIDs[i] );
			}
		}
		
		objTransform = meshFn.create( newVerts.length(), nNewPolys, newVerts, 
									  newPolyCounts, newPolyConnects,
									  newUCoords, newVCoords, 
									  MObject::kNullObj, &stat ); 
		if( !stat )
		{
			MGlobal::displayError( MString( "Unable to create mesh: " ) + stat.errorString() );
			return stat;
		}	
		
		objTransforms.append( objTransform );
				
		meshFn.assignUVs( newPolyCounts, newFvUVIDs );
				
		meshFn.updateSurface();
		
		// Rename transform node
		dagFn.setObject( objTransform );
		dagFn.setName( "molecule" );
				
		// Put mesh into the initial shading group
		dagMod.commandToExecute( MString( "sets -e -fe initialShadingGroup " ) + meshFn.name() );
	}

	// Select all the newly created molecule meshes
	MString cmd( "select -r" );
	for( i=0; i < objTransforms.length(); i++ )
	{
		dagFn.setObject( objTransforms[i] );
		cmd += " " + dagFn.name();	
	}

	dagMod.commandToExecute( cmd );
	
	return dagMod.doIt();
}
Exemple #7
0
MStatus convertOsdFarToMayaMeshData(
     FMesh const * farMesh,
     OpenSubdiv::OsdCpuVertexBuffer * vertexBuffer,
     int subdivisionLevel,
     MFnMesh const & inMeshFn,
     MObject newMeshDataObj ) {

    MStatus returnStatus;

    // Get sizing data from OSD
    const OpenSubdiv::FarPatchTables *farPatchTables = farMesh->GetPatchTables();
    int numPolygons = farPatchTables->GetNumFaces(); // use the highest level stored in the patch tables
    const unsigned int *polygonConnects_orig = farPatchTables->GetFaceVertices(); // use the highest level stored in the patch tables

    const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *farSubdivTables = farMesh->GetSubdivisionTables();
    unsigned int numVertices  = farSubdivTables->GetNumVertices(subdivisionLevel);
    unsigned int vertexOffset = farSubdivTables->GetFirstVertexOffset(subdivisionLevel);

    // Init Maya Data
    MFloatPointArray points(numVertices);
    MIntArray faceCounts(numPolygons); // number of edges for each polygon.  Assume quads (4-edges per face)
    MIntArray faceConnects(numPolygons*4); // array of vertex ids for all edges. assuming quads

    // -- Face Counts
    for (int i=0; i < numPolygons; ++i) {
        faceCounts[i] = 4;
    }

    // -- Face Connects
    for (unsigned int i=0; i < faceConnects.length(); i++) {
        faceConnects[i] = polygonConnects_orig[i] - vertexOffset; // adjust vertex indices so that v0 is at index 0
    }

    // -- Points
    // Number of floats in each vertex.  (positions, normals, etc)
    int numFloatsPerVertex = vertexBuffer->GetNumElements();
    assert(numFloatsPerVertex == 3); // assuming only xyz stored for each vertex
    const float *vertexData = vertexBuffer->BindCpuBuffer();
    float *ptrVertexData;

    for (unsigned int i=0; i < numVertices; i++) {

        // make sure to offset to the first osd vertex for that subd level
        unsigned int osdRawVertexIndex = i + vertexOffset;

        // Lookup the data in the vertexData
        ptrVertexData = (float *) vertexData + ((osdRawVertexIndex) * numFloatsPerVertex);
        points.set(i, ptrVertexData[0], ptrVertexData[1], ptrVertexData[2]);
    }

    // Create New Mesh from MFnMesh
    MFnMesh newMeshFn;
    MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(),
        points, faceCounts, faceConnects, newMeshDataObj, &returnStatus);
    MCHECKERR(returnStatus, "Cannot create new mesh");

    // Attach UVs (if present)
    // ASSUMPTION: Only tracking UVs as FVar data.  Will need to change this
    // ASSUMPTION: OSD has a unique UV for each face-vertex
    int fvarTotalWidth = farMesh->GetTotalFVarWidth();

    if (fvarTotalWidth > 0) {

        // Get face-varying set names and other info from the inMesh
        MStringArray uvSetNames;
        MStringArray colorSetNames;
        std::vector<int> colorSetChannels;
        std::vector<MFnMesh::MColorRepresentation> colorSetReps;
        int totalColorSetChannels = 0;
        returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels);

        int numUVSets = uvSetNames.length();
        int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels;
        assert(fvarTotalWidth == expectedFvarTotalWidth);

        const OpenSubdiv::FarPatchTables::FVarDataTable &fvarDataTable =  farPatchTables->GetFVarDataTable();
        assert(fvarDataTable.size() == expectedFvarTotalWidth*faceConnects.length());

        // Create an array of indices to map each face-vert to the UV and ColorSet Data
        MIntArray fvarConnects(faceConnects.length());
        for (unsigned int i=0; i < faceConnects.length(); i++) {
            fvarConnects[i] = i;
        }

        MFloatArray uCoord(faceConnects.length());
        MFloatArray vCoord(faceConnects.length());

        for (int uvSetIndex=0; uvSetIndex < numUVSets; uvSetIndex++) {

            for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) {
                int fvarItem = vertid*fvarTotalWidth + uvSetIndex*2; // stride per vertex is the fvarTotalWidth
                uCoord[vertid] = fvarDataTable[fvarItem];
                vCoord[vertid] = fvarDataTable[fvarItem+1];
            }
            // Assign UV buffer and map the uvids for each face-vertex
            if (uvSetIndex != 0) { // assume uvset index 0 is the default UVset, so do not create
                returnStatus = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] );
            }
            MCHECKERR(returnStatus, "Cannot create UVSet");
            newMeshFn.setUVs(uCoord,vCoord, &uvSetNames[uvSetIndex]);
            newMeshFn.assignUVs(faceCounts, fvarConnects, &uvSetNames[uvSetIndex]);
        }

        MColorArray colorArray(faceConnects.length());
        int colorSetRelativeStartIndex = numUVSets*2;

        for (unsigned int colorSetIndex=0; colorSetIndex < colorSetNames.length(); colorSetIndex++) {

            for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) {

                int fvarItem = vertid*fvarTotalWidth + colorSetRelativeStartIndex;
                if (colorSetChannels[colorSetIndex] == 1) {
                    colorArray[vertid].r = fvarDataTable[fvarItem];
                    colorArray[vertid].g = fvarDataTable[fvarItem];
                    colorArray[vertid].b = fvarDataTable[fvarItem];
                    colorArray[vertid].a = 1.0f;
                } else if (colorSetChannels[colorSetIndex] == 3) {
                    colorArray[vertid].r = fvarDataTable[fvarItem];
                    colorArray[vertid].g = fvarDataTable[fvarItem+1];
                    colorArray[vertid].b = fvarDataTable[fvarItem+2];
                    colorArray[vertid].a = 1.0f;
                } else {
                    colorArray[vertid].r = fvarDataTable[fvarItem];
                    colorArray[vertid].g = fvarDataTable[fvarItem+1];
                    colorArray[vertid].b = fvarDataTable[fvarItem+2];
                    colorArray[vertid].a = fvarDataTable[fvarItem+3];
                }
            }

            // Assign UV buffer and map the uvids for each face-vertex
            // API Limitation: Cannot set MColorRepresentation here
            returnStatus = newMeshFn.createColorSetDataMesh(colorSetNames[colorSetIndex]);
            MCHECKERR(returnStatus, "Cannot create ColorSet");

            bool isColorClamped = inMeshFn.isColorClamped(colorSetNames[colorSetIndex], &returnStatus);
            newMeshFn.setIsColorClamped(colorSetNames[colorSetIndex], isColorClamped);
            newMeshFn.setColors(colorArray, &colorSetNames[colorSetIndex], colorSetReps[colorSetIndex]);
            newMeshFn.assignColors(fvarConnects, &colorSetNames[colorSetIndex]);

            // Increment colorSet start location in fvar buffer
            colorSetRelativeStartIndex += colorSetChannels[colorSetIndex];
        }
    }
    return MS::kSuccess;
}
// Maps vertex points in uv coordinates (uPoints and vPoints) onto plane and creates a new mesh
// Only works with planes with the local normal along the y-axis for now (default Maya polyplane)
MStatus SplitFromImage::addPlaneSubMesh(MObject &object, MFloatArray uPoints, MFloatArray vPoints, const MFnMesh &planeMesh) {
  if(uPoints.length() != vPoints.length())
    return MS::kFailure;

  MPointArray planePoints;
  MIntArray planeVertexCount;
  MIntArray planeVertexList;
  planeMesh.getPoints(planePoints);
  planeMesh.getVertices(planeVertexCount, planeVertexList);

  cout << "planeVertexCount: " << planeVertexCount.length() << endl;
  cout << "planeVertexList: " << planeVertexList.length() << endl;

  double minX, minZ, maxX, maxZ;
  minX = minZ = 100000;
  maxX = maxZ = -100000;

  // Find min and max points of the plane
  for(unsigned int i = 0; i < planePoints.length(); i++) {
    double x = planePoints[i].x;
    double z = planePoints[i].z;
    if(planePoints[i].x < minX)
      minX = x;
    if(planePoints[i].x > maxX)
      maxX = x;
    if(planePoints[i].z < minZ)
      minZ = x;
    if(planePoints[i].z > maxZ)
      maxZ = z;
  }

  // Set plane's corner pos and width and height
  double planeX = minX;
  double planeY = minZ;
  double planeWidth = maxX - minX;
  double planeHeight = maxZ - minZ;

  // Prepare stuff for MFnMesh
  int numVertices = uPoints.length();
  int numPolygons = 1;
  MPointArray pointArray;
  int polygon_counts[1] = {numVertices};
  MIntArray polygonCounts(polygon_counts, 1);
  int *polygon_connects = new int[numVertices];

  for(int i = 0; i < numVertices; i++) {
    polygon_connects[i] = i;
    MPoint point(planeX + planeWidth * uPoints[i], 0, planeY + planeHeight * vPoints[i]);
    pointArray.append(point);
  }

  MIntArray polygonConnects(polygon_connects, numVertices);
  delete[] polygon_connects;

  // cout << "numVertices: " << numVertices << endl
  //      << "numPolygons: " << numPolygons << endl
  //      << "pointArray: " << pointArray << endl
  //      << "polygonCounts: " << polygonCounts << endl
  //      << "polygonConnects: " << polygonConnects << endl
  //      << "planeX: " << planeX << endl
  //      << "planeY: " << planeY << endl
  //      << "planeWidth: " << planeWidth << endl
  //      << "planeHeight: " << planeHeight << endl;

  for (int i = 0; i < vPoints.length(); i++){
	  vPoints[i] = 1.0 - vPoints[i];
  }

  MFnMesh mesh;
  object = mesh.create(numVertices, numPolygons, pointArray, polygonCounts, polygonConnects, uPoints, vPoints);
  mesh.assignUVs(polygonCounts, polygonConnects);

  return MS::kSuccess;
}
Exemple #9
0
MStatus ropeGenerator::compute( const MPlug& plug, MDataBlock& data )
{
	MStatus status;

	if ( plug == outMesh )
	{
		//Get Curve
		MDataHandle inCurve_Hdl = data.inputValue( inCurve, &status );
		if (status != MS::kSuccess ){
			MGlobal::displayError( "Node ropeGenerator needs an Input Curve" );
			return MS::kSuccess;
		}
		MObject inCurveObj = inCurve_Hdl.asNurbsCurve();
		MFnNurbsCurve curveFn( inCurveObj );
		
		//Get Attributes
		int inDiv = data.inputValue( divisions ).asInt();
		bool inCreateRope = data.inputValue( createRope ).asBool();
		int inRopesCount = data.inputValue( ropesCount ).asInt();
		int inPointsPerRope = data.inputValue( pointsPerRope ).asInt();
		int inPointsCount = data.inputValue( pointsCount ).asInt();
		float inRopesStrength = data.inputValue( ropesStrength ).asFloat();
		float inRadius = data.inputValue( radius ).asFloat();
		MRampAttribute inRadRamp( thisMObject(), taperRamp );
		float inTwist = data.inputValue( twist ).asFloat();
		MRampAttribute inTwistRamp( thisMObject(), twistRamp );
		float inUvWidth = data.inputValue( uvWidth ).asFloat();
		float inUvHeight = data.inputValue( uvHeight ).asFloat();
		float inUvCapSize = data.inputValue( uvCapSize ).asFloat();

		MFnMesh fnMesh;
		MFnMeshData dataCreator;
		MObject outMeshData;
		outMeshData = dataCreator.create();
		MDataHandle outputHandle = data.outputValue(outMesh);
		//createBase 
		MIntArray faceCounts, faceConnects, uvIds;
		MFloatArray uArray, vArray;
		MFloatPointArray points;
		faceCounts.clear();
		faceConnects.clear();
		points.clear();
		if (inCreateRope)
			inPointsCount = ( inPointsPerRope + 2 ) * inRopesCount;
		int numVertices = ( inDiv + 1 ) * inPointsCount;
		int numFaces = ( inPointsCount * inDiv ) + 2;
		float param;
		float lengPerDiv = curveFn.length() / inDiv;
		PrevNormal = MVector( curveFn.normal( 0.0, MSpace::kWorld ).normal() );
		float baseLeng = lengPerDiv;
		float baseParamForRamp = 0;
		float paramForRamp = 1.0 / float( inDiv );
		float uDivNumber = inUvWidth / float( inPointsCount );
		float vDivNumber = inUvHeight / float( inDiv );
		for (int d = 0; d < inDiv + 1; d++)
		{
			if (d == 0)
			{
				param = 0;
				faceCounts.append( inPointsCount );
				for ( int i = inPointsCount - 1; i >= 0; i-- )
				{
					faceConnects.append( i );
				}
				for ( int i = 0; i < inPointsCount; i++ )
				{
					uvIds.append( i );
				}
				MFloatArray uTmpArray, vTmpArray;
				if (inCreateRope)
					createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, 1.0 );
				else
					createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, 1.0 );
				for ( int u = uTmpArray.length() - 1; u >= 0 ; u-- )
				{
					uArray.append( uTmpArray[u] + 1.0 );
					vArray.append( vTmpArray[u] );
				}
				for ( int i = 0; i < inPointsCount + 1; i++ )
				{
					uArray.append( uDivNumber * float( i ) );
					vArray.append( vDivNumber * float( d ) );
				}
			}else{
				param = curveFn.findParamFromLength( baseLeng );
				for ( int i = 0; i < inPointsCount + 1; i++ )
				{
					uArray.append( uDivNumber * float( i ) );
					vArray.append( vDivNumber * float( d ) );
				}
				for ( int f = 0; f < inPointsCount; f++ )
				{
					faceCounts.append( 4 );
					if( f == ( inPointsCount - 1 ))
					{
						faceConnects.append( ( f + 1 + ( d * inPointsCount ) ) - inPointsCount - inPointsCount );
						faceConnects.append( ( f + 1 + ( d * inPointsCount ) - inPointsCount ) );
						faceConnects.append( f + 1 + ( d * inPointsCount )  - 1 );
						faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount - 1 );
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f );
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f);
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f);
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f);
					}else{
						faceConnects.append( ( f + ( d * inPointsCount ) ) - inPointsCount );
						faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount );
						faceConnects.append( f + 1 + ( d * inPointsCount ) );
						faceConnects.append( ( f + ( d * inPointsCount )) );
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f);
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f );
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f);
						uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f);
					}
				}
				if ( d == inDiv )
				{
					faceCounts.append( inPointsCount );
					for ( int i = 0; i <  inPointsCount; i++ )
					{
						faceConnects.append( ( inPointsCount * inDiv ) + i );
						uvIds.append( ( inPointsCount * ( inDiv + 2)) + i + inDiv + 1 );
					}
					MFloatArray uTmpArray, vTmpArray;
					if (inCreateRope)
						createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, -1.0 );
					else
						createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, -1.0 );
					for ( int u = 0; u < uTmpArray.length(); u++ )
					{
						uArray.append( uTmpArray[u] + 2.0 );
						vArray.append( vTmpArray[u] );
					}
				}
				baseLeng += lengPerDiv;
			}
			float divTwist;
			inTwistRamp.getValueAtPosition( baseParamForRamp, divTwist );
			float divTaper;
			inRadRamp.getValueAtPosition( baseParamForRamp, divTaper );
			baseParamForRamp += paramForRamp;
			if (inCreateRope)
				createRopesRings( inRopesCount, 
								getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees )  ),
								points, inPointsPerRope, inRopesStrength, inRadius * divTaper);
			else
				createCriclePoints( inPointsCount, 
									getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ),
									points, inRadius * divTaper );
		}
		fnMesh.create( numVertices, numFaces, points, faceCounts, faceConnects, uArray, vArray, outMeshData );
		fnMesh.assignUVs( faceCounts, uvIds );
		outputHandle.set(outMeshData);
		outputHandle.setClean();
	}
	return MS::kSuccess;
}
Exemple #10
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;
}
Exemple #11
0
MStatus meshCacheNode::compute( const MPlug& plug, MDataBlock& data )
{
	
	MStatus stat;
	
	MString path =  data.inputValue( input ).asString();
	
	double time = data.inputValue( frame ).asTime().value();
	int minfrm = data.inputValue( aminframe ).asInt();
	//int maxfrm = data.inputValue( amaxframe ).asInt();
	int frmstep = data.inputValue( aframestep ).asInt();
	
	if( time < minfrm ) time = minfrm;
		
	int frame_lo = minfrm + int(time-minfrm)/frmstep*frmstep;
	int frame_hi = frame_lo+frmstep;

	char filename[256];
	sprintf( filename, "%s.%d.mcf", path.asChar(), frame_lo );
	
	FMCFMesh mesh;
	if(mesh.load(filename) != 1)
	{
		sprintf( filename, "%s.mcf", path.asChar());
		if(mesh.load(filename) != 1)
		{
			MGlobal::displayError( MString("Failed to open file: ") + filename );
			return MS::kFailure;
		}
	}
	
	int lo_n_vertex = mesh.getNumVertex();

	vertexArray.clear();
	vertexFArray.clear();
	uArray.clear();
	vArray.clear();
	polygonCounts.clear();
	polygonConnects.clear();
	polygonUVs.clear();

	for(unsigned int i = 0; i < mesh.getNumFace(); i++ ) 
	{
		polygonCounts.append( mesh.getFaceCount(i) );
	}

	for(unsigned int i = 0; i < mesh.getNumFaceVertex(); i++) 
	{
		polygonConnects.append( mesh.getVertexId(i) );
		polygonUVs.append( mesh.getUVId(i) );
	}

	XYZ tp;
	for(unsigned int i = 0; i < mesh.getNumVertex(); i++) 
	{
		mesh.getVertex(tp, i);
		vertexArray.append( MPoint( tp.x, tp.y, tp.z ) );
	}

	for(unsigned int i = 0; i < mesh.getNumUV(); i++) 
	{
		uArray.append( mesh.getS(i) );
		vArray.append( mesh.getT(i) );
	}
	
	

	if( time > frame_lo ) 
	{
		sprintf( filename, "%s.%d.mcf", path.asChar(), frame_hi );

		if(mesh.load(filename) != 1)
		{
			MGlobal::displayError( MString("Failed to open file: ") + filename );
		}
		else if(mesh.getNumVertex() == lo_n_vertex)
		{
			XYZ tp;
			for(unsigned int i = 0; i < mesh.getNumVertex(); i++) 
			{
				mesh.getVertex(tp, i);
				vertexFArray.append( MPoint( tp.x, tp.y, tp.z ) );
			}
			
			double alpha = double(time-frame_lo) / (double)frmstep;

			for(unsigned int i = 0; i < mesh.getNumVertex(); i++) 
			{
				vertexArray[i] = vertexArray[i] + alpha * ( vertexFArray[i] - vertexArray[i] );
			}
		}
	}

	if( plug == outMesh ) 
	{
	
		MDataHandle meshh = data.outputValue(outMesh, &stat);
		
		MFnMeshData dataCreator;
		MObject outMeshData = dataCreator.create(&stat);

		int numVertex = vertexArray.length();
		int numPolygon = polygonCounts.length();
		
		MFnMesh meshFn;
		meshFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat );
		
			
		if( !stat ) 
		{
			char log[256];
			sprintf( log, "Failed to create mesh %s", filename );
			MGlobal::displayError( log );
			return MS::kFailure;
		}

		if( polygonUVs.length() != 0 ) 
		{
			meshFn.setUVs ( uArray, vArray );
			meshFn.assignUVs ( polygonCounts, polygonUVs );
		}

		meshh.set(outMeshData);
	    
		data.setClean(plug);

	} 
	else 
	{
		return MS::kUnknownParameter;
	}

		return MS::kSuccess;
}