exponential_map/
exponential_map.rs

1//! A simple 3D scene with light shining over a cube sitting on a plane and a trackball camera
2//! waiting for your input to orbit around.
3//!
4//! This is an alternative trackball technique using exponential map and parallel transport to
5//! preserve distances and angles for inducing coherent and intuitive trackball rotations. For
6//! instance, displacements on straight radial lines through the screen's center are carried to arcs
7//! of the same length on great circles of the trackball (e.g., dragging the mouse along an eights
8//! of the trackball's circumference rolls the camera by 360/8=45 degrees, dragging the mouse from
9//! the screen's center to its further edge *linearly* rotates the camera by 1 [radian], where the
10//! trackball's diameter is the maximum of the screen's width and height). This is in contrast to
11//! state-of-the-art techniques using orthogonal projection which distorts radial distances further
12//! away from the screen's center (e.g., the rotation accelerates towards the edge).
13//!
14//! [radian]: https://en.wikipedia.org/wiki/Radian
15
16use bevy::prelude::*;
17use bevy_trackball::prelude::*;
18
19fn main() {
20	App::new()
21		.add_plugins(DefaultPlugins.set(WindowPlugin {
22			primary_window: Some(Window {
23				canvas: Some("#bevy".to_owned()),
24				..default()
25			}),
26			..default()
27		}))
28		.add_plugins(TrackballPlugin)
29		.add_systems(Startup, setup)
30		.run();
31}
32
33/// set up a simple 3D scene
34fn setup(
35	mut commands: Commands,
36	mut meshes: ResMut<Assets<Mesh>>,
37	mut materials: ResMut<Assets<StandardMaterial>>,
38) {
39	// circular base
40	commands.spawn((
41		Mesh3d(meshes.add(Circle::new(4.0))),
42		MeshMaterial3d(materials.add(Color::WHITE)),
43		Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
44	));
45	// cube
46	commands.spawn((
47		Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
48		MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
49		Transform::from_xyz(0.0, 0.5, 0.0),
50	));
51	// light
52	commands.spawn((
53		PointLight {
54			shadows_enabled: true,
55			..default()
56		},
57		Transform::from_xyz(4.0, 8.0, 4.0),
58	));
59	// camera
60	commands.spawn((
61		TrackballController::default(),
62		TrackballCamera::look_at(Vec3::Y * 0.5, Vec3::new(-2.5, 4.5, 9.0), Vec3::Y),
63		Camera3d::default(),
64	));
65}