Better logic for determining which convex hulls are in the range of a lightsource (separate convexhull lists for each sub)
This commit is contained in:
@@ -428,7 +428,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (LightSource != null)
|
||||
{
|
||||
LightSource.Submarine = body.Submarine;
|
||||
LightSource.ParentSub = body.Submarine;
|
||||
LightSource.Position = Position;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Barotrauma.Items.Components
|
||||
: base (item, element)
|
||||
{
|
||||
light = new LightSource(element);
|
||||
light.Submarine = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
|
||||
light.ParentSub = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
|
||||
light.Position = item.Position;
|
||||
light.CastShadows = castShadows;
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
light.Submarine = item.Submarine;
|
||||
light.ParentSub = item.Submarine;
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime);
|
||||
|
||||
|
||||
@@ -42,9 +42,21 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
class ConvexHullList
|
||||
{
|
||||
public readonly Submarine Submarine;
|
||||
public List<ConvexHull> List;
|
||||
|
||||
public ConvexHullList(Submarine submarine)
|
||||
{
|
||||
Submarine = submarine;
|
||||
List = new List<ConvexHull>();
|
||||
}
|
||||
}
|
||||
|
||||
class ConvexHull
|
||||
{
|
||||
public static List<ConvexHull> list = new List<ConvexHull>();
|
||||
public static List<ConvexHullList> HullLists = new List<ConvexHullList>();
|
||||
static BasicEffect shadowEffect;
|
||||
static BasicEffect penumbraEffect;
|
||||
|
||||
@@ -116,15 +128,20 @@ namespace Barotrauma.Lights
|
||||
|
||||
Enabled = true;
|
||||
|
||||
foreach (ConvexHull ch in list)
|
||||
var chList = HullLists.Find(x => x.Submarine == parent.Submarine);
|
||||
if (chList == null)
|
||||
{
|
||||
chList = new ConvexHullList(parent.Submarine);
|
||||
HullLists.Add(chList);
|
||||
}
|
||||
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
UpdateIgnoredEdges(ch);
|
||||
ch.UpdateIgnoredEdges(this);
|
||||
}
|
||||
|
||||
|
||||
list.Add(this);
|
||||
|
||||
chList.List.Add(this);
|
||||
}
|
||||
|
||||
private void UpdateIgnoredEdges(ConvexHull ch)
|
||||
@@ -219,7 +236,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
foreach (KeyValuePair<LightSource, CachedShadow> cachedShadow in cachedShadows)
|
||||
{
|
||||
cachedShadow.Key.NeedsHullUpdate();
|
||||
cachedShadow.Key.NeedsHullUpdate = true;
|
||||
cachedShadow.Value.Dispose();
|
||||
}
|
||||
cachedShadows.Clear();
|
||||
@@ -377,13 +394,13 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (parentEntity != null && parentEntity.Submarine != null)
|
||||
{
|
||||
if (light.Submarine == null)
|
||||
if (light.ParentSub == null)
|
||||
{
|
||||
lightSourcePos -= parentEntity.Submarine.Position;
|
||||
}
|
||||
else if (light.Submarine != parentEntity.Submarine)
|
||||
else if (light.ParentSub != parentEntity.Submarine)
|
||||
{
|
||||
lightSourcePos += (light.Submarine.Position-parentEntity.Submarine.Position);
|
||||
lightSourcePos += (light.ParentSub.Position-parentEntity.Submarine.Position);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -467,7 +484,16 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
ClearCachedShadows();
|
||||
|
||||
list.Remove(this);
|
||||
var chList = HullLists.Find(x => x.Submarine == parentEntity.Submarine);
|
||||
|
||||
if (chList != null)
|
||||
{
|
||||
chList.List.Remove(this);
|
||||
if (chList.List.Count == 0)
|
||||
{
|
||||
HullLists.Remove(chList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
light.UpdateHullsInRange();
|
||||
light.NeedsHullUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,10 +94,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
if (light.Color.A < 0.01f || light.Range < 1.0f) continue;
|
||||
//!!!!!!!!!!!!!!!!
|
||||
if (light.hullsInRange == null) light.UpdateHullsInRange();
|
||||
if (!light.hullsInRange.Any() || !MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
||||
if (light.Color.A < 0.01f || light.Range < 1.0f || !light.CastShadows) continue;
|
||||
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
||||
|
||||
//clear alpha to 1
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
@@ -107,12 +105,7 @@ namespace Barotrauma.Lights
|
||||
graphics.RasterizerState = RasterizerState.CullNone;
|
||||
graphics.BlendState = CustomBlendStates.WriteToAlpha;
|
||||
|
||||
foreach (ConvexHull ch in light.hullsInRange)
|
||||
{
|
||||
//if (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, ch.BoundingBox)) continue;
|
||||
//draw shadow
|
||||
ch.DrawShadows(graphics, cam, light, shadowTransform, false);
|
||||
}
|
||||
light.DrawShadows(graphics, cam, shadowTransform);
|
||||
|
||||
//draw the light shape
|
||||
//where Alpha is 0, nothing will be written
|
||||
@@ -131,7 +124,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
if (light.hullsInRange==null || light.hullsInRange.Any() || light.Color.A < 0.01f) continue;
|
||||
if (light.Color.A < 0.01f || light.Range < 1.0f || light.CastShadows) continue;
|
||||
//if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
||||
|
||||
light.Draw(spriteBatch);
|
||||
@@ -186,13 +179,18 @@ namespace Barotrauma.Lights
|
||||
Matrix shadowTransform = cam.ShaderTransform
|
||||
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
|
||||
|
||||
foreach (ConvexHull convexHull in ConvexHull.list)
|
||||
{
|
||||
if (!convexHull.Intersects(camView)) continue;
|
||||
//if (!camView.Intersects(convexHull.BoundingBox)) continue;
|
||||
var convexHulls = LightSource.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine);
|
||||
|
||||
convexHull.DrawShadows(graphics, cam, pos, shadowTransform);
|
||||
}
|
||||
if (convexHulls != null)
|
||||
{
|
||||
foreach (ConvexHull convexHull in convexHulls)
|
||||
{
|
||||
if (!convexHull.Intersects(camView)) continue;
|
||||
//if (!camView.Intersects(convexHull.BoundingBox)) continue;
|
||||
|
||||
convexHull.DrawShadows(graphics, cam, pos, shadowTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
graphics.SetRenderTarget(null);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
private static Texture2D lightTexture;
|
||||
|
||||
public List<ConvexHull> hullsInRange;
|
||||
private List<ConvexHullList> hullsInRange;
|
||||
|
||||
private Color color;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
private Sprite overrideLightTexture;
|
||||
|
||||
public Entity Submarine;
|
||||
public Entity ParentSub;
|
||||
|
||||
public bool CastShadows;
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
private Vector2 prevHullUpdatePosition;
|
||||
|
||||
public bool NeedsHullUpdate;
|
||||
|
||||
private Vector2 position;
|
||||
public Vector2 Position
|
||||
{
|
||||
@@ -43,8 +45,8 @@ namespace Barotrauma.Lights
|
||||
position = value;
|
||||
|
||||
if (Vector2.Distance(prevHullUpdatePosition, position) < 5.0f) return;
|
||||
|
||||
UpdateHullsInRange();
|
||||
|
||||
NeedsHullUpdate = true;
|
||||
prevHullUpdatePosition = position;
|
||||
}
|
||||
}
|
||||
@@ -57,7 +59,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
public Vector2 WorldPosition
|
||||
{
|
||||
get { return (Submarine == null) ? position : position + Submarine.Position; }
|
||||
get { return (ParentSub == null) ? position : position + ParentSub.Position; }
|
||||
}
|
||||
|
||||
public static Texture2D LightTexture
|
||||
@@ -87,8 +89,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
if (Math.Abs(prevHullUpdateRange - range) < 10.0f) return;
|
||||
|
||||
UpdateHullsInRange();
|
||||
|
||||
NeedsHullUpdate = true;
|
||||
prevHullUpdateRange = range;
|
||||
}
|
||||
}
|
||||
@@ -117,9 +119,9 @@ namespace Barotrauma.Lights
|
||||
|
||||
public LightSource(Vector2 position, float range, Color color, Submarine submarine)
|
||||
{
|
||||
hullsInRange = new List<ConvexHull>();
|
||||
hullsInRange = new List<ConvexHullList>();
|
||||
|
||||
this.Submarine = submarine;
|
||||
this.ParentSub = submarine;
|
||||
|
||||
this.position = position;
|
||||
this.range = range;
|
||||
@@ -132,43 +134,166 @@ namespace Barotrauma.Lights
|
||||
GameMain.LightManager.AddLight(this);
|
||||
}
|
||||
|
||||
public void UpdateHullsInRange()
|
||||
public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform)
|
||||
{
|
||||
if (!CastShadows) return;
|
||||
|
||||
if (hullsInRange == null) hullsInRange = new List<ConvexHull>();
|
||||
|
||||
hullsInRange.Clear();
|
||||
if (range < 1.0f || color.A < 0.01f) return;
|
||||
|
||||
foreach (ConvexHull ch in ConvexHull.list)
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
Vector2 lightPos = position;
|
||||
var hulls = GetHullsInRange(sub);
|
||||
|
||||
if (Submarine==null)
|
||||
if (hulls == null) continue;
|
||||
|
||||
foreach ( ConvexHull ch in hulls)
|
||||
{
|
||||
if (ch.ParentEntity.Submarine != null)
|
||||
ch.DrawShadows(graphics, cam, this, shadowTransform, false);
|
||||
}
|
||||
}
|
||||
|
||||
var outsideHulls = GetHullsInRange(null);
|
||||
|
||||
NeedsHullUpdate = false;
|
||||
|
||||
if (outsideHulls == null) return;
|
||||
foreach (ConvexHull ch in outsideHulls)
|
||||
{
|
||||
ch.DrawShadows(graphics, cam, this, shadowTransform, false);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ConvexHull> GetHullsInRange(Submarine sub)
|
||||
{
|
||||
var chList = hullsInRange.Find(x => x.Submarine == sub);
|
||||
|
||||
if (chList == null)
|
||||
{
|
||||
chList = new ConvexHullList(sub);
|
||||
hullsInRange.Add(chList);
|
||||
}
|
||||
List<ConvexHull> list = chList.List;
|
||||
|
||||
|
||||
Vector2 lightPos = position;
|
||||
if (ParentSub == null)
|
||||
{
|
||||
//light and the convexhull are both outside
|
||||
if (sub == null)
|
||||
{
|
||||
if (NeedsHullUpdate)
|
||||
{
|
||||
lightPos -= ch.ParentEntity.Submarine.Position;
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
|
||||
list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
chList.List = list;
|
||||
}
|
||||
}
|
||||
else if (ch.ParentEntity.Submarine != null && ch.ParentEntity.Submarine != Submarine)
|
||||
//light is outside, convexhull inside a sub
|
||||
else
|
||||
{
|
||||
lightPos -= (ch.ParentEntity.Submarine.Position - Submarine.Position);
|
||||
}
|
||||
//todo: check
|
||||
lightPos -= sub.Position;
|
||||
|
||||
if (MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))
|
||||
{
|
||||
hullsInRange.Add(ch);
|
||||
Rectangle subBorders = sub.Borders;
|
||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||
|
||||
//only draw if the light overlaps with the sub
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null;
|
||||
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//light is inside, convexhull outside
|
||||
if (sub == null) return null;
|
||||
|
||||
//light and convexhull are both inside the same sub
|
||||
if (sub == ParentSub)
|
||||
{
|
||||
if (NeedsHullUpdate)
|
||||
{
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
|
||||
list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
chList.List = list;
|
||||
}
|
||||
}
|
||||
//light and convexhull are inside different subs
|
||||
else
|
||||
{
|
||||
lightPos -= (sub.Position - ParentSub.Position);
|
||||
|
||||
Rectangle subBorders = sub.Borders;
|
||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||
|
||||
//only draw if the light overlaps with the sub
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null;
|
||||
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void NeedsHullUpdate()
|
||||
public static List<ConvexHull> GetHullsInRange(Vector2 position, float range, Submarine ParentSub)
|
||||
{
|
||||
hullsInRange = null;
|
||||
List<ConvexHull> list = new List<ConvexHull>();
|
||||
|
||||
foreach (ConvexHullList chList in ConvexHull.HullLists)
|
||||
{
|
||||
Vector2 lightPos = position;
|
||||
if (ParentSub == null)
|
||||
{
|
||||
//light and the convexhull are both outside
|
||||
if (chList.Submarine == null)
|
||||
{
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
|
||||
}
|
||||
//light is outside, convexhull inside a sub
|
||||
else
|
||||
{
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, chList.Submarine.Borders)) continue;
|
||||
|
||||
lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition);
|
||||
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//light is inside, convexhull outside
|
||||
if (chList.Submarine == null) continue;
|
||||
|
||||
//light and convexhull are both inside the same sub
|
||||
if (chList.Submarine == ParentSub)
|
||||
{
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
}
|
||||
//light and convexhull are inside different subs
|
||||
else
|
||||
{
|
||||
lightPos -= (chList.Submarine.Position - ParentSub.Position);
|
||||
|
||||
Rectangle subBorders = chList.Submarine.Borders;
|
||||
subBorders.Location += chList.Submarine.HiddenSubPosition.ToPoint() - new Point(0, chList.Submarine.Borders.Height);
|
||||
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) continue;
|
||||
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (range > 1.0f)
|
||||
|
||||
@@ -241,20 +241,22 @@ namespace Barotrauma
|
||||
|
||||
public static bool CircleIntersectsRectangle(Vector2 circlePos, float radius, Rectangle rect)
|
||||
{
|
||||
Vector2 circleDistance = new Vector2(Math.Abs(circlePos.X - rect.Center.X), Math.Abs(circlePos.Y -rect.Center.Y));
|
||||
float xDist = Math.Abs(circlePos.X - rect.Center.X);
|
||||
int halfWidth = rect.Width / 2;
|
||||
|
||||
if (circleDistance.X > (rect.Width / 2 + radius)) { return false; }
|
||||
if (circleDistance.Y > (rect.Height / 2 + radius)) { return false; }
|
||||
if (xDist > (halfWidth + radius)) { return false; }
|
||||
if (xDist <= (halfWidth)) { return true; }
|
||||
|
||||
if (circleDistance.X <= (rect.Width / 2)) { return true; }
|
||||
if (circleDistance.Y <= (rect.Height / 2)) { return true; }
|
||||
float yDist = Math.Abs(circlePos.Y - rect.Center.Y);
|
||||
int halfHeight = rect.Height / 2;
|
||||
|
||||
float distSqX = circleDistance.X - rect.Width / 2;
|
||||
float distSqY = circleDistance.Y - rect.Height / 2;
|
||||
if (yDist > (halfHeight + radius)) { return false; }
|
||||
if (yDist <= (halfHeight)) { return true; }
|
||||
|
||||
float cornerDistanceSq = distSqX * distSqX + distSqY * distSqY;
|
||||
float distSqX = xDist - halfWidth;
|
||||
float distSqY = yDist - halfHeight;
|
||||
|
||||
return (cornerDistanceSq <= (radius * radius));
|
||||
return (distSqX * distSqX + distSqY * distSqY <= (radius * radius));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user