Simplify API of Camera

This commit is contained in:
Hanno Braun 2025-03-28 19:14:28 +01:00
parent 7993d25780
commit 938808966c
2 changed files with 44 additions and 51 deletions

View File

@ -34,13 +34,54 @@ impl Camera {
const INITIAL_FIELD_OF_VIEW_IN_X: f64 = FRAC_PI_2; // 90 degrees
/// Returns a new camera aligned for viewing a bounding box
pub fn new() -> Self {
pub fn new(aabb: &Aabb<3>) -> Self {
let initial_distance = {
// Let's make sure we choose a distance, so that the model fills
// most of the screen.
//
// To do that, first compute the model's highest point, as well
// as the furthest point from the origin, in x and y.
let highest_point = aabb.max.z;
let furthest_point =
[aabb.min.x.abs(), aabb.max.x, aabb.min.y.abs(), aabb.max.y]
.into_iter()
.reduce(Scalar::max)
// `reduce` can only return `None`, if there are no items in
// the iterator. And since we're creating an array full of
// items above, we know this can't panic.
.expect("Array should have contained items");
// The actual furthest point is not far enough. We don't want
// the model to fill the whole screen.
let furthest_point = furthest_point * 2.;
// Having computed those points, figuring out how far the camera
// needs to be from the model is just a bit of trigonometry.
let distance_from_model =
furthest_point / (Self::INITIAL_FIELD_OF_VIEW_IN_X / 2.).atan();
// And finally, the distance from the origin is trivial now.
highest_point + distance_from_model
};
let initial_offset = {
let mut offset = aabb.center();
offset.z = Scalar::ZERO;
-offset
};
let translation = Transform::translation([
initial_offset.x,
initial_offset.y,
-initial_distance,
]);
Self {
near_plane: Self::DEFAULT_NEAR_PLANE,
far_plane: Self::DEFAULT_FAR_PLANE,
rotation: Transform::identity(),
translation: Transform::identity(),
translation,
}
}
@ -129,52 +170,6 @@ impl Camera {
transform
}
/// Initialize the planes
///
/// Call this, if a shape is available for the first time.
pub fn init_planes(&mut self, aabb: &Aabb<3>) {
let initial_distance = {
// Let's make sure we choose a distance, so that the model fills
// most of the screen.
//
// To do that, first compute the model's highest point, as well
// as the furthest point from the origin, in x and y.
let highest_point = aabb.max.z;
let furthest_point =
[aabb.min.x.abs(), aabb.max.x, aabb.min.y.abs(), aabb.max.y]
.into_iter()
.reduce(Scalar::max)
// `reduce` can only return `None`, if there are no items in
// the iterator. And since we're creating an array full of
// items above, we know this can't panic.
.expect("Array should have contained items");
// The actual furthest point is not far enough. We don't want
// the model to fill the whole screen.
let furthest_point = furthest_point * 2.;
// Having computed those points, figuring out how far the camera
// needs to be from the model is just a bit of trigonometry.
let distance_from_model =
furthest_point / (Self::INITIAL_FIELD_OF_VIEW_IN_X / 2.).atan();
// And finally, the distance from the origin is trivial now.
highest_point + distance_from_model
};
let initial_offset = {
let mut offset = aabb.center();
offset.z = Scalar::ZERO;
-offset
};
self.translation = Transform::translation([
initial_offset.x,
initial_offset.y,
-initial_distance,
]);
}
/// Update the max and minimum rendering distance for this camera.
pub fn update_planes(&mut self, aabb: &Aabb<3>) {
let view_transform = self.camera_to_model();

View File

@ -47,9 +47,7 @@ impl Window {
let renderer =
Renderer::new(window.clone(), Vertices::from_tri_mesh(&tri_mesh))
.await?;
let mut camera = Camera::new();
camera.init_planes(&aabb);
let camera = Camera::new(&aabb);
Ok(Self {
new_screen_size: None,