/// <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); }
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; } } }
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)); } }
/// <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); }
public static double GetCost <T>(BVH <T> left, BVH <T> right) where T : IBoundedObject { return(GetCost(AABB.Combine(left.Volume, right.Volume))); }