Esempio n. 1
0
        public static List <Body> GeneratePolygons(List <VoronoiCell> cells, out List <VertexPositionTexture> verticeList, bool setSolid = true)
        {
            verticeList = new List <VertexPositionTexture>();
            var bodies = new List <Body>();

            List <Vector2> tempVertices = new List <Vector2>();
            List <Vector2> bodyPoints   = new List <Vector2>();

            for (int n = cells.Count - 1; n >= 0; n--)
            {
                VoronoiCell cell = cells[n];

                bodyPoints.Clear();
                tempVertices.Clear();
                foreach (GraphEdge ge in cell.edges)
                {
                    if (Math.Abs(Vector2.Distance(ge.point1, ge.point2)) < 0.1f)
                    {
                        continue;
                    }
                    if (!tempVertices.Contains(ge.point1))
                    {
                        tempVertices.Add(ge.point1);
                    }
                    if (!tempVertices.Contains(ge.point2))
                    {
                        tempVertices.Add(ge.point2);
                    }

                    VoronoiCell adjacentCell = ge.AdjacentCell(cell);
                    //if (adjacentCell!=null && cells.Contains(adjacentCell)) continue;

                    if (setSolid)
                    {
                        ge.isSolid = (adjacentCell == null || !cells.Contains(adjacentCell));
                    }

                    if (!bodyPoints.Contains(ge.point1))
                    {
                        bodyPoints.Add(ge.point1);
                    }
                    if (!bodyPoints.Contains(ge.point2))
                    {
                        bodyPoints.Add(ge.point2);
                    }
                }

                if (tempVertices.Count < 3 || bodyPoints.Count < 2)
                {
                    cells.RemoveAt(n);
                    continue;
                }

                var triangles = MathUtils.TriangulateConvexHull(tempVertices, cell.Center);
                for (int i = 0; i < triangles.Count; i++)
                {
                    foreach (Vector2 vertex in triangles[i])
                    {
                        //shift the coordinates around a bit to make the texture repetition less obvious
                        Vector2 uvCoords = new Vector2(
                            vertex.X / 2000.0f + (float)Math.Sin(vertex.X / 500.0f) * 0.15f,
                            vertex.Y / 2000.0f + (float)Math.Sin(vertex.Y / 700.0f) * 0.15f);

                        verticeList.Add(new VertexPositionTexture(new Vector3(vertex, 1.0f), uvCoords));
                    }
                }

                if (bodyPoints.Count < 2)
                {
                    continue;
                }

                if (bodyPoints.Count < 3)
                {
                    foreach (Vector2 vertex in tempVertices)
                    {
                        if (bodyPoints.Contains(vertex))
                        {
                            continue;
                        }
                        bodyPoints.Add(vertex);
                        break;
                    }
                }

                for (int i = 0; i < bodyPoints.Count; i++)
                {
                    cell.bodyVertices.Add(bodyPoints[i]);
                    bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]);
                }


                if (cell.CellType == CellType.Empty)
                {
                    continue;
                }

                triangles = MathUtils.TriangulateConvexHull(bodyPoints, ConvertUnits.ToSimUnits(cell.Center));

                Body cellBody = new Body(GameMain.World);

                for (int i = 0; i < triangles.Count; i++)
                {
                    //don't create a triangle if any of the vertices are too close to each other
                    //(apparently Farseer doesn't like polygons with a very small area, see Shape.ComputeProperties)
                    if (Vector2.Distance(triangles[i][0], triangles[i][1]) < 0.05f ||
                        Vector2.Distance(triangles[i][0], triangles[i][2]) < 0.05f ||
                        Vector2.Distance(triangles[i][1], triangles[i][2]) < 0.05f)
                    {
                        continue;
                    }

                    Vertices bodyVertices = new Vertices(triangles[i]);
                    FixtureFactory.AttachPolygon(bodyVertices, 5.0f, cellBody);
                }

                cellBody.UserData            = cell;
                cellBody.SleepingAllowed     = false;
                cellBody.BodyType            = BodyType.Kinematic;
                cellBody.CollisionCategories = Physics.CollisionLevel;

                cell.body = cellBody;
                bodies.Add(cellBody);
            }

            return(bodies);
        }
