voxel-zone/app/src/voxels/layers/traits.rs

90 lines
3.2 KiB
Rust

use bevy::{
prelude::*,
render::{
mesh::{Indices, VertexAttributeValues},
render_resource::PrimitiveTopology,
},
};
use block_mesh::{
ilattice::prelude::Vec3A,
ndshape::{ConstShape, ConstShape3u32},
visible_block_faces, UnitQuadBuffer, Voxel, RIGHT_HANDED_Y_UP_CONFIG,
};
use common::space::three_dimensional::traits::{DefaultVoxel, DefaultVoxelKinds, VoxelContainer};
use crate::voxels::mesh::into_domain;
/// A renderable collection of voxels that have 3-dimensional coordinates, and can be displayed as a single mesh.
pub trait VoxelLayer<TVoxel>
where
TVoxel: Voxel + DefaultVoxel + Copy,
{
fn get_voxel_or_default_at_vec<'a>(&self, pos: Vec3A) -> TVoxel;
fn generate_simple_mesh(&self, meshes: &mut Assets<Mesh>) -> Handle<Mesh>;
}
impl<TVoxel, TContainer> VoxelLayer<TVoxel> for TContainer
where
TVoxel: Voxel + DefaultVoxel + Copy,
TContainer: VoxelContainer<TVoxel>,
{
fn get_voxel_or_default_at_vec<'a>(&self, position: Vec3A) -> TVoxel {
match self.get_voxel_at_pos(position.into()) {
Some(v) => v,
None => DefaultVoxel::get_default(DefaultVoxelKinds::None),
}
}
fn generate_simple_mesh(&self, meshes: &mut Assets<Mesh>) -> Handle<Mesh> {
type SampleShape = ConstShape3u32<34, 34, 34>;
let mut samples: [TVoxel; SampleShape::SIZE as usize] =
[DefaultVoxel::get_default(DefaultVoxelKinds::None); SampleShape::SIZE as usize];
for i in 0u32..(SampleShape::SIZE) {
let p = into_domain(32, SampleShape::delinearize(i));
samples[i as usize] = self.get_voxel_or_default_at_vec(p);
}
let faces = RIGHT_HANDED_Y_UP_CONFIG.faces;
let mut buffer = UnitQuadBuffer::new();
visible_block_faces(
&samples,
&SampleShape {},
[0; 3],
[33; 3],
&faces,
&mut buffer,
);
let num_indices = buffer.num_quads() * 6;
let num_vertices = buffer.num_quads() * 4;
let mut indices = Vec::with_capacity(num_indices);
let mut positions = Vec::with_capacity(num_vertices);
let mut normals = Vec::with_capacity(num_vertices);
for (group, face) in buffer.groups.into_iter().zip(faces.into_iter()) {
for quad in group.into_iter() {
indices.extend_from_slice(&face.quad_mesh_indices(positions.len() as u32));
positions.extend_from_slice(&face.quad_mesh_positions(&quad.into(), 1.0));
normals.extend_from_slice(&face.quad_mesh_normals());
}
}
let mut render_mesh = Mesh::new(PrimitiveTopology::TriangleList);
render_mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION,
VertexAttributeValues::Float32x3(positions),
);
render_mesh.insert_attribute(
Mesh::ATTRIBUTE_NORMAL,
VertexAttributeValues::Float32x3(normals),
);
render_mesh.insert_attribute(
Mesh::ATTRIBUTE_UV_0,
VertexAttributeValues::Float32x2(vec![[0.0; 2]; num_vertices]),
);
render_mesh.set_indices(Some(Indices::U32(indices.clone())));
meshes.add(render_mesh)
}
}