From e059a08688d441826f68377a4daeb73673a8db1f Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 3 Mar 2017 00:02:43 +0200 Subject: [PATCH] Optimized lightsource raycasts --- Subsurface/Source/Map/Lights/ConvexHull.cs | 4 + Subsurface/Source/Map/Lights/LightSource.cs | 4 +- Subsurface/Source/Utils/MathUtils.cs | 144 +++++++++++--------- 3 files changed, 84 insertions(+), 68 deletions(-) diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs index 2740c7693..941cc827e 100644 --- a/Subsurface/Source/Map/Lights/ConvexHull.cs +++ b/Subsurface/Source/Map/Lights/ConvexHull.cs @@ -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); } } diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs index 4474d6a36..9daf95ace 100644 --- a/Subsurface/Source/Map/Lights/LightSource.cs +++ b/Subsurface/Source/Map/Lights/LightSource.cs @@ -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) { diff --git a/Subsurface/Source/Utils/MathUtils.cs b/Subsurface/Source/Utils/MathUtils.cs index 279fc3088..0aa6b5760 100644 --- a/Subsurface/Source/Utils/MathUtils.cs +++ b/Subsurface/Source/Utils/MathUtils.cs @@ -207,99 +207,111 @@ namespace Barotrauma return a1 + t * b; } - - /// - /// Get the point where line segment (a1, a2) intersects the axis-aligned line segment (axisAligned1, axisAligned2) - /// - 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 GetLineRectangleIntersections(Vector2 a1, Vector2 a2, Rectangle rect) { List intersections = new List(); - 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);