diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj
index 1cb29cd22..a7f2cdc70 100644
--- a/Subsurface/Barotrauma.csproj
+++ b/Subsurface/Barotrauma.csproj
@@ -127,6 +127,7 @@
+
diff --git a/Subsurface/Source/Map/Levels/CaveGenerator.cs b/Subsurface/Source/Map/Levels/CaveGenerator.cs
new file mode 100644
index 000000000..ee789b836
--- /dev/null
+++ b/Subsurface/Source/Map/Levels/CaveGenerator.cs
@@ -0,0 +1,554 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using Microsoft.Xna.Framework;
+using Voronoi2;
+using Microsoft.Xna.Framework.Graphics;
+using FarseerPhysics;
+using FarseerPhysics.Common;
+using FarseerPhysics.Dynamics;
+using FarseerPhysics.Factories;
+
+namespace Barotrauma
+{
+ static class CaveGenerator
+ {
+ public static List CarveCave(List cells, Vector2 startPoint, out List newCells)
+ {
+ Voronoi voronoi = new Voronoi(1.0);
+
+ List sites = new List();
+
+ float sideInterval = 400.0f;
+
+ Vector4 edges = new Vector4(
+ cells.Min(x => x.edges.Min(e => e.point1.X)),
+ cells.Min(x => x.edges.Min(e => e.point1.Y)),
+ cells.Max(x => x.edges.Max(e => e.point1.X)),
+ cells.Max(x => x.edges.Max(e => e.point1.Y)));
+
+ edges.X -= sideInterval * 2;
+ edges.Y -= sideInterval * 2;
+ edges.Z += sideInterval * 2;
+ edges.W += sideInterval * 2;
+
+ Rectangle borders = new Rectangle((int)edges.X, (int)edges.Y, (int)(edges.Z - edges.X), (int)(edges.W - edges.Y));
+
+ for (float x = edges.X + sideInterval; x < edges.Z - sideInterval; x += sideInterval)
+ {
+ for (float y = edges.Y + sideInterval; y < edges.W - sideInterval; y += sideInterval)
+ {
+ sites.Add(new Vector2(x, y) + Rand.Vector(sideInterval*0.45f, false));
+ }
+ }
+
+ List graphEdges = voronoi.MakeVoronoiGraph(sites, edges.X, edges.Y, edges.Z, edges.W);
+
+ List[,] cellGrid;
+ newCells = GraphEdgesToCells(graphEdges, borders, 1000, out cellGrid);
+
+ //remove cells that aren't inside any of the original "base cells"
+ foreach (VoronoiCell cell in newCells)
+ {
+ if (cell.edges.Any(e =>
+ e.point1.X == edges.X || e.point1.X == edges.Z ||
+ e.point1.Y == edges.Z || e.point1.Y == edges.W))
+ {
+ cell.CellType = CellType.Removed;
+ continue;
+ }
+
+ if (cells.Any(c => c.IsPointInside(cell.Center))) continue;
+ foreach (GraphEdge edge in cell.edges)
+ {
+ var adjacent = edge.AdjacentCell(cell);
+ if (adjacent != null && adjacent.CellType != CellType.Removed) adjacent.CellType = CellType.Edge;
+ }
+
+ cell.CellType = CellType.Removed;
+ }
+
+ newCells.RemoveAll(newCell => newCell.CellType == CellType.Removed);
+
+ VoronoiCell startCell = null;
+ float closestDist = 0.0f;
+ foreach (VoronoiCell cell in newCells)
+ {
+ float dist = Vector2.Distance(startPoint, cell.Center);
+ if (dist < closestDist || startCell == null)
+ {
+ startCell = cell;
+ closestDist = dist;
+ }
+ }
+
+ startCell.CellType = CellType.Path;
+
+ List path = new List() {startCell};
+ //VoronoiCell pathCell = startCell;
+ //for (int i = 0; i < newCells.Count / 2; i++)
+ //{
+
+ // var allowdNextCells = new List();
+ // foreach (GraphEdge edge in pathCell.edges)
+ // {
+ // var adjacent = edge.AdjacentCell(pathCell);
+ // if (adjacent == null ||
+ // adjacent.CellType == CellType.Path ||
+ // adjacent.CellType == CellType.Removed ||
+ // adjacent.CellType == CellType.Edge) continue;
+
+ // allowdNextCells.Add(adjacent);
+ // }
+
+ // if (allowdNextCells.Count == 0) break;
+
+ // pathCell = allowdNextCells[Rand.Int(allowdNextCells.Count, false)];
+ // path.Add(pathCell);
+ //}
+
+ return path;
+ }
+
+ public static List GraphEdgesToCells(List graphEdges, Rectangle borders, float gridCellSize, out List[,] cellGrid)
+ {
+ List cells = new List();
+
+ cellGrid = new List[(int)Math.Ceiling(borders.Width / gridCellSize), (int)Math.Ceiling(borders.Height / gridCellSize)];
+ for (int x = 0; x < borders.Width / gridCellSize; x++)
+ {
+ for (int y = 0; y < borders.Height / gridCellSize; y++)
+ {
+ cellGrid[x, y] = new List();
+ }
+ }
+
+ foreach (GraphEdge ge in graphEdges)
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ Site site = (i == 0) ? ge.site1 : ge.site2;
+
+ VoronoiCell cell = cellGrid[
+ (int)Math.Floor((site.coord.x-borders.X) / gridCellSize),
+ (int)Math.Floor((site.coord.y-borders.Y) / gridCellSize)].Find(c => c.site == site);
+
+ if (cell == null)
+ {
+ cell = new VoronoiCell(site);
+ cellGrid[
+ (int)Math.Floor((cell.Center.X-borders.X) / gridCellSize),
+ (int)Math.Floor((cell.Center.Y - borders.Y) / gridCellSize)].Add(cell);
+ cells.Add(cell);
+ }
+
+ if (ge.cell1 == null)
+ {
+ ge.cell1 = cell;
+ }
+ else
+ {
+ ge.cell2 = cell;
+ }
+ cell.edges.Add(ge);
+ }
+ }
+
+ return cells;
+ }
+
+
+ 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 List GeneratePath(
+ List pathNodes, List cells, List[,] cellGrid,
+ int gridCellSize, Rectangle limits, float wanderAmount = 0.3f, bool mirror = false, Vector2? gridOffset = null)
+ {
+ var targetCells = new List();
+ for (int i = 0; i < pathNodes.Count; i++)
+ {
+ int cellIndex = FindCellIndex(pathNodes[i], cells, cellGrid, gridCellSize, 2, gridOffset);
+ targetCells.Add(cells[cellIndex]);
+ }
+
+ return GeneratePath(targetCells, cells, cellGrid, gridCellSize, limits, wanderAmount, mirror);
+ }
+
+
+ public static List GeneratePath(
+ List targetCells, List cells, List[,] cellGrid,
+ int gridCellSize, Rectangle limits, float wanderAmount = 0.3f, bool mirror = false)
+ {
+ Stopwatch sw2 = new Stopwatch();
+ sw2.Start();
+
+ //how heavily the path "steers" towards the endpoint
+ //lower values will cause the path to "wander" more, higher will make it head straight to the end
+ wanderAmount = MathHelper.Clamp(wanderAmount, 0.0f, 1.0f);
+
+ List allowedEdges = new List();
+ List pathCells = new List();
+
+ VoronoiCell currentCell = targetCells[0];
+ currentCell.CellType = CellType.Path;
+ pathCells.Add(currentCell);
+
+ int currentTargetIndex = 1;
+
+ do
+ {
+ int edgeIndex = 0;
+
+ allowedEdges.Clear();
+ foreach (GraphEdge edge in currentCell.edges)
+ {
+ if (!limits.Contains(edge.AdjacentCell(currentCell).Center)) continue;
+
+ allowedEdges.Add(edge);
+ }
+
+ //steer towards target
+ if (Rand.Range(0.0f, 1.0f, false) > wanderAmount || allowedEdges.Count == 0)
+ {
+ for (int i = 0; i < currentCell.edges.Count; i++)
+ {
+ if (!MathUtils.LinesIntersect(currentCell.Center, targetCells[currentTargetIndex].Center,
+ currentCell.edges[i].point1, currentCell.edges[i].point2)) continue;
+ edgeIndex = i;
+ break;
+ }
+ }
+ //choose random edge (ignoring ones where the adjacent cell is outside limits)
+ else
+ {
+
+
+ //if (allowedEdges.Count==0)
+ //{
+ // edgeIndex = Rand.Int(currentCell.edges.Count, false);
+ //}
+ //else
+ //{
+ edgeIndex = Rand.Int(allowedEdges.Count, false);
+ if (mirror && edgeIndex > 0) edgeIndex = allowedEdges.Count - edgeIndex;
+ edgeIndex = currentCell.edges.IndexOf(allowedEdges[edgeIndex]);
+ //}
+ }
+
+ currentCell = currentCell.edges[edgeIndex].AdjacentCell(currentCell);
+ currentCell.CellType = CellType.Path;
+ pathCells.Add(currentCell);
+
+ if (currentCell == targetCells[currentTargetIndex])
+ {
+ currentTargetIndex += 1;
+ if (currentTargetIndex >= targetCells.Count) break;
+ }
+
+ } while (currentCell != targetCells[targetCells.Count - 1]);
+
+
+ Debug.WriteLine("gettooclose: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ return pathCells;
+ }
+
+ public static List GeneratePolygons(List cells, out List verticeList, bool setSolid=true)
+ {
+ verticeList = new List();
+ var bodies = new List();
+
+ List tempVertices = new List();
+ List bodyPoints = new List();
+
+ 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])
+ {
+ verticeList.Add(new VertexPositionColor(new Vector3(vertex, 0.0f), Color.Black));
+ }
+ }
+
+ 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]);
+ }
+
+ triangles = MathUtils.TriangulateConvexHull(bodyPoints, cell.Center);
+
+ Body edgeBody = new Body(GameMain.World);
+
+ for (int i = 0; i < triangles.Count; i++)
+ {
+ if (triangles[i][0].Y == triangles[i][1].Y && triangles[i][0].Y == triangles[i][2].Y) continue;
+ if (triangles[i][0].X == triangles[i][1].X && triangles[i][0].X == triangles[i][2].X) continue;
+
+ if (Vector2.DistanceSquared(triangles[i][0], triangles[i][1]) < 0.1f) continue;
+ if (Vector2.DistanceSquared(triangles[i][1], triangles[i][2]) < 0.1f) continue;
+
+ Vertices bodyVertices = new Vertices(triangles[i]);
+ FixtureFactory.AttachPolygon(bodyVertices, 5.0f, edgeBody);
+ }
+
+ edgeBody.UserData = cell;
+ edgeBody.SleepingAllowed = false;
+ edgeBody.BodyType = BodyType.Kinematic;
+ edgeBody.CollisionCategories = Physics.CollisionLevel;
+
+ cell.body = edgeBody;
+ bodies.Add(edgeBody);
+ }
+
+ return bodies;
+ }
+
+ public static VertexPositionTexture[] GenerateWallShapes(List cells)
+ {
+ float inwardThickness = 500.0f, outWardThickness = 30.0f;
+
+ List verticeList = new List();
+
+ 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 = null;
+ if (edge.cell2 != null && edge.cell2.body == null) 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 = null, rightEdge = null;
+
+ foreach (GraphEdge edge2 in cell.edges)
+ {
+ if (edge == edge2) continue;
+ if (edge.point1 == edge2.point1 ||
+ edge.point1 == edge2.point2)
+ {
+ leftEdge = edge2;
+ }
+ else if (edge.point2 == edge2.point2 || edge.point2 == edge2.point1)
+ {
+ rightEdge = edge2;
+ }
+ }
+
+ 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 right normal");
+#endif
+ 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
+ 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();
+ }
+
+ ///
+ /// find the index of the cell which the point is inside
+ /// (actually finds the cell whose center is closest, but it's always the correct cell assuming the point is inside the borders of the diagram)
+ ///
+ public static int FindCellIndex(Vector2 position,List cells, List[,] cellGrid, int gridCellSize, int searchDepth = 1, Vector2? offset = null)
+ {
+ float closestDist = 0.0f;
+ VoronoiCell closestCell = null;
+
+ Vector2 gridOffset = offset == null ? Vector2.Zero : (Vector2)offset;
+ position -= gridOffset;
+
+ int gridPosX = (int)Math.Floor(position.X / gridCellSize);
+ int gridPosY = (int)Math.Floor(position.Y / gridCellSize);
+
+ for (int x = Math.Max(gridPosX - searchDepth, 0); x <= Math.Min(gridPosX + searchDepth, cellGrid.GetLength(0) - 1); x++)
+ {
+ for (int y = Math.Max(gridPosY - searchDepth, 0); y <= Math.Min(gridPosY + searchDepth, cellGrid.GetLength(1) - 1); y++)
+ {
+ for (int i = 0; i < cellGrid[x, y].Count; i++)
+ {
+ float dist = Vector2.Distance(cellGrid[x, y][i].Center, position);
+ if (closestDist != 0.0f && dist > closestDist) continue;
+
+ closestDist = dist;
+ closestCell = cellGrid[x, y][i];
+ }
+ }
+ }
+
+ if (cells.IndexOf(closestCell) == -1)
+ {
+ int asdf = 1;
+ }
+
+ return cells.IndexOf(closestCell);
+ }
+
+
+ }
+}
diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs
index 69a73c480..c5e99c239 100644
--- a/Subsurface/Source/Map/Levels/Level.cs
+++ b/Subsurface/Source/Map/Levels/Level.cs
@@ -44,7 +44,7 @@ namespace Barotrauma
private int siteInterval;
- public const int GridCellWidth = 2000;
+ public const int GridCellSize = 2000;
private List[,] cellGrid;
private WrappingWall[,] wrappingWalls;
@@ -245,58 +245,17 @@ namespace Barotrauma
Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms");
sw2.Restart();
-
- cellGrid = new List[borders.Width / GridCellWidth, borders.Height / GridCellWidth];
- for (int x = 0; x < borders.Width / GridCellWidth; x++)
- {
- for (int y = 0; y < borders.Height / GridCellWidth; y++)
- {
- cellGrid[x, y] = new List();
- }
- }
-
+
//construct voronoi cells based on the graph edges
- cells = new List();
- foreach (GraphEdge ge in graphEdges)
- {
- for (int i = 0; i < 2; i++)
- {
- Site site = (i == 0) ? ge.site1 : ge.site2;
-
- VoronoiCell cell = cellGrid[
- (int)Math.Floor(site.coord.x / GridCellWidth),
- (int)Math.Floor(site.coord.y / GridCellWidth)].Find(c => c.site == site);
-
- if (cell == null)
- {
- cell = new VoronoiCell(site);
- cellGrid[(int)Math.Floor(cell.Center.X / GridCellWidth), (int)Math.Floor(cell.Center.Y / GridCellWidth)].Add(cell);
- cells.Add(cell);
- }
-
- if (ge.cell1 == null)
- {
- ge.cell1 = cell;
- }
- else
- {
- ge.cell2 = cell;
- }
- cell.edges.Add(ge);
- }
- }
+ cells = CaveGenerator.GraphEdgesToCells(graphEdges, borders, GridCellSize, out cellGrid);
Debug.WriteLine("find cells: " + sw2.ElapsedMilliseconds + " ms");
sw2.Restart();
+
+ List pathCells = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize,
+ new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.3f, mirror);
-
- //if (mirror)
- //{
- // pathNodes.Reverse();
- //}
-
- List pathCells = GeneratePath(pathNodes, cells,
- new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), minWidth, 0.3f, mirror, true);
+ EnlargeMainPath(pathCells, minWidth);
foreach (InterestingPosition positionOfInterest in positionsOfInterest)
{
@@ -305,20 +264,19 @@ namespace Barotrauma
}
startPosition.X = pathCells[0].Center.X;
- //endPosition = pathCells[pathCells.Count - 1].Center;
foreach (List tunnel in smallTunnels)
{
if (tunnel.Count<2) continue;
//find the cell which the path starts from
- int startCellIndex = FindCellIndex(tunnel[0]);
+ int startCellIndex = CaveGenerator.FindCellIndex(tunnel[0], cells, cellGrid, GridCellSize, 1);
if (startCellIndex < 0) continue;
//if it wasn't one of the cells in the main path, don't create a tunnel
- if (!pathCells.Contains(cells[startCellIndex])) continue;
+ if (cells[startCellIndex].CellType != CellType.Path) continue;
- var newPathCells = GeneratePath(tunnel, cells, pathBorders, 0.0f, 0.0f);
+ var newPathCells = CaveGenerator.GeneratePath(tunnel, cells, cellGrid, GridCellSize, pathBorders);
positionsOfInterest.Add(new InterestingPosition(tunnel.Last(), false));
@@ -339,9 +297,13 @@ namespace Barotrauma
// GeneratePath(rand, tunnelStart, new Vector2(tunnelStart.X, borders.Height), cells, pathBorders, minWidth, 0.1f, mirror)
// );
//}
+
+
cells = CleanCells(pathCells);
+
+
pathCells.AddRange(CreateBottomHoles(Rand.Range(0.2f,0.8f, false), new Rectangle(
(int)(borders.Width * 0.2f), 0,
(int)(borders.Width * 0.6f), (int)(borders.Height * 0.3f))));
@@ -351,6 +313,45 @@ namespace Barotrauma
cells.Remove(cell);
}
+ //for (int i = 0; i < 3; i++)
+ //{
+ // Vector2 startPoint = Vector2.Zero;
+ // VoronoiCell startCell = null;
+
+ // while (true)
+ // {
+ // startCell = cells[Rand.Int(cells.Count, false)];
+
+ // GraphEdge startEdge =
+ // startCell.edges.Find(e => pathCells.Contains(e.AdjacentCell(startCell)));
+
+ // if (startEdge != null)
+ // {
+ // startPoint = (startEdge.point1 + startEdge.point2) / 2.0f;
+ // break;
+ // }
+ // }
+
+ // var caveCells = GetCells(startCell.Center, 1);
+
+ // List caveSolidCells;
+
+ // var cavePathCells = CaveGenerator.CarveCave(caveCells, startPoint, out caveSolidCells);
+
+ // caveCells.ForEach(c => cells.Remove(c));
+
+ // //caveSolidCells = CleanCells(cavePathCells);
+
+ // cells.AddRange(caveSolidCells);
+
+ // foreach (VoronoiCell cell in cavePathCells)
+ // {
+ // cells.Remove(cell);
+ // }
+
+ // pathCells.AddRange(cavePathCells);
+ //}
+
for (int x = 0; x < cellGrid.GetLength(0); x++)
{
for (int y = 0; y < cellGrid.GetLength(1); y++)
@@ -361,14 +362,19 @@ namespace Barotrauma
foreach (VoronoiCell cell in cells)
{
- cellGrid[(int)Math.Floor(cell.Center.X / GridCellWidth), (int)Math.Floor(cell.Center.Y / GridCellWidth)].Add(cell);
+ cellGrid[(int)Math.Floor(cell.Center.X / GridCellSize), (int)Math.Floor(cell.Center.Y / GridCellSize)].Add(cell);
}
+
+
startPosition.Y = borders.Height;
endPosition.Y = borders.Height;
- renderer.SetBodyVertices(GeneratePolygons(cells, pathCells));
- renderer.SetWallVertices(GenerateWallShapes(cells));
+ List bodyVertices;
+ bodies = CaveGenerator.GeneratePolygons(cells, out bodyVertices);
+
+ renderer.SetBodyVertices(bodyVertices.ToArray());
+ renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells));
wrappingWalls = new WrappingWall[2, 2];
@@ -380,13 +386,11 @@ namespace Barotrauma
wrappingWalls[side, i] = new WrappingWall(pathCells, cells, borders.Height * 0.5f,
(side == 0 ? -1 : 1) * (i == 0 ? 1 : 2));
- wrappingWalls[side, i].SetBodyVertices(GeneratePolygons(wrappingWalls[side, i].Cells, new List(), false));
- wrappingWalls[side, i].SetWallVertices(GenerateWallShapes(wrappingWalls[side, i].Cells));
- //wrappingWalls[side, i].Cells[0].edges[1].isSolid = false;
- //wrappingWalls[side, i].Cells[0].edges[3].isSolid = false;
+ List wrappingWallVertices;
+ CaveGenerator.GeneratePolygons(wrappingWalls[side, i].Cells, out wrappingWallVertices, false);
- //wrappingWalls[side, i].Cells[wrappingWalls[side, i].Cells.Count-1].edges[1].isSolid = false;
- //wrappingWalls[side, i].Cells[wrappingWalls[side, i].Cells.Count - 1].edges[3].isSolid = false;
+ wrappingWalls[side, i].SetBodyVertices(wrappingWallVertices.ToArray());
+ wrappingWalls[side, i].SetWallVertices(CaveGenerator.GenerateWallShapes(wrappingWalls[side, i].Cells));
}
}
@@ -446,132 +450,6 @@ namespace Barotrauma
Debug.WriteLine("**********************************************************************************");
}
- private List GeneratePath(List points, List cells, Microsoft.Xna.Framework.Rectangle limits, float minWidth, float wanderAmount = 0.3f, bool mirror=false, bool placeWaypoints=false)
- {
- Stopwatch sw2 = new Stopwatch();
- sw2.Start();
-
- //how heavily the path "steers" towards the endpoint
- //lower values will cause the path to "wander" more, higher will make it head straight to the end
- wanderAmount = MathHelper.Clamp(wanderAmount, 0.0f, 1.0f);
-
- List allowedEdges = new List();
- List pathCells = new List();
-
- VoronoiCell[] targetCells = new VoronoiCell[points.Count];
- for (int i = 0; i wanderAmount || allowedEdges.Count == 0)
- {
- for (int i = 0; i < currentCell.edges.Count; i++)
- {
- if (!MathUtils.LinesIntersect(currentCell.Center, targetCells[currentTargetIndex].Center,
- currentCell.edges[i].point1, currentCell.edges[i].point2)) continue;
- edgeIndex = i;
- break;
- }
- }
- //choose random edge (ignoring ones where the adjacent cell is outside limits)
- else
- {
-
-
- //if (allowedEdges.Count==0)
- //{
- // edgeIndex = Rand.Int(currentCell.edges.Count, false);
- //}
- //else
- //{
- edgeIndex = Rand.Int(allowedEdges.Count, false);
- if (mirror && edgeIndex > 0) edgeIndex = allowedEdges.Count - edgeIndex;
- edgeIndex = currentCell.edges.IndexOf(allowedEdges[edgeIndex]);
- //}
- }
-
- currentCell = currentCell.edges[edgeIndex].AdjacentCell(currentCell);
- pathCells.Add(currentCell);
-
- if (currentCell==targetCells[currentTargetIndex])
- {
- currentTargetIndex += 1;
- if (currentTargetIndex>=targetCells.Length) break;
- }
-
- } while (currentCell != targetCells[targetCells.Length-1]);
-
- if (placeWaypoints)
- {
- WayPoint newWaypoint = new WayPoint(new Rectangle((int)pathCells[0].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null);
- newWaypoint.MoveWithLevel = true;
-
- WayPoint prevWaypoint = newWaypoint;
-
- for (int i = 0; i < pathCells.Count; i++)
- {
- //clean "loops" from the path
- for (int n = 0; n < i; n++)
- {
- if (pathCells[n] != pathCells[i]) continue;
-
- pathCells.RemoveRange(n+1, i-n);
- break;
- }
- if (i >= pathCells.Count) break;
-
- newWaypoint = new WayPoint(new Rectangle((int)pathCells[i].Center.X, (int)pathCells[i].Center.Y, 10, 10), null);
- newWaypoint.MoveWithLevel = true;
- if (prevWaypoint != null)
- {
- prevWaypoint.linkedTo.Add(newWaypoint);
- newWaypoint.linkedTo.Add(prevWaypoint);
- }
- prevWaypoint = newWaypoint;
- }
-
- newWaypoint = new WayPoint(new Rectangle((int)pathCells[pathCells.Count - 1].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null);
- newWaypoint.MoveWithLevel = true;
-
- prevWaypoint.linkedTo.Add(newWaypoint);
- newWaypoint.linkedTo.Add(prevWaypoint);
-
- }
-
- Debug.WriteLine("genpath: " + sw2.ElapsedMilliseconds + " ms");
- sw2.Restart();
-
- List removedCells = GetTooCloseCells(pathCells, minWidth);
- foreach (VoronoiCell removedCell in removedCells)
- {
- if (pathCells.Contains(removedCell)) continue;
- pathCells.Add(removedCell);
- }
-
- Debug.WriteLine("gettooclose: " + sw2.ElapsedMilliseconds + " ms");
- sw2.Restart();
-
- return pathCells;
- }
private List CreateBottomHoles(float holeProbability, Rectangle limits)
{
@@ -593,6 +471,55 @@ namespace Barotrauma
//}
}
+ private void EnlargeMainPath(List pathCells, float minWidth)
+ {
+
+ WayPoint newWaypoint = new WayPoint(new Rectangle((int)pathCells[0].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null);
+ newWaypoint.MoveWithLevel = true;
+
+ WayPoint prevWaypoint = newWaypoint;
+
+ for (int i = 0; i < pathCells.Count; i++)
+ {
+ //clean "loops" from the path
+ for (int n = 0; n < i; n++)
+ {
+ if (pathCells[n] != pathCells[i]) continue;
+
+ pathCells.RemoveRange(n + 1, i - n);
+ break;
+ }
+ if (i >= pathCells.Count) break;
+
+ newWaypoint = new WayPoint(new Rectangle((int)pathCells[i].Center.X, (int)pathCells[i].Center.Y, 10, 10), null);
+ newWaypoint.MoveWithLevel = true;
+ if (prevWaypoint != null)
+ {
+ prevWaypoint.linkedTo.Add(newWaypoint);
+ newWaypoint.linkedTo.Add(prevWaypoint);
+ }
+ prevWaypoint = newWaypoint;
+ }
+
+ newWaypoint = new WayPoint(new Rectangle((int)pathCells[pathCells.Count - 1].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null);
+ newWaypoint.MoveWithLevel = true;
+
+ prevWaypoint.linkedTo.Add(newWaypoint);
+ newWaypoint.linkedTo.Add(prevWaypoint);
+
+ if (minWidth > 0.0f)
+ {
+ List removedCells = GetTooCloseCells(pathCells, minWidth);
+ foreach (VoronoiCell removedCell in removedCells)
+ {
+ if (removedCell.CellType == CellType.Path) continue;
+
+ pathCells.Add(removedCell);
+ removedCell.CellType = CellType.Path;
+ }
+ }
+ }
+
private List GetTooCloseCells(List emptyCells, float minDistance)
{
List tooCloseCells = new List();
@@ -634,7 +561,7 @@ namespace Barotrauma
{
Vector2 cornerPos = position + new Vector2(x,y);
- int cellIndex = FindCellIndex(cornerPos);
+ int cellIndex = CaveGenerator.FindCellIndex(cornerPos, cells, cellGrid, GridCellSize);
if (cellIndex == -1) continue;
if (!tooCloseCells.Contains(cells[cellIndex]))
{
@@ -672,294 +599,6 @@ namespace Barotrauma
return newCells;
}
- ///
- /// find the index of the cell which the point is inside
- /// (actually finds the cell whose center is closest, but it's always the correct cell assuming the point is inside the borders of the diagram)
- ///
- private int FindCellIndex(Vector2 position, int searchDepth = 1)
- {
- float closestDist = 0.0f;
- VoronoiCell closestCell = null;
-
- int gridPosX = (int)Math.Floor(position.X / GridCellWidth);
- int gridPosY = (int)Math.Floor(position.Y / GridCellWidth);
-
- for (int x = Math.Max(gridPosX - searchDepth, 0); x <= Math.Min(gridPosX + searchDepth, cellGrid.GetLength(0) - 1); x++)
- {
- for (int y = Math.Max(gridPosY - searchDepth, 0); y <= Math.Min(gridPosY + searchDepth, cellGrid.GetLength(1) - 1); y++)
- {
- for (int i = 0; i < cellGrid[x, y].Count; i++)
- {
- float dist = Vector2.Distance(cellGrid[x, y][i].Center, position);
- if (closestDist != 0.0f && dist > closestDist) continue;
-
- closestDist = dist;
- closestCell = cellGrid[x, y][i];
- }
- }
- }
-
- return cells.IndexOf(closestCell);
- }
-
-
- private VertexPositionColor[] GeneratePolygons(List cells, List emptyCells, bool setSolid=true)
- {
- List verticeList = new List();
- //bodies = new List();
-
- List tempVertices = new List();
- List bodyPoints = new List();
-
- 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 = true;
-
- 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])
- {
- verticeList.Add(new VertexPositionColor(new Vector3(vertex, 0.0f), Color.Black));
- }
- }
-
- 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]);
- }
-
- triangles = MathUtils.TriangulateConvexHull(bodyPoints, cell.Center);
-
- Body edgeBody = new Body(GameMain.World);
-
- for (int i = 0; i < triangles.Count; i++)
- {
- if (triangles[i][0].Y == triangles[i][1].Y && triangles[i][0].Y == triangles[i][2].Y) continue;
- if (triangles[i][0].X == triangles[i][1].X && triangles[i][0].X == triangles[i][2].X) continue;
-
- if (Vector2.DistanceSquared(triangles[i][0], triangles[i][1]) < 0.1f) continue;
- if (Vector2.DistanceSquared(triangles[i][1], triangles[i][2]) < 0.1f) continue;
-
- Vertices bodyVertices = new Vertices(triangles[i]);
- FixtureFactory.AttachPolygon(bodyVertices, 5.0f, edgeBody);
- }
-
- edgeBody.UserData = cell;
- edgeBody.SleepingAllowed = false;
- edgeBody.BodyType = BodyType.Kinematic;
- edgeBody.CollisionCategories = Physics.CollisionLevel;
-
- cell.body = edgeBody;
- bodies.Add(edgeBody);
- }
-
- return verticeList.ToArray();
- }
-
- private VertexPositionTexture[] GenerateWallShapes(List cells)
- {
- float inwardThickness = 500.0f, outWardThickness = 30.0f;
-
- List verticeList = new List();
-
- 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 = null;
- if (edge.cell2 != null && edge.cell2.body == null) 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 = null, rightEdge = null;
-
- foreach (GraphEdge edge2 in cell.edges)
- {
- if (edge == edge2) continue;
- if (edge.point1 == edge2.point1 ||
- edge.point1 == edge2.point2)
- {
- leftEdge = edge2;
- }
- else if(edge.point2 == edge2.point2 || edge.point2 == edge2.point1)
- {
- rightEdge = edge2;
- }
- }
-
- 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 (!leftNormal.IsValid())
- {
-#if DEBUG
- DebugConsole.ThrowError("Invalid right normal");
-#endif
- 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 (!rightNormal.IsValid())
- {
-#if DEBUG
- DebugConsole.ThrowError("Invalid right normal");
-#endif
- 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();
- }
-
- private 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 Vector2 GetRandomItemPos(float offsetFromWall = 10.0f)
{
if (!positionsOfInterest.Any()) return Size*0.5f;
@@ -1001,17 +640,13 @@ namespace Barotrauma
if (!positionsOfInterest.Any()) return Size * 0.5f;
if (preferLarge==null)
- {
return positionsOfInterest[Rand.Int(positionsOfInterest.Count, !useSyncedRand)].Position;
- }
- else
- {
- var positionsWithSpace = positionsOfInterest.FindAll(p => (bool)preferLarge == p.IsLarge);
- if (!positionsWithSpace.Any()) return Size * 0.5f;
+
+ var positionsWithSpace = positionsOfInterest.FindAll(p => (bool)preferLarge == p.IsLarge);
+ if (!positionsWithSpace.Any()) return Size * 0.5f;
- return positionsWithSpace[Rand.Int(positionsWithSpace.Count, !useSyncedRand)].Position;
- }
+ return positionsWithSpace[Rand.Int(positionsWithSpace.Count, !useSyncedRand)].Position;
}
public void Update (float deltaTime)
@@ -1048,8 +683,8 @@ namespace Barotrauma
public List GetCells(Vector2 pos, int searchDepth = 2)
{
- int gridPosX = (int)Math.Floor(pos.X / GridCellWidth);
- int gridPosY = (int)Math.Floor(pos.Y / GridCellWidth);
+ int gridPosX = (int)Math.Floor(pos.X / GridCellSize);
+ int gridPosY = (int)Math.Floor(pos.Y / GridCellSize);
int startX = Math.Max(gridPosX - searchDepth, 0);
int endX = Math.Min(gridPosX + searchDepth, cellGrid.GetLength(0) - 1);
@@ -1090,72 +725,8 @@ namespace Barotrauma
return cells;
}
- public List GetCellEdges(Vector2 refPos, int searchDepth = 2, bool onlySolid = true)
- {
- int gridPosX = (int)Math.Floor(refPos.X / GridCellWidth);
- int gridPosY = (int)Math.Floor(refPos.Y / GridCellWidth);
-
- int startX = Math.Max(gridPosX - searchDepth, 0);
- int endX = Math.Min(gridPosX + searchDepth, cellGrid.GetLength(0) - 1);
-
- int startY = Math.Max(gridPosY - searchDepth, 0);
- int endY = Math.Min(gridPosY + searchDepth, cellGrid.GetLength(1) - 1);
-
- List edges = new List();
-
- for (int x = startX; x < endX; x++)
- {
- for (int y = startY; y < endY; y++)
- {
- foreach (VoronoiCell cell in cellGrid[x, y])
- {
- for (int i = 0; i < cell.edges.Count; i++)
- {
- if (onlySolid && !cell.edges[i].isSolid) continue;
-
- Vector2 start = cell.edges[i].point1;
- start.Y = -start.Y;
-
- Vector2 end = cell.edges[i].point2;
- end.Y = -end.Y;
-
- edges.Add(new Vector2[] { start, end });
- //GUI.DrawLine(spriteBatch, start, end, (cell.body != null && cell.body.Enabled) ? Color.Green : Color.Red);
- }
- }
- }
- }
-
- for (int side = 0; side < 2; side++ )
- {
- for (int n = 0 ; n<2; n++)
- {
- if (Vector2.Distance(wrappingWalls[side, n].MidPos, refPos) > WrappingWall.WallWidth) continue;
-
- foreach (VoronoiCell cell in wrappingWalls[side, n].Cells)
- {
- Vector2 offset = wrappingWalls[side, n].Offset;
- for (int i = 0; i < cell.edges.Count; i++)
- {
- if (onlySolid && !cell.edges[i].isSolid) continue;
- Vector2 start = cell.edges[i].point1 + offset;
- start.Y = -start.Y;
-
- Vector2 end = cell.edges[i].point2 + offset;
- end.Y = -end.Y;
-
- edges.Add(new Vector2[] { start, end });
- }
- }
- }
- }
-
- return edges;
- }
-
private void Unload()
{
-
renderer.Dispose();
renderer = null;
@@ -1173,11 +744,6 @@ namespace Barotrauma
bodies = null;
loaded = null;
-
-
-
- //vertexBuffer.Dispose();
- //vertexBuffer = null;
}
}
diff --git a/Subsurface/Source/Map/Levels/LevelRenderer.cs b/Subsurface/Source/Map/Levels/LevelRenderer.cs
index fe94afd35..577ce74a3 100644
--- a/Subsurface/Source/Map/Levels/LevelRenderer.cs
+++ b/Subsurface/Source/Map/Levels/LevelRenderer.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
+using Voronoi2;
namespace Barotrauma
{
@@ -157,6 +158,33 @@ namespace Barotrauma
{
Vector2 pos = new Vector2(0.0f, -level.Size.Y);// level.EndPosition;
+ var cells = level.GetCells(GameMain.GameScreen.Cam.WorldViewCenter, 2);
+ foreach (VoronoiCell cell in cells)
+ {
+ GUI.DrawRectangle(spriteBatch, new Vector2(cell.Center.X - 10.0f, -cell.Center.Y-10.0f), new Vector2(20.0f, 20.0f), Color.Cyan, true);
+
+ GUI.DrawLine(spriteBatch,
+ new Vector2(cell.edges[0].point1.X, -cell.edges[0].point1.Y),
+ new Vector2(cell.Center.X, -cell.Center.Y),
+ Color.White);
+
+ foreach (GraphEdge edge in cell.edges)
+ {
+ //GUI.DrawLine(spriteBatch,
+ // new Vector2(edge.point1.X, -edge.point1.Y),
+ // new Vector2(cell.Center.X, -cell.Center.Y),
+ // Color.White);
+
+ GUI.DrawLine(spriteBatch, new Vector2(edge.point1.X, -edge.point1.Y),
+ new Vector2(edge.point2.X, -edge.point2.Y), Color.White);
+ }
+
+ foreach (Vector2 point in cell.bodyVertices)
+ {
+ GUI.DrawRectangle(spriteBatch, new Vector2(point.X, -point.Y), new Vector2(10.0f, 10.0f), Color.White, true);
+ }
+ }
+
if (GameMain.GameScreen.Cam.WorldView.Y < -pos.Y - 512) return;
pos.X = GameMain.GameScreen.Cam.WorldView.X -512.0f;
@@ -169,6 +197,8 @@ namespace Barotrauma
Color.White, 0.0f,
Vector2.Zero,
SpriteEffects.None, 0.0f);
+
+
}
diff --git a/Subsurface/Source/Map/Levels/Voronoi.cs b/Subsurface/Source/Map/Levels/Voronoi.cs
index 3b456efbb..41a2252fa 100644
--- a/Subsurface/Source/Map/Levels/Voronoi.cs
+++ b/Subsurface/Source/Map/Levels/Voronoi.cs
@@ -972,6 +972,18 @@ namespace Voronoi2
return true;
}
+ public List MakeVoronoiGraph(List sites, float minX, float minY, float maxX, float maxY)
+ {
+ double[] xVal = new double[sites.Count];
+ double[] yVal = new double[sites.Count];
+ for (int i = 0; i < sites.Count; i++)
+ {
+ xVal[i] = sites[i].X;
+ yVal[i] = sites[i].Y;
+ }
+ return generateVoronoi(xVal, yVal, minX, maxX, minY, maxY);
+ }
+
public List MakeVoronoiGraph(List sites, int width, int height)
{
double[] xVal = new double[sites.Count];
diff --git a/Subsurface/Source/Map/Levels/VoronoiElements.cs b/Subsurface/Source/Map/Levels/VoronoiElements.cs
index b5ce48af9..57d0baff2 100644
--- a/Subsurface/Source/Map/Levels/VoronoiElements.cs
+++ b/Subsurface/Source/Map/Levels/VoronoiElements.cs
@@ -117,6 +117,11 @@ namespace Voronoi2
}
}
+ public enum CellType
+ {
+ Solid, Empty, Edge, Path, Removed
+ }
+
public class VoronoiCell
{
public List edges;
@@ -126,6 +131,8 @@ namespace Voronoi2
public Body body;
+ public CellType CellType;
+
public Vector2 Translation;
public Vector2 Center
@@ -174,6 +181,16 @@ namespace Voronoi2
//bodies = new List();
this.site = site;
}
+
+ public bool IsPointInside(Vector2 point)
+ {
+ foreach (GraphEdge edge in edges)
+ {
+ if (MathUtils.LinesIntersect(point, Center, edge.point1, edge.point2)) return false;
+ }
+
+ return true;
+ }
}
public class GraphEdge
diff --git a/Subsurface/Source/Map/Levels/WrappingWall.cs b/Subsurface/Source/Map/Levels/WrappingWall.cs
index 797a34bfb..cd290a1e5 100644
--- a/Subsurface/Source/Map/Levels/WrappingWall.cs
+++ b/Subsurface/Source/Map/Levels/WrappingWall.cs
@@ -198,8 +198,16 @@ namespace Barotrauma
protected virtual void Dispose(bool disposing)
{
- if (wallVertices!=null) wallVertices.Dispose();
- if (bodyVertices!=null) bodyVertices.Dispose();
+ if (wallVertices != null)
+ {
+ wallVertices.Dispose();
+ wallVertices = null;
+ }
+ if (bodyVertices != null)
+ {
+ bodyVertices.Dispose();
+ bodyVertices = null;
+ }
}
}
}