Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic NavMeshApi for raycasting the world. #745

Merged
merged 29 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3983f31
Basic NavMeshApi for raycasting the world.
DummkopfOfHachtenduden Nov 5, 2023
bafec53
Boot NavMeshManager
Nov 5, 2023
40312b6
Load surrounding NavMeshes
Nov 5, 2023
6d1fc2e
Remove unused classes
Nov 5, 2023
2489a1a
Move to RSBot.NavMeshApi namespace
Nov 6, 2023
412ee58
Experimenting with the new NavMeshApi
Nov 6, 2023
0aa8b28
Add dedicated renderer class
Nov 7, 2023
7474fa1
Merge branch 'SDClowen:master' into add-to-core
ngoedde Nov 7, 2023
ca0e0af
Try reduce complexity of Position.cs
ngoedde Nov 7, 2023
a8c010c
Implement collision check
ngoedde Nov 8, 2023
7d63739
Remove unused method
ngoedde Nov 8, 2023
44b8ed2
Merge pull request #1 from ngoedde/add-to-core
DummkopfOfHachtenduden Nov 9, 2023
94066df
Temporary NavMeshVisualizer
DummkopfOfHachtenduden Nov 9, 2023
6b81685
Merged
DummkopfOfHachtenduden Nov 9, 2023
614c39e
fixes but not done
DummkopfOfHachtenduden Nov 9, 2023
1f03cac
WIP
ngoedde Nov 9, 2023
c51baf4
WIP map plugin
ngoedde Nov 9, 2023
83feeea
Merge branch 'add-to-core' of https://github.com/ngoedde/SDCLowenRSBot
DummkopfOfHachtenduden Nov 9, 2023
956379d
Fixed a number of issues with drawing and raycasting
DummkopfOfHachtenduden Nov 9, 2023
4d5e51e
Hit now properly displays hit info
DummkopfOfHachtenduden Nov 9, 2023
b16fda9
Integrate NavMeshRenderer into Map plugin; Cleanup unused Projects
ngoedde Nov 9, 2023
4fb8688
Merge pull request #2 from ngoedde/navmesh-viewer
DummkopfOfHachtenduden Nov 9, 2023
df20d95
Ray not properly interacts with ColObjects (Stones) inside dungeons.
DummkopfOfHachtenduden Nov 11, 2023
4f369de
Add Dungeon support
Nov 11, 2023
c79d3a4
Proper loading of dungeon minimaps
ngoedde Nov 12, 2023
28baba3
Remove debug code
Nov 12, 2023
9fff42a
Merge pull request #3 from ngoedde/add-dungeon-support
DummkopfOfHachtenduden Nov 12, 2023
040c245
Added support for handling raycasting against EventZones
DummkopfOfHachtenduden Nov 12, 2023
1a24065
Delete Application/RSBot.NavMeshVisualizer/NavMeshRenderer.cs
DummkopfOfHachtenduden Nov 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
375 changes: 375 additions & 0 deletions Application/RSBot.NavMeshVisualizer/NavMeshRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
using RSBot.FileSystem;
using RSBot.NavMeshApi;
using RSBot.NavMeshApi.Mathematics;
using RSBot.NavMeshApi.Object;
using RSBot.NavMeshApi.Terrain;

using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.Numerics;

namespace RSBot.NavMeshVisualizer;

