generated from rpuzonas/raylib-cpp-template
64 lines
2.2 KiB
C++
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);
|
|
}
|
|
}
|