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::SynchSize (int numFaces) { if (numFaces<0) { // We're supposed to get the right size from the cache. if (mpCacheMesh) numFaces = mpCacheMesh->numFaces; if (mpCacheMNMesh) numFaces = mpCacheMNMesh->numf; if (numFaces<0) return; // do nothing if cache missing. } mFaceSel.SetSize (numFaces, true); mFacesAffected.SetSize (numFaces, true); mtNewFaceValues.SetCount (numFaces); }
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 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 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 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); } } } } }
static void AssignSetMatchSize(BitArray &dst, BitArray &src) { int size = dst.GetSize(); dst = src; if (dst.GetSize() != size) { dst.SetSize(size, TRUE); } }
void NifImporter::WeldVertices(Mesh& mesh) { MeshDelta tmd(mesh); BitArray vTempSel; vTempSel.SetSize(mesh.getNumVerts()); vTempSel.SetAll(); tmd.WeldByThreshold(mesh, vTempSel, weldVertexThresh); tmd.Apply(mesh); }
void RelaxModData::SetVNum (int num) { if (num==vnum) return; Clear(); vnum = num; if (num<1) return; nbor = new DWordTab[vnum]; vis = new BitArray[vnum]; fnum = new int[vnum]; sel.SetSize (vnum); }
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); } }
IObject* ParticleChannelMap::Split(BitArray& toSplit) { // SysUtil::NeedToImplementLater(); // TODO: optimize the implementation ParticleChannelMap* newChannel = (ParticleChannelMap*)Clone(); Delete(toSplit); BitArray reverse = ~toSplit; if (reverse.GetSize() != newChannel->Count()) reverse.SetSize(newChannel->Count(), TRUE); newChannel->Delete(reverse); return newChannel; }
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); }
////////////////////////////////// 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; } } }
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 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 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(); } } } }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| 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; }
void MNMesh_selectFaceLoops(MNMesh *mesh, int startid, BitArray &facesel) { BitArray secondarysel(mesh->ENum()); BitArray ringsel(mesh->ENum()); facesel.SetSize(mesh->FNum()); mesh->getEdgeSel(secondarysel); // convert to Edge MNFace *face = mesh->F(startid); for (int d = 0; d < face->deg; d++){ ringsel.Set(face->edg[d]); } // ring mesh->SelectEdgeRing(ringsel); // back to face BitArrayEdgeToFace etf(mesh,&facesel); SM_BITARRAY_ENUMSET(ringsel,etf,BitArrayEdgeToFace); mesh->FaceSelect(facesel); // restor old edges mesh->EdgeSelect(secondarysel); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| 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); }
void MeshTopoData::UpdateClusterVertices(Tab<ClusterClass*> &clusterList) { BitArray processedVerts; processedVerts.SetSize(TVMaps.v.Count()); for (int i = 0; i < clusterList.Count(); i++) { if (clusterList[i]->ld == this) { clusterList[i]->verts.SetCount(0); processedVerts.ClearAll(); for (int j = 0; j < clusterList[i]->faces.Count(); j++) { int findex = clusterList[i]->faces[j]; AddVertsToCluster(findex, processedVerts, clusterList[i]); } for (int j = 0; j < clusterList[i]->verts.Count(); j++) { int id = clusterList[i]->verts[j]; } } } }
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++; } } }
// 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 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 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); } }