コード例 #1
0
        public unsafe void GetSelfOverlapsViaQueries <TResultList>(ref TResultList results) where TResultList : IList <Overlap>
        {
            var leafQueryResults = new QuickList <int>(BufferPools <int> .Thread);

            for (int i = 0; i < leafCount; ++i)
            {
                var             leaf = leaves[i];
                BoundingBoxWide leafBoundingBox;
                BoundingBoxWide.GetBoundingBox(ref Levels[leaf.LevelIndex].Nodes[leaf.NodeIndex].BoundingBoxes, leaf.ChildIndex, out leafBoundingBox);
                TestRecursive(0, 0, ref leafBoundingBox, ref leafQueryResults);
                for (int j = 0; j < leafQueryResults.Count; ++j)
                {
                    //Only include results which which are forward in the list to avoid self tests.
                    if (i < leafQueryResults.Elements[j])
                    {
                        results.Add(new Overlap {
                            A = i, B = leafQueryResults.Elements[j]
                        });
                    }
                }
                leafQueryResults.Count = 0;
            }
            leafQueryResults.Dispose();
            //Console.WriteLine("Query-based results:");
            //for (int i = 0; i < results.Count; ++i)
            //{
            //    Console.WriteLine($"{results[i].A}, {results[i].B}");
            //}
        }
コード例 #2
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
 public unsafe void Refit()
 {
     //Go through each level, refitting as you go.
     //Note that the deepest level is skipped. It does not need to be tested; it's all leaves that were already updated.
     for (int levelIndex = maximumDepth - 1; levelIndex >= 0; --levelIndex)
     {
         //consider testing caching Levels[levelIndex]. It may have a minor effect.
         for (int nodeIndex = 0; nodeIndex < Levels[levelIndex].Count; ++nodeIndex)
         {
             for (int childIndex = 0; childIndex < Vector <int> .Count; ++childIndex)
             {
                 var childNodeIndex = Levels[levelIndex].Nodes[nodeIndex].Children[childIndex];
                 if (childNodeIndex >= 0)
                 {
                     BoundingBoxWide merged;
                     ComputeBoundingBox(ref Levels[levelIndex + 1].Nodes[childNodeIndex].BoundingBoxes, out merged);
                     BoundingBoxWide.ConditionalSelect(ref singleMasks[childIndex],
                                                       ref merged,
                                                       ref Levels[levelIndex].Nodes[nodeIndex].BoundingBoxes,
                                                       out Levels[levelIndex].Nodes[nodeIndex].BoundingBoxes);
                 }
             }
         }
     }
 }
コード例 #3
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        //[MethodImpl(MethodImplOptions.AggressiveInlining)]
        unsafe void TestRecursive <TResultList>(int level, int nodeIndex,
                                                ref BoundingBoxWide query,
                                                ref TResultList results) where TResultList : IList <int>
        {
            Vector <int> intersectionMask;

            BoundingBoxWide.Intersects(ref Levels[level].Nodes[nodeIndex].BoundingBoxes, ref query, out intersectionMask);
            //Console.WriteLine($"Intersection mask: {intersectionMask}");
            //Console.WriteLine(node.BoundingBoxes);
            //int INTERSECTEDCOUNT = 0;
            for (int i = 0; i < Vector <int> .Count; ++i)
            {
                if (intersectionMask[i] < 0)
                {
                    //++INTERSECTEDCOUNT;
                    if (Levels[level].Nodes[nodeIndex].Children[i] >= 0)
                    {
                        TestRecursive(level + 1, Levels[level].Nodes[nodeIndex].Children[i], ref query, ref results);
                    }
                    else if (Levels[level].Nodes[nodeIndex].Children[i] < -1)
                    {
                        results.Add(Encode(Levels[level].Nodes[nodeIndex].Children[i]));
                    }
                }
            }
            //Console.WriteLine($"Level {level}, intersected count: {INTERSECTEDCOUNT}");
        }
