kick
|
00001 #pragma once 00002 00003 #include "kick/math/aabb.h" 00004 #include "kick/math/ray.h" 00005 #include "glm/glm.hpp" 00006 #include <functional> 00007 #include <vector> 00008 00009 namespace kick { 00010 00011 00012 00013 00014 struct KDTreeHitInfo; 00015 00016 struct KDTreeNodeRef { 00017 KDTreeNodeRef(); 00018 KDTreeNodeRef(const KDTreeNodeRef& other); 00019 00020 glm::vec3 triangle[3]; 00021 int id; 00022 00023 bool intersectRay(const Ray &ray, KDTreeHitInfo& hit) const; 00024 AABB getAABB() const; 00025 }; 00026 struct KDTreeHitInfo { 00027 float distance = std::numeric_limits<float>::max(); 00028 KDTreeNodeRef const *hit; 00029 glm::vec3 collisionPoint; 00030 }; 00031 00032 class KDTreeNode { 00033 public: 00034 KDTreeNode *leftChild; 00035 KDTreeNode *rightChild; 00036 AABB aabb; 00037 float splittingPlane; 00038 int splittingAxis; 00039 std::vector<KDTreeNodeRef> objects; 00040 00041 KDTreeNode(const AABB &aabb); 00042 00043 00044 00045 bool isLeaf(); 00046 }; 00047 00048 // Abstract KDTree 00049 class KDTree { 00050 public: 00051 /* 00052 * treeDepth: The max depth of tree nodes 00053 * minVoxelObjects: The minimum number of objects in a tree node (if less, node is not subdivided) 00054 */ 00055 KDTree(); 00056 ~KDTree(void); 00057 virtual void init(std::vector<KDTreeNodeRef> &objectList, AABB &aabb); 00058 00059 virtual bool first_intersection(Ray &ray, KDTreeHitInfo& hit); 00060 00061 protected: 00062 std::vector<KDTreeNodeRef> objectList; 00063 KDTreeNode *rootNode; 00064 AABB aabb; 00065 bool intersect(KDTreeNode *child, const Ray &ray, KDTreeHitInfo& hit, glm::vec3 startPoint); 00066 KDTreeNode *recursiveBuild(const std::vector<KDTreeNodeRef>& objectList, AABB &aabb, int currentDepth); 00067 virtual bool terminateBuild(const std::vector<KDTreeNodeRef>& objectList, AABB &aabb, int currentDepth) = 0; 00068 /*** 00069 * Find optimal splitting plane 00070 */ 00071 virtual void findPlane(const std::vector<KDTreeNodeRef>& objectList, AABB &aabb, int currentDepth, KDTreeNode *node) = 0; 00072 }; 00073 00074 00075 // The Simple KD tree uses a näive spatial median as splitting plane 00076 class KDTreeNaive : public KDTree { 00077 public: 00078 /* 00079 * treeDepth: The max depth of tree nodes 00080 * minVoxelObjects: The minimum number of objects in a tree node (if less, node is not subdivided) 00081 */ 00082 KDTreeNaive(int treeDepth = 12, int minVoxelObjects = 20); 00083 protected: 00084 00085 bool terminateBuild(const std::vector<KDTreeNodeRef>& objectList, AABB &aabb, int currentDepth); 00086 00087 /*** 00088 * Find optimal splitting plane 00089 */ 00090 void findPlane(const std::vector<KDTreeNodeRef>& objectList, AABB &aabb, int currentDepth, KDTreeNode *node); 00091 00092 private: 00093 int treeDepth; 00094 int minVoxelObjects; 00095 }; 00096 00097 } 00098