public void RecalculateFromPosition(Point viewerPosition) { // Test from each corner of source square to center of target square PointF[] cornersToTest = { new PointF(viewerPosition.X, viewerPosition.Y), new PointF(viewerPosition.X + 1, viewerPosition.Y), new PointF(viewerPosition.X, viewerPosition.Y + 1), new PointF(viewerPosition.X + 1, viewerPosition.Y + 1) }; this.VisibilityMap = null; foreach (var point in cornersToTest) { VisibilityMap cornerMap = this.GenerateVisibilityMapForPosition(point); if (this.VisibilityMap == null) { this.VisibilityMap = cornerMap; } else { for (int x = 0; x < cornerMap.Width; ++x) { for (int y = 0; y < cornerMap.Height; ++y) { this.VisibilityMap[x, y] = (OcclusionLevel)Math.Min((int)this.VisibilityMap[x, y], (int)cornerMap[x, y]); } } } } // Calculate cover spots for (int x = 0; x < this.VisibilityMap.Width; ++x) { for (int y = 0; y < this.VisibilityMap.Height; ++y) { if (this.VisibilityMap[x, y] == OcclusionLevel.Obscured) { if (TestSquare(x, y - 1) == OcclusionLevel.Visible || TestSquare(x, y + 1) == OcclusionLevel.Visible || TestSquare(x - 1, y) == OcclusionLevel.Visible || TestSquare(x + 1, y) == OcclusionLevel.Visible) { this.VisibilityMap[x, y] = OcclusionLevel.Cover; } } } } //PointF centerOfSquare = new PointF((float)viewerPosition.X + 0.5f, (float)viewerPosition.Y + 0.5f); //this.VisibilityMap = this.GenerateVisibilityMapForPosition(centerOfSquare); //this.TestCorners(viewerPosition); }
private void TestCorners(Point viewerPosition) { List <PointF> cornersToTest = new List <PointF>(); if (this.VisibilityMap[viewerPosition.X - 1, viewerPosition.Y - 1] != OcclusionLevel.Obscured && (this.VisibilityMap[viewerPosition.X, viewerPosition.Y - 1] == OcclusionLevel.Obscured || this.VisibilityMap[viewerPosition.X - 1, viewerPosition.Y] == OcclusionLevel.Obscured)) { // test upper left corner, wall either above or left cornersToTest.Add(new PointF((float)viewerPosition.X, (float)viewerPosition.Y)); } if (this.VisibilityMap[viewerPosition.X + 1, viewerPosition.Y - 1] != OcclusionLevel.Obscured && (this.VisibilityMap[viewerPosition.X, viewerPosition.Y - 1] == OcclusionLevel.Obscured || this.VisibilityMap[viewerPosition.X + 1, viewerPosition.Y] == OcclusionLevel.Obscured)) { // test upper right corner, wall either above or right cornersToTest.Add(new PointF((float)viewerPosition.X + 1, (float)viewerPosition.Y)); } if (this.VisibilityMap[viewerPosition.X - 1, viewerPosition.Y + 1] != OcclusionLevel.Obscured && (this.VisibilityMap[viewerPosition.X, viewerPosition.Y + 1] == OcclusionLevel.Obscured || this.VisibilityMap[viewerPosition.X - 1, viewerPosition.Y] == OcclusionLevel.Obscured)) { // test lower-left corner, wall either left or bottom cornersToTest.Add(new PointF((float)viewerPosition.X, (float)viewerPosition.Y + 1)); } if (this.VisibilityMap[viewerPosition.X + 1, viewerPosition.Y + 1] != OcclusionLevel.Obscured && (this.VisibilityMap[viewerPosition.X, viewerPosition.Y + 1] == OcclusionLevel.Obscured || this.VisibilityMap[viewerPosition.X + 1, viewerPosition.Y] == OcclusionLevel.Obscured)) { // test lower-right corner, wall either right or bottom cornersToTest.Add(new PointF((float)viewerPosition.X + 1, (float)viewerPosition.Y + 1)); } // if we have corners to test, then run through the whole visibility map from that corner and union it to our result foreach (var point in cornersToTest) { VisibilityMap cornerMap = this.GenerateVisibilityMapForPosition(point); for (int x = 0; x < cornerMap.Width; ++x) { for (int y = 0; y < cornerMap.Height; ++y) { this.VisibilityMap[x, y] = this.VisibilityMap[x, y] == OcclusionLevel.Obscured ? OcclusionLevel.Obscured : cornerMap[x, y]; } } } }
private VisibilityMap GenerateVisibilityMapForPosition(PointF viewerLocation) { VisibilityMap visData = new VisibilityMap(this.Max.X - this.Min.X, this.Max.Y - this.Min.Y); for (int x = this.Min.X; x < this.Max.X; ++x) { for (int y = this.Min.Y; y < this.Max.Y; ++y) { PointF targetLocation = new PointF((float)x + 0.5f, (float)y + 0.5f); visData[x - this.Min.X, y - this.Min.Y] = this.GetOcclusion(viewerLocation, targetLocation); } } return(visData); }