diff --git a/Cargo.toml b/Cargo.toml index 14463f419b..927119ccaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -447,6 +447,16 @@ description = "A scene showcasing the built-in 3D shapes" category = "3D Rendering" wasm = true +[[example]] +name = "generate_custom_mesh" +path = "examples/3d/generate_custom_mesh.rs" + +[package.metadata.example.generate_custom_mesh] +name = "Generate Custom Mesh" +description = "Simple showcase of how to generate a custom mesh with a custom texture" +category = "3D Rendering" +wasm = true + [[example]] name = "anti_aliasing" path = "examples/3d/anti_aliasing.rs" diff --git a/examples/3d/generate_custom_mesh.rs b/examples/3d/generate_custom_mesh.rs new file mode 100644 index 0000000000..a4aa025028 --- /dev/null +++ b/examples/3d/generate_custom_mesh.rs @@ -0,0 +1,268 @@ +// ! This example demonstrates how to create a custom mesh, +// ! assign a custom UV mapping for a custom texture, +// ! and how to change the UV mapping at run-time. +use bevy::prelude::*; +use bevy::render::mesh::Indices; +use bevy::render::mesh::VertexAttributeValues; +use bevy::render::render_resource::PrimitiveTopology; + +// Define a "marker" component to mark the custom mesh. Marker components are often used in Bevy for +// filtering entities in queries with With, they're usually not queried directly since they don't contain information within them. +#[derive(Component)] +struct CustomUV; + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_systems(Startup, setup) + .add_systems(Update, input_handler) + .run(); +} + +fn setup( + mut commands: Commands, + asset_server: ResMut, + mut materials: ResMut>, + mut meshes: ResMut>, +) { + // Import the custom texture. + let custom_texture_handle: Handle = asset_server.load("textures/array_texture.png"); + // Create and save a handle to the mesh. + let cube_mesh_handle: Handle = meshes.add(create_cube_mesh()); + + // Render the mesh with the custom texture using a PbrBundle, add the marker. + commands.spawn(( + PbrBundle { + mesh: cube_mesh_handle, + material: materials.add(StandardMaterial { + base_color_texture: Some(custom_texture_handle), + ..default() + }), + ..default() + }, + CustomUV, + )); + + // Transform for the camera and lighting, looking at (0,0,0) (the position of the mesh). + let camera_and_light_transform = + Transform::from_xyz(1.8, 1.8, 1.8).looking_at(Vec3::ZERO, 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: 1000.0, + range: 100.0, + ..default() + }, + transform: camera_and_light_transform, + ..default() + }); + + // Text to describe the controls. + commands.spawn( + TextBundle::from_section( + "Controls:\nSpace: Change UVs\nX/Y/Z: Rotate\nR: Reset orientation", + TextStyle { + font_size: 20.0, + ..default() + }, + ) + .with_style(Style { + position_type: PositionType::Absolute, + top: Val::Px(12.0), + left: Val::Px(12.0), + ..default() + }), + ); +} + +// System to receive input from the user, +// check out examples/input/ for more examples about user input. +fn input_handler( + keyboard_input: Res>, + mesh_query: Query<&Handle, With>, + mut meshes: ResMut>, + mut query: Query<&mut Transform, With>, + time: Res