public partial class NavMeshRenderer : UserControl
{
private bool _isDragging;
private Point _dragPosition;

private NavMeshTransform _transform;
private NavMeshTransform _mouseTransform;
private NavMeshRaycastHit? _hit = null;

private readonly Font _font;
private readonly Font _smallFont;

private float _zoom = 1.0f;

private bool _drawRegionId = true;
private bool _drawRegionBorder = true;
private bool _drawTerrainGlobalEdges = true;
private bool _drawTerrainInternalEdges = true;
private bool _drawObjectGlobalEdges = true;
private bool _drawObjectInternalEdges = true;
private bool _drawObjectGround = true;

private bool _drawTerrainCellID = false;
private bool _drawTerrainGlobalEdgeID = false;
private bool _drawTerrainInternalEdgeID = false;
private bool _drawObjectCellID = false;
private bool _drawObjectGlobalEdgeID = false;
private bool _drawObjectInternalEdgeID = false;

public NavMeshRenderer()
{
this.InitializeComponent();

if (this.DesignMode)
return;

var data = new PackFileSystem(Path.Combine("D:\\Games\\Silkroad_TestIn", "Data.pk2"), "169841");

DummkopfOfHachtenduden marked this conversation as resolved.
Show resolved Hide resolved
var item = data.GetFile("\\navmesh\\mapinfo.mfo");
Debug.WriteLine(item.Path);

NavMeshManager.Initialize(data);

//_transform = new NavMeshTransform(new NavMeshApi.Mathematics.Region(25000), new Vector3(960, 0, 960));
_transform = new NavMeshTransform(new NavMeshApi.Mathematics.RID(135, 101), new Vector3(960, 0, 960));
_mouseTransform = new NavMeshTransform(Vector3.Zero);

_font = new Font("Arial", 64f);
_smallFont = new Font("Arial", 16f);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);

var g = e.Graphics;

var matrix = new Matrix();

matrix.Scale(this.Width / 1920.0f, this.Height / 1920.0f);
matrix.Translate(960.0f - _transform.Offset.X, 960 - _transform.Offset.Z);
g.MultiplyTransform(matrix);

var set = new HashSet<int>();

for (int rz = _transform.Region.Z - 1; rz < _transform.Region.Z + 2; rz++)
{
for (int rx = _transform.Region.X - 1; rx < _transform.Region.X + 2; rx++)
{
var rid = new RID((byte)rx, (byte)rz);
if (!NavMeshManager.TryGetNavMeshTerrain(rid, out var terrain))
continue;

foreach (var edge in terrain.GlobalEdges)
edge.Link();

this.DrawTerrain(set, g, terrain);
}
}

var localMouseOffset = RID.Transform(_mouseTransform.Offset, _transform.Region, _mouseTransform.Region);

g.DrawLine(Pens.White, _transform.Offset.X, _transform.Offset.Z, localMouseOffset.X, localMouseOffset.Z);
if (_hit != null)
{
var localHitOffset = RID.Transform(_hit.Position, _transform.Region, _hit.Region);
g.DrawLine(Pens.Red, _transform.Offset.X, _transform.Offset.Z, localHitOffset.X, localHitOffset.Z);
}

matrix.Invert();
g.MultiplyTransform(matrix);

g.DrawString($"Player: {_transform}", DefaultFont, Brushes.Black, 0, 0);
g.DrawString($"Cursor: {_mouseTransform}", DefaultFont, Brushes.Black, 0, 12);
if (_hit != null)
g.DrawString($"Hit: {_hit}", DefaultFont, Brushes.Black, 0, 24);

}

private void DrawTerrain(HashSet<int> set, Graphics g, NavMeshTerrain terrain)
{
var dx = (terrain.Region.X - _transform.Region.X) * RID.Width;
var dz = (terrain.Region.Z - _transform.Region.Z) * RID.Length;

var matrix = new Matrix();
matrix.Translate(dx, dz);

g.MultiplyTransform(matrix);

if (_drawRegionBorder)
g.DrawRectangle(Pens.Magenta, 0, 0, 1920 - 1, 1920 - 1);

if (_drawTerrainCellID)
{
foreach (var cell in terrain.Cells)
g.DrawString($"{cell}", _smallFont, Brushes.Black, cell.RectangleF.Center.ToPointF());
}

if (_drawTerrainGlobalEdges)
{
foreach (var edge in terrain.GlobalEdges)
{
var pen = edge.Flag.ToPen();
g.DrawLine(pen, edge.Line);

if (_drawTerrainGlobalEdgeID)
g.DrawString($"{edge}", _smallFont, Brushes.Black, edge.Line.Center.ToPointF());
}
}

if (_drawTerrainInternalEdges)
{
foreach (var edge in terrain.InternalEdges)
{
var pen = edge.Flag.ToPen();
g.DrawLine(pen, edge.Line);

if (_drawTerrainInternalEdgeID)
g.DrawString($"{edge}", _smallFont, Brushes.Black, edge.Line.Center.ToPointF());
}
}

foreach (var obj in terrain.Instances)
{
if (set.Contains(obj.WorldUID))
continue;

var objMatrix = new Matrix();
objMatrix.RotateAt(obj.Yaw * (180.0f / MathF.PI), obj.LocalPosition.ToPointF());
objMatrix.Translate(obj.LocalPosition.X, obj.LocalPosition.Z);

g.MultiplyTransform(objMatrix);

this.DrawNavMeshObj(g, obj.WorldUID, obj.NavMeshObj);

objMatrix.Invert();
g.MultiplyTransform(objMatrix);

set.Add(obj.WorldUID);
}

if (_drawRegionId)
g.DrawString($"{terrain.Region}", _font, Brushes.Black, 0, 0);

matrix.Invert();
g.MultiplyTransform(matrix);
}

