/// <summary>
        /// Removes redundant points.  Two points are redundant if they occupy the same hash grid cell.
        /// </summary>
        /// <param name="points">List of points to prune.</param>
        /// <param name="cellSize">Size of cells to determine redundancy.</param>
        public static void RemoveRedundantPoints(ref QuickList <Vector3> points, double cellSize)
        {
            var set = new QuickSet <Int3>(BufferPools <Int3> .Locking, BufferPools <int> .Locking, BufferPool.GetPoolIndex(points.Count));

            for (int i = points.Count - 1; i >= 0; --i)
            {
                var element = points.Elements[i];
                var cell    = new Int3
                {
                    X = (int)Math.Floor(element.X / cellSize),
                    Y = (int)Math.Floor(element.Y / cellSize),
                    Z = (int)Math.Floor(element.Z / cellSize)
                };
                if (set.Contains(cell))
                {
                    points.FastRemoveAt(i);
                }
                else
                {
                    set.Add(cell);
                    //TODO: Consider adding adjacent cells to guarantee that a point on the border between two cells will still detect the presence
                    //of a point on the opposite side of that border.
                }
            }
            set.Dispose();
        }
Example #2
0
        unsafe static void TestQuickInlining()
        {
            {
                var pool    = new PassthroughArrayPool <double>();
                var intPool = new PassthroughArrayPool <int>();
                QuickSet <double, Array <double>, Array <int>, PrimitiveComparer <double> > .Create(pool, intPool, 2, 3, out var set);

                set.AddUnsafely(5);
                var item = set[0];
                Console.WriteLine($"Managed Item: {item}");

                var comparer = default(PrimitiveComparer <double>);
                var hash     = comparer.Hash(ref item);

                Console.WriteLine($"Hash: {hash}");
            }

            {
                var pool = new BufferPool().SpecializeFor <int>();
                QuickSet <int, Buffer <int>, Buffer <int>, PrimitiveComparer <int> > .Create(pool, pool, 2, 3, out var set);

                set.AddUnsafely(5);
                var item = set[0];
                pool.Raw.Clear();
            }
        }
Example #3
0
 public BoundarySets(int sizePower)
 {
     BlockedVertexRegions = new QuickSet <int>(BufferPools <int> .Thread, BufferPools <int> .Thread, sizePower);
     BlockedEdgeRegions   = new QuickSet <Edge>(BufferPools <Edge> .Thread, BufferPools <int> .Thread, sizePower);
     EdgeContacts         = new QuickList <EdgeContact>(BufferPools <EdgeContact> .Thread, sizePower);
     VertexContacts       = new QuickList <VertexContact>(BufferPools <VertexContact> .Thread, sizePower);
 }
 /// <summary>
 /// Removes redundant points.  Two points are redundant if they occupy the same hash grid cell.
 /// </summary>
 /// <param name="points">List of points to prune.</param>
 /// <param name="cellSize">Size of cells to determine redundancy.</param>
 public static void RemoveRedundantPoints(ref QuickList<Vector3> points, double cellSize)
 {
     var set = new QuickSet<Int3>(BufferPools<Int3>.Locking, BufferPools<int>.Locking, BufferPool.GetPoolIndex(points.Count));
     for (int i = points.Count - 1; i >= 0; --i)
     {
         var element = points.Elements[i];
         var cell = new Int3
         {
             X = (int)Math.Floor(element.X / cellSize),
             Y = (int)Math.Floor(element.Y / cellSize),
             Z = (int)Math.Floor(element.Z / cellSize)
         };
         if (set.Contains(cell))
         {
             points.FastRemoveAt(i);
         }
         else
         {
             set.Add(cell);
             //TODO: Consider adding adjacent cells to guarantee that a point on the border between two cells will still detect the presence
             //of a point on the opposite side of that border.
         }
     }
     set.Dispose();
 }
Example #5
0
        unsafe void Allocate <TBodyReferenceGetter>(int constraintHandle, ref int constraintBodyHandles, int bodyCount, Bodies3D bodies3D,
                                                    int typeId, BufferPool pool, TBodyReferenceGetter bodyReferenceGetter, int minimumBodyCapacity, int minimumReferenceCapacity)
            where TBodyReferenceGetter : struct, IBodyReferenceGetter
        {
            EnsureCapacity(Math.Max(bodyConstraintReferences.Count + bodyCount, minimumBodyCapacity), pool);
            for (int i = 0; i < bodyCount; ++i)
            {
                var bodyReference = bodyReferenceGetter.GetBodyReference(bodies3D, Unsafe.Add(ref constraintBodyHandles, i));

                var bodyAlreadyListed = bodyConstraintReferences.GetTableIndices(ref bodyReference, out var tableIndex, out var elementIndex);
                //If an entry for this body does not yet exist, we'll create one.
                if (!bodyAlreadyListed)
                {
                    elementIndex = bodyConstraintReferences.Count;
                }
                ref var constraintReferences = ref bodyConstraintReferences.Values[elementIndex];

                if (!bodyAlreadyListed)
                {
                    //The body is not already contained. Create a list for it.
                    constraintReferences = new QuickSet <FallbackReference, FallbackReferenceComparer>(minimumReferenceCapacity, pool);
                    bodyConstraintReferences.Keys[elementIndex] = bodyReference;
                    bodyConstraintReferences.Table[tableIndex]  = elementIndex + 1;
                    ++bodyConstraintReferences.Count;
                }
                var fallbackReference = new FallbackReference {
                    ConstraintHandle = constraintHandle, IndexInConstraint = i
                };
                constraintReferences.AddRef(ref fallbackReference, pool);
            }
        internal IEnumerable <TElement> ResolveEnumerable <TElement>(Func <Type, string, ImplicitRegistration, object> resolve, string name)
        {
            TElement value;
            var      set  = new QuickSet <Type>();
            int      hash = typeof(TElement).GetHashCode();

            // Iterate over hierarchy
            for (var container = this; null != container; container = container._parent)
            {
                // Skip to parent if no data
                if (null == container._metadata)
                {
                    continue;
                }

                // Hold on to registries
                var registry = container._registry;

                // Get indexes and iterate over them
                var length = container._metadata.GetEntries <TElement>(hash, out int[] data);
                for (var i = 1; i < length; i++)
                {
                    var index = data[i];

                    if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type))
                    {
                        try
                        {
                            var registration = (ExplicitRegistration)registry.Entries[index].Value;
                            value = (TElement)resolve(typeof(TElement), registry.Entries[index].Key.Name, registration);
                        }
                        catch (ArgumentException ex) when(ex.InnerException is TypeLoadException)
                        {
                            continue;
                        }

                        yield return(value);
                    }
                }
            }

            // If nothing registered attempt to resolve the type
            if (0 == set.Count)
            {
                try
                {
                    var registration = GetRegistration(typeof(TElement), name);
                    value = (TElement)resolve(typeof(TElement), name, registration);
                }
                catch
                {
                    yield break;
                }

                yield return(value);
            }
        }
