Beispiel #1
0
        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;
        }
Beispiel #2
0
        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());
        }
Beispiel #3
0
 public int Compare(Lights.SegmentPoint a, Lights.SegmentPoint b)
 {
     return(-CompareCCW.Compare(a.WorldPos, b.WorldPos, center));
 }
Beispiel #4
0
        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());
        }