private void DrawNavMeshObj(Graphics g, int id, NavMeshObj obj)
{
if (_drawObjectGround)
{
var brush = new SolidBrush(id.ToColor());
foreach (var cell in obj.Cells)
{
g.FillTriangleF(brush, cell.Triangle);

if (_drawObjectCellID)
g.DrawString($"{cell}", _smallFont, Brushes.Black, cell.Triangle.Center.ToPointF());
}
}

if (_drawObjectGlobalEdges)
{
foreach (var edge in obj.GlobalEdges)
{
g.DrawLine(edge.Flag.ToPen(), edge.Line);

if (_drawObjectGlobalEdgeID)
g.DrawString($"{edge}", _smallFont, Brushes.Black, edge.Line.Center.ToPointF());
}

}

if (_drawObjectInternalEdges)
{
foreach (var edge in obj.InternalEdges)
{
g.DrawLine(edge.Flag.ToPen(), edge.Line);

if (_drawObjectInternalEdgeID)
g.DrawString($"{edge}", _smallFont, Brushes.Black, edge.Line.Center.ToPointF());
}
}
}

protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);

_zoom += e.Delta * 0.001f;
this.Invalidate();
}

protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);

if (_isDragging)
{
var dx = _dragPosition.X - e.X;
var dy = _dragPosition.Y - e.Y;
_dragPosition = e.Location;

_transform.Offset += new Vector3(dx * (RID.Width / this.Width), 0, dy * (RID.Length / this.Height));
_transform.Normalize();
_hit = null;
}

_mouseTransform.Region = _transform.Region;
_mouseTransform.Offset = new Vector3(_transform.Offset.X - 960.0f + (e.X * (RID.Width / this.Width)), 0.0f, _transform.Offset.Z - 960.0f + (e.Y * (RID.Length / this.Height)));
_mouseTransform.Normalize();

NavMeshManager.ResolveCellAndHeight(_transform);
NavMeshManager.ResolveCellAndHeight(_mouseTransform);

this.Invalidate();

}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);

if (e.Button == MouseButtons.Left)
{
try
{
this.Raycast();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}

if (e.Button == MouseButtons.Right)
contextMenuStrip1.Show(this, e.Location);

if (e.Button == MouseButtons.Middle)
{
_dragPosition = e.Location;
_isDragging = true;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);

if (e.Button == MouseButtons.Middle)
_isDragging = false;
}

private void Raycast()
{
_hit = null;
var source = new NavMeshTransform(_transform);
var destination = new NavMeshTransform(_mouseTransform);

if (!NavMeshManager.Raycast(source, destination, NavMeshRaycastType.Move, out NavMeshRaycastHit? hit) && hit != null)
{
_hit = hit;
return;
}
}

private void regionIDToolStripMenuItem_CheckedChange(object sender, EventArgs e)
{
_drawRegionId = regionIDToolStripMenuItem.Checked;
this.Invalidate();
}

private void regionBorderToolStripMenuItem_CheckedChange(object sender, EventArgs e)
{
_drawRegionBorder = regionBorderToolStripMenuItem.Checked;
this.Invalidate();
}

private void globalEdgesToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
_drawTerrainGlobalEdges = terrainGlobalEdgesToolStripMenuItem.Checked;
this.Invalidate();
}

private void internalEdgesToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
_drawTerrainInternalEdges = terrainInternalEdgesToolStripMenuItem.Checked;
this.Invalidate();
}

private void globalEdgesToolStripMenuItem1_CheckedChanged(object sender, EventArgs e)
{
_drawObjectGlobalEdges = objectGlobalEdgesToolStripMenuItem1.Checked;
this.Invalidate();
}

private void internalEdgesToolStripMenuItem1_CheckedChanged(object sender, EventArgs e)
{
_drawObjectInternalEdges = objectInternalEdgesToolStripMenuItem1.Checked;
this.Invalidate();
}

private void groundToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
_drawObjectGround = objectGroundToolStripMenuItem.Checked;
this.Invalidate();
}

private void terrainCellIDToolStripMenuItem_Click(object sender, EventArgs e)
{
_drawTerrainCellID = terrainCellIDToolStripMenuItem.Checked;
this.Invalidate();
}

private void terrainGlobalEdgeIDToolStripMenuItem_Click(object sender, EventArgs e)
{
_drawTerrainGlobalEdgeID = terrainGlobalEdgeIDToolStripMenuItem.Checked;
this.Invalidate();
}

private void terrainInternalEdgeIDToolStripMenuItem_Click(object sender, EventArgs e)
{
_drawTerrainInternalEdgeID = terrainInternalEdgeIDToolStripMenuItem.Checked;
this.Invalidate();
}

private void objectCellIDToolStripMenuItem_Click(object sender, EventArgs e)
{
_drawObjectCellID = objectCellIDToolStripMenuItem.Checked;
this.Invalidate();
}

private void objectGlobalEdgeIDToolStripMenuItem_Click(object sender, EventArgs e)
{
_drawObjectGlobalEdgeID = objectGlobalEdgeIDToolStripMenuItem.Checked;
this.Invalidate();
}

private void objectInternalEdgeIDToolStripMenuItem_Click(object sender, EventArgs e)
{
_drawObjectInternalEdgeID = objectInternalEdgeIDToolStripMenuItem.Checked;
this.Invalidate();
}
}
Loading