Example #7
0
        public MeshCache(Device device, BufferPool pool, int initialSizeInVertices = 1 << 22)
        {
            Pool = pool;
            pool.TakeAtLeast(initialSizeInVertices, out vertices);
            TriangleBuffer = new StructuredBuffer <Vector3>(device, initialSizeInVertices, "Mesh Cache Vertex Buffer");
            allocator      = new Allocator(initialSizeInVertices, pool);

            pendingUploads         = new QuickList <UploadRequest>(128, pool);
            requestedIds           = new QuickList <ulong>(128, pool);
            previouslyAllocatedIds = new QuickSet <ulong, PrimitiveComparer <ulong> >(256, pool);
        }
Example #8
0
        public MeshCache(Device device, BufferPool pool, int initialSizeInVertices = 1 << 22)
        {
            Pool = pool;
            pool.Take(initialSizeInVertices, out vertices);
            TriangleBuffer = new StructuredBuffer <Vector3>(device, initialSizeInVertices, "Mesh Cache Vertex Buffer");
            allocator      = new Allocator(initialSizeInVertices);

            QuickList <UploadRequest, Buffer <UploadRequest> > .Create(pool.SpecializeFor <UploadRequest>(), 128, out pendingUploads);

            QuickList <ulong, Buffer <ulong> > .Create(pool.SpecializeFor <ulong>(), 128, out requestedIds);

            QuickSet <ulong, Buffer <ulong>, Buffer <int>, PrimitiveComparer <ulong> > .Create(pool.SpecializeFor <ulong>(), pool.SpecializeFor <int>(), 8, 3, out previouslyAllocatedIds);
        }
Example #9
0
        internal IEnumerable <TElement> ComplexArray <TElement>(Func <Type, IRegistration, object?> resolve, Type type)
        {
            object?value;
            var    set     = new QuickSet();
            var    key     = new HashKey(typeof(TElement));
            var    typeKey = new HashKey(type);

            // Iterate over hierarchy
            for (UnityContainer?container = this; null != container; container = container._parent)
            {
                // Skip to parent if no data
                if (null == container._metadata)
                {
                    continue;
                }

                // Hold on to registries
                Debug.Assert(null != container._registry);
                var registry = container._registry;

                // Get indexes and iterate over them
                var length = container._metadata.GetMeta(ref typeKey, out int[]? data);
                if (null != data)
                {
                    for (var i = 1; i < length; i++)
                    {
                        var index        = data[i];
                        var registration = (ExplicitRegistration)registry.Entries[index].Policies;

                        if (null != registration.Name && set.Add(registration.Name))
                        {
                            try
                            {
                                var itemKey = new HashKey(typeof(TElement), registration.Name);
                                var item    = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration);
                                value = resolve(typeof(TElement), item);
                            }
                            catch (ArgumentException ex) when(ex.InnerException is TypeLoadException)
                            {
                                continue;
                            }

#pragma warning disable CS8601 // Possible null reference assignment.
                            yield return((TElement)value);

#pragma warning restore CS8601 // Possible null reference assignment.
                        }
                    }
                }
            }
        }
