Skip to content

Commit

Permalink
Scale camera zoom based on distance to target (#40)
Browse files Browse the repository at this point in the history
* Scale camera zoom based on distance to target

* Fix screen2ray scaling with zoom

* Fix zoom_towards when point is not target

* Add zoom function

* Safety check

---------

Co-authored-by: Asger Nyman Christiansen <[email protected]>
  • Loading branch information
thatcomputerguy0101 and asny authored Nov 13, 2024
1 parent 7473c05 commit 2aa308f
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ impl Camera {
Point3::from_vec(self.target),
self.up,
);
self.view[3][3] *= position.distance(target);
self.update_screen2ray();
self.update_frustrum();
}
Expand Down Expand Up @@ -557,6 +558,7 @@ impl Camera {

fn update_screen2ray(&mut self) {
let mut v = self.view;
v /= v[3][3];
if let ProjectionType::Perspective { .. } = self.projection_type {
v[3] = vec4(0.0, 0.0, 0.0, 1.0);
}
Expand Down Expand Up @@ -676,8 +678,17 @@ impl Camera {
}
}

///
/// Moves the camera towards the camera target by the amount delta while keeping the given minimum and maximum distance to the target.
///
pub fn zoom(&mut self, delta: f32, minimum_distance: f32, maximum_distance: f32) {
let target = self.target;
self.zoom_towards(&target, delta, minimum_distance, maximum_distance);
}

///
/// Moves the camera towards the given point by the amount delta while keeping the given minimum and maximum distance to the point.
/// Note that the camera target is also updated so that the view direction is the same.
///
pub fn zoom_towards(
&mut self,
Expand All @@ -694,17 +705,15 @@ impl Camera {

let position = *self.position();
let distance = point.distance(position);
let direction = (point - position).normalize();
let target = *self.target();
let up = self.up;
let new_distance = (distance - delta).clamp(minimum_distance, maximum_distance);
let new_position = point - direction * new_distance;
self.set_view(new_position, new_position + (target - position), up);
if let ProjectionType::Orthographic { height } = self.projection_type() {
let h = new_distance * height / distance;
let z_near = self.z_near();
let z_far = self.z_far();
self.set_orthographic_projection(h, z_near, z_far);
if distance > f32::EPSILON {
let delta_clamped =
distance - (distance - delta).clamp(minimum_distance, maximum_distance);
let v = (point - position) * delta_clamped / distance;
self.set_view(
self.position + v,
self.target + v - v.project_on(self.view_direction()),
self.up,
);
}
}
}

0 comments on commit 2aa308f

Please sign in to comment.