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