Add support for multiple triangles per Point
This commit is contained in:
parent
ba98ae3386
commit
40dc7850a9
@ -8,6 +8,8 @@
|
||||
#include "../Components/Transform.h"
|
||||
#include "../ECS.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace ECS;
|
||||
|
||||
class CollisionSystem : public EntitySystem {
|
||||
@ -16,7 +18,6 @@ class CollisionSystem : public EntitySystem {
|
||||
|
||||
// Initialize the kdtree
|
||||
void build() {
|
||||
std::vector<Triangle *> triangles;
|
||||
std::vector<Point *> points;
|
||||
|
||||
// ObjMesh
|
||||
@ -25,7 +26,11 @@ class CollisionSystem : public EntitySystem {
|
||||
std::vector<unsigned int> indices = mesh->indices;
|
||||
std::vector<float> vertices = mesh->vertices;
|
||||
|
||||
std::map<Vector, Point *> triangle_map;
|
||||
|
||||
// TODO: Iterate over vertices, add triangles by also iterating over indices
|
||||
for (int i = 0; i < mesh->vertex_count; i += 3) {
|
||||
// Build vertices from this triangle
|
||||
float v0p0 = vertices[indices[i + 0] * 14 + 0];
|
||||
float v0p1 = vertices[indices[i + 0] * 14 + 1];
|
||||
float v0p2 = vertices[indices[i + 0] * 14 + 2];
|
||||
@ -53,12 +58,30 @@ class CollisionSystem : public EntitySystem {
|
||||
Vector v3(v3glm.x, v3glm.y, v3glm.z);
|
||||
|
||||
Triangle *triangle = new Triangle(v1, v2, v3);
|
||||
triangles.emplace_back(triangle);
|
||||
|
||||
points.emplace_back(new Point(v1, triangle));
|
||||
points.emplace_back(new Point(v2, triangle));
|
||||
points.emplace_back(new Point(v3, triangle));
|
||||
if (triangle_map.count(v1) == 0) {
|
||||
triangle_map[v1] = new Point(v1, std::list<Triangle *>{triangle});
|
||||
} else {
|
||||
triangle_map[v1]->triangles.emplace_back(triangle);
|
||||
}
|
||||
|
||||
if (triangle_map.count(v2) == 0) {
|
||||
triangle_map[v2] = new Point(v2, std::list<Triangle *>{triangle});
|
||||
} else {
|
||||
triangle_map[v2]->triangles.emplace_back(triangle);
|
||||
}
|
||||
|
||||
if (triangle_map.count(v3) == 0) {
|
||||
triangle_map[v3] = new Point(v3, std::list<Triangle *>{triangle});
|
||||
} else {
|
||||
triangle_map[v3]->triangles.emplace_back(triangle);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to list
|
||||
std::transform(
|
||||
triangle_map.begin(), triangle_map.end(), back_inserter(points),
|
||||
[](const std::map<Vector, Point *>::value_type &val) { return val.second; });
|
||||
});
|
||||
|
||||
// LODObjMesh
|
||||
@ -70,8 +93,6 @@ class CollisionSystem : public EntitySystem {
|
||||
std::cout << "Start building kdtree with " << points.size() << " points" << std::endl;
|
||||
kdtree = new KDTree(points);
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
std::cout << kdtree->to_string() << std::endl;
|
||||
}
|
||||
|
||||
void tick(World *pWorld, float deltaTime) override {
|
||||
@ -86,7 +107,7 @@ class CollisionSystem : public EntitySystem {
|
||||
Ray ray(origin, direction);
|
||||
|
||||
Vector collision_position(0, 0, 0);
|
||||
Triangle *result = kdtree->intersect_ray(ray, collision_position);
|
||||
const Triangle *result = kdtree->intersect_ray(ray, collision_position);
|
||||
|
||||
if (result) {
|
||||
// Output to console
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
// Forward declarations
|
||||
@ -21,6 +22,14 @@ struct Vector {
|
||||
return Vector(c[0] - other.c[0], c[1] - other.c[1], c[2] - other.c[2]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Vector operator*(float scalar) const {
|
||||
return Vector(c[0] * scalar, c[1] * scalar, c[2] * scalar);
|
||||
}
|
||||
@ -36,18 +45,22 @@ struct Vector {
|
||||
};
|
||||
|
||||
struct Point {
|
||||
Point(Vector pos, Triangle *triangle) : pos(pos), triangle(triangle) {}
|
||||
Point(Vector pos) : pos(pos) {}
|
||||
|
||||
Point(Vector pos, std::list<Triangle *> triangles) : pos(pos), triangles(triangles) {}
|
||||
|
||||
Vector pos;
|
||||
|
||||
Triangle *triangle;
|
||||
std::list<Triangle *> triangles;
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
Triangle(Vector p1, Vector p2, Vector p3) : p1(p1), p2(p2), p3(p3) {}
|
||||
|
||||
std::vector<Point *> create_point_objects() {
|
||||
return std::vector<Point *>{new Point(p1, this), new Point(p2, this), new Point(p3, this)};
|
||||
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})};
|
||||
}
|
||||
|
||||
Vector p1;
|
||||
@ -74,7 +87,7 @@ struct Ray {
|
||||
|
||||
Vector direction;
|
||||
|
||||
bool intersects_triangle(Triangle *triangle, Vector &result) {
|
||||
bool intersects_triangle(const Triangle *triangle, Vector &result, float &t) {
|
||||
// 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;
|
||||
@ -103,7 +116,7 @@ struct Ray {
|
||||
|
||||
// At this stage we can compute t to find out where the intersection point is on the
|
||||
// line.
|
||||
float t = f * edge2.dot(q);
|
||||
t = f * edge2.dot(q);
|
||||
if (t > EPSILON) {
|
||||
result = origin + direction * t;
|
||||
return true;
|
||||
|
@ -11,7 +11,7 @@ class KDTree {
|
||||
|
||||
~KDTree() = default; // TODO: Delete all allocated Nodes
|
||||
|
||||
Triangle *intersect_ray(Ray ray, Vector &result) {
|
||||
const Triangle *intersect_ray(const Ray ray, Vector &result) {
|
||||
return intersect_ray_recurse(result, ray, root, 1000.0, 0);
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ class KDTree {
|
||||
build(right_of_median, depth + 1));
|
||||
}
|
||||
|
||||
Triangle *intersect_ray_recurse(Vector &result, Ray ray, Node *node, float max_distance,
|
||||
const Triangle *intersect_ray_recurse(Vector &result, Ray ray, Node *node, float max_distance,
|
||||
int depth) {
|
||||
// Exit condition: There was no collision
|
||||
if (node == nullptr) { return nullptr; }
|
||||
@ -108,17 +108,31 @@ class KDTree {
|
||||
? (node->point->pos[node->axis] - ray.origin[node->axis]) /
|
||||
ray.direction[node->axis]
|
||||
: max_distance;
|
||||
Triangle *near_result = intersect_ray_recurse(result, ray, near, t, depth + 1);
|
||||
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
|
||||
if (ray.intersects_triangle(node->point->triangle, result)) {
|
||||
// We do have a collision here, so we're done and can return this point!
|
||||
return node->point->triangle;
|
||||
float nearest = 100000; // FIXME
|
||||
const Triangle *nearest_triangle = nullptr;
|
||||
|
||||
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;
|
||||
result = current_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nearest_triangle) { return nearest_triangle; }
|
||||
|
||||
// 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user