Tile OrientTile(Tile toPlace, Tile.Edge matchingEdge, Tile.Edge toMatch) { while (true) { if (CurrentEdge(toMatch, toPlace).Checksum == toMatch.Checksum) { return(toPlace); } toPlace = toPlace.Rotate(); if (CurrentEdge(toMatch, toPlace).Checksum == toMatch.Checksum) { return(toPlace); } var flipped = toMatch.Type == Tile.EdgeType.Bottom ? toPlace.FlipHorizontal() : toPlace.FlipVertical(); if (CurrentEdge(toMatch, flipped).Checksum == toMatch.Checksum) { return(flipped); } } Tile.Edge CurrentEdge(Tile.Edge toMatch, Tile toPlace) => toMatch.Type == Tile.EdgeType.Bottom ? toPlace.TopEdge() : toPlace.LeftEdge(); }
private void SetNeihbors(ref Dictionary <Tile.Edge, List <Tile> > edgeToTriangeDic, Tile.Edge edge, Tile tile) { if (edgeToTriangeDic.ContainsKey(edge)) { var list = edgeToTriangeDic[edge]; for (int i = 0; i < list.Count; ++i) { if (list[i].neihbors.ContainsKey(edge) == false) { list[i].neihbors.Add(edge, tile); } if (tile.neihbors.ContainsKey(edge) == false) { tile.neihbors.Add(edge, list[i]); } } list.Add(tile); } else { edgeToTriangeDic.Add(edge, new List <Tile>()); edgeToTriangeDic[edge].Add(tile); } }
/// <summary> /// 初始化球形三角网格 /// </summary> /// <param name="radius">球形半径</param> /// <param name="recursion">递归细分次数</param> public void Init(float radius, int recursion) { this.radius = radius; this.recursion = recursion; if (recursion < 1) { recursion = 1; } List <Vector3> vertList = new List <Vector3>(); Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>(); // create 12 vertices of a icosahedron float t = (1f + Mathf.Sqrt(5f)) / 2f; vertList.Add(new Vector3(-1f, t, 0f).normalized *radius); vertList.Add(new Vector3(1f, t, 0f).normalized *radius); vertList.Add(new Vector3(-1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(0f, -1f, t).normalized *radius); vertList.Add(new Vector3(0f, 1f, t).normalized *radius); vertList.Add(new Vector3(0f, -1f, -t).normalized *radius); vertList.Add(new Vector3(0f, 1f, -t).normalized *radius); vertList.Add(new Vector3(t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(t, 0f, 1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, 1f).normalized *radius); // create 20 triangles of the icosahedron List <TriangleIndices> faces = new List <TriangleIndices>(); List <TriangleIndices> faces2 = new List <TriangleIndices>(); // 5 faces around point 0 faces.Add(new TriangleIndices(null, new Vector3Int(0, 11, 5))); faces.Add(new TriangleIndices(null, new Vector3Int(0, 5, 1))); faces.Add(new TriangleIndices(null, new Vector3Int(0, 1, 7))); faces.Add(new TriangleIndices(null, new Vector3Int(0, 7, 10))); faces.Add(new TriangleIndices(null, new Vector3Int(0, 10, 11))); // 5 adjacent faces faces.Add(new TriangleIndices(null, new Vector3Int(1, 5, 9))); faces.Add(new TriangleIndices(null, new Vector3Int(5, 11, 4))); faces.Add(new TriangleIndices(null, new Vector3Int(11, 10, 2))); faces.Add(new TriangleIndices(null, new Vector3Int(10, 7, 6))); faces.Add(new TriangleIndices(null, new Vector3Int(7, 1, 8))); // 5 faces around point 3 faces.Add(new TriangleIndices(null, new Vector3Int(3, 9, 4))); faces.Add(new TriangleIndices(null, new Vector3Int(3, 4, 2))); faces.Add(new TriangleIndices(null, new Vector3Int(3, 2, 6))); faces.Add(new TriangleIndices(null, new Vector3Int(3, 6, 8))); faces.Add(new TriangleIndices(null, new Vector3Int(3, 8, 9))); // 5 adjacent faces faces.Add(new TriangleIndices(null, new Vector3Int(4, 9, 5))); faces.Add(new TriangleIndices(null, new Vector3Int(2, 4, 11))); faces.Add(new TriangleIndices(null, new Vector3Int(6, 2, 10))); faces.Add(new TriangleIndices(null, new Vector3Int(8, 6, 7))); faces.Add(new TriangleIndices(null, new Vector3Int(9, 8, 1))); roots = new List <Tile>(); // refine triangles for (int i = 0; i < recursion; i++) { faces2.Clear(); foreach (var face in faces) { Tile tile = null; if (face.tile == null) { tile = new Tile(this, null, vertList[face.index.x], vertList[face.index.y], vertList[face.index.z]); tile.index = roots.Count; tile.depth = i; roots.Add(tile); } else { tile = new Tile(this, face.tile, vertList[face.index.x], vertList[face.index.y], vertList[face.index.z]); tile.index = face.tile.index * 10 + face.tile.children.Count; tile.depth = i; face.tile.children.Add(tile); } // replace triangle by 4 triangles int a = GetMiddlePoint(face.index.x, face.index.y, ref vertList, ref middlePointIndexCache, radius); int b = GetMiddlePoint(face.index.y, face.index.z, ref vertList, ref middlePointIndexCache, radius); int c = GetMiddlePoint(face.index.z, face.index.x, ref vertList, ref middlePointIndexCache, radius); faces2.Add(new TriangleIndices(tile, new Vector3Int(face.index.x, a, c))); faces2.Add(new TriangleIndices(tile, new Vector3Int(face.index.y, b, a))); faces2.Add(new TriangleIndices(tile, new Vector3Int(face.index.z, c, b))); faces2.Add(new TriangleIndices(tile, new Vector3Int(a, b, c))); } var temp = faces; faces = faces2; faces2 = temp; } Dictionary <Tile.Edge, List <Tile> > segmentToTriangeDic = new Dictionary <Tile.Edge, List <Tile> >(); Dictionary <Vector3, List <Tile> > pointToTriangeDic = new Dictionary <Vector3, List <Tile> >(); for (int i = 0; i < faces.Count; ++i) { var tri = faces[i]; if (tilesType.Count == 0 || (tilesType.Count > 0 && tilesType.ContainsKey(i))) { var tile = new Tile(this, tri.tile, vertList[tri.index.x], vertList[tri.index.y], vertList[tri.index.z]); tiles.Add(tile); if (tri.tile != null) { tile.index = i; tile.depth = tri.tile.depth + 1; tri.tile.children.Add(tile); } Tile.Edge ab = new Tile.Edge(tile.a, tile.b); Tile.Edge ac = new Tile.Edge(tile.a, tile.c); Tile.Edge bc = new Tile.Edge(tile.b, tile.c); SetNeihbors(ref segmentToTriangeDic, ab, tile); SetNeihbors(ref segmentToTriangeDic, ac, tile); SetNeihbors(ref segmentToTriangeDic, bc, tile); SetCorners(ref pointToTriangeDic, tile.a, tile); SetCorners(ref pointToTriangeDic, tile.b, tile); SetCorners(ref pointToTriangeDic, tile.c, tile); } } RemoveEmpty(roots); }