added a proper collision system

This commit is contained in:
Jay Robson 2024-01-29 22:05:12 +11:00
parent 2e0a949ab8
commit 821897bbaa
7 changed files with 110 additions and 36 deletions

View File

@ -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;
}
velocity.x += rotated.x * m * dt;
velocity.y += rotated.y * m * dt;
}
else
if(on_ground && keyboard::is_pressed(GLFW_KEY_SPACE))
{
m = 0;
velocity.z += 3.5;
}
velocity.x += rotated.x * m * dt;
velocity.y += rotated.y * m * dt;
glm::vec<3, double> velocity2 = sys.scene.check_intersect(pos, velocity * dt) / dt;
double nx = pos.x + velocity.x * dt;
double ny = pos.y + velocity.y * 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));

View File

@ -4,13 +4,15 @@
#include <glm/matrix.hpp>
#include <glm/vec3.hpp>
#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);
};

View File

@ -3,6 +3,9 @@
#include "arrays.hpp"
#include "../shader.hpp"
#include "../camera.hpp"
#include "../../math.hpp"
#include <iostream>
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<double>::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;
}

View File

@ -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 <class T>
void load_text(const char* header, T& item, double size)
{

View File

@ -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);
}

View File

@ -41,6 +41,8 @@ system::system()
valve = new coolant::valve<reactor::coolant::vessel>(*vessel, 1, 500);
pump = new coolant::pump<reactor::coolant::vessel>(*vessel, 1e4, 15);
scene.load_model("../assets/model", "scene_collisions.stl");
}
system::system(system&& o)

View File

@ -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<sim::reactor::coolant::vessel>* valve;
sim::coolant::pump<sim::reactor::coolant::vessel>* pump;
sim::graphics::mesh scene;
system();
system(system&& o);