Optimized lightsource raycasts

This commit is contained in:
Regalis
2017-03-03 00:02:43 +02:00
parent f04a00f6e1
commit e059a08688
3 changed files with 84 additions and 68 deletions

View File

@@ -70,6 +70,8 @@ namespace Barotrauma.Lights
public SegmentPoint Start;
public SegmentPoint End;
public bool IsHorizontal;
public Segment(SegmentPoint start, SegmentPoint end)
{
Start = start;
@@ -77,6 +79,8 @@ namespace Barotrauma.Lights
start.Segment = this;
end.Segment = this;
IsHorizontal = Math.Abs(start.Pos.X - end.Pos.X) > Math.Abs(start.Pos.Y - end.Pos.Y);
}
}

View File

@@ -377,10 +377,10 @@ namespace Barotrauma.Lights
{
float closestDist = 0.0f;
Vector2? closestIntersection = null;
foreach (Segment s in segments)
{
Vector2? intersection = MathUtils.GetAxisAlignedLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos);
Vector2? intersection = MathUtils.GetAxisAlignedLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, s.IsHorizontal);
if (intersection != null)
{

View File

@@ -207,99 +207,111 @@ namespace Barotrauma
return a1 + t * b;
}
/// <summary>
/// Get the point where line segment (a1, a2) intersects the axis-aligned line segment (axisAligned1, axisAligned2)
/// </summary>
public static Vector2? GetAxisAlignedLineIntersection(Vector2 a1, Vector2 a2, Vector2 axisAligned1, Vector2 axisAligned2)
public static Vector2? GetAxisAlignedLineIntersection(Vector2 a1, Vector2 a2, Vector2 axisAligned1, Vector2 axisAligned2, bool isHorizontal)
{
if (Math.Abs(axisAligned1.X - axisAligned2.X) < 1.0f)
if (!isHorizontal)
{
if (Math.Sign(a1.X - axisAligned1.X) == Math.Sign(a2.X - axisAligned1.X))
return null;
if (Math.Max(a1.Y, a2.Y) < Math.Min(axisAligned1.Y, axisAligned2.Y))
return null;
float s = (a2.Y - a1.Y) / (a2.X - a1.X);
float y = a1.Y + (axisAligned1.X - a1.X) * s;
if (Math.Min(a1.Y, a2.Y) > Math.Max(axisAligned1.Y, axisAligned2.Y))
return null;
if (axisAligned1.Y < axisAligned2.Y)
{
if (y < axisAligned1.Y) return null;
if (y > axisAligned2.Y) return null;
}
else
{
if (y > axisAligned1.Y) return null;
if (y < axisAligned2.Y) return null;
}
return new Vector2(axisAligned1.X, y);
}
else
else //horizontal line
{
if (Math.Sign(a1.Y - axisAligned1.Y) == Math.Sign(a2.Y - axisAligned1.Y))
return null;
if (Math.Max(a1.X, a2.X) < Math.Min(axisAligned1.X, axisAligned2.X))
return null;
float s = (a2.X - a1.X) / (a2.Y - a1.Y);
float x = a1.X + (axisAligned1.Y - a1.Y) * s;
if (Math.Min(a1.X, a2.X) > Math.Max(axisAligned1.X, axisAligned2.X))
return null;
if (axisAligned1.X < axisAligned2.X)
{
if (x < axisAligned1.X) return null;
if (x > axisAligned2.X) return null;
}
else
{
if (x > axisAligned1.X) return null;
if (x < axisAligned2.X) return null;
}
return new Vector2(x, axisAligned1.Y);
}
Vector2 b = a2 - a1;
Vector2 d = axisAligned2 - axisAligned1;
float bDotDPerp = b.X * d.Y - b.Y * d.X;
Vector2 c = axisAligned1 - a1;
float t = (c.X * d.Y - c.Y * d.X) / bDotDPerp;
if (t < 0 || t > 1) return null;
float u = (c.X * b.Y - c.Y * b.X) / bDotDPerp;
if (u < 0 || u > 1) return null;
return a1 + t * b;
}
public static Vector2? GetLineRectangleIntersection(Vector2 a1, Vector2 a2, Rectangle rect)
{
Vector2? intersection = GetLineIntersection(a1, a2,
Vector2? intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y),
new Vector2(rect.Right, rect.Y));
if (intersection != null) return intersection;
intersection = GetLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y-rect.Height),
new Vector2(rect.Right, rect.Y-rect.Height));
if (intersection != null) return intersection;
intersection = GetLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y),
new Vector2(rect.X, rect.Y - rect.Height));
if (intersection != null) return intersection;
return GetLineIntersection(a1, a2,
new Vector2(rect.Right, rect.Y),
new Vector2(rect.Right, rect.Y - rect.Height));
true);
if (intersection != null) return intersection;
intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y-rect.Height),
new Vector2(rect.Right, rect.Y-rect.Height),
true);
if (intersection != null) return intersection;
intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y),
new Vector2(rect.X, rect.Y - rect.Height),
false);
if (intersection != null) return intersection;
return GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.Right, rect.Y),
new Vector2(rect.Right, rect.Y - rect.Height),
false);
}
public static List<Vector2> GetLineRectangleIntersections(Vector2 a1, Vector2 a2, Rectangle rect)
{
List<Vector2> intersections = new List<Vector2>();
Vector2? intersection = GetLineIntersection(a1, a2,
Vector2? intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y),
new Vector2(rect.Right, rect.Y));
if (intersection != null) intersections.Add((Vector2)intersection);
intersection = GetLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y - rect.Height),
new Vector2(rect.Right, rect.Y - rect.Height));
if (intersection != null) intersections.Add((Vector2)intersection);
intersection = GetLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y),
new Vector2(rect.X, rect.Y - rect.Height));
if (intersection != null) intersections.Add((Vector2)intersection);
intersection = GetLineIntersection(a1, a2,
new Vector2(rect.Right, rect.Y),
new Vector2(rect.Right, rect.Y - rect.Height));
true);
if (intersection != null) intersections.Add((Vector2)intersection);
intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y - rect.Height),
new Vector2(rect.Right, rect.Y - rect.Height),
true);
if (intersection != null) intersections.Add((Vector2)intersection);
intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.X, rect.Y),
new Vector2(rect.X, rect.Y - rect.Height),
false);
if (intersection != null) intersections.Add((Vector2)intersection);
intersection = GetAxisAlignedLineIntersection(a1, a2,
new Vector2(rect.Right, rect.Y),
new Vector2(rect.Right, rect.Y - rect.Height),
false);
if (intersection != null) intersections.Add((Vector2)intersection);