Esempio n. 2
0
        public static Body GeneratePolygons(List<VoronoiCell> cells, Level level, out List<Vector2[]> renderTriangles)
        {
            renderTriangles = new List<Vector2[]>();

            List<Vector2> tempVertices = new List<Vector2>();
            List<Vector2> bodyPoints = new List<Vector2>();

            Body cellBody = new Body(GameMain.World)
            {
                SleepingAllowed = false,
                BodyType = BodyType.Static,
                CollisionCategories = Physics.CollisionLevel
            };

            for (int n = cells.Count - 1; n >= 0; n-- )
            {
                VoronoiCell cell = cells[n];
                
                bodyPoints.Clear();
                tempVertices.Clear();
                foreach (GraphEdge ge in cell.Edges)
                {
                    if (Vector2.DistanceSquared(ge.Point1, ge.Point2) < 0.01f) continue;
                    if (!tempVertices.Any(v => Vector2.DistanceSquared(ge.Point1, v) < 1.0f))
                    {
                        tempVertices.Add(ge.Point1);
                        bodyPoints.Add(ge.Point1);
                    }
                    if (!tempVertices.Any(v => Vector2.DistanceSquared(ge.Point2, v) < 1.0f))
                    {
                        tempVertices.Add(ge.Point2);
                        bodyPoints.Add(ge.Point2);
                    }
                }

                if (tempVertices.Count < 3 || bodyPoints.Count < 2)
                {
                    cells.RemoveAt(n);
                    continue;
                }

                renderTriangles.AddRange(MathUtils.TriangulateConvexHull(tempVertices, cell.Center));
                
                if (bodyPoints.Count < 2) continue;

                if (bodyPoints.Count < 3)
                {
                    foreach (Vector2 vertex in tempVertices)
                    {
                        if (bodyPoints.Contains(vertex)) continue;
                        bodyPoints.Add(vertex);
                        break;
                    }
                }

                for (int i = 0; i < bodyPoints.Count; i++)
                {
                    cell.BodyVertices.Add(bodyPoints[i]);
                    bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]);
                }
                
                if (cell.CellType == CellType.Empty) continue;

                cellBody.UserData = cell;
                var triangles = MathUtils.TriangulateConvexHull(bodyPoints, ConvertUnits.ToSimUnits(cell.Center));
                
                for (int i = 0; i < triangles.Count; i++)
                {
                    //don't create a triangle if the area of the triangle is too small
                    //(apparently Farseer doesn't like polygons with a very small area, see Shape.ComputeProperties)
                    Vector2 a = triangles[i][0];
                    Vector2 b = triangles[i][1];
                    Vector2 c = triangles[i][2];
                    float area = Math.Abs(a.X * (b.Y - c.Y) + b.X * (c.Y - a.Y) + c.X * (a.Y - b.Y)) / 2.0f;
                    if (area < 1.0f) continue;

                    Vertices bodyVertices = new Vertices(triangles[i]);
                    var newFixture = FixtureFactory.AttachPolygon(bodyVertices, 5.0f, cellBody);
                    newFixture.UserData = cell;

                    if (newFixture.Shape.MassData.Area < FarseerPhysics.Settings.Epsilon)
                    {
                        DebugConsole.ThrowError("Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + ")");
                        GameAnalyticsManager.AddErrorEventOnce(
                            "CaveGenerator.GeneratePolygons:InvalidTriangle",
                            GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                            "Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + "). Seed: " + level.Seed);
                    }
                }
                
                cell.Body = cellBody;
            }

            return cellBody;
        }