コード例 #4
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        unsafe void Test <TResultList>(TraversalTarget *stack, ref int count, int stackCapacity, int level,
                                       ref BoundingBoxWide query, ref Node node,
                                       ref TResultList results) where TResultList : IList <int>
        {
            Vector <int> intersectionMask;

            BoundingBoxWide.Intersects(ref node.BoundingBoxes, ref query, out intersectionMask);
            //Console.WriteLine($"Intersection mask: {intersectionMask}");
            //Console.WriteLine(node.BoundingBoxes);
            for (int i = 0; i < Vector <int> .Count; ++i)
            {
                if (intersectionMask[i] < 0)
                {
                    if (node.Children[i] >= 0)
                    {
                        Debug.Assert(count < stackCapacity);
                        stack[count++] = new TraversalTarget {
                            Level = level + 1, Node = node.Children[i]
                        };
                    }
                    else if (node.Children[i] < -1)
                    {
                        results.Add(Encode(node.Children[i]));
                    }
                }
            }
        }
コード例 #5
0
        unsafe void GetOverlapsBetweenDifferentNodes <TResultList>(int levelIndex, int aIndex, int bIndex, ref TResultList results) where TResultList : IList <Overlap>
        {
            //There are no shared children, so test them all.
            var a         = Levels[levelIndex].Nodes[aIndex];
            var b         = Levels[levelIndex].Nodes[bIndex];
            int nextLevel = levelIndex + 1;

            for (int i = 0; i < Vector <float> .Count; ++i)
            {
                if (a.Children[i] == -1)
                {
                    continue;
                }
                //REALLY want a shuffle here. If we could just push forward, retest, push forward, retest...
                //Unclear how much of a performance benefit this would actually be, since this is just a series of broadcasts.
                //... not sure it's actually compiled to a series of broadcasts, though.
                Vector <int>    intersectionMask;
                BoundingBoxWide aWide;
                BoundingBoxWide.GetBoundingBox(ref a.BoundingBoxes, i, out aWide);
                //var aChild = new Vector<int>(a.Children[i]);
                //var less = Vector.LessThan(aChild, b.Children);
                //var bChildIsVector.LessThan(b.Children, new Vector<int>(-1));
                BoundingBoxWide.Intersects(ref aWide, ref b.BoundingBoxes, out intersectionMask);
                for (int j = 0; j < Vector <float> .Count; ++j)
                {
                    //TODO: would it be faster to compute a single combined value via simd and then use a single switch?
                    if (b.Children[j] != -1 && intersectionMask[j] < 0)
                    {
                        //TODO: try removing branches via bool ops
                        if (a.Children[i] >= 0 && b.Children[j] >= 0)
                        {
                            GetOverlapsBetweenDifferentNodes(nextLevel, a.Children[i], b.Children[j], ref results);
                        }
                        else if (a.Children[i] < -1 && b.Children[j] >= 0)
                        {
                            //leaf A versus node B.
                            TestLeafAgainstNode(Encode(a.Children[i]), ref aWide, nextLevel, b.Children[j], ref results);
                        }
                        else if (a.Children[i] >= 0 && b.Children[j] < -1)
                        {
                            //leaf B versus node A.
                            BoundingBoxWide bWide;
                            BoundingBoxWide.GetBoundingBox(ref b.BoundingBoxes, j, out bWide);
                            TestLeafAgainstNode(Encode(b.Children[j]), ref bWide, nextLevel, a.Children[i], ref results);
                        }
                        else if (a.Children[i] < -1 && b.Children[j] < -1)
                        {
                            //Two leaves.
                            var leafA = Encode(a.Children[i]);
                            var leafB = Encode(b.Children[j]);
                            results.Add(new Overlap {
                                A = leafA, B = leafB
                            });
                        }
                    }
                }
            }
        }
コード例 #6
0
            public void Add(ref StreamingLeafGroup parent, int sourceIndex, int destinationIndex, Vector <int>[] masks)
            {
                //This is basically: a[i] = b[j]
                var             leavesBroadcast = new Vector <int>(parent.Leaves[sourceIndex]);
                BoundingBoxWide boundsBroadcast;

                BoundingBoxWide.GetBoundingBox(ref parent.BoundingBoxes, sourceIndex, out boundsBroadcast);
                Leaves = Vector.ConditionalSelect(masks[destinationIndex], leavesBroadcast, Leaves);
                BoundingBoxWide.ConditionalSelect(ref masks[destinationIndex], ref boundsBroadcast, ref BoundingBoxes, out BoundingBoxes);
            }
