diff --git a/Util/kdtree.h b/Util/kdtree.h index c55c0b4..b754423 100644 --- a/Util/kdtree.h +++ b/Util/kdtree.h @@ -1,5 +1,6 @@ #include "geometry.h" #include +#include #include #include #include @@ -7,12 +8,31 @@ class KDTree { public: - KDTree(std::vector points) { root = build(points, 0); } + KDTree(std::vector points) { + std::cout << "Starting to build tree with " << points.size() << " points took "; + auto start = std::chrono::high_resolution_clock::now(); + root = build(points, 0); + auto end = std::chrono::high_resolution_clock::now(); + + std::cout << std::chrono::duration_cast(end - start).count() + << " microseconds" << std::endl; + } ~KDTree() = default; // TODO: Delete all allocated Nodes const Triangle *intersect_ray(const Ray ray, Vector &result) { - return intersect_ray_recurse(result, ray, root, 1000.0, 0); + auto start = std::chrono::high_resolution_clock::now(); + + float nearest = 1000.0; + const Triangle *nearest_triangle = nullptr; + intersect_ray_recurse(nearest_triangle, result, ray, root, 1000.0, 0, nearest); + + auto end = std::chrono::high_resolution_clock::now(); + + std::cout << "Intersection took " + << std::chrono::duration_cast(end - start).count() + << " microseconds" << std::endl; + return nearest_triangle; } std::string to_string() { @@ -87,43 +107,16 @@ class KDTree { build(right_of_median, depth + 1)); } - const Triangle *intersect_ray_recurse(Vector &result, Ray ray, Node *node, float max_distance, - int depth) { + void intersect_ray_recurse(const Triangle *&nearest_triangle, Vector &result, Ray ray, + Node *node, float max_distance, int depth, float &nearest) { // Exit condition: There was no collision - if (node == nullptr) { return nullptr; } - - // Is the left or right child node closer to this point? - Node *near = - ray.origin[node->axis] > node->point->pos[node->axis] ? node->right : node->left; - Node *far = near == node->right ? node->left : node->right; - - // Check for collisions in this order (stopping if an intersection is found): - // 1. In the nearer section - // 2. With the point in this current node - // 3. In the further section - - // If the axes are not parallel, our max_distance decreases, since we've already covered - // some area. `t` represents the distance from this node to the splitting plane. - float t = ray.direction[node->axis] != 0.0 - ? (node->point->pos[node->axis] - ray.origin[node->axis]) / - ray.direction[node->axis] - : max_distance; - const Triangle *near_result = intersect_ray_recurse(result, ray, near, t, depth + 1); - - // If the nearer segment had a collision, we're done! We're only interested in the closest - // collision. - if (near_result != nullptr) { return near_result; } - - // No collision in the nearer side, so check for a collision directly here - float nearest = 100000; // FIXME - const Triangle *nearest_triangle = nullptr; + if (node == nullptr) { return; } + // Check for a collision here for (const Triangle *triangle : node->point->triangles) { Vector current_result(0, 0, 0); float current_distance; if (ray.intersects_triangle(triangle, current_result, current_distance)) { - std::cout << "tested with " << current_distance << std::endl; - if (current_distance < nearest) { nearest = current_distance; nearest_triangle = triangle; @@ -132,20 +125,31 @@ class KDTree { } } - if (nearest_triangle) { return nearest_triangle; } + // Is the left or right child node closer to this point? + Node *near = + ray.origin[node->axis] > node->point->pos[node->axis] ? node->right : node->left; + Node *far = near == node->right ? node->left : node->right; - // No collision here either. Does it make sense to also check the far node? - // Only if the axes are not parallel and if that area is not behind us - if (ray.direction[node->axis] != 0.0) { // FIXME: should include && t >= 0.0 - // It does make sense to check the far node. - // For this, calculate a new ray origin and continue towards that direction, but with - // the new origin (we can leave behind what we already checked) - return intersect_ray_recurse(result, Ray(ray.origin + ray.direction * t, ray.direction), - far, max_distance - t, depth + 1); + if (ray.direction[node->axis] == 0.0) { + intersect_ray_recurse(nearest_triangle, result, ray, near, max_distance, depth + 1, + nearest); + } else { + /* float t = + (node->point->pos[node->axis] - ray.origin[node->axis]) / + ray.direction[node->axis]; + + if (t >= 0.0 && t < max_distance) { + intersect_ray_recurse(nearest_triangle, result, ray, near, t, depth + 1, + nearest); intersect_ray_recurse(nearest_triangle, result, Ray(ray.origin + + ray.direction * t, ray.direction), far, max_distance - t, depth + 1, nearest); } else + { intersect_ray_recurse(nearest_triangle, result, ray, near, max_distance, depth + 1, + nearest); + } */ + intersect_ray_recurse(nearest_triangle, result, ray, near, max_distance, depth + 1, + nearest); + intersect_ray_recurse(nearest_triangle, result, ray, far, max_distance, depth + 1, + nearest); } - - // If nothing worked, return a nullptr - return nullptr; } void to_string_recurse(std::string &str, Node *node, int depth) {