Harder DynamicTree against NaN.

B2DynamicTree<T> has asserts, DynamicTree<T> handles them gracefully.

NaNs in DynamicTree were causing the internal state to corrupt resulting in the sprite flickering issues.

Fixes https://github.com/space-wizards/space-station-14/issues/2896
This commit is contained in:
Pieter-Jan Briers
2021-02-08 05:03:56 +01:00
parent b000c3178b
commit 91759cdd3c
2 changed files with 46 additions and 2 deletions

View File

@@ -18,6 +18,8 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
// #define DEBUG_DYNAMIC_TREE
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -268,6 +270,9 @@ namespace Robust.Shared.Physics
/// </summary>
public Proxy CreateProxy(in Box2 aabb, T userData)
{
// Also catches NaN fuckery.
Assert(aabb.Right >= aabb.Left && aabb.Top >= aabb.Bottom);
ref var proxy = ref AllocateNode(out var proxyId);
// Fatten the aabb.
@@ -292,6 +297,8 @@ namespace Robust.Shared.Physics
public bool MoveProxy(Proxy proxy, in Box2 aabb, Vector2 displacement)
{
Assert(0 <= proxy && proxy < Capacity);
// Also catches NaN fuckery.
Assert(aabb.Right >= aabb.Left && aabb.Top >= aabb.Bottom);
ref var leafNode = ref _nodes[proxy];

View File

@@ -71,7 +71,7 @@ namespace Robust.Shared.Physics
private readonly ExtractAabbDelegate _extractAabb;
// avoids "Collection was modified; enumeration operation may not execute."
private IDictionary<T, Proxy> _nodeLookup;
private Dictionary<T, Proxy> _nodeLookup;
private readonly B2DynamicTree<T> _b2Tree;
public DynamicTree(ExtractAabbDelegate extractAabbFunc, IEqualityComparer<T>? comparer = null, float aabbExtendSize = 1f / 32, int capacity = 256, Func<int, int>? growthFunc = null)
@@ -134,6 +134,12 @@ namespace Robust.Shared.Physics
var box = _extractAabb(item);
if (CheckNaNs(box))
{
_nodeLookup[item] = Proxy.Free;
return true;
}
proxy = _b2Tree.CreateProxy(box, item);
_nodeLookup[item] = proxy;
@@ -162,7 +168,11 @@ namespace Robust.Shared.Physics
return false;
}
_b2Tree.DestroyProxy(proxy);
if (proxy != Proxy.Free)
{
_b2Tree.DestroyProxy(proxy);
}
return true;
}
@@ -178,6 +188,25 @@ namespace Robust.Shared.Physics
}
var newBox = _extractAabb(item);
if (CheckNaNs(newBox))
{
if (proxy == Proxy.Free)
{
return false;
}
_b2Tree.DestroyProxy(proxy);
_nodeLookup[item] = Proxy.Free;
return true;
}
if (proxy == Proxy.Free)
{
_nodeLookup[item] = _b2Tree.CreateProxy(newBox, item);
return true;
}
return _b2Tree.MoveProxy(proxy, newBox, Vector2.Zero);
}
@@ -304,6 +333,14 @@ namespace Robust.Shared.Physics
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AddOrUpdate(T item) => Update(item) || Add(item);
private static bool CheckNaNs(in Box2 box)
{
return float.IsNaN(box.Left)
|| float.IsNaN(box.Top)
|| float.IsNaN(box.Bottom)
|| float.IsNaN(box.Right);
}
[Conditional("DEBUG_DYNAMIC_TREE")]
[Conditional("DEBUG_DYNAMIC_TREE_ASSERTS")]
[DebuggerNonUserCode]