Example #1
0
const MIntArray MVGMesh::getFaceVertices(const int faceId)
{
    MStatus status;
    MItMeshPolygon faceIter(_object);
    int prev;
    status = faceIter.setIndex(faceId, prev);
    CHECK(status);
    MIntArray vertices;
    status = faceIter.getVertices(vertices);
    CHECK(status);
    return vertices;
}
Example #2
0
// virtual
bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &primSchema)
{

    MStatus status = MS::kSuccess;

    // Write parent class attrs
    writeTransformAttrs(usdTime, primSchema);

    // Return if usdTime does not match if shape is animated
    if (usdTime.IsDefault() == isShapeAnimated() ) {
        // skip shape as the usdTime does not match if shape isAnimated value
        return true; 
    }

    MFnMesh lMesh( getDagPath(), &status );
    if ( !status )
    {
        MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" );
        return false;
    }
    unsigned int numVertices = lMesh.numVertices();
    unsigned int numPolygons = lMesh.numPolygons();

    // Set mesh attrs ==========
    // Get points
    // TODO: Use memcpy()
    const float* mayaRawPoints = lMesh.getRawPoints(&status);
    VtArray<GfVec3f> points(numVertices);
    for (unsigned int i = 0; i < numVertices; i++) {
        unsigned int floatIndex = i*3;
        points[i].Set(mayaRawPoints[floatIndex],
                      mayaRawPoints[floatIndex+1],
                      mayaRawPoints[floatIndex+2]);
    }
    primSchema.GetPointsAttr().Set(points, usdTime); // ANIMATED

    // Compute the extent using the raw points
    VtArray<GfVec3f> extent(2);
    UsdGeomPointBased::ComputeExtent(points, &extent);
    primSchema.CreateExtentAttr().Set(extent, usdTime);

    // Get faceVertexIndices
    unsigned int numFaceVertices = lMesh.numFaceVertices(&status);
    VtArray<int>     faceVertexCounts(numPolygons);
    VtArray<int>     faceVertexIndices(numFaceVertices);
    MIntArray mayaFaceVertexIndices; // used in loop below
    unsigned int curFaceVertexIndex = 0;
    for (unsigned int i = 0; i < numPolygons; i++) {
        lMesh.getPolygonVertices(i, mayaFaceVertexIndices);
        faceVertexCounts[i] = mayaFaceVertexIndices.length();
        for (unsigned int j=0; j < mayaFaceVertexIndices.length(); j++) {
            faceVertexIndices[ curFaceVertexIndex ] = mayaFaceVertexIndices[j]; // push_back
            curFaceVertexIndex++;
        }
    }
    primSchema.GetFaceVertexCountsAttr().Set(faceVertexCounts);   // not animatable
    primSchema.GetFaceVertexIndicesAttr().Set(faceVertexIndices); // not animatable

    // Read usdSdScheme attribute. If not set, we default to defaultMeshScheme
    // flag that can be user defined and initialized to catmullClark
    TfToken sdScheme = PxrUsdMayaMeshUtil::getSubdivScheme(lMesh, getArgs().defaultMeshScheme);    
    primSchema.CreateSubdivisionSchemeAttr(VtValue(sdScheme), true);

    // Polygonal Mesh Case
    if (sdScheme==UsdGeomTokens->none) {
        // Support for standard USD bool and with Mojito bool tag
        TfToken normalInterp=PxrUsdMayaMeshUtil::getEmitNormals(lMesh, UsdGeomTokens->none);
        
        if (normalInterp==UsdGeomTokens->faceVarying) {
            // Get References to members of meshData object
            MFloatVectorArray normalArray;
            MFloatVectorArray vertexNormalArray;
 
            lMesh.getNormals(normalArray, MSpace::kObject);

            // Iterate through each face in the mesh.
            vertexNormalArray.setLength(lMesh.numFaceVertices());
            VtArray<GfVec3f> meshNormals(lMesh.numFaceVertices());
            size_t faceVertIdx = 0;
            for (MItMeshPolygon faceIter(getDagPath()); !faceIter.isDone(); faceIter.next()) {
                // Iterate through each face-vertex.
                for (size_t locVertIdx = 0; locVertIdx < faceIter.polygonVertexCount();
                        ++locVertIdx, ++faceVertIdx) {
                    int index=faceIter.normalIndex(locVertIdx);
                    for (int j=0;j<3;j++) {
                        meshNormals[faceVertIdx][j]=normalArray[index][j];
                    }
                }
            }
            primSchema.GetNormalsAttr().Set(meshNormals, usdTime);
            primSchema.SetNormalsInterpolation(normalInterp);
        }
    } else {
        TfToken sdInterpBound = PxrUsdMayaMeshUtil::getSubdivInterpBoundary(
            lMesh, UsdGeomTokens->edgeAndCorner);

        primSchema.CreateInterpolateBoundaryAttr(VtValue(sdInterpBound), true);
        
        TfToken sdFVInterpBound = PxrUsdMayaMeshUtil::getSubdivFVInterpBoundary(
            lMesh);

        primSchema.CreateFaceVaryingLinearInterpolationAttr(
            VtValue(sdFVInterpBound), true);

        assignSubDivTagsToUSDPrim( lMesh, primSchema);
    }

    // Holes - we treat InvisibleFaces as holes
    MUintArray mayaHoles = lMesh.getInvisibleFaces();
    if (mayaHoles.length() > 0) {
        VtArray<int> subdHoles(mayaHoles.length());
        for (unsigned int i=0; i < mayaHoles.length(); i++) {
            subdHoles[i] = mayaHoles[i];
        }
        // not animatable in Maya, so we'll set default only
        primSchema.GetHoleIndicesAttr().Set(subdHoles);
    }

    // == Write UVSets as Vec2f Primvars
    MStringArray uvSetNames;
    if (getArgs().exportMeshUVs) {
        status = lMesh.getUVSetNames(uvSetNames);
    }
    for (unsigned int i=0; i < uvSetNames.length(); i++) {
        // Initialize the VtArray to the max possible size (facevarying)
        VtArray<GfVec2f> uvValues(numFaceVertices);
        TfToken interpolation=TfToken();
        // Gather UV data and interpolation into a Vec2f VtArray and try to compress if possible
        if (_GetMeshUVSetData(lMesh, uvSetNames[i], &uvValues, &interpolation) == MS::kSuccess) {
        
            // XXX:bug 118447
            // We should be able to configure the UV map name that triggers this
            // behavior, and the name to which it exports.
            // The UV Set "map1" is renamed st. This is a Pixar/USD convention
            TfToken setName(uvSetNames[i].asChar());
            if (setName == "map1") setName=UsdUtilsGetPrimaryUVSetName();
       
            // Create the primvar and set the values
            UsdGeomPrimvar uvSet = 
                primSchema.CreatePrimvar(setName, SdfValueTypeNames->Float2Array, interpolation);
            uvSet.Set( uvValues ); // not animatable
        }
    }
    
    // == Gather ColorSets
    MStringArray colorSetNames;
    if (getArgs().exportColorSets) {
        status = lMesh.getColorSetNames(colorSetNames);
    }
    // shaderColor is used in our pipeline as displayColor.
    // shaderColor is used to fill faces where the colorset is not assigned
    MColorArray shaderColors;
    MObjectArray shaderObjs;
    
    VtArray<GfVec3f> shadersRGBData;
    TfToken shadersRGBInterp;
    VtArray<float> shadersAlphaData;
    TfToken shadersAlphaInterp;

    // If exportDisplayColor is set to true or we have color sets,
    // gather color & opacity from the shader including per face
    // assignment. Color set require this to initialize unauthored/unpainted faces 
    if (getArgs().exportDisplayColor or colorSetNames.length()>0) {
        PxrUsdMayaUtil::GetLinearShaderColor(lMesh, numPolygons, 
                &shadersRGBData, &shadersRGBInterp, 
                &shadersAlphaData, &shadersAlphaInterp);
    }

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

        bool isDisplayColor=false;

        if (colorSetNames[i]=="displayColor") {
            if (not getArgs().exportDisplayColor)
                continue;
            isDisplayColor=true;
        }
        
        if (colorSetNames[i]=="displayOpacity") {
            MGlobal::displayWarning("displayOpacity on mesh:" + lMesh.fullPathName() + 
            " is a reserved PrimVar name in USD. Skipping...");
            continue;
        }

        VtArray<GfVec3f> RGBData;
        TfToken RGBInterp;
        VtArray<GfVec4f> RGBAData;
        TfToken RGBAInterp;
        VtArray<float> AlphaData;
        TfToken AlphaInterp;
        MFnMesh::MColorRepresentation colorSetRep;
        bool clamped=false;

        // If displayColor uses shaderValues for non authored areas
        // and allow RGB and Alpha to have different interpolation
        // For all other colorSets the non authored values are set 
        // to (1,1,1,1) and RGB and Alpha will have the same interplation
        // since they will be emitted as a Vec4f
        if (not _GetMeshColorSetData( lMesh, colorSetNames[i],
                                        isDisplayColor,
                                        shadersRGBData, shadersAlphaData,
                                        &RGBData, &RGBInterp,
                                        &RGBAData, &RGBAInterp,
                                        &AlphaData, &AlphaInterp,
                                        &colorSetRep, &clamped)) {
            MGlobal::displayWarning("Unable to retrieve colorSet data: " +
                    colorSetNames[i] + " on mesh: "+ lMesh.fullPathName() + ". Skipping...");
            continue;
        }

        if (isDisplayColor) {
            // We tag the resulting displayColor/displayOpacity primvar as
            // authored to make sure we reconstruct the colorset on import
            // The RGB is also convererted From DisplayToLinear
            
            
            _setDisplayPrimVar( primSchema, colorSetRep,
                                RGBData, RGBInterp,
                                AlphaData, AlphaInterp,
                                clamped, true);
        } else {
            TfToken colorSetNameToken = TfToken(
                    PxrUsdMayaUtil::SanitizeColorSetName(
                        std::string(colorSetNames[i].asChar())));
            if (colorSetRep == MFnMesh::kAlpha) {
                    _createAlphaPrimVar(primSchema, colorSetNameToken,
                        AlphaData, AlphaInterp, clamped);
            } else if (colorSetRep == MFnMesh::kRGB) {
                    _createRGBPrimVar(primSchema, colorSetNameToken,
                        RGBData, RGBInterp, clamped);
            } else if (colorSetRep == MFnMesh::kRGBA) {
                    _createRGBAPrimVar(primSchema, colorSetNameToken,
                        RGBAData, RGBAInterp, clamped);
            }
        }
    }
    // Set displayColor and displayOpacity only if they are NOT authored already
    // Since this primvar will come from the shader and not a colorset,
    // we are not adding the clamp attribute as custom data
    // If a displayColor/displayOpacity is added, it's not considered authored
    // we don't need to reconstruct this as a colorset since it orgininated
    // from bound shader[s], so the authored flag is set to false
    // Given that this RGB is for display, we do DisplayToLinear conversion
    if (getArgs().exportDisplayColor) {
        _setDisplayPrimVar( primSchema, MFnMesh::kRGBA,
                                shadersRGBData, shadersRGBInterp,
                                shadersAlphaData, shadersAlphaInterp,
                                false, false);
    }
    return true;
}
Example #3
0
File: Mesh.cpp Project: cpzhang/zen
MStatus Mesh::load(MDagPath& meshDag,MDagPath *pDagPath)
{
	MStatus stat;
	std::vector<MFloatArray> weights;
	std::vector<MIntArray> Ids;
	std::vector<MIntArray> jointIds;
	unsigned int numJoints = 0;
	std::vector<vertexInfo> vertices;
	MFloatPointArray points;
	MFloatVectorArray normals;

	if (!meshDag.hasFn(MFn::kMesh))
		return MS::kFailure;

	MFnMesh mesh(meshDag);
	/*{
		mesh.getPoints(points,MSpace::kWorld);
		MPoint pos;
		mesh.getPoint(1,pos,MSpace::kWorld);
		for(unsigned i = 0;i < points.length();i++)
		{
			MFloatPoint fp = points[i];
			float x = fp.x;
			float y = fp.y;
			float z = fp.z;
			fp = fp;
		}
	}*/
	int numVertices = mesh.numVertices();
	vertices.resize(numVertices);
	weights.resize(numVertices);
	Ids.resize(numVertices);
	jointIds.resize(numVertices);

	// 获取UV坐标集的名称
	MStringArray uvsets;
	int numUVSets = mesh.numUVSets();
	if (numUVSets > 0)
	{
		stat = mesh.getUVSetNames(uvsets);
		if (MS::kSuccess != stat)
		{
			std::cout << "Error retrieving UV sets names\n";
			return MS::kFailure;
		}
	}
	// 保存UV集信息
	for (int i=m_uvsets.size(); i<uvsets.length(); i++)
	{
		uvset uv;
		uv.size = 2;
		uv.name = uvsets[i].asChar();
		m_uvsets.push_back(uv);
	}

	MStringArray colorSetsNameArray;
	m_colorSets.clear();
	int numColorSets = mesh.numColorSets();
	if (numColorSets > 0)
	{
		mesh.getColorSetNames(colorSetsNameArray);
	}
	for (int i = 0; i != colorSetsNameArray.length(); ++i)
	{
		std::string name = colorSetsNameArray[i].asChar();
		m_colorSets.push_back(name);
	}
	// 检查法线是否反
	bool opposite = false;
	mesh.findPlug("opposite",true).getValue(opposite);

	// get connected skin cluster (if present)
	bool foundSkinCluster = false;
	MItDependencyNodes kDepNodeIt( MFn::kSkinClusterFilter );            
	for( ;!kDepNodeIt.isDone() && !foundSkinCluster; kDepNodeIt.next()) 
	{            
		MObject kObject = kDepNodeIt.item();
		m_pSkinCluster = new MFnSkinCluster(kObject);
		unsigned int uiNumGeometries = m_pSkinCluster->numOutputConnections();
		for(unsigned int uiGeometry = 0; uiGeometry < uiNumGeometries; ++uiGeometry ) 
		{
			unsigned int uiIndex = m_pSkinCluster->indexForOutputConnection(uiGeometry);
			MObject kOutputObject = m_pSkinCluster->outputShapeAtIndex(uiIndex);
			if(kOutputObject == mesh.object()) 
			{
				foundSkinCluster = true;
			}
			else
			{
				delete m_pSkinCluster;
				m_pSkinCluster = NULL;
			}
		}

		// load connected skeleton (if present)
		if (m_pSkinCluster)
		{
			if (!m_pSkeleton)
				m_pSkeleton = new skeleton();
			stat = m_pSkeleton->load(m_pSkinCluster);
			if (MS::kSuccess != stat)
				std::cout << "Error loading skeleton data\n";
		}
		else
		{
//			breakable;
		}
	}
	// get connected shaders
	MObjectArray shaders;
	MIntArray shaderPolygonMapping;
	stat = mesh.getConnectedShaders(0,shaders,shaderPolygonMapping);
	if (MS::kSuccess != stat)
	{
		std::cout << "Error getting connected shaders\n";
		return MS::kFailure;
	}

	if (shaders.length() <= 0)
	{
		std::cout << "No connected shaders, skipping mesh\n";
		return MS::kFailure;
	}

	// create a series of arrays of faces for each different submesh
	std::vector<faceArray> polygonSets;
	polygonSets.resize(shaders.length());

	// Get faces data
	// prepare vertex table
	for (int i=0; i<vertices.size(); i++)
		vertices[i].next = -2;
	//get vertex positions from mesh data

	mesh.getPoints(points,MSpace::kWorld);
	mesh.getNormals(normals,MSpace::kWorld);

	//get list of vertex weights
	if (m_pSkinCluster)
	{
		MItGeometry iterGeom(meshDag);
		for (int i=0; !iterGeom.isDone(); iterGeom.next(), i++)
		{
			weights[i].clear();
			Ids[i].clear();
			MObject component = iterGeom.component();
			MFloatArray vertexWeights;
			stat=m_pSkinCluster->getWeights(meshDag,component,vertexWeights,numJoints);
			int nWeights = vertexWeights.length();
			for(int j = 0;j<nWeights;j++)
			{
				if(vertexWeights[j] >= 0.00001f || vertexWeights[j] <= -0.00001f  )
				{
					// 记录该节点j
					Ids[i].append(j);
					weights[i].append(vertexWeights[j]);
				}
			}
		
			//weights[i]= vertexWeights;

			if (MS::kSuccess != stat)
			{
				std::cout << "Error retrieving vertex weights\n";
			}
			// get ids for the joints
			if (m_pSkeleton)
			{
				jointIds[i].clear();
				if(weights[i].length() > 0 )
				{
					MDagPathArray influenceObjs;
					m_pSkinCluster->influenceObjects(influenceObjs,&stat);
					if (MS::kSuccess != stat)
					{
						std::cout << "Error retrieving influence objects for given skin cluster\n";
					}
					jointIds[i].setLength(weights[i].length());
					for (int j=0; j<jointIds[i].length(); j++)
					{
						bool foundJoint = false;
						for (int k=0; k<m_pSkeleton->getJoints().size() && !foundJoint; k++)
						{
							if (influenceObjs[Ids[i][j]].partialPathName() == m_pSkeleton->getJoints()[k].name)
							{
								foundJoint=true;
								jointIds[i][j] = m_pSkeleton->getJoints()[k].id;
							}
						}
					}
				}
				
			}
		}
	}
	// create an iterator to go through mesh polygons
	if (mesh.numPolygons() > 0)
	{
		const char *name = mesh.name().asChar();
		MItMeshPolygon faceIter(mesh.object(),&stat);
		if (MS::kSuccess != stat)
		{
			std::cout << "Error accessing mesh polygons\n";
			return MS::kFailure;
		}

		// iterate over mesh polygons
		for (; !faceIter.isDone(); faceIter.next())
		{
			int numTris=0;
			faceIter.numTriangles(numTris);
			// for every triangle composing current polygon extract triangle info
			for (int iTris=0; iTris<numTris; iTris++)
			{
				MPointArray triPoints;
				MIntArray tempTriVertexIdx,triVertexIdx;
				int idx;
				// create a new face to store triangle info
				face newFace;
				// extract triangle vertex indices
				faceIter.getTriangle(iTris,triPoints,tempTriVertexIdx);
				// convert indices to face-relative indices
				MIntArray polyIndices;
				faceIter.getVertices(polyIndices);
				unsigned int iPoly, iObj;
				for (iObj=0; iObj < tempTriVertexIdx.length(); ++iObj)
				{
					// iPoly is face-relative vertex index
					for (iPoly=0; iPoly < polyIndices.length(); ++iPoly)
					{
						if (tempTriVertexIdx[iObj] == polyIndices[iPoly]) 
						{
							triVertexIdx.append(iPoly);
							break;
						}
					}
				}
				// iterate over triangle's vertices
				for (int i=0; i<3; i++)
				{
					bool different = true;
					int vtxIdx = faceIter.vertexIndex(triVertexIdx[i]);
					int nrmIdx = faceIter.normalIndex(triVertexIdx[i]);

					// get vertex color
					MColor color;
					if (faceIter.hasColor(triVertexIdx[i]))
					{
						//This method gets the average color of the all the vertices in this face
						stat = faceIter.getColor(color,triVertexIdx[i]);
						if (MS::kSuccess != stat)
						{
							color = MColor(1,1,1,1);
						}
						if (color.r > 1)
							color.r = 1;
						if (color.g > 1)
							color.g = 1;
						if (color.b > 1)
							color.b = 1;
						if (color.a > 1)
							color.a = 1;
					}
					else
					{
						color = MColor(1,1,1,1);
					}
					if (vertices[vtxIdx].next == -2)	// first time we encounter a vertex in this position
					{
						// save vertex position
						points[vtxIdx].cartesianize();
						vertices[vtxIdx].pointIdx = vtxIdx;
						// save vertex normal
						vertices[vtxIdx].normalIdx = nrmIdx;
						// save vertex colour
						vertices[vtxIdx].r = color.r;
						vertices[vtxIdx].g = color.g;
						vertices[vtxIdx].b = color.b;
						vertices[vtxIdx].a = color.a;
						// save vertex texture coordinates
						vertices[vtxIdx].u.resize(uvsets.length());
						vertices[vtxIdx].v.resize(uvsets.length());
						// save vbas
						vertices[vtxIdx].vba.resize(weights[vtxIdx].length());
						for (int j=0; j<weights[vtxIdx].length(); j++)
						{
							vertices[vtxIdx].vba[j] = (weights[vtxIdx])[j];
						}
						// save joint ids
						vertices[vtxIdx].jointIds.resize(jointIds[vtxIdx].length());
						for (int j=0; j<jointIds[vtxIdx].length(); j++)
						{
							vertices[vtxIdx].jointIds[j] = (jointIds[vtxIdx])[j];
						}
						// save uv sets data
						for (int j=0; j<uvsets.length(); j++)
						{
							float2 uv;
							stat = faceIter.getUV(triVertexIdx[i],uv,&uvsets[j]);
							if (MS::kSuccess != stat)
							{
								uv[0] = 0;
								uv[1] = 0;
							}
							vertices[vtxIdx].u[j] = uv[0];
							vertices[vtxIdx].v[j] = (-1)*(uv[1]-1);
						}
						// save vertex index in face info
						newFace.v[i] = vtxIdx;
						// update value of index to next vertex info (-1 means nothing next)
						vertices[vtxIdx].next = -1;
					}
					else	// already found at least 1 vertex in this position
					{
						// check if a vertex with same attributes has been saved already
						for (int k=vtxIdx; k!=-1 && different; k=vertices[k].next)
						{
							different = false;

							MFloatVector n1 = normals[vertices[k].normalIdx];
							MFloatVector n2 = normals[nrmIdx];
							if (n1.x!=n2.x || n1.y!=n2.y || n1.z!=n2.z)
							{
								different = true;
							}


							if (vertices[k].r!=color.r || vertices[k].g!=color.g || vertices[k].b!= color.b || vertices[k].a!=color.a)
							{
								different = true;
							}

							for (int j=0; j<uvsets.length(); j++)
							{
								float2 uv;
								stat = faceIter.getUV(triVertexIdx[i],uv,&uvsets[j]);
								if (MS::kSuccess != stat)
								{
									uv[0] = 0;
									uv[1] = 0;
								}
								uv[1] = (-1)*(uv[1]-1);
								if (vertices[k].u[j]!=uv[0] || vertices[k].v[j]!=uv[1])
								{
									different = true;
								}
							}

							idx = k;
						}
						// if no identical vertex has been saved, then save the vertex info
						if (different)
						{
							vertexInfo vtx;
							// save vertex position
							vtx.pointIdx = vtxIdx;
							// save vertex normal
							vtx.normalIdx = nrmIdx;
							// save vertex colour
							vtx.r = color.r;
							vtx.g = color.g;
							vtx.b = color.b;
							vtx.a = color.a;
							// save vertex vba
							vtx.vba.resize(weights[vtxIdx].length());
							for (int j=0; j<weights[vtxIdx].length(); j++)
							{
								vtx.vba[j] = (weights[vtxIdx])[j];
							}
							// save joint ids
							vtx.jointIds.resize(jointIds[vtxIdx].length());
							for (int j=0; j<jointIds[vtxIdx].length(); j++)
							{
								vtx.jointIds[j] = (jointIds[vtxIdx])[j];
							}
							// save vertex texture coordinates
							vtx.u.resize(uvsets.length());
							vtx.v.resize(uvsets.length());
							for (int j=0; j<uvsets.length(); j++)
							{
								float2 uv;
								stat = faceIter.getUV(triVertexIdx[i],uv,&uvsets[j]);
								if (MS::kSuccess != stat)
								{
									uv[0] = 0;
									uv[1] = 0;
								}
								vtx.u[j] = uv[0];
								vtx.v[j] = (-1)*(uv[1]-1);
							}
							vtx.next = -1;
							vertices.push_back(vtx);
							// save vertex index in face info
							newFace.v[i] = vertices.size()-1;
							vertices[idx].next = vertices.size()-1;
						}
						else
						{
							newFace.v[i] = idx;
						}
					}
				} // end iteration of triangle vertices
				// add face info to the array corresponding to the submesh it belongs
				// skip faces with no shaders assigned
				if (shaderPolygonMapping[faceIter.index()] >= 0)
					polygonSets[shaderPolygonMapping[faceIter.index()]].push_back(newFace);
			} // end iteration of triangles
		}
	}
	std::cout << "done reading mesh triangles\n";

	// create a submesh for every different shader linked to the mesh
	unsigned shaderLength = shaders.length();
	for (int i=0; i<shaderLength; i++)
	{
		// check if the submesh has at least 1 triangle
		if (polygonSets[i].size() > 0)
		{
			//create new submesh
			SubMesh* pSubmesh = new SubMesh();
const char *nm = mesh.name().asChar();
const char *nm1 = mesh.partialPathName().asChar();
const char *nm2 = mesh.parentNamespace().asChar();
const char *nm3 = mesh.fullPathName().asChar();
const char *nm4 = meshDag.fullPathName().asChar();

			pSubmesh->m_name = meshDag.partialPathName();
			if(pDagPath)
				pSubmesh->m_name = pDagPath->partialPathName();
			const char *szName = pSubmesh->m_name.asChar();

			if(shaderLength > 1)
			{
				char a[256];
				sprintf(a,"%d",i);
				pSubmesh->m_name += a;
			}
			OutputDebugString(pSubmesh->m_name.asChar());
			OutputDebugString("\n");

			//OutputDebugString(szName);
			//OutputDebugString("\n");

			//load linked shader
			stat = pSubmesh->loadMaterial(shaders[i],uvsets);
			if (stat != MS::kSuccess)
			{
				MFnDependencyNode shadingGroup(shaders[i]);
				std::cout << "Error loading submesh linked to shader " << shadingGroup.name().asChar() << "\n";
				return MS::kFailure;
			}

			//load vertex and face data
			stat = pSubmesh->load(polygonSets[i],vertices,points,normals,opposite);

			//add submesh to current mesh
			m_submeshes.push_back(pSubmesh);
		}
	}

	return MS::kSuccess;
}
Example #4
0
void VMesh::save(const char* filename, int isStart)
{
	MStatus status;
	MFnMesh meshFn(pgrow, &status );
	MItMeshPolygon faceIter( pgrow, &status );
	MItMeshVertex vertIter(pgrow, &status);
	
	int m_n_triangle=0, m_n_vertex=0;
	MIntArray m_vertex_id;
	MFloatArray facevarying_s, facevarying_t;
	MPointArray m_vertex_p;
	MVectorArray m_vertex_n, m_vertex_t;
	
	meshFn.getPoints(m_vertex_p, MSpace::kWorld);
	float auv[2];
	faceIter.reset();
	for( ; !faceIter.isDone(); faceIter.next() ) 
	{
		MIntArray vexlist;
		faceIter.getVertices ( vexlist );
		m_n_triangle += vexlist.length() - 2;
		for( unsigned int i=1; i < vexlist.length()-1; i++ ) 
		{
			m_vertex_id.append(vexlist[0]);
			m_vertex_id.append(vexlist[i]);
			m_vertex_id.append(vexlist[i+1]);
			faceIter.getUV(0, auv);
			facevarying_s.append(auv[0]);
			facevarying_t.append(auv[1]);
			faceIter.getUV(i, auv);
			facevarying_s.append(auv[0]);
			facevarying_t.append(auv[1]);
			faceIter.getUV(i+1, auv);
			facevarying_s.append(auv[0]);
			facevarying_t.append(auv[1]);
		}
	}
	
	XYZ* pbinormal = new XYZ[meshFn.numVertices()];
	XYZ* pv = new XYZ[meshFn.numVertices()];
	float* pscale = new float[meshFn.numVertices()];
	float* curlarray = new float[meshFn.numVertices()];
	float* widtharray = new float[meshFn.numVertices()];
	float* densityarray = new float[meshFn.numVertices()];
	
	MVector tnor, tang, ttang, binormal, dir, hair_up, hair_v;
	MPoint tpos;
	MColor Cscale, Cerect, Crotate, Cstiff, Ccurl, Cwidth, Cdensity;
	float rot;
	MATRIX44F hair_space, hair_space_inv;
	
	MString setScale("fb_scale");
	MString setErect("fb_erect");
	MString setRotate("fb_rotate");
	MString setStiff("fb_stiffness");
	MString setCurl("fb_curl");
	MString setWidth("fb_width");
	MString setDensity("fb_density");
	MIntArray conn_face;
	
	XYZ dP;
	
	vertIter.reset();
	for( int i=0; !vertIter.isDone(); vertIter.next(), i++ )
	{
		vertIter.getConnectedFaces(conn_face);
		
		vertIter.getNormal(tnor, MSpace::kWorld);
		tnor.normalize();
		m_vertex_n.append(tnor);
		
		vertIter.getColor(Cscale, &setScale);
		vertIter.getColor(Cerect, &setErect);
		vertIter.getColor(Crotate, &setRotate);
		vertIter.getColor(Cstiff, &setStiff);
		vertIter.getColor(Ccurl, &setCurl);
		vertIter.getColor(Cwidth, &setWidth);
		vertIter.getColor(Cdensity, &setDensity);
		if(Cstiff.r < 0.1) Cstiff.r = 0.1;
		
		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 = tnor^tang;
		tang.normalize();
		
		binormal = tnor^tang;
		
		if(Crotate.r<0.5)
		{
			rot = (0.5 - Crotate.r)*2;
			tang = tang + (binormal-tang)*rot;
			tang.normalize();
			binormal = tnor^tang;
		}
		else
		{
			rot = (Crotate.r-0.5)*2;
			tang = tang + (binormal*-1-tang)*rot;
			tang.normalize();
			binormal = tnor^tang;
		}
		
		pbinormal[i] = XYZ(binormal.x, binormal.y, binormal.z);
		pscale[i] = Cscale.r * m_scale;
		
		dir = tang + (tnor - tang)*Cerect.r;
		dir.normalize();
		
		m_vertex_t.append(dir);
		
		hair_up = dir^binormal;
		//pup[i] = XYZ(hair_up.x, hair_up.y, hair_up.z);
		
		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));
		hair_space.setTranslation(XYZ(m_vertex_p[i].x, m_vertex_p[i].y, m_vertex_p[i].z));
		hair_space_inv = hair_space;
		hair_space_inv.inverse();
		
		hair_v = getVelocity(i);
		dP = XYZ(hair_v.x, hair_v.y, hair_v.z);
		hair_space_inv.transformAsNormal(dP);
		if(dP.y<0) dP.y = 0;
		dP *= m_wind/Cstiff.r;
		
		pv[i] = dP;
		
		curlarray[i] = Ccurl.r;
		widtharray[i] = Cwidth.r;
		densityarray[i] = Cdensity.r;
	}

	m_n_vertex = meshFn.numVertices();
	
	FXMLTriangleMap fmap;
	fmap.beginMap(filename);
	
