protected static void TriangulateQuad(HexMesh mesh, EdgeVertices e1, EdgeVertices e2, Color c1, Color c2) { mesh.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); mesh.AddQuadColor(c1, c1, c2, c2); mesh.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); mesh.AddQuadColor(c1, c1, c2, c2); mesh.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); mesh.AddQuadColor(c1, c1, c2, c2); mesh.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); mesh.AddQuadColor(c1, c1, c2, c2); }
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); }
private void TriangulateEdgeStrip(EdgeVertices e1, Color c1, EdgeVertices e2, Color c2, bool hasWall = false) { _terrain.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); _terrain.AddQuadColor(c1, c2); _terrain.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); _terrain.AddQuadColor(c1, c2); _terrain.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); _terrain.AddQuadColor(c1, c2); _terrain.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); _terrain.AddQuadColor(c1, c2); if (hasWall) { TriangulateWallSegment(e1.v2, e1.v3, e1.v4, e2.v2, e2.v3, e2.v4); } }
public override void Triangulate(HexMesh mesh) { Vector3 v1 = beginCorner; Vector3 v2 = beginCorner; Color c1 = beginCell.Color; Color c2 = beginCell.Color; for (int step = 1; step < HexMetrics.terraceSteps + 1; ++step) { Vector3 v3 = HexMetrics.TerraceLerp(beginCorner, leftCorner, step); Vector3 v4 = HexMetrics.TerraceLerp(beginCorner, rightCorner, step); Color c3 = HexMetrics.ColorLerp(beginCell.Color, leftCell.Color, step); Color c4 = HexMetrics.ColorLerp(beginCell.Color, rightCell.Color, step); if (step == 1) { mesh.AddTriangle(v1, v3, v4); mesh.AddTriangleColor(c1, c3, c4); } else { mesh.AddQuad(v1, v2, v3, v4); mesh.AddQuadColor(c1, c2, c3, c4); } v1 = v3; v2 = v4; c1 = c3; c2 = c4; } }
void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.kInnerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.kInnerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddTriangleColor(cell.Color); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuadColor(cell.Color); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddQuadColor(cell.Color); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(cell.Color); if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, cell.RiverSurfaceY, 0.5f, HexMetrics.kRiverSolidUVStep, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, cell.RiverSurfaceY, 0.5f + HexMetrics.kRiverSolidUVStep, HexMetrics.kRiverSolidUVStep, reversed); } }
void TriangulateEdgeStrip(EdgeVertices e1, Color c1, EdgeVertices e2, Color c2) { terrain.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); terrain.AddQuadColor(c1, c2); terrain.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); terrain.AddQuadColor(c1, c2); terrain.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); terrain.AddQuadColor(c1, c2); terrain.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); terrain.AddQuadColor(c1, c2); }
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); terrain.AddQuad(v3, v4, left, right); terrain.AddQuadColor(c3, c4, leftCell.Color, rightCell.Color); }
/* * 连接三角形 针对left right都是梯田的 */ void TriangulateCornerTerraces( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { //在slope-slope-flat类型中,和平台的插值TriangulateEdgeTerraces方法一样 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); //添加地形贴图UV Vector3 types; types.x = beginCell.TerrainTypeIndex; types.y = leftCell.TerrainTypeIndex; types.z = rightCell.TerrainTypeIndex; 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); } terrain.AddQuad(v3, v4, left, right); terrain.AddQuadColor(c3, c4, color2, color3); terrain.AddQuadTerrainTypes(types); }
void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { //outer walls Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetric.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetric.GetSecondSolidCorner(direction.Next()) * 0.25f; } // sharp turns else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } // two way turns else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetric.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetric.innerToOuter); } else { centerL = center + HexMetric.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetric.innerToOuter); centerR = center; } //mid point of channel EdgeVertices m = new EdgeVertices(Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); m.v3.y = center.y = e.v3.y; //fill area TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(color1); terrain.AddQuadColor(color1); terrain.AddQuadColor(color1); terrain.AddTriangleColor(color1); Vector3 types; types.x = types.y = types.z = cell.TerrainTypeIndex; terrain.AddTriangleTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); //river water quads if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }
void TriangulateConnection( HexDirection direction, HexCell cell, Vector3 vert1, Vector3 vert2 ) { HexCell neighbor = cell.GetNeighbor(direction); if (neighbor == null) { return; } Vector3 bridge = Hexmetrics.GetBridge(direction); Vector3 vert3 = vert1 + bridge; Vector3 vert4 = vert2 + bridge; vert3.y = vert4.y = neighbor.Elevation * Hexmetrics.elevationChange; if (cell.GetEdgeType(direction) == HexEdgeType.Slope) { TriangulateEdgeTerraces(vert1, vert2, cell, vert3, vert4, neighbor); } else { terrain.AddQuad(vert1, vert2, vert3, vert4); terrain.AddQuadColor(cell.color, neighbor.color); } // for (int i = 2; i < Hexmetrics.terraceSteps; i++) { // Vector3 v1 = vert3; // Vector3 v2 = vert4; // Color c1 = c2; // vert3 = Hexmetrics.TerraceLerp(beginLeft, endLeft, i); // vert4 = Hexmetrics.TerraceLerp(beginRight, endRight, i); // c2 = Hexmetrics.TerraceLerp(beginCell.color, endCell.color, i); // terrain.AddQuad(v1, v2, v3, v4); // terrain.AddQuadColor(c1, c2); // } // // terrain.AddQuad(vert3, vert4, endLeft, endRight); // terrain.AddQuadColor(c2, endCell.color); HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (direction <= HexDirection.E && nextNeighbor != null) { Vector3 vert5 = vert2 + Hexmetrics.GetBridge(direction.Next()); vert5.y = nextNeighbor.Elevation * Hexmetrics.elevationChange; if (cell.Elevation <= neighbor.Elevation) { if (cell.Elevation <= nextNeighbor.Elevation) { TriangulateCorner(vert2, cell, vert4, neighbor, vert5, nextNeighbor); } else { TriangulateCorner(vert5, nextNeighbor, vert2, cell, vert4, neighbor); } } else if (neighbor.Elevation <= nextNeighbor.Elevation) { TriangulateCorner(vert4, neighbor, vert5, nextNeighbor, vert2, cell); } else { TriangulateCorner(vert5, nextNeighbor, vert2, cell, vert4, neighbor); } terrain.AddTriangle(vert2, vert4, vert5); terrain.AddTriangleColor(cell.color, neighbor.color, nextNeighbor.color); } }
void TriangulateWithRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, color1, (int)cell.TerrainType, e, color1, (int)cell.TerrainType); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(color1); terrain.AddQuadColor(color1); terrain.AddQuadColor(color1); terrain.AddTriangleColor(color1); Vector3 types; types.x = types.y = types.z = (float)cell.TerrainType; terrain.AddTriangleTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad( centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed ); TriangulateRiverQuad( m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed ); }
/// <summary> /// 细胞中心河流河道的绘制方法 /// 有流入和有流出的情况 /// </summary> /// <param name="direction"></param> /// <param name="cell"></param> /// <param name="center"></param> /// <param name="e"></param> void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { //通过前一个方向得到中心点往左偏移的位置 centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; //通过下一个方向得到中心点往右偏移的位置 centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { //同一个细胞中,如果当前方向相邻1个单位方向上有河道,那么相连处河道拓宽,让河流能通过 centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { //同一个细胞中,如果当前方向相邻1个单位方向上有河道,那么相连处河道拓宽,让河流能通过 centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { //同一个细胞中,如果当前方向相邻2个单位方向上有河道 centerL = center; centerR = center + HexMetrics.GetSoliEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { //同一个细胞中,如果当前方向相邻2个单位方向上有河道 centerL = center + HexMetrics.GetSoliEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); //得到偏移后的左右两点与细胞的边界顶点做差值,得到中间位置的点 EdgeVertices m = new EdgeVertices(Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); //将细胞顶面中的河道中心线的高度设为一样 m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddTriangleColor(cell.Color); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuadColor(cell.Color); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddQuadColor(cell.Color); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(cell.Color); if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }
void Triangulate(HexDirection direction, HexCell cell) { bool isDeep = cell.Elevation == ElevationLevel.Deep ? true : false; Vector3 center = cell.transform.localPosition; Vector3 v1 = center + HexMetrics.GetFirstSolidCorner(direction, isDeep); Vector3 v2 = center + HexMetrics.GetSecondSolidCorner(direction, isDeep); //Center Tris terrain.AddTriangle(center, v1, v2); terrain.AddTriangleColor(cell.Color); Vector3 edge = HexMetrics.GetEdge(direction, isDeep); Vector3 tempV3 = center + HexMetrics.GetFirstEdgeCorner(direction, isDeep); Vector3 tempV4 = center + HexMetrics.GetSecondEdgeCorner(direction, isDeep); Vector3 v3 = tempV3 + edge; Vector3 v4 = tempV4 + edge; HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell; HexCell neighbor = cell.GetNeighbor(direction) ?? cell; HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell; //Edge Elevation if (cell.Elevation < neighbor.Elevation) { v3.y = v4.y = neighbor.Position.y; } //Edge Terrace Quads & Quads if (isDeep && neighbor.Elevation == ElevationLevel.Flat) { TriangulateEdgeTerraces(v1, v2, cell, v3, v4, neighbor); } else if (isDeep && neighbor.Elevation != ElevationLevel.Flat && cell.Elevation < neighbor.Elevation) { terrain.AddQuad(v1, v2, v3, v4); terrain.AddQuadColor(neighbor.Color); } else { terrain.AddQuad(v1, v2, v3, v4); terrain.AddQuadColor(cell.Color); } Vector3 v5 = center + HexMetrics.GetFirstCorner(direction); Vector3 v6 = center + HexMetrics.GetSecondCorner(direction); //Vertice Elevation Change if (cell.Elevation < neighbor.Elevation) { v5.y = v6.y = neighbor.Position.y; } if (cell.Elevation < nextNeighbor.Elevation) { if (nextNeighbor.Elevation < neighbor.Elevation) { v6.y = neighbor.Position.y; } else { v6.y = nextNeighbor.Position.y; } } if (cell.Elevation < prevNeighbor.Elevation) { if (prevNeighbor.Elevation < neighbor.Elevation) { v5.y = neighbor.Position.y; } else { v5.y = prevNeighbor.Position.y; } } //Corner Tris & Corner Terrace Tris if (isDeep) { if (neighbor.Elevation == ElevationLevel.Flat) { TriangulateCornerTerraces(v1, cell, v5, v3, neighbor); TriangulateCornerTerraces(v2, cell, v4, v6, neighbor); } else if (cell.Elevation == neighbor.Elevation) { if (nextNeighbor.Elevation == ElevationLevel.Flat && prevNeighbor.Elevation == ElevationLevel.Flat) { TriangulateOuterCornerTerraces(v5, cell, v3, v1, prevNeighbor); TriangulateOuterCornerTerraces(v6, cell, v2, v4, nextNeighbor); } else if (nextNeighbor.Elevation == ElevationLevel.Flat) { TriangulateOuterCornerTerraces(v6, cell, v2, v4, nextNeighbor); terrain.AddTriangle(v1, v5, v3); if (cell.Elevation < prevNeighbor.Elevation) { terrain.AddTriangleColor(prevNeighbor.Color); } else { terrain.AddTriangleColor(cell.Color); } } else if (prevNeighbor.Elevation == ElevationLevel.Flat) { TriangulateOuterCornerTerraces(v5, cell, v3, v1, prevNeighbor); terrain.AddTriangle(v2, v4, v6); if (cell.Elevation < nextNeighbor.Elevation) { terrain.AddTriangleColor(nextNeighbor.Color); } else { terrain.AddTriangleColor(cell.Color); } } else if (cell.Elevation < nextNeighbor.Elevation && cell.Elevation < prevNeighbor.Elevation) { terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(prevNeighbor.Color); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(nextNeighbor.Color); } else if (cell.Elevation < nextNeighbor.Elevation) { terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(cell.Color); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(nextNeighbor.Color); } else if (cell.Elevation < prevNeighbor.Elevation) { terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(prevNeighbor.Color); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(cell.Color); } else { terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(cell.Color); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(cell.Color); } } else { if (nextNeighbor.Elevation == ElevationLevel.Flat && prevNeighbor.Elevation == ElevationLevel.Flat) { TriangulateNextCornerTerracesCliff(v6, cell, v2, v4, neighbor, nextNeighbor); TriangulatePrevCornerTerracesCliff(v5, cell, v3, v1, neighbor, prevNeighbor); } else if (nextNeighbor.Elevation == ElevationLevel.Flat) { TriangulateNextCornerTerracesCliff(v6, cell, v2, v4, neighbor, nextNeighbor); terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(neighbor.Color); } else if (prevNeighbor.Elevation == ElevationLevel.Flat) { TriangulatePrevCornerTerracesCliff(v5, cell, v3, v1, neighbor, prevNeighbor); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(neighbor.Color); } else { terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(neighbor.Color); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(neighbor.Color); } } } else { terrain.AddTriangle(v1, v5, v3); terrain.AddTriangleColor(cell.Color); terrain.AddTriangle(v2, v4, v6); terrain.AddTriangleColor(cell.Color); } //Features if (cell.Elevation == ElevationLevel.Flat) { features.AddFeature(cell, (center + v1 + v5) * (1f / 3f)); } }
/// <summary> /// 生成有河流的三角网格 /// </summary> /// <param name="direction">处理的对应方向</param> /// <param name="cell">六边形对象引用</param> /// <param name="center">中心点坐标</param> /// <param name="e">边界中值插值对象</param> void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { // 河道拓宽为直线的左边界点,后续逻辑以此类推 // 总之向转弯内侧进行网格拼接 centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); // 同步河道底部高度 m.v3.y = center.y = e.v3.y; // 填充插值中间点与边界间的平面 TriangulateEdgeStrip(m, cell.Color, e, cell.Color); // 根据计算进行网格拼接 terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddTriangleColor(cell.Color); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuadColor(cell.Color); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddQuadColor(cell.Color); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(cell.Color); // 排除河流在水面下显示 if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad( centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed ); TriangulateRiverQuad( m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed ); } }
private void TriangulateWithRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; // Two cases: // If the cell has a river going through the opposite direction as well as the direction // that we are working with, the cell holds a straight river. if (cell.HasRiverThroughEdge(direction.Opposite())) { // Stretch the center into a line. Move 25% from the center to the first corner of the previous // direction, and 25% from the center to the second corner of the second direction. // One simple way of visualizing this is having a top-down view of the HexMesh and imagining // a triangulation in the eastern direction. centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; // Otherwise, the river does not flow in a straight line, check special cases: // Detect sharp turns by checking whether the cell has a rive going through the next // or previous cell part. // When there is a sharp turn, align the center line with the edge between this and the adjacent part. } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f /* Increased center line width from 1/2 to 2/3 */); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f /* Increased center line width from 1/2 to 2/3 */); centerR = center; // 2 step rotations, these produce gently curving rivers. // A river is going through two directions after this one. // Expand the center towards the center of the next direction's edge. } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; // Note that the edge middle point is closer that the vertex itself (it's within the inner radius) // which is why extending the center towards that edge will end up with a pinched section. // We extend the center edge towards the middle edge times innerToOuter radius to keep // the channel width constant. centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); // 2 step rotation, a river is going through two directions before this one. } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } // Determine the final center by averaging the Left and Right centers center = Vector3.Lerp(centerL, centerR, 0.5f); // We lerp the second and fourth vertices using 1/6 instead of the usual 1/4 as the // length from the edges is 1/8 instead of 1/4. This is because the channel has a // the same width along the river, so the relative edge length of the outer edges // will be 1/6 relative to the edge's middle length. (1/8 of 3/4) EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); // Add the triangles and quads that reached the center. terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddTriangleColor(cell.Color); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuadColor(cell.Color); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddQuadColor(cell.Color); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(cell.Color); if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }