/// <summary> /// This function is useful if you want to test some parameters /// </summary> private static void StressTests() { log.Debug($"{LosTreeType.createdNodes} tree nodes"); var reg = WorldMgr.GetRegion(201); // just warm the hot path var stats = new RaycastStats(); var objects = reg.Objects.Where(o => o != null).ToList(); foreach (var o1 in objects.Take(1000)) { foreach (var o2 in objects.Skip(1000).Take(1000)) { GetCollisionDistance(o1.CurrentRegion, o1.Position, o2.Position, ref stats); } } var sw = new Stopwatch(); sw.Start(); stats = new RaycastStats(); foreach (var o1 in objects) { foreach (var o2 in objects) { GetCollisionDistance(o1.CurrentRegion, o1.Position, o2.Position, ref stats); } } sw.Stop(); long count = objects.Count * objects.Count; var raySeconds = stats.nbTests * 1000 / sw.ElapsedMilliseconds; log.Debug($"tests {count:N0} tests ({stats.nbTests:N0} ray, {stats.nbNodeTests:N0} node, {stats.nbAABBTests:N0} aabb, {stats.nbFaceTests:N0} face) in {sw.ElapsedMilliseconds} ms (~{count:N0} tests/s ~{raySeconds:N0} r/s)"); reg = WorldMgr.GetRegion(51); objects = reg.Objects.Where(o => o != null && (o.CurrentZone.ID == 51 || o.CurrentZone.ID == 52)).ToList(); sw.Reset(); sw.Start(); stats = new RaycastStats(); foreach (var o1 in objects) { foreach (var o2 in objects) { GetCollisionDistance(o1.CurrentRegion, o1.Position, o2.Position, ref stats); } } sw.Stop(); count = objects.Count * objects.Count; raySeconds = stats.nbTests * 1000 / sw.ElapsedMilliseconds; log.Debug($"tests {count:N0} tests ({stats.nbTests:N0} ray, {stats.nbNodeTests:N0} node, {stats.nbAABBTests:N0} aabb, {stats.nbFaceTests:N0} face) in {sw.ElapsedMilliseconds} ms (~{count:N0} tests/s ~{raySeconds:N0} r/s)"); // stop to read the logs Console.ReadKey(); }
public void Render() { try { if (_renderDebugOverlay) { DebugOverlay.Render(GameViews.Primary); } if (_renderObjectTree) { new DebugObjectGraph().Render(); } if (_renderRaycastStats) { RaycastStats.Render(); } RenderMainMenuBar(out var height); // Disable mouse scrolling when the mouse is on the debug UI if (GameViews.Primary is GameView gameView) { gameView.IsMouseScrollingEnabled = height <= 0; } ObjectEditors.Render(); ActionsDebugUi.Render(); Tig.Console.Render(height); } catch (Exception e) { if (!ErrorReporting.ReportException(e)) { throw; } } ErrorReportingUi.Render(); ImGui.Render(); var drawData = ImGui.GetDrawData(); _renderer.ImGui_ImplDX11_RenderDrawLists(drawData); }
public async void OnCommand(GameClient client, string[] args) { if (client.Player?.TargetObject == null && client.Player?.GroundTarget == null) { DisplayMessage(client, "You need a target to use this command."); return; } var text = new List <string>(); if (client.Player.TargetObject != null) { var target = client.Player.TargetObject; text.Add($"Target: {target.Name} (OID: {target.ObjectID}, distance: {Vector3.Distance(target.Position, client.Player.Position)})"); text.Add($"Target in view (player's cache): {client.Player.TargetInView}"); var stats = new RaycastStats(); var sw = new Stopwatch(); sw.Start(); var serverResult = LosCheckMgr.GetCollisionDistance(client.Player, target, ref stats); sw.Stop(); text.Add($"Target in view (server-side los): {serverResult} ({stats.nbNodeTests} node, {stats.nbFaceTests} face, {sw.Elapsed.TotalMilliseconds}ms)"); var losResult = new TaskCompletionSource <ushort>(); client.Out.SendCheckLOS(client.Player, target, (player, response, targetOID) => losResult.SetResult(response)); var result = await losResult.Task; text.Add($"CheckLOS packet response: 0x{result:X4} (in view: {(result & 0x100) != 0})"); } else { var ground = client.Player.GroundTarget; text.Add($"Ground target: {ground}"); text.Add($"Target in view (player's cache): {client.Player.GroundTargetInView}"); // TODO } client.Out.SendCustomTextWindow("Check LOS", text); }
public static float GetCollisionDistance(int regionId, Vector3 origin, Vector3 target, ref RaycastStats stats) { if (!_regionTriangles.ContainsKey(regionId)) { return(float.PositiveInfinity); } var diff = target - origin; var distance = diff.Length() + 1e-6f; if (distance < 32 || distance > WorldMgr.VISIBILITY_DISTANCE) { return(float.PositiveInfinity); } stats.nbTests += 1; diff = Vector3.Normalize(diff); foreach (var tree in _regionTriangles[regionId]) { if (tree == null) { continue; } var rayDist = tree.CollideWithRay(origin, diff, distance, ref stats); if (distance > rayDist) { return(rayDist); } } return(float.PositiveInfinity); }
public static float GetCollisionDistance(Region region, Vector3 origin, Vector3 target, ref RaycastStats stats) { return(GetCollisionDistance(region.ID, origin, target, ref stats)); }
public static float GetCollisionDistance(GameObject origin, GameObject target, ref RaycastStats stats) { if (origin.CurrentRegion != target.CurrentRegion) { return(float.PositiveInfinity); } var height = new Vector3(0, 0, 64); // maybe we should calculate that from the model id and size -- 64inch seems to be okay-ish for players return(GetCollisionDistance(origin.CurrentRegion, origin.Position + height, target.Position + height, ref stats)); }