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
use nalgebra::{Vector2, Vector3};
use traffloat_types::geometry;
use xias::Xias;

pub fn compute() -> three_d::CPUMesh {
    let mut positions = Vec::new();
    let mut normals = Vec::new();
    let mut uvs = Vec::new();

    for axis in 0..3 {
        for sign in [Sign::Positive, Sign::Negative] {
            let direction = Direction { axis, sign };

            let normal = direction.as_vector();

            let b = {
                let mut vector = Vector3::new(0., 0., 0.);
                vector[(axis + 1) % 3] = sign.as_float();
                vector
            };
            let c = normal.cross(&b);

            let tex_pos = geometry::Unit::Cube
                .search_sprite_coord_by_name(direction.name())
                .expect("Direction::name mismatches Unit::sprite_name");
            let uv0 = Vector2::new(tex_pos.0.small_float(), tex_pos.1.small_float());

            let corners = [
                Vector2::new(-1., -1.),
                Vector2::new(-1., 1.),
                Vector2::new(1., -1.),
                Vector2::new(1., 1.),
            ];

            for triangle in [[0, 2, 1], [1, 2, 3]] {
                for corner in triangle {
                    let offset = corners[corner];

                    let position = normal + b * offset[0] + c * offset[1];

                    let mut uv = uv0 + Vector2::new(0.5, 0.5) + offset * 0.5;
                    uv /= 4.; // 6 sprites for a cube mesh, fits on a 4^2 spritesheet.

                    positions.extend(position.as_slice());
                    normals.extend(normal.as_slice());
                    uvs.extend(uv.as_slice());
                }
            }
        }
    }

    three_d::CPUMesh {
        name: "traffloat.cube".to_string(),
        positions,
        normals: Some(normals),
        uvs: Some(uvs),
        ..Default::default()
    }
}

#[derive(Debug, Clone, Copy)]
struct Direction {
    axis: usize,
    sign: Sign,
}

impl Direction {
    fn as_vector(self) -> Vector3<f32> {
        let mut triple = [0.; 3];
        triple[self.axis] = self.sign.as_float();
        Vector3::from_iterator(triple)
    }

    fn name(&self) -> &'static str {
        match self {
            Self { axis: 0, sign: Sign::Positive } => "xp",
            Self { axis: 0, sign: Sign::Negative } => "xn",
            Self { axis: 1, sign: Sign::Positive } => "yp",
            Self { axis: 1, sign: Sign::Negative } => "yn",
            Self { axis: 2, sign: Sign::Positive } => "zp",
            Self { axis: 2, sign: Sign::Negative } => "zn",
            _ => unreachable!("Constructed direction with invalid axis"),
        }
    }
}

#[derive(Debug, Clone, Copy)]
enum Sign {
    Positive,
    Negative,
}

impl Sign {
    fn as_float(self) -> f32 {
        match self {
            Self::Positive => 1.,
            Self::Negative => -1.,
        }
    }
}