// write vertex id
	string static_path(filename);
	zGlobal::cutByFirstDot(static_path);
	static_path.append(".hbs");
	
	if(isStart == 1)
	{
		fmap.staticBegin(static_path.c_str(), m_n_triangle);
	
		int* id_list = new int[m_n_triangle*3];
		for(int i=0; i<m_n_triangle*3; i++) id_list[i] = m_vertex_id[i];
	
		fmap.addVertexId(m_n_triangle*3, id_list);
		delete[] id_list;
		
		float* sarray = new float[m_n_triangle*3];
		float* tarray = new float[m_n_triangle*3];
		for(int i=0; i<m_n_triangle*3; i++) 
		{
			sarray[i] = facevarying_s[i];
			tarray[i] = facevarying_t[i];
		}
		fmap.addStaticFloatArray("root_s", m_n_triangle*3, sarray);
		fmap.addStaticFloatArray("root_t", m_n_triangle*3, tarray);
		
		delete[] sarray;
		delete[] tarray;
		
		XYZ* recpref = new XYZ[m_n_vertex];
	
		for(int i=0; i<m_n_vertex; i++) recpref[i] = XYZ(m_vertex_p[i].x, m_vertex_p[i].y, m_vertex_p[i].z);
		fmap.addPref(m_n_vertex, recpref);
		delete[] recpref;
		
		fmap.addStaticFloatArray("scale", m_n_vertex, pscale);
		
		fmap.addStaticFloatArray("curl", m_n_vertex, curlarray);

		fmap.addStaticFloatArray("width", m_n_vertex, widtharray);
	
		fmap.addStaticFloatArray("density", m_n_vertex, densityarray);
	
		fmap.staticEnd();
	}
	else
	{
		fmap.staticBeginNoWrite(static_path.c_str(), m_n_triangle);
	
		fmap.addVertexId(m_n_triangle*3);
		fmap.addStaticFloatArray("root_s", m_n_triangle*3);
		fmap.addStaticFloatArray("root_t", m_n_triangle*3);
		fmap.addPref(m_n_vertex);
		fmap.addStaticFloatArray("scale", m_n_vertex);
		fmap.addStaticFloatArray("curl", m_n_vertex);
		fmap.addStaticFloatArray("width", m_n_vertex);
		fmap.addStaticFloatArray("density", m_n_vertex);
		
		fmap.staticEndNoWrite();
	}
	
	delete[] curlarray;
	delete[] widtharray;
	delete[] densityarray;

