Skip to main content

three_d/renderer/control/
orbit_control.rs

1use super::*;
2
3///
4/// A control that makes the camera orbit around a target.
5///
6#[derive(Clone, Copy, Debug)]
7pub struct OrbitControl {
8    /// The target point to orbit around.
9    pub target: Vec3,
10    /// The minimum distance to the target point.
11    pub min_distance: f32,
12    /// The maximum distance to the target point.
13    pub max_distance: f32,
14}
15
16impl OrbitControl {
17    /// Creates a new orbit control with the given target and minimum and maximum distance to the target.
18    pub fn new(target: Vec3, min_distance: f32, max_distance: f32) -> Self {
19        Self {
20            target,
21            min_distance,
22            max_distance,
23        }
24    }
25
26    /// Handles the events. Must be called each frame.
27    pub fn handle_events(
28        &mut self,
29        camera: &mut three_d_asset::Camera,
30        events: &mut [Event],
31    ) -> bool {
32        let mut change = false;
33        for event in events.iter_mut() {
34            match event {
35                Event::MouseMotion {
36                    delta,
37                    button,
38                    handled,
39                    ..
40                } if !*handled && Some(MouseButton::Left) == *button => {
41                    let speed = 0.01;
42                    camera.rotate_around_with_fixed_up(
43                        self.target,
44                        speed * delta.0,
45                        speed * delta.1,
46                    );
47                    *handled = true;
48                    change = true;
49                }
50                Event::MouseWheel { delta, handled, .. } if !*handled => {
51                    let distance = self.target.distance(camera.position());
52                    let zoom_amount = distance * (1.0 - (-delta.1 * 0.01).exp());
53                    camera.zoom_towards(
54                        self.target,
55                        zoom_amount,
56                        self.min_distance,
57                        self.max_distance,
58                    );
59                    *handled = true;
60                    change = true;
61                }
62                Event::PinchGesture { delta, handled, .. } if !*handled => {
63                    let speed = self.target.distance(camera.position()) + 0.1;
64                    camera.zoom_towards(
65                        self.target,
66                        speed * *delta,
67                        self.min_distance,
68                        self.max_distance,
69                    );
70                    *handled = true;
71                    change = true;
72                }
73                _ => {}
74            }
75        }
76        change
77    }
78}