DotRecastNetSim/src/DotRecast.Recast.Demo/RecastDemo.cs

790 lines
28 KiB
C#
Raw Normal View History

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-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-06-07 17:19:25 +03:00
using DotRecast.Recast.DemoTool.Builder;
2023-03-14 08:02:43 +03:00
using DotRecast.Recast.Demo.Draw;
2023-06-07 17:19:25 +03:00
using DotRecast.Recast.DemoTool.Geom;
2023-03-14 08:02:43 +03:00
using DotRecast.Recast.Demo.Tools;
using DotRecast.Recast.Demo.UI;
2023-06-07 17:35:40 +03:00
using DotRecast.Recast.DemoTool;
2023-05-10 16:44:51 +03:00
using static DotRecast.Core.RcMath;
2023-03-14 08:02:43 +03:00
using Window = Silk.NET.Windowing.Window;
namespace DotRecast.Recast.Demo;
2023-03-19 17:16:41 +03:00
public class RecastDemo
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 bool building = false;
private float timeAcc = 0;
private float camr = 1000;
private readonly SoloNavMeshBuilder soloNavMeshBuilder = new SoloNavMeshBuilder();
private readonly TileNavMeshBuilder tileNavMeshBuilder = new TileNavMeshBuilder();
2023-03-18 18:09:36 +03:00
private Sample 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];
private RcVec3f origCameraPos = new RcVec3f();
2023-03-14 08:02:43 +03:00
private readonly float[] cameraEulers = { 45, -45 };
private RcVec3f cameraPos = RcVec3f.Of(0, 0, 0);
2023-03-14 08:02:43 +03:00
private RcVec3f rayStart = new RcVec3f();
private RcVec3f rayEnd = new RcVec3f();
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;
private RcVec3f markerPosition = new RcVec3f();
2023-04-17 18:12:28 +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-03-14 08:02:43 +03:00
public RecastDemo()
{
}
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-05-05 02:44:48 +03:00
float[] modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
2023-04-29 07:24:26 +03:00
cameraPos.x += scrollZoom * 2.0f * modelviewMatrix[2];
cameraPos.y += scrollZoom * 2.0f * modelviewMatrix[6];
cameraPos.z += scrollZoom * 2.0f * modelviewMatrix[10];
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-05-05 02:44:48 +03:00
float[] modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
2023-04-29 07:24:26 +03:00
cameraPos.x = origCameraPos.x;
cameraPos.y = origCameraPos.y;
cameraPos.z = origCameraPos.z;
2023-03-19 17:16:41 +03:00
2023-04-29 07:24:26 +03:00
cameraPos.x -= 0.1f * dx * modelviewMatrix[0];
cameraPos.y -= 0.1f * dx * modelviewMatrix[4];
cameraPos.z -= 0.1f * dx * modelviewMatrix[8];
2023-03-19 17:16:41 +03:00
2023-04-29 07:24:26 +03:00
cameraPos.x += 0.1f * dy * modelviewMatrix[1];
cameraPos.y += 0.1f * dy * modelviewMatrix[5];
cameraPos.z += 0.1f * dy * modelviewMatrix[9];
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-13 18:00:45 +03:00
processHitTestShift = _modState != 0 ? true : false;
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-05-05 02:44:48 +03:00
private DemoInputGeomProvider LoadInputMesh(byte[] stream)
2023-03-14 08:02:43 +03:00
{
2023-05-05 02:44:48 +03:00
DemoInputGeomProvider geom = DemoObjImporter.Load(stream);
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
{
DtNavMesh mesh = null;
2023-03-14 08:02:43 +03:00
if (filename.EndsWith(".zip") || filename.EndsWith(".bytes"))
{
UnityAStarPathfindingImporter importer = new UnityAStarPathfindingImporter();
2023-05-05 02:44:48 +03:00
mesh = importer.Load(file)[0];
2023-03-14 08:02:43 +03:00
}
else if (filename.EndsWith(".bin") || filename.EndsWith(".navmesh"))
{
DtMeshSetReader reader = new DtMeshSetReader();
2023-03-14 08:02:43 +03:00
using (var fis = new BinaryReader(file))
{
2023-05-05 02:44:48 +03:00
mesh = reader.Read(fis, 6);
2023-03-14 08:02:43 +03:00
}
}
if (mesh != null)
{
//sample = new Sample(null, ImmutableArray<RecastBuilderResult>.Empty, mesh, settingsUI, dd);
toolset.SetEnabled(true);
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-03-14 08:02:43 +03:00
_imgui = new ImGuiController(_gl, window, _input);
2023-04-17 18:12:28 +03:00
DemoInputGeomProvider geom = LoadInputMesh(Loader.ToBytes("nav_test.obj"));
2023-06-12 18:24:48 +03:00
sample = new Sample(geom, ImmutableArray<RecastBuilderResult>.Empty, null);
2023-06-11 08:58:37 +03:00
settingsView = new RcSettingsView();
settingsView.SetSample(sample);
toolset = new RcToolsetView(
2023-03-14 08:02:43 +03:00
new TestNavmeshTool(),
new OffMeshConnectionTool(),
new ConvexVolumeTool(),
new CrowdTool(),
new JumpLinkBuilderTool(),
2023-03-18 08:05:01 +03:00
new DynamicUpdateTool()
);
toolset.SetEnabled(true);
2023-06-11 08:58:37 +03:00
logView = new RcLogView();
2023-04-16 05:54:50 +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);
var renderGl = _gl.GetStringS(GLEnum.Renderer);
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
2023-04-17 18:12:28 +03:00
2023-06-07 17:19:25 +03:00
var workingDirectory = Directory.GetCurrentDirectory();
Logger.Information($"working directory - {workingDirectory}");
Logger.Information(vendor);
Logger.Information(version);
Logger.Information(renderGl);
Logger.Information(glslString);
2023-03-14 08:02:43 +03:00
}
2023-03-22 18:03:32 +03:00
private void UpdateKeyboard(float dt)
{
_modState = 0;
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;
var tempControl = keyboard.IsKeyPressed(Key.ControlLeft) || keyboard.IsKeyPressed(Key.ControlRight);
2023-03-22 18:03:32 +03:00
_modState |= tempControl || 0 < tempMoveAccel ? 1 : 0;
//Logger.Information($"{_modState}");
2023-05-05 02:44:48 +03:00
_moveFront = Clamp(_moveFront + tempMoveFront * dt * 4.0f, 0, 2.0f);
_moveLeft = Clamp(_moveLeft + tempMoveLeft * dt * 4.0f, 0, 2.0f);
_moveBack = Clamp(_moveBack + tempMoveBack * dt * 4.0f, 0, 2.0f);
_moveRight = Clamp(_moveRight + tempMoveRight * dt * 4.0f, 0, 2.0f);
_moveUp = Clamp(_moveUp + tempMoveUp * dt * 4.0f, 0, 2.0f);
_moveDown = Clamp(_moveDown + tempMoveDown * dt * 4.0f, 0, 2.0f);
_moveAccel = 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-05-05 02:44:48 +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-03-18 18:09:36 +03:00
*/
2023-05-05 02:44:48 +03:00
if (sample.GetInputGeom() != null)
2023-03-22 18:03:32 +03:00
{
var settings = sample.GetSettings();
RcVec3f bmin = sample.GetInputGeom().GetMeshBoundsMin();
RcVec3f bmax = sample.GetInputGeom().GetMeshBoundsMax();
Recast.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
2023-06-11 08:58:37 +03:00
settingsView.SetVoxels(gw, gh);
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-05-05 02:44:48 +03:00
timeAcc = 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;
if (simIter < 5 && sample != null)
{
toolset.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-06-11 08:58:37 +03:00
if (settingsView.IsMeshInputTrigerred())
2023-03-25 06:17:09 +03:00
{
2023-06-11 08:58:37 +03:00
var bytes = Loader.ToBytes(settingsView.GetMeshInputFilePath());
var geom = LoadInputMesh(bytes);
2023-06-12 18:24:48 +03:00
sample.Update(geom, ImmutableArray<RecastBuilderResult>.Empty, null);
2023-03-25 06:17:09 +03:00
}
2023-06-11 08:58:37 +03:00
else if (settingsView.IsNavMeshInputTrigerred())
2023-04-17 18:12:28 +03:00
{
2023-05-25 17:12:23 +03:00
// try (MemoryStack stack = StackPush()) {
// PointerBuffer aFilterPatterns = stack.MallocPointer(4);
// aFilterPatterns.Put(stack.UTF8("*.bin"));
// aFilterPatterns.Put(stack.UTF8("*.zip"));
// aFilterPatterns.Put(stack.UTF8("*.bytes"));
// aFilterPatterns.Put(stack.UTF8("*.navmesh"));
// aFilterPatterns.Flip();
// string filename = TinyFileDialogs.Tinyfd_openFileDialog("Open Nav Mesh File", "", aFilterPatterns,
// "Nav Mesh File", false);
// if (filename != null) {
// File file = new File(filename);
// if (file.Exists()) {
// try {
// LoadNavMesh(file, filename);
// geom = null;
// } catch (Exception e) {
// Console.WriteLine(e);
// }
// }
// }
// }
2023-04-17 18:12:28 +03:00
}
2023-05-25 17:12:23 +03:00
2023-06-11 08:58:37 +03:00
if (settingsView.IsBuildTriggered() && sample.GetInputGeom() != null)
2023-03-22 18:03:32 +03:00
{
if (!building)
{
var settings = sample.GetSettings();
var partitioning = settings.partitioning;
var cellSize = settings.cellSize;
var cellHeight = settings.cellHeight;
var agentHeight = settings.agentHeight;
var agentRadius = settings.agentRadius;
var agentMaxClimb = settings.agentMaxClimb;
var agentMaxSlope = settings.agentMaxSlope;
var regionMinSize = settings.minRegionSize;
var regionMergeSize = settings.mergedRegionSize;
var edgeMaxLen = settings.edgeMaxLen;
var edgeMaxError = settings.edgeMaxError;
var vertsPerPoly = settings.vertsPerPoly;
var detailSampleDist = settings.detailSampleDist;
var detailSampleMaxError = settings.detailSampleMaxError;
var filterLowHangingObstacles = settings.filterLowHangingObstacles;
var filterLedgeSpans = settings.filterLedgeSpans;
var filterWalkableLowHeightSpans = settings.filterWalkableLowHeightSpans;
var tileSize = settings.tileSize;
2023-05-06 05:44:57 +03:00
long t = RcFrequency.Ticks;
2023-04-17 18:12:28 +03:00
2023-04-16 05:54:50 +03:00
Logger.Information($"build");
2023-03-22 18:03:32 +03:00
Tuple<IList<RecastBuilderResult>, DtNavMesh> buildResult;
if (settings.tiled)
2023-03-22 18:03:32 +03:00
{
buildResult = tileNavMeshBuilder.Build(
sample.GetInputGeom(),
partitioning,
cellSize,
cellHeight,
agentHeight,
agentRadius,
agentMaxClimb,
agentMaxSlope,
regionMinSize,
regionMergeSize,
edgeMaxLen,
edgeMaxError,
vertsPerPoly,
detailSampleDist,
detailSampleMaxError,
filterLowHangingObstacles,
filterLedgeSpans,
filterWalkableLowHeightSpans,
tileSize
);
2023-03-22 18:03:32 +03:00
}
else
{
buildResult = soloNavMeshBuilder.Build(
sample.GetInputGeom(),
partitioning,
cellSize,
cellHeight,
agentHeight,
agentRadius,
agentMaxClimb,
agentMaxSlope,
regionMinSize,
regionMergeSize,
edgeMaxLen,
edgeMaxError,
vertsPerPoly,
detailSampleDist,
detailSampleMaxError,
filterLowHangingObstacles,
filterLedgeSpans,
filterWalkableLowHeightSpans
);
2023-03-22 18:03:32 +03:00
}
2023-05-05 02:44:48 +03:00
sample.Update(sample.GetInputGeom(), buildResult.Item1, buildResult.Item2);
sample.SetChanged(false);
2023-06-11 08:58:37 +03:00
settingsView.SetBuildTime((RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond);
2023-05-05 02:44:48 +03:00
//settingsUI.SetBuildTelemetry(buildResult.Item1.Select(x => x.GetTelemetry()).ToList());
toolset.SetSample(sample);
2023-04-17 18:12:28 +03:00
2023-04-16 05:54:50 +03:00
Logger.Information($"build times");
Logger.Information($"-----------------------------------------");
var telemetries = buildResult.Item1
2023-05-05 02:44:48 +03:00
.Select(x => x.GetTelemetry())
2023-04-16 05:54:50 +03:00
.SelectMany(x => x.ToList())
.GroupBy(x => x.Item1)
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Item2));
2023-04-17 18:12:28 +03:00
2023-04-16 05:54:50 +03:00
foreach (var (key, millis) in telemetries)
{
Logger.Information($"{key}: {millis} ms");
}
2023-03-22 18:03:32 +03:00
}
}
else
{
building = false;
}
2023-03-14 08:02:43 +03:00
2023-03-25 16:02:44 +03:00
if (!_mouseOverMenu)
{
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-03-25 16:02:44 +03:00
// Hit test mesh.
2023-05-05 02:44:48 +03:00
DemoInputGeomProvider inputGeom = sample.GetInputGeom();
2023-03-25 16:02:44 +03:00
if (processHitTest && sample != null)
{
float? hit = null;
if (inputGeom != null)
{
2023-05-05 02:44:48 +03:00
hit = inputGeom.RaycastMesh(rayStart, rayEnd);
2023-03-25 16:02:44 +03:00
}
2023-05-05 02:44:48 +03:00
if (!hit.HasValue && sample.GetNavMesh() != null)
2023-03-25 16:02:44 +03:00
{
2023-05-05 02:44:48 +03:00
hit = NavMeshRaycast.Raycast(sample.GetNavMesh(), rayStart, rayEnd);
2023-03-25 16:02:44 +03:00
}
2023-05-05 02:44:48 +03:00
if (!hit.HasValue && sample.GetRecastResults() != null)
2023-03-25 16:02:44 +03:00
{
2023-05-05 02:44:48 +03:00
hit = PolyMeshRaycast.Raycast(sample.GetRecastResults(), rayStart, rayEnd);
2023-03-25 16:02:44 +03:00
}
RcVec3f rayDir = RcVec3f.Of(rayEnd.x - rayStart.x, rayEnd.y - rayStart.y, rayEnd.z - rayStart.z);
IRcTool rayTool = toolset.GetTool();
2023-05-25 17:12:23 +03:00
rayDir.Normalize();
2023-03-25 16:02:44 +03:00
if (rayTool != null)
{
Logger.Information($"click ray - tool({rayTool.GetTool().GetName()}) rayStart({rayStart}) pos({rayDir}) shift({processHitTestShift})");
2023-05-05 02:44:48 +03:00
rayTool.HandleClickRay(rayStart, rayDir, processHitTestShift);
2023-03-25 16:02:44 +03:00
}
if (hit.HasValue)
{
float hitTime = hit.Value;
2023-06-13 18:00:45 +03:00
if (0 != _modState)
2023-03-25 16:02:44 +03:00
{
// Marker
markerPositionSet = true;
2023-04-29 07:24:26 +03:00
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;
2023-03-25 16:02:44 +03:00
}
else
{
RcVec3f pos = new RcVec3f();
2023-04-29 07:24:26 +03:00
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-03-25 16:02:44 +03:00
if (rayTool != null)
{
Logger.Information($"click - tool({rayTool.GetTool().GetName()}) rayStart({rayStart}) pos({pos}) shift({processHitTestShift})");
2023-05-05 02:44:48 +03:00
rayTool.HandleClick(rayStart, pos, processHitTestShift);
2023-03-25 16:02:44 +03:00
}
}
}
else
{
2023-06-13 18:00:45 +03:00
if (0 != _modState)
2023-03-25 16:02:44 +03:00
{
// Marker
markerPositionSet = false;
}
}
}
processHitTest = false;
}
2023-03-14 08:02:43 +03:00
2023-05-05 02:44:48 +03:00
if (sample.IsChanged())
2023-03-18 18:09:36 +03:00
{
RcVec3f? bminN = null;
RcVec3f? bmaxN = null;
2023-05-05 02:44:48 +03:00
if (sample.GetInputGeom() != null)
2023-03-18 18:09:36 +03:00
{
2023-05-05 02:44:48 +03:00
bminN = sample.GetInputGeom().GetMeshBoundsMin();
bmaxN = sample.GetInputGeom().GetMeshBoundsMax();
2023-03-18 18:09:36 +03:00
}
2023-05-05 02:44:48 +03:00
else if (sample.GetNavMesh() != null)
2023-03-18 18:09:36 +03:00
{
RcVec3f[] bounds = NavMeshUtils.GetNavMeshBounds(sample.GetNavMesh());
2023-03-30 19:10:04 +03:00
bminN = bounds[0];
bmaxN = bounds[1];
2023-03-18 18:09:36 +03:00
}
2023-05-05 02:44:48 +03:00
else if (0 < sample.GetRecastResults().Count)
2023-03-18 18:09:36 +03:00
{
2023-05-05 02:44:48 +03:00
foreach (RecastBuilderResult 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-03-30 19:10:04 +03:00
if (bminN == null)
2023-03-18 18:09:36 +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
bminN = RcVec3f.Of(
2023-05-05 02:44:48 +03:00
Math.Min(bminN.Value.x, result.GetSolidHeightfield().bmin.x),
Math.Min(bminN.Value.y, result.GetSolidHeightfield().bmin.y),
Math.Min(bminN.Value.z, result.GetSolidHeightfield().bmin.z)
2023-04-06 12:43:31 +03:00
);
bmaxN = RcVec3f.Of(
2023-05-05 02:44:48 +03:00
Math.Max(bmaxN.Value.x, result.GetSolidHeightfield().bmax.x),
Math.Max(bmaxN.Value.y, result.GetSolidHeightfield().bmax.y),
Math.Max(bmaxN.Value.z, result.GetSolidHeightfield().bmax.z)
2023-04-06 12:43:31 +03:00
);
2023-03-18 18:09:36 +03:00
}
}
}
2023-03-19 17:16:41 +03:00
2023-03-30 19:10:04 +03:00
if (bminN != null && bmaxN != null)
2023-03-18 18:09:36 +03:00
{
RcVec3f bmin = bminN.Value;
RcVec3f bmax = bmaxN.Value;
2023-03-30 19:10:04 +03:00
2023-03-18 18:09:36 +03:00
camr = (float)(Math.Sqrt(
2023-05-05 02:44:48 +03:00
Sqr(bmax.x - bmin.x) + Sqr(bmax.y - bmin.y) + Sqr(bmax.z - bmin.z))
2023-03-18 18:09:36 +03:00
/ 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-03-18 18:09:36 +03:00
camr *= 3;
cameraEulers[0] = 45;
cameraEulers[1] = -45;
}
2023-03-19 17:16:41 +03:00
2023-05-05 02:44:48 +03:00
sample.SetChanged(false);
toolset.SetSample(sample);
2023-03-18 18:09:36 +03:00
}
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();
projectionMatrix = dd.ProjectionMatrix(50f, (float)width / (float)height, 1.0f, camr);
modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
2023-03-18 18:09:36 +03:00
2023-05-05 02:44:48 +03:00
dd.Fog(camr * 0.1f, camr * 1.25f);
renderer.Render(sample, settingsView.GetDrawMode());
IRcTool tool = toolset.GetTool();
2023-03-19 16:47:34 +03:00
if (tool != null)
{
2023-05-05 02:44:48 +03:00
tool.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);
_mouseOverMenu = _canvas.IsMouseOverUI();
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-05-25 17:12:23 +03:00
}