three_d/renderer/control/
free_orbit_control.rs

1use crate::renderer::*;
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(&mut self, camera: &mut Camera, events: &mut [Event]) -> bool {
28        let mut change = false;
29        for event in events.iter_mut() {
30            match event {
31                Event::MouseMotion {
32                    delta,
33                    button,
34                    handled,
35                    ..
36                } => {
37                    if !*handled {
38                        if Some(MouseButton::Left) == *button {
39                            let speed = 0.01 * self.target.distance(camera.position()) + 0.001;
40                            camera.rotate_around(self.target, speed * delta.0, speed * delta.1);
41                            *handled = true;
42                            change = true;
43                        }
44                    }
45                }
46                Event::MouseWheel { delta, handled, .. } => {
47                    if !*handled {
48                        let speed = 0.01 * self.target.distance(camera.position()) + 0.001;
49                        camera.zoom_towards(
50                            self.target,
51                            speed * delta.1,
52                            self.min_distance,
53                            self.max_distance,
54                        );
55                        *handled = true;
56                        change = true;
57                    }
58                }
59                Event::PinchGesture { delta, handled, .. } => {
60                    if !*handled {
61                        let speed = self.target.distance(camera.position()) + 0.1;
62                        camera.zoom_towards(
63                            self.target,
64                            speed * *delta,
65                            self.min_distance,
66                            self.max_distance,
67                        );
68                        *handled = true;
69                        change = true;
70                    }
71                }
72                _ => {}
73            }
74        }
75        change
76    }
77}