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
use crate::{Vec2, Vec3};

const CONCAT: &str = "|";

/// A set of utility functions for chunk operations.
pub struct ChunkUtils;

fn floor_scale_coords(x: f32, y: f32, z: f32, factor: f32) -> Vec3<f32> {
    Vec3(
        (x * factor).floor(),
        (y * factor).floor(),
        (z * factor).floor(),
    )
}

impl ChunkUtils {
    /// Generate a chunk representation from a chunk coordinate.
    pub fn get_chunk_name(cx: i32, cz: i32) -> String {
        format!("{}{}{}", cx, CONCAT, cz)
    }

    /// Parse a chunk coordinate from a chunk representation.
    pub fn parse_chunk_name(name: &str) -> Vec2<i32> {
        let vec = name.split(CONCAT).collect::<Vec<&str>>();
        Vec2(vec[0].parse().unwrap(), vec[1].parse().unwrap())
    }

    /// Generate a voxel representation from a voxel coordinate.
    pub fn get_voxel_name(vx: i32, vy: i32, vz: i32) -> String {
        format!("{}{}{}{}{}", vx, CONCAT, vy, CONCAT, vz)
    }

    /// Parse a voxel coordinate from a voxel representation.
    pub fn parse_voxel_name(name: &str) -> Vec3<i32> {
        let vec = name.split(CONCAT).collect::<Vec<&str>>();
        Vec3(
            vec[0].parse().unwrap(),
            vec[1].parse().unwrap(),
            vec[2].parse().unwrap(),
        )
    }

    /// Map a voxel coordinate to a chunk coordinate.
    pub fn map_voxel_to_chunk(vx: i32, vy: i32, vz: i32, chunk_size: usize) -> Vec2<i32> {
        let scaled = Vec3::<i32>::from(&floor_scale_coords(
            vx as f32,
            vy as f32,
            vz as f32,
            1.0 / (chunk_size as f32),
        ));
        Vec2(scaled.0, scaled.2)
    }

    /// Map a voxel coordinate to a chunk local coordinate.
    pub fn map_voxel_to_chunk_local(vx: i32, vy: i32, vz: i32, chunk_size: usize) -> Vec3<usize> {
        let Vec2(cx, cz) = ChunkUtils::map_voxel_to_chunk(vx, vy, vz, chunk_size);
        let cs = chunk_size as i32;

        Vec3(
            (vx - cx * cs) as usize,
            vy as usize,
            (vz - cz * cs) as usize,
        )
    }
}