コード例 #7
0
 public void Add(ref Vector <int> leafIndex, ref BoundingBoxWide boundingBox, Vector <int>[] masks)
 {
     if (LastLeavesCount < Vector <float> .Count)
     {
         LeafGroups.Elements[LeafGroups.Count - 1].Add(ref boundingBox, ref leafIndex, ref masks[LastLeavesCount]);
         ++LastLeavesCount;
     }
     else
     {
         var newLeaves = new StreamingLeafGroup();
         newLeaves.Add(ref boundingBox, ref leafIndex, ref masks[0]);
         LeafGroups.Add(ref newLeaves);
         LastLeavesCount = 1;
     }
 }
コード例 #8
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        public unsafe void RefitLeaves()
        {
            //Update the bounding boxes of every leaf-owner.
            //Note the scalar-ness of this. It seems like there should exist some way to vectorize it properly, though it may require changing things around.
            for (int i = 0; i < leafCount; ++i)
            {
                BoundingBox box;
                leaves[i].Bounded.GetBoundingBox(out box);
                BoundingBoxWide wideBox = new BoundingBoxWide(ref box);
                //Console.WriteLine($"index reached: {i}, child index: {leaves[i].ChildIndex}, level: {leaves[i].LevelIndex}, node: { leaves[i].NodeIndex}");

                BoundingBoxWide.ConditionalSelect(ref singleMasks[leaves[i].ChildIndex],
                                                  ref wideBox,
                                                  ref Levels[leaves[i].LevelIndex].Nodes[leaves[i].NodeIndex].BoundingBoxes,
                                                  out Levels[leaves[i].LevelIndex].Nodes[leaves[i].NodeIndex].BoundingBoxes);
                //Console.WriteLine($"comp");
            }
        }
コード例 #9
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        //[MethodImpl(MethodImplOptions.AggressiveInlining)]
        public unsafe void Query <TResultList>(ref BoundingBox boundingBox, ref TResultList results) where TResultList : IList <int>
        {
            //TODO: could optimize this by keeping the next target out of the stack.
            var stackCapacity = (Vector <int> .Count - 1) * maximumDepth + 1;
            var stack         = stackalloc TraversalTarget[stackCapacity];
            int count         = 0;

            var boundingBoxWide = new BoundingBoxWide(ref boundingBox);

            Test(stack, ref count, stackCapacity, 0, ref boundingBoxWide, ref Levels[0].Nodes[0], ref results);

            while (count > 0)
            {
                --count;
                var target = stack[count];

                Test(stack, ref count, stackCapacity, target.Level, ref boundingBoxWide, ref Levels[target.Level].Nodes[target.Node], ref results);
            }
        }
コード例 #10
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        void ComputeBoundingBox(ref BoundingBoxWide boundingBoxes, out BoundingBoxWide mergedWide)
        {
            //YIKES transposition
            BoundingBox merged;

            merged.Min = new Vector3(float.MaxValue);
            merged.Max = new Vector3(-float.MaxValue);
            for (int childIndex = 0; childIndex < Vector <int> .Count; ++childIndex)
            {
                var childMin = new Vector3(
                    boundingBoxes.Min.X[childIndex],
                    boundingBoxes.Min.Y[childIndex],
                    boundingBoxes.Min.Z[childIndex]);
                var childMax = new Vector3(
                    boundingBoxes.Max.X[childIndex],
                    boundingBoxes.Max.Y[childIndex],
                    boundingBoxes.Max.Z[childIndex]);
                merged.Min = Vector3.Min(merged.Min, childMin);
                merged.Max = Vector3.Max(merged.Max, childMax);
            }
            mergedWide = new BoundingBoxWide(ref merged);
        }