// write vertex p
	string dynamic_path(filename);
	zGlobal::cutByLastDot(dynamic_path);
	dynamic_path.append(".hbd");
	
	fmap.dynamicBegin(dynamic_path.c_str());
	
	XYZ* recp = new XYZ[m_n_vertex];
	
	for(int i=0; i<m_n_vertex; i++) recp[i] = XYZ(m_vertex_p[i].x, m_vertex_p[i].y, m_vertex_p[i].z);
	fmap.addP(m_n_vertex, recp);
	delete[] recp;
	
// write vertex n
	XYZ* recn = new XYZ[m_n_vertex];
	
	for(int i=0; i<m_n_vertex; i++) recn[i] = XYZ(m_vertex_n[i].x, m_vertex_n[i].y, m_vertex_n[i].z);
	fmap.addN(m_n_vertex, recn);
	delete[] recn;
	
// write veretx tangent
	XYZ* rect = new XYZ[m_n_vertex];
	
	for(int i=0; i<m_n_vertex; i++) rect[i] = XYZ(m_vertex_t[i].x, m_vertex_t[i].y, m_vertex_t[i].z);
	fmap.addDynamicVectorArray("direction", m_n_vertex, rect);
	delete[] rect;
	
// write vertex binormal
	fmap.addDynamicVectorArray("binormal", m_n_vertex, pbinormal);
	delete[] pbinormal;
	

	
