private TriMesh ChangeTopologyInit(TriMesh sourceMesh) { TriMesh mesh = new TriMesh(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; faceMap = new HalfEdgeMesh.Vertex[sourceMesh.Faces.Count]; foreach (var face in sourceMesh.Faces) { faceMap[face.Index] = mesh.Vertices.Add( new VertexTraits(TriMeshUtil.GetMidPoint(face))); } foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = mesh.Vertices.Add(new VertexTraits(v.Traits.Position)); foreach (var hf in v.HalfEdges) { if (hf.Face != null && hf.Opposite.Face != null) { mesh.Faces.AddTriangles(faceMap[hf.Face.Index], vMap[v.Index], faceMap[hf.Opposite.Face.Index]); } } } foreach (var hf in sourceMesh.HalfEdges) { if (hf.Face == null) { mesh.Faces.AddTriangles(vMap[hf.ToVertex.Index], vMap[hf.FromVertex.Index], faceMap[hf.Opposite.Face.Index]); } } return(mesh); }
public static TriMesh CreateGrid(int m, int n, double lengthx, double lengthy) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m, n]; double x0 = -m * lengthx / 2d; double y0 = -n * lengthy / 2d; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { arr[i, j] = new HalfEdgeMesh.Vertex(); arr[i, j].Traits = new VertexTraits(x0 + i * lengthx, y0 + j * lengthy, 0d); mesh.AppendToVertexList(arr[i, j]); } } for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n - 1; j++) { mesh.Faces.AddTriangles(arr[i + 1, j], arr[i, j + 1], arr[i, j]); mesh.Faces.AddTriangles(arr[i + 1, j], arr[i + 1, j + 1], arr[i, j + 1]); } } return(mesh); }
public static TriMesh CreateCylinder(int m, int n, double r, double l, double maxU, double maxV, int diff) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m, n]; for (int i = 0; i < m; i++) { double z = l / m * i - l / 2; double v = maxV / m * i; for (int j = 0; j < n; j++) { double x = r * Math.Cos(Math.PI * 2 / n * j); double y = r * Math.Sin(Math.PI * 2 / n * j); double u = maxU / n * j; VertexTraits trait = new VertexTraits(x, y, z); trait.UV = new Vector2D(u, v); arr[i, j] = mesh.Vertices.Add(trait); } } for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n - diff; j++) { int ni = i + 1; int nj = (j + 1) % n; mesh.Faces.AddTriangles(arr[i, nj], arr[ni, nj], arr[ni, j], arr[i, j]); } } return(mesh); }
public static TriMesh CreateCylinderPlane(int m, int n, double r, double l, double maxU, double maxV, int diff) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m, n]; for (int i = 0; i < m; i++) { double x = l / m * i - l / 2; for (int j = 0; j < n; j++) { double y = l / n * j - l / 2; VertexTraits trait = new VertexTraits(x, y, 0); trait.UV = new Vector2D(x, y); arr[i, j] = mesh.Vertices.Add(trait); } } for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n - diff; j++) { int ni = i + 1; int nj = (j + 1) % n; mesh.Faces.AddTriangles(arr[i, nj], arr[ni, nj], arr[ni, j], arr[i, j]); } } return(mesh); }
private TriMesh ChangeTopologyLoop(TriMesh sourceMesh) { TriMesh newMesh = new TriMesh(); newMesh.Clear(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; eMap = new HalfEdgeMesh.Vertex[sourceMesh.Edges.Count]; foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var edge in sourceMesh.Edges) { eMap[edge.Index] = newMesh.Vertices.Add( new VertexTraits(TriMeshUtil.GetMidPoint(edge))); } foreach(TriMesh.Face face in sourceMesh.Faces) { foreach (var hf in face.Halfedges) { newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]); } newMesh.Faces.AddTriangles( eMap[face.HalfEdge.Previous.Edge.Index], eMap[face.HalfEdge.Edge.Index], eMap[face.HalfEdge.Next.Edge.Index]); } return newMesh; }
public static TriMesh CreatePlaneTest(int m, int n, double l) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m + 1, n + 1]; for (int i = 0; i <= m; i++) { double x = l / m * i; for (int j = 0; j <= n; j++) { double y = l / n * j; VertexTraits trait = new VertexTraits(x, y, 0); trait.UV = new Vector2D(x, y); arr[i, j] = mesh.Vertices.Add(trait); } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int ni = i + 1; int nj = j + 1; mesh.Faces.AddTriangles(arr[i, nj], arr[ni, nj], arr[ni, j], arr[i, j]); } } return(mesh); }
TriMesh Create(IEnumerable <TriMesh.Face> region) { TriMesh newMesh = new TriMesh(); foreach (var f in region) { TriMesh.Vertex[] arr = new HalfEdgeMesh.Vertex[3]; int i = 0; foreach (var v in f.Vertices) { if (!this.vMap.ContainsKey(v)) { TriMesh.Vertex newV = new HalfEdgeMesh.Vertex(new VertexTraits(v.Traits.Position)); this.vMap[v] = newV; newMesh.AppendToVertexList(newV); } arr[i++] = this.vMap[v]; } newMesh.Faces.AddTriangles(arr); this.fFlag[f.Index] = true; } return(newMesh); }
public static List <TriMesh> SeperateComponent(TriMesh mesh) { List <TriMesh> meshes = new List <TriMesh>(); Dictionary <int, TriMesh.Vertex> map = new Dictionary <int, HalfEdgeMesh.Vertex>(); bool[] visited = new bool[mesh.Faces.Count]; Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>(); TriMesh newMesh = new TriMesh(); queue.Enqueue(mesh.Faces[0]); visited[0] = true; while (queue.Count != 0) { TriMesh.Face face = queue.Dequeue(); foreach (var hf in face.Halfedges) { if (!map.ContainsKey(hf.ToVertex.Index)) { TriMesh.Vertex v = new HalfEdgeMesh.Vertex(new VertexTraits(hf.ToVertex.Traits.Position)); newMesh.AppendToVertexList(v); map[hf.ToVertex.Index] = v; } if (hf.Opposite.Face != null && !visited[hf.Opposite.Face.Index]) { queue.Enqueue(hf.Opposite.Face); visited[hf.Opposite.Face.Index] = true; } } newMesh.Faces.AddTriangles( map[face.HalfEdge.FromVertex.Index], map[face.HalfEdge.ToVertex.Index], map[face.HalfEdge.Next.ToVertex.Index]); if (queue.Count == 0) { meshes.Add(newMesh); for (int i = 0; i < visited.Length; i++) { if (!visited[i]) { newMesh = new TriMesh(); queue.Enqueue(mesh.Faces[i]); visited[i] = true; break; } } } } foreach (TriMesh child in meshes) { TriMeshUtil.SetUpNormalVertex(child); } return(meshes); }
private TriMesh ChangeTopologyInit(TriMesh sourceMesh) { TriMesh mesh = new TriMesh(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; faceMap = new HalfEdgeMesh.Vertex[sourceMesh.Faces.Count]; foreach (var face in sourceMesh.Faces) { faceMap[face.Index] = mesh.Vertices.Add( new VertexTraits(TriMeshUtil.GetMidPoint(face))); } foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = mesh.Vertices.Add(new VertexTraits(v.Traits.Position)); foreach (var hf in v.HalfEdges) { if (hf.Face != null && hf.Opposite.Face != null) { mesh.Faces.AddTriangles(faceMap[hf.Face.Index], vMap[v.Index], faceMap[hf.Opposite.Face.Index]); } } } foreach (var hf in sourceMesh.HalfEdges) { if (hf.Face == null) { mesh.Faces.AddTriangles(vMap[hf.ToVertex.Index], vMap[hf.FromVertex.Index], faceMap[hf.Opposite.Face.Index]); } } return mesh; }
private TriMesh ChangeTopologyLoop(TriMesh sourceMesh) { TriMesh newMesh = new TriMesh(); newMesh.Clear(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; eMap = new HalfEdgeMesh.Vertex[sourceMesh.Edges.Count]; foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var edge in sourceMesh.Edges) { eMap[edge.Index] = newMesh.Vertices.Add( new VertexTraits(TriMeshUtil.GetMidPoint(edge))); } foreach (TriMesh.Face face in sourceMesh.Faces) { foreach (var hf in face.Halfedges) { newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]); } newMesh.Faces.AddTriangles( eMap[face.HalfEdge.Previous.Edge.Index], eMap[face.HalfEdge.Edge.Index], eMap[face.HalfEdge.Next.Edge.Index]); } return(newMesh); }
public static TriMesh.HalfEdge Split(TriMesh.HalfEdge hf, Vector3D v1Pos, Vector3D v2Pos) { TriMesh mesh = (TriMesh)hf.Mesh; List <TriMesh.HalfEdge> list = new List <HalfEdgeMesh.HalfEdge>(); TriMesh.HalfEdge cur = hf; list.Add(cur); do { cur = cur.Opposite.Next; list.Add(cur); } while (cur.Opposite.Face != null && cur != hf); for (int i = 1; i < list.Count; i++) { TriMeshModify.RemoveEdge(list[i].Edge); } hf.FromVertex.Traits.Position = v1Pos; TriMesh.Vertex v2 = new HalfEdgeMesh.Vertex(new VertexTraits(v2Pos)); mesh.AppendToVertexList(v2); for (int i = 1; i < list.Count; i++) { mesh.Faces.AddTriangles(list[i - 1].ToVertex, v2, list[i].ToVertex); } mesh.Faces.AddTriangles(list[0].ToVertex, hf.FromVertex, v2); return(hf.FromVertex.FindHalfedgeTo(v2)); }
public static List<TriMesh> SeperateComponent(TriMesh mesh) { List<TriMesh> meshes = new List<TriMesh>(); Dictionary<int, TriMesh.Vertex> map = new Dictionary<int, HalfEdgeMesh.Vertex>(); bool[] visited = new bool[mesh.Faces.Count]; Queue<TriMesh.Face> queue = new Queue<HalfEdgeMesh.Face>(); TriMesh newMesh = new TriMesh(); queue.Enqueue(mesh.Faces[0]); visited[0] = true; while (queue.Count != 0) { TriMesh.Face face = queue.Dequeue(); foreach (var hf in face.Halfedges) { if (!map.ContainsKey(hf.ToVertex.Index)) { TriMesh.Vertex v = new HalfEdgeMesh.Vertex(new VertexTraits(hf.ToVertex.Traits.Position)); newMesh.AppendToVertexList(v); map[hf.ToVertex.Index] = v; } if (hf.Opposite.Face != null && !visited[hf.Opposite.Face.Index]) { queue.Enqueue(hf.Opposite.Face); visited[hf.Opposite.Face.Index] = true; } } newMesh.Faces.AddTriangles( map[face.HalfEdge.FromVertex.Index], map[face.HalfEdge.ToVertex.Index], map[face.HalfEdge.Next.ToVertex.Index]); if (queue.Count == 0) { meshes.Add(newMesh); for (int i = 0; i < visited.Length; i++) { if (!visited[i]) { newMesh = new TriMesh(); queue.Enqueue(mesh.Faces[i]); visited[i] = true; break; } } } } foreach (TriMesh child in meshes) { TriMeshUtil.SetUpNormalVertex(child); } return meshes ; }
public static PolygonMesh BuildDual(TriMesh mesh, EnumDual type) { TriMeshModify.RepaireAllHole(mesh); PolygonMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[mesh.Faces.Count]; PolygonMesh.Vertex[] edgeMap = new HalfEdgeMesh.Vertex[mesh.Edges.Count]; PolygonMesh pm = new PolygonMesh(); foreach (var face in mesh.Faces) { Vector3D center = Vector3D.Zero; switch (type) { case EnumDual.DualA: center = TriMeshUtil.GetMidPoint(face); break; case EnumDual.DualB: TriMesh.Vertex vertex0 = face.GetVertex(0); TriMesh.Vertex vertex1 = face.GetVertex(1); TriMesh.Vertex vertex2 = face.GetVertex(2); Triangle triangle = new Triangle(vertex0.Traits.Position, vertex1.Traits.Position, vertex2.Traits.Position); center = triangle.ComputeCircumCenter(); break; default: break; } PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(new VertexTraits(center)); faceMap[face.Index] = v; pm.AppendToVertexList(v); } foreach (var edge in mesh.Edges) { VertexTraits trait = new VertexTraits(TriMeshUtil.GetMidPoint(edge)); PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(trait); edgeMap[edge.Index] = v; pm.AppendToVertexList(v); } foreach (var v in mesh.Vertices) { List <PolygonMesh.Vertex> list = new List <HalfEdgeMesh.Vertex>(); foreach (var hf in v.HalfEdges) { list.Add(faceMap[hf.Face.Index]); list.Add(edgeMap[hf.Edge.Index]); } list.Reverse(); pm.Faces.Add(list.ToArray()); } return(pm); }
TriMesh.Vertex Clone(TriMesh.Vertex oldV, Vector3D moveVec) { TriMesh.Vertex newV = new HalfEdgeMesh.Vertex(); newV.Traits = new VertexTraits(oldV.Traits.Position); this.vertexMap.Add(oldV, newV); this.mesh.AppendToVertexList(newV); oldV.Traits.Position += moveVec; newV.Traits.Position -= moveVec; return(newV); }
public static PolygonMesh BuildDual(TriMesh mesh, EnumDual type) { TriMeshModify.RepaireAllHole(mesh); PolygonMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[mesh.Faces.Count]; PolygonMesh.Vertex[] edgeMap = new HalfEdgeMesh.Vertex[mesh.Edges.Count]; PolygonMesh pm = new PolygonMesh(); foreach (var face in mesh.Faces) { Vector3D center = Vector3D.Zero; switch (type) { case EnumDual.DualA: center = TriMeshUtil.GetMidPoint(face); break; case EnumDual.DualB: TriMesh.Vertex vertex0 = face.GetVertex(0); TriMesh.Vertex vertex1 = face.GetVertex(1); TriMesh.Vertex vertex2 = face.GetVertex(2); Triangle triangle = new Triangle(vertex0.Traits.Position, vertex1.Traits.Position, vertex2.Traits.Position); center = triangle.ComputeCircumCenter(); break; default: break; } PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(new VertexTraits(center)); faceMap[face.Index] = v; pm.AppendToVertexList(v); } foreach (var edge in mesh.Edges) { VertexTraits trait = new VertexTraits(TriMeshUtil.GetMidPoint(edge)); PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(trait); edgeMap[edge.Index] = v; pm.AppendToVertexList(v); } foreach (var v in mesh.Vertices) { List<PolygonMesh.Vertex> list = new List<HalfEdgeMesh.Vertex>(); foreach (var hf in v.HalfEdges) { list.Add(faceMap[hf.Face.Index]); list.Add(edgeMap[hf.Edge.Index]); } list.Reverse(); pm.Faces.Add(list.ToArray()); } return pm; }
public void Subdivision() { /* /\ /\ * / \ /__\ * / \ /\ /\ * / \ /__\/__\ * / \ /\ /\ /\ * /__________\ /__\/__\/__\ * * 为了让每个顶点周围都有它专属的一圈价为6的点,把每个三角形拆成9个 */ TriMesh copy = TriMeshIO.Clone(this.mesh); this.mesh.Clear(); TriMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[copy.Faces.Count]; TriMesh.Vertex[] hfMap = new HalfEdgeMesh.Vertex[copy.HalfEdges.Count]; foreach (var v in copy.Vertices) { this.mesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var face in copy.Faces) { faceMap[face.Index] = this.mesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(face))); } foreach (var hf in copy.HalfEdges) { Vector3D pos = hf.FromVertex.Traits.Position * 2 / 3 + hf.ToVertex.Traits.Position * 1 / 3; hfMap[hf.Index] = this.mesh.Vertices.Add(new VertexTraits(pos)); } foreach (var face in copy.Faces) { foreach (var hf in face.Halfedges) { this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Index], hfMap[hf.Opposite.Index]); this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Opposite.Index], hfMap[hf.Next.Index]); } } foreach (var v in copy.Vertices) { foreach (var hf in v.HalfEdges) { if (hf.Face != null) { this.mesh.Faces.AddTriangles(this.mesh.Vertices[v.Index], hfMap[hf.Index], hfMap[hf.Previous.Opposite.Index]); } } } }
public TriMesh.Vertex[] GetAllCascade(TriMesh.Vertex v) { TriMesh.Vertex src = this.GetSrcVertex(v); TriMesh.Vertex[] dst = this.GetOtherCascade(src, false); TriMesh.Vertex[] all = new HalfEdgeMesh.Vertex[dst.Length + 1]; all[0] = src; for (int i = 0; i < dst.Length; i++) { all[i + 1] = dst[i]; } return(all); }
protected override void AfterMerge(HalfEdgeMesh.Vertex v) { foreach (var face in this.removed) { this.heap.Del(handle[face.Index]); } this.traits.MergeUpdate(v); foreach (var face in v.Faces) { ErrorPair pair = this.GetErrorPair(face); this.faceError[face.Index] = pair; this.heap.Update(handle[face.Index], pair.Error); } }
public static void BoundaryExpand(TriMesh mesh) { double length = TriMeshUtil.ComputeEdgeAvgLength(mesh); List <List <TriMesh.HalfEdge> > holes = TriMeshUtil.RetrieveBoundaryEdgeAll(mesh); foreach (var hole in holes) { TriMesh.Vertex[] arr = new HalfEdgeMesh.Vertex[hole.Count]; for (int i = 0; i < hole.Count; i++) { Vector3D normal = Vector3D.UnitX; if (hole[i].Opposite.Face != null) { normal = TriMeshUtil.ComputeNormalFace(hole[i].Opposite.Face); } Vector3D toPos = hole[i].ToVertex.Traits.Position; Vector3D fromPos = hole[i].FromVertex.Traits.Position; Vector3D hfDir = toPos - fromPos; Vector3D hfMid = (toPos + fromPos) / 2; Vector3D pos = hfMid + normal.Cross(hfDir).Normalize() * length; arr[i] = mesh.Vertices.Add(new VertexTraits(pos)); } for (int i = 0; i < hole.Count; i++) { int next = (i + 1) % hole.Count; TriMesh.Face face = mesh.Faces.Add(arr[i], hole[i].ToVertex, hole[next].ToVertex); face.Traits.SelectedFlag = 1; face = mesh.Faces.Add(arr[i], hole[next].ToVertex, arr[next]); face.Traits.SelectedFlag = 1; } } }
public static TriMesh CreateGrid(int m, int n, double lengthx,double lengthy) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m, n]; double x0 = -m * lengthx / 2d; double y0 = -n * lengthy / 2d; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { arr[i, j] = new HalfEdgeMesh.Vertex(); arr[i, j].Traits = new VertexTraits(x0 + i * lengthx, y0 + j * lengthy, 0d); mesh.AppendToVertexList(arr[i, j]); } } for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n - 1; j++) { mesh.Faces.AddTriangles(arr[i + 1, j], arr[i, j + 1], arr[i, j]); mesh.Faces.AddTriangles(arr[i + 1, j], arr[i + 1, j + 1], arr[i, j + 1]); } } return mesh; }
public static TriMesh CreateCylinderPlane(int m, int n, double r, double l, double maxU, double maxV, int diff) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m, n]; for (int i = 0; i < m; i++) { double x = l / m * i - l / 2; for (int j = 0; j < n; j++) { double y = l / n * j - l / 2; VertexTraits trait = new VertexTraits(x,y, 0); trait.UV = new Vector2D(x, y); arr[i, j] = mesh.Vertices.Add(trait); } } for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n - diff; j++) { int ni = i + 1; int nj = (j + 1) % n; mesh.Faces.AddTriangles(arr[i, nj], arr[ni, nj], arr[ni, j], arr[i, j]); } } return mesh; }
public static TriMesh CreateCylinder(int m, int n, double r, double l, double maxU, double maxV,int diff) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m, n]; for (int i = 0; i < m; i++) { double z = l / m * i - l / 2; double v = maxV / m * i; for (int j = 0; j < n; j++) { double x = r * Math.Cos(Math.PI * 2 / n * j); double y = r * Math.Sin(Math.PI * 2 / n * j); double u = maxU / n * j; VertexTraits trait = new VertexTraits(x, y, z); trait.UV = new Vector2D(u, v); arr[i, j] = mesh.Vertices.Add(trait); } } for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n-diff; j++) { int ni = i + 1; int nj = (j + 1) % n; mesh.Faces.AddTriangles(arr[i, nj], arr[ni, nj], arr[ni, j], arr[i, j]); } } return mesh; }
public static TriMesh CreatePlaneFolded(int m, int n, double l) { TriMesh mesh = new TriMesh(); TriMesh.Vertex[,] arr = new HalfEdgeMesh.Vertex[m + 1, n + 1]; for (int i = 0; i <= m; i++) { double x = l / m * i ; double temp = 0; for (int j = 0; j <= n/2; j++) { double y = l / n * j ; VertexTraits trait = new VertexTraits(x, y, 0); trait.UV = new Vector2D(x, y); arr[i, j] = mesh.Vertices.Add(trait); temp = y; } for (int j = 1; j <= n / 2; j++) { double y = l / n * j; VertexTraits trait = new VertexTraits(x, temp, y); trait.UV = new Vector2D(x, y); arr[i, n / 2+j] = mesh.Vertices.Add(trait); } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int ni = i + 1; int nj = j + 1; mesh.Faces.AddTriangles(arr[i, nj], arr[ni, nj], arr[ni, j], arr[i, j]); } } return mesh; }
private TriMesh ChangeTopologyLoopSelected(TriMesh sourceMesh) { TriMesh newMesh = new TriMesh(); newMesh.Clear(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; eMap = new HalfEdgeMesh.Vertex[Mesh.Edges.Count]; foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var edge in sourceMesh.Edges) { if (edge.Vertex0.Traits.SelectedFlag != 0 && edge.Vertex1.Traits.SelectedFlag != 0) { eMap[edge.Index] = newMesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(edge))); } } foreach (TriMesh.Face face in sourceMesh.Faces) { List <TriMesh.HalfEdge> list = new List <HalfEdgeMesh.HalfEdge>(); foreach (var hf in face.Halfedges) { if (hf.ToVertex.Traits.SelectedFlag != 0 && hf.FromVertex.Traits.SelectedFlag != 0) { list.Add(hf); } } switch (list.Count) { case 0: newMesh.Faces.AddTriangles( vMap[face.GetVertex(0).Index], vMap[face.GetVertex(1).Index], vMap[face.GetVertex(2).Index]); break; case 1: TriMesh.HalfEdge h = list[0]; newMesh.Faces.AddTriangles( eMap[h.Edge.Index], vMap[h.ToVertex.Index], vMap[h.Next.ToVertex.Index]); newMesh.Faces.AddTriangles( eMap[h.Edge.Index], vMap[h.Next.ToVertex.Index], vMap[h.FromVertex.Index]); break; case 3: foreach (var hf in face.Halfedges) { newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]); } newMesh.Faces.AddTriangles( eMap[face.HalfEdge.Previous.Edge.Index], eMap[face.HalfEdge.Edge.Index], eMap[face.HalfEdge.Next.Edge.Index]); break; default: break; } } return(newMesh); }
public void Subdivision() { /* /\ /\ * / \ /__\ * / \ /\ /\ * / \ /__\/__\ * / \ /\ /\ /\ * /__________\ /__\/__\/__\ * * 为了让每个顶点周围都有它专属的一圈价为6的点,把每个三角形拆成9个 */ TriMesh copy = TriMeshIO.Clone(this.mesh); this.mesh.Clear(); TriMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[copy.Faces.Count]; TriMesh.Vertex[] hfMap = new HalfEdgeMesh.Vertex[copy.HalfEdges.Count]; foreach (var v in copy.Vertices) { this.mesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var face in copy.Faces) { faceMap[face.Index] = this.mesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(face))); } foreach (var hf in copy.HalfEdges) { Vector3D pos = hf.FromVertex.Traits.Position * 2 / 3 + hf.ToVertex.Traits.Position * 1 / 3; hfMap[hf.Index] = this.mesh.Vertices.Add(new VertexTraits(pos)); } foreach (var face in copy.Faces) { foreach (var hf in face.Halfedges) { this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Index], hfMap[hf.Opposite.Index]); this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Opposite.Index], hfMap[hf.Next.Index]); } } foreach (var v in copy.Vertices) { foreach (var hf in v.HalfEdges) { if (hf.Face != null) { this.mesh.Faces.AddTriangles(this.mesh.Vertices[v.Index], hfMap[hf.Index], hfMap[hf.Previous.Opposite.Index]); } } } }
public TriMesh Cut(IEnumerable<TriMesh.Vertex> region) { Dictionary<int, TriMesh.Vertex> vMap = new Dictionary<int, HalfEdgeMesh.Vertex>(); Dictionary<int, bool> fFlag = new Dictionary<int, bool>(); TriMesh newMesh = new TriMesh(); foreach (var v in region) { TriMesh.Vertex newV = new HalfEdgeMesh.Vertex( new VertexTraits(v.Traits.Position)); vMap[v.Index] = newV; newMesh.AppendToVertexList(newV); } foreach (var f in this.mesh.Faces) { bool inner = true; foreach (var v in f.Vertices) { if (!vMap.ContainsKey(v.Index)) { inner = false; break; } } if (inner) { TriMesh.HalfEdge hf = f.HalfEdge; newMesh.Faces.AddTriangles( vMap[hf.FromVertex.Index], vMap[hf.ToVertex.Index], vMap[hf.Next.ToVertex.Index]); fFlag[f.Index] = true; } } List<TriMesh.Edge> remove = new List<HalfEdgeMesh.Edge>(); foreach (var e in this.mesh.Edges) { if (fFlag.ContainsKey(e.Face0.Index) && fFlag.ContainsKey(e.Face1.Index)) { remove.Add(e); } } foreach (var e in remove) { TriMeshModify.RemoveEdge(e); } foreach (var v in region) { bool inner = true; foreach (var round in v.Vertices) { if (!vMap.ContainsKey(round.Index)) { inner = false; } } if (inner) { this.mesh.RemoveVertex(v); } } return newMesh; }
TriMesh Create(IEnumerable<TriMesh.Face> region) { TriMesh newMesh = new TriMesh(); foreach (var f in region) { TriMesh.Vertex[] arr = new HalfEdgeMesh.Vertex[3]; int i = 0; foreach (var v in f.Vertices) { if (!this.vMap.ContainsKey(v)) { TriMesh.Vertex newV = new HalfEdgeMesh.Vertex(new VertexTraits(v.Traits.Position)); this.vMap[v] = newV; newMesh.AppendToVertexList(newV); } arr[i++] = this.vMap[v]; } newMesh.Faces.AddTriangles(arr); this.fFlag[f.Index] = true; } return newMesh; }
public static void BoundaryExpand(TriMesh mesh) { double length = TriMeshUtil.ComputeEdgeAvgLength(mesh); List<List<TriMesh.HalfEdge>> holes = TriMeshUtil.RetrieveBoundaryEdgeAll(mesh); foreach (var hole in holes) { TriMesh.Vertex[] arr = new HalfEdgeMesh.Vertex[hole.Count]; for (int i = 0; i < hole.Count; i++) { Vector3D normal = Vector3D.UnitX; if (hole[i].Opposite.Face != null) { normal = TriMeshUtil.ComputeNormalFace(hole[i].Opposite.Face); } Vector3D toPos = hole[i].ToVertex.Traits.Position; Vector3D fromPos = hole[i].FromVertex.Traits.Position; Vector3D hfDir = toPos - fromPos; Vector3D hfMid = (toPos + fromPos) / 2; Vector3D pos = hfMid + normal.Cross(hfDir).Normalize() * length; arr[i] = mesh.Vertices.Add(new VertexTraits(pos)); } for (int i = 0; i < hole.Count; i++) { int next = (i + 1) % hole.Count; TriMesh.Face face= mesh.Faces.Add(arr[i], hole[i].ToVertex, hole[next].ToVertex); face.Traits.SelectedFlag = 1; face = mesh.Faces.Add(arr[i], hole[next].ToVertex, arr[next]); face.Traits.SelectedFlag = 1; } } }
public TriMesh Cut(IEnumerable <TriMesh.Vertex> region) { Dictionary <int, TriMesh.Vertex> vMap = new Dictionary <int, HalfEdgeMesh.Vertex>(); Dictionary <int, bool> fFlag = new Dictionary <int, bool>(); TriMesh newMesh = new TriMesh(); foreach (var v in region) { TriMesh.Vertex newV = new HalfEdgeMesh.Vertex( new VertexTraits(v.Traits.Position)); vMap[v.Index] = newV; newMesh.AppendToVertexList(newV); } foreach (var f in this.mesh.Faces) { bool inner = true; foreach (var v in f.Vertices) { if (!vMap.ContainsKey(v.Index)) { inner = false; break; } } if (inner) { TriMesh.HalfEdge hf = f.HalfEdge; newMesh.Faces.AddTriangles( vMap[hf.FromVertex.Index], vMap[hf.ToVertex.Index], vMap[hf.Next.ToVertex.Index]); fFlag[f.Index] = true; } } List <TriMesh.Edge> remove = new List <HalfEdgeMesh.Edge>(); foreach (var e in this.mesh.Edges) { if (fFlag.ContainsKey(e.Face0.Index) && fFlag.ContainsKey(e.Face1.Index)) { remove.Add(e); } } foreach (var e in remove) { TriMeshModify.RemoveEdge(e); } foreach (var v in region) { bool inner = true; foreach (var round in v.Vertices) { if (!vMap.ContainsKey(round.Index)) { inner = false; } } if (inner) { this.mesh.RemoveVertex(v); } } return(newMesh); }
public static TriMesh.HalfEdge Split(TriMesh.HalfEdge hf, Vector3D v1Pos, Vector3D v2Pos) { TriMesh mesh = (TriMesh)hf.Mesh; List<TriMesh.HalfEdge> list = new List<HalfEdgeMesh.HalfEdge>(); TriMesh.HalfEdge cur = hf; list.Add(cur); do { cur = cur.Opposite.Next; list.Add(cur); } while (cur.Opposite.Face != null && cur != hf); for (int i = 1; i < list.Count; i++) { TriMeshModify.RemoveEdge(list[i].Edge); } hf.FromVertex.Traits.Position = v1Pos; TriMesh.Vertex v2 = new HalfEdgeMesh.Vertex(new VertexTraits(v2Pos)); mesh.AppendToVertexList(v2); for (int i = 1; i < list.Count; i++) { mesh.Faces.AddTriangles(list[i - 1].ToVertex, v2, list[i].ToVertex); } mesh.Faces.AddTriangles(list[0].ToVertex, hf.FromVertex, v2); return hf.FromVertex.FindHalfedgeTo(v2); }
TriMesh.Vertex Clone(TriMesh.Vertex oldV, Vector3D moveVec) { TriMesh.Vertex newV = new HalfEdgeMesh.Vertex(); newV.Traits = new VertexTraits(oldV.Traits.Position); this.vertexMap.Add(oldV, newV); this.mesh.AppendToVertexList(newV); oldV.Traits.Position += moveVec; newV.Traits.Position -= moveVec; return newV; }
private TriMesh ChangeTopologyLoopSelected(TriMesh sourceMesh) { TriMesh newMesh = new TriMesh(); newMesh.Clear(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; eMap = new HalfEdgeMesh.Vertex[Mesh.Edges.Count]; foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var edge in sourceMesh.Edges) { if (edge.Vertex0.Traits.SelectedFlag != 0 && edge.Vertex1.Traits.SelectedFlag != 0) { eMap[edge.Index] = newMesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(edge))); } } foreach (TriMesh.Face face in sourceMesh.Faces) { List<TriMesh.HalfEdge> list = new List<HalfEdgeMesh.HalfEdge>(); foreach (var hf in face.Halfedges) { if (hf.ToVertex.Traits.SelectedFlag != 0 && hf.FromVertex.Traits.SelectedFlag != 0) { list.Add(hf); } } switch (list.Count) { case 0: newMesh.Faces.AddTriangles( vMap[face.GetVertex(0).Index], vMap[face.GetVertex(1).Index], vMap[face.GetVertex(2).Index]); break; case 1: TriMesh.HalfEdge h = list[0]; newMesh.Faces.AddTriangles( eMap[h.Edge.Index], vMap[h.ToVertex.Index], vMap[h.Next.ToVertex.Index]); newMesh.Faces.AddTriangles( eMap[h.Edge.Index], vMap[h.Next.ToVertex.Index], vMap[h.FromVertex.Index]); break; case 3: foreach (var hf in face.Halfedges) { newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]); } newMesh.Faces.AddTriangles( eMap[face.HalfEdge.Previous.Edge.Index], eMap[face.HalfEdge.Edge.Index], eMap[face.HalfEdge.Next.Edge.Index]); break; default: break; } } return newMesh; }