boids-playground/src/raycast.cpp

64 lines
2.2 KiB
C++

#include "raycast.hpp"
static float get_intersect_point(Vector2 ray_origin, Vector2 ray_dir, Vector2 line1, Vector2 line2) {
Vector2 line_dir = Vector2Subtract(line2, line1);
float D = ray_dir.x * line_dir.y - ray_dir.y * line_dir.x;
float u = ((line1.x - ray_origin.x) * ray_dir.y - (line1.y - ray_origin.y) * ray_dir.x) / D;
float t = ((line1.x - ray_origin.x) * line_dir.y - (line1.y - ray_origin.y) * line_dir.x) / D;
if (0 <= u && u <= 1 && t >= 0) {
return t;
} else {
return -1;
}
}
static void set_nearest_hit(RayHitResult *nearest_hit, float hit, Vector2 line1, Vector2 line2) {
bool got_hit = hit >= 0;
bool is_gotten_hit_better = (nearest_hit->hit < 0 || nearest_hit->hit > hit);
if (got_hit && is_gotten_hit_better) {
nearest_hit->hit = hit;
nearest_hit->line1 = line1;
nearest_hit->line2 = line2;
}
}
static void get_intersect_with_polygon(RayHitResult *result, Vector2 ray_origin, Vector2 ray_dir, Vector2 *points, int point_count) {
if (point_count < 2) return;
for (int i = 0; i < point_count-1; i++) {
Vector2 p1 = points[i];
Vector2 p2 = points[i+1];
float hit = get_intersect_point(ray_origin, ray_dir, p1, p2);
set_nearest_hit(result, hit, p1, p2);
}
if (point_count > 2) {
Vector2 p1 = points[0];
Vector2 p2 = points[point_count-1];
float hit = get_intersect_point(ray_origin, ray_dir, p1, p2);
set_nearest_hit(result, hit, p1, p2);
}
}
static void get_intersect_with_obstacles(RayHitResult *result, Vector2 ray_origin, Vector2 ray_dir, std::vector<Obstacle> *obstacles) {
for (int i = 0; i < (*obstacles).size(); i++) {
Obstacle *obstacle = &(*obstacles)[i];
get_intersect_with_polygon(result, ray_origin, ray_dir, obstacle->points.data(), obstacle->points.size());
}
}
static void get_intersect_with_world(RayHitResult *result, Vector2 ray_origin, Vector2 ray_dir, World *world) {
get_intersect_with_obstacles(result, ray_origin, ray_dir, &world->obstacles);
if (result->hit == -1 && !world->looping_walls) {
Vector2 lines[] = {
{ 0 , 0 },
{ world->size.x, 0 },
{ world->size.x, world->size.y },
{ 0 , world->size.y }
};
get_intersect_with_polygon(result, ray_origin, ray_dir, lines, 4);
}
}