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;
|
|
|
|
using DotRecast.Recast.Demo.Builder;
|
|
|
|
using DotRecast.Recast.Demo.Draw;
|
|
|
|
using DotRecast.Recast.Demo.Geom;
|
|
|
|
using DotRecast.Recast.Demo.Settings;
|
|
|
|
using DotRecast.Recast.Demo.Tools;
|
|
|
|
using DotRecast.Recast.Demo.UI;
|
2023-03-25 09:43:20 +03:00
|
|
|
using static DotRecast.Core.RecastMath;
|
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 17:56:10 +03:00
|
|
|
private RcViewSystem _viewSys;
|
2023-03-14 08:02:43 +03:00
|
|
|
private IWindow window;
|
|
|
|
private IInputContext _input;
|
|
|
|
private ImGuiController _imgui;
|
|
|
|
private GL _gl;
|
|
|
|
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;
|
|
|
|
private int modState;
|
|
|
|
|
|
|
|
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-03-29 18:59:00 +03:00
|
|
|
private Vector3f origCameraPos = new Vector3f();
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
private readonly float[] cameraEulers = { 45, -45 };
|
2023-03-29 18:59:00 +03:00
|
|
|
private Vector3f cameraPos = Vector3f.Of(0, 0, 0);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-30 19:10:04 +03:00
|
|
|
private Vector3f rayStart = new Vector3f();
|
|
|
|
private Vector3f rayEnd = new Vector3f();
|
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-03-30 19:10:04 +03:00
|
|
|
private Vector3f markerPosition = new Vector3f();
|
2023-03-18 18:09:36 +03:00
|
|
|
private ToolsView toolsUI;
|
|
|
|
private RcSettingsView settingsUI;
|
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()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
public void start()
|
|
|
|
{
|
|
|
|
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-03-19 17:16:41 +03:00
|
|
|
float[] modelviewMatrix = dd.viewMatrix(cameraPos, cameraEulers);
|
|
|
|
cameraPos[0] += scrollZoom * 2.0f * modelviewMatrix[2];
|
|
|
|
cameraPos[1] += scrollZoom * 2.0f * modelviewMatrix[6];
|
|
|
|
cameraPos[2] += 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)
|
|
|
|
{
|
|
|
|
float[] modelviewMatrix = dd.viewMatrix(cameraPos, cameraEulers);
|
|
|
|
cameraPos[0] = origCameraPos[0];
|
|
|
|
cameraPos[1] = origCameraPos[1];
|
|
|
|
cameraPos[2] = origCameraPos[2];
|
|
|
|
|
|
|
|
cameraPos[0] -= 0.1f * dx * modelviewMatrix[0];
|
|
|
|
cameraPos[1] -= 0.1f * dx * modelviewMatrix[4];
|
|
|
|
cameraPos[2] -= 0.1f * dx * modelviewMatrix[8];
|
|
|
|
|
|
|
|
cameraPos[0] += 0.1f * dy * modelviewMatrix[1];
|
|
|
|
cameraPos[1] += 0.1f * dy * modelviewMatrix[5];
|
|
|
|
cameraPos[2] += 0.1f * dy * modelviewMatrix[9];
|
|
|
|
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
|
|
|
{
|
2023-03-19 17:16:41 +03:00
|
|
|
modState = 0;
|
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];
|
|
|
|
origCameraPos[0] = cameraPos[0];
|
|
|
|
origCameraPos[1] = cameraPos[1];
|
|
|
|
origCameraPos[2] = cameraPos[2];
|
|
|
|
}
|
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;
|
|
|
|
//processHitTestShift = (mods & Keys.GLFW_MOD_SHIFT) != 0 ? true : false;
|
|
|
|
//processHitTestShift = (mods & Keys.) != 0 ? true : false;
|
|
|
|
}
|
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();
|
|
|
|
// // if (monitors.limit() > 1) {
|
|
|
|
// // monitor = monitors[1];
|
|
|
|
// // }
|
|
|
|
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-03-14 19:34:31 +03:00
|
|
|
options.VSync = false;
|
|
|
|
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-03-14 08:02:43 +03:00
|
|
|
window.Update += OnWindowOnUpdate;
|
|
|
|
window.Render += OnWindowOnRender;
|
|
|
|
|
|
|
|
|
|
|
|
// // -- move somewhere else:
|
|
|
|
// glfw.SetWindowPos(window, (mode->Width - width) / 2, (mode->Height - height) / 2);
|
|
|
|
// // glfwSetWindowMonitor(window.getWindow(), monitor, 0, 0, mode.width(), mode.height(), mode.refreshRate());
|
|
|
|
// glfw.ShowWindow(window);
|
|
|
|
// glfw.MakeContextCurrent(window);
|
|
|
|
//}
|
|
|
|
|
|
|
|
//glfw.SwapInterval(1);
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
private DemoInputGeomProvider loadInputMesh(byte[] stream)
|
|
|
|
{
|
|
|
|
DemoInputGeomProvider geom = DemoObjImporter.load(stream);
|
2023-03-18 18:09:36 +03:00
|
|
|
sample = new Sample(geom, ImmutableArray<RecastBuilderResult>.Empty, null, settingsUI, dd);
|
|
|
|
toolsUI.setEnabled(true);
|
2023-03-14 08:02:43 +03:00
|
|
|
return geom;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadNavMesh(FileStream file, string filename)
|
|
|
|
{
|
|
|
|
NavMesh mesh = null;
|
|
|
|
if (filename.EndsWith(".zip") || filename.EndsWith(".bytes"))
|
|
|
|
{
|
|
|
|
UnityAStarPathfindingImporter importer = new UnityAStarPathfindingImporter();
|
|
|
|
mesh = importer.load(file)[0];
|
|
|
|
}
|
|
|
|
else if (filename.EndsWith(".bin") || filename.EndsWith(".navmesh"))
|
|
|
|
{
|
|
|
|
MeshSetReader reader = new MeshSetReader();
|
|
|
|
using (var fis = new BinaryReader(file))
|
|
|
|
{
|
|
|
|
mesh = reader.read(fis, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mesh != null)
|
|
|
|
{
|
|
|
|
//sample = new Sample(null, ImmutableArray<RecastBuilderResult>.Empty, mesh, settingsUI, dd);
|
2023-03-18 18:09:36 +03:00
|
|
|
toolsUI.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-22 18:03:32 +03:00
|
|
|
|
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-03-18 22:36:31 +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);
|
|
|
|
|
|
|
|
|
|
|
|
// // if (capabilities.OpenGL43) {
|
|
|
|
// // GL43.glDebugMessageControl(GL43.GL_DEBUG_SOURCE_API, GL43.GL_DEBUG_TYPE_OTHER,
|
|
|
|
// // GL43.GL_DEBUG_SEVERITY_NOTIFICATION,
|
|
|
|
// // (int[]) null, false);
|
|
|
|
// // } else if (capabilities.GL_ARB_debug_output) {
|
|
|
|
// // ARBDebugOutput.glDebugMessageControlARB(ARBDebugOutput.GL_DEBUG_SOURCE_API_ARB,
|
|
|
|
// // ARBDebugOutput.GL_DEBUG_TYPE_OTHER_ARB, ARBDebugOutput.GL_DEBUG_SEVERITY_LOW_ARB, (int[]) null, false);
|
|
|
|
// // }
|
|
|
|
var vendor = _gl.GetStringS(GLEnum.Vendor);
|
2023-03-18 22:36:31 +03:00
|
|
|
Logger.Debug(vendor);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
var version = _gl.GetStringS(GLEnum.Version);
|
2023-03-18 22:36:31 +03:00
|
|
|
Logger.Debug(version);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
var renderGl = _gl.GetStringS(GLEnum.Renderer);
|
2023-03-18 22:36:31 +03:00
|
|
|
Logger.Debug(renderGl);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
|
2023-03-18 22:36:31 +03:00
|
|
|
Logger.Debug(glslString);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
settingsUI = new RcSettingsView();
|
|
|
|
toolsUI = new ToolsView(
|
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()
|
|
|
|
);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
_viewSys = new RcViewSystem(window, _input, settingsUI, toolsUI);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
DemoInputGeomProvider geom = loadInputMesh(Loader.ToBytes("nav_test.obj"));
|
2023-03-18 18:09:36 +03:00
|
|
|
sample = new Sample(geom, ImmutableArray<RecastBuilderResult>.Empty, null, settingsUI, dd);
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-03-22 18:03:32 +03:00
|
|
|
private void UpdateKeyboard(float dt)
|
|
|
|
{
|
|
|
|
// 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-03-22 18:03:32 +03:00
|
|
|
|
2023-03-25 16:02:44 +03:00
|
|
|
modState = keyboard.IsKeyPressed(Key.ControlLeft) || keyboard.IsKeyPressed(Key.ShiftRight) ? 1 : 0;
|
|
|
|
_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-03-14 08:02:43 +03:00
|
|
|
private void OnWindowOnUpdate(double dt)
|
|
|
|
{
|
|
|
|
/*
|
2023-03-18 18:09:36 +03:00
|
|
|
* try (MemoryStack stack = stackPush()) { int[] w = stack.mallocInt(1); int[] h =
|
|
|
|
* stack.mallocInt(1); glfwGetWindowSize(win, w, h); width = w[0]; height = h[0]; }
|
|
|
|
*/
|
2023-03-22 18:03:32 +03:00
|
|
|
if (sample.getInputGeom() != null)
|
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
Vector3f bmin = sample.getInputGeom().getMeshBoundsMin();
|
|
|
|
Vector3f bmax = sample.getInputGeom().getMeshBoundsMax();
|
2023-03-22 18:03:32 +03:00
|
|
|
int[] voxels = Recast.calcGridSize(bmin, bmax, settingsUI.getCellSize());
|
|
|
|
settingsUI.setVoxels(voxels);
|
|
|
|
settingsUI.setTiles(tileNavMeshBuilder.getTiles(sample.getInputGeom(), settingsUI.getCellSize(), settingsUI.getTileSize()));
|
|
|
|
settingsUI.setMaxTiles(tileNavMeshBuilder.getMaxTiles(sample.getInputGeom(), settingsUI.getCellSize(), settingsUI.getTileSize()));
|
|
|
|
settingsUI.setMaxPolys(tileNavMeshBuilder.getMaxPolysPerTile(sample.getInputGeom(), settingsUI.getCellSize(), settingsUI.getTileSize()));
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
cameraPos[0] += (float)(movex * modelviewMatrix[0]);
|
|
|
|
cameraPos[1] += (float)(movex * modelviewMatrix[4]);
|
|
|
|
cameraPos[2] += (float)(movex * modelviewMatrix[8]);
|
|
|
|
|
|
|
|
cameraPos[0] += (float)(movey * modelviewMatrix[2]);
|
|
|
|
cameraPos[1] += (float)(movey * modelviewMatrix[6]);
|
|
|
|
cameraPos[2] += (float)(movey * modelviewMatrix[10]);
|
|
|
|
|
|
|
|
cameraPos[1] += (float)((_moveUp - _moveDown) * keySpeed * dt);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-04-14 16:41:29 +03:00
|
|
|
long time = FrequencyWatch.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;
|
|
|
|
timeAcc = clamp((float)(timeAcc + dt), -1.0f, 1.0f);
|
|
|
|
int simIter = 0;
|
|
|
|
while (timeAcc > DELTA_TIME)
|
|
|
|
{
|
|
|
|
timeAcc -= DELTA_TIME;
|
|
|
|
if (simIter < 5 && sample != null)
|
|
|
|
{
|
2023-03-26 07:13:51 +03:00
|
|
|
toolsUI.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-03-25 06:17:09 +03:00
|
|
|
if (settingsUI.isMeshInputTrigerred())
|
|
|
|
{
|
|
|
|
var bytes = Loader.ToBytes(settingsUI.GetMeshInputFilePath());
|
|
|
|
sample.update(loadInputMesh(bytes), null, null);
|
|
|
|
}
|
2023-03-25 16:02:44 +03:00
|
|
|
|
2023-03-18 22:36:31 +03:00
|
|
|
// else if (settingsUI.isNavMeshInputTrigerred())
|
|
|
|
// {
|
2023-03-19 17:16:41 +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-03-18 22:36:31 +03:00
|
|
|
// }
|
2023-03-22 18:03:32 +03:00
|
|
|
if (settingsUI.isBuildTriggered() && sample.getInputGeom() != null)
|
|
|
|
{
|
|
|
|
if (!building)
|
|
|
|
{
|
|
|
|
float m_cellSize = settingsUI.getCellSize();
|
|
|
|
float m_cellHeight = settingsUI.getCellHeight();
|
|
|
|
float m_agentHeight = settingsUI.getAgentHeight();
|
|
|
|
float m_agentRadius = settingsUI.getAgentRadius();
|
|
|
|
float m_agentMaxClimb = settingsUI.getAgentMaxClimb();
|
|
|
|
float m_agentMaxSlope = settingsUI.getAgentMaxSlope();
|
|
|
|
int m_regionMinSize = settingsUI.getMinRegionSize();
|
|
|
|
int m_regionMergeSize = settingsUI.getMergedRegionSize();
|
|
|
|
float m_edgeMaxLen = settingsUI.getEdgeMaxLen();
|
|
|
|
float m_edgeMaxError = settingsUI.getEdgeMaxError();
|
|
|
|
int m_vertsPerPoly = settingsUI.getVertsPerPoly();
|
|
|
|
float m_detailSampleDist = settingsUI.getDetailSampleDist();
|
|
|
|
float m_detailSampleMaxError = settingsUI.getDetailSampleMaxError();
|
|
|
|
int m_tileSize = settingsUI.getTileSize();
|
2023-04-14 16:41:29 +03:00
|
|
|
long t = FrequencyWatch.Ticks;
|
2023-03-22 18:03:32 +03:00
|
|
|
|
|
|
|
Tuple<IList<RecastBuilderResult>, NavMesh> buildResult;
|
|
|
|
if (settingsUI.isTiled())
|
|
|
|
{
|
|
|
|
buildResult = tileNavMeshBuilder.build(sample.getInputGeom(), settingsUI.getPartitioning(), m_cellSize,
|
|
|
|
m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize,
|
|
|
|
m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
|
|
|
|
m_detailSampleMaxError, settingsUI.isFilterLowHangingObstacles(), settingsUI.isFilterLedgeSpans(),
|
|
|
|
settingsUI.isFilterWalkableLowHeightSpans(), m_tileSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buildResult = soloNavMeshBuilder.build(sample.getInputGeom(), settingsUI.getPartitioning(), m_cellSize,
|
|
|
|
m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize,
|
|
|
|
m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
|
|
|
|
m_detailSampleMaxError, settingsUI.isFilterLowHangingObstacles(), settingsUI.isFilterLedgeSpans(),
|
|
|
|
settingsUI.isFilterWalkableLowHeightSpans());
|
|
|
|
}
|
|
|
|
|
|
|
|
sample.update(sample.getInputGeom(), buildResult.Item1, buildResult.Item2);
|
|
|
|
sample.setChanged(false);
|
2023-04-14 16:41:29 +03:00
|
|
|
settingsUI.setBuildTime((FrequencyWatch.Ticks - t) / TimeSpan.TicksPerMillisecond);
|
2023-03-25 07:23:25 +03:00
|
|
|
settingsUI.setBuildTelemetry(buildResult.Item1.Select(x => x.getTelemetry()).ToList());
|
2023-03-22 18:03:32 +03:00
|
|
|
toolsUI.setSample(sample);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
building = false;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-25 16:02:44 +03:00
|
|
|
if (!_mouseOverMenu)
|
|
|
|
{
|
2023-03-30 19:10:04 +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.
|
|
|
|
DemoInputGeomProvider inputGeom = sample.getInputGeom();
|
|
|
|
if (processHitTest && sample != null)
|
|
|
|
{
|
|
|
|
float? hit = null;
|
|
|
|
if (inputGeom != null)
|
|
|
|
{
|
|
|
|
hit = inputGeom.raycastMesh(rayStart, rayEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hit.HasValue && sample.getNavMesh() != null)
|
|
|
|
{
|
|
|
|
hit = NavMeshRaycast.raycast(sample.getNavMesh(), rayStart, rayEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hit.HasValue && sample.getRecastResults() != null)
|
|
|
|
{
|
|
|
|
hit = PolyMeshRaycast.raycast(sample.getRecastResults(), rayStart, rayEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
float[] rayDir = new float[] { rayEnd[0] - rayStart[0], rayEnd[1] - rayStart[1], rayEnd[2] - rayStart[2] };
|
|
|
|
Tool rayTool = toolsUI.getTool();
|
|
|
|
vNormalize(rayDir);
|
|
|
|
if (rayTool != null)
|
|
|
|
{
|
|
|
|
rayTool.handleClickRay(rayStart, rayDir, processHitTestShift);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hit.HasValue)
|
|
|
|
{
|
|
|
|
float hitTime = hit.Value;
|
|
|
|
if (0 != modState)
|
|
|
|
{
|
|
|
|
// Marker
|
|
|
|
markerPositionSet = true;
|
|
|
|
markerPosition[0] = rayStart[0] + (rayEnd[0] - rayStart[0]) * hitTime;
|
|
|
|
markerPosition[1] = rayStart[1] + (rayEnd[1] - rayStart[1]) * hitTime;
|
|
|
|
markerPosition[2] = rayStart[2] + (rayEnd[2] - rayStart[2]) * hitTime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-03-28 18:03:33 +03:00
|
|
|
Vector3f pos = new Vector3f();
|
2023-03-25 16:02:44 +03:00
|
|
|
pos[0] = rayStart[0] + (rayEnd[0] - rayStart[0]) * hitTime;
|
|
|
|
pos[1] = rayStart[1] + (rayEnd[1] - rayStart[1]) * hitTime;
|
|
|
|
pos[2] = rayStart[2] + (rayEnd[2] - rayStart[2]) * hitTime;
|
|
|
|
if (rayTool != null)
|
|
|
|
{
|
|
|
|
rayTool.handleClick(rayStart, pos, processHitTestShift);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (0 != modState)
|
|
|
|
{
|
|
|
|
// Marker
|
|
|
|
markerPositionSet = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
processHitTest = false;
|
|
|
|
}
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
if (sample.isChanged())
|
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
Vector3f? bminN = null;
|
|
|
|
Vector3f? bmaxN = null;
|
2023-03-18 18:09:36 +03:00
|
|
|
if (sample.getInputGeom() != null)
|
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
bminN = sample.getInputGeom().getMeshBoundsMin();
|
|
|
|
bmaxN = sample.getInputGeom().getMeshBoundsMax();
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
|
|
|
else if (sample.getNavMesh() != null)
|
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
Vector3f[] bounds = NavMeshUtils.getNavMeshBounds(sample.getNavMesh());
|
|
|
|
bminN = bounds[0];
|
|
|
|
bmaxN = bounds[1];
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
|
|
|
else if (0 < sample.getRecastResults().Count)
|
|
|
|
{
|
|
|
|
foreach (RecastBuilderResult result in sample.getRecastResults())
|
|
|
|
{
|
|
|
|
if (result.getSolidHeightfield() != null)
|
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
if (bminN == null)
|
2023-03-18 18:09:36 +03:00
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
bminN = Vector3f.Of(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
|
|
|
bmaxN = Vector3f.Of(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
|
2023-03-18 18:09:36 +03:00
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-04-06 12:43:31 +03:00
|
|
|
bminN = Vector3f.Of(
|
|
|
|
Math.Min(bminN.Value[0], result.getSolidHeightfield().bmin[0]),
|
|
|
|
Math.Min(bminN.Value[1], result.getSolidHeightfield().bmin[1]),
|
|
|
|
Math.Min(bminN.Value[2], result.getSolidHeightfield().bmin[2])
|
|
|
|
);
|
|
|
|
|
|
|
|
bmaxN = Vector3f.Of(
|
|
|
|
Math.Max(bmaxN.Value[0], result.getSolidHeightfield().bmax[0]),
|
|
|
|
Math.Max(bmaxN.Value[1], result.getSolidHeightfield().bmax[1]),
|
|
|
|
Math.Max(bmaxN.Value[2], result.getSolidHeightfield().bmax[2])
|
|
|
|
);
|
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
|
|
|
{
|
2023-03-30 19:10:04 +03:00
|
|
|
Vector3f bmin = bminN.Value;
|
|
|
|
Vector3f bmax = bmaxN.Value;
|
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
camr = (float)(Math.Sqrt(
|
2023-03-25 16:02:44 +03:00
|
|
|
sqr(bmax[0] - bmin[0]) + sqr(bmax[1] - bmin[1]) + sqr(bmax[2] - bmin[2]))
|
2023-03-18 18:09:36 +03:00
|
|
|
/ 2);
|
|
|
|
cameraPos[0] = (bmax[0] + bmin[0]) / 2 + camr;
|
|
|
|
cameraPos[1] = (bmax[1] + bmin[1]) / 2 + camr;
|
|
|
|
cameraPos[2] = (bmax[2] + bmin[2]) / 2 + camr;
|
|
|
|
camr *= 3;
|
|
|
|
cameraEulers[0] = 45;
|
|
|
|
cameraEulers[1] = -45;
|
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
sample.setChanged(false);
|
|
|
|
toolsUI.setSample(sample);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
//window.DoEvents();
|
2023-03-14 08:02:43 +03:00
|
|
|
_imgui.Update((float)dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
private unsafe void OnWindowOnRender(double dt)
|
|
|
|
{
|
2023-03-18 18:09:36 +03:00
|
|
|
// _gl.ClearColor(Color.CadetBlue);
|
|
|
|
// _gl.Clear(ClearBufferMask.ColorBufferBit);
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
// Set the viewport.
|
|
|
|
// glViewport(0, 0, width, height);
|
|
|
|
//_gl.Viewport(0, 0, (uint)width, (uint)height);
|
2023-03-25 16:02:44 +03:00
|
|
|
//viewport = new int[] { 0, 0, width, height };
|
2023-03-18 18:09:36 +03:00
|
|
|
// glGetIntegerv(GL_VIEWPORT, viewport);
|
|
|
|
|
|
|
|
// Clear the screen
|
|
|
|
dd.clear();
|
2023-03-22 18:03:32 +03:00
|
|
|
projectionMatrix = dd.projectionMatrix(50f, (float)width / (float)height, 1.0f, camr);
|
|
|
|
modelviewMatrix = dd.viewMatrix(cameraPos, cameraEulers);
|
2023-03-18 18:09:36 +03:00
|
|
|
|
|
|
|
dd.fog(camr * 0.1f, camr * 1.25f);
|
|
|
|
renderer.render(sample);
|
2023-03-19 16:47:34 +03:00
|
|
|
Tool tool = toolsUI.getTool();
|
|
|
|
if (tool != null)
|
|
|
|
{
|
|
|
|
tool.handleRender(renderer);
|
|
|
|
}
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-03-18 18:09:36 +03:00
|
|
|
dd.fog(false);
|
2023-03-19 17:16:41 +03:00
|
|
|
|
2023-03-22 18:29:25 +03:00
|
|
|
_viewSys.Draw();
|
|
|
|
_mouseOverMenu = _viewSys.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-03-14 17:56:10 +03:00
|
|
|
private void ErrorCallback(Silk.NET.GLFW.ErrorCode code, string message)
|
2023-03-14 08:02:43 +03:00
|
|
|
{
|
|
|
|
Console.WriteLine($"GLFW error [{code}]: {message}");
|
|
|
|
}
|
|
|
|
}
|