2023-03-14 08:02:43 +03:00
|
|
|
/*
|
|
|
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
|
|
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
2023-03-15 17:00:29 +03:00
|
|
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
using System;
|
2023-03-18 18:09:36 +03:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Immutable;
|
2023-08-14 16:47:57 +03:00
|
|
|
using System.Globalization;
|
2023-03-14 08:02:43 +03:00
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2023-03-14 19:34:31 +03:00
|
|
|
using System.Numerics;
|
2023-03-14 08:02:43 +03:00
|
|
|
using Serilog;
|
|
|
|
using Silk.NET.Input;
|
|
|
|
using Silk.NET.Maths;
|
|
|
|
using Silk.NET.OpenGL;
|
|
|
|
using Silk.NET.OpenGL.Extensions.ImGui;
|
|
|
|
using Silk.NET.Windowing;
|
2023-03-14 19:34:31 +03:00
|
|
|
using ImGuiNET;
|
2023-03-14 08:02:43 +03:00
|
|
|
using DotRecast.Core;
|
|
|
|
using DotRecast.Detour;
|
|
|
|
using DotRecast.Detour.Extras.Unity.Astar;
|
|
|
|
using DotRecast.Detour.Io;
|
2023-08-04 17:08:29 +03:00
|
|
|
using DotRecast.Recast.Toolset.Builder;
|
2023-03-14 08:02:43 +03:00
|
|
|
using DotRecast.Recast.Demo.Draw;
|
2023-07-02 09:35:46 +03:00
|
|
|
using DotRecast.Recast.Demo.Messages;
|
2023-08-04 17:08:29 +03:00
|
|
|
using DotRecast.Recast.Toolset.Geom;
|
2023-03-14 08:02:43 +03:00
|
|
|
using DotRecast.Recast.Demo.Tools;
|
|
|
|
using DotRecast.Recast.Demo.UI;
|
2023-08-04 17:08:29 +03:00
|
|
|
using DotRecast.Recast.Toolset;
|
2023-06-28 16:41:12 +03:00
|
|
|
using MouseButton = Silk.NET.Input.MouseButton;
|
2023-03-14 08:02:43 +03:00
|
|
|
using Window = Silk.NET.Windowing.Window;
|
|
|
|
|
|
|
|
namespace DotRecast.Recast.Demo;
|
|
|
|
|
2023-07-02 09:35:46 +03:00
|
|
|
public class RecastDemo : IRecastDemoChannel
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-18 22:36:31 +03:00
|
|
|
private static readonly ILogger Logger = Log.ForContext<RecastDemo>();
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
private IWindow window;
|
2023-04-17 18:12:28 +03:00
|
|
|
private GL _gl;
|
2023-03-14 08:02:43 +03:00
|
|
|
private IInputContext _input;
|
|
|
|
private ImGuiController _imgui;
|
2023-06-11 08:58:37 +03:00
|
|
|
private RcCanvas _canvas;
|
2023-05-25 17:12:23 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
private int width = 1000;
|
|
|
|
private int height = 900;
|
2023-03-14 19:34:31 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
private readonly string title = "DotRecast Demo";
|
2023-03-14 19:34:31 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
//private readonly RecastDebugDraw dd;
|
2023-03-18 22:36:31 +03:00
|
|
|
private NavMeshRenderer renderer;
|
2023-03-14 08:02:43 +03:00
|
|
|
private float timeAcc = 0;
|
|
|
|
private float camr = 1000;
|
|
|
|
|
|
|
|
private readonly SoloNavMeshBuilder soloNavMeshBuilder = new SoloNavMeshBuilder();
|
|
|
|
private readonly TileNavMeshBuilder tileNavMeshBuilder = new TileNavMeshBuilder();
|
|
|
|
|
2023-07-02 18:16:53 +03:00
|
|
|
private string _lastGeomFileName;
|
2023-08-20 06:40:05 +03:00
|
|
|
private DemoSample _sample;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
private bool processHitTest = false;
|
|
|
|
private bool processHitTestShift;
|
2023-06-13 18:00:45 +03:00
|
|
|
private int _modState;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
private readonly float[] mousePos = new float[2];
|
|
|
|
|
2023-03-22 18:29:25 +03:00
|
|
|
private bool _mouseOverMenu;
|
2023-03-14 08:02:43 +03:00
|
|
|
private bool pan;
|
|
|
|
private bool movedDuringPan;
|
|
|
|
private bool rotate;
|
|
|
|
private bool movedDuringRotate;
|
|
|
|
private float scrollZoom;
|
|
|
|
private readonly float[] origMousePos = new float[2];
|
|
|
|
private readonly float[] origCameraEulers = new float[2];
|
2023-06-03 15:47:26 +03:00
|
|
|
private RcVec3f origCameraPos = new RcVec3f();
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
private readonly float[] cameraEulers = { 45, -45 };
|
2023-06-03 15:47:26 +03:00
|
|
|
private RcVec3f cameraPos = RcVec3f.Of(0, 0, 0);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
|
2023-03-22 18:03:32 +03:00
|
|
|
private float[] projectionMatrix = new float[16];
|
|
|
|
private float[] modelviewMatrix = new float[16];
|
|
|
|
|
|
|
|
private float _moveFront;
|
|
|
|
private float _moveLeft;
|
|
|
|
private float _moveBack;
|
|
|
|
private float _moveRight;
|
|
|
|
private float _moveUp;
|
|
|
|
private float _moveDown;
|
|
|
|
private float _moveAccel;
|
2023-03-22 18:29:25 +03:00
|
|
|
|
2023-03-25 16:02:44 +03:00
|
|
|
private int[] viewport;
|
2023-03-14 08:02:43 +03:00
|
|
|
private bool markerPositionSet;
|
2023-06-03 15:47:26 +03:00
|
|
|
private RcVec3f markerPosition = new RcVec3f();
|
2023-04-17 18:12:28 +03:00
|
|
|
|
2023-06-11 10:04:21 +03:00
|
|
|
private RcToolsetView toolset;
|
2023-06-11 08:58:37 +03:00
|
|
|
private RcSettingsView settingsView;
|
|
|
|
private RcLogView logView;
|
2023-04-17 18:12:28 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
private long prevFrameTime;
|
2023-03-14 19:34:31 +03:00
|
|
|
private RecastDebugDraw dd;
|
2023-07-02 18:02:43 +03:00
|
|
|
private readonly Queue<IRecastDemoMessage> _messages;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
public RecastDemo()
|
|
|
|
{
|
2023-07-02 09:35:46 +03:00
|
|
|
_messages = new();
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-04-17 18:12:28 +03:00
|
|
|
public void Run()
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
window = CreateWindow();
|
|
|
|
window.Run();
|
|
|
|
}
|
|
|
|
|
2023-03-19 17:16:41 +03:00
|
|
|
public void OnMouseScrolled(IMouse mice, ScrollWheel scrollWheel)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-19 17:16:41 +03:00
|
|
|
if (scrollWheel.Y < 0)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
// wheel down
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!_mouseOverMenu)
|
|
|
|
{
|
|
|
|
scrollZoom += 1.0f;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!_mouseOverMenu)
|
|
|
|
{
|
|
|
|
scrollZoom -= 1.0f;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-09-14 16:58:13 +03:00
|
|
|
var modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
|
|
|
|
cameraPos.x += scrollZoom * 2.0f * modelviewMatrix.M13;
|
|
|
|
cameraPos.y += scrollZoom * 2.0f * modelviewMatrix.M23;
|
|
|
|
cameraPos.z += scrollZoom * 2.0f * modelviewMatrix.M33;
|
2023-03-14 08:02:43 +03:00
|
|
|
scrollZoom = 0;
|
|
|
|
}
|
|
|
|
|
2023-03-19 17:16:41 +03:00
|
|
|
public void OnMouseMoved(IMouse mouse, Vector2 position)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-19 17:16:41 +03:00
|
|
|
mousePos[0] = (float)position.X;
|
|
|
|
mousePos[1] = (float)position.Y;
|
2023-03-14 08:02:43 +03:00
|
|
|
int dx = (int)(mousePos[0] - origMousePos[0]);
|
|
|
|
int dy = (int)(mousePos[1] - origMousePos[1]);
|
|
|
|
if (rotate)
|
|
|
|
{
|
|
|
|
cameraEulers[0] = origCameraEulers[0] + dy * 0.25f;
|
|
|
|
cameraEulers[1] = origCameraEulers[1] + dx * 0.25f;
|
|
|
|
if (dx * dx + dy * dy > 3 * 3)
|
|
|
|
{
|
|
|
|
movedDuringRotate = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-19 17:16:41 +03:00
|
|
|
if (pan)
|
|
|
|
{
|
2023-09-14 16:58:13 +03:00
|
|
|
var modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
|
2023-07-02 18:02:43 +03:00
|
|
|
cameraPos = origCameraPos;
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-09-14 16:58:13 +03:00
|
|
|
cameraPos.x -= 0.1f * dx * modelviewMatrix.M11;
|
|
|
|
cameraPos.y -= 0.1f * dx * modelviewMatrix.M21;
|
|
|
|
cameraPos.z -= 0.1f * dx * modelviewMatrix.M31;
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-09-14 16:58:13 +03:00
|
|
|
cameraPos.x += 0.1f * dy * modelviewMatrix.M12;
|
|
|
|
cameraPos.y += 0.1f * dy * modelviewMatrix.M22;
|
|
|
|
cameraPos.z += 0.1f * dy * modelviewMatrix.M32;
|
2023-03-19 17:16:41 +03:00
|
|
|
if (dx * dx + dy * dy > 3 * 3)
|
|
|
|
{
|
|
|
|
movedDuringPan = true;
|
|
|
|
}
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-03-19 17:16:41 +03:00
|
|
|
public void OnMouseUpAndDown(IMouse mouse, MouseButton button, bool down)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
if (down)
|
|
|
|
{
|
2023-03-19 17:16:41 +03:00
|
|
|
if (button == MouseButton.Right)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!_mouseOverMenu)
|
|
|
|
{
|
|
|
|
// Rotate view
|
|
|
|
rotate = true;
|
|
|
|
movedDuringRotate = false;
|
|
|
|
origMousePos[0] = mousePos[0];
|
|
|
|
origMousePos[1] = mousePos[1];
|
|
|
|
origCameraEulers[0] = cameraEulers[0];
|
|
|
|
origCameraEulers[1] = cameraEulers[1];
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
else if (button == MouseButton.Middle)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!_mouseOverMenu)
|
|
|
|
{
|
|
|
|
// Pan view
|
|
|
|
pan = true;
|
|
|
|
movedDuringPan = false;
|
|
|
|
origMousePos[0] = mousePos[0];
|
|
|
|
origMousePos[1] = mousePos[1];
|
2023-04-29 07:24:26 +03:00
|
|
|
origCameraPos.x = cameraPos.x;
|
|
|
|
origCameraPos.y = cameraPos.y;
|
|
|
|
origCameraPos.z = cameraPos.z;
|
2023-03-22 18:29:25 +03:00
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Handle mouse clicks here.
|
2023-03-19 17:16:41 +03:00
|
|
|
if (button == MouseButton.Right)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
rotate = false;
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!_mouseOverMenu)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!movedDuringRotate)
|
|
|
|
{
|
|
|
|
processHitTest = true;
|
|
|
|
processHitTestShift = true;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
else if (button == MouseButton.Left)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-22 18:29:25 +03:00
|
|
|
if (!_mouseOverMenu)
|
|
|
|
{
|
|
|
|
processHitTest = true;
|
2023-06-28 16:41:12 +03:00
|
|
|
processHitTestShift = 0 != (_modState & KeyModState.Shift);
|
2023-03-22 18:29:25 +03:00
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
else if (button == MouseButton.Middle)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
pan = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-22 18:03:32 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
private IWindow CreateWindow()
|
|
|
|
{
|
|
|
|
var monitor = Window.Platforms.First().GetMainMonitor();
|
|
|
|
var resolution = monitor.VideoMode.Resolution.Value;
|
|
|
|
|
|
|
|
float aspect = 16.0f / 9.0f;
|
|
|
|
width = Math.Min(resolution.X, (int)(resolution.Y * aspect)) - 100;
|
|
|
|
height = resolution.Y - 100;
|
2023-03-25 16:02:44 +03:00
|
|
|
viewport = new int[] { 0, 0, width, height };
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
var options = WindowOptions.Default;
|
|
|
|
options.Title = title;
|
|
|
|
options.Size = new Vector2D<int>(width, height);
|
|
|
|
options.Position = new Vector2D<int>((resolution.X - width) / 2, (resolution.Y - height) / 2);
|
2023-04-17 18:12:28 +03:00
|
|
|
options.VSync = true;
|
2023-03-14 19:34:31 +03:00
|
|
|
options.ShouldSwapAutomatically = false;
|
2023-04-06 17:32:00 +03:00
|
|
|
options.PreferredDepthBufferBits = 24;
|
2023-03-14 08:02:43 +03:00
|
|
|
window = Window.Create(options);
|
|
|
|
|
|
|
|
if (window == null)
|
|
|
|
{
|
|
|
|
throw new Exception("Failed to create the GLFW window");
|
|
|
|
}
|
|
|
|
|
2023-03-14 19:34:31 +03:00
|
|
|
window.Closing += OnWindowClosing;
|
2023-03-14 08:02:43 +03:00
|
|
|
window.Load += OnWindowOnLoad;
|
2023-03-14 19:34:31 +03:00
|
|
|
window.Resize += OnWindowResize;
|
|
|
|
window.FramebufferResize += OnWindowFramebufferSizeChanged;
|
2023-04-17 18:12:28 +03:00
|
|
|
window.Update += OnWindowUpdate;
|
|
|
|
window.Render += OnWindowRender;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
|
|
|
|
// // -- move somewhere else:
|
|
|
|
// glfw.SetWindowPos(window, (mode->Width - width) / 2, (mode->Height - height) / 2);
|
2023-05-05 02:44:48 +03:00
|
|
|
// // GlfwSetWindowMonitor(window.GetWindow(), monitor, 0, 0, mode.Width(), mode.Height(), mode.RefreshRate());
|
2023-03-14 08:02:43 +03:00
|
|
|
// glfw.ShowWindow(window);
|
|
|
|
// glfw.MakeContextCurrent(window);
|
|
|
|
//}
|
|
|
|
|
|
|
|
//glfw.SwapInterval(1);
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
2023-07-02 18:16:53 +03:00
|
|
|
private DemoInputGeomProvider LoadInputMesh(string filename)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-09-24 12:42:41 +03:00
|
|
|
DemoInputGeomProvider geom = DemoInputGeomProvider.LoadFile(filename);
|
2023-07-02 18:16:53 +03:00
|
|
|
_lastGeomFileName = filename;
|
2023-03-14 08:02:43 +03:00
|
|
|
return geom;
|
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
private void LoadNavMesh(FileStream file, string filename)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-07-02 18:02:43 +03:00
|
|
|
try
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-07-02 18:02:43 +03:00
|
|
|
DtNavMesh mesh = null;
|
|
|
|
if (filename.EndsWith(".zip"))
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-07-02 18:02:43 +03:00
|
|
|
UnityAStarPathfindingImporter importer = new UnityAStarPathfindingImporter();
|
|
|
|
mesh = importer.Load(file)[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
using var br = new BinaryReader(file);
|
|
|
|
DtMeshSetReader reader = new DtMeshSetReader();
|
|
|
|
mesh = reader.Read(br, 6);
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-07-02 18:02:43 +03:00
|
|
|
if (null != mesh)
|
|
|
|
{
|
2023-09-22 17:42:21 +03:00
|
|
|
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RcBuilderResult>.Empty, mesh);
|
2023-07-02 18:02:43 +03:00
|
|
|
toolset.SetEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-07-02 18:02:43 +03:00
|
|
|
Logger.Error(e, "");
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-14 19:34:31 +03:00
|
|
|
private void OnWindowClosing()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnWindowResize(Vector2D<int> size)
|
|
|
|
{
|
|
|
|
width = size.X;
|
|
|
|
height = size.Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnWindowFramebufferSizeChanged(Vector2D<int> size)
|
|
|
|
{
|
|
|
|
_gl.Viewport(size);
|
2023-03-25 16:02:44 +03:00
|
|
|
viewport = new int[] { 0, 0, width, height };
|
2023-03-14 19:34:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
private void OnWindowOnLoad()
|
|
|
|
{
|
|
|
|
_input = window.CreateInput();
|
2023-03-22 18:03:32 +03:00
|
|
|
|
|
|
|
// mouse input
|
2023-03-19 17:16:41 +03:00
|
|
|
foreach (var mice in _input.Mice)
|
|
|
|
{
|
|
|
|
mice.Scroll += OnMouseScrolled;
|
|
|
|
mice.MouseDown += (m, b) => OnMouseUpAndDown(m, b, true);
|
|
|
|
mice.MouseUp += (m, b) => OnMouseUpAndDown(m, b, false);
|
|
|
|
mice.MouseMove += OnMouseMoved;
|
|
|
|
}
|
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
_gl = window.CreateOpenGL();
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-03-18 22:36:31 +03:00
|
|
|
dd = new RecastDebugDraw(_gl);
|
|
|
|
renderer = new NavMeshRenderer(dd);
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
dd.Init(camr);
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-06-22 18:00:21 +03:00
|
|
|
ImGuiFontConfig imGuiFontConfig = new(Path.Combine("resources\\fonts", "DroidSans.ttf"), 16, null);
|
2023-06-22 10:22:52 +03:00
|
|
|
_imgui = new ImGuiController(_gl, window, _input, imGuiFontConfig);
|
2023-04-17 18:12:28 +03:00
|
|
|
|
2023-07-02 18:16:53 +03:00
|
|
|
DemoInputGeomProvider geom = LoadInputMesh("nav_test.obj");
|
2023-09-22 17:42:21 +03:00
|
|
|
_sample = new DemoSample(geom, ImmutableArray<RcBuilderResult>.Empty, null);
|
2023-06-11 10:27:17 +03:00
|
|
|
|
2023-07-02 09:35:46 +03:00
|
|
|
settingsView = new RcSettingsView(this);
|
2023-07-03 18:09:07 +03:00
|
|
|
settingsView.SetSample(_sample);
|
2023-06-11 10:27:17 +03:00
|
|
|
|
2023-06-11 10:04:21 +03:00
|
|
|
toolset = new RcToolsetView(
|
2023-08-20 07:19:47 +03:00
|
|
|
new TestNavmeshSampleTool(),
|
|
|
|
new TileSampleTool(),
|
|
|
|
new ObstacleSampleTool(),
|
|
|
|
new OffMeshConnectionSampleTool(),
|
|
|
|
new ConvexVolumeSampleTool(),
|
2023-09-09 06:51:44 +03:00
|
|
|
new CrowdSampleTool(),
|
2023-09-21 17:36:55 +03:00
|
|
|
new CrowdAgentProfilingSampleTool(),
|
2023-08-20 07:19:47 +03:00
|
|
|
new JumpLinkBuilderSampleTool(),
|
|
|
|
new DynamicUpdateSampleTool()
|
2023-03-18 08:05:01 +03:00
|
|
|
);
|
2023-06-11 10:27:17 +03:00
|
|
|
toolset.SetEnabled(true);
|
2023-06-11 08:58:37 +03:00
|
|
|
logView = new RcLogView();
|
2023-04-16 05:54:50 +03:00
|
|
|
|
2023-06-11 10:04:21 +03:00
|
|
|
_canvas = new RcCanvas(window, settingsView, toolset, logView);
|
2023-04-17 18:12:28 +03:00
|
|
|
|
2023-04-16 05:54:50 +03:00
|
|
|
var vendor = _gl.GetStringS(GLEnum.Vendor);
|
|
|
|
var version = _gl.GetStringS(GLEnum.Version);
|
2023-08-15 04:34:18 +03:00
|
|
|
var rendererGl = _gl.GetStringS(GLEnum.Renderer);
|
2023-04-16 05:54:50 +03:00
|
|
|
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
|
2023-08-14 16:47:57 +03:00
|
|
|
var currentCulture = CultureInfo.CurrentCulture;
|
2023-08-15 04:34:18 +03:00
|
|
|
string bitness = Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit";
|
2023-06-28 16:41:12 +03:00
|
|
|
|
2023-06-07 17:19:25 +03:00
|
|
|
var workingDirectory = Directory.GetCurrentDirectory();
|
2023-08-14 16:47:57 +03:00
|
|
|
Logger.Information($"Working directory - {workingDirectory}");
|
2023-06-20 15:13:09 +03:00
|
|
|
Logger.Information($"ImGui.Net version - {ImGui.GetVersion()}");
|
2023-08-15 04:34:18 +03:00
|
|
|
Logger.Information($"Dotnet - {Environment.Version.ToString()} culture({currentCulture.Name})");
|
|
|
|
Logger.Information($"OS Version - {Environment.OSVersion} {bitness}");
|
|
|
|
Logger.Information($"{vendor} {rendererGl}");
|
|
|
|
Logger.Information($"gl version - {version}");
|
|
|
|
Logger.Information($"gl lang version - {glslString}");
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-03-22 18:03:32 +03:00
|
|
|
private void UpdateKeyboard(float dt)
|
|
|
|
{
|
2023-06-14 18:36:26 +03:00
|
|
|
_modState = 0;
|
2023-06-28 16:41:12 +03:00
|
|
|
|
2023-03-22 18:03:32 +03:00
|
|
|
// keyboard input
|
|
|
|
foreach (var keyboard in _input.Keyboards)
|
|
|
|
{
|
|
|
|
var tempMoveFront = keyboard.IsKeyPressed(Key.W) || keyboard.IsKeyPressed(Key.Up) ? 1.0f : -1f;
|
|
|
|
var tempMoveLeft = keyboard.IsKeyPressed(Key.A) || keyboard.IsKeyPressed(Key.Left) ? 1.0f : -1f;
|
|
|
|
var tempMoveBack = keyboard.IsKeyPressed(Key.S) || keyboard.IsKeyPressed(Key.Down) ? 1.0f : -1f;
|
|
|
|
var tempMoveRight = keyboard.IsKeyPressed(Key.D) || keyboard.IsKeyPressed(Key.Right) ? 1.0f : -1f;
|
|
|
|
var tempMoveUp = keyboard.IsKeyPressed(Key.Q) || keyboard.IsKeyPressed(Key.PageUp) ? 1.0f : -1f;
|
2023-03-22 18:29:25 +03:00
|
|
|
var tempMoveDown = keyboard.IsKeyPressed(Key.E) || keyboard.IsKeyPressed(Key.PageDown) ? 1.0f : -1f;
|
|
|
|
var tempMoveAccel = keyboard.IsKeyPressed(Key.ShiftLeft) || keyboard.IsKeyPressed(Key.ShiftRight) ? 1.0f : -1f;
|
2023-06-14 18:36:26 +03:00
|
|
|
var tempControl = keyboard.IsKeyPressed(Key.ControlLeft) || keyboard.IsKeyPressed(Key.ControlRight);
|
2023-03-22 18:03:32 +03:00
|
|
|
|
2023-06-28 16:41:12 +03:00
|
|
|
_modState |= tempControl ? (int)KeyModState.Control : (int)KeyModState.None;
|
|
|
|
_modState |= 0 < tempMoveAccel ? (int)KeyModState.Shift : (int)KeyModState.None;
|
|
|
|
|
2023-06-14 18:36:26 +03:00
|
|
|
//Logger.Information($"{_modState}");
|
2023-09-23 01:38:46 +03:00
|
|
|
_moveFront = Math.Clamp(_moveFront + tempMoveFront * dt * 4.0f, 0, 2.0f);
|
|
|
|
_moveLeft = Math.Clamp(_moveLeft + tempMoveLeft * dt * 4.0f, 0, 2.0f);
|
|
|
|
_moveBack = Math.Clamp(_moveBack + tempMoveBack * dt * 4.0f, 0, 2.0f);
|
|
|
|
_moveRight = Math.Clamp(_moveRight + tempMoveRight * dt * 4.0f, 0, 2.0f);
|
|
|
|
_moveUp = Math.Clamp(_moveUp + tempMoveUp * dt * 4.0f, 0, 2.0f);
|
|
|
|
_moveDown = Math.Clamp(_moveDown + tempMoveDown * dt * 4.0f, 0, 2.0f);
|
|
|
|
_moveAccel = Math.Clamp(_moveAccel + tempMoveAccel * dt * 4.0f, 0, 2.0f);
|
2023-03-22 18:03:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-17 18:12:28 +03:00
|
|
|
private void OnWindowUpdate(double dt)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
/*
|
2023-08-14 16:47:57 +03:00
|
|
|
* try (MemoryStack stack = StackPush()) { int[] w = stack.MallocInt(1); int[] h =
|
|
|
|
* stack.MallocInt(1); GlfwGetWindowSize(win, w, h); width = w.x; height = h.x; }
|
|
|
|
*/
|
2023-07-03 18:09:07 +03:00
|
|
|
if (_sample.GetInputGeom() != null)
|
2023-03-22 18:03:32 +03:00
|
|
|
{
|
2023-07-03 18:09:07 +03:00
|
|
|
var settings = _sample.GetSettings();
|
|
|
|
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
|
|
|
|
RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax();
|
2023-09-22 17:42:21 +03:00
|
|
|
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
|
2023-06-11 08:58:37 +03:00
|
|
|
settingsView.SetVoxels(gw, gh);
|
2023-07-03 18:09:07 +03:00
|
|
|
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
|
|
|
settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
|
|
|
settingsView.SetMaxPolys(tileNavMeshBuilder.GetMaxPolysPerTile(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
2023-03-22 18:03:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateKeyboard((float)dt);
|
|
|
|
|
|
|
|
// camera move
|
|
|
|
float keySpeed = 22.0f;
|
|
|
|
if (0 < _moveAccel)
|
|
|
|
{
|
|
|
|
keySpeed *= _moveAccel * 2.0f;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-22 18:03:32 +03:00
|
|
|
double movex = (_moveRight - _moveLeft) * keySpeed * dt;
|
|
|
|
double movey = (_moveBack - _moveFront) * keySpeed * dt + scrollZoom * 2.0f;
|
|
|
|
scrollZoom = 0;
|
|
|
|
|
2023-04-29 07:24:26 +03:00
|
|
|
cameraPos.x += (float)(movex * modelviewMatrix[0]);
|
|
|
|
cameraPos.y += (float)(movex * modelviewMatrix[4]);
|
|
|
|
cameraPos.z += (float)(movex * modelviewMatrix[8]);
|
2023-03-22 18:03:32 +03:00
|
|
|
|
2023-04-29 07:24:26 +03:00
|
|
|
cameraPos.x += (float)(movey * modelviewMatrix[2]);
|
|
|
|
cameraPos.y += (float)(movey * modelviewMatrix[6]);
|
|
|
|
cameraPos.z += (float)(movey * modelviewMatrix[10]);
|
2023-03-22 18:03:32 +03:00
|
|
|
|
2023-04-29 07:24:26 +03:00
|
|
|
cameraPos.y += (float)((_moveUp - _moveDown) * keySpeed * dt);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-05-06 05:44:57 +03:00
|
|
|
long time = RcFrequency.Ticks;
|
2023-03-25 06:17:09 +03:00
|
|
|
prevFrameTime = time;
|
2023-03-25 16:02:44 +03:00
|
|
|
|
2023-03-25 06:17:09 +03:00
|
|
|
// Update sample simulation.
|
|
|
|
float SIM_RATE = 20;
|
|
|
|
float DELTA_TIME = 1.0f / SIM_RATE;
|
2023-09-23 01:38:46 +03:00
|
|
|
timeAcc = Math.Clamp((float)(timeAcc + dt), -1.0f, 1.0f);
|
2023-03-25 06:17:09 +03:00
|
|
|
int simIter = 0;
|
|
|
|
while (timeAcc > DELTA_TIME)
|
|
|
|
{
|
|
|
|
timeAcc -= DELTA_TIME;
|
2023-07-03 18:09:07 +03:00
|
|
|
if (simIter < 5 && _sample != null)
|
2023-03-25 06:17:09 +03:00
|
|
|
{
|
2023-09-09 08:04:25 +03:00
|
|
|
var tool = toolset.GetTool();
|
|
|
|
if (null != tool)
|
|
|
|
{
|
|
|
|
tool.HandleUpdate(DELTA_TIME);
|
|
|
|
}
|
2023-03-25 06:17:09 +03:00
|
|
|
}
|
2023-03-25 16:02:44 +03:00
|
|
|
|
2023-03-25 06:17:09 +03:00
|
|
|
simIter++;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-07-03 17:04:14 +03:00
|
|
|
if (processHitTest)
|
2023-03-25 16:02:44 +03:00
|
|
|
{
|
2023-07-03 17:04:14 +03:00
|
|
|
processHitTest = false;
|
2023-07-27 08:29:34 +03:00
|
|
|
|
2023-07-03 17:04:14 +03:00
|
|
|
RcVec3f rayStart = new RcVec3f();
|
|
|
|
RcVec3f rayEnd = new RcVec3f();
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
GLU.GlhUnProjectf(mousePos[0], viewport[3] - 1 - mousePos[1], 0.0f, modelviewMatrix, projectionMatrix, viewport, ref rayStart);
|
|
|
|
GLU.GlhUnProjectf(mousePos[0], viewport[3] - 1 - mousePos[1], 1.0f, modelviewMatrix, projectionMatrix, viewport, ref rayEnd);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-07-03 17:04:14 +03:00
|
|
|
SendMessage(new RaycastEvent()
|
2023-03-25 16:02:44 +03:00
|
|
|
{
|
2023-07-03 17:04:14 +03:00
|
|
|
Start = rayStart,
|
|
|
|
End = rayEnd,
|
|
|
|
});
|
2023-03-25 16:02:44 +03:00
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-07-03 18:09:07 +03:00
|
|
|
if (_sample.IsChanged())
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-07-15 05:11:03 +03:00
|
|
|
bool hasBound = false;
|
|
|
|
RcVec3f bminN = RcVec3f.Zero;
|
|
|
|
RcVec3f bmaxN = RcVec3f.Zero;
|
2023-07-03 18:09:07 +03:00
|
|
|
if (_sample.GetInputGeom() != null)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-07-03 18:09:07 +03:00
|
|
|
bminN = _sample.GetInputGeom().GetMeshBoundsMin();
|
|
|
|
bmaxN = _sample.GetInputGeom().GetMeshBoundsMax();
|
2023-07-15 05:11:03 +03:00
|
|
|
hasBound = true;
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
2023-07-03 18:09:07 +03:00
|
|
|
else if (_sample.GetNavMesh() != null)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-08-01 18:00:00 +03:00
|
|
|
_sample.GetNavMesh().ComputeBounds(out bminN, out bmaxN);
|
2023-07-15 05:11:03 +03:00
|
|
|
hasBound = true;
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
2023-07-03 18:09:07 +03:00
|
|
|
else if (0 < _sample.GetRecastResults().Count)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-09-22 17:42:21 +03:00
|
|
|
foreach (RcBuilderResult result in _sample.GetRecastResults())
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-05-05 02:44:48 +03:00
|
|
|
if (result.GetSolidHeightfield() != null)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-07-15 05:11:03 +03:00
|
|
|
if (!hasBound)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-06-03 15:47:26 +03:00
|
|
|
bminN = RcVec3f.Of(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
|
|
|
bmaxN = RcVec3f.Of(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-06-03 15:47:26 +03:00
|
|
|
bminN = RcVec3f.Of(
|
2023-07-15 05:11:03 +03:00
|
|
|
Math.Min(bminN.x, result.GetSolidHeightfield().bmin.x),
|
|
|
|
Math.Min(bminN.y, result.GetSolidHeightfield().bmin.y),
|
|
|
|
Math.Min(bminN.z, result.GetSolidHeightfield().bmin.z)
|
2023-04-06 12:43:31 +03:00
|
|
|
);
|
|
|
|
|
2023-06-03 15:47:26 +03:00
|
|
|
bmaxN = RcVec3f.Of(
|
2023-07-15 05:11:03 +03:00
|
|
|
Math.Max(bmaxN.x, result.GetSolidHeightfield().bmax.x),
|
|
|
|
Math.Max(bmaxN.y, result.GetSolidHeightfield().bmax.y),
|
|
|
|
Math.Max(bmaxN.z, result.GetSolidHeightfield().bmax.z)
|
2023-04-06 12:43:31 +03:00
|
|
|
);
|
2023-07-15 05:11:03 +03:00
|
|
|
|
|
|
|
hasBound = true;
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-07-15 05:11:03 +03:00
|
|
|
if (hasBound)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-07-15 05:11:03 +03:00
|
|
|
RcVec3f bmin = bminN;
|
|
|
|
RcVec3f bmax = bmaxN;
|
2023-03-30 19:10:04 +03:00
|
|
|
|
2023-09-23 01:30:47 +03:00
|
|
|
camr = (float)(Math.Sqrt(RcMath.Sqr(bmax.x - bmin.x) + RcMath.Sqr(bmax.y - bmin.y) + RcMath.Sqr(bmax.z - bmin.z)) / 2);
|
2023-04-29 07:24:26 +03:00
|
|
|
cameraPos.x = (bmax.x + bmin.x) / 2 + camr;
|
|
|
|
cameraPos.y = (bmax.y + bmin.y) / 2 + camr;
|
|
|
|
cameraPos.z = (bmax.z + bmin.z) / 2 + camr;
|
2023-07-02 18:02:43 +03:00
|
|
|
camr *= 5;
|
2023-03-18 18:09:36 +03:00
|
|
|
cameraEulers[0] = 45;
|
|
|
|
cameraEulers[1] = -45;
|
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-07-03 18:09:07 +03:00
|
|
|
_sample.SetChanged(false);
|
|
|
|
toolset.SetSample(_sample);
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
|
|
|
|
2023-07-02 09:35:46 +03:00
|
|
|
if (_messages.TryDequeue(out var msg))
|
|
|
|
{
|
|
|
|
OnMessage(msg);
|
|
|
|
}
|
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-14 19:34:31 +03:00
|
|
|
var io = ImGui.GetIO();
|
|
|
|
|
|
|
|
io.DisplaySize = new Vector2(width, height);
|
|
|
|
io.DisplayFramebufferScale = Vector2.One;
|
|
|
|
io.DeltaTime = (float)dt;
|
|
|
|
|
2023-04-16 05:54:50 +03:00
|
|
|
_canvas.Update(dt);
|
2023-03-14 08:02:43 +03:00
|
|
|
_imgui.Update((float)dt);
|
|
|
|
}
|
|
|
|
|
2023-05-01 16:42:01 +03:00
|
|
|
private void OnWindowRender(double dt)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
2023-03-18 18:09:36 +03:00
|
|
|
// Clear the screen
|
2023-05-05 02:44:48 +03:00
|
|
|
dd.Clear();
|
2023-09-14 17:17:40 +03:00
|
|
|
dd.ProjectionMatrix(50f, (float)width / (float)height, 1.0f, camr).CopyTo(projectionMatrix);
|
2023-09-14 16:58:13 +03:00
|
|
|
dd.ViewMatrix(cameraPos, cameraEulers).CopyTo(modelviewMatrix);
|
2023-03-18 18:09:36 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
dd.Fog(camr * 0.1f, camr * 1.25f);
|
2023-07-03 18:09:07 +03:00
|
|
|
renderer.Render(_sample, settingsView.GetDrawMode());
|
2023-06-11 10:04:21 +03:00
|
|
|
|
2023-08-20 07:19:47 +03:00
|
|
|
ISampleTool sampleTool = toolset.GetTool();
|
|
|
|
if (sampleTool != null)
|
2023-03-19 16:47:34 +03:00
|
|
|
{
|
2023-08-20 07:19:47 +03:00
|
|
|
sampleTool.HandleRender(renderer);
|
2023-03-19 16:47:34 +03:00
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
dd.Fog(false);
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-04-16 05:54:50 +03:00
|
|
|
_canvas.Draw(dt);
|
2023-06-15 17:10:52 +03:00
|
|
|
_mouseOverMenu = _canvas.IsMouseOver();
|
2023-06-28 16:41:12 +03:00
|
|
|
|
2023-03-19 16:47:34 +03:00
|
|
|
_imgui.Render();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-03-14 19:34:31 +03:00
|
|
|
window.SwapBuffers();
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
2023-07-02 09:35:46 +03:00
|
|
|
|
|
|
|
public void SendMessage(IRecastDemoMessage message)
|
|
|
|
{
|
|
|
|
_messages.Enqueue(message);
|
|
|
|
}
|
|
|
|
|
2023-07-02 09:44:34 +03:00
|
|
|
private void OnMessage(IRecastDemoMessage message)
|
2023-07-02 09:35:46 +03:00
|
|
|
{
|
2023-07-02 09:53:32 +03:00
|
|
|
if (message is GeomLoadBeganEvent args)
|
|
|
|
{
|
|
|
|
OnGeomLoadBegan(args);
|
|
|
|
}
|
|
|
|
else if (message is NavMeshBuildBeganEvent args2)
|
|
|
|
{
|
|
|
|
OnNavMeshBuildBegan(args2);
|
|
|
|
}
|
|
|
|
else if (message is NavMeshSaveBeganEvent args3)
|
2023-07-02 09:44:34 +03:00
|
|
|
{
|
2023-07-02 09:53:32 +03:00
|
|
|
OnNavMeshSaveBegan(args3);
|
2023-07-02 09:44:34 +03:00
|
|
|
}
|
2023-07-02 09:53:32 +03:00
|
|
|
else if (message is NavMeshLoadBeganEvent args4)
|
2023-07-02 09:35:46 +03:00
|
|
|
{
|
2023-07-02 09:53:32 +03:00
|
|
|
OnNavMeshLoadBegan(args4);
|
2023-07-02 09:44:34 +03:00
|
|
|
}
|
2023-07-03 17:04:14 +03:00
|
|
|
else if (message is RaycastEvent args5)
|
|
|
|
{
|
|
|
|
OnRaycast(args5);
|
|
|
|
}
|
2023-07-02 09:44:34 +03:00
|
|
|
}
|
2023-07-02 09:35:46 +03:00
|
|
|
|
2023-07-02 09:53:32 +03:00
|
|
|
private void OnGeomLoadBegan(GeomLoadBeganEvent args)
|
2023-07-02 09:44:34 +03:00
|
|
|
{
|
2023-07-02 18:16:53 +03:00
|
|
|
var geom = LoadInputMesh(args.FilePath);
|
2023-07-02 09:44:34 +03:00
|
|
|
|
2023-09-22 17:42:21 +03:00
|
|
|
_sample.Update(geom, ImmutableArray<RcBuilderResult>.Empty, null);
|
2023-07-02 09:44:34 +03:00
|
|
|
}
|
|
|
|
|
2023-07-02 09:53:32 +03:00
|
|
|
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
2023-07-02 09:44:34 +03:00
|
|
|
{
|
2023-07-03 18:09:07 +03:00
|
|
|
if (null == _sample.GetInputGeom())
|
2023-07-02 09:44:34 +03:00
|
|
|
{
|
|
|
|
Logger.Information($"not found source geom");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
long t = RcFrequency.Ticks;
|
|
|
|
|
|
|
|
Logger.Information($"build");
|
|
|
|
|
|
|
|
NavMeshBuildResult buildResult;
|
2023-07-27 08:29:34 +03:00
|
|
|
|
|
|
|
var settings = _sample.GetSettings();
|
2023-07-02 09:44:34 +03:00
|
|
|
if (settings.tiled)
|
|
|
|
{
|
2023-07-27 08:29:34 +03:00
|
|
|
buildResult = tileNavMeshBuilder.Build(_sample.GetInputGeom(), settings);
|
2023-07-02 09:44:34 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-07-27 08:29:34 +03:00
|
|
|
buildResult = soloNavMeshBuilder.Build(_sample.GetInputGeom(), settings);
|
2023-07-02 09:44:34 +03:00
|
|
|
}
|
|
|
|
|
2023-07-29 06:01:38 +03:00
|
|
|
if (!buildResult.Success)
|
|
|
|
{
|
|
|
|
Logger.Error("failed to build");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-03 18:09:07 +03:00
|
|
|
_sample.Update(_sample.GetInputGeom(), buildResult.RecastBuilderResults, buildResult.NavMesh);
|
|
|
|
_sample.SetChanged(false);
|
2023-07-02 09:44:34 +03:00
|
|
|
settingsView.SetBuildTime((RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond);
|
|
|
|
//settingsUI.SetBuildTelemetry(buildResult.Item1.Select(x => x.GetTelemetry()).ToList());
|
2023-07-03 18:09:07 +03:00
|
|
|
toolset.SetSample(_sample);
|
2023-07-02 09:44:34 +03:00
|
|
|
|
|
|
|
Logger.Information($"build times");
|
|
|
|
Logger.Information($"-----------------------------------------");
|
|
|
|
var telemetries = buildResult.RecastBuilderResults
|
|
|
|
.Select(x => x.GetTelemetry())
|
|
|
|
.SelectMany(x => x.ToList())
|
|
|
|
.GroupBy(x => x.Key)
|
|
|
|
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Millis));
|
|
|
|
|
|
|
|
foreach (var (key, millis) in telemetries)
|
|
|
|
{
|
|
|
|
Logger.Information($"{key}: {millis} ms");
|
2023-07-02 09:35:46 +03:00
|
|
|
}
|
|
|
|
}
|
2023-07-02 09:53:32 +03:00
|
|
|
|
|
|
|
private void OnNavMeshSaveBegan(NavMeshSaveBeganEvent args)
|
|
|
|
{
|
2023-07-03 18:09:07 +03:00
|
|
|
var navMesh = _sample.GetNavMesh();
|
2023-07-02 18:16:53 +03:00
|
|
|
if (null == navMesh)
|
|
|
|
{
|
|
|
|
Logger.Error("navmesh is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DateTime now = DateTime.Now;
|
|
|
|
string ymdhms = $"{now:yyyyMMdd_HHmmss}";
|
|
|
|
var filename = Path.GetFileNameWithoutExtension(_lastGeomFileName);
|
|
|
|
var navmeshFilePath = $"{filename}_{ymdhms}.navmesh";
|
2023-07-03 17:04:14 +03:00
|
|
|
|
2023-07-02 18:16:53 +03:00
|
|
|
using var fs = new FileStream(navmeshFilePath, FileMode.Create, FileAccess.Write);
|
|
|
|
using var bw = new BinaryWriter(fs);
|
|
|
|
|
|
|
|
var writer = new DtMeshSetWriter();
|
|
|
|
writer.Write(bw, navMesh, RcByteOrder.LITTLE_ENDIAN, true);
|
|
|
|
Logger.Information($"saved navmesh - {navmeshFilePath}");
|
2023-07-02 09:53:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
private void OnNavMeshLoadBegan(NavMeshLoadBeganEvent args)
|
|
|
|
{
|
2023-07-02 18:02:43 +03:00
|
|
|
if (string.IsNullOrEmpty(args.FilePath))
|
|
|
|
{
|
|
|
|
Logger.Error("file path is empty");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!File.Exists(args.FilePath))
|
|
|
|
{
|
|
|
|
Logger.Error($"not found navmesh file - {args.FilePath}");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2023-09-20 17:41:18 +03:00
|
|
|
using FileStream fs = new FileStream(args.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
2023-07-02 18:02:43 +03:00
|
|
|
LoadNavMesh(fs, args.FilePath);
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
Logger.Error(e, "");
|
|
|
|
}
|
2023-07-02 09:53:32 +03:00
|
|
|
}
|
2023-07-03 17:04:14 +03:00
|
|
|
|
|
|
|
private void OnRaycast(RaycastEvent args)
|
|
|
|
{
|
|
|
|
var rayStart = args.Start;
|
|
|
|
var rayEnd = args.End;
|
|
|
|
|
|
|
|
// Hit test mesh.
|
2023-07-03 18:09:07 +03:00
|
|
|
DemoInputGeomProvider inputGeom = _sample.GetInputGeom();
|
|
|
|
if (_sample == null)
|
2023-07-03 17:04:14 +03:00
|
|
|
return;
|
|
|
|
|
2023-08-01 17:32:28 +03:00
|
|
|
float hitTime = 0.0f;
|
|
|
|
bool hit = false;
|
2023-07-03 17:04:14 +03:00
|
|
|
if (inputGeom != null)
|
|
|
|
{
|
2023-08-01 17:32:28 +03:00
|
|
|
hit = inputGeom.RaycastMesh(rayStart, rayEnd, out hitTime);
|
2023-07-03 17:04:14 +03:00
|
|
|
}
|
|
|
|
|
2023-08-01 17:32:28 +03:00
|
|
|
if (!hit && _sample.GetNavMesh() != null)
|
2023-07-03 17:04:14 +03:00
|
|
|
{
|
2023-08-01 17:32:28 +03:00
|
|
|
hit = DtNavMeshRaycast.Raycast(_sample.GetNavMesh(), rayStart, rayEnd, out hitTime);
|
2023-07-03 17:04:14 +03:00
|
|
|
}
|
|
|
|
|
2023-08-01 17:32:28 +03:00
|
|
|
if (!hit && _sample.GetRecastResults() != null)
|
2023-07-03 17:04:14 +03:00
|
|
|
{
|
2023-08-01 17:32:28 +03:00
|
|
|
hit = RcPolyMeshRaycast.Raycast(_sample.GetRecastResults(), rayStart, rayEnd, out hitTime);
|
2023-07-03 17:04:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
RcVec3f rayDir = RcVec3f.Of(rayEnd.x - rayStart.x, rayEnd.y - rayStart.y, rayEnd.z - rayStart.z);
|
2023-08-20 07:19:47 +03:00
|
|
|
ISampleTool raySampleTool = toolset.GetTool();
|
2023-07-03 17:04:14 +03:00
|
|
|
rayDir.Normalize();
|
2023-08-20 07:19:47 +03:00
|
|
|
if (raySampleTool != null)
|
2023-07-03 17:04:14 +03:00
|
|
|
{
|
2023-08-20 07:19:47 +03:00
|
|
|
Logger.Information($"click ray - tool({raySampleTool.GetTool().GetName()}) rayStart({rayStart.x:0.#},{rayStart.y:0.#},{rayStart.z:0.#}) pos({rayDir.x:0.#},{rayDir.y:0.#},{rayDir.z:0.#}) shift({processHitTestShift})");
|
|
|
|
raySampleTool.HandleClickRay(rayStart, rayDir, processHitTestShift);
|
2023-07-03 17:04:14 +03:00
|
|
|
}
|
|
|
|
|
2023-08-01 17:32:28 +03:00
|
|
|
if (hit)
|
2023-07-03 17:04:14 +03:00
|
|
|
{
|
|
|
|
if (0 != (_modState & KeyModState.Control))
|
|
|
|
{
|
|
|
|
// Marker
|
|
|
|
markerPositionSet = true;
|
|
|
|
markerPosition.x = rayStart.x + (rayEnd.x - rayStart.x) * hitTime;
|
|
|
|
markerPosition.y = rayStart.y + (rayEnd.y - rayStart.y) * hitTime;
|
|
|
|
markerPosition.z = rayStart.z + (rayEnd.z - rayStart.z) * hitTime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RcVec3f pos = new RcVec3f();
|
|
|
|
pos.x = rayStart.x + (rayEnd.x - rayStart.x) * hitTime;
|
|
|
|
pos.y = rayStart.y + (rayEnd.y - rayStart.y) * hitTime;
|
|
|
|
pos.z = rayStart.z + (rayEnd.z - rayStart.z) * hitTime;
|
2023-08-20 07:19:47 +03:00
|
|
|
if (raySampleTool != null)
|
2023-07-03 17:04:14 +03:00
|
|
|
{
|
2023-08-20 07:19:47 +03:00
|
|
|
Logger.Information($"click - tool({raySampleTool.GetTool().GetName()}) rayStart({rayStart.x:0.#},{rayStart.y:0.#},{rayStart.z:0.#}) pos({pos.x:0.#},{pos.y:0.#},{pos.z:0.#}) shift({processHitTestShift})");
|
|
|
|
raySampleTool.HandleClick(rayStart, pos, processHitTestShift);
|
2023-07-03 17:04:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (0 != (_modState & KeyModState.Control))
|
|
|
|
{
|
|
|
|
// Marker
|
|
|
|
markerPositionSet = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-25 17:12:23 +03:00
|
|
|
}
|