Example #10
0
        /// <summary>
        /// Identifies the points on the surface of hull.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull.
        /// Each group of 3 indices represents a triangle on the surface of the hull.</param>
        /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param>
        public static void GetConvexHull(ref QuickList <Vector3> points, ref QuickList <int> outputTriangleIndices, IList <Vector3> outputSurfacePoints)
        {
            GetConvexHull(ref points, ref outputTriangleIndices);

            var alreadyContainedIndices = new QuickSet <int>(BufferPools <int> .Locking, BufferPools <int> .Locking);

            for (int i = outputTriangleIndices.Count - 1; i >= 0; i--)
            {
                int index = outputTriangleIndices[i];
                if (alreadyContainedIndices.Add(index))
                {
                    outputSurfacePoints.Add(points[index]);
                }
            }
            alreadyContainedIndices.Dispose();
        }
        public static void TestSetResizing <TSpan, TPool>(TPool pool)
            where TSpan : ISpan <int>
            where TPool : IMemoryPool <int, TSpan>
        {
            Random random = new Random(5);

            QuickSet <int, TSpan, TSpan, PrimitiveComparer <int> > .Create(pool, pool, 2, 3, out var set);

            HashSet <int> controlSet = new HashSet <int>();

            for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex)
            {
                if (random.NextDouble() < 0.7)
                {
                    set.Add(iterationIndex, pool, pool);
                    controlSet.Add(iterationIndex);
                }
                if (random.NextDouble() < 0.2)
                {
                    var indexToRemove = random.Next(set.Count);
                    var toRemove      = set[indexToRemove];
                    set.FastRemove(toRemove);
                    controlSet.Remove(toRemove);
                }
                if (iterationIndex % 1000 == 0)
                {
                    set.EnsureCapacity(set.Count * 3, pool, pool);
                }
                else if (iterationIndex % 7777 == 0)
                {
                    set.Compact(pool, pool);
                }
            }

            Debug.Assert(set.Count == controlSet.Count);
            for (int i = 0; i < set.Count; ++i)
            {
                Debug.Assert(controlSet.Contains(set[i]));
            }
            foreach (var element in controlSet)
            {
                Debug.Assert(set.Contains(element));
            }

            set.Dispose(pool, pool);
        }
        internal IEnumerable <TElement> ComplexArray <TElement>(Func <Type, string, ImplicitRegistration, object> resolve, Type type)
        {
            TElement value;
            var      set      = new QuickSet <Type>();
            int      hashCode = type.GetHashCode();

            // Iterate over hierarchy
            for (var container = this; null != container; container = container._parent)
            {
                // Skip to parent if no data
                if (null == container._metadata)
                {
                    continue;
                }

                // Hold on to registries
                var registry = container._registry;

                // Get indexes and iterate over them
                var length = container._metadata.GetEntries(hashCode, type, out int[] data);
                for (var i = 1; i < length; i++)
                {
                    var index = data[i];
                    var name  = registry.Entries[index].Key.Name;
                    if (null == name)
                    {
                        continue;
                    }
                    if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type))
                    {
                        try
                        {
                            int hash         = NamedType.GetHashCode(typeof(TElement), name);
                            var registration = container.GetOrAdd(hash, typeof(TElement), name, registry.Entries[index].Value);
                            value = (TElement)resolve(typeof(TElement), name, registration);
                        }
                        catch (ArgumentException ex) when(ex.InnerException is TypeLoadException)
                        {
                            continue;
                        }

                        yield return(value);
                    }
                }
            }
        }
        unsafe static void TestQuickInlining(BufferPool pool)
        {
            {
                var set = new QuickSet <double, PrimitiveComparer <double> >(4, pool);
                set.AddUnsafely(5);
                var item = set[0];
                Console.WriteLine($"Managed Item: {item}");

                var comparer = default(PrimitiveComparer <double>);
                var hash     = comparer.Hash(ref item);

                Console.WriteLine($"Hash: {hash}");
            }

            {
                var set = new QuickSet <int, PrimitiveComparer <int> >(4, pool);
                set.AddUnsafely(5);
                var item = set[0];
            }
        }
Example #14
0
        public static void TestSetResizing()
        {
            Random random = new Random(5);
            UnsafeBufferPool <int> pool       = new UnsafeBufferPool <int>();
            QuickSet <int>         set        = new QuickSet <int>(pool, pool);
            HashSet <int>          controlSet = new HashSet <int>();

            for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex)
            {
                if (random.NextDouble() < 0.7)
                {
                    set.Add(iterationIndex);
                    controlSet.Add(iterationIndex);
                }
                if (random.NextDouble() < 0.2)
                {
                    var indexToRemove = random.Next(set.Count);
                    var toRemove      = set[indexToRemove];
                    set.FastRemove(toRemove);
                    controlSet.Remove(toRemove);
                }
                if (iterationIndex % 1000 == 0)
                {
                    set.EnsureCapacity(set.Count * 3);
                }
                else if (iterationIndex % 7777 == 0)
                {
                    set.Compact();
                }
            }

            Assert.IsTrue(set.Count == controlSet.Count);
            for (int i = 0; i < set.Count; ++i)
            {
                Assert.IsTrue(controlSet.Contains(set[i]));
            }
            foreach (var element in controlSet)
            {
                Assert.IsTrue(set.Contains(element));
            }
        }
        public static void RasterizeTriangle(ref Vector3 a, ref Vector3 b, ref Vector3 c, float cellSize, ref Vector3 gridOrigin, BufferPool pool, ref QuickSet <Cell, CellComparer> cells)
        {
            var gridA = a - gridOrigin;
            var gridB = b - gridOrigin;
            var gridC = c - gridOrigin;

            //Compute the bounding box of the triangle.
            var max = Vector3.Max(Vector3.Max(gridA, gridB), gridC);
            var min = Vector3.Min(Vector3.Min(gridA, gridB), gridC);

            var epsilon = new Vector3(1e-5f);

            min -= epsilon;
            max += epsilon;

            //Discretize the bounding box.
            //All indices are positive, so we can just truncate.
            int   startX, endX, startY, endY, startZ, endZ;
            float inverseCellSize = 1f / cellSize;

            startX = (int)Math.Floor(min.X * inverseCellSize);
            endX   = (int)Math.Floor(max.X * inverseCellSize);
            startY = (int)Math.Floor(min.Y * inverseCellSize);
            endY   = (int)Math.Floor(max.Y * inverseCellSize);
            startZ = (int)Math.Floor(min.Z * inverseCellSize);
            endZ   = (int)Math.Floor(max.Z * inverseCellSize);

            //Test the triangle against each cell.
            var halfExtents = new Vector3(cellSize * 0.5f);

            for (int i = startX; i <= endX; ++i)
            {
                for (int j = startY; j <= endY; ++j)
                {
                    for (int k = startZ; k <= endZ; ++k)
                    {
                        var cellIndex  = new Vector3(i, j, k);
                        var cellOrigin = cellSize * cellIndex + halfExtents;
                        var shiftedA   = gridA - cellOrigin;
                        var shiftedB   = gridB - cellOrigin;
                        var shiftedC   = gridC - cellOrigin;

                        if (BoxTriangleCollider.Intersecting(ref halfExtents, ref shiftedA, ref shiftedB, ref shiftedC))
                        {
                            cells.Add(new Cell {
                                X = i, Y = j, Z = k
                            }, pool);
                        }
                    }
                }
            }
        }
        internal IEnumerable <TElement> ResolveEnumerable <TElement>(Func <Type, string, ImplicitRegistration, object> resolve,
                                                                     Type typeDefinition, string name)
        {
            TElement value;
            var      set         = new QuickSet <Type>();
            int      hashCode    = typeof(TElement).GetHashCode();
            int      hashGeneric = typeDefinition.GetHashCode();

            // Iterate over hierarchy
            for (var container = this; null != container; container = container._parent)
            {
                // Skip to parent if no data
                if (null == container._metadata)
                {
                    continue;
                }

                // Hold on to registries
                var registry = container._registry;

                // Get indexes for bound types and iterate over them
                var length = container._metadata.GetEntries <TElement>(hashCode, out int[] data);
                for (var i = 1; i < length; i++)
                {
                    var index = data[i];

                    if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type))
                    {
                        try
                        {
                            var registration = (ExplicitRegistration)registry.Entries[index].Value;
                            value = (TElement)resolve(typeof(TElement), registry.Entries[index].Key.Name, registration);
                        }
                        catch (ArgumentException ex) when(ex.InnerException is TypeLoadException)
                        {
                            continue;
                        }

                        yield return(value);
                    }
                }

                // Get indexes for unbound types and iterate over them
                length = container._metadata.GetEntries(hashGeneric, typeDefinition, out data);
                for (var i = 1; i < length; i++)
                {
                    var index = data[i];
                    var key   = registry.Entries[index].Key.Name;

                    if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type))
                    {
                        try
                        {
                            int hash         = NamedType.GetHashCode(typeof(TElement), key);
                            var registration = container.GetOrAdd(hash, typeof(TElement), key, registry.Entries[index].Value);
                            value = (TElement)resolve(typeof(TElement), key, registration);
                        }
                        catch (MakeGenericTypeFailedException) { continue; }
                        catch (InvalidOperationException ex) when(ex.InnerException is InvalidRegistrationException)
                        {
                            continue;
                        }
                        // TODO: Verify if required
                        //catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
                        //{
                        //    continue;
                        //}

                        yield return(value);
                    }
                }
            }

            // If nothing registered attempt to resolve the type
            if (0 == set.Count)
            {
                try
                {
                    var registration = GetRegistration(typeof(TElement), name);
                    value = (TElement)resolve(typeof(TElement), name, registration);
                }
                catch
                {
                    yield break;
                }

                yield return(value);
            }
        }