// write vertex up
//	fmap.addDynamicVectorArray("up", m_n_vertex, pup);
//	delete[] pup;
	
// write vertex wind
	fmap.addDynamicVectorArray("wind", m_n_vertex, pv);
	delete[] pv;

// write bound box	
	MPoint corner_l, corner_h;
	
	getBBox(corner_l, corner_h);
	
	fmap.addBBox(corner_l.x, corner_l.y, corner_l.z, corner_h.x, corner_h.y, corner_h.z);
	
	fmap.dynamicEnd();
	
	fmap.endMap(filename);
	
	char info[256];
	sprintf(info, "hairBase writes %s", filename);
	MGlobal::displayInfo ( info );
	
	m_vertex_id.clear();
	m_vertex_p.clear();
	m_vertex_n.clear();
	m_vertex_t.clear();

	delete[] pscale;
}
Example #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;
}
Example #6
0
// write a normal mesh
//
MStatus vxCache::writeMesh(const char* filename, MDagPath meshDag, const MObject& meshObj)
{	
	struct meshInfo mesh;

	MString uvset("map1");
	
	MStatus status;
	MFnMesh meshFn(meshDag, &status );
	MItMeshPolygon faceIter( meshDag, MObject::kNullObj, &status );
	MItMeshVertex vertIter(meshDag, MObject::kNullObj, &status);
	MItMeshEdge edgeIter(meshDag, MObject::kNullObj, &status);
	
	mesh.numPolygons = meshFn.numPolygons();
	mesh.numVertices = meshFn.numVertices();
	mesh.numFaceVertices = meshFn.numFaceVertices();
	mesh.numUVs = meshFn.numUVs(uvset, &status);
	mesh.skip_interreflection = mesh.skip_scattering = 0;
	
	//if(zWorks::hasNamedAttribute(meshObj, "_prt_ig_intr") == 1) mesh.skip_interreflection = 1;
	//if(zWorks::hasNamedAttribute(meshObj, "_prt_ig_scat") == 1) mesh.skip_scattering = 1;

	//zWorks::displayIntParam("N Face", mesh.numPolygons);
	//zWorks::displayIntParam("N Vertex", mesh.numVertices);
	//zWorks::displayIntParam("N Facevertex", mesh.numFaceVertices);
	//zWorks::displayIntParam("N UV", mesh.numUVs);
	
	int *fcbuf = new int[mesh.numPolygons];
	faceIter.reset();
	for( ; !faceIter.isDone(); faceIter.next() ) 
	{
		fcbuf[ faceIter.index() ] = faceIter.polygonVertexCount();
	}

	int* vertex_id = new int[mesh.numFaceVertices];
	int* uv_id = new int[mesh.numFaceVertices];
// output face loop
	int acc = 0;
	faceIter.reset();
	for( ; !faceIter.isDone(); faceIter.next() ) 
	{
		MIntArray  vexlist;
		faceIter.getVertices ( vexlist );
		for( unsigned int i=0; i < vexlist.length(); i++ ) 
		{
			vertex_id[acc] = vexlist[i];
			faceIter.getUVIndex ( i, uv_id[acc] );
			acc++;
		}
	}
	
// output vertices
	MPointArray pArray;
	
	if(worldSpace) meshFn.getPoints ( pArray, MSpace::kWorld);
	else meshFn.getPoints ( pArray, MSpace::kObject );
	
	XYZ *pbuf = new XYZ[pArray.length()];
	
	for( unsigned int i=0; i<pArray.length(); i++) 
	{
		pbuf[i].x = pArray[i].x;
		pbuf[i].y = pArray[i].y;
		pbuf[i].z= pArray[i].z;
	}

//output texture coordinate
	MFloatArray uArray, vArray;
	meshFn.getUVs ( uArray, vArray, &uvset );

	double* ubuf = new double[mesh.numUVs];
	double* vbuf = new double[mesh.numUVs];
	
	for( unsigned int i=0; i<uArray.length(); i++) 
	{
		ubuf[i] = uArray[i];
		vbuf[i] = vArray[i];
	}
/*
	XYZ *norbuf = new XYZ[mesh.numVertices];
	vertIter.reset();
	MVector tnor;
	
	for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ )
	{
		if(worldSpace) vertIter.getNormal(tnor, MSpace::kWorld);
		else vertIter.getNormal(tnor, MSpace::kObject);
		tnor.normalize();
		norbuf[i].x = tnor.x;
		norbuf[i].y = tnor.y;
		norbuf[i].z = tnor.z;
	}

	MStatus hasAttr;
	MString sColorSet("set_prt_attr");
	meshFn.numColors( sColorSet,  &hasAttr );
	
	XYZ *colbuf = new XYZ[mesh.numVertices];
	vertIter.reset();
	if(hasAttr)
	{
		MColor col;
		for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ )
		{
			MIntArray conn_face;
			vertIter.getConnectedFaces(conn_face);
			vertIter.getColor(col, conn_face[0], &sColorSet);
			colbuf[i].x = col.r;
			colbuf[i].y = col.g;
			colbuf[i].z = col.b;
		}
	}
	else
	{
		for( unsigned int i=0; i<vertIter.count(); i++ ) colbuf[i] = XYZ(1.0f);
	}
	
	vertIter.reset();
	XYZ *vsbuf = new XYZ[mesh.numVertices];
	for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ )
	{
		MIntArray conn_face, conn_edge;
		vertIter.getConnectedFaces(conn_face);
		vertIter.getConnectedEdges(conn_edge);
		MPoint Q;
		for(unsigned j=0; j<conn_face.length(); j++)
		{
			int pre_id;
			faceIter.setIndex(conn_face[j],pre_id);
			Q += faceIter.center(MSpace::kWorld);
		}
		Q = Q/(double)conn_face.length();
		
		MPoint R;
		for(unsigned j=0; j<conn_edge.length(); j++)
		{
			int pre_id;
			edgeIter.setIndex(conn_edge[j], pre_id);
			R += edgeIter.center(MSpace::kWorld);
		}
		R = R/(double)conn_edge.length();
		
		MPoint S = vertIter.position(MSpace::kWorld);
		
		int nv = conn_edge.length();
		MPoint nS = (Q + R*2 + S*(nv-3))/nv;

		vsbuf[i].x = nS.x;
		vsbuf[i].y = nS.y;
		vsbuf[i].z = nS.z;
	}
	
	XYZ *tangbuf = new XYZ[mesh.numVertices];
	
	vertIter.reset();
	for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ )
	{
		MIntArray conn_face;
		MVector tang(0,0,0);
		vertIter.getConnectedFaces(conn_face);
		
		//for(int j = 0; j<conn_face.length(); j++) 
		{
			MVector ttang;
			meshFn.getFaceVertexTangent (conn_face[0], i,  ttang,  MSpace::kWorld, &uvset);
			tang += ttang;
		}
		tang.normalize();
		tangbuf[i].x = tang.x;
		tangbuf[i].y = tang.y;
		tangbuf[i].z = tang.z;
		
		tangbuf[i] = norbuf[i].cross(tangbuf[i]);
		tangbuf[i].normalize();
	}
*/	
	FMCFMesh fmesh;
	fmesh.save(mesh.numVertices, 
			mesh.numFaceVertices, 
			mesh.numPolygons, 
			mesh.numUVs, 
			mesh.skip_interreflection,
			mesh.skip_scattering,
			fcbuf, 
			vertex_id, 
			uv_id,
			pbuf,
			//vsbuf,
			//norbuf,
			//tangbuf,
			//colbuf,
			ubuf,
			vbuf,
			filename);
			
	delete[] fcbuf;
	delete[] vertex_id;
	delete[] uv_id;
	delete[] pbuf;
	//delete[] vsbuf;
	//delete[] norbuf;
	//delete[] tangbuf;
	//delete[] colbuf;
	delete[] ubuf;
	delete[] vbuf;

	return MS::kSuccess;
}
Example #7
0
void getPointAndNormal(MDagPath meshDagPath, int faceIndex, bool relative, double parameterU, double parameterV, MPoint &point, MVector &normal, MObject theMesh)

