unsafe void PushPair(int encodedLeafIndex, BoundingBox *leafBounds, int b, PairToTest *stack, ref int nextToVisit) { //Potential microoptimizations here stack[++nextToVisit] = new PairToTest { A = encodedLeafIndex, B = b, LeafBounds = leafBounds }; }
unsafe void TestDifferent <TResultList>(int a, int b, BoundingBox *aBounds, BoundingBox *bBounds, TestPair *stack, ref int nextToVisit, ref TResultList results) where TResultList : IList <Overlap> { if (a >= 0) { if (b >= 0) { //both internal nodes PushDifferent(nodes + a, nodes + b, stack, ref nextToVisit); } else { //leaf and internal PushLeafInternal(nodes + a, bBounds, b, stack, ref nextToVisit); } } else if (b >= 0) { //leaf and internal PushLeafInternal(nodes + b, aBounds, a, stack, ref nextToVisit); } else { //two leaves results.Add(new Overlap { A = Encode(a), B = Encode(b) }); } }
unsafe void TestDifferentNodes <TResultList>(int childA, int childB, BoundingBox *a, BoundingBox *b, PairToTest *stack, ref int nextToVisit, ref TResultList results) where TResultList : IList <Overlap> { if (childA >= 0) { if (childB >= 0) { PushPair(childA, childB, stack, ref nextToVisit); } else { //leaf B versus node A. PushPair(childB, b, childA, stack, ref nextToVisit); } } else if (childB >= 0) { //leaf A versus node B. PushPair(childA, a, childB, stack, ref nextToVisit); } else { //Two leaves. results.Add(new Overlap { A = Encode(childA), B = Encode(childB) }); } }
unsafe void TestDifferentNodes<TResultList>(BoundingBox* a, BoundingBox* b, int childA, int childB, int leafCountA, int leafCountB, ref PriorityQueue queue, ref QuickList<TestPair2> pairsToTest, ref TResultList results) where TResultList : IList<Overlap> { if (childA >= 0) { if (childB >= 0) { PushDifferent(childA, childB, leafCountA, leafCountB, ref queue, ref pairsToTest); } else { //leaf B versus node A. PushLeafInternal(childA, leafCountA, b, childB, ref queue, ref pairsToTest); } } else if (childB >= 0) { //leaf A versus node B. PushLeafInternal(childB, leafCountB, a, childA, ref queue, ref pairsToTest); } else { //Two leaves. results.Add(new Overlap { A = Encode(childA), B = Encode(childB) }); } }
unsafe void PushLeafInternal(Node *internalNode, BoundingBox *leafBounds, int encodedLeafIndex, TestPair *stack, ref int count) { var element = stack + count++; element->A = internalNode; element->LeafBounds = leafBounds; element->EncodedLeafIndex = encodedLeafIndex; element->Type = PairType.LeafInternal; }
public unsafe BoundingBoxWide(BoundingBox *boundingBoxes, Vector <int>[] masks) { Min = new Vector3Wide(ref boundingBoxes[0].Min); Max = new Vector3Wide(ref boundingBoxes[0].Max); for (int i = 1; i < Vector <float> .Count; ++i) { BoundingBoxWide wide = new BoundingBoxWide(ref boundingBoxes[i]); ConditionalSelect(ref masks[i], ref wide, ref this, out this); } }
unsafe void FindPartitionForAxis(BoundingBox *boundingBoxes, BoundingBox *aMerged, float *centroids, int *indexMap, int count, out int splitIndex, out float cost, out BoundingBox a, out BoundingBox b, out int leafCountA, out int leafCountB) { Debug.Assert(count > 1); Quicksort(centroids, indexMap, 0, count - 1); //Search for the best split. //Sweep across from low to high, caching the merged size and leaf count at each point. //Index N includes every subtree from 0 to N, inclusive. So index 0 contains subtree 0's information. var lastIndex = count - 1; aMerged[0] = boundingBoxes[indexMap[0]]; for (int i = 1; i < lastIndex; ++i) { var index = indexMap[i]; BoundingBox.Merge(ref aMerged[i - 1], ref boundingBoxes[index], out aMerged[i]); } //Sweep from high to low. BoundingBox bMerged = new BoundingBox { Min = new Vector3(float.MaxValue), Max = new Vector3(float.MinValue) }; cost = float.MaxValue; splitIndex = 0; a = bMerged; b = bMerged; leafCountA = 0; leafCountB = 0; for (int i = lastIndex; i >= 1; --i) { int aIndex = i - 1; var subtreeIndex = indexMap[i]; BoundingBox.Merge(ref bMerged, ref boundingBoxes[subtreeIndex], out bMerged); var aCost = i * ComputeBoundsMetric(ref aMerged[aIndex]); var bCost = (count - i) * ComputeBoundsMetric(ref bMerged); var totalCost = aCost + bCost; if (totalCost < cost) { cost = totalCost; splitIndex = i; a = aMerged[aIndex]; b = bMerged; leafCountA = i; leafCountB = count - i; } } }
public extern static unsafe CONTAIN_TYPE SDK_v3dxFrustum_WhichContainTypeFastWithTransform(IntPtr frustum, BoundingBox *box, Matrix *matrix, int testInner);
public extern static unsafe CONTAIN_TYPE SDK_v3dxFrustum_WhichContainTypeFast(IntPtr frustum, BoundingBox *box, int testInner);
public extern static unsafe void SDK_GfxMeshPrimitives_SetAABB(NativePointer self, BoundingBox *box);
public extern static unsafe vBOOL SDK_GfxMeshPrimitives_InitFromGeomtryMesh(NativePointer self, CRenderContext.NativePointer rc, CGeometryMesh.NativePointer mesh, UInt32 atom, BoundingBox *box);
private extern static unsafe CGeometryMesh.NativePointer SDK_IGeometryMesh_MergeGeoms(CRenderContext.NativePointer rc, CGeometryMesh.NativePointer *meshArray, Matrix *scaleArray, int count, BoundingBox *aabb);
unsafe void PushLeafInternal(int internalIndex, int leafCount, BoundingBox* leafBounds, int encodedLeafIndex, ref PriorityQueue queue, ref QuickList<TestPair2> pairsToTest) { queue.Insert(pairsToTest.Count, (float)Math.Log(leafCount)); //queue.Insert(pairsToTest.Count, leafCount); pairsToTest.Add(new TestPair2 { A = internalIndex, LeafBounds = leafBounds, B = encodedLeafIndex, Type = PairType.LeafInternal }); }
unsafe void FindPartitionForAxis(BoundingBox *boundingBoxes, int *leafCounts, float *centroids, int *indexMap, int subtreeCount, out int splitIndex, out float cost, out BoundingBox a, out BoundingBox b, out int leafCountA, out int leafCountB) { Debug.Assert(subtreeCount > 1); //Sort the index map according to the centroids. //for (int i = 1; i < subtreeCount; ++i) //{ // var index = i; // var previousIndex = index - 1; // while (centroids[indexMap[index]] < centroids[indexMap[previousIndex]]) // { // var tempPointer = indexMap[index]; // indexMap[index] = indexMap[previousIndex]; // indexMap[previousIndex] = tempPointer; // if (previousIndex == 0) // break; // index = previousIndex; // --previousIndex; // } //} Quicksort(centroids, indexMap, 0, subtreeCount - 1); //for (int i = 1; i < subtreeCount; ++i) //{ // if (centroids[indexMap[i]] < centroids[indexMap[i - 1]]) // { // Console.WriteLine("not sorteD"); // } //} //Search for the best split. //Sweep across from low to high, caching the merged size and leaf count at each point. //Index N includes every subtree from 0 to N, inclusive. So index 0 contains subtree 0's information. var lastIndex = subtreeCount - 1; var aLeafCounts = stackalloc int[lastIndex]; var aMerged = stackalloc BoundingBox[lastIndex]; *aLeafCounts = leafCounts[*indexMap]; *aMerged = boundingBoxes[*indexMap]; for (int i = 1; i < lastIndex; ++i) { var index = indexMap[i]; aLeafCounts[i] = leafCounts[index] + aLeafCounts[i - 1]; BoundingBox.Merge(ref aMerged[i - 1], ref boundingBoxes[index], out aMerged[i]); } //Sweep from high to low. BoundingBox bMerged = new BoundingBox { Min = new Vector3(float.MaxValue), Max = new Vector3(float.MinValue) }; cost = float.MaxValue; splitIndex = 0; int bLeafCount = 0; a = bMerged; b = bMerged; leafCountA = 0; leafCountB = 0; for (int i = lastIndex; i >= 1; --i) { int aIndex = i - 1; var subtreeIndex = indexMap[i]; BoundingBox.Merge(ref bMerged, ref boundingBoxes[subtreeIndex], out bMerged); bLeafCount += leafCounts[subtreeIndex]; var aCost = aLeafCounts[aIndex] * ComputeBoundsMetric(ref aMerged[aIndex]); var bCost = bLeafCount * ComputeBoundsMetric(ref bMerged); var totalCost = aCost + bCost; if (totalCost < cost) { cost = totalCost; splitIndex = i; a = aMerged[aIndex]; b = bMerged; leafCountA = aLeafCounts[aIndex]; leafCountB = bLeafCount; } } }
unsafe void FindPartitionForAxis(BoundingBox *boundingBoxes, BoundingBox *aMerged, float *centroids, int *indexMap, int count, out int splitIndex, out float cost, out BoundingBox a, out BoundingBox b, out int leafCountA, out int leafCountB) { Debug.Assert(count > 1); //TODO: Note that sorting at every level isn't necessary. Like in one of the much older spatial splitting implementations we did, you can just sort once, and thereafter //just do an O(n) operation to shuffle leaf data to the relevant location on each side of the partition. That allows us to punt all sort work to a prestep. //There, we could throw an optimized parallel sort at it. Or just do the three axes independently, hidden alongside some other work maybe. //I suspect the usual problems with parallel sorts would be mitigated somewhat by having three of them going on at the same time- more chances for load balancing. //Also note that, at each step, both the above partitioning scheme and the sort result in a contiguous block of data to work on. //If you're already doing a gather like that, you might as well throw wider SIMD at the problem. This version only goes up to 3 wide, which is unfortunate for AVX2 and AVX512. //With those changes, we can probably get the sweep builder to be faster than v1's insertion builder- it's almost there already. //(You'll also want to bench it against similarly simd accelerated binned approaches for use in incremental refinement. If it's not much slower, the extra quality benefits //might make it faster on net by virtue of speeding up self-tests, which are a dominant cost.) var comparer = new IndexMapComparer { Centroids = centroids }; QuickSort.Sort(ref indexMap[0], 0, count - 1, ref comparer); //Search for the best split. //Sweep across from low to high, caching the merged size and leaf count at each point. //Index N includes every subtree from 0 to N, inclusive. So index 0 contains subtree 0's information. var lastIndex = count - 1; aMerged[0] = boundingBoxes[indexMap[0]]; for (int i = 1; i < lastIndex; ++i) { var index = indexMap[i]; BoundingBox.CreateMerged(aMerged[i - 1], boundingBoxes[index], out aMerged[i]); } //Sweep from high to low. BoundingBox bMerged = new BoundingBox { Min = new Vector3(float.MaxValue), Max = new Vector3(float.MinValue) }; cost = float.MaxValue; splitIndex = 0; a = bMerged; b = bMerged; leafCountA = 0; leafCountB = 0; for (int i = lastIndex; i >= 1; --i) { int aIndex = i - 1; var subtreeIndex = indexMap[i]; BoundingBox.CreateMerged(bMerged, boundingBoxes[subtreeIndex], out bMerged); var aCost = i * ComputeBoundsMetric(ref aMerged[aIndex]); var bCost = (count - i) * ComputeBoundsMetric(ref bMerged); var totalCost = aCost + bCost; if (totalCost < cost) { cost = totalCost; splitIndex = i; a = aMerged[aIndex]; b = bMerged; leafCountA = i; leafCountB = count - i; } } }
internal static extern unsafe void Detect(IntPtr matPtr, int matRows, int matCols, float thresh, bool useMean, out BoundingBox *elems, out int elemsSize);
unsafe void CollapseTree(int depthRemaining, TempNode *tempNodes, int tempNodeIndex, int *nodeChildren, ref int childCount, BoundingBox *nodeBounds, int *leafCounts) { var tempNode = tempNodes + tempNodeIndex; if (tempNode->A >= 0) { //Internal node. if (depthRemaining > 0) { depthRemaining -= 1; CollapseTree(depthRemaining, tempNodes, tempNode->A, nodeChildren, ref childCount, nodeBounds, leafCounts); CollapseTree(depthRemaining, tempNodes, tempNode->B, nodeChildren, ref childCount, nodeBounds, leafCounts); } else { //Reached the bottom of the recursion. Add the collected children. int a = childCount++; int b = childCount++; nodeBounds[a] = tempNodes[tempNode->A].BoundingBox; nodeBounds[b] = tempNodes[tempNode->B].BoundingBox; //If the child is a leaf, collapse it. Slightly less annoying to handle it here than later. //This is a byproduct of the awkward data layout for tempnodes... if (tempNodes[tempNode->A].A >= 0) { nodeChildren[a] = tempNode->A; } else { nodeChildren[a] = tempNodes[tempNode->A].A; //It's a leaf. } if (tempNodes[tempNode->B].A >= 0) { nodeChildren[b] = tempNode->B; } else { nodeChildren[b] = tempNodes[tempNode->B].A; //It's a leaf. Leaf index is always stored in A... } leafCounts[a] = tempNodes[tempNode->A].LeafCount; leafCounts[b] = tempNodes[tempNode->B].LeafCount; } } else { //Leaf node. var index = childCount++; nodeBounds[index] = tempNode->BoundingBox; nodeChildren[index] = tempNode->A; leafCounts[index] = tempNode->LeafCount; } }
private unsafe BoundingBox GetChildBoundingBox(BoundingBox parentBoundingBox, int childIndex) { Vector3 vector; switch (childIndex) { case 0: vector = new Vector3(0f, 0f, 0f); break; case 1: vector = new Vector3(1f, 0f, 0f); break; case 2: vector = new Vector3(1f, 0f, 1f); break; case 3: vector = new Vector3(0f, 0f, 1f); break; case 4: vector = new Vector3(0f, 1f, 0f); break; case 5: vector = new Vector3(1f, 1f, 0f); break; case 6: vector = new Vector3(1f, 1f, 1f); break; case 7: vector = new Vector3(0f, 1f, 1f); break; default: throw new InvalidBranchException(); } Vector3 vector2 = (parentBoundingBox.Max - parentBoundingBox.Min) / 2f; BoundingBox box = new BoundingBox { Min = parentBoundingBox.Min + (vector * vector2) }; BoundingBox *boxPtr1 = (BoundingBox *)ref box; boxPtr1->Max = box.Min + vector2; Vector3 *vectorPtr1 = (Vector3 *)ref box.Min; vectorPtr1[0] -= vector2 * 0.3f; Vector3 *vectorPtr2 = (Vector3 *)ref box.Max; vectorPtr2[0] += vector2 * 0.3f; BoundingBox *boxPtr2 = (BoundingBox *)ref box; boxPtr2->Min = Vector3.Max(box.Min, parentBoundingBox.Min); BoundingBox *boxPtr3 = (BoundingBox *)ref box; boxPtr3->Max = Vector3.Min(box.Max, parentBoundingBox.Max); return(box); }