public void Unfog(Vector3 position, float radius, float angle, Vector3 forward, int layermask = 0) { FogFill fogfill = new FogFill(this, position, radius, angle, forward); ColliderFogRectList colliderrects = GetExtendedColliders(fogfill, layermask); if (colliderrects == null) { fogfill.UnfogCircle(_values); return; } //if (colliderrects.Count != 1 || !colliderrects[0].ContainsCircle(fogfill.position, fogfill.radius)) // fogfill.UnfogCircle(_values, colliderrects); fogfill.UnfogCircleLineOfSight(_values, colliderrects, layermask); }
ColliderFogRectList GetExtendedColliders(FogFill fogfill, int layermask) { // quick check to see if all raycasts will hit something if (layermask == 0) { return(null); } ColliderFogRectList colliderrects = null; if (mode == FogOfWarMode.Mode2D) { // is there anything overlapping with the area? Collider2D[] colliders = Physics2D.OverlapCircleAll(fogfill.worldPosition, fogfill.worldRadius, layermask); if (colliders.Length == 0) { return(null); } // extend the colliders outwards away from the center colliderrects = new ColliderFogRectList(this); colliderrects.Add(colliders); } else//if (mode == FogOfWarMode.Mode3D) { // is there anything overlapping with the area? Collider[] colliders = Physics.OverlapSphere(fogfill.worldPosition, fogfill.worldRadius, layermask); if (colliders.Length == 0) { return(null); } // extend the colliders outwards away from the center colliderrects = new ColliderFogRectList(this); colliderrects.Add(colliders); } colliderrects.ExtendToCircleEdge(fogfill.position, fogfill.radius); colliderrects.Optimise(); return(colliderrects.Count == 0 ? null : colliderrects); }
public void UnfogCircleLineOfSight(byte[] values, ColliderFogRectList excluderects, int layermask) { for (int y = yStart; y < yEnd; ++y) { for (int x = xStart; x < xEnd; ++x) { int index = y * fogOfWar.mapResolution + x; // do nothing if it is already completely unfogged if (values[index] == 0) { continue; } Vector2i offset = new Vector2i(x - position.x, y - position.y); // do nothing if too far too see int sqrdistance = offset.sqrMagnitude; if (sqrdistance >= radiusSqr) { continue; } // is this point in the view cone? Vector2 dir = offset.normalized; if (!IsInViewCone(dir)) { continue; } // if it could be hidden, raycast to make sure if (excluderects.Contains(new Vector2i(x, y))) { // perform raycast float hitdistance; if (Raycast(sqrdistance, offset, layermask, out hitdistance)) { // optimisation if (fogOfWar.fieldOfViewPenetration == 0.0f) { continue; } // offset the pixel back so that we can see what we are looking at // TODO: This could be optimised by keeping it as ints float pixeldistsqr = new Vector2(offset.x * fogOfWar.pixelSize, offset.y * fogOfWar.pixelSize).sqrMagnitude; float penetration = Mathf.Min(hitdistance + fogOfWar.fieldOfViewPenetration, worldRadius); if (pixeldistsqr >= penetration * penetration) { continue; } } } // fully unfogged if (sqrdistance <= innerRadiusSqr) { values[index] = 0; } // partially fogged (lerp between innerradius and radius) else// if (sqrdistance <= radiusSqr) { float t = (Mathf.Sqrt(sqrdistance) - innerRadius) / (radius - innerRadius); byte v = (byte)Mathf.Lerp(0, 255, t); if (v < values[index]) { values[index] = v; } } } } }