Example #17
0
        internal IEnumerable <TElement> ResolveEnumerable <TElement>(Func <Type, IRegistration, object?> resolve,
                                                                     Type typeDefinition, string?name)
        {
            object?value;
            var    set        = new QuickSet();
            var    key        = new HashKey(typeof(TElement));
            var    keyGeneric = new HashKey(typeDefinition);

            // Iterate over hierarchy
            for (UnityContainer?container = this; null != container; container = container._parent)
            {
                // Skip to parent if no data
                if (null == container._metadata)
                {
                    continue;
                }

                // Hold on to registries
                Debug.Assert(null != container._registry);
                var registry = container._registry;

                // Get indexes for bound types and iterate over them
                var length = container._metadata.GetMeta(ref key, out int[]? data);
                if (null != data)
                {
                    for (var i = 1; i < length; i++)
                    {
                        var index        = data[i];
                        var registration = (ExplicitRegistration)registry.Entries[index].Policies;

                        if (!set.Add(registration.Name))
                        {
                            continue;
                        }

                        try
                        {
                            value = resolve(typeof(TElement), registration);
                        }
                        catch (ArgumentException ex) when(ex.InnerException is TypeLoadException)
                        {
                            continue;
                        }

#pragma warning disable CS8601 // Possible null reference assignment.
                        yield return((TElement)value);

#pragma warning restore CS8601 // Possible null reference assignment.
                    }
                }

                // Get indexes for unbound types and iterate over them
                length = container._metadata.GetMeta(ref keyGeneric, out data);
                if (null != data)
                {
                    for (var i = 1; i < length; i++)
                    {
                        var index        = data[i];
                        var registration = (ExplicitRegistration)registry.Entries[index].Policies;

                        if (set.Add(registration.Name))
                        {
                            try
                            {
                                var itemKey = new HashKey(typeof(TElement), registration.Name);
                                var item    = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration);
                                value = resolve(typeof(TElement), item);
                            }
                            catch (MakeGenericTypeFailedException) { continue; }
                            catch (InvalidRegistrationException)   { continue; }

#pragma warning disable CS8601 // Possible null reference assignment.
                            yield return((TElement)value);

#pragma warning restore CS8601 // Possible null reference assignment.
                        }
                    }
                }
            }

            // If nothing registered attempt to resolve the type
            if (0 == set.Count)
            {
                try
                {
                    var registration = GetRegistration(typeof(TElement), name);
                    value = resolve(typeof(TElement), registration);
                }
                catch
                {
                    yield break;
                }

#pragma warning disable CS8601 // Possible null reference assignment.
                yield return((TElement)value);

#pragma warning restore CS8601 // Possible null reference assignment.
            }
        }
