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
use std::f32::consts::PI;
use std::mem;

use xias::Xias;

const NUM_STEPS: usize = 32;

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

    let mut indices = Vec::new();
    let mut index_counter: u16 = 0;

    macro_rules! push_vertex {
        ($pos:expr, $theta:expr, $phi:expr) => {{
            positions.extend_from_slice(&[$pos[0], $pos[1], $pos[2]]);
            normals.extend_from_slice(&[$pos[0], $pos[1], $pos[2]]);
            uvs.extend_from_slice(&[$phi / PI / 2., $theta / PI]);

            let index = index_counter;
            index_counter += 1;
            index
        }};
    }

    let top = push_vertex!([0., 0., 1.], 0., 0.);
    let bottom = push_vertex!([0., 0., -1.], PI, 0.);

    let mut previous = vec![top; NUM_STEPS];
    let mut current = vec![0; NUM_STEPS];

    for i in 1..NUM_STEPS {
        let theta = i.small_float::<f32>() * PI / NUM_STEPS.small_float::<f32>();
        let (theta_sin, theta_cos) = theta.sin_cos();

        #[allow(clippy::needless_range_loop)]
        for j in 0..NUM_STEPS {
            let phi = j.small_float::<f32>() * PI * 2. / NUM_STEPS.small_float::<f32>();
            let (phi_sin, phi_cos) = phi.sin_cos();

            let vert =
                push_vertex!([theta_sin * phi_cos, theta_sin * phi_sin, theta_cos], theta, phi);
            current[j] = vert;
        }

        for j in 0..NUM_STEPS {
            let jj = if j + 1 == NUM_STEPS { 0 } else { j + 1 };

            indices.extend_from_slice(&[previous[j], previous[jj], current[j]]);
            indices.extend_from_slice(&[current[j], previous[jj], current[jj]]);

            if i + 1 == NUM_STEPS {
                indices.extend_from_slice(&[current[j], current[jj], bottom]);
            }
        }

        mem::swap(&mut previous, &mut current);
    }

    three_d::CPUMesh {
        name: "traffloat.sphere".to_string(),
        positions,
        normals: Some(normals),
        uvs: Some(uvs),
        indices: Some(three_d::Indices::U16(indices)),
        ..Default::default()
    }
}