{

   // CREATE FACE ITERATOR, AND SET ITS INDEX TO THAT OF THE SPECIFIED FACE:

   MItMeshPolygon faceIter(meshDagPath);

   if (theMesh!=MObject::kNullObj)

      faceIter.reset(theMesh);

   int dummyIndex;

   faceIter.setIndex(faceIndex, dummyIndex);



   // WHEN "RELATIVE" MODE IS SPECIFIED, CALCULATE THE *ABSOLUTE* UV'S FROM THE SPECIFIED FACE AND "RELATIVE" UV'S:

   float u, v;

   if (relative)

   {

      MFloatArray uArray, vArray;

      faceIter.getUVs(uArray, vArray);

      float minU=999999, minV=999999, maxU=0, maxV=0;

      for (unsigned i=0; i<uArray.length(); i++)

      {

         minU = (uArray[i] < minU) ? uArray[i] : minU;

         minV = (vArray[i] < minV) ? vArray[i] : minV;

         maxU = (uArray[i] > maxU) ? uArray[i] : maxU;

         maxV = (vArray[i] > maxV) ? vArray[i] : maxV;

      }

      u = minU + (float)parameterU * (maxU - minU);

      v = minV + (float)parameterV * (maxV - minV);

   }

   // OTHERWISE, JUST TAKE THE ABSOLUTE UV'S TO BE THE ONES SPECIFIED:

   else

   {

      u = (float)parameterU;

      v = (float)parameterV;

   }



   // FIND THE WORLDSPACE COORDINATE AT THE SPECIFIED UV:

   float2 UV;

   UV[0] = u;

   UV[1] = v;

   faceIter.getPointAtUV(point, UV, MSpace::kWorld);



   // FIND THE NORMAL AT THE SPECIFIED UV:

   MFnMesh meshFn(meshDagPath);

   if (theMesh!=MObject::kNullObj)

      meshFn.setObject(theMesh);

   meshFn.getClosestNormal(point, normal, MSpace::kWorld);

}
Example #8
0
void ExportACache::save(const char* filename, int frameNumber, char bfirst)
{	
	MStatus status;
	FXMLScene xml_f;
	xml_f.begin(filename, frameNumber, bfirst);
	for(unsigned it=0; it<m_mesh_list.length(); it++) {
		m_mesh_list[it].extendToShape();
		
		MString surface = m_mesh_list[it].partialPathName();
	
		AHelper::validateFilePath(surface);
		
		MFnDependencyNode fnode(m_mesh_list[it].node());
		MString smsg("prtMsg");
		MStatus hasMsg;
		MPlug pmsg = fnode.findPlug( smsg, 1,  &hasMsg );
		
		char bNoChange = 0;
		if(hasMsg) {
			MObject oattrib;
			AHelper::getConnectedNode(oattrib, pmsg);
			fnode.setObject(oattrib);

			bool iattr = 0;
			
			AHelper::getBoolAttributeByName(fnode, "noChange", iattr);
			if(iattr) bNoChange = 1;
		}

		xml_f.meshBegin(surface.asChar(), bNoChange);
	
		MFnMesh meshFn(m_mesh_list[it], &status );
		MItMeshPolygon faceIter(m_mesh_list[it], MObject::kNullObj, &status );
		MItMeshVertex vertIter(m_mesh_list[it], MObject::kNullObj, &status);
		MItMeshEdge edgeIter(m_mesh_list[it], MObject::kNullObj, &status);
		
		int n_tri = 0;
		float f_area = 0;
		double area;
		
		faceIter.reset();
		for( ; !faceIter.isDone(); faceIter.next() ) {
			MIntArray vexlist;
			faceIter.getVertices ( vexlist );
			n_tri += vexlist.length() - 2;
			
			faceIter.getArea( area,  MSpace::kWorld );
			f_area += (float)area;
		}
		
		xml_f.triangleInfo(n_tri, f_area);
		
		float avg_grid = sqrt(f_area/n_tri)/2;
		
		double light_intensity = 1.0;
		
		if(hasMsg) {
			MObject oattrib;
			AHelper::getConnectedNode(oattrib, pmsg);
			fnode.setObject(oattrib);

			bool iattr = 0;
			
			AHelper::getBoolAttributeByName(fnode, "noChange", iattr);
			if(iattr) xml_f.addAttribute("noChange", 1);
			
			AHelper::getBoolAttributeByName(fnode, "skipIndirect", iattr);
			if(iattr) xml_f.addAttribute("skipIndirect", 1);
			
			iattr = 0;
			AHelper::getBoolAttributeByName(fnode, "skipScatter", iattr);
			if(iattr) xml_f.addAttribute("skipScatter", 1);
			
			iattr = 0;
			AHelper::getBoolAttributeByName(fnode, "skipBackscatter", iattr);
			if(iattr) xml_f.addAttribute("skipBackscatter", 1);
			
			iattr = 0;
			AHelper::getBoolAttributeByName(fnode, "asLightsource", iattr);
			if(iattr) xml_f.addAttribute("asLightsource", 1);
			
			iattr = 0;
			AHelper::getBoolAttributeByName(fnode, "asGhost", iattr);
			if(iattr) xml_f.addAttribute("invisible", 1);
			
			iattr = 0;
			AHelper::getBoolAttributeByName(fnode, "castNoShadow", iattr);
			if(iattr) xml_f.addAttribute("noShadow", 1);
			
			double td;
			if(AHelper::getDoubleAttributeByName(fnode, "lightIntensity", td)) light_intensity = td;
			
			fnode.setObject(m_mesh_list[it].node());
		}

		xml_f.staticBegin();
		
		int n_poly = meshFn.numPolygons();
		int n_vert = meshFn.numVertices();
		int* polycount = new int[n_poly];
		
		faceIter.reset();
		for( ; !faceIter.isDone(); faceIter.next() ) polycount[ faceIter.index() ] = faceIter.polygonVertexCount();
		
		xml_f.addFaceCount(n_poly, polycount);
		delete[] polycount;
		
		int n_facevertex = meshFn.numFaceVertices();
		int* polyconnect = new int[n_facevertex];
		
		int acc = 0;
		faceIter.reset();
		for( ; !faceIter.isDone(); faceIter.next() ) 
		{
			MIntArray  vexlist;
			faceIter.getVertices ( vexlist );
			for( int i=vexlist.length()-1; i >=0; i-- ) 
			{
				polyconnect[acc] = vexlist[i];
				acc++;
			}
		}
		
		xml_f.addFaceConnection(n_facevertex, polyconnect);
		delete[] polyconnect;
		
		int* triconnect = new int[3*n_tri];
		acc = 0;
		faceIter.reset();
		for( ; !faceIter.isDone(); faceIter.next() ) 
		{
			MIntArray  vexlist;
			faceIter.getVertices ( vexlist );
			for( int i=vexlist.length()-2; i >0; i-- ) 
			{
				triconnect[acc] = vexlist[vexlist.length()-1];
				acc++;
				triconnect[acc] = vexlist[i];
				acc++;
				triconnect[acc] = vexlist[i-1];
				acc++;
			}
		}
		
		xml_f.addTriangleConnection(3*n_tri, triconnect);
		delete[] triconnect;

		if(meshFn.numUVSets() > 0)
		{
			MStringArray setNames;
			meshFn.getUVSetNames(setNames);
			for(unsigned i=0; i< setNames.length(); i++)
			{
				float* scoord = new float[n_facevertex];
				float* tcoord = new float[n_facevertex];
				
				acc = 0;
				faceIter.reset();
				MFloatArray uarray, varray;
				if(faceIter.hasUVs (setNames[i], &status))
				{
					for( ; !faceIter.isDone(); faceIter.next() ) 
					{
						faceIter.getUVs ( uarray, varray, &setNames[i] );
						for( int j=uarray.length()-1; j >=0 ; j-- ) 
						{
							scoord[acc] = uarray[j];
							tcoord[acc] = 1.0 - varray[j];
							acc++;
						}
					}
					
					
					if(setNames[i] == "map1")
					{
						xml_f.uvSetBegin(setNames[i].asChar());
						xml_f.addS("facevarying float s", meshFn.numFaceVertices(), scoord);
						xml_f.addT("facevarying float t", meshFn.numFaceVertices(), tcoord);
						xml_f.uvSetEnd();
					}
					else
					{
						xml_f.uvSetBegin(setNames[i].asChar());
						std::string paramname("facevarying float u_");
						paramname.append(setNames[i].asChar());
						xml_f.addS(paramname.c_str(), meshFn.numFaceVertices(), scoord);
						
						paramname = "facevarying float v_";
						paramname.append(setNames[i].asChar());
						xml_f.addT(paramname.c_str(), meshFn.numFaceVertices(), tcoord);
						xml_f.uvSetEnd();
					}
				}
				else MGlobal::displayWarning(MString("Skip empty uv set: ") + setNames[i]);
				
				delete[] scoord;
				delete[] tcoord;
			}
		}
		
		MStringArray colorSetNames;
		meshFn.getColorSetNames (colorSetNames);
		
		for(unsigned int i=0; i<colorSetNames.length(); i++)
		{
			MStatus hasColor;
			
			XYZ *colors = new XYZ[n_vert];
			vertIter.reset();
			MString aset = colorSetNames[i];
			MColor col;
			for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) {
					MIntArray conn_face;
					vertIter.getConnectedFaces(conn_face);
					vertIter.getColor(col, conn_face[0], &aset);
					colors[i].x = col.r*light_intensity;
					colors[i].y = col.g*light_intensity;
					colors[i].z = col.b*light_intensity;
			}
				
			xml_f.addVertexColor(aset.asChar(), n_vert, colors);
			delete[] colors;
		}
		
		//if(!bNoChange) {

			
		//}
		
		MPointArray p_vert;
		
		meshFn.getPoints ( p_vert, MSpace::kWorld );
		
		MPoint corner_l(10e6, 10e6, 10e6);
		MPoint corner_h(-10e6, -10e6, -10e6);
		
		for( unsigned int i=0; i<p_vert.length(); i++) {
			if( p_vert[i].x < corner_l.x ) corner_l.x = p_vert[i].x;
			if( p_vert[i].y < corner_l.y ) corner_l.y = p_vert[i].y;
			if( p_vert[i].z < corner_l.z ) corner_l.z = p_vert[i].z;
			if( p_vert[i].x > corner_h.x ) corner_h.x = p_vert[i].x;
			if( p_vert[i].y > corner_h.y ) corner_h.y = p_vert[i].y;
			if( p_vert[i].z > corner_h.z ) corner_h.z = p_vert[i].z;
		}
		
		
		
		XYZ *cv = new XYZ[n_vert];
		
		for( unsigned int i=0; i<p_vert.length(); i++) 
		{
			cv[i].x = p_vert[i].x;
			cv[i].y = p_vert[i].y;
			cv[i].z= p_vert[i].z;
		}
		
		//if(!bNoChange) 
		//else 
		xml_f.addStaticP(n_vert, cv);
		
		
		
		XYZ *nor = new XYZ[n_vert];
		XYZ *tang = new XYZ[n_vert];
		
		vertIter.reset();
		MVector vnor;
		
		for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ )
		{
			vertIter.getNormal(vnor, MSpace::kWorld);
			vnor.normalize();
			nor[i].x = vnor.x;
			nor[i].y = vnor.y;
			nor[i].z = vnor.z;
		}
		
		MString uvset("map1");
		
		vertIter.reset();
		for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ )
		{
			MIntArray conn_face;
			vertIter.getConnectedFaces(conn_face);
			
			MVector ctang(0,0,0);
			MVector ttang;
			for(unsigned j = 0; j<conn_face.length(); j++) 
			{
				meshFn.getFaceVertexTangent (conn_face[j], i,  ttang,  MSpace::kWorld, &uvset);
				ttang.normalize();
				ctang += ttang;
			}
			ctang.normalize();
			tang[i].x = ctang.x;
			tang[i].y = ctang.y;
			tang[i].z = ctang.z;
			
			tang[i] = nor[i].cross(tang[i]);
			tang[i].normalize();
		}

		//if(!bNoChange) 
		//else 
		xml_f.addStaticN(n_vert, nor);
		//xml_f.addTangent(n_vert, tang);
		
		
