internal void PrepareTextureForDrawDevice(IDrawDevice device) { System.Drawing.PointF[] points = new System.Drawing.PointF[_verticesPositions.Count]; /** * Drawing texture based on displacement for each camera **/ Vector3 start = _absoluteStart * device.GetScaleAtZ(_absoluteStart.Z); Vector3 end = _absoluteEnd * device.GetScaleAtZ(_absoluteEnd.Z); Vector2 tangent = (end - start).Xy; float length = tangent.Length; for (int i = 0; i < points.Length; i++) { points[i] = new System.Drawing.PointF(_verticesPositions[i].X * length, _verticesPositions[i].Y); } System.Drawing.Bitmap pixelData = new System.Drawing.Bitmap((int)MathF.Ceiling(length), (int)MathF.Ceiling(_sway2)); using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(pixelData)) { g.Clear(System.Drawing.Color.Transparent); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed; g.DrawLines(_pen, points); } if (!BatchInfos.ContainsKey(device)) { BatchInfo bi = new BatchInfo( DrawTechnique.Add, Colors.White, new ContentRef <Texture>( new Texture(new ContentRef <Pixmap>(new Pixmap())) { FilterMin = TextureMinFilter.LinearMipmapLinear, FilterMag = TextureMagFilter.LinearSharpenSgis, WrapX = TextureWrapMode.ClampToEdge, WrapY = TextureWrapMode.ClampToEdge, TexSizeMode = Texture.SizeMode.Stretch })); BatchInfos.Add(device, new BoltData() { BatchInfo = bi }); } BoltData bd = BatchInfos[device]; Texture tx = bd.BatchInfo.MainTexture.Res; tx.BasePixmap.Res.MainLayer.FromBitmap(pixelData); tx.ReloadData(); bd.Start = start; bd.End = end; bd.IsReady = true; }
public int CalcPriority(IDrawDevice device) { if (!this.IsDirectional) { float uniformScale = this.GameObj.Transform.Scale; Vector3 pos = this.GameObj.Transform.Pos; float scale = device.GetScaleAtZ(pos.Z); float planarDist = (this.GameObj.Transform.Pos.Xy - device.ViewerPos.Xy).Length; float rangeFactor = 1.0f / (this.range * uniformScale); float distFactor = (MathF.Min(scale, 1.0f) * planarDist); float spotFactor; if (this.dir != Vector3.Zero) { spotFactor = 0.5f * (1.0f + Vector3.Dot((device.ViewerPos - this.GameObj.Transform.Pos).Normalized, this.dir)); } else { spotFactor = 1.0f; } return(MathF.RoundToInt(1000000.0f * spotFactor * distFactor * MathF.Pow(rangeFactor, 1.5f) * MathF.Pow(1.0f / this.intensity, 0.5f))); } else { return(MathF.RoundToInt(100.0f * MathF.Pow(1.0f / this.intensity, 0.5f))); } }
/// <summary> /// Determines the rectangular tile area that is visible to the specified <see cref="IDrawDevice"/>. /// </summary> /// <param name="device"></param> /// <param name="input"></param> public static TileOutput GetVisibleTileRect(IDrawDevice device, TileInput input) { TileOutput output; // Determine the view space transform of the tilemap float cameraScaleAtObj = device.GetScaleAtZ(input.TilemapPos.Z); Vector3 viewCenterWorldPos = device.GetWorldPos(new Vector3(device.TargetSize * 0.5f, input.TilemapPos.Z)); // Early-out, if so small that it might break the math behind rendering a single tile. if (cameraScaleAtObj <= 0.000000001f) { return(EmptyOutput); } // Determine transformed X and Y axis in world space output.XAxisWorld = Vector2.UnitX; output.YAxisWorld = Vector2.UnitY; MathF.TransformCoord(ref output.XAxisWorld.X, ref output.XAxisWorld.Y, input.TilemapAngle, input.TilemapScale); MathF.TransformCoord(ref output.YAxisWorld.X, ref output.YAxisWorld.Y, input.TilemapAngle, input.TilemapScale); // Determine which tile is in the center of view space. Point2 viewCenterTile = Point2.Zero; { Vector2 localViewCenter = (viewCenterWorldPos - input.TilemapPos).Xy; localViewCenter = new Vector2( Vector2.Dot(localViewCenter, output.XAxisWorld.Normalized), Vector2.Dot(localViewCenter, output.YAxisWorld.Normalized)) / input.TilemapScale; viewCenterTile = new Point2( (int)MathF.Floor(localViewCenter.X / input.TileSize.X), (int)MathF.Floor(localViewCenter.Y / input.TileSize.Y)); } // Determine the edge length of a square that is big enough to enclose the world space rect of the Camera view float visualAngle = input.TilemapAngle - device.ViewerAngle; Vector2 visualBounds = new Vector2( device.TargetSize.Y * MathF.Abs(MathF.Sin(visualAngle)) + device.TargetSize.X * MathF.Abs(MathF.Cos(visualAngle)), device.TargetSize.X * MathF.Abs(MathF.Sin(visualAngle)) + device.TargetSize.Y * MathF.Abs(MathF.Cos(visualAngle))); Vector2 localVisualBounds = visualBounds / cameraScaleAtObj; Point2 targetVisibleTileCount = new Point2( 3 + (int)MathF.Ceiling(localVisualBounds.X / (MathF.Min(input.TileSize.X, input.TileSize.Y) * input.TilemapScale)), 3 + (int)MathF.Ceiling(localVisualBounds.Y / (MathF.Min(input.TileSize.X, input.TileSize.Y) * input.TilemapScale))); // Determine the tile indices (xy) that are visible within that rect output.VisibleTileStart = new Point2( MathF.Max(viewCenterTile.X - targetVisibleTileCount.X / 2, 0), MathF.Max(viewCenterTile.Y - targetVisibleTileCount.Y / 2, 0)); Point2 tileGridEndPos = new Point2( MathF.Min(viewCenterTile.X + targetVisibleTileCount.X / 2, input.TileCount.X), MathF.Min(viewCenterTile.Y + targetVisibleTileCount.Y / 2, input.TileCount.Y)); output.VisibleTileCount = new Point2( MathF.Clamp(tileGridEndPos.X - output.VisibleTileStart.X, 0, input.TileCount.X), MathF.Clamp(tileGridEndPos.Y - output.VisibleTileStart.Y, 0, input.TileCount.Y)); // Determine start position for rendering output.RenderOriginWorld = input.TilemapPos + new Vector3( output.VisibleTileStart.X * output.XAxisWorld * input.TileSize.X + output.VisibleTileStart.Y * output.YAxisWorld * input.TileSize.Y); return(output); }
protected internal override void OnCollectDrawcalls(Canvas canvas) { base.OnCollectDrawcalls(canvas); IDrawDevice device = canvas.DrawDevice; GridLayerData displayedData = default(GridLayerData); this.View.ActiveState.GetDisplayedGridData(Point.Empty, ref displayedData); float distanceToCamera = 0.0f - device.ViewerPos.Z; if (distanceToCamera <= device.NearZ) { return; } float alphaTemp = 0.5f; alphaTemp *= (float)Math.Min(1.0d, ((distanceToCamera - device.NearZ) / (device.NearZ * 5.0f))); if (alphaTemp <= 0.005f) { return; } ColorRgba gridColor = this.FgColor.WithAlpha(alphaTemp); float gridVisualMinSize = 50.0f; Vector2 gridBaseSize = displayedData.GridBaseSize; if (gridBaseSize.X <= 0.0f) { gridBaseSize.X = 100.0f; } if (gridBaseSize.Y <= 0.0f) { gridBaseSize.Y = 100.0f; } Vector2 adjustedGridBaseSize; adjustedGridBaseSize.X = gridBaseSize.X * MathF.NextPowerOfTwo((int)MathF.Ceiling(gridVisualMinSize / gridBaseSize.X)); adjustedGridBaseSize.Y = gridBaseSize.Y * MathF.NextPowerOfTwo((int)MathF.Ceiling(gridVisualMinSize / gridBaseSize.Y)); float scaleAtGrid = device.GetScaleAtZ(0.0f); float scaleAdjustmentFactor = 4.0f * MathF.Pow(2.0f, -MathF.Round(1.0f - MathF.Log(1.0f / scaleAtGrid, 2.0f))); Vector2 adjustedGridSize; adjustedGridSize.X = MathF.Max(adjustedGridBaseSize.X * scaleAdjustmentFactor, gridBaseSize.X); adjustedGridSize.Y = MathF.Max(adjustedGridBaseSize.Y * scaleAdjustmentFactor, gridBaseSize.Y); Vector2 stepSize = adjustedGridSize; float viewBoundRad = MathF.Distance(device.TargetSize.X, device.TargetSize.Y) * 0.5f / scaleAtGrid; int lineCountX = (2 + (int)MathF.Ceiling(viewBoundRad * 2 / stepSize.X)) * 4; int lineCountY = (2 + (int)MathF.Ceiling(viewBoundRad * 2 / stepSize.Y)) * 4; int vertexCount = (lineCountX * 2 + lineCountY * 2); if (this.vertexBuffer == null) { this.vertexBuffer = new RawList <VertexC1P3>(vertexCount); } this.vertexBuffer.Count = vertexCount; VertexC1P3[] vertices = this.vertexBuffer.Data; float beginPos; float pos; int lineIndex; int vertOff = 0; beginPos = stepSize.X * (int)(device.ViewerPos.X / stepSize.X - (lineCountX / 8)); pos = beginPos; lineIndex = 0; for (int x = 0; x < lineCountX; x++) { bool primaryLine = lineIndex % 4 == 0; bool secondaryLine = lineIndex % 4 == 2; vertices[vertOff + x * 2 + 0].Color = primaryLine ? gridColor : gridColor.WithAlpha(alphaTemp * (secondaryLine ? 0.5f : 0.25f)); vertices[vertOff + x * 2 + 0].Pos.X = pos; vertices[vertOff + x * 2 + 0].Pos.Y = device.ViewerPos.Y - viewBoundRad; vertices[vertOff + x * 2 + 0].Pos.Z = 0.0f; vertices[vertOff + x * 2 + 0].DepthOffset = 1.0f; vertices[vertOff + x * 2 + 1] = vertices[vertOff + x * 2 + 0]; vertices[vertOff + x * 2 + 1].Pos.Y = device.ViewerPos.Y + viewBoundRad; pos += stepSize.X / 4; lineIndex++; } vertOff += lineCountX * 2; beginPos = stepSize.Y * (int)(device.ViewerPos.Y / stepSize.Y - (lineCountY / 8)); pos = beginPos; lineIndex = 0; for (int y = 0; y < lineCountY; y++) { bool primaryLine = lineIndex % 4 == 0; bool secondaryLine = lineIndex % 4 == 2; vertices[vertOff + y * 2 + 0].Color = primaryLine ? gridColor : gridColor.WithAlpha(alphaTemp * (secondaryLine ? 0.5f : 0.25f)); vertices[vertOff + y * 2 + 0].Pos.X = device.ViewerPos.X - viewBoundRad; vertices[vertOff + y * 2 + 0].Pos.Y = pos; vertices[vertOff + y * 2 + 0].Pos.Z = 0.0f; vertices[vertOff + y * 2 + 0].DepthOffset = 1.0f; vertices[vertOff + y * 2 + 1] = vertices[vertOff + y * 2 + 0]; vertices[vertOff + y * 2 + 1].Pos.X = device.ViewerPos.X + viewBoundRad; pos += stepSize.Y / 4; lineIndex++; } vertOff += lineCountY * 2; BatchInfo material = device.RentMaterial(); material.Technique = DrawTechnique.Alpha; device.AddVertices(material, VertexMode.Lines, vertices, this.vertexBuffer.Count); }
void ICmpRenderer.Draw(IDrawDevice device) { if (_inEditor) { if (FXSource != null && FXTarget != null) { Canvas c = new Canvas(device); FXSource.DrawInEditor(c); FXTarget.DrawInEditor(c); Vector3 src = FXSource.GameObj.Transform.Pos; Vector3 tar = FXTarget.GameObj.Transform.Pos; c.PushState(); Vector3 line = tar - src; Vector2 normal = line.Xy.PerpendicularLeft; Vector3 p1 = line * 0.33f; Vector3 p2 = line * 0.33f; Vector3 p3 = line * 0.67f; Vector3 p4 = line * 0.67f; p1 += src + new Vector3(normal * .04f, p1.Z); p2 += src + new Vector3(normal * -.02f, p2.Z); p3 += src + new Vector3(normal * .02f, p3.Z); p4 += src + new Vector3(normal * -.04f, p4.Z); c.State.ColorTint = Colors.Pink; c.DrawLine(src.X, src.Y, src.Z, p1.X, p1.Y, p1.Z); c.DrawLine(p1.X, p1.Y, p1.Z, p2.X, p2.Y, p2.Z); c.DrawLine(p2.X, p2.Y, p2.Z, p3.X, p3.Y, p3.Z); c.DrawLine(p3.X, p3.Y, p3.Z, p4.X, p4.Y, p4.Z); c.DrawLine(p4.X, p4.Y, p4.Z, tar.X, tar.Y, tar.Z); c.PopState(); } } else { foreach (LightningBolt bolt in _bolts) { if (bolt.IsAlive) { if (!bolt.BatchInfos.ContainsKey(device) || !bolt.BatchInfos[device].IsReady) { bolt.PrepareTextureForDrawDevice(device); } LightningBolt.BoltData bd = bolt.BatchInfos[device]; float scaleAtStart = device.GetScaleAtZ(FXSource.GameObj.Transform.Pos.Z); float scaleAtEnd = device.GetScaleAtZ(FXTarget.GameObj.Transform.Pos.Z); Vector2 axis = (bd.End - bd.Start).Xy; Vector2 normal = axis.PerpendicularLeft.Normalized; VertexC1P3T2[] v = new VertexC1P3T2[4]; v[0] = new VertexC1P3T2(); v[0].Pos = bd.Start - new Vector3(normal * Sway * scaleAtStart, 0); v[0].TexCoord = new Vector2(0, 0); v[0].Color = bolt.CurrentColor; v[1] = new VertexC1P3T2(); v[1].Pos = bd.Start + new Vector3(normal * Sway * scaleAtStart, 0); v[1].TexCoord = new Vector2(0, 1); v[1].Color = bolt.CurrentColor; v[2] = new VertexC1P3T2(); v[2].Pos = bd.End + new Vector3(normal * Sway * scaleAtEnd, 0); v[2].TexCoord = new Vector2(1, 1); v[2].Color = bolt.CurrentColor; v[3] = new VertexC1P3T2(); v[3].Pos = bd.End - new Vector3(normal * Sway * scaleAtEnd, 0); v[3].TexCoord = new Vector2(1, 0); v[3].Color = bolt.CurrentColor; device.AddVertices(bd.BatchInfo, VertexMode.Quads, v); } } } }