void OverlapMap::Hit(UVWChannel &uvMesh,int mapIndex, int faceIndex,BitArray &selection) { BOOL hit = TRUE; if (mBuffer[mapIndex].mFaceID == -1) hit = FALSE; //if nothing in this cell just add it if (!hit) { mBuffer[mapIndex].mFaceID = faceIndex; } else { //have somethign in the cell need to check //get the ld and face id in the cell int baseFaceIndex = mBuffer[mapIndex].mFaceID; //hit on the same mesh id cannot be the same if ((baseFaceIndex != faceIndex)) { selection.Set(faceIndex); selection.Set(baseFaceIndex); } //hit on different mesh dont care about the face ids } }
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 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 UnwrapMod::BuildUsedList(BitArray &usedVerts, ClusterClass *cluster) { usedVerts.SetSize(TVMaps.v.Count()); usedVerts.ClearAll(); for (int j =0; j < cluster->faces.Count(); j++) { int faceIndex = cluster->faces[j]; for (int k = 0; k < TVMaps.f[faceIndex]->count; k++) { //need to put patch handles in here also int index = TVMaps.f[faceIndex]->t[k]; usedVerts.Set(index); if ((TVMaps.f[faceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[faceIndex]->vecs)) { index = TVMaps.f[faceIndex]->vecs->handles[k*2]; if ((index >= 0) && (index < usedVerts.GetSize())) usedVerts.Set(index); index = TVMaps.f[faceIndex]->vecs->handles[k*2+1]; if ((index >= 0) && (index < usedVerts.GetSize())) usedVerts.Set(index); if (TVMaps.f[faceIndex]->flags & FLAG_INTERIOR) { index = TVMaps.f[faceIndex]->vecs->interiors[k]; if ((index >= 0) && (index < usedVerts.GetSize())) usedVerts.Set(index); } } } } }
void MeshTopoData::AddVertsToCluster(int faceIndex, BitArray &processedVerts, ClusterClass *cluster) { int degree = TVMaps.f[faceIndex]->count; for (int k = 0; k < degree; k++) { int index = TVMaps.f[faceIndex]->t[k]; if (!processedVerts[index]) { cluster->verts.Append(1,&index,100); processedVerts.Set(index,TRUE); } if (TVMaps.f[faceIndex]->vecs) { int index = TVMaps.f[faceIndex]->vecs->handles[k*2]; if (!processedVerts[index]) { cluster->verts.Append(1,&index,100); processedVerts.Set(index,TRUE); } index = TVMaps.f[faceIndex]->vecs->handles[k*2+1]; if (!processedVerts[index]) { cluster->verts.Append(1,&index,100); processedVerts.Set(index,TRUE); } index = TVMaps.f[faceIndex]->vecs->interiors[k]; if (!processedVerts[index]) { cluster->verts.Append(1,&index,100); processedVerts.Set(index,TRUE); } } } }
void EditPolyData::GrowSelection (IMeshSelect *imod, int level) { DbgAssert (mpMesh); if( !mpMesh ) return; BitArray newSel; int mnSelLevel = meshSelLevel[level]; DbgAssert (mpMesh->GetFlag (MN_MESH_FILLED_IN)); if (!mpMesh->GetFlag (MN_MESH_FILLED_IN)) return; SynchBitArrays(); int i; switch (mnSelLevel) { case MNM_SL_VERTEX: for (i=0; i<mpMesh->numv; i++) mpMesh->v[i].SetFlag (MN_USER, mVertSel[i]!=0); mpMesh->ClearEFlags (MN_USER); mpMesh->PropegateComponentFlags (MNM_SL_EDGE, MN_USER, MNM_SL_VERTEX, MN_USER); newSel.SetSize (mpMesh->numv); for (i=0; i<mpMesh->nume; i++) { if (mpMesh->e[i].GetFlag (MN_USER)) { newSel.Set (mpMesh->e[i].v1); newSel.Set (mpMesh->e[i].v2); } } SetVertSel (newSel, imod, TimeValue(0)); break; case MNM_SL_EDGE: for (i=0; i<mpMesh->nume; i++) mpMesh->e[i].SetFlag (MN_USER, mEdgeSel[i]!=0); mpMesh->ClearVFlags (MN_USER); mpMesh->PropegateComponentFlags (MNM_SL_VERTEX, MN_USER, MNM_SL_EDGE, MN_USER); newSel.SetSize (mpMesh->nume); for (i=0; i<mpMesh->nume; i++) { if (mpMesh->v[mpMesh->e[i].v1].GetFlag (MN_USER) || mpMesh->v[mpMesh->e[i].v2].GetFlag (MN_USER)) newSel.Set (i); } SetEdgeSel (newSel, imod, TimeValue(0)); break; case MNM_SL_FACE: for (i=0; i<mpMesh->numf; i++) mpMesh->f[i].SetFlag (MN_USER, mFaceSel[i]!=0); mpMesh->ClearVFlags (MN_USER); mpMesh->PropegateComponentFlags (MNM_SL_VERTEX, MN_USER, MNM_SL_FACE, MN_USER); newSel.SetSize (mpMesh->numf); for (i=0; i<mpMesh->numf; i++) { int j; for (j=0; j<mpMesh->f[i].deg; j++) { if (mpMesh->v[mpMesh->f[i].vtx[j]].GetFlag (MN_USER)) break; } if (j<mpMesh->f[i].deg) newSel.Set (i); } SetFaceSel (newSel, imod, TimeValue(0)); break; } }
void EditFaceDataModData::SetFaceValue (BitArray & faces, float val) { for (int i=0; i<faces.GetSize(); i++) { if (!faces[i]) continue; mFacesAffected.Set (i); mtNewFaceValues[i] = val; } }
void XTCSample::DeleteFaces(TimeValue t,Object *obj) { if(bNF_OnOff) { Mesh *mesh = GetMesh(obj); if(!mesh) return; Interval ivalid = FOREVER; int nf; bo->GetParamBlockByID(x_params)->GetValue(pb_nf_spin,t,nf, ivalid); BitArray ba; ba.SetSize(mesh->getNumFaces()); ba.ClearAll(); for(int i = nf ; i < mesh->getNumFaces() ; i++ ) { ba.Set(i); } if(!ba.IsEmpty()) mesh->DeleteFaceSet(ba); } }
void MNMesh_selectVertexLoops(MNMesh *mesh, int startid, BitArray &vertexloops) { BitArray secondarysel(mesh->ENum()); BitArray connectededges(mesh->ENum()); vertexloops.SetSize(mesh->VNum()); mesh->getEdgeSel(secondarysel); // convert to Edge Tab<int> &connected = mesh->vedg[startid]; for (int e=0; e < connected.Count(); e++){ connectededges.Set(connected[e]); } // loop edges mesh->SelectEdgeLoop(connectededges); // convert back to vertex MNEdge *edge = mesh->e; MNEdge *lastedge = edge+mesh->ENum(); int eid = 0; while (edge < lastedge){ if (connectededges[eid]){ vertexloops.Set(edge->v1); vertexloops.Set(edge->v2); } edge++; eid++; } // select those vertices mesh->VertexSelect(vertexloops); // restore old edges mesh->EdgeSelect(secondarysel); }
void UVW_ChannelClass::MarkDeadVertices() { BitArray usedVerts; usedVerts.SetSize(v.Count()); usedVerts.ClearAll(); for (int i =0; i < f.Count(); i++) { if (!(f[i]->flags & FLAG_DEAD)) { for (int j=0; j < f[i]->count; j++) { int id = f[i]->t[j]; if (id < usedVerts.GetSize()) usedVerts.Set(id); if ((f[i]->flags & FLAG_CURVEDMAPPING) && (f[i]->vecs)) { id = f[i]->vecs->handles[j*2]; if (id < usedVerts.GetSize()) usedVerts.Set(id); id = f[i]->vecs->handles[j*2+1]; if (id < usedVerts.GetSize()) usedVerts.Set(id); if (f[i]->flags & FLAG_INTERIOR) { id = f[i]->vecs->interiors[j]; if (id < usedVerts.GetSize()) usedVerts.Set(id); } } } } } for (int i =0; i < v.Count(); i++) { if (i < usedVerts.GetSize()) { BOOL isRigPoint = v[i].GetFlag() & FLAG_RIGPOINT; if (!usedVerts[i] && (!isRigPoint)) { v[i].SetDead(); } } } }
void Add (int ind) { if (!flags.Test(ind)) { set.Append (ind); flags.Set (ind); } }
void GetWorkingArea(BitArray & working_elements, BitArray & working_points, const Mesh & mesh, const Array<ElementIndex> & bad_elements, const int width) { working_elements.Clear(); working_points.Clear(); for(int i=0; i<bad_elements.Size(); i++) { working_elements.Set(bad_elements[i]); const Element & el = mesh[bad_elements[i]]; for(int j=1; j<=el.GetNP(); j++) working_points.Set(el.PNum(j)); } for(int i=0; i<width; i++) { for(ElementIndex j=0; j<mesh.GetNE(); j++) { if(!working_elements.Test(j)) { const Element & el = mesh[j]; bool set_active = false; for(int k=1; !set_active && k<=el.GetNP(); k++) set_active = working_points.Test(el.PNum(k)); if(set_active) working_elements.Set(j); } } for(ElementIndex j=0; j<mesh.GetNE(); j++) { if(working_elements.Test(j)) { const Element & el = mesh[j]; for(int k=1; k<=el.GetNP(); k++) working_points.Set(el.PNum(k)); } } } }
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 UniformGrid::ClosestPoint(Point3 p, float radius, int &pindex, float &d) { xHitList.ClearAll(); yHitList.ClearAll(); zHitList.ClearAll(); hitList.SetCount(0); //find the cell in the XGrid TagCells(p,radius, 0); //find the cell in the YGrid TagCells(p,radius, 1); //find the cell in the ZGrid TagCells(p,radius, 2); BitArray usedList; usedList.SetSize(pointBase.Count()); usedList.ClearAll(); int closest = -1; d = 0.0f; Box3 localBounds; localBounds.Init(); localBounds += p; localBounds.EnlargeBy(radius); for (int i = 0; i < hitList.Count(); i++) { int index = hitList[i]; if (!usedList[index]) //check to see if we have processed this one or not { if (xHitList[index] && yHitList[index] && zHitList[index]) { usedList.Set(index); Point3 source = pointBase[index]; if (localBounds.Contains(source)) { float dist = LengthSquared(source-p); if ((dist < d) || (closest == -1)) { d = dist; closest = index; } } } } } pindex = closest; d = sqrt(d); }
BlurMgr::BlurMgr() : pbMaster(NULL), pbBlurData(NULL), pbSelData(NULL), mp_CCtl(NULL), m_lastBMModifyID(0xFFFFFFFF), m_imageW(0), m_imageH(0), m_imageSz(0), m_compValid(false) // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- { m_blurs[idBlurUnif] = new BlurUniform(this); m_blurs[idBlurDir] = new BlurDirectional(this); m_blurs[idBlurRadial] = new BlurRadial(this); m_sels[idSelImage] = new SelImage(this); m_sels[idSelIBack] = new SelIgnBack(this); m_sels[idSelLum] = new SelLum(this); m_sels[idSelMask] = new SelMaps(this); m_sels[idSelObjIds] = new SelObjIds(this); m_sels[idSelMatIds] = new SelMatIds(this); // this added to allow extension of seltypes -- adding new param active ids breaks the original sequential enumeration // i should have enumerated the param ids sparsely to allow for extensibility. // if they are added sequentially, it changes the value of old param ids and will break loading of old versions m_selActiveIds[idSelImage] = prmImageActive; m_selActiveIds[idSelIBack] = prmIBackActive; m_selActiveIds[idSelLum] = prmLumActive; m_selActiveIds[idSelMask] = prmMaskActive; m_selActiveIds[idSelObjIds] = prmObjIdsActive; m_selActiveIds[idSelMatIds] = prmMatIdsActive; // set default blur radial origin to coincide with current render settings pbdBlurData.ParamOption(prmRadialXOrig, p_default, GetCOREInterface()->GetRendWidth()/2); pbdBlurData.ParamOption(prmRadialYOrig, p_default, GetCOREInterface()->GetRendHeight()/2); blurMgrCD.MakeAutoParamBlocks(this); assert( pbMaster && pbBlurData && pbSelData); // create a curve control and reference it ICurveCtl *pICurveCtl = (ICurveCtl*)CreateInstance(REF_MAKER_CLASS_ID, CURVE_CONTROL_CLASS_ID); assert (pICurveCtl); ReplaceReference(idSelCurveCtrl, pICurveCtl); pICurveCtl->RegisterResourceMaker(this); pICurveCtl->SetCCFlags(CC_DRAWUTOOLBAR | CC_CONSTRAIN_Y | CC_SHOWRESET/*| CC_RCMENU_MOVE_XY | CC_RCMENU_MOVE_X | CC_RCMENU_MOVE_Y | CC_RCMENU_SCALE | CC_RCMENU_INSERT_CORNER | CC_RCMENU_INSERT_BEZIER | CC_RCMENU_DELETE*/); pICurveCtl->SetXRange(0.0f,1.0f); pICurveCtl->SetYRange(0.0f,1.0f); BitArray ba; ba.SetSize(32); ba.Set(0); ba.Clear(1); pICurveCtl->SetDisplayMode(ba); pICurveCtl->SetNumCurves(2); pICurveCtl->SetScrollValues(2, -44); pICurveCtl->SetZoomValues(133, 117); }
void MNMeshLoop::Build(MNMeshLoopAdvancer &adv, int startid, BitArray &finalsel) { // prepare Loopitems m_items.SetCount(MESHLOOP_ALLOC_ITEMCOUNT); int allocated = MESHLOOP_ALLOC_ITEMCOUNT; // add ourself int itemcnt = 0; int wave = 1; MNMeshLoopItem *item = m_items.Addr(0); item->wave = 0; item->distance = 0.0f; item->id = startid; item->pos = adv.GetPos(startid); item->prev = NULL; finalsel.Set(startid); item++; itemcnt++; Tab<MNMeshLoopFront> fronts; int outcount = adv.SetupFront(startid,fronts); // then advance each direction int added = TRUE; while(added){ added = FALSE; for (int o = 0; o < outcount; o++){ MNMeshLoopFront *front = fronts.Addr(o); // loop ended if (adv.Advance(front,item,itemcnt,wave,finalsel)) continue; item++; itemcnt++; // expand memory (we could use append but well no clue how it resizes) if (itemcnt%MESHLOOP_ALLOC_ITEMCOUNT == 0){ m_items.SetCount(itemcnt+MESHLOOP_ALLOC_ITEMCOUNT); item = m_items.Addr(itemcnt); } added = TRUE; } wave += 1; } m_numitems = itemcnt; }
void MNMesh_selectEdgeRingsAndLoops(MNMesh *mesh, int startid, BitArray &outsel) { BitArray loopsel(mesh->ENum()); outsel.SetSize(mesh->ENum()); // ring outsel.Set(startid); mesh->SelectEdgeRing(outsel); // loop loopsel.Set(startid); mesh->SelectEdgeRing(loopsel); // combine both and set selection outsel |= loopsel; }
void SymmetryMod::WeldTriObject (Mesh & mesh, Point3 & N, float offset, float threshold) { // Find vertices in target zone of mirror plane: BitArray targetVerts; targetVerts.SetSize (mesh.numVerts, true); targetVerts.ClearAll (); for (int i=0; i<mesh.numVerts; i++) { float dist = DotProd (N, mesh.verts[i]) - offset; if (fabsf(dist) > threshold) continue; targetVerts.Set (i); } // Weld the suitable border vertices: MeshDelta tmd(mesh); BOOL found = tmd.WeldByThreshold (mesh, targetVerts, threshold); tmd.Apply (mesh); }
void UniformGrid::InRadius(Point3 p, Tab<int> &indexList) { float radius = largestRadius; xHitList.ClearAll(); yHitList.ClearAll(); zHitList.ClearAll(); hitList.SetCount(0); //find the cell in the XGrid TagCells(p,radius, 0); //find the cell in the YGrid TagCells(p,radius, 1); //find the cell in the ZGrid TagCells(p,radius, 2); BitArray usedList; usedList.SetSize(pointBase.Count()); usedList.ClearAll(); int closest = -1; float d = 0.0f; Box3 localBounds; localBounds.Init(); localBounds += p; localBounds.EnlargeBy(radius); for (int i = 0; i < hitList.Count(); i++) { int index = hitList[i]; if (!usedList[index]) //check to see if we have processed this one or not { if (xHitList[index] && yHitList[index] && zHitList[index]) { usedList.Set(index); Point3 source = pointBase[index]; if (localBounds.Contains(source)) { indexList.Append(1,&index,1000); } } } } }
void EditPolyData::SelectByMaterial (EditPolyMod *pMod) { if (pMod->GetMNSelLevel() != MNM_SL_FACE) return; if (!mpMesh) return; int clear = pMod->getParamBlock()->GetInt (epm_material_selby_clear); int matInt = pMod->getParamBlock()->GetInt (epm_material_selby); MtlID matID = (MtlID) matInt; SetupNewSelection (MNM_SL_FACE); BitArray *pSel = GetNewSelection (); for (int i=0; i<pSel->GetSize(); i++) { if (mpMesh->f[i].material == matID) pSel->Set(i); } ApplyNewSelection (pMod, !clear); }
void EditPolyData::SelectBySmoothingGroup (EditPolyMod *pMod) { if (pMod->GetMNSelLevel() != MNM_SL_FACE) return; if (!mpMesh) return; int clear = pMod->getParamBlock()->GetInt (epm_smoother_selby_clear); int smgInt = pMod->getParamBlock()->GetInt (epm_smoother_selby); DWORD *smg = (DWORD *) ((void *)&smgInt); SetupNewSelection (MNM_SL_FACE); BitArray *pSel = GetNewSelection (); for (int i=0; i<pSel->GetSize(); i++) { if (mpMesh->f[i].smGroup & (*smg)) pSel->Set(i); } ApplyNewSelection (pMod, !clear); }
// Since vertices might have different normals depending on the face // you are accessing it through, we get the normal for each face that // connects to this vertex and interpolate these normals to get a single // vertex normal fairly perpendicular to the mesh at the point of // this vertex. Point3 interpVertexNormal(Mesh* mesh, Matrix3 tm, unsigned int vxNo, BitArray& faceList) { Point3 iNormal = Point3(0.0f, 0.0f, 0.0f); int numNormals = 0; for (int f = 0; f < mesh->numFaces; f++) { for (int fi = 0; fi < 3; fi++) { if (mesh->faces[f].v[fi] == vxNo) { Point3& fn = VectorTransform(tm, mesh->getFaceNormal(f)); iNormal += fn; numNormals++; faceList.Set(f); } } } iNormal = iNormal / (float)numNormals; return Normalize(iNormal); }
void EditFaceDataMod::SelectSubComponent (HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert) { EditFaceDataModData *d = NULL, *od = NULL; ModContextList mcList; INodeTab nodes; ip->GetModContexts(mcList,nodes); BitArray nsel; for (int nd=0; nd<mcList.Count(); nd++) { d = (EditFaceDataModData*) mcList[nd]->localData; if (d==NULL) continue; HitRecord *hr = hitRec; if (!all && (hr->modContext->localData != d)) continue; for (; hr!=NULL; hr=hr->Next()) if (hr->modContext->localData == d) break; if (hr==NULL) continue; Mesh *mesh = d->GetCacheMesh(); MNMesh *mnmesh = d->GetCacheMNMesh(); if (!mesh && !mnmesh) continue; if (theHold.Holding() && !d->GetHeld()) theHold.Put (new SelectRestore (this, d)); switch (selLevel) { case SEL_FACE: nsel = d->GetFaceSel(); for (; hr != NULL; hr=hr->Next()) { if (d != hr->modContext->localData) continue; nsel.Set (hr->hitInfo, invert ? !d->GetFaceSel()[hr->hitInfo] : selected); if (!all) break; } d->GetFaceSel() = nsel; break; } } nodes.DisposeTemporary (); SelectionChanged (); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSplitSelected::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); int conditionType = pblock()->GetInt(kSplitSelected_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(); IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelBoolR* chSelect = GetParticleChannelSelectionRInterface(pCont); // test all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); for(int i=0; i<count; i++) { bool selected = (chSelect != NULL) ? chSelect->GetValue(i) : false; bool sendOut = ((selected && (conditionType == kSplitSelected_conditionType_selected)) || (!selected && (conditionType == kSplitSelected_conditionType_notSelected))); if (sendOut && exactStep) { testResult.Set(i); testTime[i] = 0.0f; } } return true; }
void SymmetryMod::SliceTriObject (Mesh & mesh, Point3 & N, float offset) { // Steve Anderson 9/14/2002 // Using the new "MESH_TEMP_1" flag to override Slice selection behavior, // which is undesirable here. mesh.SetFlag (MESH_TEMP_1); MeshDelta slicemd; slicemd.Slice (mesh, N, offset, false, true); slicemd.Apply (mesh); mesh.ClearFlag (MESH_TEMP_1); // We need to strip out faces on the mirror plane itself. // (These aren't always removed by slice.) // Mark vertices at the plane boundary: BitArray targetVerts; targetVerts.SetSize (mesh.numVerts); targetVerts.ClearAll (); for (int i=0; i<mesh.numVerts; i++) { float dist = DotProd (N, mesh.verts[i]) - offset; if (fabsf(dist) > MNEPS) continue; targetVerts.Set (i); } BitArray delFaces, delVerts; delFaces.SetSize (mesh.numFaces); for (int i=0; i<mesh.numFaces; i++) { int j; for (j=0; j<3; j++) { if (!targetVerts[mesh.faces[i].v[j]]) break; } if (j<3) continue; // Face needs to be deleted. delFaces.Set (i); } mesh.DeleteFaceSet (delFaces, &delVerts); mesh.DeleteVertSet (delVerts); }
BOOL MNMeshLoopAdvancer::Advance(MNMeshLoopFront* front, MNMeshLoopItem* item, int itemindex, int wave, BitArray &finalsel) { if (front->nextid < 0 || (front->crossed && finalsel[front->nextid])) return TRUE; int newid = front->nextid; item->wave = wave; item->previndex = front->previndex; item->id = newid; item->pos = GetPos(newid); front->previndex = itemindex; front->previd = newid; front->crossed = finalsel[newid]; finalsel.Set(newid); // check for next connector front->connector = GetNextConnector(front->connector,front->contype,newid); //front->connector = front->connector == newconnector ? -1 : newconnector; front->nextid = front->connector < 0 ? -1 : GetNextID(front->connector,front->contype,newid); return FALSE; }
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); } } } } } } }
// Selection set, misc fixup utility function // This depends on PatchMesh::RecordTopologyTags being called prior to the topo changes void EditPatchMod::ResolveTopoChanges() { ModContextList mcList; INodeTab nodes; TimeValue t = ip->GetTime(); ip->GetModContexts(mcList, nodes); ClearPatchDataFlag(mcList, EPD_BEENDONE); for (int i = 0; i < mcList.Count(); i++) { EditPatchData *patchData =(EditPatchData*)mcList[i]->localData; if (!patchData) continue; if (patchData->GetFlag(EPD_BEENDONE)) continue; // If the mesh isn't yet cache, this will cause it to get cached. RPatchMesh *rpatch; PatchMesh *patch = patchData->TempData(this)->GetPatch(t, rpatch); if (!patch) continue; // First, the vertex selections int set; for (set = 0; set < patchData->vselSet.Count(); ++set) { BitArray *oldVS = &patchData->vselSet[set]; BitArray newVS; newVS.SetSize(patch->numVerts); for (int vert = 0; vert < patch->numVerts; ++vert) { // Get the knot's previous location, then copy that selection into the new set int tag = patch->verts[vert].aux1; if (tag >= 0) newVS.Set(vert, (*oldVS)[tag]); else newVS.Clear(vert); } if (theHold.Holding()) theHold.Put(new ChangeNamedSetRestore(&patchData->vselSet, set, oldVS)); patchData->vselSet[set] = newVS; } // Now the edge selections for (set = 0; set < patchData->eselSet.Count(); ++set) { BitArray *oldES = &patchData->eselSet[set]; BitArray newES; newES.SetSize(patch->numEdges); for (int edge = 0; edge < patch->numEdges; ++edge) { // Get the knot's previous location, then copy that selection into the new set int tag = patch->edges[edge].aux1; if (tag >= 0) newES.Set(edge, (*oldES)[tag]); else newES.Clear(edge); } if (theHold.Holding()) theHold.Put(new ChangeNamedSetRestore(&patchData->eselSet, set, oldES)); patchData->eselSet[set] = newES; } // Now the patch selections for (set = 0; set < patchData->pselSet.Count(); ++set) { BitArray *oldPS = &patchData->pselSet[set]; BitArray newPS; newPS.SetSize(patch->numPatches); for (int p = 0; p < patch->numPatches; ++p) { // Get the knot's previous location, then copy that selection into the new set int tag = patch->patches[p].aux1; if (tag >= 0) newPS.Set(p, (*oldPS)[tag]); else newPS.Clear(p); } if (theHold.Holding()) theHold.Put(new ChangeNamedSetRestore(&patchData->pselSet, set, oldPS)); patchData->pselSet[set] = newPS; } // watje 4-16-99 patch->HookFixTopology(); patchData->SetFlag(EPD_BEENDONE, TRUE); } nodes.DisposeTemporary(); ClearPatchDataFlag(mcList, EPD_BEENDONE); }
void FExtrudeMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float a, s; Point3 pt, center; int c; pblock->GetValue(PB_AMOUNT,t,a,iv); pblock->GetValue(PB_SCALE,t,s,iv); pblock->GetValue(PB_CENTER,t,c,iv); base->GetValue(t,&pt,iv,CTRL_ABSOLUTE); // Extrude the faces -- this just creates the new faces mesh.ExtrudeFaces(); // Build normals of selected faces only Tab<Point3> normals; if (!c) { normals.SetCount(mesh.getNumVerts()); for (int i=0; i<mesh.getNumVerts(); i++) { normals[i] = Point3(0,0,0); } for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) { Point3 norm = (mesh.verts[mesh.faces[i].v[1]]-mesh.verts[mesh.faces[i].v[0]]) ^ (mesh.verts[mesh.faces[i].v[2]]-mesh.verts[mesh.faces[i].v[1]]); for (int j=0; j<3; j++) { normals[mesh.faces[i].v[j]] += norm; } } } for (int i=0; i<mesh.getNumVerts(); i++) { normals[i] = Normalize(normals[i]); } } else { // Compute the center point base->GetValue(t,¢er,iv,CTRL_ABSOLUTE); } // Mark vertices used by selected faces BitArray sel; sel.SetSize(mesh.getNumVerts()); for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) { for (int j=0; j<3; j++) sel.Set(mesh.faces[i].v[j],TRUE); } } // Move selected verts for (int i=0; i<mesh.getNumVerts(); i++) { if (sel[i]) { if (!c) { mesh.verts[i] += normals[i]*a; } else { Point3 vect = Normalize((mesh.verts[i] * (*mc.tm)) - center); mesh.verts[i] += vect*a; } } } // Scale verts if (s!=100.0f) { s /= 100.0f; AdjEdgeList ae(mesh); AdjFaceList af(mesh,ae); FaceClusterList clust(mesh.faceSel,af); // Make sure each vertex is only scaled once. BitArray done; done.SetSize(mesh.getNumVerts()); // scale each cluster independently for (int i=0; (DWORD)i<clust.count; i++) { // First determine cluster center Point3 cent(0,0,0); int ct=0; for (int j=0; j<mesh.getNumFaces(); j++) { if (clust[j]==(DWORD)i) { for (int k=0; k<3; k++) { cent += mesh.verts[mesh.faces[j].v[k]]; ct++; } } } if (ct) cent /= float(ct); // Now scale the cluster about its center for (int j=0; j<mesh.getNumFaces(); j++) { if (clust[j]==(DWORD)i) { for (int k=0; k<3; k++) { int index = mesh.faces[j].v[k]; if (done[index]) continue; done.Set(index); mesh.verts[index] = (mesh.verts[index]-cent)*s + cent; } } } } } mesh.InvalidateTopologyCache (); os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); } }