public void TriangulateContoursBetween( IHexCell center, IHexCell right, HexDirection direction, Color centerWeights, Color rightWeights, IHexMesh mesh ) { var centerRightContour = CellContourCanon.GetContourForCellEdge(center, direction); var rightCenterContour = CellContourCanon.GetContourForCellEdge(right, direction.Opposite()); int centerRightIndex = 1, rightCenterIndex = rightCenterContour.Count - 1; while (centerRightIndex < centerRightContour.Count && rightCenterIndex > 0) { mesh.AddQuad( centerRightContour[centerRightIndex - 1].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ(), rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ() ); mesh.AddQuadColor(centerWeights, rightWeights); centerRightIndex++; rightCenterIndex--; } for (; centerRightIndex < centerRightContour.Count; centerRightIndex++) { mesh.AddTriangle( centerRightContour[centerRightIndex - 1].ToXYZ(), rightCenterContour[0].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ() ); mesh.AddTriangleColor(centerWeights, rightWeights, centerWeights); } for (; rightCenterIndex > 0; rightCenterIndex--) { mesh.AddTriangle( centerRightContour.Last().ToXYZ(), rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ() ); mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights); } if (RiverCanon.HasRiverAlongEdge(right, direction.Next2())) { var nextRight = Grid.GetNeighbor(center, direction.Next()); var rightNextRightContour = CellContourCanon.GetContourForCellEdge(right, direction.Next2()); var nextRightRightContour = CellContourCanon.GetContourForCellEdge(nextRight, direction.Previous()); mesh.AddTriangle( centerRightContour.Last().ToXYZ(), rightNextRightContour.Last().ToXYZ(), nextRightRightContour.First().ToXYZ() ); mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights); } }
private bool ShouldAddQuad( List <IHexCell> farmBlob, Vector2 northVertex, Vector2 eastVertex, Vector2 southVertex, Vector2 westVertex ) { bool northValid = false, eastValid = false, southValid = false, westValid = false; foreach (var cell in farmBlob) { foreach (var direction in EnumUtil.GetValues <HexDirection>()) { if (RiverCanon.HasRiverAlongEdge(cell, direction)) { var contour = CellContourCanon.GetContourForCellEdge(cell, direction); if (CellContourCanon.DoesSegmentCrossContour(northVertex, eastVertex, contour) || CellContourCanon.DoesSegmentCrossContour(northVertex, westVertex, contour) || CellContourCanon.DoesSegmentCrossContour(southVertex, eastVertex, contour) || CellContourCanon.DoesSegmentCrossContour(southVertex, westVertex, contour) ) { return(false); } } northValid |= CellContourCanon.IsPointWithinContour(northVertex, cell, direction); eastValid |= CellContourCanon.IsPointWithinContour(eastVertex, cell, direction); southValid |= CellContourCanon.IsPointWithinContour(southVertex, cell, direction); westValid |= CellContourCanon.IsPointWithinContour(westVertex, cell, direction); } } return(northValid && eastValid && southValid && westValid); }
public void TriangulateCultureInDirection( IHexCell center, HexDirection direction, IHexMesh cultureMesh ) { var centerOwner = CivTerritoryLogic.GetCivClaimingCell(center); if (centerOwner == null) { return; } IHexCell left = Grid.GetNeighbor(center, direction.Previous()); IHexCell right = Grid.GetNeighbor(center, direction); IHexCell nextRight = Grid.GetNeighbor(center, direction.Next()); if (right == null) { return; } if (CivTerritoryLogic.GetCivClaimingCell(right) != centerOwner) { TriangulateCultureAlongContour(center, direction, centerOwner.Template.Color, cultureMesh); } else { var centerRightContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction); var rightCenterContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Opposite()); if (rightCenterContour.Count <= 3) { TriangulateCultureCorners_FlatEdge( center, left, right, nextRight, direction, centerOwner, centerRightContour, rightCenterContour, cultureMesh ); } else { TriangulateCultureCorners_River( center, left, right, nextRight, direction, centerOwner, centerRightContour, cultureMesh ); } } }
private void OnDrawGizmos_Contours() { Vector3 lineOne = Vector3.zero, lineTwo = Vector3.zero; foreach (var cell in Grid.Cells) { Vector3 center = cell.AbsolutePosition; foreach (var direction in EnumUtil.GetValues <HexDirection>()) { var contour = CellEdgeContourCanon.GetContourForCellEdge(cell, direction); if (contour.Count == 0) { continue; } for (int i = 0; i < contour.Count - 1; i++) { Gizmos.color = Color.white; lineOne.x = contour[i].x; lineOne.z = contour[i].y; lineTwo.x = contour[i + 1].x; lineTwo.z = contour[i + 1].y; Gizmos.DrawLine(lineOne, lineTwo); Gizmos.color = Color.gray; lineTwo.x = contour[i].x; lineTwo.z = contour[i].y; Gizmos.DrawLine(center, lineTwo); } lineTwo.x = contour.Last().x; lineTwo.z = contour.Last().y; Gizmos.DrawLine(center, lineTwo); Gizmos.color = Color.red; Gizmos.DrawLine(center, center + RenderConfig.GetFirstCorner(direction)); Gizmos.DrawLine(center, center + RenderConfig.GetSecondCorner(direction)); } } }
private void TriangulateCellWeights_River( IHexCell center, IHexCell right, HexDirection direction, bool hasCenterRightRiver, IHexMesh weightsMesh ) { var centerRightContour = CellContourCanon.GetContourForCellEdge(center, direction); Vector3 innerOne, innerTwo, contourOneXYZ, contourTwoXYZ; for (int i = 1; i < centerRightContour.Count; i++) { contourOneXYZ = centerRightContour[i - 1].ToXYZ(); contourTwoXYZ = centerRightContour[i].ToXYZ(); innerOne = Vector3.Lerp(center.AbsolutePosition, contourOneXYZ, RenderConfig.SolidFactor); innerTwo = Vector3.Lerp(center.AbsolutePosition, contourTwoXYZ, RenderConfig.SolidFactor); weightsMesh.AddTriangle(center.AbsolutePosition, innerOne, innerTwo); weightsMesh.AddTriangleColor(CenterWeights); weightsMesh.AddQuad(innerOne, innerTwo, contourOneXYZ, contourTwoXYZ); if (hasCenterRightRiver) { weightsMesh.AddQuadColor(CenterWeights); } else { weightsMesh.AddQuadColor(CenterWeights, CenterRightWeights); } } if (hasCenterRightRiver && direction <= HexDirection.SE) { ContourTriangulator.TriangulateContoursBetween( center, right, direction, CenterWeights, RightWeights, weightsMesh ); } }
public void TriangulateOrientation(IHexCell center, IHexMesh orientationMesh) { short indexOffset = (short)(center.Index + 1); foreach (var direction in EnumUtil.GetValues <HexDirection>()) { byte[] rg = BitConverter.GetBytes(indexOffset); byte b = (byte)direction; var cellColor = new Color32(rg[0], rg[1], b, 0); var centerContour = CellContourCanon.GetContourForCellEdge(center, direction); for (int i = 1; i < centerContour.Count; i++) { orientationMesh.AddTriangle( center.AbsolutePosition, centerContour[i - 1].ToXYZ(), centerContour[i].ToXYZ() ); orientationMesh.AddTriangleColor(cellColor); } if (direction <= HexDirection.SE && RiverCanon.HasRiverAlongEdge(center, direction)) { var right = Grid.GetNeighbor(center, direction); ContourTriangulator.TriangulateContoursBetween( center, right, direction, cellColor, cellColor, orientationMesh ); if (direction <= HexDirection.E && RiverCanon.HasRiverAlongEdge(right, direction.Previous2())) { } } } }
public void BuildNonRiverContour(IHexCell center, HexDirection direction) { if (RiverCanon.HasRiverAlongEdge(center, direction)) { return; } var contourPoints = new List <Vector2>(); IHexCell left = Grid.GetNeighbor(center, direction.Previous()); IHexCell right = Grid.GetNeighbor(center, direction); IHexCell nextRight = Grid.GetNeighbor(center, direction.Next()); bool hasCenterLeftRiver = RiverCanon.HasRiverAlongEdge(center, direction.Previous()); bool hasCenterNextRightRiver = RiverCanon.HasRiverAlongEdge(center, direction.Next()); bool hasLeftRightRiver = left != null && RiverCanon.HasRiverAlongEdge(left, direction.Next()); bool hasNextRightRightRiver = nextRight != null && RiverCanon.HasRiverAlongEdge(nextRight, direction.Previous()); if (hasCenterLeftRiver) { ICollection <Vector2> centerLeftContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Previous()); contourPoints.Add(centerLeftContour.Last()); } else if (hasLeftRightRiver) { ICollection <Vector2> rightLeftContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Previous2()); contourPoints.Add(rightLeftContour.First()); } else { contourPoints.Add(center.AbsolutePositionXZ + RenderConfig.GetFirstCornerXZ(direction)); } if (hasCenterNextRightRiver || (hasNextRightRightRiver && RiverCanon.GetFlowOfRiverAtEdge(nextRight, direction.Previous()) == RiverFlow.Clockwise) ) { ICollection <Vector2> centerNextRightContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Next()); contourPoints.Add(centerNextRightContour.First()); } else if (hasNextRightRightRiver) { //We need to add two points here in case the edge is up against the //outflow of a river. We've decided to give the outflow over entirely //to one of the cells, but other constructions are possible. ICollection <Vector2> rightNextRightContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Next2()); ICollection <Vector2> nextRightRightContour = CellEdgeContourCanon.GetContourForCellEdge(nextRight, direction.Previous()); contourPoints.Add(rightNextRightContour.Last()); contourPoints.Add(nextRightRightContour.First()); } else { contourPoints.Add(center.AbsolutePositionXZ + RenderConfig.GetSecondCornerXZ(direction)); } CellEdgeContourCanon.SetContourForCellEdge(center, direction, contourPoints); }
/* * There are a handful of possible cases for this method. * * In the first case, CenterLeftContour and CenterRightContour intersect each-other. * In that case, we want to remove all of the points in each contour beyond the other * and then join them at the intersect. We do this by checking the contours in opposite * directions. Because all contours are oriented clockwise around their cell, if we * check for line segment collision carefully we'll know exactly which points need to * be removed. Any intersection will appear close to the beginning of CenterRightContour * and the end of CenterLeftContour. Thus we work up CenterRightContour and down * CenterLeftContour. Once we find an intersection, we strip points from the beginning of * CenterRightContour and the end of CenterLeftContour and add the intersection point at * the beginning and end, respectively. * * In the second case, CenterLeftContour doesn't touch CenterRightContour but CenterRightContour * extends undesirably into the rivers. To handle this, we extrapolate forward from * CenterLeftContour using its last and second to last points, check for an intersection, * and then cull points and add the intersection as above. * * In the third case, CenterRightContour doesn't touch CenterLeftContour but CenterLeftContour * extends undesirably into the rivers. We handle this much the same way, extrapolating * backwards from the first and second points of CenterRightContour, checking for an intersecton, * and culling as needed. * * In the fourth case, neither contours touch each-other or extend into the rivers. In that case, * we extrapolate on both contours (forward for CenterLeft, backward for CenterRight) and add * their intersection without culling. */ public void RationalizeCellContours( IHexCell center, HexDirection direction ) { List <Vector2> centerLeftContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Previous()).ToList(); List <Vector2> centerRightContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction).ToList(); int lastOutsideLeftIndex = centerLeftContour.Count - 1; int lastOutsideRightIndex = 0; Vector2 contourIntersect = Vector2.zero; bool hasFoundIntersect = false; //We multiply our extrapolating vector by some relatively large number to make it more likely //that they intersect properly. for (; lastOutsideLeftIndex > 0; lastOutsideLeftIndex--) { if (Geometry2D.AreLineSegmentsCrossing( centerLeftContour[lastOutsideLeftIndex], centerLeftContour [lastOutsideLeftIndex - 1], out contourIntersect, centerRightContour[0], centerRightContour[0] + (centerRightContour[0] - centerRightContour[1]) * 10, out contourIntersect )) { hasFoundIntersect = true; break; } for (lastOutsideRightIndex = 0; lastOutsideRightIndex < centerRightContour.Count - 1; lastOutsideRightIndex++) { if (Geometry2D.AreLineSegmentsCrossing( centerLeftContour [lastOutsideLeftIndex], centerLeftContour [lastOutsideLeftIndex - 1], out contourIntersect, centerRightContour[lastOutsideRightIndex], centerRightContour[lastOutsideRightIndex + 1], out contourIntersect )) { hasFoundIntersect = true; break; } } if (hasFoundIntersect) { break; } } if (!hasFoundIntersect) { Vector2 lastLeft = centerLeftContour.Last(); Vector2 secondLastLeft = centerLeftContour[centerLeftContour.Count - 2]; if (Geometry2D.AreLineSegmentsCrossing( lastLeft, lastLeft + (lastLeft - secondLastLeft) * 10, out contourIntersect, centerRightContour[0], centerRightContour[0] + (centerRightContour[0] - centerRightContour[1]) * 10, out contourIntersect )) { hasFoundIntersect = true; } for (lastOutsideRightIndex = 0; lastOutsideRightIndex < centerRightContour.Count - 1; lastOutsideRightIndex++) { if (Geometry2D.AreLineSegmentsCrossing( lastLeft, lastLeft + (lastLeft - secondLastLeft) * 10, out contourIntersect, centerRightContour[lastOutsideRightIndex], centerRightContour[lastOutsideRightIndex + 1], out contourIntersect )) { hasFoundIntersect = true; break; } } } if (lastOutsideLeftIndex > 0) { centerLeftContour.RemoveRange(lastOutsideLeftIndex, centerLeftContour.Count - lastOutsideLeftIndex); } if (lastOutsideRightIndex < centerRightContour.Count - 1) { centerRightContour.RemoveRange(0, lastOutsideRightIndex + 1); } if (hasFoundIntersect) { centerLeftContour.Add(contourIntersect); centerRightContour.Insert(0, contourIntersect); } CellEdgeContourCanon.SetContourForCellEdge(center, direction.Previous(), centerLeftContour); CellEdgeContourCanon.SetContourForCellEdge(center, direction, centerRightContour); }