/// <summary> /// Update the contents of ConvexHullList and check if we need to recalculate vertices /// </summary> private void RefreshConvexHullList(ConvexHullList chList, Vector2 lightPos, Submarine sub) { var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub); if (fullChList == null) { return; } chList.List = fullChList.List.FindAll(ch => ch.Enabled && MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); NeedsHullCheck = true; }
public ConvexHull(Vector2[] points, Color color, Entity parent) { if (shadowEffect == null) { shadowEffect = new BasicEffect(GameMain.Instance.GraphicsDevice); shadowEffect.VertexColorEnabled = true; } if (penumbraEffect == null) { penumbraEffect = new BasicEffect(GameMain.Instance.GraphicsDevice); penumbraEffect.TextureEnabled = true; //shadowEffect.VertexColorEnabled = true; penumbraEffect.LightingEnabled = false; penumbraEffect.Texture = TextureLoader.FromFile("Content/Lights/penumbra.png"); } parentEntity = parent; //cachedShadows = new Dictionary<LightSource, CachedShadow>(); shadowVertices = new VertexPositionColor[6 * 2]; penumbraVertices = new VertexPositionTexture[6]; //vertices = points; SetVertices(points); //CalculateDimensions(); backFacing = new bool[4]; ignoreEdge = new bool[4]; Enabled = true; 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); } chList.List.Add(this); }
/// <summary> /// Recheck which convex hulls are in range (if needed), /// and check if we need to recalculate vertices due to changes in the convex hulls /// </summary> private void CheckHullsInRange() { List <Submarine> subs = new List <Submarine>(Submarine.Loaded); subs.Add(null); foreach (Submarine sub in subs) { //find the list of convexhulls that belong to the sub var chList = hullsInRange.Find(x => x.Submarine == sub); //not found -> create one if (chList == null) { chList = new ConvexHullList(sub); hullsInRange.Add(chList); NeedsRecalculation = true; } if (chList.List.Any(ch => ch.LastVertexChangeTime > lastRecalculationTime && !chList.IsHidden.Contains(ch))) { NeedsRecalculation = true; } Vector2 lightPos = position; if (ParentSub == null) { //light and the convexhulls are both outside if (sub == null) { if (NeedsHullCheck) { RefreshConvexHullList(chList, lightPos, null); } } //light is outside, convexhulls inside a sub else { lightPos -= sub.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)) { if (chList.List.Count > 0) { NeedsRecalculation = true; } chList.List.Clear(); continue; } RefreshConvexHullList(chList, lightPos, sub); } } else { //light is inside, convexhull outside if (sub == null) { continue; } //light and convexhull are both inside the same sub if (sub == ParentSub) { if (NeedsHullCheck) { RefreshConvexHullList(chList, lightPos, sub); } } //light and convexhull are inside different subs else { if (sub.DockedTo.Contains(ParentSub) && !NeedsHullCheck) { continue; } lightPos -= (sub.Position - ParentSub.Position); Rectangle subBorders = sub.Borders; subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height); //don't draw any shadows if the light doesn't overlap with the borders of the sub if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) { if (chList.List.Count > 0) { NeedsRecalculation = true; } chList.List.Clear(); continue; } //recalculate vertices if the subs have moved > 5 px relative to each other Vector2 diff = ParentSub.WorldPosition - sub.WorldPosition; Vector2 prevDiff; if (!diffToSub.TryGetValue(sub, out prevDiff)) { diffToSub.Add(sub, diff); NeedsRecalculation = true; } else if (Vector2.DistanceSquared(diff, prevDiff) > 5.0f * 5.0f) { diffToSub[sub] = diff; NeedsRecalculation = true; } RefreshConvexHullList(chList, lightPos, sub); } } } }
public ConvexHull(Vector2[] points, Color color, MapEntity parent) { if (shadowEffect == null) { shadowEffect = new BasicEffect(GameMain.Instance.GraphicsDevice) { VertexColorEnabled = true }; } if (penumbraEffect == null) { 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]; 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; if (ParentEntity is Structure structure) { System.Diagnostics.Debug.Assert(!structure.Removed); isHorizontal = structure.IsHorizontal; } else if (ParentEntity is Item item) { System.Diagnostics.Debug.Assert(!item.Removed); var door = item.GetComponent <Door>(); if (door != null) { isHorizontal = door.IsHorizontal; } } SetVertices(points); Enabled = true; var chList = HullLists.Find(h => h.Submarine == parent.Submarine); if (chList == null) { chList = new ConvexHullList(parent.Submarine); HullLists.Add(chList); } foreach (ConvexHull ch in chList.List) { MergeOverlappingSegments(ch); ch.MergeOverlappingSegments(this); } chList.List.Add(this); }
public ConvexHull(Vector2[] points, Color color, MapEntity parent) { if (shadowEffect == null) { shadowEffect = new BasicEffect(GameMain.Instance.GraphicsDevice) { VertexColorEnabled = true }; } if (penumbraEffect == null) { penumbraEffect = new BasicEffect(GameMain.Instance.GraphicsDevice) { TextureEnabled = true, LightingEnabled = false, Texture = TextureLoader.FromFile("Content/Lights/penumbra.png") }; } ParentEntity = parent; ShadowVertices = new VertexPositionColor[6 * 2]; PenumbraVertices = new VertexPositionTexture[6]; backFacing = new bool[4]; ignoreEdge = new bool[4]; SetVertices(points); Enabled = true; isHorizontal = BoundingBox.Width > BoundingBox.Height; if (ParentEntity is Structure structure) { isHorizontal = structure.IsHorizontal; } else if (ParentEntity is Item item) { var door = item.GetComponent <Door>(); if (door != null) { isHorizontal = door.IsHorizontal; } } var chList = HullLists.Find(h => h.Submarine == parent.Submarine); if (chList == null) { chList = new ConvexHullList(parent.Submarine); HullLists.Add(chList); } foreach (ConvexHull ch in chList.List) { MergeOverlappingSegments(ch); ch.MergeOverlappingSegments(this); } chList.List.Add(this); }