90 lines
3.2 KiB
Rust
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)
|
|
}
|
|
}
|