]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/raycast.c
c1f4a93a385a8ceefbfd02c7b040f4800155534f
[dragonblocks_alpha.git] / src / client / raycast.c
1 #include <math.h>
2 #include "client/client_node.h"
3 #include "client/client_terrain.h"
4 #include "client/raycast.h"
5
6 bool raycast(v3f64 pos, v3f64 dir, f64 len, v3s32 *node_pos, NodeType *node)
7 {
8         f64 dir_len = sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
9
10         while (len > 0) {
11                 *node = terrain_get_node(client_terrain,
12                         *node_pos = (v3s32) {floor(pos.x + 0.5), floor(pos.y + 0.5), floor(pos.z + 0.5)}).type;
13
14                 if (*node == NODE_UNLOADED)
15                         return false;
16
17                 if (client_node_defs[*node].pointable)
18                         return true;
19
20                 f64 vpos[3] = {pos.x, pos.y, pos.z};
21                 f64 vdir[3] = {dir.x, dir.y, dir.z};
22                 f64 min_mul = 1.0;
23
24                 for (int i = 0; i < 3; i++) {
25                         if (!vdir[i])
26                                 continue;
27
28                         f64 p = vpos[i] + 0.5;
29                         f64 d = vdir[i] / fabs(vdir[i]);
30
31                         f64 f = floor(p) - p;
32                         if (d > 0.0)
33                                 f += 1.0;
34                         f += 0.001 * d;
35
36                         f64 mul = f / vdir[i];
37                         if (min_mul > mul && mul)
38                                 min_mul = mul;
39                 }
40
41                 pos = v3f64_add(pos, v3f64_scale(dir, min_mul));
42                 len -= dir_len * min_mul;
43         }
44
45         return false;
46 }