/// <summary> /// merge two VFaces into lhs, /// modify other related data-structures as well /// </summary> private void _MergeVFace(VFace lhs, VFace rhs) { //int lhsTriIdx = lhs.GetRTriIdx(0); int rhsTriIdx = rhs.GetRTriIdx(0); m_VFaceCont[rhsTriIdx] = lhs; //link rhs's rTri to lhs // merge the data from rhs to lhs lhs.AddRTri(rhsTriIdx); }
private bool _HasIntersect(VFLst lhs, VFLst rhs) { for (int i = 0; i < rhs.Count; ++i) { VFace vf = rhs[i]; if (lhs.Contains(vf)) { return(true); } } return(false); }
/// <summary> /// assume the rTriIdx is not degraded /// </summary> public VFace GetVFaceFromRTri(int rTriIdx) { VFace vf = null; if (m_VFaceCont.TryGetValue(rTriIdx, out vf)) { return(vf); } else { Dbg.LogErr("VMesh.GetVFaceFromRTri: the rTriIdx is not found in m_VFaceCont, {0}", rTriIdx); return(null); } }
/// <summary> /// get VFaces that containing this VEdge /// </summary> public void GetVFaces(List <VFace> vFaces) { vFaces.Clear(); VMesh vmesh = VMesh.Instance; for (int i = 0; i < m_TriCont.Count; ++i) { int triIdx = m_TriCont[i]; VFace vf = vmesh.GetVFaceFromRTri(triIdx); if (!vFaces.Contains(vf)) { vFaces.Add(vf); } } }
/// <summary> /// tell each VVert which VFace it's in /// </summary> private void _MapVVertToVFaces() { // HashSet <VFace> faces = new HashSet <VFace>(); for (var ie = m_VFaceCont.GetEnumerator(); ie.MoveNext();) { VFace f = ie.Current.Value; faces.Add(f); } for (var ie = faces.GetEnumerator(); ie.MoveNext();) { VFace f = ie.Current; List <VVert> vvLst = f.GetVVerts(); foreach (VVert vv in vvLst) { vv.AddVFace(f); } } }
/// <summary> /// rTriIdx might be degraded rtri, but we can get the VFace to which it belongs anyway /// </summary> public VFace GetVFaceFromRTri(int rTriIdx, RaycastHit hit) { VFace vf = null; if (m_VFaceCont.TryGetValue(rTriIdx, out vf)) { return(vf); } else { Dbg.Assert(m_DegRTriCont.Contains(rTriIdx), "VMesh.GetVFaceFromRTri: not in m_VFaceCont or degradedTriCont!?"); m_tmpVVLst.Clear(); GetVVertsFromRTri(rTriIdx, m_tmpVVLst); float minDist = float.MaxValue; VVert retVV = null; for (int i = 0; i < m_tmpVVLst.Count; ++i) { VVert vv = m_tmpVVLst[i]; float dist = Vector3.Distance(hit.point, vv.GetWorldPos()); if (dist < minDist) { minDist = dist; retVV = vv; } } Dbg.Assert(retVV != null, "VMesh.GetVFaceFromRTri: no VVert for given rtri!? {0}", rTriIdx); VFLst vfLst = retVV.GetAllVFaces(); Dbg.Assert(vfLst.Count > 0, "VMesh.GetVFaceFromRTri: the vvert has no VFace, {0}", retVV); return(vfLst[0]); } }
// "VQuad table init" /// <summary> /// this method will try to make VMesh from tri-mesh into hybrid tri-quad-mesh, /// it will mark some vedges as "ActiveEdge" which will be used, /// /// the result will be used in: /// * edge marker, /// * edge loop /// * etc /// /// [BE WARNED]: /// </summary> private void _InitVFaceTable() { ////////////////////////////////////////////////// // 1. foreach vedge of the vmesh // if vedge has and only has 2 tris // calc a score and store in sorted_vEdges // 2. foreach vedge in sorted_vEdges // if the 2 tris not be 'marked' yet, then // take it as the 'non-quad' edge; // mark the 2 tris; // 3. get all active-edge into m_VActiveEdgeArr // 3.1 call all vvert, to make activeVEdge // 4. prepare the VFaceCont: // create the rTriIdx <=> VFace first; // merge VFace with those markedTris; // 5. process the degraded r-tris, assign them to some good VFace (so we can handle click-selection) ////////////////////////////////////////////////// int totalTriCnt = MeshCache.Instance.triangles.Length / 3; VVert[] tmpVertArr = new VVert[4]; // step 1 SortedDictionary <_ScoredEdge, bool> sortedVEdges = new SortedDictionary <_ScoredEdge, bool>(); foreach (var vedge in m_VEdgeCont) { if (vedge.GetRTriCount() != 2) { continue; } RTriCont rtris = vedge.GetRTris(); _GetAsQuadVerts(rtris[0], rtris[1], vedge, tmpVertArr); float score = _CalcQuadScore(tmpVertArr); // calc score for the quad-to-be sortedVEdges.Add(new _ScoredEdge(score, vedge), false); } // step 2 //int cnt = 0; Dictionary <int, int> markedTris = new Dictionary <int, int>(); for (var ie = sortedVEdges.GetEnumerator(); ie.MoveNext();) { var vedge = ie.Current.Key.vEdge; //if (cnt < 100) //Dbg.Log("sortedVEdges: {0}: {1}, score:{2}", cnt++, vedge, ie.Current.Key.score); RTriCont triCont = vedge.GetRTris(); Dbg.Assert(triCont.Count == 2, "VMesh._InitVFaceTable: the tri-cont count of vEdge != 2"); if (!markedTris.ContainsKey(triCont[0]) && !markedTris.ContainsKey(triCont[1])) { //Dbg.Log("Add markedTris: {0}<=>{1}", triCont[0], triCont[1]); markedTris.Add(triCont[0], triCont[1]); markedTris.Add(triCont[1], triCont[0]); vedge.IsActiveEdge = false; if (markedTris.Count >= totalTriCnt) { break; // all tris covered, no need to loop on } } } // step 3 List <VEdge> quadEdges = new List <VEdge>(); for (int i = 0; i < m_VEdgeArr.Length; ++i) { if (m_VEdgeArr[i].IsActiveEdge) { quadEdges.Add(m_VEdgeArr[i]); } } m_VActiveEdgeArr = quadEdges.ToArray(); //step 3.1 for (int i = 0; i < m_VVertArr.Length; ++i) { m_VVertArr[i].CreateActiveVEdgesList(); } // step 4 int[] rTriIdxs = MeshCache.Instance.triangles; int rTriCnt = rTriIdxs.Length / 3; for (int i = 0; i < rTriCnt; ++i) { VFace vFace = new VFace(); vFace.AddRTri(i); m_VFaceCont.Add(i, vFace); } for (var ie = markedTris.GetEnumerator(); ie.MoveNext();) { int rTriIdx0 = ie.Current.Key; int rTriIdx1 = ie.Current.Value; if (rTriIdx0 > rTriIdx1) { continue; } VFace vf0 = m_VFaceCont[rTriIdx0]; VFace vf1 = m_VFaceCont[rTriIdx1]; _MergeVFace(vf0, vf1); } markedTris.Clear(); // step 5 _MapVVertToVFaces(); }
public override void Awake() { base.Awake(); vFace = GetComponent <VFace>(); }
// "vface" public void AddVFace(VFace vf) { m_vfLst.Add(vf); }