Rewrite intersect_ray_recurse
Like the function in the slides now, but I had to change a part because it's not working 100% otherwise... not very optimized now
This commit is contained in:
parent
40dc7850a9
commit
59d9311cc8
@ -1,5 +1,6 @@
|
|||||||
#include "geometry.h"
|
#include "geometry.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -7,12 +8,31 @@
|
|||||||
|
|
||||||
class KDTree {
|
class KDTree {
|
||||||
public:
|
public:
|
||||||
KDTree(std::vector<Point *> points) { root = build(points, 0); }
|
KDTree(std::vector<Point *> 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<std::chrono::microseconds>(end - start).count()
|
||||||
|
<< " microseconds" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
~KDTree() = default; // TODO: Delete all allocated Nodes
|
~KDTree() = default; // TODO: Delete all allocated Nodes
|
||||||
|
|
||||||
const Triangle *intersect_ray(const Ray ray, Vector &result) {
|
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<std::chrono::microseconds>(end - start).count()
|
||||||
|
<< " microseconds" << std::endl;
|
||||||
|
return nearest_triangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string to_string() {
|
std::string to_string() {
|
||||||
@ -87,43 +107,16 @@ class KDTree {
|
|||||||
build(right_of_median, depth + 1));
|
build(right_of_median, depth + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Triangle *intersect_ray_recurse(Vector &result, Ray ray, Node *node, float max_distance,
|
void intersect_ray_recurse(const Triangle *&nearest_triangle, Vector &result, Ray ray,
|
||||||
int depth) {
|
Node *node, float max_distance, int depth, float &nearest) {
|
||||||
// Exit condition: There was no collision
|
// Exit condition: There was no collision
|
||||||
if (node == nullptr) { return nullptr; }
|
if (node == nullptr) { return; }
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
|
// Check for a collision here
|
||||||
for (const Triangle *triangle : node->point->triangles) {
|
for (const Triangle *triangle : node->point->triangles) {
|
||||||
Vector current_result(0, 0, 0);
|
Vector current_result(0, 0, 0);
|
||||||
float current_distance;
|
float current_distance;
|
||||||
if (ray.intersects_triangle(triangle, current_result, current_distance)) {
|
if (ray.intersects_triangle(triangle, current_result, current_distance)) {
|
||||||
std::cout << "tested with " << current_distance << std::endl;
|
|
||||||
|
|
||||||
if (current_distance < nearest) {
|
if (current_distance < nearest) {
|
||||||
nearest = current_distance;
|
nearest = current_distance;
|
||||||
nearest_triangle = triangle;
|
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?
|
if (ray.direction[node->axis] == 0.0) {
|
||||||
// Only if the axes are not parallel and if that area is not behind us
|
intersect_ray_recurse(nearest_triangle, result, ray, near, max_distance, depth + 1,
|
||||||
if (ray.direction[node->axis] != 0.0) { // FIXME: should include && t >= 0.0
|
nearest);
|
||||||
// It does make sense to check the far node.
|
} else {
|
||||||
// For this, calculate a new ray origin and continue towards that direction, but with
|
/* float t =
|
||||||
// the new origin (we can leave behind what we already checked)
|
(node->point->pos[node->axis] - ray.origin[node->axis]) /
|
||||||
return intersect_ray_recurse(result, Ray(ray.origin + ray.direction * t, ray.direction),
|
ray.direction[node->axis];
|
||||||
far, max_distance - t, depth + 1);
|
|
||||||
|
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) {
|
void to_string_recurse(std::string &str, Node *node, int depth) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user