Exemple #1
0
            unsafe void Refine(int workerIndex)
            {
                var spareNodes           = new QuickList <int>(Pool, 8);
                var subtreeReferences    = new QuickList <int>(Pool, BufferPool <int> .GetPoolIndex(MaximumSubtrees));
                var treeletInternalNodes = new QuickList <int>(Pool, BufferPool <int> .GetPoolIndex(MaximumSubtrees));

                int[]           buffer;
                MemoryRegion    region;
                BinnedResources resources;

                CreateBinnedResources(Pool, MaximumSubtrees, out buffer, out region, out resources);

                int refineIndex;

                while ((refineIndex = Interlocked.Increment(ref RefineIndex)) < RefinementTargets.Count)
                {
                    subtreeReferences.Count    = 0;
                    treeletInternalNodes.Count = 0;
                    bool nodesInvalidated;
                    Tree.BinnedRefine(RefinementTargets.Elements[refineIndex], ref subtreeReferences, MaximumSubtrees, ref treeletInternalNodes, ref spareNodes, ref resources, out nodesInvalidated);
                    //Allow other refines to traverse this node.
                    Tree.nodes[RefinementTargets.Elements[refineIndex]].RefineFlag = 0;
                }

                Tree.RemoveUnusedInternalNodes(ref spareNodes);
                region.Dispose();
                Pool.GiveBack(buffer);
                spareNodes.Dispose();
                subtreeReferences.Count = 0;
                subtreeReferences.Dispose();
                treeletInternalNodes.Count = 0;
                treeletInternalNodes.Dispose();
            }
Exemple #2
0
        /// <summary>
        /// Clears and returns the list's buffers.
        /// </summary>
        public void Dispose()
        {
            Clear();
            pool.GiveBack(Elements, poolIndex);
#if DEBUG
            pool = null;
#endif
        }
        /// <summary>
        /// Clears and returns the set's buffers to the pools.
        /// </summary>
        public void Dispose()
        {
            //We must clean out the table before returning it to the pool.

            Clear();

            tablePool.GiveBack(table, tablePoolIndex);
            elementPool.GiveBack(Elements, elementPoolIndex);
#if DEBUG
            table = null;
#endif
        }
        /// <summary>
        /// Clears and returns the set's buffers to the pools.
        /// </summary>
        public void Dispose()
        {
            //We must clean out the table before returning it to the pool.

            Clear();

            tablePool.GiveBack(table, tablePoolIndex);
            keyPool.GiveBack(Keys, pairPoolIndex);
            valuePool.GiveBack(Values, pairPoolIndex);
#if DEBUG
            table = null;
#endif
        }
