-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathraycast.cpp
More file actions
74 lines (58 loc) · 1.95 KB
/
raycast.cpp
File metadata and controls
74 lines (58 loc) · 1.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Copyright (C) 2019 - Sebastien Alaiwan
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
#include "collision.h"
#include <cmath>
static float min(float a, float b) { return a < b ? a : b; }
static Vec2 rotateLeft(Vec2 v) { return Vec2(-v.y, v.x); }
static float scalarProduct(Vec2 a, Vec2 b) { return a.x * b.x + a.y * b.y; }
float clamp(float val, float min, float max) { return val < min ? min : (val > max ? max : val); }
static float raycast(const Segment& segment, Vec2 from, Vec2 to)
{
Vec2 axes[4];
axes[0] = (to - from);
axes[1] = rotateLeft(to - from);
axes[2] = (segment.b - segment.a);
axes[3] = rotateLeft(segment.b - segment.a);
float maxSeparation = -1.0 / 0.0;
for(auto& axis : axes)
{
auto sFrom = scalarProduct(axis, from);
auto sTo = scalarProduct(axis, to);
auto sA = scalarProduct(axis, segment.a);
auto sB = scalarProduct(axis, segment.b);
// ensure 'sFrom <= sTo', so we can later take 'min(sA, sB)'
if(sFrom > sTo)
{
sFrom = -sFrom;
sTo = -sTo;
sA = -sA;
sB = -sB;
}
// sB sA sFrom sTo
// ---[======]-----[==========]----
if(sFrom > sA && sFrom > sB)
return 1.0; // separated by axis
// sFrom sTo sB sA
// --[==========]------[======]--------
if(sTo < sA && sTo < sB)
return 1.0; // separated by axis
auto separation = clamp((min(sA, sB) - sFrom) / (sTo - sFrom), 0, 1);
if(separation > maxSeparation)
maxSeparation = separation;
}
return maxSeparation;
}
float raycast(Vec2 from, Vec2 to, span<Segment> segments)
{
float minRatio = 1.0;
for(auto& segment : segments)
{
auto ratio = raycast(segment, from, to);
if(ratio < minRatio)
minRatio = ratio;
}
return minRatio;
}