Esempio n. 3
0
        public static List <Body> GeneratePolygons(List <VoronoiCell> cells, Level level, out List <Vector2[]> renderTriangles, bool setSolid = true)
        {
            renderTriangles = new List <Vector2[]>();
            var bodies = new List <Body>();

            List <Vector2> tempVertices = new List <Vector2>();
            List <Vector2> bodyPoints   = new List <Vector2>();

            Body cellBody = new Body(GameMain.World)
            {
                SleepingAllowed     = false,
                BodyType            = BodyType.Static,
                CollisionCategories = Physics.CollisionLevel
            };

            bodies.Add(cellBody);

            for (int n = cells.Count - 1; n >= 0; n--)
            {
                VoronoiCell cell = cells[n];

                bodyPoints.Clear();
                tempVertices.Clear();
                foreach (GraphEdge ge in cell.edges)
                {
                    if (Math.Abs(Vector2.Distance(ge.point1, ge.point2)) < 0.1f)
                    {
                        continue;
                    }
                    if (!tempVertices.Contains(ge.point1))
                    {
                        tempVertices.Add(ge.point1);
                    }
                    if (!tempVertices.Contains(ge.point2))
                    {
                        tempVertices.Add(ge.point2);
                    }

                    VoronoiCell adjacentCell = ge.AdjacentCell(cell);
                    //if (adjacentCell!=null && cells.Contains(adjacentCell)) continue;

                    if (setSolid)
                    {
                        ge.isSolid = (adjacentCell == null || !cells.Contains(adjacentCell));
                    }

                    if (!bodyPoints.Contains(ge.point1))
                    {
                        bodyPoints.Add(ge.point1);
                    }
                    if (!bodyPoints.Contains(ge.point2))
                    {
                        bodyPoints.Add(ge.point2);
                    }
                }

                if (tempVertices.Count < 3 || bodyPoints.Count < 2)
                {
                    cells.RemoveAt(n);
                    continue;
                }

                renderTriangles.AddRange(MathUtils.TriangulateConvexHull(tempVertices, cell.Center));

                if (bodyPoints.Count < 2)
                {
                    continue;
                }

                if (bodyPoints.Count < 3)
                {
                    foreach (Vector2 vertex in tempVertices)
                    {
                        if (bodyPoints.Contains(vertex))
                        {
                            continue;
                        }
                        bodyPoints.Add(vertex);
                        break;
                    }
                }

                for (int i = 0; i < bodyPoints.Count; i++)
                {
                    cell.bodyVertices.Add(bodyPoints[i]);
                    bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]);
                }

                if (cell.CellType == CellType.Empty)
                {
                    continue;
                }

                cellBody.UserData = cell;
                var triangles = MathUtils.TriangulateConvexHull(bodyPoints, ConvertUnits.ToSimUnits(cell.Center));

                for (int i = 0; i < triangles.Count; i++)
                {
                    //don't create a triangle if any of the vertices are too close to each other
                    //(apparently Farseer doesn't like polygons with a very small area, see Shape.ComputeProperties)
                    if (Vector2.DistanceSquared(triangles[i][0], triangles[i][1]) < 0.006f ||
                        Vector2.DistanceSquared(triangles[i][0], triangles[i][2]) < 0.006f ||
                        Vector2.DistanceSquared(triangles[i][1], triangles[i][2]) < 0.006f)
                    {
                        continue;
                    }

                    Vertices bodyVertices = new Vertices(triangles[i]);
                    var      newFixture   = FixtureFactory.AttachPolygon(bodyVertices, 5.0f, cellBody);
                    newFixture.UserData = cell;

                    if (newFixture.Shape.MassData.Area < FarseerPhysics.Settings.Epsilon)
                    {
                        DebugConsole.ThrowError("Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + ")");
                        GameAnalyticsManager.AddErrorEventOnce(
                            "CaveGenerator.GeneratePolygons:InvalidTriangle",
                            GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                            "Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + "). Seed: " + level.Seed);
                    }
                }
                cell.body = cellBody;
            }

            return(bodies);
        }