Exemple #5
0
        /// <summary>
        /// Clears and returns the set's buffers to the pools.
        /// </summary>
        public void Dispose()
        {
            //We must clean out the table before returning it to the pool in case the array contains reference types which would otherwise leak.
            //The user may have already manually cleared it. To avoid doing redundant work, check the count first.
            //The user may have chosen to leave reference types in the list if they did a fast clear, but that's not for us to worry about.
            if (Count > 0)
            {
                Clear();
            }

            tablePool.GiveBack(table, tablePoolIndex);
            elementPool.GiveBack(Elements, elementPoolIndex);
#if DEBUG
            table = null;
#endif
        }
        public unsafe void SweepBuild(int[] leafIds, BoundingBox[] leafBounds, int start = 0, int length = -1, BufferPool <int> intPool = null, BufferPool <float> floatPool = null)
        {
            if (leafIds.Length != leafBounds.Length)
            {
                throw new ArgumentException("leafIds and leafBounds lengths must be equal.");
            }
            if (start + length > leafIds.Length)
            {
                throw new ArgumentException("Start + length must be smaller than the leaves array length.");
            }
            if (start < 0)
            {
                throw new ArgumentException("Start must be nonnegative.");
            }
            if (length == 0)
            {
                throw new ArgumentException("Length must be positive.");
            }
            if (length < 0)
            {
                length = leafIds.Length;
            }
            if (nodes[0].ChildCount != 0)
            {
                throw new InvalidOperationException("Cannot build a tree that already contains nodes.");
            }
            //The tree is built with an empty node at the root to make insertion work more easily.
            //As long as that is the case (and as long as this is not a constructor),
            //we must clear it out.
            nodeCount = 0;

            //Guarantee that no resizes will occur during the build.
            if (LeafCapacity < leafBounds.Length)
            {
                LeafCapacity = leafBounds.Length;
            }
            var preallocatedNodeCount = leafBounds.Length * 2 - 1;

            if (NodeCapacity < preallocatedNodeCount)
            {
                NodeCapacity = preallocatedNodeCount;
            }

            //Gather necessary information and put it into a convenient format.

            var indexMap   = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var indexMapX  = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var indexMapY  = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var indexMapZ  = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var centroidsX = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length);
            var centroidsY = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length);
            var centroidsZ = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length);
            var mergedSize = leafIds.Length * (sizeof(BoundingBox) / sizeof(float));
            var merged     = floatPool == null ? new float[mergedSize] : floatPool.Take(mergedSize);

            fixed(BoundingBox *leafBoundsPointer = leafBounds)
            fixed(int *leafIdsPointer      = leafIds)
            fixed(int *indexMapPointer     = indexMap)
            fixed(int *indexMapXPointer    = indexMapX)
            fixed(int *indexMapYPointer    = indexMapY)
            fixed(int *indexMapZPointer    = indexMapZ)
            fixed(float *centroidsXPointer = centroidsX)
            fixed(float *centroidsYPointer = centroidsY)
            fixed(float *centroidsZPointer = centroidsZ)
            fixed(float *mergedPointer     = merged)
            {
                SweepResources leaves;

                leaves.Bounds     = leafBoundsPointer;
                leaves.Ids        = leafIdsPointer;
                leaves.IndexMap   = indexMapPointer;
                leaves.IndexMapX  = indexMapXPointer;
                leaves.IndexMapY  = indexMapYPointer;
                leaves.IndexMapZ  = indexMapZPointer;
                leaves.CentroidsX = centroidsXPointer;
                leaves.CentroidsY = centroidsYPointer;
                leaves.CentroidsZ = centroidsZPointer;
                leaves.Merged     = (BoundingBox *)mergedPointer;

                for (int i = 0; i < leafIds.Length; ++i)
                {
                    var bounds = leaves.Bounds[i];
                    leaves.IndexMap[i] = i;
                    //Per-axis index maps don't need to be initialized here. They're filled in at the time of use.

                    var centroid = bounds.Min + bounds.Max;
                    centroidsX[i] = centroid.X;
                    centroidsY[i] = centroid.Y;
                    centroidsZ[i] = centroid.Z;
                }


                //Now perform a top-down sweep build.
                CreateSweepBuilderNode(-1, -1, ref leaves, 0, leafIds.Length);
            }


            //Return resources.
            if (floatPool != null)
            {
                Array.Clear(centroidsX, 0, leafIds.Length);
                Array.Clear(centroidsY, 0, leafIds.Length);
                Array.Clear(centroidsZ, 0, leafIds.Length);
                Array.Clear(merged, 0, mergedSize);
                floatPool.GiveBack(centroidsX);
                floatPool.GiveBack(centroidsY);
                floatPool.GiveBack(centroidsZ);
                floatPool.GiveBack(merged);
            }
            if (intPool != null)
            {
                Array.Clear(indexMap, 0, leafIds.Length);
                Array.Clear(indexMapX, 0, leafIds.Length);
                Array.Clear(indexMapY, 0, leafIds.Length);
                Array.Clear(indexMapZ, 0, leafIds.Length);
                intPool.GiveBack(indexMap);
                intPool.GiveBack(indexMapX);
                intPool.GiveBack(indexMapY);
                intPool.GiveBack(indexMapZ);
            }
        }
        public unsafe void SweepBuild(int[] leafIds, BoundingBox[] leafBounds, int start = 0, int length = -1, BufferPool<int> intPool = null, BufferPool<float> floatPool = null)
        {
            if (leafIds.Length != leafBounds.Length)
                throw new ArgumentException("leafIds and leafBounds lengths must be equal.");
            if (start + length > leafIds.Length)
                throw new ArgumentException("Start + length must be smaller than the leaves array length.");
            if (start < 0)
                throw new ArgumentException("Start must be nonnegative.");
            if (length == 0)
                throw new ArgumentException("Length must be positive.");
            if (length < 0)
                length = leafIds.Length;
            if (nodes[0].ChildCount != 0)
                throw new InvalidOperationException("Cannot build a tree that already contains nodes.");
            //The tree is built with an empty node at the root to make insertion work more easily.
            //As long as that is the case (and as long as this is not a constructor),
            //we must clear it out.
            nodeCount = 0;

            //Guarantee that no resizes will occur during the build.
            if (LeafCapacity < leafBounds.Length)
            {
                LeafCapacity = leafBounds.Length;
            }
            var preallocatedNodeCount = leafBounds.Length * 2 - 1;
            if (NodeCapacity < preallocatedNodeCount)
            {
                NodeCapacity = preallocatedNodeCount;
            }

            //Gather necessary information and put it into a convenient format.

            var indexMap = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var indexMapX = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var indexMapY = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var indexMapZ = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length);
            var centroidsX = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length);
            var centroidsY = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length);
            var centroidsZ = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length);
            var mergedSize = leafIds.Length * (sizeof(BoundingBox) / sizeof(float));
            var merged = floatPool == null ? new float[mergedSize] : floatPool.Take(mergedSize);
            fixed (BoundingBox* leafBoundsPointer = leafBounds)
            fixed (int* leafIdsPointer = leafIds)
            fixed (int* indexMapPointer = indexMap)
            fixed (int* indexMapXPointer = indexMapX)
            fixed (int* indexMapYPointer = indexMapY)
            fixed (int* indexMapZPointer = indexMapZ)
            fixed (float* centroidsXPointer = centroidsX)
            fixed (float* centroidsYPointer = centroidsY)
            fixed (float* centroidsZPointer = centroidsZ)
            fixed (float* mergedPointer = merged)
            {
                SweepResources leaves;
                leaves.Bounds = leafBoundsPointer;
                leaves.Ids = leafIdsPointer;
                leaves.IndexMap = indexMapPointer;
                leaves.IndexMapX = indexMapXPointer;
                leaves.IndexMapY = indexMapYPointer;
                leaves.IndexMapZ = indexMapZPointer;
                leaves.CentroidsX = centroidsXPointer;
                leaves.CentroidsY = centroidsYPointer;
                leaves.CentroidsZ = centroidsZPointer;
                leaves.Merged = (BoundingBox*)mergedPointer;

                for (int i = 0; i < leafIds.Length; ++i)
                {
                    var bounds = leaves.Bounds[i];
                    leaves.IndexMap[i] = i;
                    //Per-axis index maps don't need to be initialized here. They're filled in at the time of use.

                    var centroid = bounds.Min + bounds.Max;
                    centroidsX[i] = centroid.X;
                    centroidsY[i] = centroid.Y;
                    centroidsZ[i] = centroid.Z;
                }

                //Now perform a top-down sweep build.
                CreateSweepBuilderNode(-1, -1, ref leaves, 0, leafIds.Length);

            }

            //Return resources.
            if (floatPool != null)
            {
                Array.Clear(centroidsX, 0, leafIds.Length);
                Array.Clear(centroidsY, 0, leafIds.Length);
                Array.Clear(centroidsZ, 0, leafIds.Length);
                Array.Clear(merged, 0, mergedSize);
                floatPool.GiveBack(centroidsX);
                floatPool.GiveBack(centroidsY);
                floatPool.GiveBack(centroidsZ);
                floatPool.GiveBack(merged);
            }
            if (intPool != null)
            {
                Array.Clear(indexMap, 0, leafIds.Length);
                Array.Clear(indexMapX, 0, leafIds.Length);
                Array.Clear(indexMapY, 0, leafIds.Length);
                Array.Clear(indexMapZ, 0, leafIds.Length);
                intPool.GiveBack(indexMap);
                intPool.GiveBack(indexMapX);
                intPool.GiveBack(indexMapY);
                intPool.GiveBack(indexMapZ);
            }
        }