Lighting optimization: lightsources mark convex hulls that are within range but not visible as hidden and don't recalculate the light volume when these convex hulls change (= e.g. when opening/closing a door, only the lightsources that cast light to the door have to recalculated).
This commit is contained in:
@@ -9,6 +9,7 @@ namespace Barotrauma.Lights
|
||||
class ConvexHullList
|
||||
{
|
||||
private List<ConvexHull> list;
|
||||
public HashSet<ConvexHull> IsHidden;
|
||||
|
||||
public readonly Submarine Submarine;
|
||||
public List<ConvexHull> List
|
||||
@@ -19,13 +20,16 @@ namespace Barotrauma.Lights
|
||||
Debug.Assert(value != null);
|
||||
Debug.Assert(!list.Contains(null));
|
||||
list = value;
|
||||
IsHidden.RemoveWhere(ch => !list.Contains(ch));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ConvexHullList(Submarine submarine)
|
||||
{
|
||||
Submarine = submarine;
|
||||
list = new List<ConvexHull>();
|
||||
IsHidden = new HashSet<ConvexHull>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,15 +38,18 @@ namespace Barotrauma.Lights
|
||||
public SegmentPoint Start;
|
||||
public SegmentPoint End;
|
||||
|
||||
public ConvexHull ConvexHull;
|
||||
|
||||
public bool IsHorizontal;
|
||||
|
||||
public Segment(SegmentPoint start, SegmentPoint end)
|
||||
public Segment(SegmentPoint start, SegmentPoint end, ConvexHull convexHull)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
ConvexHull = convexHull;
|
||||
|
||||
start.Segment = this;
|
||||
end.Segment = this;
|
||||
start.ConvexHull = convexHull;
|
||||
end.ConvexHull = convexHull;
|
||||
|
||||
IsHorizontal = Math.Abs(start.Pos.X - end.Pos.X) > Math.Abs(start.Pos.Y - end.Pos.Y);
|
||||
}
|
||||
@@ -53,14 +60,13 @@ namespace Barotrauma.Lights
|
||||
public Vector2 Pos;
|
||||
public Vector2 WorldPos;
|
||||
|
||||
public Segment Segment;
|
||||
public ConvexHull ConvexHull;
|
||||
|
||||
public SegmentPoint(Vector2 pos)
|
||||
public SegmentPoint(Vector2 pos, ConvexHull convexHull)
|
||||
{
|
||||
Pos = pos;
|
||||
WorldPos = pos;
|
||||
|
||||
Segment = null;
|
||||
ConvexHull = convexHull;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -244,13 +250,13 @@ namespace Barotrauma.Lights
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
vertices[i] = new SegmentPoint(points[i]);
|
||||
losVertices[i] = new SegmentPoint(points[i]);
|
||||
vertices[i] = new SegmentPoint(points[i], this);
|
||||
losVertices[i] = new SegmentPoint(points[i], this);
|
||||
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
segments[i] = new Segment(vertices[i], vertices[(i + 1) % 4]);
|
||||
segments[i] = new Segment(vertices[i], vertices[(i + 1) % 4], this);
|
||||
}
|
||||
|
||||
int margin = 0;
|
||||
|
||||
@@ -42,7 +42,22 @@ namespace Barotrauma.Lights
|
||||
//(e.g. position or range of the lightsource has changed)
|
||||
public bool NeedsHullCheck = true;
|
||||
//do we need to recalculate the vertices of the light volume
|
||||
public bool NeedsRecalculation = true;
|
||||
private bool needsRecalculation;
|
||||
public bool NeedsRecalculation
|
||||
{
|
||||
get { return needsRecalculation; }
|
||||
set
|
||||
{
|
||||
if (!needsRecalculation && value)
|
||||
{
|
||||
foreach (ConvexHullList chList in hullsInRange)
|
||||
{
|
||||
chList.IsHidden.Clear();
|
||||
}
|
||||
}
|
||||
needsRecalculation = value;
|
||||
}
|
||||
}
|
||||
|
||||
//when were the vertices of the light volume last calculated
|
||||
private float lastRecalculationTime;
|
||||
@@ -64,7 +79,7 @@ namespace Barotrauma.Lights
|
||||
position = value;
|
||||
|
||||
if (Vector2.DistanceSquared(prevCalculatedPosition, position) < 5.0f * 5.0f) return;
|
||||
|
||||
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
prevCalculatedPosition = position;
|
||||
@@ -117,7 +132,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
if (Math.Abs(prevCalculatedRange - range) < 10.0f) return;
|
||||
|
||||
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
prevCalculatedRange = range;
|
||||
@@ -209,7 +224,7 @@ namespace Barotrauma.Lights
|
||||
NeedsRecalculation = true;
|
||||
}
|
||||
|
||||
if (chList.List.Any(ch => ch.LastVertexChangeTime > lastRecalculationTime))
|
||||
if (chList.List.Any(ch => ch.LastVertexChangeTime > lastRecalculationTime && !chList.IsHidden.Contains(ch)))
|
||||
{
|
||||
NeedsRecalculation = true;
|
||||
}
|
||||
@@ -309,7 +324,16 @@ namespace Barotrauma.Lights
|
||||
var hulls = new List<ConvexHull>();// ConvexHull.GetHullsInRange(position, range, ParentSub);
|
||||
foreach (ConvexHullList chList in hullsInRange)
|
||||
{
|
||||
hulls.AddRange(chList.List);
|
||||
//hulls.AddRange(chList.List);
|
||||
foreach (ConvexHull hull in chList.List)
|
||||
{
|
||||
if (!chList.IsHidden.Contains(hull)) hulls.Add(hull);
|
||||
//hulls.Add(hull);
|
||||
}
|
||||
foreach (ConvexHull hull in chList.List)
|
||||
{
|
||||
chList.IsHidden.Add(hull);
|
||||
}
|
||||
}
|
||||
|
||||
float bounds = range * 2;
|
||||
@@ -353,7 +377,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
SegmentPoint start = visibleSegments[i].Start;
|
||||
SegmentPoint end = visibleSegments[i].End;
|
||||
SegmentPoint mid = new SegmentPoint(intersectionVal);
|
||||
SegmentPoint mid = new SegmentPoint(intersectionVal, null);
|
||||
|
||||
if (Vector2.DistanceSquared(start.WorldPos, mid.WorldPos) < 25.0f ||
|
||||
Vector2.DistanceSquared(end.WorldPos, mid.WorldPos) < 25.0f)
|
||||
@@ -361,8 +385,8 @@ namespace Barotrauma.Lights
|
||||
continue;
|
||||
}
|
||||
|
||||
Segment seg1 = new Segment(start, mid); seg1.IsHorizontal = visibleSegments[i].IsHorizontal;
|
||||
Segment seg2 = new Segment(mid, end); seg2.IsHorizontal = visibleSegments[i].IsHorizontal;
|
||||
Segment seg1 = new Segment(start, mid, visibleSegments[i].ConvexHull); seg1.IsHorizontal = visibleSegments[i].IsHorizontal;
|
||||
Segment seg2 = new Segment(mid, end, visibleSegments[i].ConvexHull); seg2.IsHorizontal = visibleSegments[i].IsHorizontal;
|
||||
visibleSegments[i] = seg1;
|
||||
visibleSegments.Insert(i+1,seg2);
|
||||
i--;
|
||||
@@ -386,17 +410,17 @@ namespace Barotrauma.Lights
|
||||
|
||||
//(might be more effective to calculate if we actually need these extra points)
|
||||
var boundaryCorners = new List<SegmentPoint> {
|
||||
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y + bounds)),
|
||||
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y - bounds)),
|
||||
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y - bounds)),
|
||||
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y + bounds))
|
||||
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y + bounds), null),
|
||||
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y - bounds), null),
|
||||
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y - bounds), null),
|
||||
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y + bounds), null)
|
||||
};
|
||||
|
||||
points.AddRange(boundaryCorners);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
visibleSegments.Add(new Segment(boundaryCorners[i], boundaryCorners[(i + 1) % 4]));
|
||||
visibleSegments.Add(new Segment(boundaryCorners[i], boundaryCorners[(i + 1) % 4], null));
|
||||
}
|
||||
|
||||
var compareCCW = new CompareSegmentPointCW(drawPos);
|
||||
@@ -447,8 +471,15 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (isPoint1 && isPoint2)
|
||||
{
|
||||
//hit at the current segmentpoint -> place the segmentpoint into the list
|
||||
//hit at the current segmentpoint -> place the segmentpoint into the list
|
||||
output.Add(p.WorldPos);
|
||||
|
||||
foreach (ConvexHullList hullList in hullsInRange)
|
||||
{
|
||||
hullList.IsHidden.Remove(p.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg1.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg2.ConvexHull);
|
||||
}
|
||||
}
|
||||
else if (intersection1.First != intersection2.First)
|
||||
{
|
||||
@@ -456,6 +487,13 @@ namespace Barotrauma.Lights
|
||||
//we definitely want to generate new geometry here
|
||||
output.Add(isPoint1 ? p.WorldPos : intersection1.Second);
|
||||
output.Add(isPoint2 ? p.WorldPos : intersection2.Second);
|
||||
|
||||
foreach (ConvexHullList hullList in hullsInRange)
|
||||
{
|
||||
hullList.IsHidden.Remove(p.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg1.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg2.ConvexHull);
|
||||
}
|
||||
}
|
||||
//if neither of the conditions above are met, we just assume
|
||||
//that the raycasts both resulted on the same segment
|
||||
|
||||
Reference in New Issue
Block a user