コード例 #11
0
        unsafe void TestLeafAgainstNode <TResultList>(int leaf, ref BoundingBoxWide leafBounds, int levelIndex, int nodeIndex, ref TResultList results) where TResultList : IList <Overlap>
        {
            int          nextLevel = levelIndex + 1;
            Vector <int> intersectionMask;

            BoundingBoxWide.Intersects(ref leafBounds, ref Levels[levelIndex].Nodes[nodeIndex].BoundingBoxes, out intersectionMask);
            for (int i = 0; i < Vector <int> .Count; ++i)
            {
                if (intersectionMask[i] < 0)
                {
                    if (Levels[levelIndex].Nodes[nodeIndex].Children[i] < -1)
                    {
                        var otherLeaf = Encode(Levels[levelIndex].Nodes[nodeIndex].Children[i]);
                        results.Add(new Overlap {
                            A = leaf, B = otherLeaf
                        });
                    }
                    else if (Levels[levelIndex].Nodes[nodeIndex].Children[i] >= 0)
                    {
                        TestLeafAgainstNode(leaf, ref leafBounds, nextLevel, Levels[levelIndex].Nodes[nodeIndex].Children[i], ref results);
                    }
                }
            }
        }
コード例 #12
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        public unsafe void QueryRecursive <TResultList>(ref BoundingBox boundingBox, ref TResultList results) where TResultList : IList <int>
        {
            var boundingBoxWide = new BoundingBoxWide(ref boundingBox);

            TestRecursive(0, 0, ref boundingBoxWide, ref results);
        }
