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
|
#include "shared/pch.hh"
#include "shared/world/ray_dda.hh"
#include "shared/world/dimension.hh"
#include "shared/coord.hh"
world::RayDDA::RayDDA(const world::Dimension* dimension, const chunk_pos& start_chunk, const glm::fvec3& start_fpos,
const glm::fvec3& direction)
{
reset(dimension, start_chunk, start_fpos, direction);
}
world::RayDDA::RayDDA(const world::Dimension& dimension, const chunk_pos& start_chunk, const glm::fvec3& start_fpos,
const glm::fvec3& direction)
{
reset(dimension, start_chunk, start_fpos, direction);
}
void world::RayDDA::reset(const world::Dimension* dimension, const chunk_pos& start_chunk, const glm::fvec3& start_fpos,
const glm::fvec3& direction)
{
this->dimension = dimension;
this->start_chunk = start_chunk;
this->start_fpos = start_fpos;
this->direction = direction;
this->delta_dist.x = direction.x ? math::abs(1.0f / direction.x) : std::numeric_limits<float>::max();
this->delta_dist.y = direction.y ? math::abs(1.0f / direction.y) : std::numeric_limits<float>::max();
this->delta_dist.z = direction.z ? math::abs(1.0f / direction.z) : std::numeric_limits<float>::max();
this->distance = 0.0f;
this->vpos = coord::to_voxel(start_chunk, start_fpos);
this->vnormal = voxel_pos(0, 0, 0);
// Need this for initial direction calculations
auto lpos = coord::to_local(start_fpos);
if(direction.x < 0.0f) {
this->side_dist.x = this->delta_dist.x * (start_fpos.x - lpos.x);
this->vstep.x = voxel_pos::value_type(-1);
}
else {
this->side_dist.x = this->delta_dist.x * (lpos.x + 1.0f - start_fpos.x);
this->vstep.x = voxel_pos::value_type(+1);
}
if(direction.y < 0.0f) {
this->side_dist.y = this->delta_dist.y * (start_fpos.y - lpos.y);
this->vstep.y = voxel_pos::value_type(-1);
}
else {
this->side_dist.y = this->delta_dist.y * (lpos.y + 1.0f - start_fpos.y);
this->vstep.y = voxel_pos::value_type(+1);
}
if(direction.z < 0.0f) {
this->side_dist.z = this->delta_dist.z * (start_fpos.z - lpos.z);
this->vstep.z = voxel_pos::value_type(-1);
}
else {
this->side_dist.z = this->delta_dist.z * (lpos.z + 1.0f - start_fpos.z);
this->vstep.z = voxel_pos::value_type(+1);
}
}
void world::RayDDA::reset(const world::Dimension& dimension, const chunk_pos& start_chunk, const glm::fvec3& start_fpos,
const glm::fvec3& direction)
{
reset(&dimension, start_chunk, start_fpos, direction);
}
const world::Voxel* world::RayDDA::step(void)
{
if(side_dist.x < side_dist.z) {
if(side_dist.x < side_dist.y) {
vnormal = voxel_pos(-vstep.x, 0, 0);
distance = side_dist.x;
side_dist.x += delta_dist.x;
vpos.x += vstep.x;
}
else {
vnormal = voxel_pos(0, -vstep.y, 0);
distance = side_dist.y;
side_dist.y += delta_dist.y;
vpos.y += vstep.y;
}
}
else {
if(side_dist.z < side_dist.y) {
vnormal = voxel_pos(0, 0, -vstep.z);
distance = side_dist.z;
side_dist.z += delta_dist.z;
vpos.z += vstep.z;
}
else {
vnormal = voxel_pos(0, -vstep.y, 0);
distance = side_dist.y;
side_dist.y += delta_dist.y;
vpos.y += vstep.y;
}
}
// This is slower than I want it to be
return dimension->get_voxel(vpos);
}
|