void TriangulateWithRiverBeginOrEnd(HexDirection dir, HexCell hexCell, Vector3 center, EdgeVertices e) { EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f), 1f / 6f ); m.v3.y = e.v3.y; TriangulateEdgeStrip(m, /*hexCell.Color*/ weights1, hexCell.Index, e, /*hexCell.Color*/ weights1, hexCell.Index); TriangulateEdgeFan(center, m, hexCell.Index); if (!hexCell.IsUnderwater) { bool reversed = hexCell.HasIncomingRiver; Vector3 indices; indices.x = indices.y = indices.z = hexCell.Index; TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, hexCell.RiverSurfaceY, 0.6f, reversed, indices); center.y = m.v2.y = m.v4.y = hexCell.RiverSurfaceY; rivers.AddTriangle(center, m.v2, m.v4); if (reversed) { rivers.AddTriangleUV( new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f) ); } else { rivers.AddTriangleUV( new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f) ); } rivers.AddTriangleCellData(indices, weights1); } }
void TriangulateRoad( Vector3 center, Vector3 mL, Vector3 mR, EdgeVertices e, bool hasRoadThroughCellEdge, float index) { if (hasRoadThroughCellEdge) { Vector3 indices; indices.x = indices.y = indices.z = index; Vector3 mC = Vector3.Lerp(mL, mR, 0.5f); TriangulateRoadSegment(mL, mC, mR, e.v2, e.v3, e.v4, weights1, weights1, indices); roads.AddTriangle(center, mL, mC); roads.AddTriangle(center, mC, mR); roads.AddTriangleUV(new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(1f, 0f)); roads.AddTriangleUV(new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 0f)); roads.AddTriangleCellData(indices, weights1); roads.AddTriangleCellData(indices, weights1); } else { TriangulateRoadEdge(center, mL, mR, index); } }
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 TriangulateRoad( Vector3 center, Vector3 mL, Vector3 mR, EdgeVertices e, bool hasRoadThroughCellEdge) { if (hasRoadThroughCellEdge) { //靠近边界的矩形 Vector3 mC = Vector3.Lerp(mL, mR, 0.5f); TriangulateRoadSegment(mL, mC, mR, e.v2, e.v3, e.v4); //靠近中心的三角形 roads.AddTriangle(center, mL, mC); roads.AddTriangle(center, mC, mR); roads.AddTriangleUV( new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(1f, 0f)); roads.AddTriangleUV( new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 0f)); } else { TriangulateRoadEdge(center, mL, mR); } }
void TriangulateWithRiverBeginOrEnd(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { EdgeVertices m = new EdgeVertices(Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f)); m.v3.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); TriangulateEdgeFan(center, m, cell.Color); bool reversed = cell.HasIncomingRiver; TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); center.y = m.v2.y = m.v4.y = cell.RiverSurfaceY; rivers.AddTriangle(center, m.v2, m.v4); if (reversed) { rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f)); } else { rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f)); } }
public void edgeVerticiesTerraceLerpTest() { int step = 1; EdgeVertices a = new EdgeVertices(corner1, corner2); EdgeVertices b = new EdgeVertices(corner1, corner2); expected.Add(HexMetrics.TerraceLerp(a.v1, b.v1, step)); expected.Add(HexMetrics.TerraceLerp(a.v2, b.v2, step)); expected.Add(HexMetrics.TerraceLerp(a.v3, b.v3, step)); expected.Add(HexMetrics.TerraceLerp(a.v4, b.v4, step)); expected.Add(HexMetrics.TerraceLerp(a.v5, b.v5, step)); EdgeVertices vert = EdgeVertices.TerraceLerp(a, b, step); actual.Add(v1); actual.Add(v2); actual.Add(v3); actual.Add(v4); actual.Add(v5); CollectionAssert.AreEqual(expected, actual); }
/// <summary> /// cell中有河流,但是不是自己的扇形 /// </summary> /// <param name="direction"></param> /// <param name="cell"></param> /// <param name="center"></param> /// <param name="e"></param> private 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) * 0.5f * HexMetrics.innerToOuter; } 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 (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
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 = beginCell.TerrainTypeIndex; float t2 = endCell.TerrainTypeIndex; 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); }
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); }
//-----------------------WALLS------------------------------ public void AddWall(EdgeVertices near, HexCell nearCell, EdgeVertices far, HexCell farCell, bool hasRiver, bool hasRoad) { if (nearCell.Walled != farCell.Walled && !nearCell.IsUnderWater && !farCell.IsUnderWater && nearCell.GetEdgeType(farCell) != HexEdgeType.Cliff) { AddWallSegment(near.v1, far.v1, near.v2, far.v2); if (hasRiver || hasRoad) { AddWallCap(near.v2, far.v2); AddWallCap(far.v4, near.v4); } else { AddWallSegment(near.v2, far.v2, near.v3, far.v3); AddWallSegment(near.v3, far.v3, near.v4, far.v4); } AddWallSegment(near.v4, far.v4, near.v5, far.v5); } }
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); }
private void TriangulateRoadWithoutRiver( Hex source, HexDirections direction, EdgeVertices edgeVertices, Dictionary <HexDirections, bool> roadEdges, Vector3 center, float hexOuterRadius, int wrapSize, MapMeshChunkLayer roads ) { Vector2 interpolators = GetRoadInterpolators( source, direction, roadEdges ); TriangulateRoad( center, Vector3.Lerp( center, edgeVertices.vertex1, interpolators.x ), Vector3.Lerp( center, edgeVertices.vertex5, interpolators.y ), edgeVertices, // hex.HasRoadThroughEdge(direction), roadEdges[direction], source.Index, hexOuterRadius, wrapSize, roads ); }
void TriangulateEdgeStrip( EdgeVertices e1, Color w1, float index1, EdgeVertices e2, Color w2, float index2, bool hasRoad = false ) { terrain.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); terrain.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); terrain.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); terrain.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); Vector3 indices; indices.x = indices.z = index1; indices.y = index2; terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); //terrain.AddQuadColor(c1, c2); //terrain.AddQuadColor(c1, c2); //terrain.AddQuadColor(c1, c2); // terrain.AddQuadColor(c1, c2); // Vector3 types; // types.x = types.z = type1; // types.y = type2; // terrain.AddQuadTerrainTypes(types); // terrain.AddQuadTerrainTypes(types); // terrain.AddQuadTerrainTypes(types); // terrain.AddQuadTerrainTypes(types); if (hasRoad) { TriangulateRoadSegment(e1.v2, e1.v3, e1.v4, e2.v2, e2.v3, e2.v4, w1, w2, indices); } }
void Triangulate(HexDirection direction, HexCell cell) { //Create triangle Vector3 center = cell.Position; EdgeVertices e = new EdgeVertices( center + HexMetrics.GetFirstSolidCorner(direction), center + HexMetrics.GetSecondSolidCorner(direction) ); if (cell.HasRiver) { if (cell.HasRiverThroughEdge(direction)) { e.v3.y = cell.StreamBedY; if (cell.HasRiverBeginOrEnd) { TriangulateWithRiverBeginOrEnd(direction, cell, center, e); } else { TriangulateWithRiver(direction, cell, center, e); } } else { TriangulateAdjacentToRiver(direction, cell, center, e); } } else { TriangulateEdgeFan(center, e, cell.Color); } if (direction <= HexDirection.SE) { TriangulateConnection(direction, cell, e); } }
/// <summary> /// If eligible creates a wall segment between 2 cells. /// </summary> public void AddWall(EdgeVertices near, HexCell nearCell, EdgeVertices far, HexCell farCell, bool hasRiver, bool hasRoad) { bool walledUnwalled = nearCell.Walled != farCell.Walled; // Walls only between walled and unwalled cells bool noUnderwater = !nearCell.IsUnderwater && !farCell.IsUnderwater; // No walls underwater bool noSlope = nearCell.GetEdgeType(farCell) != HexEdgeType.Cliff; // No walls on slopes if (walledUnwalled && noUnderwater && noSlope) { AddWallSegment(near.v1, far.v1, near.v2, far.v2); if (hasRiver || hasRoad) { // Leave a gap. AddWallCap(near.v2, far.v2); AddWallCap(far.v4, near.v4); } else { AddWallSegment(near.v2, far.v2, near.v3, far.v3); AddWallSegment(near.v3, far.v3, near.v4, far.v4); } AddWallSegment(near.v4, far.v4, near.v5, far.v5); } }
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); }
private void TriangulateEdgeStrip( EdgeVertices e1, Color w1, float type1, EdgeVertices e2, Color w2, float type2, bool hasRoad = false ) { terrain.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); terrain.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); terrain.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); terrain.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); var indices = new Vector3(type1, type2, type1); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); if (hasRoad) { TriangulateRoadSegment(e1.v2, e1.v3, e1.v4, e2.v2, e2.v3, e2.v4, w1, w2, indices); } }
void TriangulateEdgeFan(Vector3 center, EdgeVertices edge, float type) { terrain.AddTriangle(center, edge.v1, edge.v2); // terrain.AddTriangleColor(color); terrain.AddTriangle(center, edge.v2, edge.v3); // terrain.AddTriangleColor(color); terrain.AddTriangle(center, edge.v3, edge.v4); // terrain.AddTriangleColor(color); terrain.AddTriangle(center, edge.v4, edge.v5); // terrain.AddTriangleColor(color); terrain.AddTriangleColor(color1); terrain.AddTriangleColor(color1); terrain.AddTriangleColor(color1); terrain.AddTriangleColor(color1); Vector3 types; types.x = types.y = types.z = type; terrain.AddTriangleTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); }
void TriangulateEdgeStrip( EdgeVertices e1, Color c1, float type1, EdgeVertices e2, Color c2, float type2 ) { 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); Vector3 types; types.x = types.z = type1; types.y = type2; terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); }
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); } }
/// <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); }
void TriangulateEdgeTerraces(EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad) { EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); Color c2 = HexMetric.TerraceLerp(color1, color2, 1); float t1 = beginCell.TerrainTypeIndex; float t2 = endCell.TerrainTypeIndex; //first task TriangulateEdgeStrip(begin, color1, t1, e2, c2, t2, hasRoad); //process of creating actual steps for (int i = 2; i < HexMetric.terraceSteps; i++) { EdgeVertices e1 = e2; Color c1 = c2; e2 = EdgeVertices.TerraceLerp(begin, end, i); c2 = HexMetric.TerraceLerp(color1, color2, i); TriangulateEdgeStrip(e1, c1, t1, e2, c2, t2, hasRoad); } //last task TriangulateEdgeStrip(e2, c2, t1, end, color2, t2, hasRoad); }
/// <summary> /// 三角化是河流开端或者结尾(只有流出或者只有流入)的六边形内部的有河流的扇形 /// </summary> /// <param name="direction"></param> /// <param name="cell"></param> /// <param name="center"></param> /// <param name="e"></param> void TriangulateWithRiverBeginOrEnd(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { // 计算出六边形中心点与外部边缘的中线 // 外部边缘: ———— // 中线: -——- // 六边形中心点: . EdgeVertices m = new EdgeVertices(Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f)); // 调整中线的中心顶点的高度为河床高度 m.v3.y = e.v3.y; // 三角化中线到外部边缘之间的长方形 TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); // 三角化六边形中心店到中线的扇形 TriangulateEdgeFan(center, m, cell.Index); // 三角化河水 if (!cell.IsUnderwater) // 检查是否在陆地 { bool reversed = cell.HasIncomingRiver; // 流入河水需要翻转UV Vector3 indices; indices.x = indices.y = indices.z = cell.Index; TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices); center.y = m.v2.y = m.v4.y = cell.RiverSurfaceY; rivers.AddTriangle(center, m.v2, m.v4); if (reversed) { rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f)); } else { rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f)); } rivers.AddTriangleCellData(indices, weights1); } }
/// <summary> /// Creates the triangles for a side of the hexagon, with river starting or ending this side. /// </summary> void TriangulateWithRiverBeginOrEnd(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { // Edge 1/2 the way from edge and cell center EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); m.v3.y = e.v3.y; // middle at river bed height, but not the center of the cell TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); TriangulateEdgeFan(center, m, cell.Index); if (!cell.IsUnderwater) // No river water surface underwater, riverbed itself is allowed // River water surface { bool reversed = cell.HasIncomingRiver; Vector3 indices; indices.x = indices.y = indices.z = cell.Index; TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices); // Add first/last water surface triangle for river begin/end center.y = m.v2.y = m.v4.y = cell.RiverSurfaceY; Rivers.AddTriangle(center, m.v2, m.v4); if (reversed) { Rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f)); } else { Rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f)); } Rivers.AddTriangleCellData(indices, weights1); } }
void TriangulateEstuary(EdgeVertices e1, EdgeVertices e2, bool incomingRiver, Vector3 indices) { waterShore.AddTriangle(e2.v1, e1.v2, e1.v1); waterShore.AddTriangle(e2.v5, e1.v5, e1.v4); waterShore.AddTriangleUV(new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f)); waterShore.AddTriangleUV(new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f)); waterShore.AddTriangleCellData(indices, weights2, weights1, weights1); waterShore.AddTriangleCellData(indices, weights2, weights1, weights1); estuaries.AddQuad(e2.v1, e1.v2, e2.v2, e1.v3); estuaries.AddTriangle(e1.v3, e2.v2, e2.v4); estuaries.AddQuad(e1.v3, e1.v4, e2.v4, e2.v5); estuaries.AddQuadUV(new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 0f)); estuaries.AddTriangleUV(new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(1f, 1f)); estuaries.AddQuadUV(new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f)); estuaries.AddQuadCellData( indices, weights2, weights1, weights2, weights1 ); estuaries.AddTriangleCellData(indices, weights1, weights2, weights2); estuaries.AddQuadCellData(indices, weights1, weights2); if (incomingRiver) { estuaries.AddQuadUV2(new Vector2(1.5f, 1.0f), new Vector2(0.7f, 1.15f), new Vector2(1f, 0.8f), new Vector2(0.5f, 1.1f)); estuaries.AddTriangleUV2(new Vector2(0.5f, 1.1f), new Vector2(1f, 0.8f), new Vector2(0f, 0.8f)); estuaries.AddQuadUV2(new Vector2(0.5f, 1.1f), new Vector2(0.3f, 1.15f), new Vector2(0f, 0.8f), new Vector2(-0.5f, 1f)); } else { estuaries.AddQuadUV2(new Vector2(-0.5f, -0.2f), new Vector2(0.3f, -0.35f), new Vector2(0f, 0f), new Vector2(0.5f, -0.3f)); estuaries.AddTriangleUV2(new Vector2(0.5f, -0.3f), new Vector2(0f, 0f), new Vector2(1f, 0f)); estuaries.AddQuadUV2(new Vector2(0.5f, -0.3f), new Vector2(0.7f, -0.35f), new Vector2(1f, 0f), new Vector2(1.5f, -0.2f)); } }
/// <summary> /// Creates the triangles for the bridge between two cells. /// </summary> void TriangulateEdgeStrip(EdgeVertices e1, Color w1, float index1, EdgeVertices e2, Color w2, float index2, bool hasRoad = false) { // Geometry Terrain.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); Terrain.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); Terrain.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); Terrain.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); // Add splat map and terrain types to cell data Vector3 indices; indices.x = indices.z = index1; indices.y = index2; Terrain.AddQuadCellData(indices, w1, w2); Terrain.AddQuadCellData(indices, w1, w2); Terrain.AddQuadCellData(indices, w1, w2); Terrain.AddQuadCellData(indices, w1, w2); // If road present then build it in the middle of the cell bridge. if (hasRoad) { TriangulateRoadSegment(e1.v2, e1.v3, e1.v4, e2.v2, e2.v3, e2.v4, w1, w2, indices); } }
/// <summary> /// Creates road geometry for cell center. /// </summary> void TriangulateRoad(Vector3 center, Vector3 mL, Vector3 mR, EdgeVertices e, bool hasRoadThroughCellEdge, float index) { if (hasRoadThroughCellEdge) // Road in this direction ? { Vector3 indices; indices.x = indices.y = indices.z = index; Vector3 mC = Vector3.Lerp(mL, mR, 0.5f); TriangulateRoadSegment(mL, mC, mR, e.v2, e.v3, e.v4, weights1, weights1, indices); // Center connection triangles Roads.AddTriangle(center, mL, mC); Roads.AddTriangle(center, mC, mR); Roads.AddTriangleUV(new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(1f, 0f)); Roads.AddTriangleUV(new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 0f)); Roads.AddTriangleCellData(indices, weights1); Roads.AddTriangleCellData(indices, weights1); } else { // Then road exists in cell but not at this edge so draw auxiliary road geometry TriangulateRoadEdge(center, mL, mR, index); } }
// Walls: //&& // !nearCell.IsUnderwater && !farCell.IsUnderwater && // nearCell.GetEdgeType(farCell) != HexEdgeType.Cliff public void AddWall( EdgeVertices near, HexCell nearCell, EdgeVertices far, HexCell farCell, bool hasRiver, bool hasRoad ) { if ( nearCell.Walled != farCell.Walled ) { AddWallSegment(near.v1, far.v1, near.v2, far.v2); if (hasRiver || hasRoad) { AddWallCap(near.v2, far.v2); AddWallCap(far.v4, near.v4); } else { AddWallSegment(near.v2, far.v2, near.v3, far.v3); AddWallSegment(near.v3, far.v3, near.v4, far.v4); } AddWallSegment(near.v4, far.v4, near.v5, far.v5); } }
//三角化河流 void TriangulateWithRiver(int direction, int prevD, int nextD, Color cellColor, Vector3 center, EdgeVertices e, ref DynamicBuffer <ColorBuffer> colorBuffer, ref DynamicBuffer <VertexBuffer> vertexBuffer, bool oppositeHasRiverThroughEdge) { Vector3 centerL, centerR; if (oppositeHasRiverThroughEdge) { centerL = center + HexMetrics.GetFirstSolidCorner(prevD) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(nextD) * 0.25f; } else { centerL = centerR = center; } 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, cellColor, e, cellColor, ref colorBuffer, ref vertexBuffer); AddTriangle(centerL, cellColor, m.v1, cellColor, m.v2, cellColor, ref colorBuffer, ref vertexBuffer); AddQuad(centerL, cellColor, center, cellColor, m.v2, cellColor, m.v3, cellColor, ref colorBuffer, ref vertexBuffer); AddQuad(center, cellColor, centerR, cellColor, m.v3, cellColor, m.v4, cellColor, ref colorBuffer, ref vertexBuffer); AddTriangle(centerR, cellColor, m.v4, cellColor, m.v5, cellColor, ref colorBuffer, ref vertexBuffer); }
void TriangulateAdjacentToRiver(Direction direction, Cell cell, Vector3 center, EdgeVertices edges) { if (cell.HasRoads) { TriangulateRoadsNearRiver(direction, cell, center, edges); } if (cell.HasRiverAtDirection(direction.Next())) { if (cell.HasRiverAtDirection(direction.Previous())) { center += Metrics.GetMiddleSolidCorner(direction) * Metrics.InnerToOuter * 0.5f; } else if (cell.HasRiverAtDirection(direction.PrePrevious())) { center += Metrics.GetFirstSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverAtDirection(direction.Previous()) && cell.HasRiverAtDirection(direction.AfterNext())) { center += Metrics.GetSecondSolidCorner(direction) * 0.25f; } var middleChannelVertices = new EdgeVertices( Vector3.Lerp(center, edges.vertex1, 0.5f), Vector3.Lerp(center, edges.vertex5, 0.5f)); middleChannelVertices.vertex3.y = edges.vertex3.y; TriangulateEdgeStrip(middleChannelVertices, edges, cell.Color, cell.Color); TriangulateEdgeFan(center, middleChannelVertices, cell.Color); if (!cell.IsUnderWater && !cell.HasRoadAtDirection(direction)) { objectManager.AddObjects((center + edges.vertex1 + edges.vertex5) / 3, cell); } }