-
Notifications
You must be signed in to change notification settings - Fork 0
/
w_collision.c
134 lines (127 loc) · 3.37 KB
/
w_collision.c
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "w_collision.h"
#include "m_math.h"
static bool raySegmentIntersect(Ray ray, Segment segment)
{
const Vec2 v1 = m_Subtract(ray.orig, segment.A);
const Vec2 d1 = ray.dir;
const Vec2 d2 = m_Subtract(segment.B, segment.A);
const Mat2 m1 = {
v1.x, d2.x,
v1.y, d2.y
};
const Mat2 m2 = {
v1.x, d1.x,
v1.y, d1.y
};
const Mat2 m3 = {
d2.x, d1.x,
d2.y, d1.y
};
const float denom = m_Determinant(m3);
if (denom == 0) return false;
const float t1 = m_Determinant(m1) / denom;
const float t2 = m_Determinant(m2) / denom;
if (t1 < 0) return false;
if (t2 < 0 || t2 > 1) return false;
return true;
}
static bool segmentIntersect(Segment seg1, Segment seg2)
{
const Vec2 v1 = m_Subtract(seg1.A, seg2.A);
const Vec2 d1 = m_Subtract(seg1.B, seg1.A);
const Vec2 d2 = m_Subtract(seg2.B, seg2.A);
const Mat2 m1 = {
v1.x, d2.x,
v1.y, d2.y
};
const Mat2 m2 = {
v1.x, d1.x,
v1.y, d1.y
};
const Mat2 m3 = {
d2.x, d1.x,
d2.y, d1.y
};
const float denom = m_Determinant(m3);
if (denom == 0) return false;
const float t1 = m_Determinant(m1) / denom;
const float t2 = m_Determinant(m2) / denom;
if (t1 < 0 || t1 > 1) return false;
if (t2 < 0 || t2 > 1) return false;
return true;
}
static bool pointInCircle(Vec2 point, Vec2 center, const float radius)
{
m_Scale(-1, ¢er);
m_Translate(center, &point);
return (m_Length2(point) < radius * radius);
}
static bool segmentCrossGeo(const Vec2 endPoint, const Vec2 startPoint, const Geo geo)
{
const Vertex* verts = &w_ObjectVertexBuffer[geo.vertIndex];
Segment segmentA = {
.A = startPoint,
.B = endPoint
};
for (int i = 0; i < geo.vertCount - 1; i++)
{
Segment segmentB = {
.A = verts[i],
.B = verts[i+1]
};
if (segmentIntersect(segmentA, segmentB))
return true;
}
return false;
}
static bool pointInGeo(const Vec2 point, const Geo geo)
{
int intersections = 0;
const Vertex* verts = &w_ObjectVertexBuffer[geo.vertIndex];
Ray ray = {
.orig = point,
.dir = {1, 0}
};
for (int i = 0; i < geo.vertCount - 1; i++)
{
Segment segment = {
.A = verts[i],
.B = verts[i+1]
};
if (raySegmentIntersect(ray, segment))
intersections++;
}
if (intersections % 2 == 0)
return false;
return true;
}
static bool emitInObject(int emitId, int objId)
{
if (pointInCircle(w_Emitables[emitId].pos,
w_Objects[objId].pos,
w_Colliders[objId].radius))
return (segmentCrossGeo(w_Emitables[emitId].pos, w_Emitables[emitId].prevPos, w_Geos[objId]));
return false;
}
HitInfo w_DetectBulletObjectCols(void)
{
HitInfo hitInfo;
const int emitCount = w_EmitableCount;
const int objCount = w_ObjectCount;
for (int i = 0; i < emitCount; i++)
{
// start at 1 becuase 0 is player
for (int j = 1; j < objCount; j++)
{
if (emitInObject(i, j))
{
hitInfo.collision = true;
hitInfo.object1 = i;
hitInfo.object2 = j;
return hitInfo;
}
}
}
hitInfo.collision = false;
return hitInfo;
}