// export per-vertex thickness
		float* vgrd = new float[n_vert];
		int pidx;
		vertIter.reset();
		for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) {
			MIntArray connfaces;
			vertIter.getConnectedFaces( connfaces );
			float connarea = 0;
			for(unsigned j=0; j<connfaces.length(); j++)
			{
				faceIter.setIndex(connfaces[j], pidx);
				faceIter.getArea(area, MSpace::kWorld );
				connarea += (float)area/faceIter.polygonVertexCount();
			}
			vgrd[i] = sqrt(connarea)/2;
			if(vgrd[i] > avg_grid) vgrd[i] = avg_grid;
		}
		
		//if(!bNoChange) 
		//else 
		xml_f.addStaticGridSize(n_vert, vgrd);
		
		
		
		// 
		//else 
		xml_f.staticEnd();
		
		if(!bNoChange) {
			
			xml_f.dynamicBegin();
		
			xml_f.addP(n_vert, cv);
			xml_f.addN(n_vert, nor);
			xml_f.addGridSize(n_vert, vgrd);
			
			xml_f.dynamicEnd();
		}
		
		delete[] cv;
		delete[] tang;
		delete[] nor;
		delete[] vgrd;
		
		xml_f.addBBox(corner_l.x, corner_l.y, corner_l.z, corner_h.x, corner_h.y, corner_h.z);

		xml_f.meshEnd(bNoChange);
	}
