Unstable 1.2.4.0

This commit is contained in:
Markus Isberg
2023-11-30 13:53:00 +02:00
parent 8a2e2ea0ae
commit fb5ea537bf
210 changed files with 4201 additions and 1283 deletions
@@ -37,9 +37,9 @@ namespace Barotrauma.Lights
TextureRange = range;
if (OverrideLightTexture != null)
{
TextureRange += Math.Max(
Math.Abs(OverrideLightTexture.RelativeOrigin.X - 0.5f) * OverrideLightTexture.size.X,
Math.Abs(OverrideLightTexture.RelativeOrigin.Y - 0.5f) * OverrideLightTexture.size.Y);
TextureRange *= 1.0f + Math.Max(
Math.Abs(OverrideLightTexture.RelativeOrigin.X - 0.5f),
Math.Abs(OverrideLightTexture.RelativeOrigin.Y - 0.5f));
}
}
}
@@ -238,7 +238,11 @@ namespace Barotrauma.Lights
private bool needsRecalculationWhenUpToDate;
public bool NeedsRecalculation
{
get { return needsRecalculation; }
get
{
if (ParentBody?.UserData is Item it && it.Prefab.Identifier == "flashlight") { return true; }
return needsRecalculation;
}
set
{
if (!needsRecalculation && value)
@@ -708,6 +712,7 @@ namespace Barotrauma.Lights
{
foreach (ConvexHull hull in chList.List)
{
if (hull.IsInvalid) { continue; }
if (!chList.IsHidden.Contains(hull))
{
//find convexhull segments that are close enough and facing towards the light source
@@ -735,6 +740,7 @@ namespace Barotrauma.Lights
GameMain.LightManager.AddRayCastTask(this, drawPos, rotation);
}
const float MinPointDistance = 6;
public void RayCastTask(Vector2 drawPos, float rotation)
{
@@ -877,12 +883,11 @@ namespace Barotrauma.Lights
}
}
const float MinPointDistance = 6;
//remove points that are very close to each other
for (int i = 0; i < points.Count; i++)
//+= 2 because the points are added in pairs above, i.e. 0 and 1 belong to the same segment
for (int i = 0; i < points.Count; i += 2)
{
for (int j = Math.Min(i + 4, points.Count - 1); j > i; j--)
for (int j = Math.Min(i + 2, points.Count - 1); j > i; j--)
{
if (Math.Abs(points[i].WorldPos.X - points[j].WorldPos.X) < MinPointDistance &&
Math.Abs(points[i].WorldPos.Y - points[j].WorldPos.Y) < MinPointDistance)
@@ -892,14 +897,14 @@ namespace Barotrauma.Lights
}
}
var compareCCW = new CompareSegmentPointCW(drawPos);
try
{
points.Sort(compareCCW);
var compareCW = new CompareSegmentPointCW(drawPos);
points.Sort(compareCW);
}
catch (Exception e)
{
StringBuilder sb = new StringBuilder("Constructing light volumes failed! Light pos: " + drawPos + ", Hull verts:\n");
StringBuilder sb = new StringBuilder($"Constructing light volumes failed ({nameof(CompareSegmentPointCW)})! Light pos: {drawPos}, Hull verts:\n");
foreach (SegmentPoint sp in points)
{
sb.AppendLine(sp.Pos.ToString());
@@ -914,7 +919,11 @@ namespace Barotrauma.Lights
verts.Clear();
foreach (SegmentPoint p in points)
{
Vector2 dir = Vector2.Normalize(p.WorldPos - drawPos);
Vector2 diff = p.WorldPos - drawPos;
float dist = diff.Length();
//light source exactly at the segment point, don't cast a shadow (normalizing the vector would lead to NaN)
if (dist <= 0.0001f) { continue; }
Vector2 dir = diff / dist;
Vector2 dirNormal = new Vector2(-dir.Y, dir.X) * MinPointDistance;
//do two slightly offset raycasts to hit the segment itself and whatever's behind it
@@ -940,9 +949,36 @@ namespace Barotrauma.Lights
{
//the raycasts landed on different segments
//we definitely want to generate new geometry here
verts.Add(isPoint1 ? p.WorldPos : intersection1.pos);
verts.Add(isPoint2 ? p.WorldPos : intersection2.pos);
markAsVisible = true;
if (isPoint1)
{
TryAddPoints(intersection2.pos, p.WorldPos, drawPos, verts);
markAsVisible = true;
}
else if (isPoint2)
{
TryAddPoints(intersection1.pos, p.WorldPos, drawPos, verts);
markAsVisible = true;
}
else
{
//didn't hit either point, completely obstructed
verts.Add(intersection1.pos);
verts.Add(intersection2.pos);
}
static void TryAddPoints(Vector2 intersection, Vector2 point, Vector2 refPos, List<Vector2> verts)
{
//* 0.8f because we don't care about obstacles that are very close (intersecting walls),
//only about obstacles that are clearly between the point and the refPos
bool intersectionCloserThanPoint = Vector2.DistanceSquared(intersection, refPos) < Vector2.DistanceSquared(point, refPos) * 0.8f;
//if the raycast hit a segment that's closer than the point we're aiming towards,
//it means we didn't hit a segment behind the point, but something that's obstructing it
//= we don't want to add vertex at that obstructed point, it could make the light go through obstacles
if (!intersectionCloserThanPoint)
{
verts.Add(point);
}
verts.Add(intersection);
}
}
if (markAsVisible)
{
@@ -959,15 +995,32 @@ namespace Barotrauma.Lights
//remove points that are very close to each other
for (int i = 0; i < verts.Count - 1; i++)
{
for (int j = Math.Min(i + 4, verts.Count - 1); j > i; j--)
for (int j = verts.Count - 1; j > i; j--)
{
if (Math.Abs(verts[i].X - verts[j].X) < 6 &&
Math.Abs(verts[i].Y - verts[j].Y) < 6)
if (Math.Abs(verts[i].X - verts[j].X) < MinPointDistance &&
Math.Abs(verts[i].Y - verts[j].Y) < MinPointDistance)
{
verts.RemoveAt(j);
}
}
}
try
{
var compareCW = new CompareCW(drawPos);
verts.Sort(compareCW);
}
catch (Exception e)
{
StringBuilder sb = new StringBuilder($"Constructing light volumes failed ({nameof(CompareSegmentPointCW)})! Light pos: {drawPos}, verts:\n");
foreach (Vector2 v in verts)
{
sb.AppendLine(v.ToString());
}
DebugConsole.ThrowError(sb.ToString(), e);
}
calculatedDrawPos = drawPos;
state = LightVertexState.PendingVertexRecalculation;
}
@@ -1114,7 +1167,7 @@ namespace Barotrauma.Lights
//add the normals together and use some magic numbers to create
//a somewhat useful/good-looking blur
float blurDistance = 40.0f;
float blurDistance = 25.0f;
Vector2 nDiff = nDiff1 * blurDistance;
if (MathUtils.GetLineIntersection(vertex + (nDiff1 * blurDistance), nextVertex + (nDiff1 * blurDistance), vertex + (nDiff2 * blurDistance), prevVertex + (nDiff2 * blurDistance), true, out Vector2 intersection))
{
@@ -1230,7 +1283,8 @@ namespace Barotrauma.Lights
/// <param name="spriteBatch"></param>
public void DrawSprite(SpriteBatch spriteBatch, Camera cam)
{
if (GameMain.DebugDraw)
//uncomment if you want to visualize the bounds of the light volume
/*if (GameMain.DebugDraw)
{
Vector2 drawPos = position;
if (ParentSub != null)
@@ -1269,7 +1323,7 @@ namespace Barotrauma.Lights
{
GUI.DrawLine(spriteBatch, boundaryCorners[i].Pos, boundaryCorners[(i + 1) % 4].Pos, Color.White, 0, 3);
}
}
}*/
if (DeformableLightSprite != null)
{
@@ -1367,6 +1421,38 @@ namespace Barotrauma.Lights
}
}
public void DebugDrawVertices(SpriteBatch spriteBatch)
{
if (Range < 1.0f || Color.A < 1 || CurrentBrightness <= 0.0f) { return; }
//commented out because this is mostly just useful in very specific situations, otherwise it just makes debugdraw very messy
//(you may also need to add a condition here that only draws this for the specific light you're interested in)
if (GameMain.DebugDraw && vertices != null)
{
if (ParentBody?.UserData is Item it && it.Prefab.Identifier == "flashlight")
for (int i = 1; i < vertices.Length - 1; i += 2)
{
Vector2 vert1 = new Vector2(vertices[i].Position.X, vertices[i].Position.Y);
int nextIndex = (i + 2) % vertices.Length;
//the first vertex is the one at the position of the light source, skip that one
//(we just want to draw lines between the vertices at the circumference of the light volume)
if (nextIndex == 0) { nextIndex++; }
Vector2 vert2 = new Vector2(vertices[nextIndex].Position.X, vertices[nextIndex].Position.Y);
if (ParentSub != null)
{
vert1 += ParentSub.DrawPosition;
vert2 += ParentSub.DrawPosition;
}
vert1.Y = -vert1.Y;
vert2.Y = -vert2.Y;
var randomColor = ToolBox.GradientLerp(i / (float)vertices.Length, Color.Magenta, Color.Blue, Color.Yellow, Color.Green, Color.Cyan, Color.Red, Color.Purple, Color.Yellow);
GUI.DrawLine(spriteBatch, vert1, vert2, randomColor * 0.8f, width: 2);
}
}
}
public void DrawLightVolume(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform, bool allowRecalculation, ref int recalculationCount)
{
if (Range < 1.0f || Color.A < 1 || CurrentBrightness <= 0.0f) { return; }