public bool Weldable(HexMetrics.Direction dir) { switch (dir) { case HexMetrics.Direction.Up: return weldsUp; case HexMetrics.Direction.RightUp: return weldsRightUp; case HexMetrics.Direction.LeftUp: return weldsLeftUp; case HexMetrics.Direction.Down: return weldsDown; case HexMetrics.Direction.RightDown: return weldsRightDown; case HexMetrics.Direction.LeftDown: return weldsLeftDown; } return false; }
void TriangulateEdgeTerraces( EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad ) { EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); Color c2 = HexMetrics.TerraceLerp(beginCell.Color, endCell.Color, 1); TriangulateEdgeStrip(begin, beginCell.Color, e2, c2, hasRoad); for (int i = 2; i < HexMetrics.terraceSteps; i++) { EdgeVertices e1 = e2; Color c1 = c2; e2 = EdgeVertices.TerraceLerp(begin, end, i); c2 = HexMetrics.TerraceLerp(beginCell.Color, endCell.Color, i); TriangulateEdgeStrip(e1, c1, e2, c2, hasRoad); } TriangulateEdgeStrip(e2, c2, end, endCell.Color, hasRoad); }
void TriangulateAdjacentToRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.innerToOuter * 0.5f); } else if ( cell.HasRiverThroughEdge(direction.Previous2()) ) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if ( cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()) ) { center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip(m, cell.Color, e, cell.Color); TriangulateEdgeFan(center, m, cell.Color); }
void TriangulateEdgeTerraces(EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad) { EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); Color w2 = HexMetrics.TerraceLerp(weights1, weights2, 1); float i1 = beginCell.Index; float i2 = endCell.Index; TriangulateEdgeStrip(begin, weights1, i1, e2, w2, i2, hasRoad); for (int i = 2; i < HexMetrics.terraceSteps; i++) { EdgeVertices e1 = e2; Color w1 = w2; e2 = EdgeVertices.TerraceLerp(begin, end, i); w2 = HexMetrics.TerraceLerp(weights1, weights2, i); TriangulateEdgeStrip(e1, w1, i1, e2, w2, i2, hasRoad); } TriangulateEdgeStrip(e2, w2, i1, end, weights2, i2, hasRoad); }
void TriangulateCornerTerraces(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { Vector3 v3 = HexMetrics.TerraceLerp(begin, left, 1); Vector3 v4 = HexMetrics.TerraceLerp(begin, right, 1); Color c3 = HexMetrics.TerraceLerp(color1, color2, 1); Color c4 = HexMetrics.TerraceLerp(color1, color3, 1); Vector3 types; types.x = beginCell.TerrainTypeIndex; types.y = leftCell.TerrainTypeIndex; types.z = rightCell.TerrainTypeIndex; //first step terrain.AddTriangle(begin, v3, v4); terrain.AddTriangleColor(color1, c3, c4); terrain.AddTriangleTerrainTypes(types); for (int i = 2; i < HexMetrics.terraceSteps; i++) { Vector3 v1 = v3; Vector3 v2 = v4; Color c1 = c3; Color c2 = c4; v3 = HexMetrics.TerraceLerp(begin, left, i); v4 = HexMetrics.TerraceLerp(begin, right, i); c3 = HexMetrics.TerraceLerp(color1, color2, i); c4 = HexMetrics.TerraceLerp(color1, color3, i); terrain.AddQuad(v1, v2, v3, v4); terrain.AddQuadColor(c1, c2, c3, c4); terrain.AddQuadTerrainTypes(types); } //final step terrain.AddQuad(v3, v4, left, right); terrain.AddQuadColor(c3, c4, color2, color3); terrain.AddQuadTerrainTypes(types); }
void TriangulateCornerCliffTerraces( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { float b = 1f / (leftCell.Elevation - beginCell.Elevation); if (b < 0) { b = -b; } Vector3 boundary = Vector3.Lerp( HexMetrics.Perturb(begin), HexMetrics.Perturb(left), b ); Color boundaryColor = Color.Lerp(beginCell.Color, leftCell.Color, b); TriangulateBoundaryTriangle( right, rightCell, begin, beginCell, boundary, boundaryColor ); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle( left, leftCell, right, rightCell, boundary, boundaryColor ); } else { terrain.AddTriangleUnperturbed( HexMetrics.Perturb(left), HexMetrics.Perturb(right), boundary ); terrain.AddTriangleColor( leftCell.Color, rightCell.Color, boundaryColor ); } }
void TriangulateCornerTerracesCliff( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { float b = 1f / (rightCell.Elevation - beginCell.Elevation); if (b < 0) { b = -b; } Vector3 boundary = Vector3.Lerp(HexMetrics.Perturb(begin), HexMetrics.Perturb(right), b); Color boundaryColor = Color.Lerp(color1, color3, b); Vector3 types; types.x = (float)beginCell.TerrainType; types.y = (float)leftCell.TerrainType; types.z = (float)rightCell.TerrainType; TriangulateBoundaryTriangle( begin, color1, left, color2, boundary, boundaryColor, types ); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle( left, color2, right, color3, boundary, boundaryColor, types ); } else { terrain.AddTriangleUnPerturbed(HexMetrics.Perturb(left), HexMetrics.Perturb(right), boundary); terrain.AddTriangleColor(color2, color3, boundaryColor); terrain.AddTriangleTerrainTypes(types); } }
void TriangulateOpenWater( HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center ) { Vector3 c1 = center + HexMetrics.GetFirstWaterCorner(direction); Vector3 c2 = center + HexMetrics.GetSecondWaterCorner(direction); water.AddTriangle(center, c1, c2); Vector3 indices; indices.x = indices.y = indices.z = cell.Index; water.AddTriangleCellData(indices, weights1); if (direction <= HexDirection.SE && neighbor != null) { Vector3 bridge = HexMetrics.GetWaterBridge(direction); Vector3 e1 = c1 + bridge; Vector3 e2 = c2 + bridge; water.AddQuad(c1, c2, e1, e2); indices.y = neighbor.Index; water.AddQuadCellData(indices, weights1, weights2); if (direction <= HexDirection.E) { HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor == null || !nextNeighbor.IsUnderwater) { return; } water.AddTriangle( c2, e2, c2 + HexMetrics.GetWaterBridge(direction.Next()) ); indices.z = nextNeighbor.Index; water.AddTriangleCellData(indices, weights1, weights2, weights3); } } }
private void RightTrangulateConnection(HexDirectionEnum direction, HexCell cell, Vector3 v1, Vector3 v2) { HexCell neighbor = cell.GetNeighbor(direction); if (neighbor == null) { NoNeighborConnection(direction, cell, v1, v2); return; } Vector3 bridge = HexMetrics.GetTwoBridge(direction); Vector3 v3 = v1 + bridge; Vector3 v4 = v2 + bridge; AddQuad(v1, v2, v3, v4); AddQuadColor(cell.color, neighbor.color); HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { AddTriangle(v2, v4, v2 + HexMetrics.GetTwoBridge(direction.Next())); AddTriangleColor(cell.color, neighbor.color, nextNeighbor.color); } else { //绘制缺失的小三角 AddTriangle(v2, v4, cell.center + HexMetrics.GetSecondConrner(direction)); AddTriangleColor(cell.color, neighbor.color, (cell.color + neighbor.color) * 0.5f); } //绘制缺失的小三角 HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()); if (prevNeighbor == null) { AddTriangle(v1, cell.center + HexMetrics.GetFirstCorner(direction), v3); AddTriangleColor(cell.color, (cell.color + cell.color + neighbor.color) / 3f, neighbor.color); } }
/// <summary> /// Creates the triangles for a side of the hexagon, when there is a river in the hex. /// </summary> void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } // Determine center by finding river channel center edge if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.InnerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(direction.Previous2())) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2())) { center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); TriangulateEdgeFan(center, m, cell.Index); // If possible add any features if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { Features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
void AddWallSegment( Vector3 nearLeft, Vector3 farLeft, Vector3 nearRight, Vector3 farRight ) { nearLeft = HexMetrics.Perturb(nearLeft); farLeft = HexMetrics.Perturb(farLeft); nearRight = HexMetrics.Perturb(nearRight); farRight = HexMetrics.Perturb(farRight); Vector3 left = HexMetrics.WallLerp(nearLeft, farLeft); Vector3 right = HexMetrics.WallLerp(nearRight, farRight); Vector3 leftThicknessOffset = HexMetrics.WallThicknessOffset(nearLeft, farLeft); Vector3 rightThicknessOffset = HexMetrics.WallThicknessOffset(nearRight, farRight); float leftTop = left.y + HexMetrics.wallHeight; float rightTop = right.y + HexMetrics.wallHeight; Vector3 v1, v2, v3, v4; v1 = v3 = left - leftThicknessOffset; v2 = v4 = right - rightThicknessOffset; v3.y = leftTop; v4.y = rightTop; walls.AddQuadUnperturbed(v1, v2, v3, v4); Vector3 t1 = v3, t2 = v4; v1 = v3 = left + leftThicknessOffset; v2 = v4 = right + rightThicknessOffset; v3.y = leftTop; v4.y = rightTop; walls.AddQuadUnperturbed(v2, v1, v4, v3); walls.AddQuadUnperturbed(t1, t2, v3, v4); }
private void InitGhostCell() { Debug.Log("Scaling ghost cell"); ghostCellPrefab = GameObject.Instantiate(ghostCellPrefab); //Scale the cell so it is the correct size Vector3 targetSize = new Vector3(HexMetrics.ScaledInnerRadius(terrain) * 2, HexMetrics.ScaledHeight(terrain), HexMetrics.ScaledOuterRadius(terrain) * 2); GameUtils.ScaleGameObjectToSize(ghostCellPrefab, targetSize); //Set the initial position of the ghost cell ghostCellPrefab.transform.position = terrain.transform.position; //Apply the ghost material to the ghost cell MeshRenderer ghostRenderer = ghostCellPrefab.GetComponent <MeshRenderer>(); Material[] ghostMaterials = new Material[ghostRenderer.materials.Length]; for (int i = 0; i < ghostMaterials.Length; i++) { ghostMaterials[i] = ghostMaterial; } ghostRenderer.materials = ghostMaterials; }
public override void Triangulate(HexMesh mesh) { float lerpCoef = (float)(leftCell.Elevation - beginCell.Elevation) / (rightCell.Elevation - beginCell.Elevation); if (lerpCoef < 0) { lerpCoef = -lerpCoef; } Vector3 boundary = Vector3.Lerp(HexMetrics.Perturb(beginCorner), HexMetrics.Perturb(rightCorner), lerpCoef); Color boundaryColor = Color.Lerp(beginCell.Color, rightCell.Color, lerpCoef); Corner.TriangulateBoundaryTriangle(mesh, beginCorner, beginCell, leftCorner, leftCell, boundary, boundaryColor); if (HexMetrics.GetEdgeType(leftCell.Elevation, rightCell.Elevation) == HexEdgeType.Slope) { Corner.TriangulateBoundaryTriangle(mesh, leftCorner, leftCell, rightCorner, rightCell, boundary, boundaryColor); } else { mesh.AddTriangle(HexMetrics.Perturb(leftCorner), HexMetrics.Perturb(rightCorner), boundary, false); mesh.AddTriangleColor(leftCell.Color, rightCell.Color, boundaryColor); } }
private void TriangulateConnection(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e1) { HexCell neighbor = cell.GetNeighbor(direction); if (neighbor == null) { return; } Vector3 bridge = HexMetrics.GetBridge(direction); EdgeVertices e2 = new EdgeVertices(e1.v1 + bridge, e1.v4 + bridge); TriangulateEdgeStrip(e1, e2, cell.color, neighbor.color); HexDirection nextDirection = direction.Next(); HexCell nextNeighbor = cell.GetNeighbor(nextDirection); if (direction <= HexDirection.E && nextNeighbor != null) { AddTriangle(e1.v4, e2.v4, e1.v4 + HexMetrics.GetBridge(nextDirection)); AddTriangleColor(cell.color, neighbor.color, nextNeighbor.color); } }
void Precalculation(HexCell cell) { cell.Center = cell.WaterCenter = cell.transform.localPosition; cell.WaterCenter.y = HexMetrics.WaterSurfaceY; for (int i = 0; i <= 5; i++) { var direction = (HexDirection)i; cell.Edges[i] = new EdgeVertices( cell.Center + HexMetrics.GetLeftSolidCorner(direction), cell.Center + HexMetrics.GetRightSolidCorner(direction)); if (cell.HasRiver && cell.HasRiverThroughEdge(direction)) { cell.Edges[i].V3.y = cell.StreamBedY; } cell.WaterEdges[i] = new EdgeVertices( cell.WaterCenter + HexMetrics.GetLeftWaterCorner(direction), cell.WaterCenter + HexMetrics.GetRightWaterCorner(direction)); } }
/// <summary> /// 三角化瀑布 /// </summary> /// <param name="v1">从瀑布上方,自上而下看,上方左边的顶点</param> /// <param name="v2">上右顶点</param> /// <param name="v3">下左顶点</param> /// <param name="v4">下右顶点</param> /// <param name="y1">上方所在六边形河流高度</param> /// <param name="y2">下方所在六边形河流高度</param> /// <param name="waterY">下方水平面高度</param> void TriangulateWaterfallInWater(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, float y1, float y2, float waterY, Vector3 indices) { // 让桥边线顶点高度变成河流高度 v1.y = v2.y = y1; v3.y = v4.y = y2; // 由于底部顶点的位置已经改变了,它们和原始顶点受微扰的程度不一样。 // 这意味着最后的结果和原始瀑布不相符。为了解决这个问题,我们需要在插值前手动微扰顶点,然后加上一个未被微扰的四边形。 v1 = HexMetrics.Perturb(v1); v2 = HexMetrics.Perturb(v2); v3 = HexMetrics.Perturb(v3); v4 = HexMetrics.Perturb(v4); // 用插值的方法获得v3->v1向量、v4->v2向量与水平面的交点 float t = (waterY - y2) / (y1 - y2); v3 = Vector3.Lerp(v3, v1, t); v4 = Vector3.Lerp(v4, v2, t); rivers.AddQuadUnperturbed(v1, v2, v3, v4); rivers.AddQuadUV(0f, 1f, 0.8f, 1f); rivers.AddQuadCellData(indices, weights1, weights2); }
void TriangulateBoundaryTriangle(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 boundary, Color boundaryColor) { Vector3 v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, 1)); Color c2 = HexMetrics.TerraceLerp(beginCell.Color, leftCell.Color, 1); terrain.AddTriangleUnperturbed(HexMetrics.Perturb(begin), v2, boundary); terrain.AddTriangleColor(beginCell.Color, c2, boundaryColor); for (int i = 2; i < HexMetrics.terraceSteps; i++) { Vector3 v1 = v2; Color c1 = c2; v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, i)); c2 = HexMetrics.TerraceLerp(beginCell.Color, leftCell.Color, i); terrain.AddTriangleUnperturbed(v1, v2, boundary); terrain.AddTriangleColor(c1, c2, boundaryColor); } terrain.AddTriangleUnperturbed(v2, HexMetrics.Perturb(left), boundary); terrain.AddTriangleColor(c2, leftCell.Color, boundaryColor); }
public void TriangulateCornerCliffTerraces(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { float b = Mathf.Abs(1f / (leftCell.Elevation - beginCell.Elevation)); Vector3 boundary = Vector3.Lerp(HexMetrics.PerturbVector(begin), HexMetrics.PerturbVector(left), b); Color boundaryWeights = Color.Lerp(Weights1, Weights2, b); Vector3 indices; indices.x = beginCell.TerrainTypeIndex; indices.y = leftCell.TerrainTypeIndex; indices.z = rightCell.TerrainTypeIndex; TriangulateBoundaryTriangle(right, rightCell, begin, beginCell, boundary, boundaryWeights, indices); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle(left, leftCell, right, rightCell, boundary, boundaryWeights, indices); } else { Terrain.AddTriangleUnperturbed(HexMetrics.PerturbVector(left), HexMetrics.PerturbVector(right), boundary); Terrain.AddTriangleCellData(indices, Weights1, Weights2, boundaryWeights); } }
private void TriangulateEdgeTerraces(EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad) { var e2 = EdgeVertices.TerraceLerp(begin, end, 1); var w2 = HexMetrics.TerraceLerp(weights1, weights2, 1); var i1 = beginCell.Index; var i2 = endCell.Index; TriangulateEdgeStrip(begin, weights1, i1, e2, w2, i2, hasRoad); for (var i = 2; i < HexMetrics.terraceSteps; i++) { var e1 = e2; var c1 = w2; e2 = EdgeVertices.TerraceLerp(begin, end, i); w2 = HexMetrics.TerraceLerp(weights1, weights2, i); TriangulateEdgeStrip(e1, c1, i1, e2, w2, i2, hasRoad); } TriangulateEdgeStrip(e2, w2, i1, end, weights2, i2, hasRoad); }
protected static void TriangulateBoundaryTriangle( HexMesh mesh, Vector3 beginCorner, HexCell beginCell, Vector3 leftCorner, HexCell leftCell, Vector3 boundary, Color boundaryColor ) { Vector3 v1 = beginCorner; Color c1 = beginCell.Color; for (int step = 1; step < HexMetrics.terraceSteps + 1; ++step) { Vector3 v3 = HexMetrics.TerraceLerp(beginCorner, leftCorner, step); Color c3 = HexMetrics.ColorLerp(beginCell.Color, leftCell.Color, step); mesh.AddTriangle(HexMetrics.Perturb(v1), HexMetrics.Perturb(v3), boundary, false); mesh.AddTriangleColor(c1, c3, boundaryColor); v1 = v3; c1 = c3; } }
/// <summary> /// 通过世界内的一个点(vector3),经过彩色噪点图扰动后,返回扰动后的Vect3 /// </summary> /// <param name="position">世界坐标内的点</param> /// <returns>经过噪点图扰动后的点坐标</returns> private Vector3 Perturb(Vector3 position) { //利用世界空间内一点,在彩色噪点图上进行采样,得到彩色噪点图内一点的RGBA信息 Vector4 sample = HexMetrics.SampleNoise(position); //使用原始坐标加上噪点图的采样坐标,得到扰动后坐标 //position.x += sample.x; //position.y += sample.y; //position.z += sample.z; //将采样后的扰动结果控制在1到-1之间 //position.x += sample.x * 2f - 1f; //position.y += sample.y * 2f - 1f; //position.z += sample.z * 2f - 1f; //增加了每个点的扰动强度 position.x += (sample.x * 2f - 1f) * HexMetrics.cellPerturbStrength; //为了让cell表面变得平坦,这里不再在垂直方向上进行扰动。 //position.y += (sample.y * 2f - 1f) * HexMetrics.cellPerturbStrength; position.z += (sample.z * 2f - 1f) * HexMetrics.cellPerturbStrength; return(position); }
//绘制绝壁三角 private void TriangulateCornerTerracesCliff(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { float b = Mathf.Abs(1f / (rightCell.Elevation - beginCell.Elevation)); Vector3 boundary = Vector3.Lerp(HexMetrics.Perturb(begin), HexMetrics.Perturb(right), b); Color boundaryWeights = Color.Lerp(weights1, weights3, b); Vector3 indices; indices.x = beginCell.Index; indices.y = leftCell.Index; indices.z = rightCell.Index; TriangulateBoundaryTriangle(begin, weights1, left, weights2, boundary, boundaryWeights, indices); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle(left, weights2, right, weights3, boundary, boundaryWeights, indices); } else { AddTerrainTriangle(HexMetrics.Perturb(left), HexMetrics.Perturb(right), boundary); terrain.AddTriangleCellData(indices, weights2, weights3, boundaryWeights); } }
void TriangulateEdgeTerraces(EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad) { EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); Color c2 = HexMetrics.TerraceLerp(color1, color2, 1); float t1 = beginCell.TerrainTypeIndex; float t2 = endCell.TerrainTypeIndex; // bottom quad TriangulateEdgeStrip(begin, color1, t1, e2, c2, t2, hasRoad); for (int i = 2; i < HexMetrics.terraceSteps; i++) { EdgeVertices e1 = e2; Color c1 = c2; e2 = EdgeVertices.TerraceLerp(begin, end, i); c2 = HexMetrics.TerraceLerp(color1, color2, i); TriangulateEdgeStrip(e1, c1, t1, e2, c2, t2, hasRoad); } // final quad TriangulateEdgeStrip(e2, c2, t1, end, color2, t2, hasRoad); }
void TriangulateEdgeTerraces( EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell ) { EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); Color c2 = HexMetrics.TerraceLerp(color1, color2, 1); float t1 = (float)beginCell.TerrainType; float t2 = (float)endCell.TerrainType; TriangulateEdgeStrip(begin, color1, t1, e2, c2, t2); for (int i = 2; i < HexMetrics.terraceSteps; i++) { EdgeVertices e1 = e2; Color c1 = c2; e2 = EdgeVertices.TerraceLerp(begin, end, i); c2 = HexMetrics.TerraceLerp(color1, color2, i); TriangulateEdgeStrip(e1, c1, t1, e2, c2, t2); } TriangulateEdgeStrip(e2, c2, t1, end, color2, t2); }
/// <summary> /// Creates geometry for connecting terraces with a cliff. /// </summary> void TriangulateBoundaryTriangle(Vector3 begin, Color beginWeights, Vector3 left, Color leftWeights, Vector3 boundary, Color boundaryWeights, Vector3 indices) { Vector3 v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, 1)); Color w2 = HexMetrics.TerraceLerp(beginWeights, leftWeights, 1); // Boundary must not suffer from noise or terraces and cliffs are impossible to merge // Use AddTriangleUnperturbed and perturb vertices other than boundary, v2 is perturbed at creation Terrain.AddTriangleUnperturbed(HexMetrics.Perturb(begin), v2, boundary); Terrain.AddTriangleCellData(indices, beginWeights, w2, boundaryWeights); for (int i = 2; i < HexMetrics.TerraceSteps; i++) { Vector3 v1 = v2; Color w1 = w2; v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, i)); w2 = HexMetrics.TerraceLerp(beginWeights, leftWeights, i); Terrain.AddTriangleUnperturbed(v1, v2, boundary); Terrain.AddTriangleCellData(indices, w1, w2, boundaryWeights); } Terrain.AddTriangleUnperturbed(v2, HexMetrics.Perturb(left), boundary); Terrain.AddTriangleCellData(indices, w2, leftWeights, boundaryWeights); }
void TriangulateBoundaryTriangle( Vector3 begin, Color beginWeights, Vector3 left, Color leftWeights, Vector3 boundary, Color boundaryWeights, Vector3 indices) { Vector3 v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, 1)); Color w2 = HexMetrics.TerraceLerp(beginWeights, leftWeights, 1); terrain.AddTriangleUnperturbed(HexMetrics.Perturb(begin), v2, boundary); terrain.AddTriangleCellData(indices, beginWeights, w2, boundaryWeights); for (int i = 2; i < HexMetrics.terraceSteps; i++) { Vector3 v1 = v2; Color w1 = w2; v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, i)); w2 = HexMetrics.TerraceLerp(beginWeights, leftWeights, i); terrain.AddTriangleUnperturbed(v1, v2, boundary); } terrain.AddTriangleUnperturbed(v2, HexMetrics.Perturb(left), boundary); terrain.AddTriangleCellData(indices, w2, leftWeights, boundaryWeights); }
/// <summary> /// 构建阶梯状连接区域 /// 这里不再使用单一的顶点,而是直接使用cell与阶梯区域相连接的边,通过计算得出边上的顶点位置以及每个顶点的颜色 /// </summary> /// <param name="begin">第一个cell与相邻阶梯化区域的边上顶点</param> /// <param name="beginCell">第一个cell的实例</param> /// <param name="end">第二个cell与相邻阶梯化区域的边上顶点</param> /// <param name="endCell">第二个cell的实例</param> private void TriangulateEdgeTerraces(EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell) { //通过插值计算出相邻cell边的每个坐标点 EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); //通过插值计算出相邻cell边每个坐标点的颜色 Color c2 = HexMetrics.TerraceLerp(beginCell.Color, endCell.Color, 1); //构建阶梯的第一段 TriangulateEdgeStrip(begin, beginCell.Color, e2, c2); //循环生成中间部分 for (int i = 2; i < HexMetrics.terraceSteps; i++) { EdgeVertices e1 = e2; Color c1 = c2; e2 = EdgeVertices.TerraceLerp(begin, end, i); c2 = HexMetrics.TerraceLerp(beginCell.Color, endCell.Color, i); TriangulateEdgeStrip(e1, c1, e2, c2); } //构建阶梯的最后一段 TriangulateEdgeStrip(e2, c2, end, endCell.Color); }
//绘制斜坡小三角 private void TriangulateCornerTerraces(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { Vector3 v3 = begin; Vector3 v4 = begin; Color w3 = weights1; Color w4 = weights1; Vector3 indices; indices.x = beginCell.Index; indices.y = leftCell.Index; indices.z = rightCell.Index; for (int i = 1; i <= HexMetrics.terraceSetps; i++) { Vector3 v1 = v3; Vector3 v2 = v4; Color w1 = w3; Color w2 = w4; v3 = HexMetrics.TerraceLerp(begin, left, i); v4 = HexMetrics.TerraceLerp(begin, right, i); w3 = HexMetrics.TerraceLerp(weights1, weights2, i); w4 = HexMetrics.TerraceLerp(weights1, weights3, i); if (v1 == v2) { AddTerrainPerturTriangle(v1, v3, v4); terrain.AddTriangleCellData(indices, w1, w3, w4); } else { AddTerrainQuad(v1, v2, v3, v4); terrain.AddQuadCellData(indices, w1, w2, w3, w4); } } }
/// <summary> /// 制作角落的梯田坡 /// 三个六边形组成的角落,只有一种高度变化,形成的梯田型的角落 /// </summary> /// <param name="begin"></param> /// <param name="beginCell"></param> /// <param name="left"></param> /// <param name="leftCell"></param> /// <param name="right"></param> /// <param name="rightCell"></param> void TriangulateCornerTerraces( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { //角落梯田第一步数,是个三角面--------- Vector3 v3 = HexMetrics.TerraceLerp(begin, left, 1); Vector3 v4 = HexMetrics.TerraceLerp(begin, right, 1); Color c3 = HexMetrics.TerraceLerp(beginCell.Color, leftCell.Color, 1); Color c4 = HexMetrics.TerraceLerp(beginCell.Color, rightCell.Color, 1); terrain.AddTriangle(begin, v3, v4); terrain.AddTriangleColor(beginCell.Color, c3, c4); //---------------------------------- //中间步数梯田,是矩形面片---------------------- for (int i = 2; i < HexMetrics.terraceSteps; i++) { Vector3 v1 = v3; Vector3 v2 = v4; Color c1 = c3; Color c2 = c4; v3 = HexMetrics.TerraceLerp(begin, left, i); v4 = HexMetrics.TerraceLerp(begin, right, i); c3 = HexMetrics.TerraceLerp(beginCell.Color, leftCell.Color, i); c4 = HexMetrics.TerraceLerp(beginCell.Color, rightCell.Color, i); terrain.AddQuad(v1, v2, v3, v4); terrain.AddQuadColor(c1, c2, c3, c4); } //------------------------------------------- //最后一步数矩形梯田------------------------- terrain.AddQuad(v3, v4, left, right); terrain.AddQuadColor(c3, c4, leftCell.Color, rightCell.Color); //------------------------------------- }
void Triangulate(HexDirection direction, HexCell cell) { //纯色区域三角化使用单一颜色 Vector3 center = cell.transform.localPosition; Vector3 v1 = center + HexMetrics.GetFirstSolidCorner(direction); Vector3 v2 = center + HexMetrics.GetSecondSolidCorner(direction); AddTriangle(center, v1, v2); AddTriangleColor(cell.color); //梯形混色区域 Vector3 bridge = HexMetrics.GetBridge(direction); Vector3 v3 = v1 + bridge; Vector3 v4 = v2 + bridge; AddQuad(v1, v2, v3, v4); HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell; HexCell neighbor = cell.GetNeighbor(direction) ?? cell; HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell; AddQuadColor(cell.color, (cell.color + prevNeighbor.color + neighbor.color) * 0.5f); //补上被剔除的两个三角形(第一个三角形三个顶点的颜色分别是v1本色,2三个六边形混色,3桥色) Color bridgeColor = (cell.color + neighbor.color) * 0.5f; // AddQuadColor(cell.color, bridgeColor); AddTriangle(v1, center + HexMetrics.GetFirstCorner(direction), v3); AddExcludedTriangleColor( cell.color, (cell.color + prevNeighbor.color + neighbor.color) / 3f, bridgeColor); AddTriangle(v2, v4, center + HexMetrics.GetSecondCorner(direction)); AddExcludedTriangleColor( cell.color, bridgeColor, (cell.color + neighbor.color + nextNeighbor.color) / 3f ); }
public static Mesh CreateMesh(float size) { var vertices = new List <Vector3>(); var uv = new List <Vector2>(); var triangles = new List <int>(); vertices.Add(Vector3.zero); uv.Add(Vector2.zero); foreach (var corner in HexMetrics.HexCorners(size)) { vertices.Add(corner); uv.Add(Vector2.one); } for (int i = 1; i < HexMetrics.CornerNums; i++) { triangles.Add(0); triangles.Add(i); triangles.Add(i + 1); } // 循环一周 triangles.Add(0); triangles.Add(HexMetrics.CornerNums); triangles.Add(1); var mesh = new Mesh(); mesh.vertices = vertices.ToArray(); mesh.uv = uv.ToArray(); mesh.triangles = triangles.ToArray(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); return(mesh); }
public static IntVector2 GetGridOffset (HexMetrics.Direction direction) { switch (direction) { case HexMetrics.Direction.Up: return new IntVector2( 0, 1); case HexMetrics.Direction.RightUp: return new IntVector2( 1, 0); case HexMetrics.Direction.RightDown: return new IntVector2( 1,-1); case HexMetrics.Direction.Down: return new IntVector2( 0,-1); case HexMetrics.Direction.LeftDown: return new IntVector2(-1, 0); case HexMetrics.Direction.LeftUp: return new IntVector2(-1, 1); } return null; // return new Dictionary<HexMetrics.Direction, System.Func<IntVector2>>() // { // {HexMetrics.Direction.Up, () => new IntVector2( 0, 1)}, // {HexMetrics.Direction.RightUp, () => new IntVector2( 1, 0)}, // {HexMetrics.Direction.RightDown,() => new IntVector2( 1,-1)}, // {HexMetrics.Direction.Down, () => new IntVector2( 0,-1)}, // {HexMetrics.Direction.LeftDown, () => new IntVector2(-1, 0)}, // {HexMetrics.Direction.LeftUp, () => new IntVector2(-1, 1)} // // } }
public Vector2 GetDirection (HexMetrics.Direction direction) { return new Dictionary<HexMetrics.Direction, System.Func<Vector2>>() { {HexMetrics.Direction.Up, () => Up}, {HexMetrics.Direction.RightUp, () => RightUp}, {HexMetrics.Direction.RightDown,() => RightDown}, {HexMetrics.Direction.Down, () => -Up}, {HexMetrics.Direction.LeftDown, () => -RightUp}, {HexMetrics.Direction.LeftUp, () => -RightDown} }[direction](); }
public static HexMetrics.Direction Reverse(HexMetrics.Direction direction) { return ReverseDirection(direction); }
//========================================================================================= #region Direction Functions /* * SimulationOrientation - Orientation the cell is oriented relative to up * RelativeDirection - a direction relative to SimulationOrientation * AbsoluteDirection - a direction relative to Up * * */ public void RotatateSimulationOrientation(HexMetrics.Direction offset) { RotatateSimulationOrientation((int)offset); }
public static int RotationDifference(HexMetrics.Direction a) { return RotationDifference(a, HexMetrics.Direction.Up); }
public static int RotationDifference(HexMetrics.Direction a, HexMetrics.Direction b) { HexMetrics.Direction diff = (HexMetrics.Direction)((int)a-(int)b); return (((int)diff+3)%6)-3; }
public HexMetrics.Direction Absolute(HexMetrics.Direction relativeDirection) { return AbsoluteDirectionFromRelative(relativeDirection); }
// public GrabbablePart GetConnectedPartAtRelative(HexMetrics.Direction relativeDirection) // { // return _connectedParts[Absolute(relativeDirection)].connectedPart; // } public GrabbablePart GetConnectedPart(HexMetrics.Direction relativeDirection) { return _connectedParts[(int)relativeDirection].connectedPart; }
public HexMetrics.Direction AbsoluteDirectionFromRelative(HexMetrics.Direction relativeDirection) { return (HexMetrics.Direction)( ((int)relativeDirection + (int)SimulationOrientation) % 6); }
// public void ConnectPartAndPlaceAtAbsoluteDirection(GrabbablePart otherPart, PhysicalConnectionType connectionType, HexMetrics.Direction absoluteDirection) // { // ConnectPartAndPlaceAtRelativeDirection(otherPart, connectionType, Relative(absoluteDirection)); // } public void ConnectPartAndPlaceAtRelativeDirection(GrabbablePart otherPart, PhysicalConnectionType connectionType, HexMetrics.Direction relativeDirection) { HexMetrics.Direction absoluteDirection = Absolute(relativeDirection); ConnectionDescription connDesc = _connectedParts[(int)relativeDirection]; connDesc.connectedPart = otherPart; // connect the part ConnectionDescription otherConnDesc = otherPart._connectedParts[(int)ConnectedsOpposite(relativeDirection)]; // get the other parts opposite side that is connected to this otherConnDesc.connectedPart = this; // connect that side connDesc.connectedPart.transform.position = transform.position + (Vector3)GameSettings.instance.hexCellPrefab.GetDirection(absoluteDirection); SetPhysicalConnection(relativeDirection, connectionType); if (ParentConstruction != null) { // Debug.Log("Adding to construction "+ParentConstruction.name); ParentConstruction.AddToConstruction(otherPart); } }
public void SetAuxilaryConnections(HexMetrics.Direction relativeDirection, int newConnectionTypes) { ConnectionDescription connDesc = _connectedParts[(int)relativeDirection]; if (connDesc.connectedPart == null) { connDesc.auxConnectionTypes = 0; return; } HexMetrics.Direction oppositeDirection = ConnectedsOpposite(relativeDirection); ConnectionDescription otherConnDesc = connDesc.connectedPart._connectedParts[(int)oppositeDirection]; bool weldableHere = Weldable(relativeDirection); bool weldabelThere = connDesc.connectedPart.Weldable(oppositeDirection); if (weldableHere && weldabelThere) { connDesc.auxConnectionTypes = newConnectionTypes; otherConnDesc.auxConnectionTypes = newConnectionTypes; } else { connDesc.auxConnectionTypes = 0; otherConnDesc.auxConnectionTypes = 0; } }
public HexMetrics.Direction ConnectedsOpposite(HexMetrics.Direction relativeDirection) { return ConnectedPartsOppositeDirection(relativeDirection); }
public int GetAuxilaryConnectionTypes(HexMetrics.Direction relativeDirection) { if (GetConnectedPart(relativeDirection) == null) { return 0; } return _connectedParts[(int)relativeDirection].auxConnectionTypes; }
public HashSet<Construction> SetPhysicalConnection(HexMetrics.Direction relativeDirection, PhysicalConnectionType newConnectionType, SplitOptions splitOption) { ConnectionDescription connDesc = _connectedParts[(int)relativeDirection]; // PhysicalConnectionType originalConnection = connDesc.connectionType; if (connDesc.connectedPart == null) { // disconnecting part connDesc.connectionType = PhysicalConnectionType.None; SetWeldSprite(relativeDirection, false); if (ParentConstruction != null) { if (splitOption == SplitOptions.SplitIfNecessary) { return ParentConstruction.CheckForSplitsOrJoins(); } return new HashSet<Construction> { ParentConstruction }; } return new HashSet<Construction> (); } HexMetrics.Direction oppositeDirection = ConnectedsOpposite(relativeDirection); ConnectionDescription otherConnDesc = connDesc.connectedPart._connectedParts[(int)oppositeDirection]; bool weldableHere = Weldable(relativeDirection); bool weldableThere = connDesc.connectedPart.Weldable(oppositeDirection); // Debug.Log("Checking weldability: "+direction+"("+weldableHere+") <-> "+oppositeDirection+"("+weldabelThere+")"); if (weldableHere && weldableThere) { connDesc.connectionType = newConnectionType; otherConnDesc.connectionType = newConnectionType; } else { connDesc.connectionType = PhysicalConnectionType.None; otherConnDesc.connectionType = PhysicalConnectionType.None; } // update the weld sprites SetWeldSprite(relativeDirection, connDesc.connectionType != PhysicalConnectionType.None); connDesc.connectedPart.SetWeldSprite(oppositeDirection, connDesc.connectionType != PhysicalConnectionType.None); //if we are disconnecting the side (None) or if it's not weldable, make sure that the parts are not connected if (connDesc.connectionType == PhysicalConnectionType.None) { otherConnDesc.connectedPart = null; connDesc.connectedPart = null; if (ParentConstruction == null) { Debug.LogWarning ("Parent is null!"); } else { // check that by disconnecting a side, we have not split the construction up if (splitOption == SplitOptions.SplitIfNecessary) { return ParentConstruction.CheckForSplitsOrJoins(); } return new HashSet<Construction> { ParentConstruction }; } } if (ParentConstruction != null) { return new HashSet<Construction> { ParentConstruction }; } return new HashSet<Construction>(); }
public HashSet<Construction> SetPhysicalConnection(HexMetrics.Direction relativeDirection, PhysicalConnectionType newConnectionType) { return SetPhysicalConnection(relativeDirection, newConnectionType, SplitOptions.SplitIfNecessary); }
private void SetWeldSprite(HexMetrics.Direction relativeDirection, bool show) { GameObject weldSprite = _weldSpriteObjects[(int)relativeDirection]; if (weldSprite != null) { weldSprite.transform.localScale = Vector3.one * (show ? 1 : 0); } }
public PhysicalConnectionType GetPhysicalConnectionType(HexMetrics.Direction relativeDirection) { if (GetConnectedPart(relativeDirection) == null) { return PhysicalConnectionType.None; } return _connectedParts[(int)relativeDirection].connectionType; }
public static HexMetrics.Direction ReverseDirection(HexMetrics.Direction direction) { return (HexMetrics.Direction)( ((int)direction+3)%6 ); }
public HexMetrics.Direction ConnectedPartsOppositeDirection(HexMetrics.Direction relativeDirection) { GrabbablePart connectedPart = GetConnectedPart(relativeDirection); if (connectedPart == null) return (HexMetrics.Direction)(-1); return OtherPartsOppositeDirection(relativeDirection, connectedPart); }
public HexMetrics.Direction RelativeDirectionFromAbsolute(HexMetrics.Direction absoluteDirection) { return (HexMetrics.Direction)( ((int)absoluteDirection + 6 - (int)SimulationOrientation) % 6); }
public HashSet<Construction> SetSimulationOrientation(HexMetrics.Direction orientation) { for (int i = 0 ; i < 6 ; i++) { if ( _connectedParts[i] == null) { _connectedParts[i] = new ConnectionDescription(); } } // adjacent.ForEach((obj) => obj.parent = null); int directionChange = ((int)orientation - (int)SimulationOrientation + 6)%6; transform.rotation = Quaternion.Euler(0, 0, (int)orientation * -60); ConnectionDescription [] newParts = new ConnectionDescription [6]; PhysicalConnectionType [] physicalConnections = new PhysicalConnectionType [6]; int [] auxilaryConnections = new int [6]; // adjacent.ForEach((obj) => obj.parent = transform); for (int i = 0 ; i < 6 ; i++) { int newDirection = (i+directionChange)%6; newParts[i] = _connectedParts[newDirection]; physicalConnections[i] = _connectedParts[newDirection].connectionType; auxilaryConnections[i] = _connectedParts[newDirection].auxConnectionTypes; } for (int i = 0 ; i < 6 ; i++) { int newDirection = (i+directionChange)%6; _connectedParts[i] = newParts[i]; if (_connectedParts[i].connectedPart == null) { physicalConnections[i] = PhysicalConnectionType.None; auxilaryConnections[i] = 0; } // Debug.Log ("Replacing Connection ("+(HexMetrics.Direction)newDirection+") "+ _connectedParts[i].connectionType +" -> ("+(HexMetrics.Direction)i+") " + physicalConnections[i]); SetPhysicalConnection((HexMetrics.Direction)i, physicalConnections[i], SplitOptions.DoNotSplit); SetAuxilaryConnections((HexMetrics.Direction)i, auxilaryConnections[i]); } if (ParentConstruction != null) { return ParentConstruction.CheckForSplitsOrJoins(); } return new HashSet<Construction>(); }
public GrabberState(HexMetrics.Direction dir, int ext, bool clampOpen) { direction = dir; extention = ext; this.clampOpen = clampOpen; rotation = 0; }
public int SimulationRotationDifference(HexMetrics.Direction other) { return RotationDifference(SimulationOrientation, other); }
public IEnumerable<HexMetrics.Direction> IsWeldableWithRotationFactor (HexMetrics.Direction relativeDirection, GrabbablePart otherPart) { for (int i = 0 ; i < 6 ; i++) { HexMetrics.Direction iDir = (HexMetrics.Direction)i; if (IsWeldable(relativeDirection, otherPart, iDir)) { yield return iDir; } } }
public HexMetrics.Direction OtherPartsOppositeDirection(HexMetrics.Direction relativeDirection, GrabbablePart otherPart) { return ReverseDirection( otherPart.RelativeDirectionFromAbsolute(AbsoluteDirectionFromRelative(relativeDirection))); }
public bool IsWeldable (HexMetrics.Direction relativeDirection, GrabbablePart otherPart) { return IsWeldable(relativeDirection, otherPart, (HexMetrics.Direction)0); }
public bool IsWeldable (HexMetrics.Direction relativeDirection, GrabbablePart otherPart, HexMetrics.Direction rotationFactor) { // relativeDirection = (HexMetrics.Direction)(((int)relativeDirection+(int)rotationFactor+6)%6); if (otherPart == null) return false; HexMetrics.Direction oppositeDirection = OtherPartsOppositeDirection(relativeDirection, otherPart); oppositeDirection = (HexMetrics.Direction)(((int)oppositeDirection+(int)rotationFactor+6)%6); // what if we were to rotate the other part? // ConnectionDescription otherConnDesc = connDesc.connectedPart._connectedParts[(int)oppositeDirection]; bool weldableHere = Weldable(relativeDirection); bool weldabelThere = otherPart.Weldable(oppositeDirection); // Debug.Log("Checking weldability: "+direction+"("+weldableHere+") <-> "+oppositeDirection+"("+weldabelThere+")"); return weldableHere && weldabelThere; }
public GrabbablePart RemoveConnectedPart(HexMetrics.Direction relativeDirection) { GrabbablePart ret = _connectedParts[(int)relativeDirection].connectedPart; // if ( transform.parent != null && ret != null && ret.transform == transform.parent ) // { // transform.parent = null; // } _connectedParts[(int)relativeDirection].connectedPart = null; _connectedParts[(int)relativeDirection].connectionType = PhysicalConnectionType.None; _connectedParts[(int)relativeDirection].auxConnectionTypes = 0; return ret; }
public HexMetrics.Direction Relative(HexMetrics.Direction absoluteDirection) { return RelativeDirectionFromAbsolute(absoluteDirection); }