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