public IntersectKey(PartFromPrefab partA, PartFromPrefab partB, MatrixI transformAB, bool testOptional) { m_partA = partA; m_partB = partB; m_transformAB = transformAB; m_testOptional = testOptional; }
public static bool Intersects(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional, bool testQuick = false) { var cheapResult = IntersectsInternalCheap(ref partA, ref transformA, ref invTransformA, ref partB, ref transformB, ref invTransformB, testOptional); switch (cheapResult) { case CheapIntersection.Yes: return(true); case CheapIntersection.No: return(false); case CheapIntersection.Maybe: default: break; } if (testQuick) { return(true); } MatrixI abTransform; MatrixI.Multiply(ref transformA, ref invTransformB, out abTransform); var key = new IntersectKey(partA, partB, abTransform, testOptional); bool result; // ReSharper disable once ConvertIfStatementToReturnStatement // TODO when threading cause a wait when another thread is preparing this cache value? if (IntersectionCache.TryGet(key, out result)) { return(result); } return(IntersectionCache.Store(key, IntersectsInternalExpensive(ref partA, ref transformA, ref invTransformA, ref partB, ref transformB, ref invTransformB, testOptional))); }
private static bool IntersectsInternalExpensive(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional) { using (partA.LockSharedUsing()) using (partB.LockSharedUsing()) { var reservedAAll = Utilities.TransformBoundingBox(partA.ReservedSpace, ref transformA); var reservedBAll = Utilities.TransformBoundingBox(partB.ReservedSpace, ref transformB); var reservedA = new List <MyTuple <ReservedSpace, BoundingBox> >(partA.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partA.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedA.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformA))); } } var reservedB = new List <MyTuple <ReservedSpace, BoundingBox> >(partB.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partB.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedB.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformB))); } } // Reserved spaces intersect? if (partA.m_reservedSpaces.Count > 0 && partB.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(reservedBAll)) { if (reservedA.Any(x => reservedB.Any(y => !y.Item1.IsShared && !x.Item1.IsShared && x.Item2.Intersects(y.Item2)))) { return(true); } } var blockAAll = Utilities.TransformBoundingBox(partA.BoundingBox, ref transformA); var blockBAll = Utilities.TransformBoundingBox(partB.BoundingBox, ref transformB); // Block spaces intersect with reserved space? if (partA.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(blockBAll)) { foreach (var aabb in reservedA) { var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockBAll.Min)); var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockBAll.Max)); for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext()) { if (partB.CubeExists(Vector3I.Transform(vi.Current, invTransformB))) { return(true); } } } } if (partB.m_reservedSpaces.Count > 0 && reservedBAll.Intersects(blockAAll)) { foreach (var aabb in reservedB) { var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockAAll.Min)); var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockAAll.Max)); for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext()) { if (partA.CubeExists(Vector3I.Transform(vi.Current, invTransformA))) { return(true); } } } } // Block space intersects with block space? if (!blockAAll.Intersects(blockBAll)) { return(false); } if (partA.m_blocks.Count < partB.m_blocks.Count) { foreach (var pos in partA.m_blocks.Keys) { if (partB.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformA), ref invTransformB))) { return(true); } } } else { foreach (var pos in partB.m_blocks.Keys) { if (partA.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformB), ref invTransformA))) { return(true); } } } return(false); } }
public static bool Intersects(PartFromPrefab partA, MatrixI transformA, MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional, bool testQuick = false) { return(Intersects(ref partA, ref transformA, ref invTransformA, ref partB, ref transformB, ref invTransformB, testOptional, testQuick)); }
private static CheapIntersection IntersectsInternalCheap(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional) { using (partA.LockSharedUsing()) using (partB.LockSharedUsing()) { var reservedAAll = Utilities.TransformBoundingBox(partA.ReservedSpace, ref transformA); var reservedBAll = Utilities.TransformBoundingBox(partB.ReservedSpace, ref transformB); var reservedA = new List <MyTuple <ReservedSpace, BoundingBox> >(partA.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partA.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedA.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformA))); } } var reservedB = new List <MyTuple <ReservedSpace, BoundingBox> >(partB.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partB.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedB.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformB))); } } // Reserved spaces intersect? if (partA.m_reservedSpaces.Count > 0 && partB.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(reservedBAll)) { if (reservedA.Any(x => reservedB.Any(y => !y.Item1.IsShared && !x.Item1.IsShared && x.Item2.Intersects(y.Item2)))) { return(CheapIntersection.Yes); } } var blockAAll = Utilities.TransformBoundingBox(partA.BoundingBox, ref transformA); var blockBAll = Utilities.TransformBoundingBox(partB.BoundingBox, ref transformB); // Block spaces intersect with reserved space? if (partA.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(blockBAll)) { if (reservedA.Any(aabb => aabb.Item2.Intersects(blockBAll))) { return(CheapIntersection.Maybe); } } // ReSharper disable once InvertIf if (partB.m_reservedSpaces.Count > 0 && reservedBAll.Intersects(blockAAll)) { if (reservedB.Any(aabb => aabb.Item2.Intersects(blockAAll))) { return(CheapIntersection.Maybe); } } // Block space intersects with block space? return(!blockAAll.Intersects(blockBAll) ? CheapIntersection.No : CheapIntersection.Maybe); } }