Radar plugin Image export and render mismatch menu

Shout-Out

User Tag List

Results 1 to 4 of 4
  1. #1
    Raiwulf's Avatar Member
    Reputation
    10
    Join Date
    Nov 2016
    Posts
    50
    Thanks G/R
    8/7
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    Radar plugin Image export and render mismatch

    Hello,

    I simply added

    Code:
    image.SaveAsPng("Exports/Image.png");
    after last line at Radar.MemoryInteraction.cs. However, the image and the render mismatch. Any tips or ideas are appreciated.

    Render and export: https://imgur.com/a/EzzjVfV

    Radar.cs:
    Code:
    using ExileCore;
    using ExileCore.PoEMemory.Elements;
    using ExileCore.PoEMemory.MemoryObjects;
    using ExileCore.Shared;
    using ExileCore.Shared.Helpers;
    using GameOffsets;
    using GameOffsets.Native;
    using ImGuiNET;
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Numerics;
    using System.Text.RegularExpressions;
    using System.Threading;
    using Color = SharpDX.Color;
    using Positioned = ExileCore.PoEMemory.Components.Positioned;
    using RectangleF = SixLabors.ImageSharp.RectangleF;
    
    namespace Radar;
    
    public partial class Radar : BaseSettingsPlugin<RadarSettings>
    {
        private const string TextureName = "radar_minimap";
        private const int TileToGridConversion = 23;
        private const int TileToWorldConversion = 250;
        public const float GridToWorldMultiplier = TileToWorldConversion / (float)TileToGridConversion;
        private const double CameraAngle = 38.7 * Math.PI / 180;
        private static readonly float CameraAngleCos = (float)Math.Cos(CameraAngle);
        private static readonly float CameraAngleSin = (float)Math.Sin(CameraAngle);
        private double _mapScale;
    
        private ConcurrentDictionary<string, List<TargetDescription>> _targetDescriptions = new();
        private Vector2i? _areaDimensions;
        private TerrainData _terrainMetadata;
        private float[][] _heightData;
        private int[][] _processedTerrainData;
        private Dictionary<string, TargetDescription> _targetDescriptionsInArea = new();
        private List<(Regex, TargetDescription x)> _currentZoneTargetEntityPaths = new();
        private CancellationTokenSource _findPathsCts = new CancellationTokenSource();
        private ConcurrentDictionary<string, TargetLocations> _clusteredTargetLocations = new();
        private ConcurrentDictionary<string, List<Vector2i>> _allTargetLocations = new();
        private ConcurrentDictionary<Vector2i, List<string>> _locationsByPosition = new();
        private SharpDX.RectangleF _rect;
        private ImDrawListPtr _backGroundWindowPtr;
        private ConcurrentDictionary<Vector2, RouteDescription> _routes = new();
        private Vector2 p1, p2, p3, p4;
    
        public override bool Initialise()
        {
            GameController.PluginBridge.SaveMethod("Radar.LookForRoute",
                (Vector2 target, Action<List<Vector2i>> callback, CancellationToken cancellationToken) =>
                    AddRoute(target, null, callback, cancellationToken));
            GameController.PluginBridge.SaveMethod("Radar.ClusterTarget",
                (string targetName, int expectedCount) => ClusterTarget(targetName, expectedCount));
    
            return true;
        }
    
        public override void AreaChange(AreaInstance area)
        {
            StopPathFinding();
            if (GameController.Game.IsInGameState || GameController.Game.IsEscapeState)
            {
                _targetDescriptionsInArea = GetTargetDescriptionsInArea().ToDictionary(x => x.Name);
                _currentZoneTargetEntityPaths = _targetDescriptionsInArea.Values.Where(x => x.TargetType == TargetType.Entity).DistinctBy(x => x.Name).Select(x => (x.Name.ToLikeRegex(), x)).ToList();
                _terrainMetadata = GameController.IngameState.Data.DataStruct.Terrain;
                _heightData = GameController.IngameState.Data.RawTerrainHeightData;
                _allTargetLocations = GetTargets();
                _locationsByPosition = new ConcurrentDictionary<Vector2i, List<string>>(_allTargetLocations
                    .SelectMany(x => x.Value.Select(y => (x.Key, y)))
                    .ToLookup(x => x.y, x => x.Key)
                    .ToDictionary(x => x.Key, x => x.ToList()));
                _areaDimensions = GameController.IngameState.Data.AreaDimensions;
                _processedTerrainData = GameController.IngameState.Data.RawPathfindingData;
                GenerateMapTexture();
                _clusteredTargetLocations = ClusterTargets();
                StartPathFinding();
            }
        }
    
        public override void DrawSettings()
        {
            Settings.PathfindingSettings.CurrentZoneName.Value = GameController.Area.CurrentArea.Area.RawName;
            base.DrawSettings();
        }
    
        private static readonly List<Color> RainbowColors = new List<Color>
        {
            Color.Red,
            Color.Green,
            Color.Blue,
            Color.Yellow,
            Color.Violet,
            Color.Orange,
            Color.White,
            Color.LightBlue,
            Color.Indigo,
        };
    
        public override void OnLoad()
        {
            LoadTargets();
            Settings.Reload.OnPressed = () =>
            {
                Core.MainRunner.Run(new Coroutine(() =>
                {
                    LoadTargets();
                    AreaChange(GameController.Area.CurrentArea);
                }, new WaitTime(0), this, "RestartPathfinding", false, true));
            };
            Settings.MaximumPathCount.OnValueChanged += (_, _) => { Core.MainRunner.Run(new Coroutine(RestartPathFinding, new WaitTime(0), this, "RestartPathfinding", false, true)); };
            Settings.TerrainColor.OnValueChanged += (_, _) => { GenerateMapTexture(); };
            Settings.Debug.DrawHeightMap.OnValueChanged += (_, _) => { GenerateMapTexture(); };
            Settings.Debug.SkipEdgeDetector.OnValueChanged += (_, _) => { GenerateMapTexture(); };
            Settings.Debug.SkipNeighborFill.OnValueChanged += (_, _) => { GenerateMapTexture(); };
            Settings.Debug.SkipRecoloring.OnValueChanged += (_, _) => { GenerateMapTexture(); };
            Settings.Debug.DisableHeightAdjust.OnValueChanged += (_, _) => { GenerateMapTexture(); };
            Settings.MaximumMapTextureDimension.OnValueChanged += (_, _) => { GenerateMapTexture(); };
        }
    
        public override void EntityAdded(Entity entity)
        {
            var positioned = entity.GetComponent<Positioned>();
            if (positioned != null)
            {
                var path = entity.Path;
                if (_currentZoneTargetEntityPaths.FirstOrDefault(x => x.Item1.IsMatch(path)).x is { } targetDescription)
                {
                    bool alreadyContains = false;
                    var truncatedPos = positioned.GridPosNum.Truncate();
                    _allTargetLocations.AddOrUpdate(targetDescription.Name, _ => [truncatedPos],
                        // ReSharper disable once AssignmentInConditionalExpression
                        (_, l) => (alreadyContains = l.Contains(truncatedPos)) ? l : [.. l, truncatedPos]);
                    _locationsByPosition.AddOrUpdate(truncatedPos, _ => [targetDescription.Name],
                        (_, l) => l.Contains(targetDescription.Name) ? l : [.. l, targetDescription.Name]);
                    if (!alreadyContains)
                    {
                        var oldValue = _clusteredTargetLocations.GetValueOrDefault(targetDescription.Name);
                        var newValue = _clusteredTargetLocations.AddOrUpdate(targetDescription.Name,
                            _ => ClusterTarget(_targetDescriptionsInArea[targetDescription.Name]),
                            (_, _) => ClusterTarget(_targetDescriptionsInArea[targetDescription.Name]));
                        foreach (var newLocation in newValue.Locations.Except(oldValue?.Locations ?? []))
                        {
                            AddRoute(newLocation, targetDescription, entity);
                        }
                    }
                }
            }
        }
    
        private Vector2 GetPlayerPosition()
        {
            var player = GameController.Game.IngameState.Data.LocalPlayer;
            var playerPositionComponent = player.GetComponent<Positioned>();
            if (playerPositionComponent == null)
                return new Vector2(0, 0);
            var playerPosition = new Vector2(playerPositionComponent.GridX, playerPositionComponent.GridY);
            return playerPosition;
        }
    
        public override void Render()
        {
            var ingameUi = GameController.Game.IngameState.IngameUi;
            if (!Settings.Debug.IgnoreFullscreenPanels &&
                ingameUi.FullscreenPanels.Any(x => x.IsVisible))
            {
                return;
            }
    
            if (!Settings.Debug.IgnoreLargePanels &&
                ingameUi.LargePanels.Any(x => x.IsVisible))
            {
                return;
            }
    
            _rect = GameController.Window.GetWindowRectangle() with { Location = Vector2.Zero.ToSharpDx() };
            if (!Settings.Debug.DisableDrawRegionLimiting)
            {
                if (ingameUi.OpenRightPanel.IsVisible)
                {
                    _rect.Right = ingameUi.OpenRightPanel.GetClientRectCache.Left;
                }
    
                if (ingameUi.OpenLeftPanel.IsVisible)
                {
                    _rect.Left = ingameUi.OpenLeftPanel.GetClientRectCache.Right;
                }
            }
    
            ImGui.SetNextWindowSize(new Vector2(_rect.Width, _rect.Height));
            ImGui.SetNextWindowPos(new Vector2(_rect.Left, _rect.Top));
    
            ImGui.Begin("radar_background",
                ImGuiWindowFlags.NoDecoration |
                ImGuiWindowFlags.NoInputs |
                ImGuiWindowFlags.NoMove |
                ImGuiWindowFlags.NoScrollWithMouse |
                ImGuiWindowFlags.NoSavedSettings |
                ImGuiWindowFlags.NoFocusOnAppearing |
                ImGuiWindowFlags.NoBringToFrontOnFocus |
                ImGuiWindowFlags.NoBackground);
    
            _backGroundWindowPtr = ImGui.GetWindowDrawList();
            var map = ingameUi.Map;
            var largeMap = map.LargeMap.AsObject<SubMap>();
            if (largeMap.IsVisible)
            {
                var mapCenter = largeMap.MapCenter + new Vector2(Settings.Debug.MapCenterOffsetX, Settings.Debug.MapCenterOffsetY);
                _mapScale = largeMap.MapScale * Settings.CustomScale;
                DrawLargeMap(mapCenter);
                DrawTargets(mapCenter);
            }
    
            DrawWorldPaths(largeMap);
            ImGui.End();
        }
    
        private void DrawWorldPaths(SubMap largeMap)
        {
            if (Settings.PathfindingSettings.WorldPathSettings.ShowPathsToTargets &&
                (!largeMap.IsVisible || !Settings.PathfindingSettings.WorldPathSettings.ShowPathsToTargetsOnlyWithClosedMap))
            {
                var player = GameController.Game.IngameState.Data.LocalPlayer;
                var playerRender = player?.GetComponent<ExileCore.PoEMemory.Components.Render>();
                if (playerRender == null)
                    return;
                var initPos = GameController.IngameState.Camera.WorldToScreen(playerRender.PosNum with { Z = playerRender.RenderStruct.Height });
                foreach (var (route, offsetAmount) in _routes.Values
                             .GroupBy(x => x.Path.Count < 2 ? 0 : (x.Path[1] - x.Path[0]) switch { var diff => Math.Atan2(diff.Y, diff.X) })
                             .SelectMany(group => group.Select((route, i) => (route, i - group.Count() / 2.0f + 0.5f))))
                {
                    var p0 = initPos;
                    var p0WithOffset = p0;
                    var i = 0;
                    foreach (var elem in route.Path)
                    {
                        var p1 = GameController.IngameState.Camera.WorldToScreen(
                            new Vector3(elem.X * GridToWorldMultiplier, elem.Y * GridToWorldMultiplier, _heightData[elem.Y][elem.X]));
                        var offsetDirection = Settings.PathfindingSettings.WorldPathSettings.OffsetPaths
                            ? (p1 - p0) switch { var s => new Vector2(s.Y, -s.X) / s.Length() }
                            : Vector2.Zero;
                        var finalOffset = offsetDirection * offsetAmount * Settings.PathfindingSettings.WorldPathSettings.PathThickness;
                        p0 = p1;
                        p1 += finalOffset;
                        if (++i % Settings.PathfindingSettings.WorldPathSettings.DrawEveryNthSegment == 0)
                        {
                            if (_rect.Contains(p0WithOffset) || _rect.Contains(p1))
                            {
                                Graphics.DrawLine(p0WithOffset, p1, Settings.PathfindingSettings.WorldPathSettings.PathThickness, route.WorldColor());
                            }
                            else
                            {
                                break;
                            }
                        }
    
                        p0WithOffset = p1;
                    }
                }
            }
        }
    
        private void DrawBox(Vector2 p0, Vector2 p1, Color color)
        {
            _backGroundWindowPtr.AddRectFilled(p0, p1, color.ToImgui());
        }
    
        private void DrawText(string text, Vector2 pos, Color color)
        {
            _backGroundWindowPtr.AddText(pos, color.ToImgui(), text);
        }
    
        private Vector2 TranslateGridDeltaToMapDelta(Vector2 delta, float deltaZ)
        {
            deltaZ /= GridToWorldMultiplier; //z is normally "world" units, translate to grid
            return (float)_mapScale * new Vector2((delta.X - delta.Y) * CameraAngleCos, (deltaZ - (delta.X + delta.Y)) * CameraAngleSin);
        }
    
        private void DrawLargeMap(Vector2 mapCenter)
        {
            if (!Settings.DrawWalkableMap || !Graphics.LowLevel.HasTexture(TextureName) || _areaDimensions == null)
                return;
            var player = GameController.Game.IngameState.Data.LocalPlayer;
            var playerRender = player.GetComponent<ExileCore.PoEMemory.Components.Render>();
            if (playerRender == null)
                return;
            var rectangleF = new RectangleF(-playerRender.GridPos().X, -playerRender.GridPos().Y, _areaDimensions.Value.X, _areaDimensions.Value.Y);
            var playerHeight = -playerRender.RenderStruct.Height;
            p1 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Left, rectangleF.Top), playerHeight);
            p2 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Right, rectangleF.Top), playerHeight);
            p3 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Right, rectangleF.Bottom), playerHeight);
            p4 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Left, rectangleF.Bottom), playerHeight);
            _backGroundWindowPtr.AddImageQuad(Graphics.LowLevel.GetTexture(TextureName), p1, p2, p3, p4);
        }
    
        private void DrawTargets(Vector2 mapCenter)
        {
            var color = Settings.PathfindingSettings.TargetNameColor.Value;
            var player = GameController.Game.IngameState.Data.LocalPlayer;
            var playerRender = player.GetComponent<ExileCore.PoEMemory.Components.Render>();
            if (playerRender == null)
                return;
            var playerPosition = new Vector2(playerRender.GridPos().X, playerRender.GridPos().Y);
            var playerHeight = -playerRender.RenderStruct.Height;
            var ithElement = 0;
            if (Settings.PathfindingSettings.ShowPathsToTargetsOnMap)
            {
                foreach (var route in _routes.Values)
                {
                    ithElement++;
                    ithElement %= 5;
                    foreach (var elem in route.Path.Skip(ithElement).GetEveryNth(5))
                    {
                        var mapDelta = TranslateGridDeltaToMapDelta(new Vector2(elem.X, elem.Y) - playerPosition, playerHeight + _heightData[elem.Y][elem.X]);
                        DrawBox(mapCenter + mapDelta - new Vector2(2, 2), mapCenter + mapDelta + new Vector2(2, 2), route.MapColor());
                    }
                }
            }
    
            if (Settings.PathfindingSettings.ShowAllTargets)
            {
                foreach (var (location, texts) in _locationsByPosition)
                {
                    var regex = string.IsNullOrEmpty(Settings.PathfindingSettings.TargetNameFilter)
                        ? null
                        : new Regex(Settings.PathfindingSettings.TargetNameFilter);
    
                    bool TargetFilter(string t) =>
                        (regex?.IsMatch(t) ?? true) &&
                        _allTargetLocations.GetValueOrDefault(t) is { } list && list.Count <= Settings.PathfindingSettings.MaxTargetNameCount;
    
                    var text = string.Join("\n", texts.Distinct().Where(TargetFilter));
                    var textOffset = Graphics.MeasureText(text) / 2f;
                    var mapDelta = TranslateGridDeltaToMapDelta(location.ToVector2Num() - playerPosition, playerHeight + _heightData[location.Y][location.X]);
                    var mapPos = mapCenter + mapDelta;
                    if (Settings.PathfindingSettings.EnableTargetNameBackground)
                        DrawBox(mapPos - textOffset, mapPos + textOffset, Color.Black);
                    DrawText(text, mapPos - textOffset, color);
                }
            }
            else if (Settings.PathfindingSettings.ShowSelectedTargets)
            {
                foreach (var (_, description) in _clusteredTargetLocations)
                {
                    foreach (var clusterPosition in description.Locations)
                    {
                        float clusterHeight = 0;
                        if (clusterPosition.X < _heightData[0].Length && clusterPosition.Y < _heightData.Length)
                            clusterHeight = _heightData[(int)clusterPosition.Y][(int)clusterPosition.X];
                        var text = description.DisplayName;
                        var textOffset = Graphics.MeasureText(text) / 2f;
                        var mapDelta = TranslateGridDeltaToMapDelta(clusterPosition - playerPosition, playerHeight + clusterHeight);
                        var mapPos = mapCenter + mapDelta;
                        if (Settings.PathfindingSettings.EnableTargetNameBackground)
                            DrawBox(mapPos - textOffset, mapPos + textOffset, Color.Black);
                        DrawText(text, mapPos - textOffset, color);
                    }
                }
            }
        }
    }
    Radar.MemoryInteraction.cs:
    Code:
    using System;
    using System.Linq;
    using System.Threading.Tasks;
    using ExileCore.Shared.Helpers;
    using SixLabors.ImageSharp;
    using SixLabors.ImageSharp.PixelFormats;
    using SixLabors.ImageSharp.Processing;
    using SixLabors.ImageSharp.Processing.Processors.Convolution;
    using SixLabors.ImageSharp.Processing.Processors.Transforms;
    using Configuration = SixLabors.ImageSharp.Configuration;
    using Vector4 = System.Numerics.Vector4;
    
    namespace Radar;
    
    public partial class Radar
    {
        private void GenerateMapTexture()
        {
            var gridHeightData = _heightData;
            var maxX = _areaDimensions.Value.X;
            var maxY = _areaDimensions.Value.Y;
            var configuration = Configuration.Default.Clone();
            configuration.PreferContiguousImageBuffers = true;
            using var image = new Image<Rgba32>(configuration, maxX, maxY);
            if (Settings.Debug.DrawHeightMap)
            {
                var minHeight = gridHeightData.Min(x => x.Min());
                var maxHeight = gridHeightData.Max(x => x.Max());
                image.Mutate(configuration, c => c.ProcessPixelRowsAsVector4((row, i) =>
                {
                    for (var x = 0; x < row.Length - 1; x += 2)
                    {
                        var cellData = gridHeightData[i.Y][x];
                        for (var x_s = 0; x_s < 2; ++x_s)
                        {
                            row[x + x_s] = new Vector4(0, (cellData - minHeight) / (maxHeight - minHeight), 0, 1);
                        }
                    }
                }));
            }
            else
            {
                var unwalkableMask = Vector4.UnitX + Vector4.UnitW;
                var walkableMask = Vector4.UnitY + Vector4.UnitW;
                if (Settings.Debug.DisableHeightAdjust)
                {
                    Parallel.For(0, maxY, y =>
                    {
                        for (var x = 0; x < maxX; x++)
                        {
                            var terrainType = _processedTerrainData[y][x];
                            image[x, y] = new Rgba32(terrainType is 0 ? unwalkableMask : walkableMask);
                        }
                    });
                }
                else
                {
                    Parallel.For(0, maxY, y =>
                    {
                        for (var x = 0; x < maxX; x++)
                        {
                            var cellData = gridHeightData[y][x / 2 * 2];
    
                            //basically, offset x and y by half the offset z would cause when rendering in 3d
                            var heightOffset = (int)(cellData / GridToWorldMultiplier / 2);
                            var offsetX = x - heightOffset;
                            var offsetY = y - heightOffset;
                            var terrainType = _processedTerrainData[y][x];
                            if (offsetX >= 0 && offsetX < maxX && offsetY >= 0 && offsetY < maxY)
                            {
                                image[offsetX, offsetY] = new Rgba32(terrainType is 0 ? unwalkableMask : walkableMask);
                            }
                        }
                    });
                }
    
                if (!Settings.Debug.SkipNeighborFill)
                {
                    Parallel.For(0, maxY, y =>
                    {
                        for (var x = 0; x < maxX; x++)
                        {
                            //this fills in the blanks that are left over from the height projection
                            if (image[x, y].ToVector4() == Vector4.Zero)
                            {
                                var countWalkable = 0;
                                var countUnwalkable = 0;
                                for (var xO = -1; xO < 2; xO++)
                                {
                                    for (var yO = -1; yO < 2; yO++)
                                    {
                                        var xx = x + xO;
                                        var yy = y + yO;
                                        if (xx >= 0 && xx < maxX && yy >= 0 && yy < maxY)
                                        {
                                            var nPixel = image[x + xO, y + yO].ToVector4();
                                            if (nPixel == walkableMask)
                                                countWalkable++;
                                            else if (nPixel == unwalkableMask)
                                                countUnwalkable++;
                                        }
                                    }
                                }
    
                                image[x, y] = new Rgba32(countWalkable > countUnwalkable ? walkableMask : unwalkableMask);
                            }
                        }
                    });
                }
    
                if (!Settings.Debug.SkipEdgeDetector)
                {
                    var edgeDetector = new EdgeDetectorProcessor(EdgeDetectorKernel.Laplacian5x5, false)
                       .CreatePixelSpecificProcessor(configuration, image, image.Bounds());
                    edgeDetector.Execute();
                }
    
                if (!Settings.Debug.SkipRecoloring)
                {
                    image.Mutate(configuration, c => c.ProcessPixelRowsAsVector4((row, p) =>
                    {
                        for (var x = 0; x < row.Length - 0; x++)
                        {
                            row[x] = row[x] switch
                            {
                                { X: 1 } => Settings.TerrainColor.Value.ToImguiVec4(),
                                { X: 0 } => Vector4.Zero,
                                var s => s
                            };
                        }
                    }));
                }
            }
    
            if (Math.Max(image.Height, image.Width) > Settings.MaximumMapTextureDimension)
            {
                var (newWidth, newHeight) = (image.Width, image.Height);
                if (image.Height > image.Width)
                {
                    newWidth = newWidth * Settings.MaximumMapTextureDimension / newHeight;
                    newHeight = Settings.MaximumMapTextureDimension;
                }
                else
                {
                    newHeight = newHeight * Settings.MaximumMapTextureDimension / newWidth;
                    newWidth = Settings.MaximumMapTextureDimension;
                }
    
                var targetSize = new Size(newWidth, newHeight);
                var resizer = new ResizeProcessor(new ResizeOptions { Size = targetSize }, image.Size())
                    .CreatePixelSpecificCloningProcessor(configuration, image, image.Bounds());
                resizer.Execute();
            }
    
            //unfortunately the library doesn't respect our allocation settings above
            
            using var imageCopy = image.Clone(configuration);
            Graphics.LowLevel.AddOrUpdateTexture(TextureName, imageCopy);
        }
    }

    Radar plugin Image export and render mismatch
  2. #2
    Sychotix's Avatar Moderator Authenticator enabled
    Reputation
    1425
    Join Date
    Apr 2006
    Posts
    3,951
    Thanks G/R
    285/575
    Trade Feedback
    1 (100%)
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Like when you PMed me, I still think looking at Radar/Radar.cs at 8d8ee97b34f7dd62dce8d5350ec1d6f9883181b7 . exApiTools/Radar . GitHub and the previous section to see how rotations are done is the right approach if you're attempting to save the map in a separate file

  3. #3
    Raiwulf's Avatar Member
    Reputation
    10
    Join Date
    Nov 2016
    Posts
    50
    Thanks G/R
    8/7
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Sychotix View Post
    Like when you PMed me, I still think looking at Radar/Radar.cs at 8d8ee97b34f7dd62dce8d5350ec1d6f9883181b7 . exApiTools/Radar . GitHub and the previous section to see how rotations are done is the right approach if you're attempting to save the map in a separate file
    I couldn't figure it out yet. I need more advices

    Correct me if I'm wrong:

    • I think AddOrUpdateTexture replaces the old texture while keeping it's properties.
    • I also think rotation, dimensions and positions are set here:


    Code:
    p1 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Left, rectangleF.Top), playerHeight);
            p2 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Right, rectangleF.Top), playerHeight);
            p3 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Right, rectangleF.Bottom), playerHeight);
            p4 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Left, rectangleF.Bottom), playerHeight);
            _backGroundWindowPtr.AddImageQuad(Graphics.LowLevel.GetTexture(TextureName), p1, p2, p3, p4);

  4. #4
    cout00's Avatar Member
    Reputation
    13
    Join Date
    Sep 2022
    Posts
    39
    Thanks G/R
    13/11
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Raiwulf View Post
    I couldn't figure it out yet. I need more advices

    Correct me if I'm wrong:

    • I think AddOrUpdateTexture replaces the old texture while keeping it's properties.
    • I also think rotation, dimensions and positions are set here:


    Code:
    p1 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Left, rectangleF.Top), playerHeight);
            p2 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Right, rectangleF.Top), playerHeight);
            p3 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Right, rectangleF.Bottom), playerHeight);
            p4 = mapCenter + TranslateGridDeltaToMapDelta(new Vector2(rectangleF.Left, rectangleF.Bottom), playerHeight);
            _backGroundWindowPtr.AddImageQuad(Graphics.LowLevel.GetTexture(TextureName), p1, p2, p3, p4);
    AddImageQuad its just a transformation into original texture.
    QuadrilateralTransformation its perspective transform. you can get any lib which can do this, like AForge. if you lazy you can just copy a code from them, to how matrix is generated and just do Mutate into them
    backsub/aforge/Sources/Imaging/Filters/Transform/QuadrilateralTransformation.cs at master . lachesis/backsub . GitHub
    or you can rotate with dual numbers (geometry - Using dual complex numbers for combined rotation and translation - Mathematics Stack Exchange)

  5. Thanks Raiwulf (1 members gave Thanks to cout00 for this useful post)

Similar Threads

  1. Question regarding DLL-export and problems with the stack
    By schlumpf in forum WoW Memory Editing
    Replies: 8
    Last Post: 03-12-2009, 06:28 PM
  2. Replies: 0
    Last Post: 08-21-2008, 09:10 PM
  3. [Rate] Sig and Render
    By Phoenix WoW in forum Art & Graphic Design
    Replies: 7
    Last Post: 07-08-2008, 05:57 AM
  4. [Showoff] Simple Batman Signature, and render!
    By PrimoPie in forum Art & Graphic Design
    Replies: 0
    Last Post: 06-01-2008, 01:47 AM
  5. Brushes and Renders
    By Xcynic in forum Art & Graphic Design
    Replies: 10
    Last Post: 10-02-2007, 12:47 PM
All times are GMT -5. The time now is 09:13 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search