summaryrefslogtreecommitdiff
path: root/src/gfx/map/mesh.rs
blob: 0befb1ec6bbad4e837f53b6ba9a75ac1a52da8e9 (plain)
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
115
116
117
118
119
120
121
122
123
124
125
use super::{LeavesMode, MapRenderSettings, MeshMakeInfo, Vertex, CUBE};
use cgmath::Point3;
use mt_net::MapBlock;
use std::ops::Deref;
use std::sync::Arc;

#[derive(Clone)]
pub(super) struct MeshData {
    pub vertices: Vec<Vertex>,
    pub vertices_blend: Vec<Vertex>,
}

impl MeshData {
    pub fn new(cap: usize) -> Self {
        Self {
            vertices: Vec::with_capacity(cap),
            vertices_blend: Vec::with_capacity(cap),
        }
    }

    pub fn cap(&self) -> usize {
        std::cmp::max(self.vertices.capacity(), self.vertices_blend.capacity())
    }
}

pub(super) fn create_mesh(
    buffer_cap: &mut usize,
    mkinfo: Arc<MeshMakeInfo>,
    settings: &MapRenderSettings,
    pos: Point3<i16>,
    block: Box<MapBlock>,
) -> (Point3<i16>, MeshData) {
    let mkinfo = mkinfo.deref();
    let mut buffer = MeshData::new(*buffer_cap);

    for (index, content) in block.param_0.iter().enumerate() {
        let def = match &mkinfo.nodes[*content as usize] {
            Some(x) => x,
            None => continue,
        };

        use mt_net::{DrawType, Param1Type};
        use std::array::from_fn as array;

        let mut tiles = &def.tiles;
        let mut draw_type = def.draw_type;

        match draw_type {
            DrawType::AllFacesOpt => {
                draw_type = match settings.leaves {
                    LeavesMode::Opaque => DrawType::Cube,
                    LeavesMode::Simple => {
                        tiles = &def.special_tiles;

                        DrawType::GlassLike
                    }
                    LeavesMode::Fancy => DrawType::AllFaces,
                };
            }
            DrawType::None => continue,
            _ => {}
        }

        let light = match def.param1_type {
            Param1Type::Light => block.param_1[index] as f32 / 15.0,
            _ => 1.0,
        };

        let pos: [i16; 3] = array(|i| ((index >> (4 * i)) & 0xf) as i16);

        for (f, face) in CUBE.iter().enumerate() {
            let dir = FACE_DIR[f];
            let npos: [i16; 3] = array(|i| dir[i] + pos[i]);
            if npos.iter().all(|x| (0..16).contains(x)) {
                let nindex = npos[0] | (npos[1] << 4) | (npos[2] << 8);

                if let Some(ndef) = &mkinfo.nodes[block.param_0[nindex as usize] as usize] {
                    if ndef.draw_type == DrawType::Cube {
                        continue;
                    }
                }
            }

            let tile = &tiles[f];
            let texture = mkinfo.textures[tile.texture.custom].cube_tex_coords[f];

            let mut add_vertex = |vertex: (usize, &([f32; 3], [f32; 2]))| {
                /*println!(
                    "{:?} {:?} {:?} {:?}",
                    (vertex.1[0], vertex.1[1]),
                    (rect[0].start, rect[1].start),
                    (rect[0].end, rect[1].end),
                    (
                        vertex.1[0].lerp(rect[0].start, rect[0].end),
                        vertex.1[1].lerp(rect[1].start, rect[1].end)
                    )
                );*/

                buffer.vertices.push(Vertex {
                    pos: array(|i| pos[i] as f32 - 8.5 + vertex.1 .0[i]),
                    tex_coords: texture[vertex.0],
                    light,
                });
            };

            face.iter().enumerate().for_each(&mut add_vertex);
            /*if !backface_cull {
                face.iter().enumerate().rev().for_each(&mut add_vertex);
            }*/
        }
    }

    *buffer_cap = buffer.cap();
    (pos, buffer)
}

#[rustfmt::skip]
const FACE_DIR: [[i16; 3]; 6] = [
	[ 0,  1,  0],
	[ 0, -1,  0],
	[ 1,  0,  0],
	[-1,  0,  0],
	[ 0,  0,  1],
	[ 0,  0, -1],
];