/// <summary> /// Delete the specified revealer. /// </summary> static void DoRemoveRevealer(IMangoFogRevealer rev) { if (rev != null) { lock (revealersRemoved) revealersRemoved.Add(rev); } }
/// <summary> /// Create a new fog revealer. /// </summary> static void DoAddRevealer(IMangoFogRevealer rev) { if (rev != null) { lock (revealersAdded) revealersAdded.Add(rev); } }
/// <summary> /// The fastest form of visibility updates -- radius-based, no line of sights checks. /// </summary> protected void RevealUsingRadius(IMangoFogRevealer r, float worldToTex) { // Position relative to the fog of war Vector3 pos = (r.GetPosition() - chunkOrigin) * worldToTex; //Vector3 pos = (r.GetPosition() - chunkOrigin) * worldToTex; float radius = r.GetRadius() * worldToTex; // Coordinates we'll be dealing with int xmin = Mathf.RoundToInt(pos.x - radius); int xmax = Mathf.RoundToInt(pos.x + radius); int ymin, ymax, cy; //use z for 3d, and y for 2d if (orientation == MangoFogOrientation.Perspective3D) { ymin = Mathf.RoundToInt(pos.z - radius); ymax = Mathf.RoundToInt(pos.z + radius); cy = Mathf.RoundToInt(pos.z); } else { ymin = Mathf.RoundToInt(pos.y - radius); ymax = Mathf.RoundToInt(pos.y + radius); cy = Mathf.RoundToInt(pos.y); } int cx = Mathf.RoundToInt(pos.x); int radiusSqr = Mathf.RoundToInt(radius * radius); for (int y = ymin; y < ymax; ++y) { if (y > -1 && y < textureSize) { int yw = y * textureSize; for (int x = xmin; x < xmax; ++x) { int xd = x - cx; int yd = y - cy; int dist = xd * xd + yd * yd; if (x > -1 && x < textureSize) { // Reveal this pixel if (dist < radiusSqr) { buffer1[x + yw].r = 255; } } } } } }
/// <summary> /// Update the fog of war's visibility. /// </summary> protected void UpdateBuffer() { // Use the texture blend time, thus estimating the time this update will finish // Doing so helps avoid visible changes in blending caused by the blended result being X milliseconds behind. float factor = (textureBlendTime > 0f) ? Mathf.Clamp01(blendFactor + elapsed / textureBlendTime) : 1f; // Clear the buffer's red channel (channel used for current visibility -- it's updated right after) for (int i = 0, imax = buffer0.Length; i < imax; ++i) { buffer0[i] = Color32.Lerp(buffer0[i], buffer1[i], factor); buffer1[i].r = 0; } // For conversion from world coordinates to texture coordinates float worldToTex = (float)textureSize / chunkSize; // Update the visibility buffer, one revealer at a time for (int i = 0; i < MangoFogInstance.revealers.size; ++i) { IMangoFogRevealer rev = MangoFogInstance.revealers[i]; if (rev.IsValid()) { if (rev.GetRevealerType() == RevealerType.Radius) { RevealUsingRadius(rev, worldToTex); } else { RevealUsingLOS(rev, worldToTex); } } } // Blur the final visibility data for (int i = 0; i < blurIterations; ++i) { BlurVisibility(); } // Reveal the map based on what's currently visible RevealMap(); // Merge two buffer to one MergeBuffer(); //ready to update the texture , multi chunk experimental only changeStates[chunkID] = 2; }
protected void UpdateRevealers(int deltaMS) { // Add all items scheduled to be added if (revealersAdded.size > 0) { lock (revealersAdded) { while (revealersAdded.size > 0) { int index = revealersAdded.size - 1; revealers.Add(revealersAdded.buffer[index]); revealersAdded.RemoveAt(index); } } } // Remove all items scheduled for removal if (revealersRemoved.size > 0) { lock (revealersRemoved) { while (revealersRemoved.size > 0) { int index = revealersRemoved.size - 1; revealers.Remove(revealersRemoved.buffer[index]); revealersRemoved.RemoveAt(index); } } } for (int i = revealers.size - 1; i >= 0; i--) { IMangoFogRevealer revealer = revealers[i]; revealer.Update(deltaMS); if (!revealer.IsValid()) { revealer.Release(); } } }
/// <summary> /// Reveal the map around the revealer performing line-of-sight checks. /// </summary> void RevealUsingLOS(IMangoFogRevealer r, float worldToTex) { // Position relative to the fog of war Vector3 pos = r.GetPosition() - chunkOrigin; int ymin, ymax, xmin, xmax, cx, cy, gh; // Coordinates we'll be dealing with //use z for 3d, and y for 2d if (orientation == MangoFogOrientation.Perspective3D) { ymin = Mathf.RoundToInt((pos.z - r.GetLOSOuterRadius()) * worldToTex); ymax = Mathf.RoundToInt((pos.z + r.GetLOSOuterRadius()) * worldToTex); cy = Mathf.RoundToInt(pos.z * worldToTex); gh = WorldToGridHeight(r.GetPosition().y); } else { ymin = Mathf.RoundToInt((pos.y - r.GetLOSOuterRadius()) * worldToTex); ymax = Mathf.RoundToInt((pos.y + r.GetLOSOuterRadius()) * worldToTex); cy = Mathf.RoundToInt(pos.y * worldToTex); gh = WorldToGridHeight(r.GetPosition().z); } cx = Mathf.RoundToInt(pos.x * worldToTex); xmin = Mathf.RoundToInt((pos.x - r.GetLOSOuterRadius()) * worldToTex); xmax = Mathf.RoundToInt((pos.x + r.GetLOSOuterRadius()) * worldToTex); xmin = Mathf.Clamp(xmin, 0, textureSize - 1); xmax = Mathf.Clamp(xmax, 0, textureSize - 1); ymin = Mathf.Clamp(ymin, 0, textureSize - 1); ymax = Mathf.Clamp(ymax, 0, textureSize - 1); cx = Mathf.Clamp(cx, 0, textureSize - 1); cy = Mathf.Clamp(cy, 0, textureSize - 1); int minRange = Mathf.RoundToInt(r.GetLOSInnerRadius() * r.GetLOSInnerRadius() * worldToTex * worldToTex); int maxRange = Mathf.RoundToInt(r.GetLOSOuterRadius() * r.GetLOSOuterRadius() * worldToTex * worldToTex); int variance = Mathf.RoundToInt(Mathf.Clamp01(MangoFogInstance.Instance.margin / (MangoFogInstance.Instance.heightRange.y - MangoFogInstance.Instance.heightRange.x)) * 255); Color32 white = new Color32(255, 255, 255, 255); // Leave the edges unrevealed int limit = textureSize - 1; for (int y = ymin; y < ymax; ++y) { if (y > -1 && y < limit) { for (int x = xmin; x < xmax; ++x) { if (x > -1 && x < limit) { int xd = x - cx; int yd = y - cy; int dist = xd * xd + yd * yd; int index = x + y * textureSize; if (dist < minRange || (cx == x && cy == y)) { buffer1[index] = white; } else if (dist < maxRange) { Vector2 v = new Vector2(xd, yd); v.Normalize(); v *= r.GetRadius() / 2; int sx = cx + Mathf.RoundToInt(v.x); int sy = cy + Mathf.RoundToInt(v.y); if (sx > -1 && sx < textureSize && sy > -1 && sy < textureSize && IsVisible(sx, sy, x, y, Mathf.Sqrt(dist), gh, variance, r.GetRot(), r.GetFOVCosine(), r.DoReverseLOSDirection())) { buffer1[index] = white; } } } } } } }