Build 1.1.4.0
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using SharpFont;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -12,28 +10,14 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
class ConvexHullList
|
||||
{
|
||||
private List<ConvexHull> list;
|
||||
public HashSet<ConvexHull> IsHidden;
|
||||
|
||||
public readonly Submarine Submarine;
|
||||
public List<ConvexHull> List
|
||||
{
|
||||
get { return list; }
|
||||
set
|
||||
{
|
||||
Debug.Assert(value != null);
|
||||
Debug.Assert(!list.Contains(null));
|
||||
list = value;
|
||||
IsHidden.RemoveWhere(ch => !list.Contains(ch));
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<ConvexHull> IsHidden = new HashSet<ConvexHull>();
|
||||
public readonly List<ConvexHull> List = new List<ConvexHull>();
|
||||
|
||||
public ConvexHullList(Submarine submarine)
|
||||
{
|
||||
Submarine = submarine;
|
||||
list = new List<ConvexHull>();
|
||||
IsHidden = new HashSet<ConvexHull>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +31,13 @@ namespace Barotrauma.Lights
|
||||
public bool IsHorizontal;
|
||||
public bool IsAxisAligned;
|
||||
|
||||
public Vector2 SubmarineDrawPos;
|
||||
|
||||
public Segment(SegmentPoint start, SegmentPoint end, ConvexHull convexHull)
|
||||
{
|
||||
if (start.Pos.Y > end.Pos.Y)
|
||||
{
|
||||
var temp = start;
|
||||
start = end;
|
||||
end = temp;
|
||||
(end, start) = (start, end);
|
||||
}
|
||||
|
||||
Start = start;
|
||||
@@ -102,14 +86,15 @@ namespace Barotrauma.Lights
|
||||
|
||||
private readonly Segment[] segments = new Segment[4];
|
||||
private readonly SegmentPoint[] vertices = new SegmentPoint[4];
|
||||
private readonly SegmentPoint[] losVertices = new SegmentPoint[4];
|
||||
private readonly VectorPair[] losOffsets = new VectorPair[4];
|
||||
|
||||
private readonly bool[] backFacing;
|
||||
private readonly bool[] ignoreEdge;
|
||||
private readonly SegmentPoint[] losVertices = new SegmentPoint[2];
|
||||
private readonly Vector2[] losOffsets = new Vector2[2];
|
||||
|
||||
private readonly bool isHorizontal;
|
||||
|
||||
private readonly int thickness;
|
||||
|
||||
public bool IsExteriorWall;
|
||||
|
||||
public VertexPositionColor[] ShadowVertices { get; private set; }
|
||||
public VertexPositionTexture[] PenumbraVertices { get; private set; }
|
||||
public int ShadowVertexCount { get; private set; }
|
||||
@@ -145,47 +130,27 @@ namespace Barotrauma.Lights
|
||||
|
||||
public Rectangle BoundingBox { get; private set; }
|
||||
|
||||
public ConvexHull(Vector2[] points, Color color, MapEntity parent)
|
||||
public ConvexHull(Rectangle rect, bool? isHorizontal, MapEntity parent)
|
||||
{
|
||||
if (shadowEffect == null)
|
||||
{
|
||||
shadowEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
shadowEffect ??= new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
{
|
||||
VertexColorEnabled = true
|
||||
};
|
||||
}
|
||||
if (penumbraEffect == null)
|
||||
{
|
||||
penumbraEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
penumbraEffect ??= new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
{
|
||||
TextureEnabled = true,
|
||||
LightingEnabled = false,
|
||||
Texture = TextureLoader.FromFile("Content/Lights/penumbra.png")
|
||||
};
|
||||
}
|
||||
|
||||
ParentEntity = parent;
|
||||
|
||||
ShadowVertices = new VertexPositionColor[6 * 4];
|
||||
PenumbraVertices = new VertexPositionTexture[6 * 4];
|
||||
|
||||
backFacing = new bool[4];
|
||||
ignoreEdge = new bool[4];
|
||||
BoundingBox = rect;
|
||||
|
||||
float minX = points[0].X, minY = points[0].Y, maxX = points[0].X, maxY = points[0].Y;
|
||||
|
||||
for (int i = 1; i < vertices.Length; i++)
|
||||
{
|
||||
if (points[i].X < minX) minX = points[i].X;
|
||||
if (points[i].Y < minY) minY = points[i].Y;
|
||||
|
||||
if (points[i].X > maxX) maxX = points[i].X;
|
||||
if (points[i].Y > minY) maxY = points[i].Y;
|
||||
}
|
||||
|
||||
BoundingBox = new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
||||
|
||||
isHorizontal = BoundingBox.Width > BoundingBox.Height;
|
||||
this.isHorizontal = isHorizontal ?? BoundingBox.Width > BoundingBox.Height;
|
||||
if (ParentEntity is Structure structure)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(!structure.Removed);
|
||||
@@ -198,8 +163,26 @@ namespace Barotrauma.Lights
|
||||
if (door != null) { isHorizontal = door.IsHorizontal; }
|
||||
}
|
||||
|
||||
SetVertices(points);
|
||||
|
||||
Vector2[] verts = new Vector2[]
|
||||
{
|
||||
new Vector2(rect.X, rect.Bottom),
|
||||
new Vector2(rect.Right, rect.Bottom),
|
||||
new Vector2(rect.Right, rect.Y),
|
||||
new Vector2(rect.X, rect.Y),
|
||||
};
|
||||
|
||||
Vector2[] losVerts;
|
||||
if (this.isHorizontal)
|
||||
{
|
||||
thickness = rect.Height;
|
||||
losVerts = new Vector2[] { new Vector2(rect.X, rect.Center.Y), new Vector2(rect.Right, rect.Center.Y) };
|
||||
}
|
||||
else
|
||||
{
|
||||
thickness = rect.Width;
|
||||
losVerts = new Vector2[] { new Vector2(rect.Center.X, rect.Y), new Vector2(rect.Center.X, rect.Bottom) };
|
||||
}
|
||||
SetVertices(verts, losVerts);
|
||||
Enabled = true;
|
||||
|
||||
var chList = HullLists.Find(h => h.Submarine == parent.Submarine);
|
||||
@@ -211,257 +194,72 @@ namespace Barotrauma.Lights
|
||||
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
MergeOverlappingSegments(ch);
|
||||
ch.MergeOverlappingSegments(this);
|
||||
MergeLosVertices(ch);
|
||||
ch.MergeLosVertices(this);
|
||||
}
|
||||
|
||||
chList.List.Add(this);
|
||||
}
|
||||
|
||||
private void MergeOverlappingSegments(ConvexHull ch)
|
||||
private void MergeLosVertices(ConvexHull ch, bool refreshOtherOverlappingHulls = true)
|
||||
{
|
||||
if (ch == this) { return; }
|
||||
|
||||
if (isHorizontal == ch.isHorizontal)
|
||||
//hide segments that are roughly at the some position as some other segment (e.g. the ends of two adjacent wall pieces)
|
||||
float mergeDist = MathHelper.Clamp(ch.thickness * 0.55f, 16, 512);
|
||||
mergeDist = Math.Min(mergeDist, Vector2.Distance(losVertices[0].Pos, losVertices[1].Pos) / 2);
|
||||
|
||||
float mergeDistSqr = mergeDist * mergeDist;
|
||||
|
||||
bool changed = false;
|
||||
for (int i = 0; i < losVertices.Length; i++)
|
||||
{
|
||||
//hide segments that are roughly at the some position as some other segment (e.g. the ends of two adjacent wall pieces)
|
||||
float mergeDist = 16;
|
||||
float mergeDistSqr = mergeDist * mergeDist;
|
||||
//find the closest point on the other convex hull segment
|
||||
Vector2 closest = MathUtils.GetClosestPointOnLineSegment(
|
||||
ch.losVertices[0].Pos + ch.losOffsets[0],
|
||||
ch.losVertices[1].Pos + ch.losOffsets[1],
|
||||
losVertices[i].Pos);
|
||||
if (Vector2.DistanceSquared(closest, losVertices[i].Pos) > mergeDistSqr) { continue; }
|
||||
|
||||
Rectangle intersection = Rectangle.Intersect(BoundingBox, ch.BoundingBox);
|
||||
int intersectionArea = intersection.Width * intersection.Height;
|
||||
int bboxArea = BoundingBox.Width * BoundingBox.Height;
|
||||
int otherBboxArea = ch.BoundingBox.Width * ch.BoundingBox.Height;
|
||||
if (Math.Abs(intersectionArea - bboxArea) < mergeDistSqr) { return; }
|
||||
if (Math.Abs(intersectionArea - otherBboxArea) < mergeDistSqr) { return; }
|
||||
|
||||
for (int i = 0; i < segments.Length; i++)
|
||||
//find where the segments would intersect if they had infinite length
|
||||
// if it's close to the closest point, let's use that instead to keep
|
||||
// the direction of the segment unchanged (i.e. vertical segment stays vertical)
|
||||
if (MathUtils.GetLineIntersection(
|
||||
ch.losVertices[0].Pos + ch.losOffsets[0],
|
||||
ch.losVertices[1].Pos + ch.losOffsets[1],
|
||||
losVertices[0].Pos,
|
||||
losVertices[1].Pos,
|
||||
out Vector2 intersection))
|
||||
{
|
||||
for (int j = 0; j < ch.segments.Length; j++)
|
||||
if (Vector2.DistanceSquared(intersection, losVertices[i].Pos) < mergeDistSqr ||
|
||||
Vector2.DistanceSquared(intersection, closest) < 16.0f * 16.0f)
|
||||
{
|
||||
if (segments[i].IsHorizontal != ch.segments[j].IsHorizontal) { continue; }
|
||||
if (ignoreEdge[i] || ch.ignoreEdge[j]) { continue; }
|
||||
|
||||
//the segments must be at different sides of the convex hulls to be merged
|
||||
//(e.g. the right edge of a wall piece and the left edge of another one)
|
||||
var segment1Center = (segments[i].Start.Pos + segments[i].End.Pos) / 2.0f;
|
||||
var segment2Center = (ch.segments[j].Start.Pos + ch.segments[j].End.Pos) / 2.0f;
|
||||
if (Vector2.Dot(segment1Center - BoundingBox.Center.ToVector2(), segment2Center - ch.BoundingBox.Center.ToVector2()) > 0) { continue; }
|
||||
|
||||
if (Vector2.DistanceSquared(segments[i].Start.Pos, ch.segments[j].Start.Pos) < mergeDistSqr &&
|
||||
Vector2.DistanceSquared(segments[i].End.Pos, ch.segments[j].End.Pos) < mergeDistSqr)
|
||||
{
|
||||
ignoreEdge[i] = true;
|
||||
ch.ignoreEdge[j] = true;
|
||||
MergeSegments(segments[i], ch.segments[j], true);
|
||||
}
|
||||
else if (Vector2.DistanceSquared(segments[i].Start.Pos, ch.segments[j].End.Pos) < mergeDistSqr &&
|
||||
Vector2.DistanceSquared(segments[i].End.Pos, ch.segments[j].Start.Pos) < mergeDistSqr)
|
||||
{
|
||||
ignoreEdge[i] = true;
|
||||
ch.ignoreEdge[j] = true;
|
||||
MergeSegments(segments[i], ch.segments[j], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < segments.Length; i++)
|
||||
{
|
||||
if (ignoreEdge[i]) { continue; }
|
||||
if (Vector2.DistanceSquared(segments[i].Start.Pos, segments[i].End.Pos) < 1.0f) { continue; }
|
||||
for (int j = 0; j < ch.segments.Length; j++)
|
||||
{
|
||||
if (ch.ignoreEdge[j]) { continue; }
|
||||
if (Vector2.DistanceSquared(ch.segments[j].Start.Pos, ch.segments[j].End.Pos) < 1.0f) { continue; }
|
||||
if (IsSegmentAInB(segments[i], ch.segments[j]))
|
||||
{
|
||||
ignoreEdge[i] = true;
|
||||
if (Vector2.DistanceSquared(ch.segments[j].Start.Pos, segments[i].Start.Pos) < 4.0f)
|
||||
{
|
||||
ch.ShiftSegmentPoint(j, false, segments[i].End.Pos);
|
||||
}
|
||||
else if (Vector2.DistanceSquared(ch.segments[j].Start.Pos, segments[i].End.Pos) < 4.0f)
|
||||
{
|
||||
ch.ShiftSegmentPoint(j, false, segments[i].Start.Pos);
|
||||
}
|
||||
|
||||
if (Vector2.DistanceSquared(ch.segments[j].End.Pos, segments[i].Start.Pos) < 4.0f)
|
||||
{
|
||||
ch.ShiftSegmentPoint(j, true, segments[i].End.Pos);
|
||||
}
|
||||
else if (Vector2.DistanceSquared(ch.segments[j].End.Pos, segments[i].End.Pos) < 4.0f)
|
||||
{
|
||||
ch.ShiftSegmentPoint(j, true, segments[i].Start.Pos);
|
||||
}
|
||||
}
|
||||
else if (IsSegmentAInB(ch.segments[j], segments[i]))
|
||||
{
|
||||
ch.ignoreEdge[j] = true;
|
||||
|
||||
if (Vector2.DistanceSquared(segments[i].Start.Pos, ch.segments[j].Start.Pos) < 4.0f)
|
||||
{
|
||||
ShiftSegmentPoint(i, false, ch.segments[j].End.Pos);
|
||||
}
|
||||
else if (Vector2.DistanceSquared(segments[i].Start.Pos, ch.segments[j].End.Pos) < 4.0f)
|
||||
{
|
||||
ShiftSegmentPoint(i, false, ch.segments[j].Start.Pos);
|
||||
}
|
||||
|
||||
if (Vector2.DistanceSquared(segments[i].End.Pos, ch.segments[j].Start.Pos) < 4.0f)
|
||||
{
|
||||
ShiftSegmentPoint(i, true, ch.segments[j].End.Pos);
|
||||
}
|
||||
else if (Vector2.DistanceSquared(segments[i].End.Pos, ch.segments[j].End.Pos) < 4.0f)
|
||||
{
|
||||
ShiftSegmentPoint(i, true, ch.segments[j].Start.Pos);
|
||||
}
|
||||
closest = intersection;
|
||||
}
|
||||
}
|
||||
|
||||
losOffsets[i] = closest - losVertices[i].Pos;
|
||||
overlappingHulls.Add(ch);
|
||||
ch.overlappingHulls.Add(this);
|
||||
changed = true;
|
||||
|
||||
}
|
||||
|
||||
//ignore edges that are inside some other convex hull
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
if (changed && refreshOtherOverlappingHulls)
|
||||
{
|
||||
if (ch.IsPointInside(vertices[i].Pos))
|
||||
foreach (var overlapping in overlappingHulls)
|
||||
{
|
||||
if (ch.IsPointInside(vertices[(i + 1) % vertices.Length].Pos))
|
||||
{
|
||||
ignoreEdge[i] = true;
|
||||
overlappingHulls.Add(ch);
|
||||
}
|
||||
overlapping.MergeLosVertices(this, refreshOtherOverlappingHulls: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShiftSegmentPoint(int segmentIndex, bool end, Vector2 newPos)
|
||||
{
|
||||
var segment = segments[segmentIndex];
|
||||
|
||||
losOffsets[segmentIndex] ??= new VectorPair();
|
||||
bool flipped = false;
|
||||
if (Vector2.DistanceSquared(vertices[segmentIndex].Pos, segment.Start.Pos) > Vector2.DistanceSquared(vertices[segmentIndex].Pos, segment.End.Pos))
|
||||
{
|
||||
flipped = true;
|
||||
}
|
||||
if (end == !flipped)
|
||||
{
|
||||
losOffsets[segmentIndex].B = newPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
losOffsets[segmentIndex].A = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSegmentAInB(Segment a, Segment b)
|
||||
{
|
||||
if (Vector2.DistanceSquared(a.Start.Pos, a.End.Pos) > Vector2.DistanceSquared(b.Start.Pos, b.End.Pos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector2 min = new Vector2(Math.Min(b.Start.Pos.X, b.End.Pos.X), Math.Min(b.Start.Pos.Y, b.End.Pos.Y));
|
||||
Vector2 max = new Vector2(Math.Max(b.Start.Pos.X, b.End.Pos.X), Math.Max(b.Start.Pos.Y, b.End.Pos.Y));
|
||||
min.X -= 1.0f; min.Y -= 1.0f;
|
||||
max.X += 1.0f; max.Y += 1.0f;
|
||||
|
||||
if (a.Start.Pos.X < min.X) { return false; }
|
||||
if (a.Start.Pos.Y < min.Y) { return false; }
|
||||
if (a.End.Pos.X < min.X) { return false; }
|
||||
if (a.End.Pos.Y < min.Y) { return false; }
|
||||
|
||||
if (a.Start.Pos.X > max.X) { return false; }
|
||||
if (a.Start.Pos.Y > max.Y) { return false; }
|
||||
if (a.End.Pos.X > max.X) { return false; }
|
||||
if (a.End.Pos.Y > max.Y) { return false; }
|
||||
|
||||
float startDist = MathUtils.LineToPointDistanceSquared(b.Start.Pos, b.End.Pos, a.Start.Pos);
|
||||
if (startDist > 1.0f) { return false; }
|
||||
float endDist = MathUtils.LineToPointDistanceSquared(b.Start.Pos, b.End.Pos, a.End.Pos);
|
||||
if (endDist > 1.0f) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsPointInside(Vector2 point)
|
||||
{
|
||||
if (!BoundingBox.Contains(point)) { return false; }
|
||||
|
||||
Vector2 center = (vertices[0].Pos + vertices[1].Pos + vertices[2].Pos + vertices[3].Pos) * 0.25f;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Vector2 segmentVector = vertices[(i + 1) % 4].Pos - vertices[i].Pos;
|
||||
Vector2 centerToVertex = center - vertices[i].Pos;
|
||||
Vector2 pointToVertex = point - vertices[i].Pos;
|
||||
|
||||
float dotCenter = Vector2.Dot(centerToVertex, segmentVector);
|
||||
float dotPoint = Vector2.Dot(pointToVertex, segmentVector);
|
||||
|
||||
if ((dotCenter > 0f && dotPoint < 0f) || (dotCenter < 0f && dotPoint > 0f)) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void MergeSegments(Segment segment1, Segment segment2, bool startPointsMatch)
|
||||
{
|
||||
int startPointIndex = -1, endPointIndex = -1;
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
if (vertices[i].Pos.NearlyEquals(segment1.Start.Pos))
|
||||
startPointIndex = i;
|
||||
else if (vertices[i].Pos.NearlyEquals(segment1.End.Pos))
|
||||
endPointIndex = i;
|
||||
}
|
||||
if (startPointIndex == -1 || endPointIndex == -1) { return; }
|
||||
|
||||
int startPoint2Index = -1, endPoint2Index = -1;
|
||||
for (int i = 0; i < segment2.ConvexHull.vertices.Length; i++)
|
||||
{
|
||||
if (segment2.ConvexHull.vertices[i].Pos.NearlyEquals(segment2.Start.Pos))
|
||||
startPoint2Index = i;
|
||||
else if (segment2.ConvexHull.vertices[i].Pos.NearlyEquals(segment2.End.Pos))
|
||||
endPoint2Index = i;
|
||||
}
|
||||
if (startPoint2Index == -1 || endPoint2Index == -1) { return; }
|
||||
|
||||
if (startPointsMatch)
|
||||
{
|
||||
losVertices[startPointIndex].Pos = segment2.ConvexHull.losVertices[startPoint2Index].Pos =
|
||||
(segment1.Start.Pos + segment2.Start.Pos) / 2.0f;
|
||||
losVertices[endPointIndex].Pos = segment2.ConvexHull.losVertices[endPoint2Index].Pos =
|
||||
(segment1.End.Pos + segment2.End.Pos) / 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vector2.DistanceSquared(losVertices[startPointIndex].Pos, segment1.Start.Pos) <
|
||||
Vector2.DistanceSquared(losVertices[startPointIndex].Pos, segment1.End.Pos))
|
||||
{
|
||||
losVertices[startPointIndex].Pos = segment2.ConvexHull.losVertices[startPoint2Index].Pos =
|
||||
(segment1.Start.Pos + segment2.End.Pos) / 2.0f;
|
||||
losVertices[endPointIndex].Pos = segment2.ConvexHull.losVertices[endPoint2Index].Pos =
|
||||
(segment1.End.Pos + segment2.Start.Pos) / 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
losVertices[startPointIndex].Pos = segment2.ConvexHull.losVertices[startPoint2Index].Pos =
|
||||
(segment1.End.Pos + segment2.Start.Pos) / 2.0f;
|
||||
losVertices[endPointIndex].Pos = segment2.ConvexHull.losVertices[endPoint2Index].Pos =
|
||||
(segment1.Start.Pos + segment2.End.Pos) / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
overlappingHulls.Add(segment2.ConvexHull);
|
||||
segment2.ConvexHull.overlappingHulls.Add(this);
|
||||
}
|
||||
|
||||
public void Rotate(Vector2 origin, float amount)
|
||||
{
|
||||
Matrix rotationMatrix =
|
||||
Matrix.CreateTranslation(-origin.X, -origin.Y, 0.0f) *
|
||||
Matrix.CreateRotationZ(amount) *
|
||||
Matrix.CreateTranslation(origin.X, origin.Y, 0.0f);
|
||||
SetVertices(vertices.Select(v => v.Pos).ToArray(), rotationMatrix: rotationMatrix);
|
||||
SetVertices(vertices.Select(v => v.Pos).ToArray(), losVertices.Select(v => v.Pos).ToArray(), rotationMatrix: rotationMatrix);
|
||||
}
|
||||
|
||||
private void CalculateDimensions()
|
||||
@@ -470,11 +268,10 @@ namespace Barotrauma.Lights
|
||||
|
||||
for (int i = 1; i < vertices.Length; i++)
|
||||
{
|
||||
if (vertices[i].Pos.X < minX) minX = vertices[i].Pos.X;
|
||||
if (vertices[i].Pos.Y < minY) minY = vertices[i].Pos.Y;
|
||||
|
||||
if (vertices[i].Pos.X > maxX) maxX = vertices[i].Pos.X;
|
||||
if (vertices[i].Pos.Y > minY) maxY = vertices[i].Pos.Y;
|
||||
minX = Math.Min(minX, vertices[i].Pos.X);
|
||||
minY = Math.Min(minY, vertices[i].Pos.Y);
|
||||
maxX = Math.Max(maxX, vertices[i].Pos.X);
|
||||
maxY = Math.Max(maxY, vertices[i].Pos.Y);
|
||||
}
|
||||
|
||||
BoundingBox = new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
||||
@@ -485,21 +282,17 @@ namespace Barotrauma.Lights
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i].Pos += amount;
|
||||
losVertices[i].Pos += amount;
|
||||
|
||||
losOffsets[i] = null;
|
||||
|
||||
segments[i].Start.Pos += amount;
|
||||
segments[i].End.Pos += amount;
|
||||
}
|
||||
for (int i = 0; i < losVertices.Length; i++)
|
||||
{
|
||||
losVertices[i].Pos += amount;
|
||||
}
|
||||
|
||||
LastVertexChangeTime = (float)Timing.TotalTime;
|
||||
|
||||
overlappingHulls.Clear();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ignoreEdge[i] = false;
|
||||
}
|
||||
|
||||
CalculateDimensions();
|
||||
|
||||
@@ -511,8 +304,8 @@ namespace Barotrauma.Lights
|
||||
overlappingHulls.Clear();
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
MergeOverlappingSegments(ch);
|
||||
ch.MergeOverlappingSegments(this);
|
||||
MergeLosVertices(ch);
|
||||
ch.MergeLosVertices(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,23 +318,23 @@ namespace Barotrauma.Lights
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
ch.overlappingHulls.Clear();
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < ch.losOffsets.Length; i++)
|
||||
{
|
||||
ch.ignoreEdge[i] = false;
|
||||
ch.losOffsets[i] = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < chList.List.Count; i++)
|
||||
{
|
||||
for (int j = i + 1; j < chList.List.Count; j++)
|
||||
{
|
||||
chList.List[i].MergeOverlappingSegments(chList.List[j]);
|
||||
chList.List[j].MergeOverlappingSegments(chList.List[i]);
|
||||
chList.List[i].MergeLosVertices(chList.List[j]);
|
||||
chList.List[j].MergeLosVertices(chList.List[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVertices(Vector2[] points, bool mergeOverlappingSegments = true, Matrix? rotationMatrix = null)
|
||||
public void SetVertices(Vector2[] points, Vector2[] losPoints, bool mergeOverlappingSegments = true, Matrix? rotationMatrix = null)
|
||||
{
|
||||
Debug.Assert(points.Length == 4, "Only rectangular convex hulls are supported");
|
||||
|
||||
@@ -549,39 +342,23 @@ namespace Barotrauma.Lights
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
vertices[i] = new SegmentPoint(points[i], this);
|
||||
losVertices[i] = new SegmentPoint(points[i], this);
|
||||
losOffsets[i] = null;
|
||||
vertices[i] = new SegmentPoint(points[i], this);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
ignoreEdge[i] = false;
|
||||
losVertices[i] = new SegmentPoint(losPoints[i], this);
|
||||
}
|
||||
|
||||
overlappingHulls.Clear();
|
||||
|
||||
int margin = 0;
|
||||
if (Math.Abs(points[0].X - points[2].X) < Math.Abs(points[0].Y - points[2].Y))
|
||||
{
|
||||
losVertices[0].Pos = new Vector2(points[0].X + margin, points[0].Y);
|
||||
losVertices[1].Pos = new Vector2(points[1].X + margin, points[1].Y);
|
||||
losVertices[2].Pos = new Vector2(points[2].X - margin, points[2].Y);
|
||||
losVertices[3].Pos = new Vector2(points[3].X - margin, points[3].Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
losVertices[0].Pos = new Vector2(points[0].X, points[0].Y + margin);
|
||||
losVertices[1].Pos = new Vector2(points[1].X, points[1].Y - margin);
|
||||
losVertices[2].Pos = new Vector2(points[2].X, points[2].Y - margin);
|
||||
losVertices[3].Pos = new Vector2(points[3].X, points[3].Y + margin);
|
||||
}
|
||||
|
||||
if (rotationMatrix.HasValue)
|
||||
{
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i].Pos = Vector2.Transform(vertices[i].Pos, rotationMatrix.Value);
|
||||
}
|
||||
for (int i = 0; i < losVertices.Length; i++)
|
||||
{
|
||||
losVertices[i].Pos = Vector2.Transform(losVertices[i].Pos, rotationMatrix.Value);
|
||||
}
|
||||
}
|
||||
@@ -602,7 +379,7 @@ namespace Barotrauma.Lights
|
||||
overlappingHulls.Clear();
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
MergeOverlappingSegments(ch);
|
||||
MergeLosVertices(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -624,31 +401,17 @@ namespace Barotrauma.Lights
|
||||
/// <summary>
|
||||
/// Returns the segments that are facing towards viewPosition
|
||||
/// </summary>
|
||||
public void GetVisibleSegments(Vector2 viewPosition, List<Segment> visibleSegments, bool ignoreEdges)
|
||||
public void GetVisibleSegments(Vector2 viewPosition, List<Segment> visibleSegments)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (ignoreEdge[i] && ignoreEdges) continue;
|
||||
|
||||
Vector2 pos1 = vertices[i].WorldPos;
|
||||
Vector2 pos2 = vertices[(i + 1) % 4].WorldPos;
|
||||
|
||||
Vector2 middle = (pos1 + pos2) / 2;
|
||||
|
||||
Vector2 L = viewPosition - middle;
|
||||
|
||||
Vector2 N = new Vector2(
|
||||
-(pos2.Y - pos1.Y),
|
||||
pos2.X - pos1.X);
|
||||
|
||||
if (Vector2.Dot(N, L) > 0)
|
||||
if (IsSegmentFacing(vertices[i].WorldPos, vertices[(i + 1) % 4].WorldPos, viewPosition))
|
||||
{
|
||||
visibleSegments.Add(segments[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void RefreshWorldPositions()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -676,34 +439,12 @@ namespace Barotrauma.Lights
|
||||
|
||||
ShadowVertexCount = 0;
|
||||
|
||||
//compute facing of each edge, using N*L
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < losVertices.Length; i++)
|
||||
{
|
||||
if (ignoreEdge[i])
|
||||
{
|
||||
backFacing[i] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 firstVertex = losVertices[i].Pos;
|
||||
Vector2 secondVertex = losVertices[(i+1) % 4].Pos;
|
||||
|
||||
Vector2 L = lightSourcePos - ((firstVertex + secondVertex) / 2.0f);
|
||||
|
||||
Vector2 N = new Vector2(
|
||||
-(secondVertex.Y - firstVertex.Y),
|
||||
secondVertex.X - firstVertex.X);
|
||||
|
||||
backFacing[i] = (Vector2.Dot(N, L) < 0);
|
||||
}
|
||||
|
||||
ShadowVertexCount = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (!backFacing[i]) { continue; }
|
||||
int currentIndex = i;
|
||||
Vector3 vertexPos0 = new Vector3(losOffsets[currentIndex]?.A ?? losVertices[currentIndex].Pos, 0.0f);
|
||||
Vector3 vertexPos1 = new Vector3(losOffsets[currentIndex]?.B ?? losVertices[(currentIndex + 1) % 4].Pos, 0.0f);
|
||||
int nextIndex = (currentIndex + 1) % 2;
|
||||
Vector3 vertexPos0 = new Vector3(losVertices[currentIndex].Pos + losOffsets[currentIndex], 0.0f);
|
||||
Vector3 vertexPos1 = new Vector3(losVertices[nextIndex].Pos + losOffsets[nextIndex], 0.0f);
|
||||
|
||||
if (Vector3.DistanceSquared(vertexPos0, vertexPos1) < 1.0f) { continue; }
|
||||
|
||||
@@ -754,9 +495,24 @@ namespace Barotrauma.Lights
|
||||
ShadowVertexCount += 6;
|
||||
}
|
||||
|
||||
if (IsSegmentFacing(losVertices[0].Pos, losVertices[1].Pos, lightSourcePos))
|
||||
{
|
||||
Array.Reverse(ShadowVertices);
|
||||
}
|
||||
|
||||
CalculateLosPenumbraVertices(lightSourcePos);
|
||||
}
|
||||
|
||||
private static bool IsSegmentFacing(Vector2 segmentPos1, Vector2 segmentPos2, Vector2 viewPosition)
|
||||
{
|
||||
Vector2 segmentMid = (segmentPos1 + segmentPos2) / 2;
|
||||
Vector2 segmentDiff = segmentPos2 - segmentPos1;
|
||||
Vector2 segmentNormal = new Vector2(-segmentDiff.Y, segmentDiff.X);
|
||||
|
||||
Vector2 viewDirection = viewPosition - segmentMid;
|
||||
return Vector2.Dot(segmentNormal, viewDirection) > 0;
|
||||
}
|
||||
|
||||
private void CalculateLosPenumbraVertices(Vector2 lightSourcePos)
|
||||
{
|
||||
Vector3 offset = Vector3.Zero;
|
||||
@@ -766,73 +522,101 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
|
||||
PenumbraVertexCount = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < losVertices.Length; i++)
|
||||
{
|
||||
int currentIndex = i;
|
||||
int prevIndex = (i + 3) % 4;
|
||||
int nextIndex = (i + 1) % 4;
|
||||
bool disjointed = losOffsets[i]?.A != null;
|
||||
Vector2 vertexPos0 = losOffsets[currentIndex]?.A ?? losVertices[currentIndex].Pos;
|
||||
Vector2 vertexPos1 = losOffsets[currentIndex]?.B ?? losVertices[nextIndex].Pos;
|
||||
int nextIndex = (i + 1) % 2;
|
||||
Vector2 vertexPos0 = losVertices[currentIndex].Pos + losOffsets[currentIndex];
|
||||
Vector2 vertexPos1 = losVertices[nextIndex].Pos + losOffsets[nextIndex];
|
||||
|
||||
if (Vector2.DistanceSquared(vertexPos0, vertexPos1) < 1.0f) { continue; }
|
||||
|
||||
Vector3 penumbraStart = new Vector3(vertexPos0, 0.0f);
|
||||
|
||||
if (backFacing[currentIndex] && (disjointed || (!backFacing[prevIndex])))
|
||||
PenumbraVertices[PenumbraVertexCount] = new VertexPositionTexture
|
||||
{
|
||||
Vector3 penumbraStart = new Vector3(vertexPos0, 0.0f);
|
||||
Position = penumbraStart + offset,
|
||||
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
||||
};
|
||||
|
||||
PenumbraVertices[PenumbraVertexCount] = new VertexPositionTexture
|
||||
{
|
||||
Position = penumbraStart + offset,
|
||||
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
||||
};
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
PenumbraVertices[PenumbraVertexCount + j + 1] = new VertexPositionTexture();
|
||||
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
||||
vertexDir.Normalize();
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
PenumbraVertices[PenumbraVertexCount + j + 1] = new VertexPositionTexture();
|
||||
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
||||
vertexDir.Normalize();
|
||||
Vector3 normal = (j == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
||||
|
||||
Vector3 normal = (j == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
||||
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) - normal * 20.0f);
|
||||
vertexDir.Normalize();
|
||||
PenumbraVertices[PenumbraVertexCount + j + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
||||
|
||||
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) - normal * 20.0f);
|
||||
vertexDir.Normalize();
|
||||
PenumbraVertices[PenumbraVertexCount + j + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
||||
|
||||
PenumbraVertices[PenumbraVertexCount + j + 1].TextureCoordinate = (j == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
||||
}
|
||||
|
||||
PenumbraVertexCount += 3;
|
||||
PenumbraVertices[PenumbraVertexCount + j + 1].TextureCoordinate = (j == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
||||
}
|
||||
|
||||
disjointed = losOffsets[i]?.B != null;
|
||||
if (backFacing[currentIndex] && (disjointed || (!backFacing[nextIndex])))
|
||||
PenumbraVertexCount += 3;
|
||||
|
||||
penumbraStart = new Vector3(vertexPos1, 0.0f);
|
||||
|
||||
PenumbraVertices[PenumbraVertexCount] = new VertexPositionTexture
|
||||
{
|
||||
Vector3 penumbraStart = new Vector3(vertexPos1, 0.0f);
|
||||
Position = penumbraStart + offset,
|
||||
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
||||
};
|
||||
|
||||
PenumbraVertices[PenumbraVertexCount] = new VertexPositionTexture
|
||||
{
|
||||
Position = penumbraStart + offset,
|
||||
TextureCoordinate = new Vector2(0.0f, 1.0f)
|
||||
};
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1] = new VertexPositionTexture();
|
||||
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
||||
vertexDir.Normalize();
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1] = new VertexPositionTexture();
|
||||
Vector3 vertexDir = penumbraStart - new Vector3(lightSourcePos, 0);
|
||||
vertexDir.Normalize();
|
||||
Vector3 normal = (j == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
||||
|
||||
Vector3 normal = (j == 0) ? new Vector3(-vertexDir.Y, vertexDir.X, 0.0f) : new Vector3(vertexDir.Y, -vertexDir.X, 0.0f) * 0.05f;
|
||||
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) + normal * 20.0f);
|
||||
vertexDir.Normalize();
|
||||
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
||||
|
||||
vertexDir = penumbraStart - (new Vector3(lightSourcePos, 0) + normal * 20.0f);
|
||||
vertexDir.Normalize();
|
||||
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1].Position = new Vector3(lightSourcePos, 0) + vertexDir * 9000 + offset;
|
||||
|
||||
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1].TextureCoordinate = (j == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
||||
}
|
||||
|
||||
PenumbraVertexCount += 3;
|
||||
PenumbraVertices[PenumbraVertexCount + (1 - j) + 1].TextureCoordinate = (j == 0) ? new Vector2(0.05f, 0.0f) : new Vector2(1.0f, 0.0f);
|
||||
}
|
||||
|
||||
PenumbraVertexCount += 3;
|
||||
}
|
||||
}
|
||||
|
||||
public void DebugDraw(SpriteBatch spriteBatch)
|
||||
{
|
||||
//RecalculateAll(Submarine.MainSub);
|
||||
//RefreshWorldPositions();
|
||||
|
||||
DrawLine(losVertices[0].Pos, losVertices[1].Pos, Color.Gray * 0.5f, width: 3);
|
||||
DrawLine(losVertices[0].Pos + losOffsets[0], losVertices[1].Pos + losOffsets[1], Color.LightGreen, width: 2);
|
||||
DrawLine(GameMain.GameScreen.Cam.Position + Vector2.One * 1000, GameMain.GameScreen.Cam.Position - Vector2.One * 1000, Color.Magenta, width: 2);
|
||||
|
||||
if (GameMain.LightManager.LightingEnabled)
|
||||
{
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
Vector2 start = vertices[i].Pos;
|
||||
Vector2 end = vertices[(i + 1) % 4].Pos;
|
||||
DrawLine(
|
||||
start,
|
||||
end, Color.Yellow * 0.5f,
|
||||
width: 4);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLine(Vector2 vertexPos0, Vector2 vertexPos1, Color color, int width)
|
||||
{
|
||||
if (ParentEntity != null && ParentEntity.Submarine != null)
|
||||
{
|
||||
vertexPos0 += ParentEntity.Submarine.DrawPosition;
|
||||
vertexPos1 += ParentEntity.Submarine.DrawPosition;
|
||||
}
|
||||
Vector2 viewTargetPos = LightManager.ViewTarget.WorldPosition;
|
||||
float alpha = IsSegmentFacing(vertexPos0, vertexPos1, viewTargetPos) ? 1.0f : 0.5f;
|
||||
vertexPos0.Y = -vertexPos0.Y;
|
||||
vertexPos1.Y = -vertexPos1.Y;
|
||||
GUI.DrawLine(spriteBatch, vertexPos0, vertexPos1, color * alpha, width: width);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -903,16 +687,13 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
HullLists.Remove(chList);
|
||||
}
|
||||
foreach (ConvexHull ch2 in overlappingHulls)
|
||||
//create a new list because MergeLosVertices can edit overlappingHulls
|
||||
foreach (ConvexHull ch2 in overlappingHulls.ToList())
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ch2.ignoreEdge[i] = false;
|
||||
}
|
||||
ch2.overlappingHulls.Remove(this);
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
ch.MergeOverlappingSegments(ch2);
|
||||
ch.MergeLosVertices(ch2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user