use bevy::{prelude::*, render::{mesh::{Indices, PrimitiveTopology}, render_asset::RenderAssetUsages}};
use crate::air::Air;
use super::{voxel_mesher::VoxelMesher, Transparent};
pub const SIDE_INDICES: [u32; 6] = [0, 1, 2, 3, 2, 1];
pub const SIDE_UV: [Vec2; 4] = [
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 1.0, y: 0.0 },
];
pub const CUBE_NORMALS: [Vec3; 6] = [
Vec3 { x: -1.0, y: 0.0, z: 0.0 },
Vec3 { x: 1.0, y: 0.0, z: 0.0 },
Vec3 { x: 0.0, y: -1.0, z: 0.0 },
Vec3 { x: 0.0, y: 1.0, z: 0.0 },
Vec3 { x: 0.0, y: 0.0, z: -1.0 },
Vec3 { x: 0.0, y: 0.0, z: 1.0 },
];
pub const CUBE_VERTECIES: [[Vec3; 4]; 6] = [
[
Vec3 { x: 0.0, y: 0.0, z: 0.0 }, Vec3 { x: 0.0, y: 0.0, z: 1.0 },
Vec3 { x: 0.0, y: 1.0, z: 0.0 }, Vec3 { x: 0.0, y: 1.0, z: 1.0 },
],
[
Vec3 { x: 1.0, y: 0.0, z: 0.0 }, Vec3 { x: 1.0, y: 1.0, z: 0.0 },
Vec3 { x: 1.0, y: 0.0, z: 1.0 }, Vec3 { x: 1.0, y: 1.0, z: 1.0 },
],
[
Vec3 { x: 0.0, y: 0.0, z: 0.0 }, Vec3 { x: 1.0, y: 0.0, z: 0.0 },
Vec3 { x: 0.0, y: 0.0, z: 1.0 }, Vec3 { x: 1.0, y: 0.0, z: 1.0 },
],
[
Vec3 { x: 0.0, y: 1.0, z: 0.0 }, Vec3 { x: 0.0, y: 1.0, z: 1.0 },
Vec3 { x: 1.0, y: 1.0, z: 0.0 }, Vec3 { x: 1.0, y: 1.0, z: 1.0 },
],
[
Vec3 { x: 0.0, y: 0.0, z: 0.0 }, Vec3 { x: 0.0, y: 1.0, z: 0.0 },
Vec3 { x: 1.0, y: 0.0, z: 0.0 }, Vec3 { x: 1.0, y: 1.0, z: 0.0 },
],
[
Vec3 { x: 0.0, y: 0.0, z: 1.0 }, Vec3 { x: 1.0, y: 0.0, z: 1.0 },
Vec3 { x: 0.0, y: 1.0, z: 1.0 }, Vec3 { x: 1.0, y: 1.0, z: 1.0 },
],
];
pub fn generate_side_mesh(side_n: usize) -> Mesh {
Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default())
.with_inserted_indices(Indices::U32(SIDE_INDICES.to_vec()))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, CUBE_VERTECIES[side_n].to_vec())
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![CUBE_NORMALS[side_n]; 4])
}
pub struct CubeMesher {
pub is_air: bool
}
impl Default for CubeMesher {
fn default() -> Self {
Self { is_air: true }
}
}
impl Air for CubeMesher {
fn is_air(&self) -> bool {
self.is_air
}
}
impl Transparent for CubeMesher {
fn is_transparent(&self) -> bool {
self.is_air
}
}
impl VoxelMesher for CubeMesher {
fn generate(&self, visible_sides: [bool; 6]) -> Mesh {
let mut result = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default())
.with_inserted_indices(Indices::U32(vec![]))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vec![Vec3::ZERO; 0])
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vec![Vec3::ZERO; 0])
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![Vec2::ZERO; 0]);
for (side_n, is_visible) in visible_sides.iter().enumerate() {
if *is_visible {
let side_mesh = generate_side_mesh(side_n)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, SIDE_UV.to_vec());
result.merge(side_mesh);
}
}
result
}
}