Last active
November 28, 2022 07:26
-
-
Save wareya/175ab2992dbf0652f2e1f4b1bee9b10c to your computer and use it in GitHub Desktop.
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
use glm::*; | |
use std::collections::HashMap; | |
/* | |
class TileType: | |
var coord_top : Vector2 = Vector2(1, 4) | |
var coord_side : Vector2 = Vector2(1, 4) | |
var coord_bottom : Vector2 = Vector2(1, 4) | |
var is_transparent : bool = false | |
func _init(top_x, top_y, side_x, side_y, bottom_x, bottom_y, transparent : bool): | |
coord_top = Vector2(top_x, top_y) | |
coord_side = Vector2(side_x, side_y) | |
coord_bottom = Vector2(bottom_x, bottom_y) | |
is_transparent = transparent | |
var tile_type_info = { | |
0 : TileType.new(15, 7, 15, 7, 15, 7, true), | |
65 : TileType.new( 1, 4, 1, 4, 1, 4, false), | |
66 : TileType.new( 7, 4, 0, 4, 1, 4, false), | |
10 : TileType.new(15, 2, 8, 7, 15, 2, true), | |
20 : TileType.new( 9, 5, 9, 5, 9, 5, true), | |
} | |
*/ | |
#[derive(PartialEq, Clone, Copy)] | |
struct Info | |
{ | |
top : Vec2, | |
bottom : Vec2, | |
side : Vec2, | |
transparent : bool, | |
air : bool, | |
} | |
impl Info | |
{ | |
fn new(top : Vec2, bottom : Vec2, side : Vec2, transparent : bool, air : bool) -> Info | |
{ | |
Info{top, bottom, side, transparent, air} | |
} | |
} | |
impl Default for Info | |
{ | |
fn default() -> Info | |
{ | |
Info{top : vec2(15.0, 7.0), bottom : vec2(15.0, 7.0), side : vec2(15.0, 7.0), transparent : true, air : true} | |
} | |
} | |
struct Chunk | |
{ | |
size : i32, | |
size2 : i32, | |
data : [u8; 18*18*18], | |
info : [Info; 18*18*18], | |
//infos_transparent : HashMap<u8, bool>, | |
//infos_top : HashMap<u8, Vec2>, | |
//infos_bottom : HashMap<u8, Vec2>, | |
//infos_side : HashMap<u8, Vec2>, | |
} | |
impl Chunk | |
{ | |
fn load(fname : &String) -> Chunk | |
{ | |
let air = HashMap::from([ | |
( 0, true), | |
(65, false), | |
(66, false), | |
(10, false), | |
(20, false), | |
]); | |
let tparent = HashMap::from([ | |
( 0, true), | |
(65, false), | |
(66, false), | |
(10, true), | |
(20, true), | |
]); | |
let top = HashMap::from([ | |
( 0, vec2(15.0, 7.0)), | |
(65, vec2( 1.0, 4.0)), | |
(66, vec2( 7.0, 4.0)), | |
(10, vec2(15.0, 2.0)), | |
(20, vec2( 9.0, 5.0)), | |
]); | |
let bottom = HashMap::from([ | |
( 0, vec2(15.0, 7.0)), | |
(65, vec2( 1.0, 4.0)), | |
(66, vec2( 0.0, 4.0)), | |
(10, vec2( 8.0, 7.0)), | |
(20, vec2( 9.0, 5.0)), | |
]); | |
let side = HashMap::from([ | |
( 0, vec2(15.0, 7.0)), | |
(65, vec2( 1.0, 4.0)), | |
(66, vec2( 1.0, 4.0)), | |
(10, vec2(15.0, 2.0)), | |
(20, vec2( 9.0, 5.0)), | |
]); | |
let data_vec : Vec<u8> = std::fs::read(fname).unwrap(); | |
let mut data_raw = [0u8; 4096]; | |
for (i, d) in data_vec.iter().enumerate() | |
{ | |
data_raw[i] = *d; | |
} | |
let mut data = [0u8; 18*18*18]; | |
let mut info = [Info::default(); 18*18*18]; | |
for z in 0..16 | |
{ | |
for y in 0..16 | |
{ | |
for x in 0..16 | |
{ | |
let index = (x + (z*16) + (y*16*16)) as usize; | |
let index2 = (x+1 + ((z+1)*18) + ((y+1)*18*18)) as usize; | |
let t = &data_raw[index]; | |
data[index2] = *t; | |
info[index2] = Info::new(top[t], bottom[t], side[t], tparent[t], air[t]); | |
} | |
} | |
} | |
let size = 16; | |
let size2 = 16*16; | |
Chunk{size, size2, data, info} | |
} | |
//fn in_bounds(&self, x : i32, y : i32, z : i32) -> bool | |
//{ | |
// x < self.size && y < self.size && z < self.size && x >= 0 && y >= 0 && z >= 0 | |
//} | |
fn get_tile_priv(&self, x : i32, y : i32, z : i32) -> u8 | |
{ | |
//if !self.in_bounds(x, y, z) | |
//{ | |
// return 0; | |
//} | |
//let index = (x + (z*self.size) + (y*self.size2)) as usize; | |
let index2 = (x+1 + ((z+1)*18) + ((y+1)*18*18)) as usize; | |
unsafe | |
{ | |
self.data[index2 as usize] | |
} | |
} | |
fn get_info_priv(&self, x : i32, y : i32, z : i32) -> Info | |
{ | |
//if !self.in_bounds(x, y, z) | |
//{ | |
// return 0; | |
//} | |
//let index = (x + (z*self.size) + (y*self.size2)) as usize; | |
let index2 = (x+1 + ((z+1)*18) + ((y+1)*18*18)) as usize; | |
unsafe | |
{ | |
self.info[index2 as usize] | |
} | |
} | |
fn mesh(&self) | |
{ | |
let size = self.size; | |
let divide_res = 1; | |
let mut verts = vec!(); | |
let mut normals = vec!(); | |
let mut uv2s = vec!(); | |
macro_rules! for_dirs( | |
($f:expr) => | |
{ | |
for dir in [ | |
vec3( 0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), | |
vec3(-1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), | |
vec3( 0.0, 0.0, -1.0), vec3(0.0, 0.0, 1.0) | |
] | |
{ | |
let basis; | |
if dir.y == 1.0 | |
{ | |
basis = mat3( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,-1.0, 0.0); | |
} | |
else if dir.y == -1.0 | |
{ | |
basis = mat3( 1.0, 0.0, 0.0, 0.0, 0.0,-1.0, 0.0, 1.0, 0.0); | |
} | |
else if dir.x == -1.0 | |
{ | |
basis = mat3( 0.0, 0.0,-1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0); | |
} | |
else if dir.x == 1.0 | |
{ | |
basis = mat3( 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0); | |
} | |
else if dir.z == -1.0 | |
{ | |
basis = mat3( 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); | |
} | |
else | |
{ | |
basis = mat3(-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,-1.0); | |
} | |
let c1 = basis.mul_v(&vec3(-0.5, 0.5, -0.5)); | |
let c2 = basis.mul_v(&vec3(-0.5, -0.5, -0.5)); | |
let c3 = basis.mul_v(&vec3( 0.5, 0.5, -0.5)); | |
let c4 = basis.mul_v(&vec3( 0.5, -0.5, -0.5)); | |
let normal = basis.mul_v(&vec3(0.0, 0.0, -1.0)); | |
$f(dir, basis, c1, c2, c3, c4, normal); | |
} | |
} | |
); | |
for_dirs!(&mut |dir : Vec3, mut basis : Mat3, mut _c1 : Vec3, mut _c2 : Vec3, mut _c3 : Vec3, mut _c4 : Vec3, normal : Vec3| | |
{ | |
let side; | |
if dir.z != 0.0 | |
{ | |
side = 0; | |
} | |
else if dir.x != 0.0 | |
{ | |
side = 1; | |
} | |
else | |
{ | |
side = 2; | |
} | |
let mut rightwards = basis.mul_v(&vec3(1.0, 0.0, 0.0)); | |
let mut leftwards = vec3(0.0, 0.0, 0.0); | |
let forwards = basis.mul_v(&vec3(0.0, 0.0, -1.0)); | |
let forwards_x = (forwards.x as i32) * divide_res; | |
let forwards_y = (forwards.y as i32) * divide_res; | |
let forwards_z = (forwards.z as i32) * divide_res; | |
for n in basis.as_array_mut() | |
{ | |
*n = n.abs(); | |
} | |
if basis.mul_v(&vec3(1.0, 0.0, 0.0)) != rightwards | |
{ | |
leftwards = -rightwards; | |
rightwards = vec3(0.0, 0.0, 0.0); | |
} | |
let vh = vec3(0.5, 0.5, 0.5); | |
_c1 = (_c1 + vh) * divide_res as f32 - vh; | |
_c2 = (_c2 + vh) * divide_res as f32 - vh; | |
_c3 = (_c3 + vh) * divide_res as f32 - vh; | |
_c4 = (_c4 + vh) * divide_res as f32 - vh; | |
// slightly faster than having two sets of separate x/y/z variables | |
let mut c = vec!(0, 0, 0); | |
let c_x = if side == 1 { 2 } else { 0 }; | |
let c_y = if side == 2 { 2 } else { 1 }; | |
let c_z = if side == 2 { 1 } else if side == 1 { 0 } else { 2 }; | |
let mut fwd_c = vec!(0, 0, 0); | |
let mut fwd_base = vec!(0, 0, 0); | |
fwd_base[c_x] = forwards_x; | |
fwd_base[c_y] = forwards_y; | |
fwd_base[c_z] = forwards_z; | |
c[1] = 0; | |
fwd_c[1] = fwd_base[1]; | |
while c[1] < size+divide_res | |
{ | |
c[2] = 0; | |
fwd_c[2] = fwd_base[2]; | |
while c[2] < size+divide_res | |
{ | |
c[0] = 0; | |
fwd_c[0] = fwd_base[0]; | |
while c[0] < size+divide_res | |
{ | |
let mut tile = self.get_info_priv(c[c_x], c[c_y], c[c_z]); | |
if tile.air | |
{ | |
c[0] += divide_res; | |
fwd_c[0] += divide_res; | |
continue; | |
} | |
if !self.get_info_priv(fwd_c[c_x], fwd_c[c_y], fwd_c[c_z]).transparent | |
{ | |
c[0] += divide_res; | |
fwd_c[0] += divide_res; | |
continue; | |
} | |
let start = c[0]; | |
let start_tile = tile; | |
while tile == start_tile && c[0] < size+divide_res | |
{ | |
c[0] += divide_res; | |
fwd_c[0] += divide_res; | |
tile = self.get_info_priv(c[c_x], c[c_y], c[c_z]); | |
if !self.get_info_priv(fwd_c[c_x], fwd_c[c_y], fwd_c[c_z]).transparent | |
{ | |
break; | |
} | |
} | |
c[0] -= divide_res; | |
fwd_c[0] -= divide_res; | |
tile = start_tile; | |
// check tile type | |
let mut offset; | |
if dir.y == 1.0 | |
{ | |
offset = tile.top; | |
// if top and non-base resolution, check above and use above if present | |
if divide_res != 1 | |
{ | |
let tile2 = self.get_info_priv(c[c_x], c[c_y] + divide_res-1, c[c_z]); | |
if !tile2.air | |
{ | |
offset = tile2.top; | |
} | |
} | |
} | |
else if dir.y == -1.0 | |
{ | |
offset = tile.bottom; | |
} | |
else | |
{ | |
offset = tile.side; | |
} | |
let coord = vec3(c[c_x] as f32, c[c_y] as f32, c[c_z] as f32); | |
let c1 = _c1 + coord + rightwards * (start - c[0]) as f32; | |
let c2 = _c2 + coord + rightwards * (start - c[0]) as f32; | |
let c3 = _c3 + coord + leftwards * (start - c[0]) as f32; | |
let c4 = _c4 + coord + leftwards * (start - c[0]) as f32; | |
verts.push(c1); | |
verts.push(c2); | |
verts.push(c3); | |
verts.push(c3); | |
verts.push(c2); | |
verts.push(c4); | |
uv2s.push(offset); | |
uv2s.push(offset); | |
uv2s.push(offset); | |
uv2s.push(offset); | |
uv2s.push(offset); | |
uv2s.push(offset); | |
normals.push(normal); | |
normals.push(normal); | |
normals.push(normal); | |
normals.push(normal); | |
normals.push(normal); | |
normals.push(normal); | |
c[0] += divide_res; | |
fwd_c[0] += divide_res; | |
} | |
c[2] += divide_res; | |
fwd_c[2] += divide_res; | |
} | |
c[1] += divide_res; | |
fwd_c[1] += divide_res; | |
} | |
}); | |
} | |
} | |
fn main() | |
{ | |
let paths = std::fs::read_dir("./chunkdata").unwrap(); | |
let mut time = 0.0; | |
for path in paths | |
{ | |
let fname = path.unwrap().path().display().to_string(); | |
let chunk = Chunk::load(&fname); | |
let start = std::time::Instant::now(); | |
chunk.mesh(); | |
let elapsed = start.elapsed().as_micros(); | |
time += elapsed as f32/1_000_000.0 | |
} | |
println!("time spent: {}", time); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment