Example #1
0
        /// <summary>
        /// Creates a parent of the two provided nodes.
        /// This will change values on the child to make the BVH structure as efficient as possible,
        /// so only use this function on a final pair.
        /// </summary>
        /// <param name="left">The left child node.</param>
        /// <param name="right">The right child node.</param>
        /// <returns>A new node which will be the parent of the provided nodes.</returns>
        public static BVH <T> CreateParent <T>(BVH <T> left, BVH <T> right) where T : IBoundedObject
        {
            BVH <T> parent = new BVH <T>(left, right);

            MakeParent(parent);
            return(parent);
        }
Example #2
0
        private static BVH <T> ConstructLocalAgglom <T>(List <T> objects) where T : IBoundedObject
        {
            // See "Fast Agglomerative Clustering for Rendering": https://www.cs.cornell.edu/~kb/publications/IRT08.pdf
            List <BVH <T> > leafList = objects.Select((o, i) => new BVH <T>(o, i)).ToList();

            KDTree <BVH <T> > tree = KDTree.Construct(leafList);

            BVH <T> a = leafList[0];
            BVH <T> b = tree.GetNearestNeighbor(a).Element;

            while (true)
            {
                BVH <T> c = tree.GetNearestNeighbor(b).Element;

                if (a == c)
                {
                    tree.Remove(a);
                    Util.Assert(!tree.ContainsElement(a), "test");
                    a = CreateParent(a, b);

                    // If the tree is a leaf, we're removing the last elements, exit early.
                    if (tree.IsLeaf)
                    {
                        return(a);
                    }

                    tree.Remove(b);
                    Util.Assert(!tree.ContainsElement(b), "test");
                    tree.Add(a);
                    Util.Assert(tree.ContainsElement(a), "test");

                    b = tree.GetNearestNeighbor(a).Element;
                }
                else
                {
                    a = b;
                    b = c;
                }
            }
        }
Example #3
0
        private static BVH <T> ConstructHeapAgglom <T>(List <T> objects) where T : IBoundedObject
        {
            BVH <T>[] nodes = new BVH <T> [objects.Count];

            // Make array of leaves to construct the k-d tree
            for (int i = 0; i < nodes.Length; i++)
            {
                nodes[i] = new BVH <T>(objects[i], i);
            }

            KDTree <BVH <T> > tree = KDTree.Construct(nodes);

            // Prepare priority queue to get the cheapest pairs
            Comparer <BVH <T> > pairComparer = Comparer <BVH <T> > .Create((a, b) =>
            {
                if (a.Equals(b))
                {
                    return(0);
                }

                int comp = a.Cost.CompareTo(b.Cost);
                if (comp != 0)
                {
                    return(comp);
                }

                // Break ties by preferring  more leaves first to flatten the tree.
                comp = b.ChildLeaves.CompareTo(a.ChildLeaves);
                if (comp != 0)
                {
                    return(comp);
                }

                return(0);
            });

            // Make list of nearest pairs
            for (int i = 0; i < nodes.Length; i++)
            {
                BVH <T> node = nodes[i];
                nodes[i] = new BVH <T>(node, tree.GetNearestNeighbor(node).Element);
            }

            /*MinQueue<BVH<T>> cheapPairs = new MinQueue<BVH<T>>(nodes, pairComparer);
             *
             * while (true)
             * {
             *      // Get the next cheapest pair to make
             *      BVH<T> cheapest = cheapPairs.Min;
             *      cheapPairs.RemoveMin();
             *
             *      // If we've already paired this node, leave it removed.
             *      if (!tree.ContainsElement(cheapest.Left))
             *              continue;
             *
             *      // If we've paired the left element but not the right, find the new nearest neighbor and resort.
             *      if (!tree.ContainsElement(cheapest.Right))
             *      {
             *              cheapPairs.Add(new BVH<T>(cheapest.Left, tree.GetNearestNeighbor(cheapest.Left).Element));
             *              cheapPairs = new MinQueue<BVH<T>>(cheapPairs, pairComparer);
             *              continue;
             *      }
             *
             *      // Finalize parentizing this pair, so that resulting BVH is more efficient.
             *      MakeParent(cheapest);
             *
             *      tree.Remove(cheapest.Left);
             *
             *      // If the tree is a leaf, we're removing the last elements, exit early.
             *      if (tree.IsLeaf)
             *              return cheapest;
             *
             *      tree.Remove(cheapest.Right);
             *      tree.Add(cheapest);
             *
             *      cheapPairs.Add(new BVH<T>(cheapest, tree.GetNearestNeighbor(cheapest).Element));
             * }*/

            Heap <BVH <T> > cheapPairs = new Heap <BVH <T> >(nodes, pairComparer);

            while (true)
            {
                // Get the next cheapest pair to make
                BVH <T> cheapest = cheapPairs.Extract();

                // If we've already paired this node, leave it removed.
                if (!tree.ContainsElement(cheapest.Left))
                {
                    continue;
                }

                // If we've paired the left element but not the right, find the new nearest neighbor and resort.
                if (!tree.ContainsElement(cheapest.Right))
                {
                    cheapPairs.Add(new BVH <T>(cheapest.Left, tree.GetNearestNeighbor(cheapest.Left).Element));
                    continue;
                }

                // Finalize parentizing this pair, so that resulting BVH is more efficient.
                MakeParent(cheapest);

                tree.Remove(cheapest.Left);

                // If the tree is a leaf, we're removing the last elements, exit early.
                if (tree.IsLeaf)
                {
                    return(cheapest);
                }

                tree.Remove(cheapest.Right);
                tree.Add(cheapest);

                cheapPairs.Add(new BVH <T>(cheapest, tree.GetNearestNeighbor(cheapest).Element));
            }
        }
Example #4
0
 /// <summary>
 /// Finalizes making a BVH node a parent to its children.
 /// This will change values on the child to make the BVH structure as efficient as possible,
 /// so only use this function on a final pair.
 /// </summary>
 /// <param name="left">The node to finalize as a parent.</param>
 public static void MakeParent <T>(BVH <T> parent) where T : IBoundedObject
 {
     parent.Left.SkipVolume  = parent.Left.Volume.Equals(parent.Volume);
     parent.Right.SkipVolume = parent.Right.Volume.Equals(parent.Volume);
 }
Example #5
0
 public static double GetCost <T>(BVH <T> left, BVH <T> right) where T : IBoundedObject
 {
     return(GetCost(AABB.Combine(left.Volume, right.Volume)));
 }