BOOL MeshExpUtility::BuildObject(CEditableObject*& exp_obj, LPCSTR m_ExportName) { bool bResult = true; if (m_ExportName[0]==0) return false; ELog.Msg(mtInformation,"Building object..." ); char fname[256]; _splitpath( m_ExportName, 0, 0, fname, 0 ); exp_obj = xr_new<CEditableObject>(fname); exp_obj->SetVersionToCurrent(TRUE,TRUE); ExportItemIt it = m_Items.begin(); for(;it!=m_Items.end();it++){ CEditableMesh *submesh = xr_new<CEditableMesh>(exp_obj); ELog.Msg(mtInformation,"Converting node '%s'...", it->pNode->GetName()); if( submesh->Convert(it->pNode) ){ // transform Matrix3 mMatrix; mMatrix = it->pNode->GetNodeTM(0)*Inverse(it->pNode->GetParentNode()->GetNodeTM(0)); Point3 r1 = mMatrix.GetRow(0); Point3 r2 = mMatrix.GetRow(1); Point3 r3 = mMatrix.GetRow(2); Point3 r4 = mMatrix.GetRow(3); Fmatrix m; m.identity(); m.i.set(r1.x, r1.z, r1.y); m.j.set(r2.x, r2.z, r2.y); m.k.set(r3.x, r3.z, r3.y); m.c.set(r4.x, r4.z, r4.y); submesh->Transform( m ); // flip faces Fvector v; v.crossproduct(m.j, m.k); if(v.dotproduct(m.i)<0.f) submesh->FlipFaces(); if(m_ObjectFlipFaces) submesh->FlipFaces(); submesh->RecomputeBBox(); // append mesh submesh->SetName (it->pNode->GetName()); exp_obj->m_Meshes.push_back (submesh); }else{ ELog.Msg(mtError,"! can't convert", it->pNode->GetName()); xr_delete(submesh); bResult = false; break; } } if (bResult){ exp_obj->UpdateBox (); exp_obj->VerifyMeshNames(); ELog.Msg (mtInformation,"Object '%s' contains: %d points, %d faces", exp_obj->GetName(), exp_obj->GetVertexCount(), exp_obj->GetFaceCount()); }else{ xr_delete(exp_obj); } //------------------------------------------------------------------- return bResult; }
MStatus CXRayObjectExport::ExportPart(CEditableObject* O, MDagPath& mdagPath, MObject& mComponent) { MStatus stat = MS::kSuccess; MSpace::Space space = MSpace::kWorld; MFnMesh fnMesh( mdagPath, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MFnMesh initialization.\n"); return MS::kFailure; } MString mdagPathNodeName = fnMesh.name(); MFnDagNode dagNode1(mdagPath); u32 pc = dagNode1.parentCount(); for(u32 ip=0;ip<pc;++ip) { MObject object_parent = dagNode1.parent(ip, &stat); if(object_parent.hasFn(MFn::kTransform)) { MFnTransform parent_transform(object_parent,&stat); if ( MS::kSuccess == stat) { mdagPathNodeName = parent_transform.name(); break; } } } MItMeshPolygon meshPoly( mdagPath, mComponent, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MItMeshPolygon initialization.\n"); return MS::kFailure; } MItMeshVertex vtxIter( mdagPath, mComponent, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MItMeshVertex initialization.\n"); return MS::kFailure; } // If the shape is instanced then we need to determine which // instance this path refers to. // int instanceNum = 0; if (mdagPath.isInstanced()) instanceNum = mdagPath.instanceNumber(); // Get a list of all shaders attached to this mesh MObjectArray rgShaders; MIntArray texMap; MStatus status; status = fnMesh.getConnectedShaders (instanceNum, rgShaders, texMap); if (status == MStatus::kFailure) { Log("! Unable to load shaders for mesh"); return (MStatus::kFailure); } XRShaderDataVec xr_data; { for ( int i=0; i<(int)rgShaders.length(); i++ ) { MObject shader = rgShaders[i]; xr_data.push_back(SXRShaderData()); SXRShaderData& D = xr_data.back(); status = parseShader(shader, D); if (status == MStatus::kFailure) { status.perror ("Unable to retrieve filename of texture"); continue; } } } CEditableMesh* MESH = new CEditableMesh(O); MESH->SetName(mdagPathNodeName.asChar()); O->AppendMesh(MESH); int objectIdx, length; // Find i such that objectGroupsTablePtr[i] corresponds to the // object node pointed to by mdagPath length = objectNodeNamesArray.length(); { for( int i=0; i<length; i++ ) { if( objectNodeNamesArray[i] == mdagPathNodeName ) { objectIdx = i; break; } } } // Reserve uv table { VMapVec& _vmaps = MESH->m_VMaps; _vmaps.resize (1); st_VMap*& VM = _vmaps.back(); VM = new st_VMap("Texture",vmtUV,false); } // write faces { using FaceVec = xr_vector<st_Face>; using FaceIt = FaceVec::iterator; VMapVec& _vmaps = MESH->m_VMaps; SurfFaces& _surf_faces = MESH->m_SurfFaces; VMRefsVec& _vmrefs = MESH->m_VMRefs; // temp variables FvectorVec _points; FaceVec _faces; U32Vec _sgs; int f_cnt = fnMesh.numPolygons(); _sgs.reserve (f_cnt); _faces.reserve (f_cnt); _vmrefs.reserve (f_cnt*3); // int lastSmoothingGroup = INITIALIZE_SMOOTHING; MPointArray rgpt; MIntArray rgint; PtLookupMap ptMap; CSurface* surf = 0; for ( ; !meshPoly.isDone(); meshPoly.next()){ // Write out the smoothing group that this polygon belongs to // We only write out the smoothing group if it is different // from the last polygon. // int compIdx = meshPoly.index(); int smoothingGroup = polySmoothingGroups[ compIdx ]; // for each polygon, first setup the reverse mapping // between object-relative vertex indices and face-relative // vertex indices ptMap.clear(); for (int i=0; i<(int)meshPoly.polygonVertexCount(); i++) ptMap.insert (PtLookupMap::value_type(meshPoly.vertexIndex(i), i) ); // verify polygon zero area if (meshPoly.zeroArea()){ status = MS::kFailure; Log("! polygon have zero area:",meshPoly.index()); return status; } // verify polygon zero UV area /* if (meshPoly.zeroUVArea()){ status = MS::kFailure; Log("! polygon have zero UV area:",meshPoly.index()); return status; } */ // verify polygon has UV information if (!meshPoly.hasUVs (&status)) { status = MS::kFailure; Log("! polygon is missing UV information:",meshPoly.index()); return status; } int cTri; // now iterate through each triangle on this polygon and create a triangle object in our list status = meshPoly.numTriangles (cTri); if (!status) { Log("! can't getting triangle count"); return status; } for (int i=0; i < cTri; i++) { // for each triangle, first get the triangle data rgpt.clear();//triangle vertices rgint.clear();//triangle vertex indices // triangles that come from object are retrieved in world space status = meshPoly.getTriangle (i, rgpt, rgint, MSpace::kWorld); if (!status) { Log("! can't getting triangle for mesh poly"); return status; } if ((rgpt.length() != 3) || (rgint.length() != 3)) { Msg("! 3 points not returned for triangle"); return MS::kFailure; } // Write out vertex/uv index information // R_ASSERT2(fnMesh.numUVs()>0,"Can't find uvmaps."); _faces.push_back(st_Face()); _sgs.push_back(smoothingGroup); //set_smooth set_smoth_flags( _sgs.back(), rgint ); st_Face& f_it = _faces.back(); for ( int vtx=0; vtx<3; vtx++ ) { // get face-relative vertex PtLookupMap::iterator mapIt; int vtLocal, vtUV; int vt = rgint[vtx]; mapIt = ptMap.find(vt); Fvector2 uv; if (mapIt == ptMap.end()){ Msg("! Can't find local index."); return MS::kFailure; } vtLocal = (*mapIt).second; status = meshPoly.getUVIndex (vtLocal, vtUV, uv.x, uv.y); if (!status) { Msg("! error getting UV Index for local vertex '%d' and object vertex '%d'",vtLocal,vt); return status; } // flip v-part uv.y=1.f-uv.y; f_it.pv[2-vtx].pindex = AppendVertex(_points,rgpt[vtx]); f_it.pv[2-vtx].vmref = _vmrefs.size(); _vmrefs.push_back (st_VMapPtLst()); st_VMapPtLst& vm_lst = _vmrefs.back(); vm_lst.count = 1; vm_lst.pts = xr_alloc<st_VMapPt>(vm_lst.count); vm_lst.pts[0].vmap_index= 0; vm_lst.pts[0].index = AppendUV(_vmaps.back(),uv); } // out face material int iTexture = texMap[meshPoly.index()]; if (iTexture<0) xrDebug::Fatal(DEBUG_INFO,"Can't find material for polygon: %d",meshPoly.index()); SXRShaderData& D= xr_data[iTexture]; int compIdx = meshPoly.index(); surf = MESH->Parent()->CreateSurface(getMaterialName(mdagPath, compIdx, objectIdx),D); if (!surf) return MStatus::kFailure; _surf_faces[surf].push_back(_faces.size()-1); } } { // copy from temp MESH->m_VertCount = _points.size(); MESH->m_FaceCount = _faces.size(); MESH->m_Vertices = xr_alloc<Fvector>(MESH->m_VertCount); Memory.mem_copy (MESH->m_Vertices,&*_points.begin(),MESH->m_VertCount*sizeof(Fvector)); MESH->m_Faces = xr_alloc<st_Face>(MESH->m_FaceCount); Memory.mem_copy (MESH->m_Faces,&*_faces.begin(),MESH->m_FaceCount*sizeof(st_Face)); MESH->m_SmoothGroups = xr_alloc<u32>(MESH->m_FaceCount); Memory.mem_copy (MESH->m_SmoothGroups,&*_sgs.begin(),MESH->m_FaceCount*sizeof(u32)); MESH->RecomputeBBox (); } if ((MESH->GetVertexCount()<4)||(MESH->GetFaceCount()<2)) { Log ("! Invalid mesh: '%s'. Faces<2 or Verts<4",*MESH->Name()); return MS::kFailure; } } return stat; }