Created
July 17, 2021 11:50
-
-
Save IcyTv/7408523d21b8cccbfb29f927d4e098b2 to your computer and use it in GitHub Desktop.
Greedy meshing algorithm for rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
The original algorithm comes from https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ | |
and the code is almost a straight adaptation of that code (https://github.com/mikolalysenko/mikolalysenko.github.com/blob/gh-pages/MinecraftMeshes/js/greedy.js) | |
*/ | |
fn greedy_meshing( | |
is_voxel_present: &dyn Fn(i32, i32, i32) -> bool, | |
dims: &[i32; 3], | |
) -> Vec<[[i32; 3]; 4]> { | |
let mut quads = Vec::new(); | |
for d in 0..3 { | |
let u = (d + 1) % 3; | |
let v = (d + 2) % 3; | |
println!("Walking {} {} {}", d, u, v); | |
let mut x = [0i32, 0i32, 0i32]; | |
let mut q = [0i32, 0i32, 0i32]; | |
let mask_size = dims[u] * dims[v]; | |
let mut mask = vec![false; mask_size as usize]; | |
mask.fill(false); | |
q[d] = 1; | |
x[d] = -1; | |
//YEs, this is a bit of a hack, but it works. | |
while x[d] < dims[d] { | |
let mut n = 0i32; | |
//Compute mask | |
x[v] = 0; | |
while x[v] < dims[v] { | |
x[u] = 0; | |
while x[u] < dims[u] { | |
let mut mask1 = false; | |
if 0 <= x[d] { | |
mask1 = is_voxel_present(x[0], x[1], x[2]); | |
} | |
let mut mask2 = false; | |
if x[d] < dims[d] - 1 { | |
mask2 = is_voxel_present(x[0] + q[0], x[1] + q[1], x[2] + q[2]); | |
} | |
if n < 0 { | |
panic!("Negative array access") | |
} | |
mask[n as usize] = mask1 != mask2; | |
n += 1; | |
x[u] += 1; | |
} | |
x[v] += 1; | |
} | |
//Increment x[d] | |
x[d] += 1; | |
//Generate mesh for mask using lexicographic ordering | |
n = 0; | |
for j in 0..dims[v] { | |
let mut i = 0; | |
while i < dims[u] { | |
if n < 0 { | |
panic!("Negative array access") | |
} | |
if mask[n as usize] { | |
//Compute width | |
let mut w = 1i32; | |
if ((n + w) as usize) as i32 != n + w { | |
panic!("Lost data in transformation!") | |
} | |
//Compute width | |
while i + w < dims[u] && mask[(n + w) as usize] { | |
w += 1; | |
} | |
//Compute height | |
let mut h = 1; | |
'outer: while j + h < dims[v] { | |
for k in 0..w { | |
if ((n + k + h * dims[u]) as usize) as i32 != n + k + h * dims[u] { | |
panic!("Lost data in transformation!") | |
} | |
if !mask[(n + k + h * dims[u]) as usize] { | |
break 'outer; | |
} | |
} | |
h += 1; | |
} | |
//Add quad | |
x[u] = i; | |
x[v] = j; | |
let mut du = [0, 0, 0]; | |
let mut dv = [0, 0, 0]; | |
du[u] = w; | |
dv[v] = h; | |
quads.push([ | |
[x[0], x[1], x[2]], | |
[x[0] + du[0], x[1] + du[1], x[2] + du[2]], | |
[ | |
x[0] + du[0] + dv[0], | |
x[1] + du[1] + dv[1], | |
x[2] + du[2] + dv[2], | |
], | |
[x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]], | |
]); | |
//Zero out mask | |
for l in 0..h { | |
for k in 0..w { | |
mask[(n + k + l * dims[u]) as usize] = false; | |
} | |
} | |
//Increment counters and continue | |
i += w; | |
n += w; | |
} else { | |
n += 1; | |
i += 1; | |
} | |
} | |
} | |
} | |
} | |
quads | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment