//! An example that showcases how to use the meshem function. #[allow(unused_imports)] use bevy::pbr::wireframe::{Wireframe, WireframeConfig, WireframePlugin}; use bevy::prelude::*; use bevy_meshem::prelude::*; /// Constants for us to use. const FACTOR: usize = 10; const SPEED: f32 = FACTOR as f32 * 2.0; const MESHING_ALGORITHM: MeshingAlgorithm = MeshingAlgorithm::Culling; fn main() { let mut app = App::new(); app.add_plugins(DefaultPlugins).add_plugins(WireframePlugin); app.insert_resource(BlockRegistry { block: generate_voxel_mesh( [1.0, 1.0, 1.0], [0, 0], [(Top, [0, 0]); 6], [0.5, 0.5, 0.5], 0.05, Some(0.8), 1.0, ), }) .insert_resource(AmbientLight { brightness: 1500.0, color: Color::WHITE, }); app.add_systems(Startup, setup).add_systems( Update, ( input_handler, toggle_wireframe, input_handler_rotation, regenerate_mesh, ), ); app.add_event::() .add_event::(); app.run(); } #[derive(Component)] struct Meshy { ma: MeshingAlgorithm, meta: MeshMD, } #[derive(Component)] struct MeshInfo; #[derive(Event, Default)] struct ToggleWireframe; #[derive(Event, Default)] struct RegenerateMesh; /// Setting up everything to showcase the mesh. fn setup( breg: Res, mut commands: Commands, mut materials: ResMut>, // wireframe_config: ResMut, mut meshes: ResMut>, ) { let grid = [1; FACTOR * FACTOR * FACTOR]; let dims: Dimensions = (FACTOR, FACTOR, FACTOR); let (culled_mesh, metadata) = mesh_grid( dims, // Automatically cull the bottom when generating the mesh &[Bottom], &grid, breg.into_inner(), MESHING_ALGORITHM, None, ) .unwrap(); let culled_mesh_handle: Handle = meshes.add(culled_mesh.clone()); commands.spawn(( PbrBundle { mesh: culled_mesh_handle, material: materials.add(StandardMaterial { base_color: Color::SALMON, alpha_mode: AlphaMode::Mask(0.5), ..default() }), ..default() }, Meshy { ma: MESHING_ALGORITHM, meta: metadata, }, )); // Transform for the camera and lighting, looking at (0,0,0) (the position of the mesh). let camera_and_light_transform = Transform::from_xyz( FACTOR as f32 * 1.7, FACTOR as f32 * 1.7, FACTOR as f32 * 1.7, ) .looking_at( Vec3::new( FACTOR as f32 * 0.5, FACTOR as f32 * 0.5, FACTOR as f32 * 0.5, ), Vec3::Y, ); // Camera in 3D space. commands.spawn(Camera3dBundle { transform: camera_and_light_transform, ..default() }); // Light up the scene. commands.spawn(PointLightBundle { point_light: PointLight { intensity: 5000.0, range: 500.0, ..default() }, transform: camera_and_light_transform, ..default() }); // for (att, _val) in culled_mesh.attributes() { // // dbg!(att); // if att == Mesh::ATTRIBUTE_POSITION.id {} // } commands.spawn( TextBundle::from_section( format!( "X/Y/Z: Rotate\nR: Reset orientation\nMove Camera: W/A/S/D/Left-Shift/Space\nToggle Wireframe: T\n"), TextStyle { font_size: 26.0, color: Color::LIME_GREEN, ..default() }, ) .with_style(Style { position_type: PositionType::Absolute, top: Val::Px(12.0), left: Val::Px(12.0), ..default() }), ); commands.spawn(( MeshInfo, TextBundle::from_section( format!("Press -C- To regenerate the mesh with a different Algorithm\nVertices Count: {}\nMeshing Algorithm: {:?}",culled_mesh.count_vertices(), MESHING_ALGORITHM,), TextStyle { font_size: 26.0, color: Color::LIME_GREEN, ..default() }, ) .with_style(Style { position_type: PositionType::Absolute, bottom: Val::Px(12.0), left: Val::Px(12.0), ..default() }), )); } #[derive(Resource)] struct BlockRegistry { block: Mesh, } /// The important part! Without implementing a [`VoxelRegistry`], you can't use the function. impl VoxelRegistry for BlockRegistry { /// The type of our Voxel, the example uses u16 for Simplicity but you may have a struct /// Block { Name: ..., etc ...}, and you'll define that as the type, but encoding the block /// data onto simple type like u16 or u64 is probably prefferable. type Voxel = u16; /// The get_mesh function, probably the most important function in the /// [`VoxelRegistry`], it is what allows us to quickly access the Mesh of each Voxel. fn get_mesh(&self, voxel: &Self::Voxel) -> VoxelMesh<&Mesh> { if *voxel == 0 { return VoxelMesh::Null; } VoxelMesh::NormalCube(&self.block) } /// Important function that tells our Algorithm if the Voxel is "full", for example, the Air /// in minecraft is not "full", but it is still on the chunk data, to singal there is nothing. fn is_covering(&self, voxel: &Self::Voxel, _side: prelude::Face) -> bool { return *voxel != 0; } /// The center of the Mesh, out mesh is defined in src/default_block.rs, just a constant. fn get_center(&self) -> [f32; 3] { return [0.5, 0.5, 0.5]; } /// The dimensions of the Mesh, out mesh is defined in src/default_block.rs, just a constant. fn get_voxel_dimensions(&self) -> [f32; 3] { return [1.0, 1.0, 1.0]; } /// The attributes we want to take from out voxels, note that using a lot of different /// attributes will likely lead to performance problems and unpredictible behaviour. /// We chose these 3 because they are very common, the algorithm does preserve UV data. fn all_attributes(&self) -> Vec { return vec![ Mesh::ATTRIBUTE_POSITION, Mesh::ATTRIBUTE_UV_0, Mesh::ATTRIBUTE_NORMAL, ]; } } /// Simple system to handle inputs for the showcase. fn input_handler( keyboard_input: Res>, mut query: Query<&mut Transform, With>, time: Res