2021-01-12 18:38:16 +01:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2021-01-16 15:57:41 +01:00
|
|
|
|
#include <list>
|
2021-01-02 16:00:09 +01:00
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
// Forward declarations
|
|
|
|
|
struct Triangle;
|
|
|
|
|
|
|
|
|
|
struct Vector {
|
|
|
|
|
Vector(float coordinates[3]) : c(coordinates) {}
|
|
|
|
|
Vector(float x, float y, float z) : c(new float[3]{x, y, z}) {}
|
|
|
|
|
|
|
|
|
|
// Avoid having to write vector.c[index], instead allow vector[index]
|
|
|
|
|
float operator[](int i) const { return c[i]; }
|
|
|
|
|
float &operator[](int i) { return c[i]; }
|
|
|
|
|
|
|
|
|
|
Vector operator+(const Vector &other) const {
|
|
|
|
|
return Vector(c[0] + other.c[0], c[1] + other.c[1], c[2] + other.c[2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector operator-(const Vector &other) const {
|
|
|
|
|
return Vector(c[0] - other.c[0], c[1] - other.c[1], c[2] - other.c[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-16 15:57:41 +01:00
|
|
|
|
bool operator<(const Vector &other) const {
|
|
|
|
|
if ((c[2] < other.c[2])) { return true; }
|
|
|
|
|
if ((c[2] == other.c[2]) && (c[1] < other.c[1])) { return true; }
|
|
|
|
|
if ((c[2] == other.c[2]) && (c[1] == other.c[1]) && (c[0] < other.c[0])) { return true; }
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-02 16:00:09 +01:00
|
|
|
|
Vector operator*(float scalar) const {
|
|
|
|
|
return Vector(c[0] * scalar, c[1] * scalar, c[2] * scalar);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector cross(const Vector &other) {
|
2021-01-12 18:38:16 +01:00
|
|
|
|
return Vector(c[1] * other[2] - c[2] * other[1], c[2] * other[0] - c[0] * other[2],
|
2021-01-02 16:00:09 +01:00
|
|
|
|
c[0] * other[1] - c[1] * other[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float dot(const Vector &other) { return c[0] * other[0] + c[1] * other[1] + c[2] * other[2]; }
|
|
|
|
|
|
|
|
|
|
float *c;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Point {
|
2021-01-16 15:57:41 +01:00
|
|
|
|
Point(Vector pos) : pos(pos) {}
|
|
|
|
|
|
|
|
|
|
Point(Vector pos, std::list<Triangle *> triangles) : pos(pos), triangles(triangles) {}
|
2021-01-02 16:00:09 +01:00
|
|
|
|
|
|
|
|
|
Vector pos;
|
|
|
|
|
|
2021-01-16 15:57:41 +01:00
|
|
|
|
std::list<Triangle *> triangles;
|
2021-01-02 16:00:09 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Triangle {
|
|
|
|
|
Triangle(Vector p1, Vector p2, Vector p3) : p1(p1), p2(p2), p3(p3) {}
|
|
|
|
|
|
|
|
|
|
std::vector<Point *> create_point_objects() {
|
2021-01-16 15:57:41 +01:00
|
|
|
|
return std::vector<Point *>{new Point(p1, std::list<Triangle *>{this}),
|
|
|
|
|
new Point(p2, std::list<Triangle *>{this}),
|
|
|
|
|
new Point(p3, std::list<Triangle *>{this})};
|
2021-01-02 16:00:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector p1;
|
|
|
|
|
Vector p2;
|
|
|
|
|
Vector p3;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Node {
|
|
|
|
|
Node(int axis, Point *point, Node *left, Node *right)
|
|
|
|
|
: axis(axis), point(point), left(left), right(right) {}
|
|
|
|
|
|
|
|
|
|
int axis;
|
|
|
|
|
|
|
|
|
|
Point *point;
|
|
|
|
|
|
|
|
|
|
Node *left;
|
|
|
|
|
Node *right;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Ray {
|
|
|
|
|
Ray(Vector origin, Vector direction) : origin(origin), direction(direction) {}
|
|
|
|
|
|
|
|
|
|
Vector origin;
|
|
|
|
|
|
|
|
|
|
Vector direction;
|
|
|
|
|
|
2021-01-16 15:57:41 +01:00
|
|
|
|
bool intersects_triangle(const Triangle *triangle, Vector &result, float &t) {
|
2021-01-02 16:00:09 +01:00
|
|
|
|
// Ray-triangle-intersection with the Möller–Trumbore algorithm
|
|
|
|
|
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
|
|
|
|
|
const float EPSILON = 0.0000001;
|
|
|
|
|
|
|
|
|
|
Vector p1 = triangle->p1;
|
|
|
|
|
Vector p2 = triangle->p2;
|
|
|
|
|
Vector p3 = triangle->p3;
|
|
|
|
|
|
|
|
|
|
Vector edge1 = p2 - p1;
|
|
|
|
|
Vector edge2 = p3 - p1;
|
|
|
|
|
|
|
|
|
|
Vector h = direction.cross(edge2);
|
|
|
|
|
float a = edge1.dot(h);
|
|
|
|
|
|
|
|
|
|
if (a > -EPSILON && a < EPSILON) return false; // This ray is parallel to this triangle.
|
|
|
|
|
|
|
|
|
|
float f = 1.0 / a;
|
|
|
|
|
Vector s = origin - p1;
|
|
|
|
|
float u = f * s.dot(h);
|
|
|
|
|
|
|
|
|
|
if (u < 0.0 || u > 1.0) return false;
|
|
|
|
|
|
|
|
|
|
Vector q = s.cross(edge1);
|
|
|
|
|
float v = f * direction.dot(q);
|
|
|
|
|
if (v < 0.0 || u + v > 1.0) return false;
|
|
|
|
|
|
|
|
|
|
// At this stage we can compute t to find out where the intersection point is on the
|
|
|
|
|
// line.
|
2021-01-16 15:57:41 +01:00
|
|
|
|
t = f * edge2.dot(q);
|
2021-01-02 16:00:09 +01:00
|
|
|
|
if (t > EPSILON) {
|
2021-01-15 11:44:28 +01:00
|
|
|
|
result = origin + direction * t;
|
2021-01-02 16:00:09 +01:00
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
// This means that there is a line intersection but not a ray intersection.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|