コード例 #13
0
ファイル: Tree.cs プロジェクト: jj-jabb/scratchpad
        public unsafe void Insert(T leaf)
        {
            int         levelIndex = 0;
            int         nodeIndex  = 0;
            BoundingBox aosBox;

            leaf.GetBoundingBox(out aosBox);
            var box = new BoundingBoxWide(ref aosBox);

#if OUTPUT
            List <int> choices = new List <int>();
#endif
            while (true)
            {
                var level = Levels[levelIndex];
                //Which child should the leaf belong to?
                Vector <float> originalVolumes;
                BoundingBoxWide.ComputeVolume(ref level.Nodes[nodeIndex].BoundingBoxes, out originalVolumes);
                originalVolumes = Vector.Max(originalVolumes, Vector <float> .Zero);
                BoundingBoxWide merged;
                BoundingBoxWide.Merge(ref level.Nodes[nodeIndex].BoundingBoxes, ref box, out merged);
                Vector <float> mergedVolumes;
                BoundingBoxWide.ComputeVolume(ref merged, out mergedVolumes);

                //Give the leaf to whichever node had the least volume change.
                var volumeIncreases = mergedVolumes - originalVolumes;
                int minimumIndex    = 0;
                var minimum         = volumeIncreases[0];
                for (int i = 1; i < Vector <float> .Count; ++i)
                {
                    if (volumeIncreases[i] < minimum)
                    {
                        minimumIndex = i;
                        minimum      = volumeIncreases[i];
                    }
                }

                //var volumeIncreases = mergedVolumes - originalVolumes;
                //int minimumIndex = 0;
                //var minimum = float.MaxValue;
                //for (int i = 0; i < Vector<float>.Count; ++i)
                //{
                //    if (level.Nodes[nodeIndex].Children[i] == -1)
                //    {
                //        minimumIndex = i;
                //        break;
                //    }
                //    if (volumeIncreases[i] < minimum)
                //    {
                //        minimumIndex = i;
                //        minimum = volumeIncreases[i];
                //    }
                //}
#if OUTPUT
                Console.WriteLine($"Minimum index: {minimumIndex}, minimum volume increase: {minimum}");
                choices.Add(minimumIndex);
#endif

                var childIndex = level.Nodes[nodeIndex].Children[minimumIndex];

                if (childIndex < -1)
                {
                    //It's a leaf node.
                    //Create a new internal node with the new leaf and the old leaf as children.
                    var nextLevel = levelIndex + 1;
                    //this is the only place where a new level could potentially be created.
                    EnsureLevel(nextLevel);
                    Node newNode;
                    InitializeNode(out newNode);
                    //The first child of the new node is the old leaf. Insert its bounding box.
                    //Since we don't have a great way of shuffling yet, just let it be in the same index.
                    BoundingBoxWide.ConditionalSelect(
                        ref singleMasks[minimumIndex],
                        ref level.Nodes[nodeIndex].BoundingBoxes,
                        ref newNode.BoundingBoxes,
                        out newNode.BoundingBoxes);
                    newNode.Children = Vector.ConditionalSelect(singleMasks[minimumIndex], level.Nodes[nodeIndex].Children, newNode.Children);

                    //Insert the new leaf into the second child slot.
                    //Just put it in the next slot over from the minimum.
                    var newLeafChildIndex = (minimumIndex + 1) & (Vector <float> .Count - 1);
                    BoundingBoxWide.ConditionalSelect(
                        ref singleMasks[newLeafChildIndex],
                        ref box,
                        ref newNode.BoundingBoxes,
                        out newNode.BoundingBoxes);
                    var newNodeIndex    = Levels[nextLevel].Add(ref newNode);
                    var leafIndex       = AddLeaf(leaf, nextLevel, newNodeIndex, newLeafChildIndex);
                    var leafIndexVector = new Vector <int>(Encode(leafIndex));
                    Levels[nextLevel].Nodes[newNodeIndex].Children = Vector.ConditionalSelect(singleMasks[newLeafChildIndex], leafIndexVector, newNode.Children);

                    //Update the old leaf node with the new index information.
                    var oldLeafIndex = Encode(childIndex);
                    leaves[oldLeafIndex].LevelIndex = nextLevel;
                    leaves[oldLeafIndex].NodeIndex  = newNodeIndex;
                    //Since we inserted it into the same slot of the new node as it was in in the old node, there is no change to the child index.

                    //Update the original node's child pointer and bounding box.
                    var newNodeIndexVector = new Vector <int>(newNodeIndex);
                    level.Nodes[nodeIndex].Children = Vector.ConditionalSelect(singleMasks[minimumIndex], newNodeIndexVector, level.Nodes[nodeIndex].Children);
                    BoundingBoxWide.ConditionalSelect(ref singleMasks[minimumIndex], ref merged, ref level.Nodes[nodeIndex].BoundingBoxes, out level.Nodes[nodeIndex].BoundingBoxes);

#if OUTPUT
                    Console.WriteLine($"Leaf {leafIndex} merged with existing leaf.");// New Node Children: {newNode.Children}, Old Node children: {level.Nodes[nodeIndex].Children}");
                    Console.WriteLine($"Choices: {GetChoiceList(choices)}");
#endif

                    break;
                }
                if (childIndex == -1)
                {
                    //There is no child at all.
                    //Put the new leaf here.
                    var leafIndex       = AddLeaf(leaf, levelIndex, nodeIndex, minimumIndex);
                    var leafIndexVector = new Vector <int>(Encode(leafIndex));
                    level.Nodes[nodeIndex].Children = Vector.ConditionalSelect(singleMasks[minimumIndex], leafIndexVector, level.Nodes[nodeIndex].Children);
                    BoundingBoxWide.ConditionalSelect(ref singleMasks[minimumIndex], ref merged, ref level.Nodes[nodeIndex].BoundingBoxes, out level.Nodes[nodeIndex].BoundingBoxes);

#if OUTPUT
                    Console.WriteLine($"Leaf {leafIndex} inserted in empty slot.");
                    Console.WriteLine($"Choices: {GetChoiceList(choices)}");
#endif
                    break;
                }
                //It's an internal node. Traverse to the next node.
                BoundingBoxWide.ConditionalSelect(ref singleMasks[minimumIndex], ref merged, ref level.Nodes[nodeIndex].BoundingBoxes, out level.Nodes[nodeIndex].BoundingBoxes);
                nodeIndex = level.Nodes[nodeIndex].Children[minimumIndex];
                ++levelIndex;
            }
        }
