void EChamferMod::ModifyTriObject (TimeValue t, ModContext &mc, TriObject *tobj) { Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float amount; int i, j; m_pblock->GetValue (kEchAmount, t, amount, iv); // Convert existing selection (at whatever level) to edge selection: BitArray targetEdges; targetEdges.SetSize (mesh.numFaces*3); targetEdges.ClearAll (); switch (mesh.selLevel) { case MESH_OBJECT: targetEdges.SetAll (); break; case MESH_VERTEX: for (i=0; i<mesh.numFaces; i++) { for (j=0; j<3; j++) { if (!mesh.vertSel[mesh.faces[i].v[j]]) continue; // Don't select invisible edges: if (mesh.faces[i].getEdgeVis(j)) targetEdges.Set (i*3+j); if (mesh.faces[i].getEdgeVis((j+2)%3)) targetEdges.Set (i*3+(j+2)%3); } } break; case MESH_EDGE: targetEdges = mesh.edgeSel; break; case MESH_FACE: for (i=0; i<mesh.numFaces; i++) { if (!mesh.faceSel[i]) continue; for (j=0; j<3; j++) { // Don't select invisible edges: if (mesh.faces[i].getEdgeVis(j)) targetEdges.Set (i*3+j); } } break; } // Chamfer the edges -- this just does the topological operation. MeshDelta tmd; tmd.InitToMesh (mesh); MeshTempData temp; temp.SetMesh (&mesh); MeshChamferData *mcd = temp.ChamferData(); AdjEdgeList *ae = temp.AdjEList(); tmd.ChamferEdges (mesh, targetEdges, *mcd, ae); tmd.Apply (mesh); // Reset the meshdelta, temp data to deal with the post-chamfered topology: tmd.InitToMesh (mesh); temp.Invalidate (TOPO_CHANNEL); // Generates a new edge list, but preserves chamfer data temp.SetMesh (&mesh); tmd.ChamferMove (mesh, *temp.ChamferData(), amount, temp.AdjEList()); tmd.Apply (mesh); tobj->UpdateValidity(GEOM_CHAN_NUM,iv); }
void VWeldMod::ConvertTriSelection (Mesh & mesh, BitArray & targetVerts) { targetVerts.SetSize (mesh.numVerts); targetVerts.ClearAll (); int i, j; switch (mesh.selLevel) { case MESH_OBJECT: targetVerts.SetAll (); break; case MESH_VERTEX: targetVerts = mesh.vertSel; break; case MESH_EDGE: for (i=0; i<mesh.numFaces; i++) { for (j=0; j<3; j++) { if (!mesh.edgeSel[i*3+j]) continue; targetVerts.Set (mesh.faces[i].v[j]); targetVerts.Set (mesh.faces[i].v[(j+1)%3]); } } break; case MESH_FACE: for (i=0; i<mesh.numFaces; i++) { if (!mesh.faceSel[i]) continue; for (j=0; j<3; j++) targetVerts.Set (mesh.faces[i].v[j]); } break; } }
void NifImporter::WeldVertices(Mesh& mesh) { MeshDelta tmd(mesh); BitArray vTempSel; vTempSel.SetSize(mesh.getNumVerts()); vTempSel.SetAll(); tmd.WeldByThreshold(mesh, vTempSel, weldVertexThresh); tmd.Apply(mesh); }
////////////////////////////////// MESH WELDER //////////////////// static void WeldMesh(Mesh *mesh, float thresh) { if (thresh == 0.0f) thresh = (float)1e-30; // find only the coincident ones BitArray vset, eset; BitArray vset; vset.SetSize(mesh->numVerts); vset.SetAll(); MeshDelta md; md.WeldByThreshold(*mesh, vset, thresh); md.Apply(*mesh); }
void SymmetryMod::MirrorTriObject (Mesh & mesh, int axis, Matrix3 & tm, Matrix3 & itm, int normalMapChannel) { // Create scaling matrix for mirroring on selected axis: Point3 scale(1,1,1); scale[axis] = -1.0f; itm.Scale(scale,TRUE); // Hang on to a copy of the incoming face selection: BitArray inputFaceSel = mesh.faceSel; // Make the mirror copy of the entire mesh: int oldnumv = mesh.numVerts; int oldnumf = mesh.numFaces; int oldNumNormals = 0; if (normalMapChannel != INVALID_NORMALMAPCHANNEL) { MeshMap& map = mesh.Map(normalMapChannel); oldNumNormals = map.vnum; } BitArray fset; fset.SetSize (oldnumf); fset.SetAll (); mesh.CloneFaces (fset); // Clears selection on originals, sets it on new faces. // Transform the cloned vertices to their mirror images: for (int i=oldnumv; i<mesh.numVerts; i++) { mesh.verts[i] = (mesh.verts[i]*itm)*tm; } // Restore selection of input faces: for (int i=0; i<oldnumf; i++) mesh.faceSel.Set (i, inputFaceSel[i]); // Flip over new faces and select to match input: for (int i=oldnumf; i<mesh.numFaces; i++) { mesh.FlipNormal (i); mesh.faceSel.Set (i, inputFaceSel[i-oldnumf]); } //flip and specified normals/faces if (normalMapChannel != INVALID_NORMALMAPCHANNEL) { MeshMap& map = mesh.Map(normalMapChannel); int numNormals = map.vnum; Matrix3 mirrorTM = itm*tm; for (int i = oldNumNormals; i < numNormals; i++) { Point3 n = map.tv[i]; n = VectorTransform(n,mirrorTM); map.tv[i] = n; } } }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSplitBySource::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { if (pNode == NULL) return false; bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); int conditionType = pblock()->GetInt(kSplitBySource_conditionType, timeStart); // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int count = chAmount->Count(); bool isSelectedSource = false; int i, systemHandle = pNode->GetHandle(); for(i=0; i<pblock()->Count(kSplitBySource_sources); i++) { if (systemHandle == pblock()->GetInt(kSplitBySource_sources, 0, i)) { isSelectedSource = true; break; } } // test all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); if (exactStep) { if ((isSelectedSource && (conditionType == kSplitBySource_conditionType_selected)) || (!isSelectedSource && (conditionType == kSplitBySource_conditionType_notSelected))) { testResult.SetAll(); for(i=0; i<count; i++) testTime[i] = 0.0f; } } return true; }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestGoToNextEvent::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { int conditionType = pblock()->GetInt(kGoToNextEvent_conditionType, timeStart); bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle int count = chAmount->Count(); if (count <= 0) return true; testResult.SetSize(count); testTime.SetCount(count); if((conditionType == kGoToNextEvent_conditionType_all) && exactStep) { testResult.SetAll(); for(int i=0; i<count; i++) testTime[i] = 0.0f; } else { testResult.ClearAll(); } return true; }
IGeometryChecker::ReturnVal IsolatedVertexChecker::GeometryCheck(TimeValue t,INode *nodeToCheck, IGeometryChecker::OutputVal &val) { val.mIndex.ZeroCount(); if(IsSupported(nodeToCheck)) { LARGE_INTEGER ups,startTime; QueryPerformanceFrequency(&ups); QueryPerformanceCounter(&startTime); //used to see if we need to pop up a dialog bool compute = true; bool checkTime = GetIGeometryCheckerManager()->GetAutoUpdate();//only check time for the dialog if auto update is active! ObjectState os = nodeToCheck->EvalWorldState(t); Object *obj = os.obj; BitArray arrayOfVerts; //we fill this up with the verts, if not empty then we have isolated vets if(os.obj->IsSubClassOf(triObjectClassID)) { TriObject *tri = dynamic_cast<TriObject *>(os.obj); if(tri) { Mesh &mesh = tri->GetMesh(); arrayOfVerts.SetSize(mesh.numVerts); arrayOfVerts.SetAll (); for (int i=0; i<mesh.numFaces; i++) { for (int j=0; j<3; j++) arrayOfVerts.Clear(mesh.faces[i].v[j]); if(checkTime==true) { DialogChecker::Check(checkTime,compute,mesh.numFaces,startTime,ups); if(compute==false) break; } } } else return IGeometryChecker::eFail; } else if(os.obj->IsSubClassOf(polyObjectClassID)) { PolyObject *poly = dynamic_cast<PolyObject *>(os.obj); if(poly) { MNMesh &mnMesh = poly->GetMesh(); arrayOfVerts.SetSize(mnMesh.numv); arrayOfVerts.SetAll(); for(int i=0;i<mnMesh.numf;++i) { for(int j=0;j<mnMesh.f[i].deg;++j) { if(mnMesh.f[i].GetFlag(MN_DEAD)==0) arrayOfVerts.Clear(mnMesh.f[i].vtx[j]); } if(checkTime==true) { DialogChecker::Check(checkTime,compute,mnMesh.numf,startTime,ups); if(compute==false) break; } } } else return IGeometryChecker::eFail; } if(arrayOfVerts.IsEmpty()==false) //we have an isolated vierts { int localsize= arrayOfVerts.GetSize(); for(int i=0;i<localsize;++i) { if(arrayOfVerts[i]) val.mIndex.Append(1,&i); } } return TypeReturned(); } return IGeometryChecker::eFail; }
void SymmetryMod::ModifyTriObject (TimeValue t, ModContext &mc, TriObject *tobj, INode *inode) { Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; int axis, slice, weld, flip; float threshold; mp_pblock->GetValue (kSymAxis, t, axis, iv); mp_pblock->GetValue (kSymFlip, t, flip, iv); mp_pblock->GetValue (kSymSlice, t, slice, iv); mp_pblock->GetValue (kSymWeld, t, weld, iv); mp_pblock->GetValue (kSymThreshold, t, threshold, iv); if (threshold<0) threshold=0; // Get transform from mirror controller: Matrix3 tm = CompMatrix (t, NULL, &mc, &iv); Matrix3 itm = Inverse (tm); // Get DotProd(N,x)=offset plane definition from transform Point3 Axis(0,0,0); Axis[axis] = flip ? -1.0f : 1.0f; Point3 origin = tm.GetTrans(); Point3 N = Normalize(tm*Axis - origin); float offset = DotProd (N, origin); // Slice operation does not handle NormalSpecs, but it handles mapping channels. // move our mesh normal data to a map channel MeshNormalSpec *pNormals = mesh.GetSpecifiedNormals (); int normalMapChannel = INVALID_NORMALMAPCHANNEL; if (pNormals && pNormals->GetNumFaces()) { pNormals->SetParent(&mesh); //find an empty map channel for (int mp = 0; mp < mesh.getNumMaps(); mp++) { if (!mesh.mapSupport(mp)) { normalMapChannel = mp; mesh.setMapSupport(normalMapChannel,TRUE); MeshMap& map = mesh.Map(normalMapChannel); for (int i = 0; i < map.fnum; i++) { for (int j = 0; j < 3; j++) { unsigned int newID = pNormals->Face(i).GetNormalID(j); map.tf[i].t[j] = newID; } } map.setNumVerts(pNormals->GetNumNormals()); for (int i = 0; i < map.vnum; i++) { map.tv[i] = pNormals->Normal(i); } // make sure nothing is done with MeshNormalSpec (until data is copied back) pNormals->Clear(); break; } } } // Slice off everything below the plane. if (slice) SliceTriObject (mesh, N, offset); MirrorTriObject (mesh, axis, tm, itm,normalMapChannel); if (weld) WeldTriObject (mesh, N, offset, threshold); //now move the normals back if (pNormals && normalMapChannel != -1) { MeshMap& map = mesh.Map(normalMapChannel); pNormals->SetNumFaces(map.fnum); pNormals->SetNumNormals(map.vnum); pNormals->SetAllExplicit(true); BitArray temp; temp.SetSize(map.vnum); temp.SetAll(); pNormals->SpecifyNormals(TRUE,&temp); for (int i = 0; i < map.vnum; i++) { pNormals->GetNormalArray()[i] = map.tv[i]; pNormals->SetNormalExplicit(i,true); } for (int i = 0; i < map.fnum; i++) { for (int j = 0; j < 3; j++) { pNormals->SetNormalIndex(i,j,map.tf[i].t[j]); MeshNormalFace& face = pNormals->Face(i); face.SpecifyAll(true); } } pNormals->SetFlag(MESH_NORMAL_MODIFIER_SUPPORT); for (int i = 0; i < pNormals->GetNumFaces(); i++) { for (int j = 0; j < 3; j++) { int id = pNormals->GetNormalIndex(i,j); } } pNormals->CheckNormals(); pNormals->SetParent(NULL); // Free the map channel mesh.setMapSupport(normalMapChannel,FALSE); } tobj->UpdateValidity (GEOM_CHAN_NUM, iv); tobj->UpdateValidity (TOPO_CHAN_NUM, iv); tobj->UpdateValidity (VERT_COLOR_CHAN_NUM, iv); tobj->UpdateValidity (TEXMAP_CHAN_NUM, iv); tobj->UpdateValidity (SELECT_CHAN_NUM, iv); }
void UnwrapMod::fnFlattenMap(float angleThreshold, Tab<Point3*> *normalList, float spacing, BOOL normalize, int layoutType, BOOL rotateClusters, BOOL fillHoles) { for (int i = 0; i < mMeshTopoData.Count(); i++) { mMeshTopoData[i]->HoldSelection(); } BailStart(); if (preventFlattening) return; /* if (TVMaps.f.Count() == 0) return; BitArray *polySel = fnGetSelectedPolygons(); if (polySel == NULL) return; */ theHold.Begin(); HoldPointsAndFaces(); /* BitArray holdPolySel; holdPolySel.SetSize(polySel->GetSize()); holdPolySel = *polySel; */ 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]; } BOOL noSelection = TRUE; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { if (mMeshTopoData[ldID]->GetFaceSelection().NumberSet()) noSelection = FALSE; } if (noSelection) { for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { BitArray fsel = mMeshTopoData[ldID]->GetFaceSelection(); fsel.SetAll(); mMeshTopoData[ldID]->SetFaceSelection(fsel); } } TSTR statusMessage; MeshTopoData::GroupBy groupBy = MeshTopoData::kFaceAngle; int v = 0; pblock->GetValue(unwrap_flattenby,0,v,FOREVER); if (v == 0) groupBy = MeshTopoData::kFaceAngle; else if (v == 2) groupBy = MeshTopoData::kMaterialID; else if (v == 1) groupBy = MeshTopoData::kSmoothingGroup; BOOL bContinue = BuildCluster( mapNormal, angleThreshold, TRUE,TRUE,groupBy); /* BitArray sel; sel.SetSize(TVMaps.f.Count()); */ gBArea = 0.0f; int initialCluster = clusterList.Count(); if (bContinue) { for (int i =0; i < clusterList.Count(); i++) { MeshTopoData *ld = clusterList[i]->ld; ld->ClearSelection(TVFACEMODE);// sel.ClearAll(); 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; } } // if (0) if (bContinue) { for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) mMeshTopoData[ldID]->UpdateClusterVertices(clusterList); if (layoutType == 1) bContinue = LayoutClusters( spacing, rotateClusters, TRUE, fillHoles); else { if (flattenMax5) bContinue = LayoutClusters3( spacing, rotateClusters, fillHoles); else bContinue = LayoutClusters2( spacing, rotateClusters, fillHoles); } //normalize map to 0,0 to 1,1 if ((bContinue) && (normalize)) { NormalizeCluster(spacing); } } } CleanUpDeadVertices(); if (bContinue) { theHold.Accept(GetString(IDS_PW_FLATTEN)); theHold.Suspend(); fnSyncTVSelection(); theHold.Resume(); } else { theHold.Cancel(); // theHold.SuperCancel(); } for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { mMeshTopoData[ldID]->SetTVEdgeInvalid(); mMeshTopoData[ldID]->BuildTVEdges(); mMeshTopoData[ldID]->BuildVertexClusterList(); } theHold.Suspend(); fnSyncTVSelection(); fnSyncGeomSelection(); theHold.Resume(); for (int i = 0; i < mMeshTopoData.Count(); i++) { mMeshTopoData[i]->RestoreSelection(); } NotifyDependents(FOREVER,PART_SELECT,REFMSG_CHANGE); InvalidateView(); #ifdef DEBUGMODE if (gDebugLevel >= 1) { int finalCluster = clusterList.Count(); gEdgeHeight = 0.0f; gEdgeWidth = 0.0f; for (int i =0; i < clusterList.Count(); i++) { gEdgeHeight += clusterList[i]->h; gEdgeWidth += clusterList[i]->w; } ScriptPrint(_T("Surface Area %f bounds area %f per used %f\n"),gSArea,gBArea,gSArea/gBArea); ScriptPrint(_T("Edge Height %f Edge Width %f\n"),gEdgeHeight,gEdgeWidth); ScriptPrint(_T("Initial Clusters %d finalClusters %d\n"),initialCluster,finalCluster); } #endif FreeClusterList(); statusMessage.printf(_T("Done, area coverage %3.2f"),(gSArea/gBArea)*100.f); Bail(ip,statusMessage,0); }
void MirrorMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { Matrix3 itm = CompMatrix(t,NULL,&mc); Matrix3 tm = Inverse(itm); Interval iv = FOREVER; int axis, copy; float offset; pblock->GetValue(PB_AXIS,t,axis,iv); pblock->GetValue(PB_COPY,t,copy,iv); pblock->GetValue(PB_OFFSET,t,offset,iv); DWORD oldLevel; BOOL convertedShape = FALSE; BitArray oldFaceSelections; // support for TriObjects if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; Mesh &mesh = tobj->GetMesh(); switch (mesh.selLevel) { case MESH_OBJECT: mesh.faceSel.SetAll(); break; case MESH_VERTEX: { for (int i=0; i<mesh.getNumFaces(); i++) { for (int j=0; j<3; j++) { if (mesh.vertSel[mesh.faces[i].v[j]]) { mesh.faceSel.Set(i); } } } break; } case MESH_EDGE: { for (int i=0; i<mesh.getNumFaces(); i++) { for (int j=0; j<3; j++) { if (mesh.edgeSel[i*3+j]) { mesh.faceSel.Set(i); } } } break; } } oldLevel = mesh.selLevel; mesh.selLevel = MESH_FACE; if (copy) { mesh.CloneFaces(mesh.faceSel); mesh.ClearVSelectionWeights (); } if (axis<3) { for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) mesh.FlipNormal(i); } } } #ifndef NO_PATCHES // support for PatchObjects if (os->obj->IsSubClassOf(patchObjectClassID)) { PatchObject *pobj = (PatchObject*)os->obj; PatchMesh &pmesh = pobj->GetPatchMesh(t); switch (pmesh.selLevel) { case PATCH_OBJECT: pmesh.patchSel.SetAll(); break; case PATCH_VERTEX: { for (int i=0; i<pmesh.getNumPatches(); i++) { Patch &p = pmesh.patches[i]; for (int j=0; j<p.type; j++) { if (pmesh.vertSel[p.v[j]]) { pmesh.patchSel.Set(i); break; } } } break; } case PATCH_EDGE: { for (int i=0; i<pmesh.getNumPatches(); i++) { Patch &p = pmesh.patches[i]; for (int j=0; j<p.type; j++) { if (pmesh.edgeSel[p.edge[j]]) { pmesh.patchSel.Set(i); break; } } } break; } } oldLevel = pmesh.selLevel; pmesh.selLevel = PATCH_PATCH; if (copy) pmesh.ClonePatchParts(); // Copy the selected patches if (axis<3) pmesh.FlipPatchNormal(-1); // Flip selected normals } #endif // NO_PATCHES // support for PolyObjects else if (os->obj->IsSubClassOf(polyObjectClassID)) { PolyObject * pPolyOb = (PolyObject*)os->obj; MNMesh &mesh = pPolyOb->GetMesh(); // Luna task 747 // We don't support specified normals here because it would take special code mesh.ClearSpecifiedNormals (); BitArray faceSelections; mesh.getFaceSel (faceSelections); switch (mesh.selLevel) { case MNM_SL_OBJECT: faceSelections.SetAll(); break; case MNM_SL_VERTEX: { faceSelections.ClearAll (); for (int i=0; i<mesh.FNum(); i++) { for (int j=0; j<mesh.F(i)->deg; j++) { int vertIndex = mesh.F(i)->vtx[j]; if (mesh.V(vertIndex)->GetFlag(MN_SEL)) { faceSelections.Set(i); break; } } } break; } case MNM_SL_EDGE: { faceSelections.ClearAll (); for (int i=0; i<mesh.FNum(); i++) { for (int j=0; j<mesh.F(i)->deg; j++) { int edgeIndex = mesh.F(i)->edg[j]; if (mesh.E(edgeIndex)->GetFlag(MN_SEL)) { faceSelections.Set(i); break; } } } break; } } // preserve the existing selection settings oldLevel = mesh.selLevel; mesh.getFaceSel (oldFaceSelections); // set the face selections mesh.ClearFFlags (MN_SEL); mesh.FaceSelect(faceSelections); mesh.selLevel = MNM_SL_FACE; // copy the selected faces and flip Normal direction as needed if (copy) { mesh.CloneFaces(); mesh.freeVSelectionWeights (); } // Now, note that by PolyMesh rules, we can only flip entire selected elements. // So we broaden our selection to include entire elements that are only partially selected: for (int i=0; i<mesh.numf; i++) { if (mesh.f[i].GetFlag (MN_DEAD)) continue; if (!mesh.f[i].GetFlag (MN_SEL)) continue; mesh.PaintFaceFlag (i, MN_SEL); } if (axis<3) { for (i=0; i<mesh.FNum(); i++) { if (mesh.F(i)->GetFlag(MN_SEL)) mesh.FlipNormal(i); } if (mesh.GetFlag (MN_MESH_FILLED_IN)) { // We also need to flip edge normals: for (i=0; i<mesh.ENum(); i++) { if (mesh.f[mesh.e[i].f1].GetFlag (MN_SEL)) { int hold = mesh.e[i].v1; mesh.e[i].v1 = mesh.e[i].v2; mesh.e[i].v2 = hold; } } } } } // support for shape objects else if (os->obj->IsSubClassOf(splineShapeClassID)) { SplineShape *ss = (SplineShape*)os->obj; BezierShape &shape = ss->shape; oldLevel = shape.selLevel; switch (shape.selLevel) { case SHAPE_OBJECT: case SHAPE_VERTEX: shape.selLevel = SHAPE_SPLINE; shape.polySel.SetAll(); break; case SHAPE_SPLINE: case SHAPE_SEGMENT: break; } if (copy) shape.CloneSelectedParts((axis < 3 && splineMethod == SPLINE_REVERSE) ? TRUE : FALSE); } else if(os->obj->SuperClassID() == SHAPE_CLASS_ID) { ShapeObject *so = (ShapeObject *)os->obj; if(so->CanMakeBezier()) { SplineShape *ss = new SplineShape(); so->MakeBezier(t, ss->shape); ss->SetChannelValidity(GEOM_CHAN_NUM, GetValidity(t) & so->ObjectValidity(t)); os->obj = ss; os->obj->UnlockObject(); convertedShape = TRUE; BezierShape &shape = ss->shape; oldLevel = shape.selLevel; switch (shape.selLevel) { case SHAPE_OBJECT: case SHAPE_VERTEX: shape.selLevel = SHAPE_SPLINE; shape.polySel.SetAll(); break; case SHAPE_SPLINE: case SHAPE_SEGMENT: break; } if (copy) shape.CloneSelectedParts((axis < 3 && splineMethod == SPLINE_REVERSE) ? TRUE : FALSE); } } MirrorDeformer deformer(axis,offset,tm,itm); os->obj->Deform(&deformer, TRUE); // if (axis < 3 && splineMethod == SPLINE_REVERSE) { if (os->obj->IsSubClassOf(splineShapeClassID)) { SplineShape *ss = (SplineShape*)os->obj; BezierShape &shape = ss->shape; for (int i = 0; i < shape.bindList.Count(); i++) { int index = 0; int spindex = shape.bindList[i].pointSplineIndex; // Point3 p=shape.splines[spindex]->GetKnot(index).Knot(); if (shape.bindList[i].isEnd) index = shape.splines[spindex]->KnotCount()-1; shape.bindList[i].bindPoint = shape.splines[spindex]->GetKnotPoint(index); shape.bindList[i].segPoint = shape.splines[spindex]->GetKnotPoint(index); } shape.UpdateBindList(TRUE); } else if(os->obj->SuperClassID() == SHAPE_CLASS_ID) { ShapeObject *so = (ShapeObject *)os->obj; if(so->CanMakeBezier()) { SplineShape *ss = new SplineShape(); so->MakeBezier(t, ss->shape); ss->SetChannelValidity(GEOM_CHAN_NUM, GetValidity(t) & so->ObjectValidity(t)); os->obj = ss; os->obj->UnlockObject(); convertedShape = TRUE; BezierShape &shape = ss->shape; for (int i = 0; i < shape.bindList.Count(); i++) { int index = 0; int spindex = shape.bindList[i].pointSplineIndex; // Point3 p; if (shape.bindList[i].isEnd) index = shape.splines[spindex]->KnotCount()-1; shape.bindList[i].bindPoint = shape.splines[spindex]->GetKnotPoint(index); shape.bindList[i].segPoint = shape.splines[spindex]->GetKnotPoint(index); } shape.UpdateBindList(TRUE); } } } os->obj->UpdateValidity(GEOM_CHAN_NUM,GetValidity(t)); // restore the original selections if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; tobj->GetMesh().selLevel = oldLevel; } #ifndef NO_PATCHES else if (os->obj->IsSubClassOf(patchObjectClassID)) { PatchObject *pobj = (PatchObject*)os->obj; pobj->GetPatchMesh(t).selLevel = oldLevel; } #endif // NO_PATCHES else if (os->obj->IsSubClassOf(polyObjectClassID)) { PolyObject *pPolyOb = (PolyObject*)os->obj; pPolyOb->GetMesh().selLevel = oldLevel; pPolyOb->GetMesh().dispFlags = 0; switch (oldLevel) { case MNM_SL_VERTEX: pPolyOb->GetMesh().dispFlags = MNDISP_SELVERTS | MNDISP_VERTTICKS; break; case MNM_SL_EDGE: pPolyOb->GetMesh().dispFlags = MNDISP_SELEDGES; break; case MNM_SL_FACE: pPolyOb->GetMesh().dispFlags = MNDISP_SELFACES; break; } pPolyOb->GetMesh().FaceSelect(oldFaceSelections); } else if(os->obj->IsSubClassOf(splineShapeClassID) || convertedShape) { SplineShape *ss = (SplineShape*)os->obj; ss->shape.selLevel = oldLevel; } }
void MeshTopoData::DetachFromGeoFaces(BitArray faceSel, BitArray &vertSel, UnwrapMod *mod) { TimeValue t = GetCOREInterface()->GetTime(); //loop through the geo vertices and create our geo list of all verts in the Tab<int> geoPoints; BitArray usedGeoPoints; usedGeoPoints.SetSize(TVMaps.geomPoints.Count()); usedGeoPoints.ClearAll(); BitArray isolatedPoints; isolatedPoints.SetSize(TVMaps.v.Count()); isolatedPoints.SetAll(); for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { if (faceSel[i]) { int degree = TVMaps.f[i]->count; for (int j = 0; j < degree; j++) { int index = TVMaps.f[i]->v[j]; if (!usedGeoPoints[index]) { usedGeoPoints.Set(index); geoPoints.Append(1,&index,3000); } if (TVMaps.f[i]->vecs) { int index = TVMaps.f[i]->vecs->vhandles[j*2]; if (index != -1) { if (!usedGeoPoints[index]) { usedGeoPoints.Set(index); geoPoints.Append(1,&index,3000); } } index = TVMaps.f[i]->vecs->vhandles[j*2+1]; if (index != -1) { if (!usedGeoPoints[index]) { usedGeoPoints.Set(index); geoPoints.Append(1,&index,3000); } } index = TVMaps.f[i]->vecs->vinteriors[j]; if (index != -1) { if (!usedGeoPoints[index]) { usedGeoPoints.Set(index); geoPoints.Append(1,&index,3000); } } } } } else { int degree = TVMaps.f[i]->count; for (int j = 0; j < degree; j++) { int index = TVMaps.f[i]->t[j]; isolatedPoints.Clear(index); if (TVMaps.f[i]->vecs) { int index = TVMaps.f[i]->vecs->handles[j*2]; if (index != -1) { isolatedPoints.Clear(index); } index = TVMaps.f[i]->vecs->handles[j*2+1]; if (index != -1) { isolatedPoints.Clear(index); } index = TVMaps.f[i]->vecs->interiors[j]; if (index != -1) { isolatedPoints.Clear(index); } } } } } } for (int i = 0; i < TVMaps.v.Count(); i++) { if (isolatedPoints[i]) SetTVVertDead(i,TRUE); } //get our dead verts Tab<int> deadVerts; for (int i = 0; i < TVMaps.v.Count(); i++) { if (TVMaps.v[i].IsDead() && !TVMaps.mSystemLockedFlag[i]) { deadVerts.Append(1,&i,1000); } } //build the look up list Tab<int> lookupList; lookupList.SetCount(TVMaps.geomPoints.Count()); for (int i = 0; i < TVMaps.geomPoints.Count(); i++) lookupList[i] = -1; int deadIndex = 0; for (int i = 0; i < geoPoints.Count(); i++) { int vIndex = geoPoints[i]; Point3 p = TVMaps.geomPoints[vIndex]; if (deadIndex < deadVerts.Count()) { lookupList[vIndex] = deadVerts[deadIndex]; SetTVVertControlIndex(deadVerts[deadIndex],-1); SetTVVert(t,deadVerts[deadIndex],p,mod);//TVMaps.v[found].p = p; SetTVVertInfluence(deadVerts[deadIndex],0.0f);//TVMaps.v[found].influence = 0.0f; SetTVVertDead(deadVerts[deadIndex],FALSE);//TVMaps.v[found].flags -= FLAG_DEAD; deadIndex++; } else { lookupList[vIndex] = TVMaps.v.Count(); UVW_TVVertClass tv; tv.SetP(p); tv.SetFlag(0); tv.SetInfluence(0.0f); tv.SetControlID(-1); TVMaps.v.Append(1,&tv,1); mVSel.SetSize(TVMaps.v.Count(), 1); TVMaps.mSystemLockedFlag.SetSize(TVMaps.v.Count(), 1); } } vertSel.SetSize(TVMaps.v.Count()); vertSel.ClearAll(); for (int i = 0; i < TVMaps.f.Count(); i++) { if ((faceSel[i]) && (!(TVMaps.f[i]->flags & FLAG_DEAD))) { int degree = TVMaps.f[i]->count; for (int j = 0; j < degree; j++) { int index = TVMaps.f[i]->v[j]; TVMaps.f[i]->t[j] = lookupList[index]; vertSel.Set(lookupList[index],TRUE); if (TVMaps.f[i]->vecs) { int index = TVMaps.f[i]->vecs->vhandles[j*2]; if ((index != -1) && (lookupList[index] != -1)) { TVMaps.f[i]->vecs->handles[j*2] = lookupList[index]; vertSel.Set(lookupList[index],TRUE); } index = TVMaps.f[i]->vecs->vhandles[j*2+1]; if ((index != -1) && (lookupList[index] != -1)) { TVMaps.f[i]->vecs->handles[j*2+1] = lookupList[index]; vertSel.Set(lookupList[index],TRUE); } index = TVMaps.f[i]->vecs->vinteriors[j]; if ((index != -1) && (lookupList[index] != -1)) { TVMaps.f[i]->vecs->interiors[j] = lookupList[index]; vertSel.Set(lookupList[index],TRUE); } } } } } }