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
|
use super::{LeavesMode, MapRenderSettings, MeshgenInfo, Vertex, CUBE, FACE_DIR};
use cgmath::Point3;
use mt_net::MapBlock;
#[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(
mkinfo: &MeshgenInfo,
settings: &MapRenderSettings,
_pos: Point3<i16>,
block: &MapBlock,
nbors: [Option<&MapBlock>; 6],
buffer: &mut MeshData,
) {
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, // FIXME
_ => 1.0,
};
let vertices = if def.alpha == mt_net::Alpha::Blend {
&mut buffer.vertices_blend
} else {
&mut buffer.vertices
};
let pos: [i16; 3] = array(|i| ((index >> (4 * i)) & 0xf) as i16);
for (f, face) in CUBE.iter().enumerate() {
if draw_type == DrawType::Cube || draw_type == DrawType::Liquid {
let c = [1, 1, 0, 0, 2, 2][f];
let mut nblk = block;
let mut npos = pos;
npos[c] += FACE_DIR[f][c];
if !(0..16).contains(&npos[c]) {
nblk = match nbors[f].as_ref() {
Some(x) => x,
None => continue,
};
npos[c] = (npos[c] + 16) % 16;
}
let nidx = npos[0] | (npos[1] << 4) | (npos[2] << 8);
let ncontent = nblk.param_0[nidx as usize];
if let Some(ndef) = &mkinfo.nodes[ncontent as usize] {
if match draw_type {
DrawType::Cube => ndef.draw_type == DrawType::Cube,
DrawType::Liquid => ndef.draw_type == DrawType::Cube || ncontent == content,
_ => false,
} {
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]))| {
vertices.push(Vertex {
pos: array(|i| pos[i] as f32 + vertex.1 .0[i]),
tex_coords: texture[vertex.0],
light,
});
};
face.iter().enumerate().for_each(&mut add_vertex);
if !tile.flags.contains(mt_net::TileFlag::BackfaceCull) {
face.iter().enumerate().rev().for_each(&mut add_vertex);
}
}
}
}
|