Skip to main content

three_d/renderer/control/
free_orbit_control.rs

1use super::*;
2
3///
4/// A control that makes the camera orbit around a target, with no fixed up direction.
5///
6#[derive(Clone, Copy, Debug)]
7pub struct FreeOrbitControl {
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 FreeOrbitControl {
17    /// Creates a new free 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 * self.target.distance(camera.position()) + 0.001;
42                    camera.rotate_around(self.target, speed * delta.0, speed * delta.1);
43                    *handled = true;
44                    change = true;
45                }
46                Event::MouseWheel { delta, handled, .. } if !*handled => {
47                    let distance = self.target.distance(camera.position());
48                    let zoom_amount = distance * (1.0 - (-delta.1 * 0.01).exp());
49                    camera.zoom_towards(
50                        self.target,
51                        zoom_amount,
52                        self.min_distance,
53                        self.max_distance,
54                    );
55                    *handled = true;
56                    change = true;
57                }
58                Event::PinchGesture { delta, handled, .. } if !*handled => {
59                    let speed = self.target.distance(camera.position()) + 0.1;
60                    camera.zoom_towards(
61                        self.target,
62                        speed * *delta,
63                        self.min_distance,
64                        self.max_distance,
65                    );
66                    *handled = true;
67                    change = true;
68                }
69                _ => {}
70            }
71        }
72        change
73    }
74}