void EditFaceDataModData::ApplyChanges (MNMesh & mesh) { // Make sure we're sized correctly for this mesh. // (NOTE: If the user reduces, then increases input number of faces, we lose data.) if (mesh.numf != mFaceSel.GetSize()) SynchSize (mesh.numf); // Set the selection: mesh.FaceSelect (mFaceSel); // Get the face data manager from the mesh: DebugPrint ("EditFaceDataMod: Getting manager from MNMesh (0x%08x)\n", &mesh); IFaceDataMgr *pFDMgr = static_cast<IFaceDataMgr*>(mesh.GetInterface (FACEDATAMGR_INTERFACE)); if (pFDMgr == NULL) return; SampleFaceData* fdc = dynamic_cast<SampleFaceData*>(pFDMgr->GetFaceDataChan( FACE_MAXSAMPLEUSE_CLSID )); if ( fdc == NULL ) { // The mesh does not have our sample face-data channel so we will add it here fdc = new SampleFaceData(); fdc->FacesCreated (0, mFaceSel.GetSize()); pFDMgr->AddFaceDataChan( fdc ); } if (!mFacesAffected.NumberSet ()) return; for (int i=0; i<mFacesAffected.GetSize(); i++) { if (!mFacesAffected[i]) continue; fdc->SetValue (i, mtNewFaceValues[i]); } }
void EditFaceDataMod::GetSubObjectTMs (SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc) { if (!mc->localData) return; if (selLevel == SEL_OBJECT) return; // shouldn't happen. EditFaceDataModData *modData = (EditFaceDataModData *) mc->localData; Mesh *mesh = modData->GetCacheMesh(); MNMesh *mnmesh = modData->GetCacheMNMesh(); if (!mesh && !mnmesh) return; Matrix3 tm = node->GetObjectTM(t); Box3 box; if (mesh) { BitArray sel = mesh->VertexTempSel (); if (!sel.NumberSet()) return; for (int i=0; i<mesh->numVerts; i++) if (sel[i]) box += mesh->verts[i] * tm; } else { int numSel, which; float value; bool valueDetermined; modData->DescribeSelection (numSel, which, value, valueDetermined); if (!numSel) return; if (numSel==1) { for (int j=0; j<mnmesh->f[which].deg; j++) box += mnmesh->P(mnmesh->f[which].vtx[j]) * tm; } else { for (int i=0; i<mnmesh->numf; i++) { if (mnmesh->f[i].GetFlag (MN_DEAD)) continue; if (!modData->GetFaceSel()[i]) continue; for (int j=0; j<mnmesh->f[i].deg; j++) box += mnmesh->P(mnmesh->f[i].vtx[j]) * tm; } } } Matrix3 ctm(1); ctm.SetTrans (box.Center()); cb->TM (ctm,0); }
void TriObject::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel ) { if ( tm || useSel ) { box.Init(); BitArray sel; BitArray vhide; float *vssel = NULL; if ( useSel ) { sel = mesh.VertexTempSel(); vssel = mesh.getVSelectionWeights (); } else { vhide = mesh.vertHide; if (vhide.NumberSet ()) { for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faces[i].Hidden ()) continue; for (int j=0; j<3; j++) vhide.Clear (mesh.faces[i].v[j]); } } } for ( int i = 0; i < mesh.getNumVerts(); i++ ) { if (!useSel && vhide[i]) continue; if ( !useSel || sel[i] || (vssel&&vssel[i])) { if ( tm ) { box += *tm * mesh.getVert(i); } else { box += mesh.getVert(i); } } } } else { box = mesh.getBoundingBox(); } }
void EditPolyData::CollapseDeadSelections (EditPolyMod *pMod, MNMesh & mesh) { BitArray delSet; // Fix the vertex selection and hide arrays: int max = mesh.numv; if (max>mVertSel.GetSize()) max = mVertSel.GetSize (); delSet.SetSize (max); for (int i=0; i<max; i++) delSet.Set (i, mesh.v[i].GetFlag (MN_DEAD)); if (delSet.NumberSet()>0) { if (theHold.Holding()) theHold.Put (new EditPolySelectRestore (pMod, this, EPM_SL_VERTEX)); mVertSel.DeleteSet (delSet); if (theHold.Holding()) theHold.Put (new EditPolyHideRestore (pMod, this, false)); mVertHide.DeleteSet (delSet); } // Fix the edge selection array: max = mesh.nume; if (max>mEdgeSel.GetSize()) max = mEdgeSel.GetSize (); delSet.SetSize (max); for (int i=0; i<max; i++) delSet.Set (i, mesh.e[i].GetFlag (MN_DEAD)); if (delSet.NumberSet()>0) { if (theHold.Holding()) theHold.Put (new EditPolySelectRestore (pMod, this, EPM_SL_EDGE)); mEdgeSel.DeleteSet (delSet); } // Fix the face selection and hide arrays: max = mesh.numf; if (max>mFaceSel.GetSize()) max = mFaceSel.GetSize (); delSet.SetSize (max); for (int i=0; i<max; i++) delSet.Set (i, mesh.f[i].GetFlag (MN_DEAD)); if (delSet.NumberSet()>0) { if (theHold.Holding()) theHold.Put (new EditPolySelectRestore (pMod, this, EPM_SL_FACE)); mFaceSel.DeleteSet (delSet); if (theHold.Holding()) theHold.Put (new EditPolyHideRestore (pMod, this, true)); mFaceHide.DeleteSet (delSet); } }
void MeshTopoData::RemoveDeadVerts(PatchMesh *mesh, int channel) { Tab<Point3> vertList; Tab<int> idList; //copy over vertlist int ct = mesh->getNumMapVerts(channel); vertList.SetCount(ct); PatchTVert *tVerts = mesh->mapVerts(channel); for (int i = 0; i < ct; i++) vertList[i] = tVerts[i].p; BitArray usedList; usedList.SetSize(ct); TVPatch *tvFace = NULL; if (!mesh->getMapSupport(channel)) { return; } tvFace = mesh->tvPatches[channel]; if (tvFace == NULL) return; for (int i =0; i < mesh->numPatches; i++) { int pcount = 3; if (mesh->patches[i].type == PATCH_QUAD) pcount = 4; for (int j = 0; j < pcount; j++) { int index = tvFace[i].tv[j]; usedList.Set(index); if (!(mesh->patches[i].flags & PATCH_LINEARMAPPING)) { if (!(mesh->patches[i].flags & PATCH_AUTO)) { index = tvFace[i].interiors[j]; if ((index >= 0) && (index < usedList.GetSize())) usedList.Set(index); } index = tvFace[i].handles[j*2]; if ((index >= 0) && (index < usedList.GetSize())) usedList.Set(index); index = tvFace[i].handles[j*2+1]; if ((index >= 0) && (index < usedList.GetSize())) usedList.Set(index); } } } mesh->setNumMapVerts (channel,usedList.NumberSet(),TRUE); int current = 0; tVerts = mesh->mapVerts(channel); for (int i = 0; i < ct; i++) { if (usedList[i]) { tVerts[current].p = vertList[i]; //now fix up faces for (int j = 0; j < mesh->numPatches; j++) { int pcount = 3; if (mesh->patches[j].type == PATCH_QUAD) pcount = 4; for (int k = 0; k < pcount; k++) { int index = tvFace[j].tv[k]; if (index == i) { tvFace[j].tv[k] = current; } index = tvFace[j].interiors[k]; if ((index >=0) && (index == i)) { tvFace[j].interiors[k] = current; } index = tvFace[j].handles[k*2]; if ((index >=0) && (index == i)) { tvFace[j].handles[k*2] = current; } index = tvFace[j].handles[k*2+1]; if ((index >=0) && (index == i)) { tvFace[j].handles[k*2+1] = current; } } } current++; } } }
void MeshTopoData::BuildInitialMapping(PatchMesh *msh) { //build bounding box Box3 bbox; bbox.Init(); //normalize the length width height for (int i = 0; i < TVMaps.f.Count(); i++) { int pcount = 3; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { bbox += TVMaps.geomPoints[TVMaps.f[i]->v[j]]; if (TVMaps.f[i]->flags & FLAG_CURVEDMAPPING) { if (TVMaps.f[i]->vecs) { bbox += TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]]; bbox += TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]]; if (TVMaps.f[i]->flags & FLAG_INTERIOR) { bbox += TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]]; } } } } } Tab<int> indexList; int vct = msh->numVecs+msh->numVerts; indexList.SetCount(vct); BitArray usedIndex; usedIndex.SetSize(vct); usedIndex.ClearAll(); for (int i = 0; i < vct; i++) indexList[i] = -1; for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { // usedIndex.Set(TVMaps.f[i].t[j]); usedIndex.Set(msh->patches[i].v[j]); if (TVMaps.f[i]->flags & FLAG_CURVEDMAPPING) { if (TVMaps.f[i]->vecs) { usedIndex.Set(msh->patches[i].vec[j*2]+msh->numVerts); usedIndex.Set(msh->patches[i].vec[j*2+1]+msh->numVerts); if (TVMaps.f[i]->flags & FLAG_INTERIOR) { usedIndex.Set(msh->patches[i].interior[j]+msh->numVerts); } } } } } } int ct = 0; for (int i = 0; i < usedIndex.GetSize(); i++) { if (usedIndex[i]) indexList[i] = ct++; } TVMaps.v.SetCount(usedIndex.NumberSet()); mVSel.SetSize(usedIndex.NumberSet()); //watje 10-19-99 bug 213437 to prevent a divide by 0 which gives you a huge u,v, or w value if (bbox.Width().x == 0.0f) bbox += Point3(0.5f,0.0f,0.0f); if (bbox.Width().y == 0.0f) bbox += Point3(0.0f,0.5f,0.0f); if (bbox.Width().z == 0.0f) bbox += Point3(0.0f,0.0f,0.5f); for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; TVMaps.f[i]->flags &= ~FLAG_DEAD; for (int j = 0; j < pcount; j++) { int index; int a = msh->patches[i].v[j]; index = indexList[a]; TVMaps.f[i]->t[j] = index; Point3 uv( TVMaps.geomPoints[TVMaps.f[i]->v[j]].x/bbox.Width().x + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].y/bbox.Width().y + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].z/bbox.Width().z + 0.5f); TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); if (TVMaps.f[i]->flags & FLAG_CURVEDMAPPING) { if (TVMaps.f[i]->vecs) { // usedIndex.Set(msh->patches[i].vec[j*2]+msh->numVerts); // usedIndex.Set(msh->patches[i].vec[j*2+1]+msh->numVerts); int index; int a = msh->patches[i].vec[j*2]+msh->numVerts; index = indexList[a]; TVMaps.f[i]->vecs->handles[j*2] = index; Point3 uv( TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]].x/bbox.Width().x + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]].y/bbox.Width().y + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]].z/bbox.Width().z + 0.5f); TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); a = msh->patches[i].vec[j*2+1]+msh->numVerts; index = indexList[a]; TVMaps.f[i]->vecs->handles[j*2+1] = index; uv.x = TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]].x/bbox.Width().x + 0.5f; uv.y = TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]].y/bbox.Width().y + 0.5f; uv.z = TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]].z/bbox.Width().z + 0.5f; TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); if (TVMaps.f[i]->flags & FLAG_INTERIOR) { int index; int a = msh->patches[i].interior[j]+msh->numVerts; index = indexList[a]; TVMaps.f[i]->vecs->interiors[j] = index; uv.x = TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]].x/bbox.Width().x + 0.5f; uv.y = TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]].y/bbox.Width().y + 0.5f; uv.z = TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]].z/bbox.Width().z + 0.5f; TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); } } } } } } }
void MeshTopoData::BuildInitialMapping(MNMesh *msh) { //build bounding box Box3 bbox; bbox.Init(); int vertCount = 0; //normalize the length width height for (int i = 0; i < TVMaps.f.Count(); i++) { int pcount = 3; pcount = TVMaps.f[i]->count; vertCount += pcount; for (int j = 0; j < pcount; j++) { bbox += TVMaps.geomPoints[TVMaps.f[i]->v[j]]; } } vertCount = msh->numv; Tab<int> indexList; indexList.SetCount(vertCount); BitArray usedIndex; usedIndex.SetSize(vertCount); usedIndex.ClearAll(); for (int i = 0; i < vertCount; i++) indexList[i] = -1; for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { usedIndex.Set(msh->f[i].vtx[j]); } } } int ct = 0; for (int i = 0; i < usedIndex.GetSize(); i++) { if (usedIndex[i]) indexList[i] = ct++; } TVMaps.v.SetCount(usedIndex.NumberSet()); mVSel.SetSize(usedIndex.NumberSet()); //watje 10-19-99 bug 213437 to prevent a divide by 0 which gives you a huge u,v, or w value if (bbox.Width().x == 0.0f) bbox += Point3(0.5f,0.0f,0.0f); if (bbox.Width().y == 0.0f) bbox += Point3(0.0f,0.5f,0.0f); if (bbox.Width().z == 0.0f) bbox += Point3(0.0f,0.0f,0.5f); for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; TVMaps.f[i]->flags &= ~FLAG_DEAD; for (int j = 0; j < pcount; j++) { int index; int a = msh->f[i].vtx[j]; index = indexList[a]; TVMaps.f[i]->t[j] = index; Point3 uv( TVMaps.geomPoints[TVMaps.f[i]->v[j]].x/bbox.Width().x + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].y/bbox.Width().y + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].z/bbox.Width().z + 0.5f ); TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); } } } }
void UnwrapMod::BuildInitialMapping(Mesh *msh) { //build bounding box Box3 bbox; bbox.Init(); //normalize the length width height for (int i = 0; i < TVMaps.f.Count(); i++) { int pcount = 3; // if (TVMaps.f[i].flags & FLAG_QUAD) pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { bbox += TVMaps.geomPoints[TVMaps.f[i]->v[j]]; } } Tab<int> indexList; indexList.SetCount(TVMaps.f.Count() *4); BitArray usedIndex; usedIndex.SetSize(TVMaps.f.Count() *4); usedIndex.ClearAll(); for (i = 0; i < TVMaps.f.Count()*4; i++) indexList[i] = -1; for (i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; // if (TVMaps.f[i].flags & FLAG_QUAD) pcount = 4; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { usedIndex.Set(msh->faces[i].v[j]); } } } int ct = 0; for (i = 0; i < usedIndex.GetSize(); i++) { if (usedIndex[i]) indexList[i] = ct++; } TVMaps.v.SetCount(usedIndex.NumberSet()); TVMaps.cont.SetCount(usedIndex.NumberSet()); vsel.SetSize(usedIndex.NumberSet()); //watje 10-19-99 bug 213437 to prevent a divide by 0 which gives you a huge u,v, or w value if (bbox.Width().x == 0.0f) bbox += Point3(0.5f,0.0f,0.0f); if (bbox.Width().y == 0.0f) bbox += Point3(0.0f,0.5f,0.0f); if (bbox.Width().z == 0.0f) bbox += Point3(0.0f,0.0f,0.5f); for (i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; // if (TVMaps.f[i].flags & FLAG_QUAD) pcount = 4; pcount = TVMaps.f[i]->count; TVMaps.f[i]->flags &= ~FLAG_DEAD; for (int j = 0; j < pcount; j++) { int index; int a = msh->faces[i].v[j]; index = indexList[a]; TVMaps.f[i]->t[j] = index; TVMaps.v[index].p.x = TVMaps.geomPoints[TVMaps.f[i]->v[j]].x/bbox.Width().x + 0.5f; TVMaps.v[index].p.y = TVMaps.geomPoints[TVMaps.f[i]->v[j]].y/bbox.Width().y + 0.5f; TVMaps.v[index].p.z = TVMaps.geomPoints[TVMaps.f[i]->v[j]].z/bbox.Width().z + 0.5f; TVMaps.v[index].influence = 0.f; TVMaps.v[index].flags = 0.f; TVMaps.cont[index] = NULL; } } } }
void UnwrapMod::MeshUpdateGData(Mesh *mesh, BitArray faceSel) { gverts.d.SetCount(faceSel.GetSize()*4); gverts.sel.SetSize(faceSel.GetSize()*4,1); gverts.sel.ClearAll(); Face *tf = mesh->faces; Point3 *tp = mesh->verts; //isolate a vertex list of just the selected faces for (int i = 0; i < faceSel.GetSize(); i++) { if (faceSel[i]) { for (int j = 0; j < 3; j++) { int index = tf[i].v[j]; gverts.addPoint(index, tp[index]); } } } //build new tv faces int ct = gfaces.Count(); for (i =0; i < ct; i++) { if (gfaces[i]->vecs) delete gfaces[i]->vecs; gfaces[i]->vecs = NULL; if (gfaces[i]->t) delete [] gfaces[i]->t; gfaces[i]->t = NULL; if (gfaces[i]->v) delete [] gfaces[i]->v; gfaces[i]->v = NULL; delete gfaces[i]; gfaces[i] = NULL; } gfaces.SetCount(faceSel.NumberSet()); for (i =0; i < faceSel.NumberSet(); i++) gfaces[i] = NULL; ct = 0; for (i = 0; i < faceSel.GetSize(); i++) { if (faceSel[i]) { UVW_TVFaceClass *t = new UVW_TVFaceClass; t->FaceIndex = i; t->flags = 0; t->t = new int[3]; t->v = new int[3]; t->count = 3; for (int j = 0; j < 3; j++) { //find indes in our vert array t->t[j] = (int)tf[i].v[j]; } t->flags = TVMaps.f[i]->flags; if (gfaces[ct]) gfaces[ct]->DeleteVec(); if ((gfaces[ct]) && (gfaces[ct]->t)) { delete [] gfaces[ct]->t; gfaces[ct]->t = NULL; } if ((gfaces[ct]) && (gfaces[ct]->v)) { delete [] gfaces[ct]->v; gfaces[ct]->v = NULL; } if (gfaces[ct]) delete gfaces[ct]; gfaces[ct++] = t; } } }
void UnwrapMod::fnCopy() { int ct = 0; int currentLDID = -1; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { BitArray fsel = mMeshTopoData[ldID]->GetFaceSelection(); if (fsel.NumberSet()) { currentLDID = ldID; ct++; } } if (ct > 1) { //pop warnign message TSTR error,msg; error.printf(_T("%s"),GetString(IDS_PW_ERROR)); msg.printf(_T("%s"),GetString(IDS_PW_COPYERROR)); MessageBox( NULL,msg,error,MB_OK); return; } //check for type if ((ct == 0) || (currentLDID==-1)) return; copyPasteBuffer.iRotate = 0; copyPasteBuffer.copyType = 2; //make sure we only have one faces off of one local data selected MeshTopoData *ld = mMeshTopoData[currentLDID]; copyPasteBuffer.mod = this; //copy the vertex list over copyPasteBuffer.tVertData.SetCount(ld->GetNumberTVVerts());//TVMaps.v.Count()); for (int i =0; i < ld->GetNumberTVVerts(); i++)//TVMaps.v.Count(); i++) { copyPasteBuffer.tVertData[i] = ld->GetTVVert(i);//TVMaps.v[i].p; } // MeshTopoData *md = (MeshTopoData*)mcList[0]->localData;//copy the face data over that is selected copyPasteBuffer.lmd = ld; for (int i = 0; i < copyPasteBuffer.faceData.Count(); i++) { delete copyPasteBuffer.faceData[i]; } BitArray faceSel = ld->GetFaceSelection(); ct = faceSel.NumberSet(); if (faceSel.NumberSet() == ld->GetNumberFaces())//TVMaps.f.Count()) copyPasteBuffer.copyType = 1; if (faceSel.NumberSet() == 1) copyPasteBuffer.copyType = 0; copyPasteBuffer.faceData.SetCount(ct); int faceIndex = 0; for (int i = 0; i < ld->GetNumberFaces(); i++)//TVMaps.f.Count(); i++) { if (faceSel[i]) { UVW_TVFaceClass *f = ld->CloneFace(i);//TVMaps.f[i]->Clone(); copyPasteBuffer.faceData[faceIndex] = f; faceIndex++; } } }
void UnwrapMod::fnFlattenMapByMatID(float angleThreshold, float spacing, BOOL normalize, int layoutType, BOOL rotateClusters, BOOL fillHoles) { int holdSubMode = fnGetTVSubMode(); fnSetTVSubMode(TVVERTMODE); // vsel.SetAll(); Tab<Point3*> normList; normList.SetCount(6); normList[0] = new Point3(1.0f,0.0f,0.0f); normList[1] = new Point3(-1.0f,0.0f,0.0f); normList[2] = new Point3(0.0f,1.0f,0.0f); normList[3] = new Point3(0.0f,-1.0f,0.0f); normList[4] = new Point3(0.0f,0.0f,1.0f); normList[5] = new Point3(0.0f,0.0f,-1.0f); int largestID = -1; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; for (int i = 0; i < ld->GetNumberFaces(); i++)//TVMaps.f.Count(); i++) { int matID = ld->GetFaceMatID(i); if (matID > largestID) largestID = matID; } } BitArray usedMats; usedMats.SetSize(largestID+1); usedMats.ClearAll(); for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; for (int i = 0; i < ld->GetNumberFaces(); i++)//TVMaps.f.Count(); i++) { int matID = ld->GetFaceMatID(i); usedMats.Set(matID,TRUE); } } Tab<int> matIDs; matIDs.SetCount(usedMats.NumberSet()); int ct = 0; for (int i = 0; i < usedMats.GetSize(); i++) { if (usedMats[i]) { matIDs[ct] = i; ct++; } } //loop through our mat ID Tab<ClusterClass*> matIDClusters; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; for (int i = 0; i < matIDs.Count(); i++) { int matID = matIDs[i]; FreeClusterList(); for (int ldIDSel = 0; ldIDSel < mMeshTopoData.Count(); ldIDSel++) { mMeshTopoData[ldIDSel]->ClearFaceSelection(); } ld->SelectByMatID(matID); if (ld->GetFaceSelection().NumberSet()) { ClusterClass *mcluster = new ClusterClass(); mcluster->ld = ld; for (int j = 0; j < ld->GetNumberFaces(); j++)//TVMaps.f.Count(); j++) { if (ld->GetFaceSelected(j))//(TVMaps.f[j]->MatID == matIDs[i]) { mcluster->faces.Append(1,&j,100); } } matIDClusters.Append(1,&mcluster,5); fnFlattenMap(flattenAngleThreshold, &normList, flattenSpacing, FALSE, 2, flattenRotate, flattenCollapse); } } } FreeClusterList(); clusterList.SetCount(matIDClusters.Count()); for (int i = 0; i < matIDClusters.Count(); i++) { clusterList[i] = new ClusterClass(); clusterList[i]->ld = matIDClusters[i]->ld; clusterList[i]->faces.SetCount(matIDClusters[i]->faces.Count()); for (int j = 0; j < matIDClusters[i]->faces.Count(); j++) clusterList[i]->faces[j] = matIDClusters[i]->faces[j]; } for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) mMeshTopoData[ldID]->UpdateClusterVertices(clusterList); Pack(0, spacing, normalize, rotateClusters, fillHoles,FALSE,FALSE); FreeClusterList(); TimeValue t = GetCOREInterface()->GetTime(); if (normalize) { float per = 1.0f-(spacing*2.0f); float add = spacing; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; for (int i = 0; i < ld->GetNumberTVVerts(); i++)//TVMaps.v.Count(); i++) { Point3 p = ld->GetTVVert(i); p *= per; p.x += add; p.y += add; ld->SetTVVert(t,i,p,this); // if (TVMaps.cont[i]) // TVMaps.cont[i]->SetValue(0,&TVMaps.v[i].p,CTRL_ABSOLUTE); } } } for (int i = 0; i < matIDs.Count(); i++) { if (matIDClusters[i]) delete matIDClusters[i]; } for (int i = 0; i < 6; i++) delete normList[i]; fnSetTVSubMode(holdSubMode); }
void UnwrapMod::fnUnfoldSelectedPolygons(int unfoldMethod, BOOL normalize) { // flatten selected polygons if (!ip) return; BailStart(); theHold.Begin(); HoldPointsAndFaces(); Point3 normal(0.0f,0.0f,1.0f); for (int ldID =0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; ld->HoldFaceSel(); } BOOL bContinue = TRUE; for (int ldID =0; ldID < mMeshTopoData.Count(); ldID++) { Tab<Point3> mapNormal; mapNormal.SetCount(0); MeshTopoData *ld = mMeshTopoData[ldID]; for (int ldIDPrep =0; ldIDPrep < mMeshTopoData.Count(); ldIDPrep++) { MeshTopoData *ldPrep = mMeshTopoData[ldIDPrep]; if (ld != ldPrep) ldPrep->ClearFaceSelection(); else ldPrep->RestoreFaceSel(); } //hold our face selection //get our processed list BitArray holdFaces = ld->GetFaceSelection(); BitArray processedFaces = ld->GetFaceSelection(); while (processedFaces.NumberSet()) { //select the first one int seed = -1; for (int faceID = 0; faceID < processedFaces.GetSize(); faceID++) { if (processedFaces[faceID]) { seed = faceID; faceID = processedFaces.GetSize(); } } BitArray faceSel = ld->GetFaceSel(); faceSel.ClearAll(); //select the element the first one faceSel.Set(seed,TRUE); //select it ld->SetFaceSel(faceSel); SelectGeomElement(ld); faceSel = ld->GetFaceSel(); // ld->SelectElement(TVFACEMODE,FALSE); faceSel &= holdFaces; //remove that from our process list for (int faceID = 0; faceID < faceSel.GetSize(); faceID++) { if (faceSel[faceID]) { processedFaces.Set(faceID,FALSE); } } ld->SetFaceSel(faceSel); bContinue = BuildCluster( mapNormal, 5.0f, TRUE, TRUE, MeshTopoData::kFaceAngle); TSTR statusMessage; if (bContinue) { for (int i =0; i < clusterList.Count(); i++) { ld->ClearFaceSelection(); for (int j = 0; j < clusterList[i]->faces.Count();j++) ld->SetFaceSelected(clusterList[i]->faces[j],TRUE);// sel.Set(clusterList[i]->faces[j]); ld->PlanarMapNoScale(clusterList[i]->normal,this); int per = (i * 100)/clusterList.Count(); statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_MAPPING),per); if (Bail(ip,statusMessage)) { i = clusterList.Count(); bContinue = FALSE; } } DebugPrint (_T("Final Vct %d \n"),ld->GetNumberTVVerts()); if ( (bContinue) && (clusterList.Count() > 1) ) { Tab<Point3> objNormList; BuildNormals(ld,objNormList); //remove internal edges Tab<int> clusterGroups; clusterGroups.SetCount(ld->GetNumberFaces()); for (int i =0; i < clusterGroups.Count(); i++) { clusterGroups[i] = -1; } for (int i = 0; i < clusterList.Count(); i++) { for (int j = 0; j < clusterList[i]->faces.Count(); j++) { int faceIndex = clusterList[i]->faces[j]; clusterGroups[faceIndex] = i; } } BitArray processedClusters; processedClusters.SetSize(clusterList.Count()); processedClusters.ClearAll(); Tab<BorderClass> edgesToBeProcessed; BOOL done = FALSE; processedClusters.Set(0); clusterList[0]->newX = 0.0f; clusterList[0]->newY = 0.0f; // clusterList[0]->angle = 0.0f; for (int i = 0; i < clusterList[0]->borderData.Count(); i++) { int outerFaceIndex = clusterList[0]->borderData[i].outerFace; int connectedClusterIndex = clusterGroups[outerFaceIndex]; if ((connectedClusterIndex != 0) && (connectedClusterIndex != -1)) { edgesToBeProcessed.Append(1,&clusterList[0]->borderData[i]); } } BitArray seedFaceList; seedFaceList.SetSize(clusterGroups.Count()); seedFaceList.ClearAll(); for (int i = 0; i < seedFaces.Count(); i++) { seedFaceList.Set(seedFaces[i]); } while (!done) { Tab<int> clustersJustProcessed; clustersJustProcessed.ZeroCount(); done = TRUE; int edgeToAlign = -1; float angDist = PI*2; if (unfoldMethod == 1) angDist = PI*2; else if (unfoldMethod == 2) angDist = 0; int i; for (i = 0; i < edgesToBeProcessed.Count(); i++) { int outerFace = edgesToBeProcessed[i].outerFace; int connectedClusterIndex = clusterGroups[outerFace]; if (!processedClusters[connectedClusterIndex]) { int innerFaceIndex = edgesToBeProcessed[i].innerFace; int outerFaceIndex = edgesToBeProcessed[i].outerFace; //get angle Point3 innerNorm, outerNorm; innerNorm = objNormList[innerFaceIndex]; outerNorm = objNormList[outerFaceIndex]; float dot = DotProd(innerNorm,outerNorm); float angle = 0.0f; if (dot == -1.0f) angle = PI; else if (dot >= 1.0f) angle = 0.f; else angle = acos(dot); if (unfoldMethod == 1) { if (seedFaceList[outerFaceIndex]) angle = 0.0f; if (angle < angDist) { angDist = angle; edgeToAlign = i; } } else if (unfoldMethod == 2) { if (seedFaceList[outerFaceIndex]) angle = 180.0f; if (angle > angDist) { angDist = angle; edgeToAlign = i; } } } } if (edgeToAlign != -1) { int innerFaceIndex = edgesToBeProcessed[edgeToAlign].innerFace; int outerFaceIndex = edgesToBeProcessed[edgeToAlign].outerFace; int edgeIndex = edgesToBeProcessed[edgeToAlign].edge; int connectedClusterIndex = clusterGroups[outerFaceIndex]; seedFaceList.Set(outerFaceIndex, FALSE); processedClusters.Set(connectedClusterIndex); clustersJustProcessed.Append(1,&connectedClusterIndex); ld->AlignCluster(clusterList,connectedClusterIndex,innerFaceIndex, outerFaceIndex,edgeIndex,this); done = FALSE; } //build new cluster list for (int j = 0; j < clustersJustProcessed.Count(); j++) { int clusterIndex = clustersJustProcessed[j]; for (int i = 0; i < clusterList[clusterIndex]->borderData.Count(); i++) { int outerFaceIndex = clusterList[clusterIndex]->borderData[i].outerFace; int connectedClusterIndex = clusterGroups[outerFaceIndex]; if ((connectedClusterIndex != 0) && (connectedClusterIndex != -1) && (!processedClusters[connectedClusterIndex])) { edgesToBeProcessed.Append(1,&clusterList[clusterIndex]->borderData[i]); } } } } } ld->ClearSelection(TVVERTMODE); for (int i = 0; i < clusterList.Count(); i++) { MeshTopoData *ld = clusterList[i]->ld; ld->UpdateClusterVertices(clusterList); for (int j =0; j < clusterList[i]->faces.Count(); j++) { int faceIndex = clusterList[i]->faces[j]; int degree = ld->GetFaceDegree(faceIndex); for (int k =0; k < degree; k++) { int vertexIndex = ld->GetFaceTVVert(faceIndex,k);//TVMaps.f[faceIndex]->t[k]; ld->SetTVVertSelected(vertexIndex,TRUE);//vsel.Set(vertexIndex); } } } //now weld the verts if (normalize) { NormalizeCluster(); } ld->WeldSelectedVerts(0.001f,this); } FreeClusterList(); } } if (bContinue) { theHold.Accept(GetString(IDS_PW_PLANARMAP)); theHold.Suspend(); fnSyncTVSelection(); theHold.Resume(); } else { theHold.Cancel(); } for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { mMeshTopoData[ldID]->BuildTVEdges(); mMeshTopoData[ldID]->RestoreFaceSel(); } theHold.Suspend(); fnSyncGeomSelection(); theHold.Resume(); if (matid != -1) // if we have a matID fileter set we need to rebuild since topology has changed SetMatFilters(); NotifyDependents(FOREVER,PART_SELECT,REFMSG_CHANGE); InvalidateView(); }
void DeletePatchParts(PatchMesh *patch, RPatchMesh *rpatch, BitArray &delVerts, BitArray &delPatches) { int patches = patch->getNumPatches(); int verts = patch->getNumVerts(); int vecs = patch->getNumVecs(); int dest; // We treat vectors specially in order to clean up after welds. First, we tag 'em all, // then untag only those on unselected patches so that any dangling vectors will be deleted. BitArray delVectors(vecs); delVectors.SetAll(); // Untag vectors that are on nondeleted patches int i; for (i = 0; i < patches; ++i) { if (!delPatches[i]) { Patch& p = patch->patches[i]; int j; for (j = 0; j <(p.type * 2); ++j) { delVectors.Clear(p.vec[j]); } for (j = 0; j < p.type; ++j) delVectors.Clear(p.interior[j]); } } // Make a table of vertices that are still in use -- Used to // delete those vertices which are floating, unused, in space. BitArray usedVerts(verts); usedVerts.ClearAll(); for (i = 0; i < patches; ++i) { if (!delPatches[i]) { Patch& p = patch->patches[i]; for (int j = 0; j < p.type; ++j) { usedVerts.Set(p.v[j]); } } } for (i = 0; i < verts; ++i) { if (!usedVerts[i]) delVerts.Set(i); } // If we have texture vertices, handle them, too for (int chan = 0; chan < patch->getNumMaps(); ++chan) { int tverts = patch->numTVerts[chan]; if (tverts && patch->tvPatches[chan]) { BitArray delTVerts(tverts); delTVerts.SetAll(); for (i = 0; i < patches; ++i) { if (!delPatches[i]) { Patch& p = patch->patches[i]; TVPatch& tp = patch->tvPatches[chan][i]; for (int j = 0; j < p.type; ++j) delTVerts.Clear(tp.tv[j]); } } // Got the list of tverts to delete -- now delete 'em // Build a table of redirected texture vertex indices int newTVerts = tverts - delTVerts.NumberSet(); IntTab tVertIndex; tVertIndex.SetCount(tverts); UVVert *newTVertArray = new UVVert[newTVerts]; dest = 0; for (i = 0; i < tverts; ++i) { if (!delTVerts[i]) { newTVertArray[dest] = patch->tVerts[chan][i]; tVertIndex[i] = dest++; } } delete[] patch->tVerts[chan]; #if MAX_RELEASE <= 3100 patch->tVerts[chan] = newTVertArray; #else *(patch->tVerts[chan]) = *newTVertArray; #endif patch->numTVerts[chan] = newTVerts; // Now, copy the untagged texture patches to a new array // While you're at it, redirect the vertex indices int newTVPatches = patches - delPatches.NumberSet(); TVPatch *newArray = new TVPatch[newTVPatches]; dest = 0; for (i = 0; i < patches; ++i) { if (!delPatches[i]) { Patch& p = patch->patches[i]; TVPatch& tp = newArray[dest++]; tp = patch->tvPatches[chan][i]; for (int j = 0; j < p.type; ++j) tp.tv[j] = tVertIndex[tp.tv[j]]; } } delete[] patch->tvPatches[chan]; patch->tvPatches[chan] = newArray;; } } // Build a table of redirected vector indices IntTab vecIndex; vecIndex.SetCount(vecs); int newVectors = vecs - delVectors.NumberSet(); PatchVec *newVecArray = new PatchVec[newVectors]; dest = 0; for (i = 0; i < vecs; ++i) { if (!delVectors[i]) { newVecArray[dest] = patch->vecs[i]; vecIndex[i] = dest++; } else vecIndex[i] = -1; } delete[] patch->vecs; patch->vecs = newVecArray; patch->numVecs = newVectors; // Build a table of redirected vertex indices int newVerts = verts - delVerts.NumberSet(); IntTab vertIndex; vertIndex.SetCount(verts); PatchVert *newVertArray = new PatchVert[newVerts]; BitArray newVertSel(newVerts); newVertSel.ClearAll(); dest = 0; for (i = 0; i < verts; ++i) { if (!delVerts[i]) { newVertArray[dest] = patch->verts[i]; newVertSel.Set(dest, patch->vertSel[i]); // redirect & adjust attached vector list PatchVert& v = newVertArray[dest]; for (int j = 0; j < v.vectors.Count(); ++j) { v.vectors[j] = vecIndex[v.vectors[j]]; if (v.vectors[j] < 0) { v.vectors.Delete(j, 1); j--; // realign index } } vertIndex[i] = dest++; } } delete[] patch->verts; patch->verts = newVertArray; patch->numVerts = newVerts; patch->vertSel = newVertSel; // Now, copy the untagged patches to a new array // While you're at it, redirect the vertex and vector indices int newPatches = patches - delPatches.NumberSet(); Patch *newArray = new Patch[newPatches]; BitArray newPatchSel(newPatches); newPatchSel.ClearAll(); dest = 0; for (i = 0; i < patches; ++i) { if (!delPatches[i]) { newArray[dest] = patch->patches[i]; Patch& p = newArray[dest]; int j; for (j = 0; j < p.type; ++j) p.v[j] = vertIndex[p.v[j]]; for (j = 0; j <(p.type * 2); ++j) p.vec[j] = vecIndex[p.vec[j]]; for (j = 0; j < p.type; ++j) p.interior[j] = vecIndex[p.interior[j]]; newPatchSel.Set(dest++, patch->patchSel[i]); } } // Rebuild info in rpatch rpatch->DeleteAndSweep (delVerts, delPatches, *patch); delete[] patch->patches; patch->patches = newArray;; patch->numPatches = newPatches; patch->patchSel.SetSize(newPatches, TRUE); patch->patchSel = newPatchSel; patch->buildLinkages(); }
BOOL MeshTopoData::NormalMap(Tab<Point3*> *normalList, Tab<ClusterClass*> &clusterList, UnwrapMod *mod ) { if (TVMaps.f.Count() == 0) return FALSE; BitArray polySel = mFSel; BitArray holdPolySel = mFSel; Point3 normal(0.0f,0.0f,1.0f); Tab<Point3> mapNormal; mapNormal.SetCount(normalList->Count()); for (int i =0; i < mapNormal.Count(); i++) { mapNormal[i] = *(*normalList)[i]; ClusterClass *cluster = new ClusterClass(); cluster->normal = mapNormal[i]; cluster->ld = this; clusterList.Append(1,&cluster); } //check for type BOOL bContinue = TRUE; TSTR statusMessage; Tab<Point3> objNormList; mod->BuildNormals(this,objNormList); if (objNormList.Count() == 0) { return FALSE; } BitArray skipFace; skipFace.SetSize(mFSel.GetSize()); skipFace.ClearAll(); int numberSet = mFSel.NumberSet(); for (int i = 0; i < mFSel.GetSize(); i++) { if (!mFSel[i]) skipFace.Set(i); } for (int i =0; i < objNormList.Count(); i++) { int index = -1; float angle = 0.0f; if (skipFace[i] == FALSE) { for (int j =0; j < clusterList.Count(); j++) { if (clusterList[j]->ld == this) { Point3 debugNorm = objNormList[i]; float dot = DotProd(debugNorm,clusterList[j]->normal);//mapNormal[j]); float newAngle = (acos(dot)); if ((dot >= 1.0f) || (newAngle <= angle) || (index == -1)) { index = j; angle = newAngle; } } } if (index != -1) { clusterList[index]->faces.Append(1,&i); } } } BitArray sel; sel.SetSize(TVMaps.f.Count()); for (int i =0; i < clusterList.Count(); i++) { if (clusterList[i]->ld == this) { sel.ClearAll(); for (int j = 0; j < clusterList[i]->faces.Count();j++) sel.Set(clusterList[i]->faces[j]); if (sel.NumberSet() > 0) { // fnSelectPolygonsUpdate(&sel, FALSE); mFSel = sel; PlanarMapNoScale(clusterList[i]->normal,mod); } int per = (i * 100)/clusterList.Count(); statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_MAPPING),per); if (mod->Bail(GetCOREInterface(),statusMessage)) { i = clusterList.Count(); bContinue = FALSE; } } } for (int i =0; i < clusterList.Count(); i++) { if (clusterList[i]->faces.Count() == 0) { delete clusterList[i]; clusterList.Delete(i,1); i--; } } BitArray clusterVerts; clusterVerts.SetSize(TVMaps.v.Count()); for (int i =0; i < clusterList.Count(); i++) { if (clusterList[i]->ld == this) { clusterVerts.ClearAll(); for (int j = 0; j < clusterList[i]->faces.Count(); j++) { int findex = clusterList[i]->faces[j]; AddVertsToCluster(findex,clusterVerts, clusterList[i]); } } } mFSel = holdPolySel ; return bContinue; }
BOOL MeshTopoData::BuildCluster( Tab<Point3> normalList, float threshold, BOOL connected, BOOL cleanUpStrayFaces, MeshTopoData::GroupBy groupBy, Tab<ClusterClass*> &clusterList, UnwrapMod *mod) { BitArray processedFaces; Tab<BorderClass> clusterBorder; BitArray sel; sel.SetSize(TVMaps.f.Count()); processedFaces.SetSize(TVMaps.f.Count()); processedFaces.ClearAll(); //check for type float radThreshold = threshold * PI/180.0f; TSTR statusMessage; Tab<Point3> objNormList; mod->BuildNormals(this,objNormList); for (int i = 0; i < mFSel.GetSize(); i++) { if (!mFSel[i]) processedFaces.Set(i); } //build normals AdjEdgeList *edges = NULL; BOOL deleteEdges = FALSE; if ((mesh) && (connected)) { edges = new AdjEdgeList(*mesh); deleteEdges = TRUE; } if (connected) { BOOL done = FALSE; int currentNormal = 0; if (normalList.Count() == 0) done = TRUE; while (!done) { sel.ClearAll(); //find the closest normal within the threshold float angDist = -1.0f; int hitIndex = -1; for (int i =0; i < objNormList.Count(); i++) { if (!processedFaces[i]) { float cangle = acos(DotProd(normalList[currentNormal],objNormList[i])); if (((cangle < angDist) || (hitIndex == -1)) && (cangle < radThreshold)) { angDist = cangle; hitIndex = i; } } } int bail = 0; if ( (hitIndex != -1) ) { //FIX HERE BY MAT OR SMGRP mod->SelectFacesByGroup( this,sel,hitIndex, normalList[currentNormal], threshold, FALSE, groupBy, objNormList, clusterBorder, edges); //add cluster if (sel.NumberSet() > 0) { //create a cluster and add it BitArray clusterVerts; clusterVerts.SetSize(TVMaps.v.Count()); clusterVerts.ClearAll(); ClusterClass *cluster = new ClusterClass(); cluster->ld = this; BOOL hit = FALSE; cluster->normal = normalList[currentNormal]; for (int j = 0; j < sel.GetSize(); j++) { if (sel[j] && (!processedFaces[j])) { //add to cluster processedFaces.Set(j,TRUE); cluster->faces.Append(1,&j); AddVertsToCluster(j,clusterVerts, cluster); hit = TRUE; } } cluster->borderData = clusterBorder; //add edges that were processed if (hit) { clusterList.Append(1,&cluster); bail++; } else { delete cluster; } } } currentNormal++; if (currentNormal >= normalList.Count()) { currentNormal = 0; if (bail == 0) done = TRUE; } int per = (processedFaces.NumberSet() * 100)/processedFaces.GetSize(); statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_BUILDCLUSTER),per); if (mod->Bail(mod->ip,statusMessage)) { if (deleteEdges) delete edges; return FALSE; } } } else { for (int i =0; i < normalList.Count(); i++) { sel.ClearAll(); //find closest face norm mod->SelectFacesByNormals(this,sel,normalList[i], threshold, objNormList); //add cluster int numberSet = sel.NumberSet(); int totalNumberSet = processedFaces.NumberSet(); if ( numberSet > 0) { //create a cluster and add it ClusterClass *cluster = new ClusterClass(); cluster->ld = this; BOOL hit = FALSE; cluster->normal = normalList[i]; BitArray clusterVerts; clusterVerts.SetSize(TVMaps.v.Count()); clusterVerts.ClearAll(); for (int j = 0; j < sel.GetSize(); j++) { if (sel[j] && (!processedFaces[j])) { //add to cluster processedFaces.Set(j,TRUE); cluster->faces.Append(1,&j); AddVertsToCluster(j,clusterVerts, cluster); hit = TRUE; } } if (hit) clusterList.Append(1,&cluster); else delete cluster; } int per = (i * 100)/normalList.Count(); statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_BUILDCLUSTER),per); if (mod->Bail(mod->ip,statusMessage)) { if (deleteEdges) delete edges; return FALSE; } } } //process the ramaining if (cleanUpStrayFaces) { // Tab<int> tempSeedFaces = seedFaces; int ct = 0; if (mod->seedFaces.Count() > 0) ct = mod->seedFaces[0]; while ( (processedFaces.NumberSet() != processedFaces.GetSize()) ) { if (!processedFaces[ct]) { if (connected) { mod->SelectFacesByGroup( this,sel,ct, objNormList[ct], threshold, FALSE,groupBy, objNormList, clusterBorder, edges); } else mod->SelectFacesByNormals(this,sel,objNormList[ct], threshold, objNormList); //add cluster if (sel.NumberSet() > 0) { //create a cluster and add it ClusterClass *cluster = new ClusterClass(); cluster->ld = this; cluster->normal = objNormList[ct]; BOOL hit = FALSE; BitArray clusterVerts; clusterVerts.SetSize(TVMaps.v.Count()); clusterVerts.ClearAll(); for (int j = 0; j < sel.GetSize(); j++) { if (sel[j] && (!processedFaces[j])) { //add to cluster processedFaces.Set(j,TRUE); cluster->faces.Append(1,&j); AddVertsToCluster(j,clusterVerts, cluster); hit = TRUE; } } if (connected) { cluster->borderData = clusterBorder; } if (hit) { clusterList.Append(1,&cluster); } else { delete cluster; } } } ct++; if (ct >= processedFaces.GetSize()) ct =0; int per = (processedFaces.NumberSet() * 100)/processedFaces.GetSize(); statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_BUILDCLUSTER),per); if (mod->Bail(mod->ip,statusMessage)) { if (deleteEdges) delete edges; return FALSE; } } } if (deleteEdges) delete edges; return TRUE; }