// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "MeshDetails.h" #include "GraphicsDefs.h" #include "Helper/GraphicsUtil.h" #include #include #include class MeshDetails_Tri; class TEXTUREGRAPHENGINE_API MeshDetails_Spatial : MeshDetails { public: struct ONode { FBox FBox; int Level; int ChildIndex; int LevelIndex; int ParentNodeId; int NodeId; int TriStart; int TriCount; int HasChildren; /// We need to do stupid shit like this to avoid having int[] Children in here because it's non-blittable /// for the compute shader and throws an error. static const int s_maxChildren = 8; int Children[s_maxChildren]; /// The children for this node ONode(int parentNodeId); }; ////////////////////////////////////////////////////////////////////////// class Node { private: static const int s_maxTriangles = 256; static const int s_maxChildren = 8; static const int s_maxLevel = 9; FCriticalSection _mutex; /// Mutex for parallel compute /// The bounds for this node FBox _bounds; /// The bounds of this node /// The triangles in this node. These are indexed into MeshDetails_Tri std::vector* _triangles; MeshDetails_Spatial* _details; /// The parent of this Octree Node* _parent = nullptr; int _level = 0; /// What level is this node on int _childIndex = 0; /// Which child is it (Check out Gemoetry.Util.BoundsCorners in GeometryUtil.cs) int _levelIndex = 0; /// What is the index of this node at the depth level that it's at int _nodeId = 0; /// Unique node id /// The children of this octree std::array _children; /// Children for this node public: ////////////////////////////////////////////////////////////////////////// bool HasChildren() const { return _children[0] != nullptr; } const std::vector* Triangles() const { return _triangles; } const FBox& Bounds() const { return _bounds; } const std::array& Children() const { return _children; } const Node* Parent() const { return _parent; } int NodeId() const { return _nodeId; } void RenderDebug() const; Node* CreateChild(int ci, int li, int ni); int FindTriangle(MeshInfo& mesh, const Vector3& pos, Vector2& bcCoord); bool Divide(MeshDetails_Tri* d_tri, Node* triNodes); static bool CheckIntersection(const FBox& nodeBounds, FRay ray, float& distance, float length = -1, FBox* bounds = nullptr); std::list GetIntersectingLeafNodes(std::list nodes, FRay ray, float* distance, float length = -1, FBox* bounds = nullptr, std::list* ignoreLeafs = nullptr); //void FindCongruentVertices(MeshInfo& mesh, const Vector3& v, int i, std::vector& congruent); //int FindCongruentVertex(MeshInfo& mesh, const Vector3& v, int i); //void GetAllNodes(ONode** allNodes, const std::vector& tris, int& triIndex); //std::list GetIntersectingLeafNodes(const std::list& nodes, Hemisphere hem) //std::list GetIntersectingLeafNodes(const std::list& nodes, const FBox& bounds); //void ClearNonLeafNodes(const std::list& leafs); //void Release(); Node(MeshDetails_Spatial* details, Node* parent, const FBox& bounds, int nodeId, std::vector* triangles = nullptr) { _details = details; _parent = parent; _bounds = bounds; _nodeId = nodeId; _triangles = triangles; } }; protected: friend class Node; /// The root node of this Octree MeshDetails_Spatial::Node* _root = nullptr; /// The root of the Octree /// The leaf nodes of this Octree for easy access std::vector _leafs; /// The leaf nodes int _maxLevel = 0; /// The current max level of the tree std::array _diagNormals; /// Normals for the diagonals of Level-0 and Level-1 of the octree. These allow us to /// to recursively calculate the AABB of a child node at L(n) given a parent at L(n - 1) //private ComputeBuffer b_octree; //private ComputeBuffer b_octreeTris; //public Node[] TriNodes { get => _triNodes; } int _nodeId = 0; /// The current node ID that we're using std::vector _allNodes; /// ALL the nodes in the Octree std::vector _tris; /// The triangles int _triCount = 0; /// How many triangles do we have virtual void CalculateTri(size_t ti) override; public: MeshDetails_Spatial(MeshInfo* mesh); virtual ~MeshDetails_Spatial(); virtual MeshDetailsPAsync Calculate() override; virtual void Release() override; };