//! Shows how to orbit camera around a static scene using pitch, yaw, and roll. //! //! See also: `first_person_view_model` example, which does something similar but as a first-person //! camera view. use std::{f32::consts::FRAC_PI_2, ops::Range}; use bevy::{input::mouse::AccumulatedMouseMotion, prelude::*}; #[derive(Debug, Resource)] struct CameraSettings { pub orbit_distance: f32, pub pitch_speed: f32, // Clamp pitch to this range pub pitch_range: Range, pub roll_speed: f32, pub yaw_speed: f32, } impl Default for CameraSettings { fn default() -> Self { // Limiting pitch stops some unexpected rotation past 90° up or down. let pitch_limit = FRAC_PI_2 - 0.01; Self { // These values are completely arbitrary, chosen because they seem to produce // "sensible" results for this example. Adjust as required. orbit_distance: 20.0, pitch_speed: 0.003, pitch_range: -pitch_limit..pitch_limit, roll_speed: 1.0, yaw_speed: 0.004, } } } fn main() { App::new() .add_plugins(DefaultPlugins) .init_resource::() .add_systems(Startup, (setup, instructions)) .add_systems(Update, orbit) .run(); } /// Set up a simple 3D scene fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { commands.spawn(( Name::new("Camera"), Camera3d::default(), Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y), )); commands.spawn(( Name::new("Plane"), Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))), MeshMaterial3d(materials.add(StandardMaterial { base_color: Color::srgb(0.3, 0.5, 0.3), // Turning off culling keeps the plane visible when viewed from beneath. cull_mode: None, ..default() })), )); commands.spawn(( Name::new("Cube"), Mesh3d(meshes.add(Cuboid::default())), MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))), Transform::from_xyz(1.5, 0.51, 1.5), )); commands.spawn(( Name::new("Light"), PointLight::default(), Transform::from_xyz(3.0, 8.0, 5.0), )); } fn instructions(mut commands: Commands) { commands.spawn(( Name::new("Instructions"), Text::new( "Mouse up or down: pitch\n\ Mouse left or right: yaw\n\ Mouse buttons: roll", ), Node { position_type: PositionType::Absolute, top: Val::Px(12.), left: Val::Px(12.), ..default() }, )); } fn orbit( mut camera: Single<&mut Transform, With>, camera_settings: Res, mouse_buttons: Res>, mouse_motion: Res, time: Res