/* disable nurbs for now

	float aspace[4][4];
	for(unsigned it=0; it<m_nurbs_list.length(); it++) {
		MVector scale = AHelper::getTransformWorldNoScale(m_nurbs_list[it].fullPathName(), aspace);
		
		MString surfacename = m_nurbs_list[it].fullPathName();
		AHelper::validateFilePath(surfacename);
		xml_f.transformBegin(surfacename.asChar(), aspace);
		xml_f.addScale(scale.x, scale.y, scale.z);
		
		m_nurbs_list[it].extendToShape();
		
		surfacename = m_nurbs_list[it].fullPathName();
		AHelper::validateFilePath(surfacename);
		
		MFnNurbsSurface fsurface(m_nurbs_list[it]);
		
		int degreeU = fsurface.degreeU();
		int degreeV = fsurface.degreeV();
		
		int formU, formV;
		
		if(fsurface.formInU() == MFnNurbsSurface::kOpen ) formU = 0;
		else if(fsurface.formInU() == MFnNurbsSurface::kClosed ) formU = 1;
		else formU = 2;

		if(fsurface.formInV() == MFnNurbsSurface::kOpen ) formV = 0;
		else if(fsurface.formInV() == MFnNurbsSurface::kClosed ) formV = 1;
		else formV = 2;
		
		xml_f.nurbssurfaceBegin(surfacename.asChar(), degreeU, degreeV, formU, formV);
		
		xml_f.staticBegin();
		
		MPointArray p_cvs;
	
		fsurface.getCVs( p_cvs, MSpace::kObject );
		
		unsigned n_cvs = p_cvs.length();
		XYZ *cv = new XYZ[n_cvs];
	
		for(unsigned i=0; i<n_cvs; i++) {
			cv[i].x = p_cvs[i].x;
			cv[i].y = p_cvs[i].y;
			cv[i].z= p_cvs[i].z;
		}
	
		xml_f.addStaticVec("cvs", n_cvs, cv);
		delete[] cv;
		
		MDoubleArray knotu, knotv;
		
		fsurface.getKnotsInU(knotu);
		fsurface.getKnotsInV(knotv);
		
		unsigned n_ku = knotu.length();
		unsigned n_kv = knotv.length();
		
		float *ku = new float[n_ku];
		for(unsigned i=0; i<n_ku; i++) ku[i] = knotu[i];
		
		float *kv = new float[n_kv];
		for(unsigned i=0; i<n_kv; i++) kv[i] = knotv[i];

		xml_f.addStaticFloat("knotu", n_ku, ku);
		xml_f.addStaticFloat("knotv", n_kv, kv);
		
		delete[] ku;
		delete[] kv;
		
		xml_f.staticEnd();
		
		xml_f.nurbssurfaceEnd();
		
		xml_f.transformEnd();
	}
*/	
	xml_f.cameraBegin("backscat_camera", m_space);
	xml_f.cameraEnd();
	
	xml_f.cameraBegin("eye_camera", m_eye);
	p_eye.extendToShape();
	MFnCamera feye(p_eye);
	xml_f.addAttribute("focal_length", (float)feye.focalLength());
	xml_f.addAttribute("horizontal_film_aperture", (float)feye.horizontalFilmAperture());
	xml_f.addAttribute("vertical_film_aperture", (float)feye.verticalFilmAperture());
	xml_f.addAttribute("near_clipping_plane", (float)feye.nearClippingPlane());
	xml_f.addAttribute("far_clipping_plane", (float)feye.farClippingPlane());
	xml_f.cameraEnd();
	
	xml_f.end(filename);
}
Example #9
0
bool tm_polyExtract::extractFaces_Func( MSelectionList &selectionList, MStringArray &node_names)
{
	MStatus status;
	MObject meshObj;
	status = selectionList.getDependNode( 0, meshObj);
	if(!status){MGlobal::displayError("tm_polyExtract::extractFaces_Func:   Can't find object !");return false;}
	MFnMesh meshFn( meshObj, &status);
	if(!status){MGlobal::displayError("tm_polyExtract::extractFaces_Func:   Non mesh object founded !");return false;}

	MDagPath meshDagPath_first, meshDagPath;
	selectionList.getDagPath( 0, meshDagPath_first);
	MObject multiFaceComponent;
	MIntArray inputFacesArray;
	inputFacesArray.clear();
	inputFacesArray.setSizeIncrement( 4096);
	MFnComponentListData compListFn;
	compListFn.create();
	for (MItSelectionList faceComponentIter(selectionList, MFn::kMeshPolygonComponent); !faceComponentIter.isDone(); faceComponentIter.next())
	{
		faceComponentIter.getDagPath(meshDagPath, multiFaceComponent);
		if(!(meshDagPath_first == meshDagPath))
		{
			MGlobal::displayError("tm_polyExtract::extractFaces_Func:   Different meshes faces founded !");
			return false;
		}
		if (!multiFaceComponent.isNull())
		{
			for (MItMeshPolygon faceIter(meshDagPath, multiFaceComponent); !faceIter.isDone(); faceIter.next())
			{
				int faceIndex = faceIter.index();
#ifdef _DEBUG
				infoMStr += faceIndex;
				infoMStr += " ";
#endif
				inputFacesArray.append( faceIndex);
				compListFn.add( multiFaceComponent );
			}
		}
	}
	if( inputFacesArray.length() == 0)
	{
		MGlobal::displayError("tm_polyExtract::extractFaces_Func:   No faces founded !");
		return false;
	}
#ifdef _DEBUG
	MGlobal::displayInfo( infoMStr);
#endif

	meshFn.setObject( meshDagPath_first);
	meshObj = meshFn.object();

//	MDagModifier dagModifier;
	MFnDagNode meshDagNodeFn;
	MFnDependencyNode depNodeFn;
	meshDagNodeFn.setObject( meshDagPath_first);
	MString meshName = meshDagNodeFn.name();
	MObject outMesh_attrObject = meshDagNodeFn.attribute( "outMesh");

// ----------------------------------- duplicate shape

	MObject duplicated_meshObjectA;
	MObject duplicated_meshObjectB;
	MObject inMesh_attrObjectA;
	MObject inMesh_attrObjectB;
/*
	MStringArray commandResult;
	MSelectionList selList;

	MGlobal::executeCommand( "duplicate " + meshDagNodeFn.name(), commandResult, 1, 1);
	selList.add( commandResult[0]);
	selList.getDependNode( 0, duplicated_meshObjectA);
	meshDagNodeFn.setObject( duplicated_meshObjectA);
	meshDagNodeFn.setName( meshName + "_tA");
	duplicated_meshObjectA = meshDagNodeFn.child(0);
	meshDagNodeFn.setObject( duplicated_meshObjectA);
	meshDagNodeFn.setName( meshName + "_sA");
	inMesh_attrObjectA = meshDagNodeFn.attribute( "inMesh");

	meshDagNodeFn.setObject( meshDagPath_first);
	selList.clear();

	MGlobal::executeCommand( "duplicate " + meshDagNodeFn.name(), commandResult, 1, 1);
	selList.add( commandResult[0]);
	selList.getDependNode( 0, duplicated_meshObjectB);
	meshDagNodeFn.setObject( duplicated_meshObjectB);
	meshDagNodeFn.setName( meshName + "_tB");
	duplicated_meshObjectB = meshDagNodeFn.child(0);
	meshDagNodeFn.setObject( duplicated_meshObjectB);
	meshDagNodeFn.setName( meshName + "_sB");
	inMesh_attrObjectB = meshDagNodeFn.attribute( "inMesh");
*/
	duplicated_meshObjectA = meshDagNodeFn.duplicate();
	meshDagNodeFn.setObject( duplicated_meshObjectA);
	meshDagNodeFn.setName( meshName + "_tA");
	duplicated_meshObjectA = meshDagNodeFn.child(0);
	meshDagNodeFn.setObject( duplicated_meshObjectA);
	meshDagNodeFn.setName( meshName + "_sA");
	inMesh_attrObjectA = meshDagNodeFn.attribute( "inMesh");

	meshDagNodeFn.setObject( meshDagPath_first);

	duplicated_meshObjectB = meshDagNodeFn.duplicate();
	meshDagNodeFn.setObject( duplicated_meshObjectB);
	meshDagNodeFn.setName( meshName + "_tB");
	duplicated_meshObjectB = meshDagNodeFn.child(0);
	meshDagNodeFn.setObject( duplicated_meshObjectB);
	meshDagNodeFn.setName( meshName + "_sB");
	inMesh_attrObjectB = meshDagNodeFn.attribute( "inMesh");

// ----------------------------------- create node deleteComponent

	MDGModifier dgModifier;

	MObject deleteComponent_nodeObjectA = dgModifier.createNode( MString("deleteComponent"));
	depNodeFn.setObject( deleteComponent_nodeObjectA );
	MObject deleteComponent_attrObjectA( depNodeFn.attribute( "deleteComponents" ));
	MObject inputGeometry_attrObjectA( depNodeFn.attribute( "inputGeometry" ));
	MObject outputGeometry_attrObjectA( depNodeFn.attribute( "outputGeometry" ));
	dgModifier.doIt();
	depNodeFn.setName( "dfA_" + meshName);
	node_names.append( depNodeFn.name());

	MObject deleteComponent_nodeObjectB = dgModifier.createNode( MString("deleteComponent"));
	depNodeFn.setObject( deleteComponent_nodeObjectB );
	MObject deleteComponent_attrObjectB( depNodeFn.attribute( "deleteComponents" ));
	MObject inputGeometry_attrObjectB( depNodeFn.attribute( "inputGeometry" ));
	MObject outputGeometry_attrObjectB( depNodeFn.attribute( "outputGeometry" ));
	dgModifier.doIt();
	depNodeFn.setName( "dfB_" + meshName);
	node_names.append( depNodeFn.name());

// ----------------------------------- set attribute deleteComponent.deleteComponents

	MObject componentList_object = compListFn.object();

	MPlug deleteComponents_plugA( deleteComponent_nodeObjectA, deleteComponent_attrObjectA );
	status = deleteComponents_plugA.setValue( componentList_object );

	MIntArray invertedFaces;
	int numPolygons = meshFn.numPolygons();
	invertedFaces.setLength( numPolygons - inputFacesArray.length());
	int selFace = 0;
	int invFace = 0;
	for( int f = 0; f < numPolygons; f++)
	{
		if( f == inputFacesArray[selFace])
			selFace++;
		else
			invertedFaces[invFace++] = f;
	}
	MFnSingleIndexedComponent singleIndexedComponentFn( meshObj);
	singleIndexedComponentFn.create( MFn::kMeshPolygonComponent);
	singleIndexedComponentFn.addElements( invertedFaces);
	compListFn.clear();
	compListFn.create();
   componentList_object = singleIndexedComponentFn.object();
	compListFn.add( componentList_object);
	componentList_object = compListFn.object();
	MPlug deleteComponents_plugB( deleteComponent_nodeObjectB, deleteComponent_attrObjectB );
	status = deleteComponents_plugB.setValue( componentList_object );

// ------------------------------------- connecting plugs
/**/
	dgModifier.connect(
			meshObj, outMesh_attrObject,
			deleteComponent_nodeObjectA, inputGeometry_attrObjectA
		);
	dgModifier.connect(
			deleteComponent_nodeObjectA, outputGeometry_attrObjectA,
			duplicated_meshObjectA, inMesh_attrObjectA
		);

	dgModifier.connect(
			meshObj, outMesh_attrObject,
			deleteComponent_nodeObjectB, inputGeometry_attrObjectB
		);
	dgModifier.connect(
			deleteComponent_nodeObjectB, outputGeometry_attrObjectB,
			duplicated_meshObjectB, inMesh_attrObjectB
		);

	dgModifier.doIt();

// ---------------------------------- assigning shading group
/**/
	meshDagNodeFn.setObject( meshDagPath_first);
	MObject instObjGroups_attrObject = meshDagNodeFn.attribute( "instObjGroups");
	MPlug instObjGroups_plug( meshObj, instObjGroups_attrObject);
	instObjGroups_plug = instObjGroups_plug.elementByPhysicalIndex(0);
	MPlugArray instObjGroups_plug_connectionsArray;
	instObjGroups_plug.connectedTo( instObjGroups_plug_connectionsArray, false, true);
	if( instObjGroups_plug_connectionsArray.length() > 0)
	{
		MPlug dagSetMembers_plug = instObjGroups_plug_connectionsArray[0];
		MObject shadingSetNode_object = dagSetMembers_plug.node();
		MFnSet setFn( shadingSetNode_object);
		setFn.addMember( duplicated_meshObjectA);
		setFn.addMember( duplicated_meshObjectB);
//depNodeFn.setObject(shadingSetNode_object);
//MGlobal::displayInfo( depNodeFn.name());
	}

// ------------------------------------------------------------
	return true;
}
MStatus meshInfo5::doIt( const MArgList& args )
{
	MStatus stat = MS::kSuccess;

	MSelectionList selection;
	MGlobal::getActiveSelectionList( selection );

	MDagPath dagPath;
	MObject component;
	
	unsigned int i, nVerts;
	int fIndex, vIndex, fvIndex;
	MVector fNormal, vNormal, fvNormal;
	
	MString txt;
	MItSelectionList iter( selection );
	for ( ; !iter.isDone(); iter.next() )
	{								
		iter.getDagPath( dagPath, component );
		
		MFnMesh meshFn( dagPath );
		
		// This handles whole mesh selections and mesh-face component selections
		MItMeshPolygon faceIter( dagPath, component, &stat );
		if( stat == MS::kSuccess )
		{
			txt += MString( "Object: " ) + dagPath.fullPathName() + "\n";	
									
			for( ; !faceIter.isDone(); faceIter.next() )
			{
				nVerts = faceIter.polygonVertexCount();
				
				for( i=0; i < nVerts; i++ )
				{
					fvIndex = i;
					fIndex = faceIter.index();
					vIndex = faceIter.vertexIndex( i );
					
					faceIter.getNormal( fNormal );
					meshFn.getVertexNormal( vIndex, vNormal );					
					faceIter.getNormal( fvIndex, fvNormal );

					addData( txt, fIndex, vIndex, fvIndex, fNormal, vNormal, fvNormal );
				}
			}
		} 
		else
		{
			// This handles mesh-vertex component selections
			MItMeshVertex vertIter( dagPath, component, &stat );
			if( stat == MS::kSuccess )
			{
				txt += MString( "Object: " ) + dagPath.fullPathName() + "\n";	

				MIntArray faceIds;
				MIntArray vertIds;
						
				for( ; !vertIter.isDone(); vertIter.next() )
				{
					vIndex = vertIter.index();
					
					vertIter.getNormal( vNormal );
					vertIter.getConnectedFaces( faceIds );
					
					for( i=0; i < faceIds.length(); i++ )
					{
						fIndex = faceIds[i];
						
						meshFn.getPolygonNormal( fIndex, fNormal );
						meshFn.getFaceVertexNormal( fIndex, vIndex, fvNormal );
						meshFn.getPolygonVertices( fIndex, vertIds );
												
						for( fvIndex=0; fvIndex < int(vertIds.length()); fvIndex++ )
						{
							if( vertIds[fvIndex] == vIndex )
								break;
						}
						
						addData( txt, fIndex, vIndex, fvIndex, fNormal, vNormal, fvNormal ); 
					}
				}
			}
		}
	}
	
	MGlobal::displayInfo( txt );

	return MS::kSuccess;
}