Unstable 1.2.4.0
This commit is contained in:
@@ -139,17 +139,17 @@ namespace Barotrauma
|
||||
return new Rectangle(rect.X - amount, rect.Y + amount, rect.Width + amount * 2, rect.Height + amount * 2);
|
||||
}
|
||||
|
||||
public static int VectorOrientation(Vector2 p1, Vector2 p2, Vector2 p)
|
||||
/// <summary>
|
||||
/// Given three points A, B and C,
|
||||
/// returns 1 if AC is oriented clockwise relative to AB,
|
||||
/// -1 if AC is oriented counter-clockwise relative to AB,
|
||||
/// or 0 if A, B and C are collinear.
|
||||
/// </summary>
|
||||
public static int VectorOrientation(Vector2 pointA, Vector2 pointB, Vector2 pointC)
|
||||
{
|
||||
// Determinant
|
||||
float Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y);
|
||||
float determinant = (pointB.X - pointA.X) * (pointC.Y - pointA.Y) - (pointC.X - pointA.X) * (pointB.Y - pointA.Y);
|
||||
|
||||
if (Orin > 0)
|
||||
return -1; // (* Orientation is to the left-hand side *)
|
||||
if (Orin < 0)
|
||||
return 1; // (* Orientation is to the right-hand side *)
|
||||
|
||||
return 0; // (* Orientation is neutral aka collinear *)
|
||||
return -Math.Sign(determinant);
|
||||
}
|
||||
|
||||
|
||||
@@ -1091,11 +1091,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
class CompareCCW : IComparer<Vector2>
|
||||
class CompareCW : IComparer<Vector2>
|
||||
{
|
||||
private Vector2 center;
|
||||
|
||||
public CompareCCW(Vector2 center)
|
||||
public CompareCW(Vector2 center)
|
||||
{
|
||||
this.center = center;
|
||||
}
|
||||
@@ -1106,25 +1106,43 @@ namespace Barotrauma
|
||||
|
||||
public static int Compare(Vector2 a, Vector2 b, Vector2 center)
|
||||
{
|
||||
if (a == b) return 0;
|
||||
if (a.X - center.X >= 0 && b.X - center.X < 0) return -1;
|
||||
if (a.X - center.X < 0 && b.X - center.X >= 0) return 1;
|
||||
if (a == b) { return 0; }
|
||||
if (a.X - center.X >= 0 && b.X - center.X < 0) { return 1; }
|
||||
if (a.X - center.X < 0 && b.X - center.X >= 0) { return -1; }
|
||||
if (a.X - center.X == 0 && b.X - center.X == 0)
|
||||
{
|
||||
if (a.Y - center.Y >= 0 || b.Y - center.Y >= 0) return Math.Sign(b.Y - a.Y);
|
||||
if (a.Y - center.Y >= 0 || b.Y - center.Y >= 0) { return Math.Sign(a.Y - b.Y); }
|
||||
return Math.Sign(a.Y - b.Y);
|
||||
}
|
||||
|
||||
// compute the cross product of vectors (center -> a) x (center -> b)
|
||||
float det = (a.X - center.X) * (b.Y - center.Y) - (b.X - center.X) * (a.Y - center.Y);
|
||||
if (det < 0) return -1;
|
||||
if (det > 0) return 1;
|
||||
if (det < 0) { return 1; }
|
||||
if (det > 0) { return -1; }
|
||||
|
||||
// points a and b are on the same line from the center
|
||||
// check which point is closer to the center
|
||||
float d1 = (a.X - center.X) * (a.X - center.X) + (a.Y - center.Y) * (a.Y - center.Y);
|
||||
float d2 = (b.X - center.X) * (b.X - center.X) + (b.Y - center.Y) * (b.Y - center.Y);
|
||||
return Math.Sign(d2 - d1);
|
||||
return Math.Sign(d1 - d2);
|
||||
}
|
||||
}
|
||||
|
||||
class CompareCCW : IComparer<Vector2>
|
||||
{
|
||||
private Vector2 center;
|
||||
|
||||
public CompareCCW(Vector2 center)
|
||||
{
|
||||
this.center = center;
|
||||
}
|
||||
public int Compare(Vector2 a, Vector2 b)
|
||||
{
|
||||
return -CompareCW.Compare(a, b, center);
|
||||
}
|
||||
public static int Compare(Vector2 a, Vector2 b, Vector2 center)
|
||||
{
|
||||
return -CompareCW.Compare(a, b, center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,14 @@ namespace Barotrauma
|
||||
{
|
||||
string subName = subElement.GetAttributeString("name", "");
|
||||
string ownedSubPath = Path.Combine(TempPath, subName + ".sub");
|
||||
ownedSubmarines.Add(new SubmarineInfo(ownedSubPath));
|
||||
if (!File.Exists(ownedSubPath))
|
||||
{
|
||||
DebugConsole.ThrowError($"Could not find the submarine \"{subName}\" ({ownedSubPath})! The save file may be corrupted. Removing the submarine from owned submarines...");
|
||||
}
|
||||
else
|
||||
{
|
||||
ownedSubmarines.Add(new SubmarineInfo(ownedSubPath));
|
||||
}
|
||||
}
|
||||
return ownedSubmarines;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma;
|
||||
|
||||
readonly record struct Quad2D(Vector2 A, Vector2 B, Vector2 C, Vector2 D)
|
||||
{
|
||||
public Vector2 Centroid => (A + B + C + D) / 4;
|
||||
|
||||
public static Quad2D FromRectangle(RectangleF rectangle)
|
||||
{
|
||||
return new Quad2D(
|
||||
A: (rectangle.Left, rectangle.Top),
|
||||
B: (rectangle.Right, rectangle.Top),
|
||||
C: (rectangle.Right, rectangle.Bottom),
|
||||
D: (rectangle.Left, rectangle.Bottom));
|
||||
}
|
||||
|
||||
public static Quad2D FromSubmarineRectangle(RectangleF rectangle)
|
||||
{
|
||||
return new Quad2D(
|
||||
A: (rectangle.X, rectangle.Y),
|
||||
B: (rectangle.X + rectangle.Width, rectangle.Y),
|
||||
C: (rectangle.X + rectangle.Width, rectangle.Y - rectangle.Height),
|
||||
D: (rectangle.X, rectangle.Y - rectangle.Height));
|
||||
}
|
||||
|
||||
public Quad2D Rotated(float radians)
|
||||
{
|
||||
return new Quad2D(
|
||||
A: MathUtils.RotatePointAroundTarget(point: A, target: Centroid, radians: radians),
|
||||
B: MathUtils.RotatePointAroundTarget(point: B, target: Centroid, radians: radians),
|
||||
C: MathUtils.RotatePointAroundTarget(point: C, target: Centroid, radians: radians),
|
||||
D: MathUtils.RotatePointAroundTarget(point: D, target: Centroid, radians: radians));
|
||||
}
|
||||
|
||||
public RectangleF BoundingAxisAlignedRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2 min = (
|
||||
X: Math.Min(A.X, Math.Min(B.X, Math.Min(C.X, D.X))),
|
||||
Y: Math.Min(A.Y, Math.Min(B.Y, Math.Min(C.Y, D.Y))));
|
||||
Vector2 max = (
|
||||
X: Math.Max(A.X, Math.Max(B.X, Math.Max(C.X, D.X))),
|
||||
Y: Math.Max(A.Y, Math.Max(B.Y, Math.Max(C.Y, D.Y))));
|
||||
return new RectangleF(location: min, size: max - min);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetEdges(Span<(Vector2 A, Vector2 B)> outputSpan)
|
||||
{
|
||||
if (outputSpan.Length < 4) { return false; }
|
||||
|
||||
outputSpan[0] = (A, B);
|
||||
outputSpan[1] = (B, C);
|
||||
outputSpan[2] = (C, D);
|
||||
outputSpan[3] = (D, A);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Contains(Vector2 point)
|
||||
{
|
||||
// Break up the quad into two triangles and then see if the point is in either triangle.
|
||||
// Since quads can be concave, care needs to be taken when splitting in two.
|
||||
|
||||
(Triangle2D triangle1, Triangle2D triangle2)
|
||||
= (new Triangle2D(A, B, C), new Triangle2D(A, D, C));
|
||||
|
||||
// If D is inside of the triangle ABC, or B is inside of the triangle ADC,
|
||||
// then the quad is concave and we split at the wrong diagonal.
|
||||
// Splitting at the other diagonal should be fine.
|
||||
if (triangle1.Contains(D) || triangle2.Contains(B))
|
||||
{
|
||||
(triangle1, triangle2) = (new Triangle2D(B, C, D), new Triangle2D(B, A, D));
|
||||
}
|
||||
|
||||
return triangle1.Contains(point) || triangle2.Contains(point);
|
||||
}
|
||||
|
||||
public bool Intersects(Quad2D other)
|
||||
{
|
||||
if (!BoundingAxisAlignedRectangle.Intersects(other.BoundingAxisAlignedRectangle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Contains(other.A)) { return true; }
|
||||
if (Contains(other.B)) { return true; }
|
||||
if (Contains(other.C)) { return true; }
|
||||
if (Contains(other.D)) { return true; }
|
||||
|
||||
if (other.Contains(A)) { return true; }
|
||||
if (other.Contains(B)) { return true; }
|
||||
if (other.Contains(C)) { return true; }
|
||||
if (other.Contains(D)) { return true; }
|
||||
|
||||
Span<(Vector2 A, Vector2 B)> myEdges = stackalloc (Vector2 A, Vector2 B)[4];
|
||||
TryGetEdges(myEdges);
|
||||
Span<(Vector2 A, Vector2 B)> otherEdges = stackalloc (Vector2 A, Vector2 B)[4];
|
||||
other.TryGetEdges(otherEdges);
|
||||
foreach (var edge in myEdges)
|
||||
{
|
||||
foreach (var otherEdge in otherEdges)
|
||||
{
|
||||
if (MathUtils.LineSegmentsIntersect(edge.A, edge.B, otherEdge.A, otherEdge.B)) { return true; }
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma;
|
||||
|
||||
readonly record struct Triangle2D(Vector2 A, Vector2 B, Vector2 C)
|
||||
{
|
||||
public bool Contains(Vector2 point)
|
||||
{
|
||||
// Get the half-plane that the point lands in, for each side of the triangle
|
||||
int halfPlaneAb = MathUtils.VectorOrientation(A, B, point);
|
||||
int halfPlaneBc = MathUtils.VectorOrientation(B, C, point);
|
||||
int halfPlaneCa = MathUtils.VectorOrientation(C, A, point);
|
||||
|
||||
// The intersection of three half-planes derived from the three sides of the triangle
|
||||
// is the triangle itself, so check for the point being in those three half-planes
|
||||
bool allNonNegative = halfPlaneAb >= 0 && halfPlaneBc >= 0 && halfPlaneCa >= 0;
|
||||
bool allNonPositive = halfPlaneAb <= 0 && halfPlaneBc <= 0 && halfPlaneCa <= 0;
|
||||
|
||||
return allNonNegative || allNonPositive;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user