bool LineOfSightCanSee(FogOfWarShape shape, Vector2 offset, float fogradius) { if (shape.lineOfSight == null) { return(true); } float idx = FogOfWarUtils.ClockwiseAngle(Vector2.up, offset) * shape.lineOfSight.Length / 360.0f; if (idx < 0) { idx += shape.lineOfSight.Length; } // sampling float value; if (_map.filterMode == FilterMode.Point) { value = shape.lineOfSight[Mathf.RoundToInt(idx) % shape.lineOfSight.Length]; } else { int idxlow = Mathf.FloorToInt(idx); int idxhigh = (idxlow + 1) % shape.lineOfSight.Length; value = Mathf.LerpUnclamped(shape.lineOfSight[idxlow], shape.lineOfSight[idxhigh], idx % 1); } float dist = value * fogradius; return(offset.sqrMagnitude < dist * dist); }
public DrawInfo(FogOfWarMap map, FogOfWarShape shape, float xradius, float yradius) { // convert size to fog space fogForward = shape.foward; forwardAngle = FogOfWarUtils.ClockwiseAngle(Vector2.up, fogForward) * Mathf.Deg2Rad; float sin = Mathf.Sin(-forwardAngle); float cos = Mathf.Cos(-forwardAngle); Vector2 relativeoffset = new Vector2(shape.offset.x * cos - shape.offset.y * sin, shape.offset.x * sin + shape.offset.y * cos); fogCenterPos = FogOfWarConversion.WorldToFog(FogOfWarConversion.WorldToFogPlane(shape.eyePosition, map.plane) + relativeoffset, map.offset, map.resolution, map.size); fogEyePos = new Vector2i(FogOfWarConversion.WorldToFog(shape.eyePosition, map.plane, map.offset, map.resolution, map.size)); // find ranges if (shape.visibleCells == null) { xMin = Mathf.Max(0, Mathf.RoundToInt(fogCenterPos.x - xradius)); xMax = Mathf.Min(map.resolution.x - 1, Mathf.RoundToInt(fogCenterPos.x + xradius)); yMin = Mathf.Max(0, Mathf.RoundToInt(fogCenterPos.y - yradius)); yMax = Mathf.Min(map.resolution.y - 1, Mathf.RoundToInt(fogCenterPos.y + yradius)); } else { fogCenterPos = FogOfWarConversion.SnapToNearestFogPixel(fogCenterPos); fogEyePos = new Vector2i(FogOfWarConversion.SnapToNearestFogPixel(FogOfWarConversion.WorldToFog(shape.eyePosition, map.offset, map.resolution, map.size))); Vector2i pos = new Vector2i(Mathf.RoundToInt(fogCenterPos.x), Mathf.RoundToInt(fogCenterPos.y)); Vector2i rad = new Vector2i(Mathf.RoundToInt(xradius), Mathf.RoundToInt(yradius)); xMin = Mathf.Max(0, Mathf.RoundToInt(pos.x - rad.x)); xMax = Mathf.Min(map.resolution.x - 1, Mathf.RoundToInt(pos.x + rad.x)); yMin = Mathf.Max(0, Mathf.RoundToInt(pos.y - rad.y)); yMax = Mathf.Min(map.resolution.y - 1, Mathf.RoundToInt(pos.y + rad.y)); } }
public override void Draw(FogOfWarShape shape, bool ismultithreaded) { DrawInfo info = new DrawInfo(_map, shape); _material.SetKeywordEnabled("SHAPE_CIRCLE", shape is FogOfWarShapeCircle); _material.SetKeywordEnabled("SHAPE_BOX", shape is FogOfWarShapeBox); _material.SetKeywordEnabled("LINE_OF_SIGHT", shape.lineOfSight != null); _material.SetKeywordEnabled("LINE_OF_SIGHT_CELLS", shape.visibleCells != null); _material.SetVector("_CenterPosition", info.fogCenterPos / (_map.size * _map.pixelSize)); _material.SetVector("_EyePosition", info.fogEyePos.ToFloat() / (_map.size * _map.pixelSize)); _material.SetVector("_EyeForward", info.fogForward); _material.SetFloat("_ForwardAngle", info.forwardAngle); _material.SetFloat("_Brightness", shape.brightness); SetupLineOfSight(shape); SetupLineOfSightCells(shape); Texture2D tex = null; if (shape is FogOfWarShapeCircle circle) { _material.SetVector("_Size", new Vector4(shape.radius / _map.size, circle.innerRadius, 1, 1)); _material.SetFloat("_Angle", 1 - circle.angle / 90); } else if (shape is FogOfWarShapeBox box) { _material.SetVector("_Size", shape.size / _map.size); tex = box.texture; } _renderTexture.MarkRestoreExpected(); Graphics.Blit(tex ?? _outputTexture, _renderTexture, _material); }
void SetupLineOfSightCells(FogOfWarShape shape) { // prepare texture if (shape.visibleCells == null) { return; } if (_lineOfSightCellsTex == null || _lineOfSightCellsTex.width * _lineOfSightCellsTex.height < shape.visibleCells.Length) { if (_lineOfSightCellsTex != null) { Object.Destroy(_lineOfSightCellsTex); } _lineOfSightCellsTex = new Texture2D(shape.visibleCellsWidth, shape.visibleCells.Length / shape.visibleCellsWidth, TextureFormat.Alpha8, false); _lineOfSightCellsTex.filterMode = FilterMode.Point; _lineOfSightCellsTex.wrapMode = TextureWrapMode.Clamp; _lineOfSightCellsCopyBuffer = new byte[shape.visibleCells.Length]; } for (int i = 0; i < shape.visibleCells.Length; ++i) { _lineOfSightCellsCopyBuffer[i] = shape.visibleCells[i] ? (byte)255 : (byte)0; } _lineOfSightCellsTex.LoadRawTextureData(_lineOfSightCellsCopyBuffer); _lineOfSightCellsTex.Apply(false, false); // setup material _material.SetTexture("_LineOfSightTex", _lineOfSightCellsTex); int pixelsize = (int)shape.CalculateMaxLineOfSightDistance() * 2 + 1; _material.SetFloat("_LineOfSightDistance", pixelsize / _map.size); }
void SetupLineOfSight(FogOfWarShape shape) { // prepare texture if (shape.lineOfSight == null) { return; } if (_lineOfSightTex == null || _lineOfSightTex.width < shape.lineOfSight.Length) { if (_lineOfSightTex != null) { Object.Destroy(_lineOfSightTex); } _lineOfSightTex = new Texture2D(shape.lineOfSight.Length, 1, TextureFormat.RFloat, false); _lineOfSightTex.filterMode = FilterMode.Bilinear; _lineOfSightTex.wrapMode = TextureWrapMode.Repeat; _lineOfSightCopyBuffer = new byte[shape.lineOfSight.Length * sizeof(float)]; } System.Buffer.BlockCopy(shape.lineOfSight, 0, _lineOfSightCopyBuffer, 0, shape.lineOfSight.Length * sizeof(float)); _lineOfSightTex.LoadRawTextureData(_lineOfSightCopyBuffer); _lineOfSightTex.Apply(false, false); // setup material _material.SetTexture("_LineOfSightTex", _lineOfSightTex); _material.SetFloat("_LineOfSightDistance", shape.CalculateMaxLineOfSightDistance() / _map.size); }
void ProcessUnits(bool checkstopwatch) { // remove any invalid units FogOfWarUnit.registeredUnits.RemoveAll(u => u == null); double millisecondfrequency = 1000.0 / System.Diagnostics.Stopwatch.Frequency; for (; _currentUnitProcessing < FogOfWarUnit.registeredUnits.Count; ++_currentUnitProcessing) { if (!FogOfWarUnit.registeredUnits[_currentUnitProcessing].isActiveAndEnabled || FogOfWarUnit.registeredUnits[_currentUnitProcessing].team != team) { continue; } FogOfWarShape shape = FogOfWarUnit.registeredUnits[_currentUnitProcessing].GetShape(this, physics, plane); if (multithreaded && updateAutomatically) { _threadPool.Run(() => _drawer.Draw(shape)); } else { _drawer.Draw(shape); } // do the timer check here so that at least one unit will be processed! if (checkstopwatch && _stopwatch.ElapsedTicks * millisecondfrequency >= maxMillisecondsPerFrame) { ++_currentUnitProcessing; break; } } }
public FogOfWarShape GetShape(FogOfWar fow, FogOfWarPhysics physics, FogOfWarPlane plane) { FogOfWarShape shape = CreateShape(fow); if (shape == null) { return(null); } shape.lineOfSight = CalculateLineOfSight(physics, shape.eyePosition, plane); shape.visibleCells = null; return(shape); }
public void Draw(FogOfWarShape shape, bool ismultithreaded) { _isMultithreaded = ismultithreaded; if (shape is FogOfWarShapeCircle) { DrawCircle(shape as FogOfWarShapeCircle); } else if (shape is FogOfWarShapeBox) { DrawBox(shape as FogOfWarShapeBox); } }
public void Draw(FogOfWarShape shape) { if (shape is FogOfWarShapeCircle) { DrawCircle(shape as FogOfWarShapeCircle); } else if (shape is FogOfWarShapeBox) { DrawBox(shape as FogOfWarShapeBox); } else if (shape is FogOfWarShapeTexture) { DrawTexture(shape as FogOfWarShapeTexture); } }
void FillShape(FogOfWarShape shape) { if (antiFlicker) { // snap to nearest fog pixel shape.eyePosition = FogOfWarConversion.SnapWorldPositionToNearestFogPixel(FogOfWarConversion.WorldToFogPlane(_transform.position, FogOfWar.current.plane), FogOfWar.current.mapOffset, FogOfWar.current.mapResolution, FogOfWar.current.mapSize); shape.eyePosition = FogOfWarConversion.FogPlaneToWorld(shape.eyePosition.x, shape.eyePosition.y, _transform.position.y, FogOfWar.current.plane); } else { shape.eyePosition = _transform.position; } shape.foward = _transform.forward; shape.offset = offset; shape.radius = radius; }
void ProcessUnits(System.Diagnostics.Stopwatch stopwatch) { // if we are not updating units and all units have finished processing if (!updateUnits && _currentUnitProcessing >= FogOfWarUnit.registeredUnits.Count) { return; } // remove any invalid units FogOfWarUnit.registeredUnits.RemoveAll(u => u == null); double millisecondfrequency = 1000.0 / System.Diagnostics.Stopwatch.Frequency; for (; _currentUnitProcessing < FogOfWarUnit.registeredUnits.Count; ++_currentUnitProcessing) { if (!FogOfWarUnit.registeredUnits[_currentUnitProcessing].isActiveAndEnabled || FogOfWarUnit.registeredUnits[_currentUnitProcessing].team != team) { continue; } FogOfWarShape shape = FogOfWarUnit.registeredUnits[_currentUnitProcessing].GetShape(this, physics, plane); if (_isMultithreaded) { ++_drawThreadTaskPoolCount; while (_drawThreadTaskPoolCount > _drawThreadTaskPool.Count) { _drawThreadTaskPool.Add(new FogOfWarDrawThreadTask()); } FogOfWarDrawThreadTask task = _drawThreadTaskPool[_drawThreadTaskPoolCount - 1]; task.drawer = _drawer; task.shape = shape; _threadPool.Run(task); } else { _drawer.Draw(shape, false); } // do the timer check here so that at least one unit will be processed if (stopwatch != null && _stopwatch.ElapsedTicks * millisecondfrequency >= maxMillisecondsPerFrame) { ++_currentUnitProcessing; break; } } }
public DrawInfo(FogOfWarMap map, FogOfWarShape shape) { // convert size to fog space Vector2 radius = shape.CalculateRadius() * map.pixelSize; fogForward = shape.foward; Vector2 relativeoffset; if (shape.absoluteOffset) { forwardAngle = 0; relativeoffset = shape.offset; } else { forwardAngle = FogOfWarUtils.ClockwiseAngle(Vector2.up, fogForward) * Mathf.Deg2Rad; float sin = Mathf.Sin(-forwardAngle); float cos = Mathf.Cos(-forwardAngle); relativeoffset = new Vector2(shape.offset.x * cos - shape.offset.y * sin, shape.offset.x * sin + shape.offset.y * cos); } fogCenterPos = FogOfWarConversion.WorldToFog(FogOfWarConversion.WorldToFogPlane(shape.eyePosition, map.plane) + relativeoffset, map.offset, map.resolution, map.size); fogEyePos = FogOfWarConversion.WorldToFog(shape.eyePosition, map.plane, map.offset, map.resolution, map.size).ToInt(); // find ranges if (shape.visibleCells == null) { xMin = Mathf.Max(0, Mathf.RoundToInt(fogCenterPos.x - radius.x)); xMax = Mathf.Min(map.resolution.x - 1, Mathf.RoundToInt(fogCenterPos.x + radius.x)); yMin = Mathf.Max(0, Mathf.RoundToInt(fogCenterPos.y - radius.y)); yMax = Mathf.Min(map.resolution.y - 1, Mathf.RoundToInt(fogCenterPos.y + radius.y)); } else { fogCenterPos = FogOfWarConversion.SnapToNearestFogPixel(fogCenterPos); fogEyePos = FogOfWarConversion.SnapToNearestFogPixel(FogOfWarConversion.WorldToFog(shape.eyePosition, map.offset, map.resolution, map.size)).ToInt(); Vector2Int pos = fogCenterPos.ToInt(); Vector2Int rad = radius.ToInt(); xMin = Mathf.Max(0, Mathf.RoundToInt(pos.x - rad.x)); xMax = Mathf.Min(map.resolution.x - 1, Mathf.RoundToInt(pos.x + rad.x)); yMin = Mathf.Max(0, Mathf.RoundToInt(pos.y - rad.y)); yMax = Mathf.Min(map.resolution.y - 1, Mathf.RoundToInt(pos.y + rad.y)); } }
void FillShape(FogOfWar fow, FogOfWarShape shape) { if (antiFlicker) { // snap to nearest fog pixel shape.eyePosition = FogOfWarConversion.SnapWorldPositionToNearestFogPixel(fow, FogOfWarConversion.WorldToFogPlane(_transform.position, fow.plane), fow.mapOffset, fow.mapResolution, fow.mapSize); shape.eyePosition = FogOfWarConversion.FogPlaneToWorld(shape.eyePosition.x, shape.eyePosition.y, _transform.position.y, fow.plane); } else { shape.eyePosition = _transform.position; } shape.brightness = brightness; shape.foward = FogOfWarConversion.TransformFogPlaneForward(_transform, fow.plane); shape.absoluteOffset = absoluteOffset; shape.offset = offset; shape.radius = circleRadius; shape.size = boxSize; }
public override void Draw(FogOfWarShape shape, bool ismultithreaded) { _isMultithreaded = ismultithreaded; if (shape is FogOfWarShapeCircle circle) { DrawCircle(circle); } else if (shape is FogOfWarShapeBox box) { if (box.rotateToForward) { DrawRotatedBox(box); } else { DrawAxisAlignedBox(box); } } }
public FogOfWarShape GetShape(FogOfWarPhysics physics, FogOfWarPlane plane) { FogOfWarShape shape = CreateShape(); if (shape == null) { return(null); } if (cellBased) { shape.lineOfSight = null; shape.visibleCells = CalculateLineOfSightCells(physics, shape.eyePosition); } else { shape.lineOfSight = CalculateLineOfSight(physics, shape.eyePosition, plane); shape.visibleCells = null; } return(shape); }
bool LineOfSightCanSeeCell(FogOfWarShape shape, Vector2i offset) { if (shape.visibleCells == null) { return(true); } int radius = Mathf.RoundToInt(shape.radius); int width = radius + radius + 1; offset.x += radius; if (offset.x < 0 || offset.x >= width) { return(true); } offset.y += radius; if (offset.y < 0 || offset.y >= width) { return(true); } return(shape.visibleCells[offset.y * width + offset.x]); }
bool LineOfSightCanSeeCell(FogOfWarShape shape, Vector2Int offset) { if (shape.visibleCells == null) { return(true); } // offset so it is relative to the center int halfwidth = shape.visibleCellsWidth >> 1; offset.x += halfwidth; if (offset.x < 0 || offset.x >= shape.visibleCellsWidth) { return(true); } offset.y += halfwidth; if (offset.y < 0 || offset.y >= shape.visibleCellsWidth) { return(true); } return(shape.visibleCells[offset.y * shape.visibleCellsWidth + offset.x]); }
public abstract void Draw(FogOfWarShape shape, bool ismultithreaded);