コード例 #14
0
        public unsafe void GetSelfOverlapsViaStreamingQueries <TResultList>(ref TResultList results) where TResultList : IList <Overlap>
        {
            //var startTime = Stopwatch.GetTimestamp();
            var rootTarget = new StreamingTarget {
                LeafGroups = new QuickList <StreamingLeafGroup>(BufferPools <StreamingLeafGroup> .Locking, BufferPool <StreamingLeafGroup> .GetPoolIndex(LeafCount))
            };

            rootTarget.LeafGroups.Add(new StreamingLeafGroup());
            for (int i = 0; i < LeafCount; ++i)
            {
                BoundingBoxWide leafWide;
                BoundingBoxWide.GetBoundingBox(ref Levels[leaves[i].LevelIndex].Nodes[leaves[i].NodeIndex].BoundingBoxes, leaves[i].ChildIndex, out leafWide);
                var leafIndexWide = new Vector <int>(i);
                rootTarget.Add(ref leafIndexWide, ref leafWide, singleMasks);
            }
            //var endTime = Stopwatch.GetTimestamp();
            //Console.WriteLine($"Initial target construction time: {(endTime - startTime) / (double)Stopwatch.Frequency}");

            QuickQueue <StreamingTarget> targets = new QuickQueue <StreamingTarget>(BufferPools <StreamingTarget> .Locking, BufferPool <StreamingLeafGroup> .GetPoolIndex(LeafCount));

            targets.Enqueue(ref rootTarget);

            QuickList <int> fallbackResults = new QuickList <int>(BufferPools <int> .Locking);

            StreamingTarget target;

            while (targets.TryDequeueLast(out target))
            {
                const int GroupFallbackThreshold = 2; //unfortunately, this should be as high as possible right now because the regular query is faster, period.
                if (target.LeafGroups.Count <= GroupFallbackThreshold)
                {
                    var max = target.LastLeavesCount == Vector <int> .Count ? target.LeafGroups.Count : target.LeafGroups.Count - 1;
                    for (int leafGroupIndex = 0; leafGroupIndex < max; ++leafGroupIndex)
                    {
                        for (int leafInGroupIndex = 0; leafInGroupIndex < Vector <int> .Count; ++leafInGroupIndex)
                        {
                            BoundingBoxWide leafWide;
                            BoundingBoxWide.GetBoundingBox(ref target.LeafGroups.Elements[leafGroupIndex].BoundingBoxes, leafInGroupIndex, out leafWide);
                            TestRecursive(target.LevelIndex, target.NodeIndex, ref leafWide, ref fallbackResults);
                            for (int resultIndex = 0; resultIndex < fallbackResults.Count; ++resultIndex)
                            {
                                var queryLeafIndex = target.LeafGroups.Elements[leafGroupIndex].Leaves[leafInGroupIndex];
                                if (queryLeafIndex < fallbackResults.Elements[resultIndex])
                                {
                                    results.Add(new Overlap {
                                        A = queryLeafIndex, B = fallbackResults.Elements[resultIndex]
                                    });
                                }
                            }
                            fallbackResults.Count = 0;
                        }
                    }
                    if (target.LastLeavesCount < Vector <int> .Count)
                    {
                        var leafGroupIndex = target.LeafGroups.Count - 1;
                        for (int leafInGroupIndex = 0; leafInGroupIndex < target.LastLeavesCount; ++leafInGroupIndex)
                        {
                            BoundingBoxWide leafWide;
                            BoundingBoxWide.GetBoundingBox(ref target.LeafGroups.Elements[leafGroupIndex].BoundingBoxes, leafInGroupIndex, out leafWide);
                            TestRecursive(target.LevelIndex, target.NodeIndex, ref leafWide, ref fallbackResults);
                            for (int resultIndex = 0; resultIndex < fallbackResults.Count; ++resultIndex)
                            {
                                var queryLeafIndex = target.LeafGroups.Elements[leafGroupIndex].Leaves[leafInGroupIndex];
                                if (queryLeafIndex < fallbackResults.Elements[resultIndex])
                                {
                                    results.Add(new Overlap {
                                        A = queryLeafIndex, B = fallbackResults.Elements[resultIndex]
                                    });
                                }
                            }
                            fallbackResults.Count = 0;
                        }
                    }
                }
                else
                {
                    var node = Levels[target.LevelIndex].Nodes[target.NodeIndex];



                    //Test each node child against all of the leaves for this node.
                    for (int nodeChildIndex = 0; nodeChildIndex < Vector <int> .Count; ++nodeChildIndex)
                    {
                        if (node.Children[nodeChildIndex] == -1)
                        {
                            continue;
                        }

                        BoundingBoxWide nodeChildWide;
                        BoundingBoxWide.GetBoundingBox(ref node.BoundingBoxes, nodeChildIndex, out nodeChildWide);

                        if (node.Children[nodeChildIndex] >= 0)
                        {
                            //Internal node. Can spawn more targets.
                            StreamingTarget newTarget = new StreamingTarget
                            {
                                LevelIndex = target.LevelIndex + 1,
                                NodeIndex  = node.Children[nodeChildIndex],
                                LeafGroups = new QuickList <StreamingLeafGroup>(BufferPools <StreamingLeafGroup> .Locking, BufferPool <StreamingLeafGroup> .GetPoolIndex(target.LeafGroups.Count))
                            };
                            newTarget.LeafGroups.Add(new StreamingLeafGroup());


                            for (int leafGroupIndex = 0; leafGroupIndex < target.LeafGroups.Count; ++leafGroupIndex)
                            {
                                Vector <int> intersectionMask;
                                BoundingBoxWide.Intersects(ref nodeChildWide, ref target.LeafGroups.Elements[leafGroupIndex].BoundingBoxes, out intersectionMask);

                                int leafCountInGroup = leafGroupIndex == target.LeafGroups.Count - 1 ? target.LastLeavesCount : Vector <int> .Count;

                                for (int leafIndexInGroup = 0; leafIndexInGroup < leafCountInGroup; ++leafIndexInGroup)
                                {
                                    if (intersectionMask[leafIndexInGroup] < 0)
                                    {
                                        newTarget.Add(ref target, leafGroupIndex, leafIndexInGroup, singleMasks);
                                    }
                                }
                            }
                            targets.Enqueue(ref newTarget);
                        }
                        else
                        {
                            //Leaf node.

                            var nodeLeafIndex = Encode(node.Children[nodeChildIndex]);

                            for (int leafGroupIndex = 0; leafGroupIndex < target.LeafGroups.Count; ++leafGroupIndex)
                            {
                                Vector <int> intersectionMask;
                                BoundingBoxWide.Intersects(ref nodeChildWide, ref target.LeafGroups.Elements[leafGroupIndex].BoundingBoxes, out intersectionMask);

                                int leafCountInGroup = leafGroupIndex == target.LeafGroups.Count - 1 ? target.LastLeavesCount : Vector <int> .Count;

                                for (int leafIndexInGroup = 0; leafIndexInGroup < leafCountInGroup; ++leafIndexInGroup)
                                {
                                    if (intersectionMask[leafIndexInGroup] < 0)
                                    {
                                        var leafIndex = target.LeafGroups[leafGroupIndex].Leaves[leafIndexInGroup];
                                        if (leafIndex < nodeLeafIndex) //The other leaf will also find a collision!
                                        {
                                            results.Add(new Overlap {
                                                A = leafIndex, B = nodeLeafIndex
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                target.LeafGroups.Count = 0; //Don't bother forcing a clear on these. TODO: buffer safety check disable
                target.LeafGroups.Dispose();
            }
            targets.Dispose();
            fallbackResults.Dispose();

            //Console.WriteLine("Streaming Query based results:");
            //for (int i = 0; i < results.Count; ++i)
            //{
            //    Console.WriteLine($"{results[i].A}, {results[i].B}");
            //}
        }
コード例 #15
0
 public void Add(ref BoundingBoxWide boundingBox, ref Vector <int> leafIndex, ref Vector <int> destinationMask)
 {
     Leaves = Vector.ConditionalSelect(destinationMask, leafIndex, Leaves);
     BoundingBoxWide.ConditionalSelect(ref destinationMask, ref boundingBox, ref BoundingBoxes, out BoundingBoxes);
 }