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
use crate::world::voxels::{BlockRotation, ROTATION_MASK, STAGE_MASK, Y_ROTATION_MASK};
pub struct BlockUtils;
impl BlockUtils {
pub fn extract_id(voxel: u32) -> u32 {
voxel & 0xFFFF
}
pub fn insert_id(voxel: u32, id: u32) -> u32 {
(voxel & 0xFFFF0000) | (id & 0xFFFF)
}
pub fn extract_rotation(voxel: u32) -> BlockRotation {
let rotation = (voxel >> 16) & 0xF;
let y_rot = (voxel >> 20) & 0xF;
BlockRotation::encode(rotation, y_rot)
}
pub fn insert_rotation(voxel: u32, rotation: &BlockRotation) -> u32 {
let (rotation, y_rot) = BlockRotation::decode(rotation);
let value = (voxel & ROTATION_MASK) | ((rotation & 0xF) << 16);
(value & Y_ROTATION_MASK) | ((y_rot & 0xF) << 20)
}
pub fn extract_stage(voxel: u32) -> u32 {
(voxel >> 24) & 0xF
}
pub fn insert_stage(voxel: u32, stage: u32) -> u32 {
assert!(stage <= 15, "Maximum stage is 15");
(voxel & STAGE_MASK) | (stage << 24)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn id_insertion() {
let mut voxel = 100230120;
let id = 13;
voxel = BlockUtils::insert_id(voxel, id);
assert_eq!(BlockUtils::extract_id(voxel), id);
voxel = BlockUtils::insert_id(voxel, 65537);
assert_eq!(BlockUtils::extract_id(voxel), 1);
}
#[test]
fn rotation_insertion() {
let mut voxel = 0;
let id = 13;
voxel = BlockUtils::insert_id(voxel, id);
assert_eq!(BlockUtils::extract_rotation(voxel), BlockRotation::PY(0));
voxel = BlockUtils::insert_rotation(voxel, &BlockRotation::NX(0));
assert_eq!(BlockUtils::extract_rotation(voxel), BlockRotation::NX(0));
voxel = BlockUtils::insert_rotation(voxel, &BlockRotation::PZ(90));
assert_eq!(BlockUtils::extract_rotation(voxel), BlockRotation::PZ(90));
assert_eq!(BlockUtils::extract_id(voxel), id);
}
#[test]
fn rotation_correctness() {
let rotation = BlockRotation::PX(0);
let compare = |a: [f32; 3], b: [f32; 3]| {
assert!((a[0] - b[0]).abs() < f32::EPSILON);
assert!((a[1] - b[1]).abs() < f32::EPSILON);
assert!((a[2] - b[2]).abs() < f32::EPSILON);
};
let mut point = [0.0, 1.0, 0.0];
rotation.rotate_node(&mut point, false);
compare(point, [1.0, 0.0, 0.0]);
point = [0.0, 0.0, 1.0];
rotation.rotate_node(&mut point, false);
compare(point, [0.0, 0.0, 1.0]);
}
#[test]
fn stage() {
let mut voxel = 0;
let id = 13;
voxel = BlockUtils::insert_id(voxel, id);
assert_eq!(BlockUtils::extract_stage(voxel), 0);
for stage in 0..16 {
voxel = BlockUtils::insert_stage(voxel, stage);
assert_eq!(BlockUtils::extract_stage(voxel), stage);
}
assert_eq!(BlockUtils::extract_id(voxel), id);
}
}