Skip to content

Instantly share code, notes, and snippets.

@wareya
Last active November 28, 2022 07:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wareya/175ab2992dbf0652f2e1f4b1bee9b10c to your computer and use it in GitHub Desktop.
Save wareya/175ab2992dbf0652f2e1f4b1bee9b10c to your computer and use it in GitHub Desktop.
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