From 821897bbaa090c473f978435788f9098db0a93b2 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Mon, 29 Jan 2024 22:05:12 +1100 Subject: [PATCH] added a proper collision system --- src/graphics/camera.cpp | 47 ++++++--------------- src/graphics/camera.hpp | 4 +- src/graphics/mesh/mesh.cpp | 85 ++++++++++++++++++++++++++++++++++++++ src/graphics/mesh/mesh.hpp | 2 + src/main.cpp | 4 +- src/system.cpp | 2 + src/system.hpp | 2 + 7 files changed, 110 insertions(+), 36 deletions(-) diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index b855ae5..2c4f94d 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -14,6 +14,7 @@ using namespace sim::graphics; +static bool on_ground = false; static double yaw = 0, pitch = 0; static glm::vec<3, double> pos(0, 0, 2); static glm::vec<3, double> velocity(0); @@ -35,7 +36,7 @@ void camera::move(double xoff, double yoff, double zoff) pos.z += zoff; } -void camera::update(double dt) +void camera::update(const system& sys, double dt) { glm::vec<2, double> off(0, 0); double m = 30; @@ -61,46 +62,24 @@ void camera::update(double dt) }; glm::vec<2, double> rotated = glm::vec<2, double>(off.x, off.y) * mat; - bool on_ground = false; - velocity.z -= 9.81 * dt; - if(pos.z + velocity.z * dt < 1.6) + if(on_ground) { - on_ground = true; - - if(keyboard::is_pressed(GLFW_KEY_SPACE)) - { - velocity.z = 3.5; - } - - else - { - velocity.z = 0; - pos.z = 1.6; - } - } - - else - { - m = 0; + velocity.x += rotated.x * m * dt; + velocity.y += rotated.y * m * dt; } - velocity.x += rotated.x * m * dt; - velocity.y += rotated.y * m * dt; + if(on_ground && keyboard::is_pressed(GLFW_KEY_SPACE)) + { + velocity.z += 3.5; + } - double nx = pos.x + velocity.x * dt; - double ny = pos.y + velocity.y * dt; + glm::vec<3, double> velocity2 = sys.scene.check_intersect(pos, velocity * dt) / dt; - if(nx > 8.9 || nx < -2.9) - velocity.x = 0; - if(std::abs(ny) > 3.9) - velocity.y = 0; - - float m2 = std::pow(0.5, dt / (on_ground ? 0.05 : 1)); - - pos += velocity * dt; - velocity *= m2; + pos += velocity2 * dt; + on_ground = ((velocity * dt / dt).z != velocity2.z); + velocity = velocity2 * std::pow(0.5, dt / (on_ground ? 0.05 : 10)); camera_mat = glm::mat4(1); camera_mat = glm::rotate(camera_mat, (float)glm::radians(-pitch), glm::vec3(1, 0, 0)); diff --git a/src/graphics/camera.hpp b/src/graphics/camera.hpp index 93ddc1c..7d08761 100644 --- a/src/graphics/camera.hpp +++ b/src/graphics/camera.hpp @@ -4,13 +4,15 @@ #include #include +#include "../system.hpp" + namespace sim::graphics::camera { glm::mat4 get_matrix(); void rotate(double pitch, double yaw); void move(double x, double y, double z); -void update(double dt); +void update(const system& sys, double dt); }; diff --git a/src/graphics/mesh/mesh.cpp b/src/graphics/mesh/mesh.cpp index a411602..93a01ca 100644 --- a/src/graphics/mesh/mesh.cpp +++ b/src/graphics/mesh/mesh.cpp @@ -3,6 +3,9 @@ #include "arrays.hpp" #include "../shader.hpp" #include "../camera.hpp" +#include "../../math.hpp" + +#include using namespace sim::graphics; @@ -50,3 +53,85 @@ void mesh::set_indices(const unsigned int* data, size_t size) } } +typedef glm::vec<3, double> vec3; + +bool ray_intersects_triangle(vec3 ray_origin, + vec3 ray_vector, + const vec3* triangle, + vec3& out_intersection_point) +{ + constexpr double epsilon = std::numeric_limits::epsilon(); + + vec3 edge1 = triangle[1] - triangle[0]; + vec3 edge2 = triangle[2] - triangle[0]; + vec3 ray_cross_e2 = cross(ray_vector, edge2); + double det = dot(edge1, ray_cross_e2); + + if (det > -epsilon && det < epsilon) + return false; // This ray is parallel to this triangle. + + double inv_det = 1.0 / det; + vec3 s = ray_origin - triangle[0]; + double u = inv_det * dot(s, ray_cross_e2); + + if (u < 0 || u > 1) + return false; + + vec3 s_cross_e1 = cross(s, edge1); + double v = inv_det * dot(ray_vector, s_cross_e1); + + if (v < 0 || u + v > 1) + return false; + + // At this stage we can compute t to find out where the intersection point is on the line. + double t = inv_det * dot(edge2, s_cross_e1); + out_intersection_point = ray_origin + ray_vector * t; + + if (t > epsilon) // ray intersection + { + return true; + } + else // This means that there is a line intersection but not a ray intersection. + return false; +} + +vec3 mesh::check_intersect(vec3 pos, vec3 path) const +{ + double l = glm::length(path); + + if(l == 0) + { + return path; + } + + vec3 path_n = path / l; + bool intersects = false; + + for(unsigned int i = 0; i < indices.size(); i += 3) + { + vec3 v[3] = { + vec3(this->vertices[indices[i]].pos), + vec3(this->vertices[indices[i + 1]].pos), + vec3(this->vertices[indices[i + 2]].pos) + }; + + vec3 ipoint; + vec3 normal = glm::normalize(glm::cross(v[1] - v[0], v[2] - v[0])); + double d = glm::dot(normal, path); + + if(d >= 0) + continue; + if(!ray_intersects_triangle(pos, path_n, v, ipoint)) + continue; + if(l < glm::length(ipoint - pos)) + continue; + + intersects = true; + path -= normal * d; + l = glm::length(path); + path_n = path / l; + } + + return path; +} + diff --git a/src/graphics/mesh/mesh.hpp b/src/graphics/mesh/mesh.hpp index 698cbc1..115d23e 100644 --- a/src/graphics/mesh/mesh.hpp +++ b/src/graphics/mesh/mesh.hpp @@ -27,6 +27,8 @@ struct mesh void load_text(const char* text, double size); void add(const mesh& o, glm::mat4 mat); + glm::vec<3, double> check_intersect(glm::vec<3, double> pos, glm::vec<3, double> path) const; + template void load_text(const char* header, T& item, double size) { diff --git a/src/main.cpp b/src/main.cpp index 2dffe43..68f7277 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,8 @@ #include "coolant/valve.hpp" #include "coolant/pump.hpp" +#include "graphics/mesh/mesh.hpp" + #include "graphics/window.hpp" #include "graphics/camera.hpp" @@ -39,7 +41,7 @@ int main() clock += passed; sys.update(dt); - graphics::camera::update(dt); + graphics::camera::update(sys, dt); graphics::window::loop(sys); } diff --git a/src/system.cpp b/src/system.cpp index c2e1759..7785f24 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -41,6 +41,8 @@ system::system() valve = new coolant::valve(*vessel, 1, 500); pump = new coolant::pump(*vessel, 1e4, 15); + + scene.load_model("../assets/model", "scene_collisions.stl"); } system::system(system&& o) diff --git a/src/system.hpp b/src/system.hpp index a8154b1..36b0f4a 100644 --- a/src/system.hpp +++ b/src/system.hpp @@ -7,6 +7,7 @@ #include "reactor/reactor.hpp" #include "coolant/pump.hpp" #include "coolant/valve.hpp" +#include "graphics/mesh/mesh.hpp" namespace sim { @@ -17,6 +18,7 @@ struct system sim::reactor::coolant::vessel* vessel; sim::coolant::valve* valve; sim::coolant::pump* pump; + sim::graphics::mesh scene; system(); system(system&& o);