-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathboxcol.c
105 lines (95 loc) · 3.19 KB
/
boxcol.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
#include "boxcol.h"
#include "utilities.h"
AABB translated_AABB(AABB * aabb, vec3_t vec)
{
return (AABB) {
v3_add(aabb->pos, vec), aabb->dim};
}
bool map_collides(AABB * aabb, Map * map, vec3_t * collision_normal,
bool enabled_faces[6])
{
/* Of course, this assumes that AABB contains the actual position of
the box itself. This could be modified by adding an additional
position vector, and adding it to the AABB, so then the AABB is
just a box. */
/* We need to calculate all the blocks that could be in the vicinity
of aabb. So, if block size is 1, then... */
/* We keep track of the closest block to have collided */
vec3_t collision_points[6];
collision_points[FACE_LEFT] = vec3(aabb->pos.x,
aabb->pos.y + aabb->dim.y / 2,
aabb->pos.z + aabb->dim.z / 2);
collision_points[FACE_RIGHT] = vec3(aabb->pos.x + aabb->dim.x,
aabb->pos.y + aabb->dim.y / 2,
aabb->pos.z + aabb->dim.z / 2);
collision_points[FACE_DOWN] = vec3(aabb->pos.x + aabb->dim.x / 2,
aabb->pos.y,
aabb->pos.z + aabb->dim.z / 2);
collision_points[FACE_UP] = vec3(aabb->pos.x + aabb->dim.x / 2,
aabb->pos.y + aabb->dim.y,
aabb->pos.z + aabb->dim.z / 2);
collision_points[FACE_BACK] = vec3(aabb->pos.x + aabb->dim.x / 2,
aabb->pos.y + aabb->dim.y / 2,
aabb->pos.z);
collision_points[FACE_FRONT] = vec3(aabb->pos.x + aabb->dim.x / 2,
aabb->pos.y + aabb->dim.y / 2,
aabb->pos.z + aabb->dim.z);
bool collision = false;
float closest_dist = 9999999;
int closest_face = FACE_BACK;
vec3_t real_start = vec3(aabb->pos.x / BLOCK_SIZE, aabb->pos.y / BLOCK_SIZE,
aabb->pos.z / BLOCK_SIZE);
vec3_t real_dim = vec3(aabb->dim.x / BLOCK_SIZE, aabb->dim.y / BLOCK_SIZE,
aabb->dim.z / BLOCK_SIZE);
for (int z = floor(real_start.z); z < ceil(real_start.z + real_dim.z); ++z) {
for (int y = floor(real_start.y); y < ceil(real_start.y + real_dim.y);
++y) {
for (int x = floor(real_start.x);
x < ceil(real_start.x + real_dim.x); ++x) {
Block *b = get_block_or_null(map, x, y, z, 0);
if (b && b->type != 0) {
collision = true;
for (int face = 0; face < 6; ++face) {
if (!enabled_faces[face]) {
continue;
}
float dist = 0.f;
switch (face) {
/* Z axis, compare against the BACK face of the cube */
case FACE_BACK:
dist = fabs(collision_points[face].z - z);
break;
case FACE_FRONT:
dist =
fabs(collision_points[face].z -
(z + BLOCK_SIZE));
break;
case FACE_RIGHT:
dist = fabs(collision_points[face].x - x);
break;
case FACE_LEFT:
dist =
fabs(collision_points[face].x -
(x + BLOCK_SIZE));
break;
case FACE_UP:
dist = fabs(collision_points[face].y - y);
break;
case FACE_DOWN:
dist =
fabs(collision_points[face].y -
(y + BLOCK_SIZE));
break;
}
if (dist < closest_dist) {
closest_dist = dist;
closest_face = face;
}
}
}
}
}
}
*collision_normal = FACE_NORMALS[closest_face];
return collision;
}