Example #18
0
        public static unsafe TestResults TestSingleArray(TestCollidable[] leaves, BoundingBox[] queries, BoundingBox positionBounds,
            int queryCount, int selfTestCount, int refitCount, int frameCount, float dt, ParallelLooper looper)
        {
            {

                var warmLeaves = GetLeaves(10, 10, 10, 10, 10);
                Tree tree = new Tree();
                //for (int i = 0; i < leaves.Length; ++i)
                //{
                //    BoundingBox box;
                //    leaves[i].GetBoundingBox(out box);
                //    //tree.Insert(i, ref box);
                //    tree.AddGlobal(i, ref box);
                //}
                int[] leafIds = new int[warmLeaves.Length];
                BoundingBox[] leafBounds = new BoundingBox[warmLeaves.Length];
                for (int i = 0; i < warmLeaves.Length; ++i)
                {
                    leafIds[i] = i;
                    warmLeaves[i].GetBoundingBox(out leafBounds[i]);
                }
                //tree.BuildMedianSplit(leafIds, leafBounds);
                //tree.BuildVolumeHeuristic(leafIds, leafBounds);
                tree.SweepBuild(leafIds, leafBounds);
                Console.WriteLine($"SingleArray Cachewarm Build: {tree.LeafCount}");

                tree.Refit();
                //tree.BottomUpAgglomerativeRefine();
                //tree.TopDownAgglomerativeRefine();
                //tree.BottomUpSweepRefine();
                //tree.TopDownSweepRefine();

                tree.RefitAndRefine(0);
                var context = new Tree.RefitAndRefineMultithreadedContext(tree);
                tree.RefitAndRefine(0, looper, context);

                var selfTestContext = new Tree.SelfTestMultithreadedContext(looper.ThreadCount, BufferPools<Overlap>.Locking);
                tree.GetSelfOverlaps(looper, selfTestContext);

                var list = new QuickList<int>(new BufferPool<int>());
                BoundingBox aabb = new BoundingBox { Min = new Vector3(0, 0, 0), Max = new Vector3(1, 1, 1) };
                tree.QueryRecursive(ref aabb, ref list);
                list.Dispose();

                var overlaps = new QuickList<Overlap>(new BufferPool<Overlap>());
                tree.GetSelfOverlaps(ref overlaps);

                overlaps = new QuickList<Overlap>(new BufferPool<Overlap>());
                tree.GetSelfOverlapsArityDedicated(ref overlaps);

                tree.IncrementalCacheOptimize(0);

                overlaps = new QuickList<Overlap>(new BufferPool<Overlap>());

                tree.GetSelfOverlapsViaQueries(ref overlaps);
                Console.WriteLine($"Cachewarm overlaps: {overlaps.Count}");
                tree.Dispose();

            }

            {
                Console.WriteLine($"SingleArray arity: {Tree.ChildrenCapacity}");
                Tree tree = new Tree(Math.Max(1, leaves.Length));
                var startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < leaves.Length; ++i)
                {
                    var leafIndex = (int)((982451653L * i) % leaves.Length);
                    BoundingBox box;
                    leaves[leafIndex].GetBoundingBox(out box);
                    tree.Add(leafIndex, ref box);
                    //tree.AddGlobal(leafIndex, ref box);
                }
                //int[] leafIds = new int[leaves.Length];
                //BoundingBox[] leafBounds = new BoundingBox[leaves.Length];
                //for (int i = 0; i < leaves.Length; ++i)
                //{
                //    leafIds[i] = i;
                //    leaves[i].GetBoundingBox(out leafBounds[i]);
                //}
                ////tree.BuildMedianSplit(leafIds, leafBounds);
                ////tree.BuildVolumeHeuristic(leafIds, leafBounds);
                //tree.SweepBuild(leafIds, leafBounds);
                var endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Build Time: {endTime - startTime}, depth: {tree.ComputeMaximumDepth()}");

                int nodeCount, childCount;
                tree.MeasureNodeOccupancy(out nodeCount, out childCount);
                Console.WriteLine($"SingleArray Occupancy: {childCount / (double)nodeCount}");
                Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");
                Console.WriteLine($"Cache Quality: {tree.MeasureCacheQuality()}");

                tree.Validate();

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < refitCount; ++i)
                {
                    //for (int i = 0; i < tree.LeafCount; ++i)
                    //{
                    //    BoundingBox box;
                    //    leaves[tree.Leaves[i].Id].GetBoundingBox(out box);
                    //    tree.UpdateLeafBoundingBox(i, ref box);
                    //}
                    tree.Refit();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Refit Time1: {endTime - startTime}");

                var overlaps = new QuickList<Overlap>(new BufferPool<Overlap>());
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlaps(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray SelfTree Time1: {endTime - startTime}, overlaps: {overlaps.Count}");

                int[] buffer;
                MemoryRegion region;
                BinnedResources resources;
                const int maximumSubtrees = 262144;
                var spareNodes = new QuickList<int>(new BufferPool<int>(), 8);
                var subtreeReferences = new QuickList<int>(BufferPools<int>.Thread, BufferPool<int>.GetPoolIndex(maximumSubtrees));
                var treeletInternalNodes = new QuickList<int>(BufferPools<int>.Thread, BufferPool<int>.GetPoolIndex(maximumSubtrees));
                Tree.CreateBinnedResources(BufferPools<int>.Thread, maximumSubtrees, out buffer, out region, out resources);
                bool nodesInvalidated;
                overlaps = new QuickList<Overlap>(new BufferPool<Overlap>());

                var refineContext = new Tree.RefitAndRefineMultithreadedContext(tree);
                var selfTestContext = new Tree.SelfTestMultithreadedContext(looper.ThreadCount, BufferPools<Overlap>.Locking);

                var visitedNodes = new QuickSet<int>(BufferPools<int>.Thread, BufferPools<int>.Thread);

                //**************** Dynamic Testing
                Random random = new Random(5);
                TestResults results = new TestResults("New", frameCount);
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int t = 0; t < frameCount; ++t)
                {
                    //Update the positions of objects.
                    for (int i = 0; i < tree.LeafCount; ++i)
                    {
                        var leafId = tree.Leaves[i].Id;
                        var leaf = leaves[leafId];

                        //Bounce off the walls.
                        if (leaf.Position.X < positionBounds.Min.X && leaf.Velocity.X < 0)
                            leaf.Velocity.X = -leaf.Velocity.X;
                        if (leaf.Position.Y < positionBounds.Min.Y && leaf.Velocity.Y < 0)
                            leaf.Velocity.Y = -leaf.Velocity.Y;
                        if (leaf.Position.Z < positionBounds.Min.Z && leaf.Velocity.Z < 0)
                            leaf.Velocity.Z = -leaf.Velocity.Z;

                        if (leaf.Position.X > positionBounds.Max.X && leaf.Velocity.X > 0)
                            leaf.Velocity.X = -leaf.Velocity.X;
                        if (leaf.Position.Y > positionBounds.Max.Y && leaf.Velocity.Y > 0)
                            leaf.Velocity.Y = -leaf.Velocity.Y;
                        if (leaf.Position.Z > positionBounds.Max.Z && leaf.Velocity.Z > 0)
                            leaf.Velocity.Z = -leaf.Velocity.Z;

                        leaf.Position += leaf.Velocity * dt;
                        BoundingBox boundingBox;
                        leaf.GetBoundingBox(out boundingBox);
                        tree.SetLeafBoundingBox(i, ref boundingBox);
                    }
                    var refineStartTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    int refinementCount;
                    if(looper.ThreadCount > 1)
                        refinementCount = tree.RefitAndRefine(t, looper, refineContext);
                    else
                        refinementCount = tree.RefitAndRefine(t);

                    var refineEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    int overlapsCount;
                    if (looper.ThreadCount > 1)
                    {
                        tree.GetSelfOverlaps(looper, selfTestContext);
                        overlapsCount = 0;
                        for (int i = 0; i < selfTestContext.WorkerOverlaps.Length; ++i)
                        {
                            overlapsCount += selfTestContext.WorkerOverlaps[i].Count;
                        }
                    }
                    else
                    {
                        overlaps.Count = 0;
                        tree.GetSelfOverlapsArityDedicated(ref overlaps);
                        overlapsCount = overlaps.Count;
                    }

                    var testEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    results.Refine[t] = 1000 * (refineEndTime - refineStartTime);
                    results.SelfTest[t] = 1000 * (testEndTime - refineEndTime);
                    results.Total[t] = 1000 * (testEndTime - refineStartTime);
                    results.OverlapCounts[t] = overlapsCount;
                    results.TreeCosts[t] = tree.MeasureCostMetric();

                    if (t % 16 == 0)
                    {
                        Console.WriteLine($"_________________{t}_________________");
                        Console.WriteLine($"Refinement count: {refinementCount}");
                        Console.WriteLine($"Refine time:      {results.Refine[t]}");
                        Console.WriteLine($"Test time:        {results.SelfTest[t]}");
                        Console.WriteLine($"TIME:             {results.Total[t]}");
                        Console.WriteLine($"Cost metric:      {results.TreeCosts[t]}");
                        Console.WriteLine($"Overlaps:         {results.OverlapCounts[t]}");
                        Console.WriteLine($"Cache Quality:    {tree.MeasureCacheQuality()}");
                        GC.Collect();
                    }
                    tree.Validate();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                tree.Validate();
                Console.WriteLine($"SingleArray Cache Quality: {tree.MeasureCacheQuality()}");
                Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");

                region.Dispose();
                tree.RemoveUnusedInternalNodes(ref spareNodes);
                BufferPools<int>.Thread.GiveBack(buffer);

                //********************

                tree.MeasureNodeOccupancy(out nodeCount, out childCount);
                Console.WriteLine($"SingleArray Occupancy: {childCount / (double)nodeCount}");

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < refitCount; ++i)
                {
                    //for (int i = 0; i < tree.LeafCount; ++i)
                    //{
                    //    BoundingBox box;
                    //    leaves[tree.Leaves[i].Id].GetBoundingBox(out box);
                    //    tree.UpdateLeafBoundingBox(i, ref box);
                    //}
                    tree.Refit();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Refit Time2: {endTime - startTime}");

                var list = new QuickList<int>(new BufferPool<int>());
                var queryMask = queries.Length - 1;
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < queryCount; ++i)
                {
                    list.Count = 0;
                    //tree.Query2(ref queries[i & queryMask], ref list);
                    tree.QueryRecursive(ref queries[i & queryMask], ref list);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Query Time: {endTime - startTime}, overlaps: {list.Count}");
                Array.Clear(list.Elements, 0, list.Elements.Length);
                list.Dispose();

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlaps(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray SelfTree Time: {endTime - startTime}, overlaps: {overlaps.Count}");

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlapsArityDedicated(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Arity-Dedicated SelfTree Time: {endTime - startTime}, overlaps: {overlaps.Count}");

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlapsViaQueries(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray SelfQuery Time: {endTime - startTime}, overlaps: {overlaps.Count}");

                tree.Dispose();

                return results;
            }
        }
Example #19
0
        public unsafe static TestResults TestSingleArray(TestCollidable[] leaves, BoundingBox[] queries, BoundingBox positionBounds,
                                                         int queryCount, int selfTestCount, int refitCount, int frameCount, float dt, ParallelLooper looper)
        {
            {
                var  warmLeaves = GetLeaves(10, 10, 10, 10, 10);
                Tree tree       = new Tree();
                //for (int i = 0; i < leaves.Length; ++i)
                //{
                //    BoundingBox box;
                //    leaves[i].GetBoundingBox(out box);
                //    //tree.Insert(i, ref box);
                //    tree.AddGlobal(i, ref box);
                //}
                int[]         leafIds    = new int[warmLeaves.Length];
                BoundingBox[] leafBounds = new BoundingBox[warmLeaves.Length];
                for (int i = 0; i < warmLeaves.Length; ++i)
                {
                    leafIds[i] = i;
                    warmLeaves[i].GetBoundingBox(out leafBounds[i]);
                }
                //tree.BuildMedianSplit(leafIds, leafBounds);
                //tree.BuildVolumeHeuristic(leafIds, leafBounds);
                tree.SweepBuild(leafIds, leafBounds);
                Console.WriteLine($"SingleArray Cachewarm Build: {tree.LeafCount}");

                tree.Refit();
                //tree.BottomUpAgglomerativeRefine();
                //tree.TopDownAgglomerativeRefine();
                //tree.BottomUpSweepRefine();
                //tree.TopDownSweepRefine();

                tree.RefitAndRefine(0);
                var context = new Tree.RefitAndRefineMultithreadedContext(tree);
                tree.RefitAndRefine(0, looper, context);

                var selfTestContext = new Tree.SelfTestMultithreadedContext(looper.ThreadCount, BufferPools <Overlap> .Locking);
                tree.GetSelfOverlaps(looper, selfTestContext);

                var         list = new QuickList <int>(new BufferPool <int>());
                BoundingBox aabb = new BoundingBox {
                    Min = new Vector3(0, 0, 0), Max = new Vector3(1, 1, 1)
                };
                tree.QueryRecursive(ref aabb, ref list);
                list.Dispose();

                var overlaps = new QuickList <Overlap>(new BufferPool <Overlap>());
                tree.GetSelfOverlaps(ref overlaps);

                overlaps = new QuickList <Overlap>(new BufferPool <Overlap>());
                tree.GetSelfOverlapsArityDedicated(ref overlaps);

                tree.IncrementalCacheOptimize(0);

                overlaps = new QuickList <Overlap>(new BufferPool <Overlap>());

                tree.GetSelfOverlapsViaQueries(ref overlaps);
                Console.WriteLine($"Cachewarm overlaps: {overlaps.Count}");
                tree.Dispose();
            }

            {
                Console.WriteLine($"SingleArray arity: {Tree.ChildrenCapacity}");
                Tree tree      = new Tree(Math.Max(1, leaves.Length));
                var  startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < leaves.Length; ++i)
                {
                    var         leafIndex = (int)((982451653L * i) % leaves.Length);
                    BoundingBox box;
                    leaves[leafIndex].GetBoundingBox(out box);
                    tree.Add(leafIndex, ref box);
                    //tree.AddGlobal(leafIndex, ref box);
                }
                //int[] leafIds = new int[leaves.Length];
                //BoundingBox[] leafBounds = new BoundingBox[leaves.Length];
                //for (int i = 0; i < leaves.Length; ++i)
                //{
                //    leafIds[i] = i;
                //    leaves[i].GetBoundingBox(out leafBounds[i]);
                //}
                ////tree.BuildMedianSplit(leafIds, leafBounds);
                ////tree.BuildVolumeHeuristic(leafIds, leafBounds);
                //tree.SweepBuild(leafIds, leafBounds);
                var endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Build Time: {endTime - startTime}, depth: {tree.ComputeMaximumDepth()}");

                int nodeCount, childCount;
                tree.MeasureNodeOccupancy(out nodeCount, out childCount);
                Console.WriteLine($"SingleArray Occupancy: {childCount / (double)nodeCount}");
                Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");
                Console.WriteLine($"Cache Quality: {tree.MeasureCacheQuality()}");

                tree.Validate();

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < refitCount; ++i)
                {
                    //for (int i = 0; i < tree.LeafCount; ++i)
                    //{
                    //    BoundingBox box;
                    //    leaves[tree.Leaves[i].Id].GetBoundingBox(out box);
                    //    tree.UpdateLeafBoundingBox(i, ref box);
                    //}
                    tree.Refit();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Refit Time1: {endTime - startTime}");

                var overlaps = new QuickList <Overlap>(new BufferPool <Overlap>());
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlaps(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray SelfTree Time1: {endTime - startTime}, overlaps: {overlaps.Count}");


                int[]           buffer;
                MemoryRegion    region;
                BinnedResources resources;
                const int       maximumSubtrees      = 262144;
                var             spareNodes           = new QuickList <int>(new BufferPool <int>(), 8);
                var             subtreeReferences    = new QuickList <int>(BufferPools <int> .Thread, BufferPool <int> .GetPoolIndex(maximumSubtrees));
                var             treeletInternalNodes = new QuickList <int>(BufferPools <int> .Thread, BufferPool <int> .GetPoolIndex(maximumSubtrees));
                Tree.CreateBinnedResources(BufferPools <int> .Thread, maximumSubtrees, out buffer, out region, out resources);
                bool nodesInvalidated;
                overlaps = new QuickList <Overlap>(new BufferPool <Overlap>());

                var refineContext   = new Tree.RefitAndRefineMultithreadedContext(tree);
                var selfTestContext = new Tree.SelfTestMultithreadedContext(looper.ThreadCount, BufferPools <Overlap> .Locking);


                var visitedNodes = new QuickSet <int>(BufferPools <int> .Thread, BufferPools <int> .Thread);

                //**************** Dynamic Testing
                Random      random  = new Random(5);
                TestResults results = new TestResults("New", frameCount);
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int t = 0; t < frameCount; ++t)
                {
                    //Update the positions of objects.
                    for (int i = 0; i < tree.LeafCount; ++i)
                    {
                        var leafId = tree.Leaves[i].Id;
                        var leaf   = leaves[leafId];

                        //Bounce off the walls.
                        if (leaf.Position.X < positionBounds.Min.X && leaf.Velocity.X < 0)
                        {
                            leaf.Velocity.X = -leaf.Velocity.X;
                        }
                        if (leaf.Position.Y < positionBounds.Min.Y && leaf.Velocity.Y < 0)
                        {
                            leaf.Velocity.Y = -leaf.Velocity.Y;
                        }
                        if (leaf.Position.Z < positionBounds.Min.Z && leaf.Velocity.Z < 0)
                        {
                            leaf.Velocity.Z = -leaf.Velocity.Z;
                        }

                        if (leaf.Position.X > positionBounds.Max.X && leaf.Velocity.X > 0)
                        {
                            leaf.Velocity.X = -leaf.Velocity.X;
                        }
                        if (leaf.Position.Y > positionBounds.Max.Y && leaf.Velocity.Y > 0)
                        {
                            leaf.Velocity.Y = -leaf.Velocity.Y;
                        }
                        if (leaf.Position.Z > positionBounds.Max.Z && leaf.Velocity.Z > 0)
                        {
                            leaf.Velocity.Z = -leaf.Velocity.Z;
                        }

                        leaf.Position += leaf.Velocity * dt;
                        BoundingBox boundingBox;
                        leaf.GetBoundingBox(out boundingBox);
                        tree.SetLeafBoundingBox(i, ref boundingBox);
                    }
                    var refineStartTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    int refinementCount;
                    if (looper.ThreadCount > 1)
                    {
                        refinementCount = tree.RefitAndRefine(t, looper, refineContext);
                    }
                    else
                    {
                        refinementCount = tree.RefitAndRefine(t);
                    }

                    var refineEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    int overlapsCount;
                    if (looper.ThreadCount > 1)
                    {
                        tree.GetSelfOverlaps(looper, selfTestContext);
                        overlapsCount = 0;
                        for (int i = 0; i < selfTestContext.WorkerOverlaps.Length; ++i)
                        {
                            overlapsCount += selfTestContext.WorkerOverlaps[i].Count;
                        }
                    }
                    else
                    {
                        overlaps.Count = 0;
                        tree.GetSelfOverlapsArityDedicated(ref overlaps);
                        overlapsCount = overlaps.Count;
                    }

                    var testEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    results.Refine[t]        = 1000 * (refineEndTime - refineStartTime);
                    results.SelfTest[t]      = 1000 * (testEndTime - refineEndTime);
                    results.Total[t]         = 1000 * (testEndTime - refineStartTime);
                    results.OverlapCounts[t] = overlapsCount;
                    results.TreeCosts[t]     = tree.MeasureCostMetric();

                    if (t % 16 == 0)
                    {
                        Console.WriteLine($"_________________{t}_________________");
                        Console.WriteLine($"Refinement count: {refinementCount}");
                        Console.WriteLine($"Refine time:      {results.Refine[t]}");
                        Console.WriteLine($"Test time:        {results.SelfTest[t]}");
                        Console.WriteLine($"TIME:             {results.Total[t]}");
                        Console.WriteLine($"Cost metric:      {results.TreeCosts[t]}");
                        Console.WriteLine($"Overlaps:         {results.OverlapCounts[t]}");
                        Console.WriteLine($"Cache Quality:    {tree.MeasureCacheQuality()}");
                        GC.Collect();
                    }
                    tree.Validate();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                tree.Validate();
                Console.WriteLine($"SingleArray Cache Quality: {tree.MeasureCacheQuality()}");
                Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");

                region.Dispose();
                tree.RemoveUnusedInternalNodes(ref spareNodes);
                BufferPools <int> .Thread.GiveBack(buffer);

                //********************

                tree.MeasureNodeOccupancy(out nodeCount, out childCount);
                Console.WriteLine($"SingleArray Occupancy: {childCount / (double)nodeCount}");

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < refitCount; ++i)
                {
                    //for (int i = 0; i < tree.LeafCount; ++i)
                    //{
                    //    BoundingBox box;
                    //    leaves[tree.Leaves[i].Id].GetBoundingBox(out box);
                    //    tree.UpdateLeafBoundingBox(i, ref box);
                    //}
                    tree.Refit();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Refit Time2: {endTime - startTime}");


                var list      = new QuickList <int>(new BufferPool <int>());
                var queryMask = queries.Length - 1;
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < queryCount; ++i)
                {
                    list.Count = 0;
                    //tree.Query2(ref queries[i & queryMask], ref list);
                    tree.QueryRecursive(ref queries[i & queryMask], ref list);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Query Time: {endTime - startTime}, overlaps: {list.Count}");
                Array.Clear(list.Elements, 0, list.Elements.Length);
                list.Dispose();

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlaps(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray SelfTree Time: {endTime - startTime}, overlaps: {overlaps.Count}");

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlapsArityDedicated(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray Arity-Dedicated SelfTree Time: {endTime - startTime}, overlaps: {overlaps.Count}");


                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    overlaps.Count = 0;
                    tree.GetSelfOverlapsViaQueries(ref overlaps);
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"SingleArray SelfQuery Time: {endTime - startTime}, overlaps: {overlaps.Count}");

                tree.Dispose();

                return(results);
            }
        }
        public static void TestSetResizing()
        {
            Random random = new Random(5);
            UnsafeBufferPool<int> pool = new UnsafeBufferPool<int>();
            QuickSet<int> set = new QuickSet<int>(pool, pool);
            HashSet<int> controlSet = new HashSet<int>();

            for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex)
            {
                if (random.NextDouble() < 0.7)
                {
                    set.Add(iterationIndex);
                    controlSet.Add(iterationIndex);
                }
                if (random.NextDouble() < 0.2)
                {
                    var indexToRemove = random.Next(set.Count);
                    var toRemove = set[indexToRemove];
                    set.FastRemove(toRemove);
                    controlSet.Remove(toRemove);
                }
                if (iterationIndex % 1000 == 0)
                {
                    set.EnsureCapacity(set.Count * 3);
                }
                else if (iterationIndex % 7777 == 0)
                {
                    set.Compact();
                }
            }

            Assert.IsTrue(set.Count == controlSet.Count);
            for (int i = 0; i < set.Count; ++i)
            {
                Assert.IsTrue(controlSet.Contains(set[i]));
            }
            foreach (var element in controlSet)
            {
                Assert.IsTrue(set.Contains(element));
            }
        }
Example #21
0
        /// <summary>
        /// Identifies the points on the surface of hull.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull.
        /// Each group of 3 indices represents a triangle on the surface of the hull.</param>
        /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param>
        public static void GetConvexHull(ref QuickList<Vector3> points, ref QuickList<int> outputTriangleIndices, IList<Vector3> outputSurfacePoints)
        {
            GetConvexHull(ref points, ref outputTriangleIndices);

            var alreadyContainedIndices = new QuickSet<int>(BufferPools<int>.Locking, BufferPools<int>.Locking);

            for (int i = outputTriangleIndices.Count - 1; i >= 0; i--)
            {
                int index = outputTriangleIndices[i];
                if (alreadyContainedIndices.Add(index))
                {
                    outputSurfacePoints.Add(points[index]);
                }
            }
            alreadyContainedIndices.Dispose();
        }