UE4 四叉树 QuadTree

UE4 四叉树 QuadTree

Engine\Source\Runtime\Engine\Public\GenericQuadTree.h

TQuadTree

template <typename ElementType, int32 NodeCapacity = 4>
class TQuadTree
{
    
    
	typedef TQuadTree<ElementType, NodeCapacity> TreeType;
public:

	/** DO NOT USE. This constructor is for internal usage only for hot-reload purposes. */
	TQuadTree();

	TQuadTree(const FBox2D& InBox, float InMinimumQuadSize = 100.f);

	/** Gets the TreeBox so systems can test insertions before trying to do so with invalid regions */
	const FBox2D& GetTreeBox() const {
    
     return TreeBox; }

	/** Inserts an object of type ElementType with an associated 2D box of size Box (log n). Pass in a DebugContext so when an issue occurs the log can report what requested this insert. */
	void Insert(const ElementType& Element, const FBox2D& Box, const TCHAR* DebugContext = nullptr);

	/** Given a 2D box, returns an array of elements within the box. There will not be any duplicates in the list. */
	template<typename ElementAllocatorType>
	void GetElements(const FBox2D& Box, TArray<ElementType, ElementAllocatorType>& ElementsOut) const;

	/** Removes an object of type ElementType with an associated 2D box of size Box (log n). Does not cleanup tree*/
	bool Remove(const ElementType& Instance, const FBox2D& Box);

	/** Does a deep copy of the tree by going through and re-creating the internal data. Cheaper than re-insertion as it should be linear instead of nlogn */
	void Duplicate(TreeType& OutDuplicate) const;

	/** Removes all elements of the tree */
	void Empty();

	void Serialize(FArchive& Ar);

	TreeType& operator=(const TreeType& Other);

	~TQuadTree();

private:
	enum QuadNames
	{
    
    
		TopLeft = 0,
		TopRight = 1,
		BottomLeft = 2,
		BottomRight = 3
	};

	/** Node used to hold the element and its corresponding 2D box*/
	struct FNode
	{
    
    
		FBox2D Box;
		ElementType Element;

		FNode() {
    
    };

		FNode(const ElementType& InElement, const FBox2D& InBox)
			: Box(InBox)
			, Element(InElement)
		{
    
    }

		friend FArchive& operator<<(FArchive& Ar, typename TQuadTree<ElementType, NodeCapacity>::FNode& Node)
		{
    
    
			return Ar << Node.Box << Node.Element;
		}
	};

	/** Given a 2D box, return the subtrees that are touched. Returns 0 for leaves. */
	int32 GetQuads(const FBox2D& Box, TreeType* Quads[4]) const;

	/** Split the tree into 4 sub-trees */
	void Split();

	/** Given a list of nodes, return which ones actually intersect the box */
	template<typename ElementAllocatorType>
	void GetIntersectingElements(const FBox2D& Box, TArray<ElementType, ElementAllocatorType>& ElementsOut) const;

	/** Given a list of nodes, remove the node that contains the given element */
	bool RemoveNodeForElement(const ElementType& Element);

	/** Internal recursive implementation of @see Insert */
	void InsertElementRecursive(const ElementType& Element, const FBox2D& Box, const TCHAR* DebugContext);

private:

	/**
	 * Contains the actual elements this tree is responsible for. Nodes are used to keep track of each element's AABB as well.
	 * For a non-internal leaf, this is the list of nodes that are fully contained within this tree.
	 * For an internal tree, this contains the nodes that overlap multiple subtrees.
	 */
	TArray<FNode> Nodes;

	/** The sub-trees of this tree */
	TreeType* SubTrees[4];

	/** AABB of the tree */
	FBox2D TreeBox;

	/** Center position of the tree */
	FVector2D Position;

	/** The smallest size of a quad allowed in the tree */
	float MinimumQuadSize;

	/** Whether this is a leaf or an internal sub-tree */
	bool bInternal;
};

Usage

#include "GenericQuadTree.h"

//Setup the Quad tree
float UVsQuadTreeMinSize = 0.001f;
TQuadTree<uint32, 100> QuadTree(BaseMeshUVBound,UVsQuadTreeMinSize);
//Insert data
for (FTriangleElement& TriangleElement : Triangles)
{
    
    
	QuadTree.Insert(TriangleElement.TriangleIndex, TriangleElement.UVsBound, DebugContext);
}
//Find a match triangle for every target vertices
TArray<uint32> QuadTreeTriangleResults;
//Reserve 10% to speed up the query
QuadTreeTriangleResults.Reserve(Triangles.Num() / 10); 

for (uint32 TargetVertexIndex = 0; TargetVertexIndex < (uint32)TargetVertices.Num(); ++TargetVertexIndex)
{
    
    
	//Reset the last data without flushing the memmery allocation
	QuadTreeTriangleResults.Reset();
	FVector2D Extent(DistanceThreshold, DistanceThreshold);
	FBox2D CurBox(TargetUV - Extent, TargetUV + Extent);
	while (QuadTreeTriangleResults.Num() <= 0)
	{
    
    
		QuadTree.GetElements(CurBox, QuadTreeTriangleResults);
		Extent *= 2;
		CurBox = FBox2D(TargetUV - Extent, TargetUV + Extent);
	}
}

应用

UE4聚合图测试

参考

  1. UE4 LOD Screen Size

猜你喜欢

转载自blog.csdn.net/mrbaolong/article/details/125000790
今日推荐