private static Vector2 GetEdgeNormal(GraphEdge edge, VoronoiCell cell = null) { if (cell == null) cell = edge.AdjacentCell(null); if (cell == null) return Vector2.UnitX; CompareCCW compare = new CompareCCW(cell.Center); if (compare.Compare(edge.Point1, edge.Point2) == -1) { var temp = edge.Point1; edge.Point1 = edge.Point2; edge.Point2 = temp; } Vector2 normal = Vector2.Zero; normal = Vector2.Normalize(edge.Point2 - edge.Point1); Vector2 diffToCell = Vector2.Normalize(cell.Center - edge.Point2); normal = new Vector2(-normal.Y, normal.X); if (Vector2.Dot(normal, diffToCell) < 0) { normal = -normal; } return normal; }
public static VertexPositionTexture[] GenerateWallShapes(List <VoronoiCell> cells, Level level) { float outWardThickness = 30.0f; List <VertexPositionTexture> verticeList = new List <VertexPositionTexture>(); foreach (VoronoiCell cell in cells) { CompareCCW compare = new CompareCCW(cell.Center); foreach (GraphEdge edge in cell.Edges) { if (edge.Cell1 != null && edge.Cell1.Body == null && edge.Cell1.CellType != CellType.Empty) { edge.Cell1 = null; } if (edge.Cell2 != null && edge.Cell2.Body == null && edge.Cell2.CellType != CellType.Empty) { edge.Cell2 = null; } if (compare.Compare(edge.Point1, edge.Point2) == -1) { var temp = edge.Point1; edge.Point1 = edge.Point2; edge.Point2 = temp; } } } foreach (VoronoiCell cell in cells) { foreach (GraphEdge edge in cell.Edges) { if (!edge.IsSolid) { continue; } GraphEdge leftEdge = cell.Edges.Find(e => e != edge && (edge.Point1 == e.Point1 || edge.Point1 == e.Point2)); GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2 == e.Point1 || edge.Point2 == e.Point2)); Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero; float inwardThickness1 = 100; float inwardThickness2 = 100; if (leftEdge != null && !leftEdge.IsSolid) { leftNormal = edge.Point1 == leftEdge.Point1 ? Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) : Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2); inwardThickness1 = Vector2.Distance(leftEdge.Point1, leftEdge.Point2) / 2; } else { leftNormal = Vector2.Normalize(cell.Center - edge.Point1); inwardThickness1 = Vector2.Distance(edge.Point1, cell.Center) / 2; } if (!MathUtils.IsValid(leftNormal)) { #if DEBUG DebugConsole.ThrowError("Invalid left normal"); #endif GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, "Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")"); if (cell.Body != null) { GameMain.World.RemoveBody(cell.Body); cell.Body = null; } leftNormal = Vector2.UnitX; break; } if (rightEdge != null && !rightEdge.IsSolid) { rightNormal = edge.Point2 == rightEdge.Point1 ? Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) : Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2); inwardThickness2 = Vector2.Distance(rightEdge.Point1, rightEdge.Point2) / 2; } else { rightNormal = Vector2.Normalize(cell.Center - edge.Point2); inwardThickness2 = Vector2.Distance(edge.Point2, cell.Center) / 2; } if (!MathUtils.IsValid(rightNormal)) { #if DEBUG DebugConsole.ThrowError("Invalid right normal"); #endif GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, "Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")"); if (cell.Body != null) { GameMain.World.RemoveBody(cell.Body); cell.Body = null; } rightNormal = Vector2.UnitX; break; } float point1UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point1 - cell.Center)); float point2UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point2 - cell.Center)); //handle wrapping around 0/360 if (point1UV - point2UV > MathHelper.Pi) { point2UV += MathHelper.TwoPi; } //the texture wraps around the cell 4 times //TODO: define the uv scale in level generation parameters? point1UV = point1UV / MathHelper.TwoPi * 4; point2UV = point2UV / MathHelper.TwoPi * 4; for (int i = 0; i < 2; i++) { Vector2[] verts = new Vector2[3]; VertexPositionTexture[] vertPos = new VertexPositionTexture[3]; if (i == 0) { verts[0] = edge.Point1 - leftNormal * outWardThickness; verts[1] = edge.Point2 - rightNormal * outWardThickness; verts[2] = edge.Point1 + leftNormal * inwardThickness1; vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.0f)); vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f)); vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point1UV, 0.5f)); } else { verts[0] = edge.Point1 + leftNormal * inwardThickness1; verts[1] = edge.Point2 - rightNormal * outWardThickness; verts[2] = edge.Point2 + rightNormal * inwardThickness2; vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.5f)); vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f)); vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point2UV, 0.5f)); } verticeList.AddRange(vertPos); } } } return(verticeList.ToArray()); }
public int Compare(Lights.SegmentPoint a, Lights.SegmentPoint b) { return(-CompareCCW.Compare(a.WorldPos, b.WorldPos, center)); }
public static VertexPositionTexture[] GenerateWallShapes(List <VoronoiCell> cells, Level level) { float inwardThickness = 500.0f, outWardThickness = 30.0f; List <VertexPositionTexture> verticeList = new List <VertexPositionTexture>(); foreach (VoronoiCell cell in cells) { //if (cell.body == null) continue; foreach (GraphEdge edge in cell.edges) { if (edge.cell1 != null && edge.cell1.body == null && edge.cell1.CellType != CellType.Empty) { edge.cell1 = null; } if (edge.cell2 != null && edge.cell2.body == null && edge.cell2.CellType != CellType.Empty) { edge.cell2 = null; } CompareCCW compare = new CompareCCW(cell.Center); if (compare.Compare(edge.point1, edge.point2) == -1) { var temp = edge.point1; edge.point1 = edge.point2; edge.point2 = temp; } } } foreach (VoronoiCell cell in cells) { //if (cell.body == null) continue; foreach (GraphEdge edge in cell.edges) { if (!edge.isSolid) { continue; } GraphEdge leftEdge = cell.edges.Find(e => e != edge && (edge.point1 == e.point1 || edge.point1 == e.point2)); GraphEdge rightEdge = cell.edges.Find(e => e != edge && (edge.point2 == e.point1 || edge.point2 == e.point2)); Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero; if (leftEdge == null) { leftNormal = GetEdgeNormal(edge, cell); } else { leftNormal = (leftEdge.isSolid) ? Vector2.Normalize(GetEdgeNormal(leftEdge) + GetEdgeNormal(edge, cell)) : Vector2.Normalize(leftEdge.Center - edge.point1); } if (!MathUtils.IsValid(leftNormal)) { #if DEBUG DebugConsole.ThrowError("Invalid left normal"); #endif GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, "Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")"); if (cell.body != null) { GameMain.World.RemoveBody(cell.body); cell.body = null; } leftNormal = Vector2.UnitX; break; } if (rightEdge == null) { rightNormal = GetEdgeNormal(edge, cell); } else { rightNormal = (rightEdge.isSolid) ? Vector2.Normalize(GetEdgeNormal(rightEdge) + GetEdgeNormal(edge, cell)) : Vector2.Normalize(rightEdge.Center - edge.point2); } if (!MathUtils.IsValid(rightNormal)) { #if DEBUG DebugConsole.ThrowError("Invalid right normal"); #endif GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, "Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")"); if (cell.body != null) { GameMain.World.RemoveBody(cell.body); cell.body = null; } rightNormal = Vector2.UnitX; break; } for (int i = 0; i < 2; i++) { Vector2[] verts = new Vector2[3]; VertexPositionTexture[] vertPos = new VertexPositionTexture[3]; if (i == 0) { verts[0] = edge.point1 - leftNormal * outWardThickness; verts[1] = edge.point2 - rightNormal * outWardThickness; verts[2] = edge.point1 + leftNormal * inwardThickness; vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), Vector2.Zero); vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), Vector2.UnitX); vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(0, 0.5f)); } else { verts[0] = edge.point1 + leftNormal * inwardThickness; verts[1] = edge.point2 - rightNormal * outWardThickness; verts[2] = edge.point2 + rightNormal * inwardThickness; vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(0.0f, 0.5f)); vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), Vector2.UnitX); vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(1.0f, 0.5f)); } var comparer = new CompareCCW((verts[0] + verts[1] + verts[2]) / 3.0f); Array.Sort(verts, vertPos, comparer); for (int j = 0; j < 3; j++) { verticeList.Add(vertPos[j]); } } } } return(verticeList.ToArray()); }